| 
									
										
										
										
											2020-06-02 16:51:13 -07:00
										 |  |  | /* This Source Code Form is subject to the terms of the Mozilla Public | 
					
						
							|  |  |  |  * License, v. 2.0. If a copy of the MPL was not distributed with this | 
					
						
							|  |  |  |  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); | 
					
						
							| 
									
										
										
										
											2020-08-12 10:09:20 -07:00
										 |  |  | const {ComponentUtils} = ChromeUtils.import("resource://gre/modules/ComponentUtils.jsm"); | 
					
						
							| 
									
										
										
										
											2020-06-02 16:51:13 -07:00
										 |  |  | const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); | 
					
						
							|  |  |  | const {Dispatcher} = ChromeUtils.import("chrome://juggler/content/protocol/Dispatcher.js"); | 
					
						
							|  |  |  | const {BrowserHandler} = ChromeUtils.import("chrome://juggler/content/protocol/BrowserHandler.js"); | 
					
						
							|  |  |  | const {NetworkObserver} = ChromeUtils.import("chrome://juggler/content/NetworkObserver.js"); | 
					
						
							|  |  |  | const {TargetRegistry} = ChromeUtils.import("chrome://juggler/content/TargetRegistry.js"); | 
					
						
							|  |  |  | const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js'); | 
					
						
							|  |  |  | const helper = new Helper(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const Cc = Components.classes; | 
					
						
							|  |  |  | const Ci = Components.interfaces; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const FRAME_SCRIPT = "chrome://juggler/content/content/main.js"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Command Line Handler
 | 
					
						
							|  |  |  | function CommandLineHandler() { | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CommandLineHandler.prototype = { | 
					
						
							|  |  |  |   classDescription: "Sample command-line handler", | 
					
						
							|  |  |  |   classID: Components.ID('{f7a74a33-e2ab-422d-b022-4fb213dd2639}'), | 
					
						
							|  |  |  |   contractID: "@mozilla.org/remote/juggler;1", | 
					
						
							|  |  |  |   _xpcom_categories: [{ | 
					
						
							|  |  |  |     category: "command-line-handler", | 
					
						
							|  |  |  |     entry: "m-juggler" | 
					
						
							|  |  |  |   }], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* nsICommandLineHandler */ | 
					
						
							|  |  |  |   handle: async function(cmdLine) { | 
					
						
							|  |  |  |     const jugglerFlag = cmdLine.handleFlagWithParam("juggler", false); | 
					
						
							| 
									
										
										
										
											2020-08-03 13:27:09 -07:00
										 |  |  |     const jugglerPipeFlag = cmdLine.handleFlag("juggler-pipe", false); | 
					
						
							|  |  |  |     if (!jugglerPipeFlag && (!jugglerFlag || isNaN(jugglerFlag))) | 
					
						
							| 
									
										
										
										
											2020-06-02 16:51:13 -07:00
										 |  |  |       return; | 
					
						
							|  |  |  |     const silent = cmdLine.preventDefault; | 
					
						
							|  |  |  |     if (silent) | 
					
						
							|  |  |  |       Services.startup.enterLastWindowClosingSurvivalArea(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const targetRegistry = new TargetRegistry(); | 
					
						
							|  |  |  |     new NetworkObserver(targetRegistry); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-03 13:27:09 -07:00
										 |  |  |     const loadFrameScript = () => { | 
					
						
							|  |  |  |       Services.mm.loadFrameScript(FRAME_SCRIPT, true /* aAllowDelayedLoad */); | 
					
						
							| 
									
										
										
										
											2021-05-19 18:59:57 -07:00
										 |  |  |       if (Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo).isHeadless) { | 
					
						
							|  |  |  |         const styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Components.interfaces.nsIStyleSheetService); | 
					
						
							|  |  |  |         const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); | 
					
						
							|  |  |  |         const uri = ioService.newURI('chrome://juggler/content/content/hidden-scrollbars.css', null, null); | 
					
						
							|  |  |  |         styleSheetService.loadAndRegisterSheet(uri, styleSheetService.AGENT_SHEET); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-08-03 13:27:09 -07:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2020-06-02 16:51:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Force create hidden window here, otherwise its creation later closes the web socket!
 | 
					
						
							|  |  |  |     Services.appShell.hiddenDOMWindow; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-03 13:27:09 -07:00
										 |  |  |     if (jugglerFlag) { | 
					
						
							|  |  |  |       const port = parseInt(jugglerFlag, 10); | 
					
						
							|  |  |  |       const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm"); | 
					
						
							|  |  |  |       const WebSocketServer = require('devtools/server/socket/websocket-server'); | 
					
						
							|  |  |  |       this._server = Cc["@mozilla.org/network/server-socket;1"].createInstance(Ci.nsIServerSocket); | 
					
						
							|  |  |  |       this._server.initSpecialConnection(port, Ci.nsIServerSocket.KeepWhenOffline | Ci.nsIServerSocket.LoopbackOnly, 4); | 
					
						
							|  |  |  |       const token = helper.generateId(); | 
					
						
							|  |  |  |       this._server.asyncListen({ | 
					
						
							|  |  |  |         onSocketAccepted: async(socket, transport) => { | 
					
						
							|  |  |  |           const input = transport.openInputStream(0, 0, 0); | 
					
						
							|  |  |  |           const output = transport.openOutputStream(0, 0, 0); | 
					
						
							|  |  |  |           const webSocket = await WebSocketServer.accept(transport, input, output, "/" + token); | 
					
						
							|  |  |  |           const dispatcher = new Dispatcher(webSocket); | 
					
						
							|  |  |  |           const browserHandler = new BrowserHandler(dispatcher.rootSession(), dispatcher, targetRegistry, () => { | 
					
						
							|  |  |  |             if (silent) | 
					
						
							|  |  |  |               Services.startup.exitLastWindowClosingSurvivalArea(); | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2020-10-06 00:15:24 -07:00
										 |  |  |           dispatcher.rootSession().setHandler(browserHandler); | 
					
						
							| 
									
										
										
										
											2020-08-03 13:27:09 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       loadFrameScript(); | 
					
						
							|  |  |  |       dump(`Juggler listening on ws://127.0.0.1:${this._server.port}/${token}\n`); | 
					
						
							|  |  |  |     } else if (jugglerPipeFlag) { | 
					
						
							| 
									
										
										
										
											2020-11-13 14:51:40 -08:00
										 |  |  |       let browserHandler; | 
					
						
							|  |  |  |       let pipeStopped = false; | 
					
						
							| 
									
										
										
										
											2020-08-03 13:27:09 -07:00
										 |  |  |       const pipe = Cc['@mozilla.org/juggler/remotedebuggingpipe;1'].getService(Ci.nsIRemoteDebuggingPipe); | 
					
						
							|  |  |  |       const connection = { | 
					
						
							|  |  |  |         QueryInterface: ChromeUtils.generateQI([Ci.nsIRemoteDebuggingPipeClient]), | 
					
						
							|  |  |  |         receiveMessage(message) { | 
					
						
							|  |  |  |           if (this.onmessage) | 
					
						
							|  |  |  |             this.onmessage({ data: message }); | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2020-11-13 14:51:40 -08:00
										 |  |  |         disconnected() { | 
					
						
							|  |  |  |           if (browserHandler) | 
					
						
							|  |  |  |             browserHandler['Browser.close'](); | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2020-08-03 13:27:09 -07:00
										 |  |  |         send(message) { | 
					
						
							| 
									
										
										
										
											2020-11-13 14:51:40 -08:00
										 |  |  |           if (pipeStopped) { | 
					
						
							|  |  |  |             // We are missing the response to Browser.close,
 | 
					
						
							|  |  |  |             // but everything works fine. Once we actually need it,
 | 
					
						
							|  |  |  |             // we have to stop the pipe after the response is sent.
 | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2020-08-03 13:27:09 -07:00
										 |  |  |           pipe.sendMessage(message); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |       pipe.init(connection); | 
					
						
							|  |  |  |       const dispatcher = new Dispatcher(connection); | 
					
						
							| 
									
										
										
										
											2020-11-13 14:51:40 -08:00
										 |  |  |       browserHandler = new BrowserHandler(dispatcher.rootSession(), dispatcher, targetRegistry, () => { | 
					
						
							| 
									
										
										
										
											2020-08-03 13:27:09 -07:00
										 |  |  |         if (silent) | 
					
						
							|  |  |  |           Services.startup.exitLastWindowClosingSurvivalArea(); | 
					
						
							| 
									
										
										
										
											2020-11-13 14:51:40 -08:00
										 |  |  |         connection.onclose(); | 
					
						
							|  |  |  |         pipe.stop(); | 
					
						
							|  |  |  |         pipeStopped = true; | 
					
						
							| 
									
										
										
										
											2020-08-03 13:27:09 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-10-06 00:15:24 -07:00
										 |  |  |       dispatcher.rootSession().setHandler(browserHandler); | 
					
						
							| 
									
										
										
										
											2020-08-03 13:27:09 -07:00
										 |  |  |       loadFrameScript(); | 
					
						
							| 
									
										
										
										
											2020-10-06 00:15:24 -07:00
										 |  |  |       dump(`\nJuggler listening to the pipe\n`); | 
					
						
							| 
									
										
										
										
											2020-06-08 15:54:47 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-02 16:51:13 -07:00
										 |  |  |   }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   QueryInterface: ChromeUtils.generateQI([ Ci.nsICommandLineHandler ]), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // CHANGEME: change the help info as appropriate, but
 | 
					
						
							|  |  |  |   // follow the guidelines in nsICommandLineHandler.idl
 | 
					
						
							|  |  |  |   // specifically, flag descriptions should start at
 | 
					
						
							|  |  |  |   // character 24, and lines should be wrapped at
 | 
					
						
							|  |  |  |   // 72 characters with embedded newlines,
 | 
					
						
							|  |  |  |   // and finally, the string should end with a newline
 | 
					
						
							|  |  |  |   helpInfo : "  --juggler            Enable Juggler automation\n" | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-12 10:09:20 -07:00
										 |  |  | var NSGetFactory = ComponentUtils.generateNSGetFactory([CommandLineHandler]); |