content-script.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // This script runs in the context of the web page
  2. // console.log( 'Three.js DevTools: Content script loaded at document_readyState:', document.readyState ); // Comment out
  3. // Function to inject the bridge script
  4. function injectBridge( target = document ) {
  5. const script = document.createElement( 'script' );
  6. script.src = chrome.runtime.getURL( 'bridge.js' );
  7. script.onload = function () {
  8. this.remove();
  9. };
  10. ( target.head || target.documentElement ).appendChild( script );
  11. return script;
  12. }
  13. // Also inject into any existing iframes
  14. function injectIntoIframes() {
  15. const iframes = document.querySelectorAll( 'iframe' );
  16. iframes.forEach( iframe => {
  17. try {
  18. injectBridge( iframe.contentDocument );
  19. } catch ( e ) {
  20. // Ignore cross-origin iframe errors
  21. // console.log( 'DevTools: Could not inject into iframe:', e ); // Comment out
  22. }
  23. } );
  24. }
  25. // Initial injection
  26. injectBridge();
  27. injectIntoIframes();
  28. // Watch for new iframes being added
  29. const observer = new MutationObserver( mutations => {
  30. mutations.forEach( mutation => {
  31. mutation.addedNodes.forEach( node => {
  32. if ( node.tagName === 'IFRAME' ) {
  33. // Wait for iframe to load
  34. node.addEventListener( 'load', () => {
  35. try {
  36. injectBridge( node.contentDocument );
  37. } catch ( e ) {
  38. // Ignore cross-origin iframe errors
  39. // console.log( 'DevTools: Could not inject into iframe:', e ); // Comment out
  40. }
  41. } );
  42. }
  43. } );
  44. } );
  45. } );
  46. observer.observe( document.documentElement, {
  47. childList: true,
  48. subtree: true
  49. } );
  50. // Helper function to check if extension context is valid
  51. function isExtensionContextValid() {
  52. try {
  53. // This will throw if context is invalidated
  54. chrome.runtime.getURL( '' );
  55. return true;
  56. } catch ( error ) {
  57. return false;
  58. }
  59. }
  60. // Handle messages from the main window
  61. function handleMainWindowMessage( event ) {
  62. // Only accept messages from the same frame
  63. if ( event.source !== window ) {
  64. return;
  65. }
  66. const message = event.data;
  67. if ( ! message || message.id !== 'three-devtools' ) {
  68. return;
  69. }
  70. // Check extension context before sending message
  71. if ( ! isExtensionContextValid() ) {
  72. console.warn( 'Extension context invalidated, cannot send message' );
  73. return;
  74. }
  75. // Add source information
  76. const messageWithSource = {
  77. ...event.data,
  78. source: event.source === window ? 'main' : 'iframe'
  79. };
  80. // Forward to background page
  81. chrome.runtime.sendMessage( messageWithSource );
  82. }
  83. // Handle messages from iframes
  84. function handleIframeMessage( event ) {
  85. // Skip messages from main window
  86. if ( event.source === window ) {
  87. return;
  88. }
  89. const message = event.data;
  90. if ( ! message || message.id !== 'three-devtools' ) {
  91. return;
  92. }
  93. // Check extension context before sending message
  94. if ( ! isExtensionContextValid() ) {
  95. console.warn( 'Extension context invalidated, cannot send message' );
  96. return;
  97. }
  98. // Add source information
  99. const messageWithSource = {
  100. ...event.data,
  101. source: 'iframe'
  102. };
  103. // Forward to background page
  104. chrome.runtime.sendMessage( messageWithSource );
  105. }
  106. // Listener for messages forwarded from the background script (originating from panel)
  107. function handleBackgroundMessage( message, sender, sendResponse ) {
  108. // Check if the message is one we need to forward to the bridge
  109. // Only forward request-state now
  110. if ( message.name === 'request-state' ) {
  111. // console.log( 'Content script: Forwarding message to bridge:', message.name );
  112. // Ensure the message has the correct ID before forwarding to the page
  113. message.id = 'three-devtools';
  114. window.postMessage( message, '*' ); // Forward the modified message to the page
  115. // Optional: Forward to iframes too, if needed (might cause duplicates if bridge is in iframe)
  116. /*
  117. const iframes = document.querySelectorAll('iframe');
  118. iframes.forEach(iframe => {
  119. try {
  120. iframe.contentWindow.postMessage(message, '*');
  121. } catch (e) {}
  122. });
  123. */
  124. }
  125. // Keep channel open? No, this listener is synchronous for now.
  126. // return true;
  127. }
  128. // Add event listeners
  129. window.addEventListener( 'message', handleMainWindowMessage, false );
  130. window.addEventListener( 'message', handleIframeMessage, false );
  131. // chrome.runtime.onMessage.addListener( handleDevtoolsMessage ); // This seems redundant/incorrectly placed in original code
  132. // Use a single listener for messages from the background script
  133. chrome.runtime.onMessage.addListener( handleBackgroundMessage );
粤ICP备19079148号