@@ -113,24 +113,85 @@ export class Tab extends StatefulClass {
113113}
114114
115115function injectDevtools ( client : ScramjetClient , tab : Tab ) {
116- const devtoolsUrl = "/chi" ;
117- let devtoolsScript = document . createElement ( "script" ) ;
116+ // right here there's three contexts, the main window, the page frame, and the empty devtools frame
117+ // chobitsu is injected into the page frame (loaded from https://fake-devtools.invalid/target.js), and then will try and inject
118+ // itself into the devtools frame through the `ChiiDevtoolsIframe` global variable
119+ // so first we need to make sure that the devtools frame is in a scramjet context so that the page frame will use proxied apis
120+ // then we set up communication between the devtools frame and the page frame
121+ // then, hand off the devtools frame to the page frame so that it can inject itself into it, but cannot use the globals to escape
122+
123+ // we're loading the entire bundle through scramjet so that eval() will be rewritten
124+ // to start, apply the same hack as window.open to scramjetify the devtools frame
125+ const contentwindow = tab . devtoolsFrame ! . contentWindow ;
126+ const ctor : any = client . constructor ;
127+ const devtoolsFrameClient : ScramjetClient = new ctor ( contentwindow ) ;
128+ // TODO: move this to frame creation
129+ scramjet . createFrame ( tab . devtoolsFrame ! ) ;
130+ devtoolsFrameClient . hook ( ) ;
131+ // the fake origin is defined in sw.js
132+ const devtoolsUrl = "https://fake-devtools.invalid" ;
133+ // make sure to create the element through the proxied document
134+ let devtoolsScript = client . global . document . createElement ( "script" ) ;
135+ devtoolsScript . setAttribute ( "src" , devtoolsUrl + "/target.js" ) ;
118136 devtoolsScript . setAttribute ( "embedded" , "true" ) ;
119- window . addEventListener ( "message" , ( event ) => {
120- console . log ( event ) ;
121- // tab.devtoolsFrame?.contentWindow?.postMessage(event.data, event.origin);
122- // client.natives.call("window.postMessage", client.global, [
123- // event.data,
124- // event.origin,
125- // ]);
126- client . global . window . postMessage ( event . data ) ;
137+
138+ devtoolsFrameClient . frame ! . addEventListener ( "contextInit" , ( ) => {
139+ // devtools frontend will try to access the parent window's postMessage
140+ // this won't work, i manually patched it to use this global instead
141+ //@ts -expect-error
142+ tab . devtoolsFrame . contentWindow . parentPostMessage = (
143+ data : any ,
144+ origin : string
145+ ) => {
146+ if ( ! JSON . parse ( data ) . method ) {
147+ console . error ( "ignoring some data" ) ;
148+ return ;
149+ }
150+
151+ // oh god
152+ // i will fix this later
153+ // we're not supposed to be postmessaging from a non-scramjet context into a scramjet one
154+ // so we need to trick the page content's scramjetclient into thinking this window is also a scramjet context
155+ //@ts -expect-error
156+ window [ Symbol . for ( "scramjet client global" ) ] = {
157+ // for our fake scramjet client in the main window, set the origin to the fake devtools url so that the event origin check will suceed
158+ url : { origin : devtoolsUrl } ,
159+ } ;
160+ //@ts -expect-error
161+ client . global . window . $scramjet$setrealm ( { } ) . postMessage ( data ) ;
162+ //@ts -expect-error
163+ delete window [ Symbol . for ( "scramjet client global" ) ] ;
164+ } ;
127165 } ) ;
128166
129- // devtoolsScript.setAttribute("cdn", devtoolsUrl);
130- devtoolsScript . setAttribute ( "src" , devtoolsUrl + "/target.js" ) ;
131- //@ts -expect-error i'm not typing this
132- client . global . ChiiDevtoolsIframe = tab . devtoolsFrame ;
167+ // VERY IMPORTANT: GIVE CHII THE *PROXIED* VERSION OF THE DEVTOOLS FRAME, AND NO REAL CTORS
168+ // this is needed for the interceptors to work - but also stops sbx
169+ //@ts -expect-error
170+ client . global . ChiiDevtoolsIframe = {
171+ contentWindow : devtoolsFrameClient . global ,
172+ // TODO this is STILL sbx annoyingly because the functions don't have their ctors intercepted
173+ set src ( value ) {
174+ devtoolsFrameClient . url = value ;
175+ } ,
176+ get src ( ) {
177+ return devtoolsFrameClient . url ;
178+ } ,
179+ } ;
133180 client . global . document . head . appendChild ( devtoolsScript ) ;
181+
182+ // unproxied version
183+ // const devtoolsUrl = "/chi";
184+ // let devtoolsScript = document.createElement("script");
185+ // devtoolsScript.setAttribute("src", devtoolsUrl + "/target.js");
186+ // devtoolsScript.setAttribute("embedded", "true");
187+
188+ // window.addEventListener("message", (event) => {
189+ // console.log(event.data);
190+ // client.global.window.postMessage(event.data, event.origin);
191+ // });
192+
193+ // client.global.ChiiDevtoolsIframe = tab.devtoolsFrame;
194+ // client.global.document.head.appendChild(devtoolsScript);
134195}
135196
136197function copyImageToClipboard ( img : HTMLImageElement ) {
0 commit comments