background.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /* global chrome */
  2. importScripts( 'constants.js' );
  3. // Map tab IDs to connections
  4. const connections = new Map();
  5. // Handle extension icon clicks in the toolbar
  6. chrome.action.onClicked.addListener( ( tab ) => {
  7. // Send scroll-to-canvas message to the content script (no UUID = scroll to first canvas)
  8. chrome.tabs.sendMessage( tab.id, {
  9. name: MESSAGE_SCROLL_TO_CANVAS,
  10. tabId: tab.id
  11. } ).catch( () => {
  12. // Ignore error - tab might not have the content script injected
  13. console.log( 'Could not send scroll-to-canvas message to tab', tab.id );
  14. } );
  15. } );
  16. // Listen for connections from the devtools panel
  17. chrome.runtime.onConnect.addListener( port => {
  18. let tabId;
  19. // Messages that should be forwarded to content script
  20. const forwardableMessages = new Set( [
  21. MESSAGE_REQUEST_STATE,
  22. MESSAGE_REQUEST_OBJECT_DETAILS,
  23. MESSAGE_SCROLL_TO_CANVAS,
  24. MESSAGE_HIGHLIGHT_OBJECT,
  25. MESSAGE_UNHIGHLIGHT_OBJECT
  26. ] );
  27. // Listen for messages from the devtools panel
  28. port.onMessage.addListener( message => {
  29. if ( message.name === MESSAGE_INIT ) {
  30. tabId = message.tabId;
  31. connections.set( tabId, port );
  32. } else if ( forwardableMessages.has( message.name ) && tabId ) {
  33. chrome.tabs.sendMessage( tabId, message );
  34. } else if ( tabId === undefined ) {
  35. console.warn( 'Background: Message received from panel before init:', message );
  36. }
  37. } );
  38. // Clean up when devtools is closed
  39. port.onDisconnect.addListener( () => {
  40. if ( tabId ) {
  41. connections.delete( tabId );
  42. }
  43. } );
  44. } );
  45. // Listen for messages from the content script
  46. chrome.runtime.onMessage.addListener( ( message, sender, sendResponse ) => {
  47. if ( message.scheme ) {
  48. chrome.action.setIcon( {
  49. path: {
  50. 128: `icons/128-${message.scheme}.png`
  51. }
  52. } );
  53. }
  54. if ( sender.tab ) {
  55. const tabId = sender.tab.id;
  56. // If three.js is detected, show a badge
  57. if ( message.name === MESSAGE_REGISTER && message.detail && message.detail.revision ) {
  58. const revision = String( message.detail.revision );
  59. const number = revision.replace( /\D+$/, '' );
  60. const isDev = revision.includes( 'dev' );
  61. chrome.action.setBadgeText( { tabId: tabId, text: number } ).catch( () => {
  62. // Ignore error - tab might have been closed
  63. } );
  64. chrome.action.setBadgeTextColor( { tabId: tabId, color: '#ffffff' } ).catch( () => {
  65. // Ignore error - tab might have been closed
  66. } );
  67. chrome.action.setBadgeBackgroundColor( { tabId: tabId, color: isDev ? '#ff0098' : '#049ef4' } ).catch( () => {
  68. // Ignore error - tab might have been closed
  69. } );
  70. }
  71. const port = connections.get( tabId );
  72. if ( port ) {
  73. // Forward the message to the devtools panel
  74. try {
  75. port.postMessage( message );
  76. // Send immediate response to avoid "message channel closed" error
  77. sendResponse( { received: true } );
  78. } catch ( e ) {
  79. console.error( 'Error posting message to devtools:', e );
  80. // If the port is broken, clean up the connection
  81. connections.delete( tabId );
  82. }
  83. }
  84. }
  85. return false; // Return false to indicate synchronous handling
  86. } );
  87. // Listen for page navigation events
  88. chrome.webNavigation.onCommitted.addListener( details => {
  89. const { tabId, frameId } = details;
  90. // Clear badge on navigation, only for top-level navigation
  91. if ( frameId === 0 ) {
  92. chrome.action.setBadgeText( { tabId: tabId, text: '' } ).catch( () => {
  93. // Ignore error - tab might have been closed
  94. } );
  95. }
  96. const port = connections.get( tabId );
  97. if ( port ) {
  98. port.postMessage( {
  99. id: MESSAGE_ID,
  100. name: MESSAGE_COMMITTED,
  101. frameId: frameId
  102. } );
  103. }
  104. } );
  105. // Clear badge when a tab is closed
  106. chrome.tabs.onRemoved.addListener( ( tabId ) => {
  107. chrome.action.setBadgeText( { tabId: tabId, text: '' } ).catch( () => {
  108. // Ignore error - tab is already gone
  109. } );
  110. // Clean up connection if it exists for the closed tab
  111. if ( connections.has( tabId ) ) {
  112. connections.delete( tabId );
  113. }
  114. } );
粤ICP备19079148号