| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /* global chrome */
- // Constants
- const MESSAGE_ID = 'three-devtools';
- const MESSAGE_INIT = 'init';
- const MESSAGE_REQUEST_STATE = 'request-state';
- const MESSAGE_REQUEST_OBJECT_DETAILS = 'request-object-details';
- const MESSAGE_SCROLL_TO_CANVAS = 'scroll-to-canvas';
- const MESSAGE_REGISTER = 'register';
- const MESSAGE_COMMITTED = 'committed';
- // Map tab IDs to connections
- const connections = new Map();
- // Handle extension icon clicks in the toolbar
- chrome.action.onClicked.addListener( ( tab ) => {
- // Send scroll-to-canvas message to the content script (no UUID = scroll to first canvas)
- chrome.tabs.sendMessage( tab.id, {
- name: MESSAGE_SCROLL_TO_CANVAS,
- tabId: tab.id
- } ).catch( () => {
- // Ignore error - tab might not have the content script injected
- console.log( 'Could not send scroll-to-canvas message to tab', tab.id );
- } );
- } );
- // Listen for connections from the devtools panel
- chrome.runtime.onConnect.addListener( port => {
- let tabId;
- // Messages that should be forwarded to content script
- const forwardableMessages = new Set( [ MESSAGE_REQUEST_STATE, MESSAGE_REQUEST_OBJECT_DETAILS, MESSAGE_SCROLL_TO_CANVAS ] );
- // Listen for messages from the devtools panel
- port.onMessage.addListener( message => {
- if ( message.name === MESSAGE_INIT ) {
- tabId = message.tabId;
- connections.set( tabId, port );
- } else if ( forwardableMessages.has( message.name ) && tabId ) {
- chrome.tabs.sendMessage( tabId, message );
- } else if ( tabId === undefined ) {
- console.warn( 'Background: Message received from panel before init:', message );
- }
- } );
- // Clean up when devtools is closed
- port.onDisconnect.addListener( () => {
- if ( tabId ) {
- connections.delete( tabId );
- }
- } );
- } );
- // Listen for messages from the content script
- chrome.runtime.onMessage.addListener( ( message, sender, sendResponse ) => {
- if ( message.scheme ) {
- chrome.action.setIcon( {
- path: {
- 128: `icons/128-${message.scheme}.png`
- }
- } );
- }
- if ( sender.tab ) {
- const tabId = sender.tab.id;
- // If three.js is detected, show a badge
- if ( message.name === MESSAGE_REGISTER && message.detail && message.detail.revision ) {
- const revision = String( message.detail.revision );
- const number = revision.replace( /\D+$/, '' );
- const isDev = revision.includes( 'dev' );
- chrome.action.setBadgeText( { tabId: tabId, text: number } ).catch( () => {
- // Ignore error - tab might have been closed
- } );
- chrome.action.setBadgeTextColor( { tabId: tabId, color: '#ffffff' } ).catch( () => {
- // Ignore error - tab might have been closed
- } );
- chrome.action.setBadgeBackgroundColor( { tabId: tabId, color: isDev ? '#ff0098' : '#049ef4' } ).catch( () => {
- // Ignore error - tab might have been closed
- } );
- }
- const port = connections.get( tabId );
- if ( port ) {
- // Forward the message to the devtools panel
- try {
- port.postMessage( message );
- // Send immediate response to avoid "message channel closed" error
- sendResponse( { received: true } );
- } catch ( e ) {
- console.error( 'Error posting message to devtools:', e );
- // If the port is broken, clean up the connection
- connections.delete( tabId );
- }
- }
- }
- return false; // Return false to indicate synchronous handling
- } );
- // Listen for page navigation events
- chrome.webNavigation.onCommitted.addListener( details => {
- const { tabId, frameId } = details;
- // Clear badge on navigation, only for top-level navigation
- if ( frameId === 0 ) {
- chrome.action.setBadgeText( { tabId: tabId, text: '' } ).catch( () => {
- // Ignore error - tab might have been closed
- } );
- }
- const port = connections.get( tabId );
- if ( port ) {
- port.postMessage( {
- id: MESSAGE_ID,
- name: MESSAGE_COMMITTED,
- frameId: frameId
- } );
- }
- } );
- // Clear badge when a tab is closed
- chrome.tabs.onRemoved.addListener( ( tabId ) => {
- chrome.action.setBadgeText( { tabId: tabId, text: '' } ).catch( () => {
- // Ignore error - tab is already gone
- } );
- // Clean up connection if it exists for the closed tab
- if ( connections.has( tabId ) ) {
- connections.delete( tabId );
- }
- } );
|