| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- // This script runs in the context of the web page
- // console.log( 'Three.js DevTools: Content script loaded at document_readyState:', document.readyState ); // Comment out
- // Function to inject the bridge script
- function injectBridge( target = document ) {
- const script = document.createElement( 'script' );
- script.src = chrome.runtime.getURL( 'bridge.js' );
- script.onload = function () {
- this.remove();
- };
- ( target.head || target.documentElement ).appendChild( script );
- return script;
- }
- // Also inject into any existing iframes
- function injectIntoIframes() {
- const iframes = document.querySelectorAll( 'iframe' );
- iframes.forEach( iframe => {
- try {
- injectBridge( iframe.contentDocument );
- } catch ( e ) {
- // Ignore cross-origin iframe errors
- // console.log( 'DevTools: Could not inject into iframe:', e ); // Comment out
- }
- } );
- }
- // Initial injection
- injectBridge();
- injectIntoIframes();
- // Watch for new iframes being added
- const observer = new MutationObserver( mutations => {
- mutations.forEach( mutation => {
- mutation.addedNodes.forEach( node => {
- if ( node.tagName === 'IFRAME' ) {
- // Wait for iframe to load
- node.addEventListener( 'load', () => {
- try {
- injectBridge( node.contentDocument );
- } catch ( e ) {
- // Ignore cross-origin iframe errors
- // console.log( 'DevTools: Could not inject into iframe:', e ); // Comment out
- }
- } );
- }
- } );
- } );
- } );
- observer.observe( document.documentElement, {
- childList: true,
- subtree: true
- } );
- // Helper function to check if extension context is valid
- function isExtensionContextValid() {
- try {
- // This will throw if context is invalidated
- chrome.runtime.getURL( '' );
- return true;
- } catch ( error ) {
- return false;
- }
- }
- // Handle messages from the main window
- function handleMainWindowMessage( event ) {
- // Only accept messages from the same frame
- if ( event.source !== window ) {
- return;
- }
- const message = event.data;
- if ( ! message || message.id !== 'three-devtools' ) {
- return;
- }
- // Check extension context before sending message
- if ( ! isExtensionContextValid() ) {
- console.warn( 'Extension context invalidated, cannot send message' );
- return;
- }
- // Add source information
- const messageWithSource = {
- ...event.data,
- source: event.source === window ? 'main' : 'iframe'
- };
- // Forward to background page
- chrome.runtime.sendMessage( messageWithSource );
- }
- // Handle messages from iframes
- function handleIframeMessage( event ) {
- // Skip messages from main window
- if ( event.source === window ) {
- return;
- }
- const message = event.data;
- if ( ! message || message.id !== 'three-devtools' ) {
- return;
- }
- // Check extension context before sending message
- if ( ! isExtensionContextValid() ) {
- console.warn( 'Extension context invalidated, cannot send message' );
- return;
- }
- // Add source information
- const messageWithSource = {
- ...event.data,
- source: 'iframe'
- };
- // Forward to background page
- chrome.runtime.sendMessage( messageWithSource );
- }
- // Listener for messages forwarded from the background script (originating from panel)
- function handleBackgroundMessage( message, sender, sendResponse ) {
- // Check if the message is one we need to forward to the bridge
- // Only forward request-state now
- if ( message.name === 'request-state' ) {
- // console.log( 'Content script: Forwarding message to bridge:', message.name );
- // Ensure the message has the correct ID before forwarding to the page
- message.id = 'three-devtools';
- window.postMessage( message, '*' ); // Forward the modified message to the page
- // Optional: Forward to iframes too, if needed (might cause duplicates if bridge is in iframe)
- /*
- const iframes = document.querySelectorAll('iframe');
- iframes.forEach(iframe => {
- try {
- iframe.contentWindow.postMessage(message, '*');
- } catch (e) {}
- });
- */
- }
- // Keep channel open? No, this listener is synchronous for now.
- // return true;
- }
- // Add event listeners
- window.addEventListener( 'message', handleMainWindowMessage, false );
- window.addEventListener( 'message', handleIframeMessage, false );
- // chrome.runtime.onMessage.addListener( handleDevtoolsMessage ); // This seems redundant/incorrectly placed in original code
- // Use a single listener for messages from the background script
- chrome.runtime.onMessage.addListener( handleBackgroundMessage );
- // Icon color scheme
- const isLightTheme = window.matchMedia( '(prefers-color-scheme: light)' ).matches;
- chrome.runtime.sendMessage( { scheme: isLightTheme ? 'light' : 'dark' } );
- window.matchMedia( '(prefers-color-scheme: light)' ).onchange = ( event ) => {
- chrome.runtime.sendMessage( { scheme: event.matches ? 'light' : 'dark' } );
- };
|