background.js 3.6 KB

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