forked from mirrors/gecko-dev
		
	Bug 1717899 - [remote] Extend the lifetime of the Remote Agent to the Firefox session. r=webdriver-reviewers,jdescottes
Differential Revision: https://phabricator.services.mozilla.com/D144338
This commit is contained in:
		
							parent
							
								
									4d5eb6f009
								
							
						
					
					
						commit
						dcdabedb93
					
				
					 21 changed files with 80 additions and 196 deletions
				
			
		|  | @ -9,7 +9,6 @@ with Files("**"): | |||
| 
 | ||||
| BROWSER_CHROME_MANIFESTS += [ | ||||
|     "test/browser/browser.ini", | ||||
|     "test/browser/component/browser.ini", | ||||
|     "test/browser/dom/browser.ini", | ||||
|     "test/browser/emulation/browser.ini", | ||||
|     "test/browser/fetch/browser.ini", | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
|  | @ -8,6 +11,7 @@ support-files = | |||
|   chrome-remote-interface.js | ||||
|   head.js | ||||
| 
 | ||||
| [browser_agent.js] | ||||
| [browser_cdp.js] | ||||
| [browser_httpd.js] | ||||
| [browser_main_target.js] | ||||
|  |  | |||
							
								
								
									
										14
									
								
								remote/cdp/test/browser/browser_agent.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								remote/cdp/test/browser/browser_agent.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| /* Any copyright is dedicated to the Public Domain. | ||||
|  * http://creativecommons.org/publicdomain/zero/1.0/ */
 | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| // To fully test the Remote Agent's capabilities an instance of the interface
 | ||||
| // also needs to be used.
 | ||||
| const remoteAgentInstance = Cc["@mozilla.org/remote/agent;1"].createInstance( | ||||
|   Ci.nsIRemoteAgent | ||||
| ); | ||||
| 
 | ||||
| add_task(async function listening() { | ||||
|   is(remoteAgentInstance.listening, true, "Agent is listening"); | ||||
| }); | ||||
|  | @ -4,8 +4,6 @@ | |||
| "use strict"; | ||||
| 
 | ||||
| add_task(async function json_version() { | ||||
|   await RemoteAgent.listen(`http://localhost:0`); | ||||
| 
 | ||||
|   const { userAgent } = Cc[ | ||||
|     "@mozilla.org/network/protocol;1?name=http" | ||||
|   ].getService(Ci.nsIHttpProtocolHandler); | ||||
|  |  | |||
|  | @ -1,12 +0,0 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| support-files = | ||||
|   !/remote/cdp/test/browser/chrome-remote-interface.js | ||||
|   !/remote/cdp/test/browser/head.js | ||||
|   head.js | ||||
| 
 | ||||
| # These tests need to start and close RemoteAgent several times. | ||||
| # It should be the only tests in this suite to avoid side-effects with | ||||
| # regular tests which reuse a shared RemoteAgent instance. | ||||
| [browser_agent.js] | ||||
|  | @ -1,75 +0,0 @@ | |||
| /* Any copyright is dedicated to the Public Domain. | ||||
|  * http://creativecommons.org/publicdomain/zero/1.0/ */
 | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| const URL = "http://localhost:0"; | ||||
| 
 | ||||
| add_agent_task(async function debuggerAddress() { | ||||
|   const port = getNonAtomicFreePort(); | ||||
| 
 | ||||
|   await RemoteAgent.listen(`http://localhost:${port}`); | ||||
|   is( | ||||
|     remoteAgentInstance.debuggerAddress, | ||||
|     `localhost:${port}`, | ||||
|     "debuggerAddress set" | ||||
|   ); | ||||
| }); | ||||
| 
 | ||||
| add_agent_task(async function listening() { | ||||
|   is(remoteAgentInstance.listening, false, "Agent is not listening"); | ||||
|   await RemoteAgent.listen(URL); | ||||
|   is(remoteAgentInstance.listening, true, "Agent is listening"); | ||||
| }); | ||||
| 
 | ||||
| add_agent_task(async function remoteListeningNotification() { | ||||
|   let active; | ||||
|   const port = getNonAtomicFreePort(); | ||||
| 
 | ||||
|   function observer(subject, topic, data) { | ||||
|     Services.obs.removeObserver(observer, topic); | ||||
| 
 | ||||
|     active = data; | ||||
|   } | ||||
| 
 | ||||
|   Services.obs.addObserver(observer, "remote-listening"); | ||||
|   await RemoteAgent.listen("http://localhost:" + port); | ||||
|   is(active, "true", "remote-listening observer notified enabled state"); | ||||
| 
 | ||||
|   Services.obs.addObserver(observer, "remote-listening"); | ||||
|   await RemoteAgent.close(); | ||||
|   is(active, null, "remote-listening observer notified disabled state"); | ||||
| }); | ||||
| 
 | ||||
| // TODO(ato): https://bugzil.la/1590829
 | ||||
| add_agent_task(async function listenTakesString() { | ||||
|   await RemoteAgent.listen("http://localhost:0"); | ||||
|   await RemoteAgent.close(); | ||||
| }); | ||||
| 
 | ||||
| // TODO(ato): https://bugzil.la/1590829
 | ||||
| add_agent_task(async function listenNonURL() { | ||||
|   try { | ||||
|     await RemoteAgent.listen("foobar"); | ||||
|     fail("listen() did not reject non-URL"); | ||||
|   } catch (e) { | ||||
|     is(e.result, Cr.NS_ERROR_MALFORMED_URI); | ||||
|   } | ||||
| }); | ||||
| 
 | ||||
| add_agent_task(async function listenRestrictedToLoopbackDevice() { | ||||
|   try { | ||||
|     await RemoteAgent.listen("http://0.0.0.0:9222"); | ||||
|     fail("listen() did not reject non-loopback device"); | ||||
|   } catch (e) { | ||||
|     is(e.result, Cr.NS_ERROR_ILLEGAL_VALUE); | ||||
|     is(e.message, "Restricted to loopback devices"); | ||||
|   } | ||||
| }); | ||||
| 
 | ||||
| add_agent_task(async function test_close() { | ||||
|   await RemoteAgent.listen(URL); | ||||
|   await RemoteAgent.close(); | ||||
|   // no-op when not listening
 | ||||
|   await RemoteAgent.close(); | ||||
| }); | ||||
|  | @ -1,42 +0,0 @@ | |||
| /* Any copyright is dedicated to the Public Domain. | ||||
|  * http://creativecommons.org/publicdomain/zero/1.0/ */
 | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| /* import-globals-from ../head.js */ | ||||
| 
 | ||||
| Services.scriptloader.loadSubScript( | ||||
|   "chrome://mochitests/content/browser/remote/cdp/test/browser/head.js", | ||||
|   this | ||||
| ); | ||||
| 
 | ||||
| // To fully test the Remote Agent's capabilities an instance of the interface
 | ||||
| // also needs to be used.
 | ||||
| const remoteAgentInstance = Cc["@mozilla.org/remote/agent;1"].createInstance( | ||||
|   Ci.nsIRemoteAgent | ||||
| ); | ||||
| 
 | ||||
| // set up test conditions and clean up
 | ||||
| function add_agent_task(originalTask) { | ||||
|   const task = async function() { | ||||
|     await RemoteAgent.close(); | ||||
|     await originalTask(); | ||||
|   }; | ||||
|   Object.defineProperty(task, "name", { | ||||
|     value: originalTask.name, | ||||
|     writable: false, | ||||
|   }); | ||||
|   add_plain_task(task); | ||||
| } | ||||
| 
 | ||||
| function getNonAtomicFreePort() { | ||||
|   const so = Cc["@mozilla.org/network/server-socket;1"].createInstance( | ||||
|     Ci.nsIServerSocket | ||||
|   ); | ||||
|   try { | ||||
|     so.init(-1, true /* aLoopbackOnly */, -1 /* aBackLog */); | ||||
|     return so.port; | ||||
|   } finally { | ||||
|     so.close(); | ||||
|   } | ||||
| } | ||||
|  | @ -1,6 +1,9 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
|  |  | |||
|  | @ -1,7 +1,12 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| skip-if = fission # Bug 1600054: Make cdp Fission compatible | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
| support-files = | ||||
|   !/remote/cdp/test/browser/chrome-remote-interface.js | ||||
|   !/remote/cdp/test/browser/head.js | ||||
|  |  | |||
|  | @ -15,16 +15,6 @@ const { TabManager } = ChromeUtils.import( | |||
|   "chrome://remote/content/shared/TabManager.jsm" | ||||
| ); | ||||
| 
 | ||||
| const { allowNullOrigin } = ChromeUtils.import( | ||||
|   "chrome://remote/content/server/WebSocketHandshake.jsm" | ||||
| ); | ||||
| 
 | ||||
| // The handshake request created by the browser mochitests contains an origin
 | ||||
| // header, which is currently not supported. This origin is a string "null".
 | ||||
| // Explicitly allow such an origin for the duration of the test.
 | ||||
| allowNullOrigin(true); | ||||
| registerCleanupFunction(() => allowNullOrigin(false)); | ||||
| 
 | ||||
| const TIMEOUT_MULTIPLIER = SpecialPowers.isDebugBuild ? 4 : 1; | ||||
| const TIMEOUT_EVENTS = 1000 * TIMEOUT_MULTIPLIER; | ||||
| 
 | ||||
|  | @ -52,16 +42,6 @@ setup and teardown described above. | |||
| 
 | ||||
| const add_plain_task = add_task.bind(this); | ||||
| 
 | ||||
| // Start RemoteAgent lazily and reuse it for all the tests in the suite.
 | ||||
| // Starting and stopping RemoteAgent for every test would trigger race conditions
 | ||||
| // in httpd.js. See Bug 1609162.
 | ||||
| async function startRemoteAgent() { | ||||
|   if (!RemoteAgent.listening) { | ||||
|     await RemoteAgent.listen(Services.io.newURI("http://localhost:9222")); | ||||
|     info("Remote agent started"); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| this.add_task = function(taskFn, opts = {}) { | ||||
|   const { | ||||
|     createTab = true, // By default run each test in its own tab
 | ||||
|  | @ -70,8 +50,6 @@ this.add_task = function(taskFn, opts = {}) { | |||
|   const fn = async function() { | ||||
|     let client, tab, target; | ||||
| 
 | ||||
|     await startRemoteAgent(); | ||||
| 
 | ||||
|     try { | ||||
|       const CDP = await getCDP(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| [DEFAULT] | ||||
| tags = remote | ||||
| subsuite = remote | ||||
| args = | ||||
|   --remote-debugging-port | ||||
|   --remote-allow-origins=null | ||||
| prefs =  # Bug 1600054: Make CDP Fission compatible | ||||
|   fission.bfcacheInParent=false | ||||
|   fission.webContentIsolationStrategy=0 | ||||
|  |  | |||
|  | @ -180,7 +180,7 @@ class RemoteAgentClass { | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   async listen(url) { | ||||
|   async #listen(url) { | ||||
|     if (Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { | ||||
|       throw Components.Exception( | ||||
|         "May only be instantiated in parent process", | ||||
|  | @ -217,12 +217,12 @@ class RemoteAgentClass { | |||
| 
 | ||||
|       await Promise.all([this.webDriverBiDi?.start(), this.cdp?.start()]); | ||||
|     } catch (e) { | ||||
|       await this.close(); | ||||
|       await this.#stop(); | ||||
|       logger.error(`Unable to start remote agent: ${e.message}`, e); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   async close() { | ||||
|   async #stop() { | ||||
|     if (!this.listening) { | ||||
|       return; | ||||
|     } | ||||
|  | @ -315,13 +315,6 @@ class RemoteAgentClass { | |||
| 
 | ||||
|           this.#allowHosts = this.handleAllowHostsFlag(subject); | ||||
|           this.#allowOrigins = this.handleAllowOriginsFlag(subject); | ||||
|         } | ||||
| 
 | ||||
|         // Ideally we should only initialize the Remote Agent when the command
 | ||||
|         // line argument has been specified. But to allow Browser Chrome tests
 | ||||
|         // to run certain states have to be set and listeners registered.
 | ||||
|         // Once bug 1762647 is fixed all the next lines can be moved to
 | ||||
|         // "final-ui-startup".
 | ||||
| 
 | ||||
|           Services.obs.addObserver(this, "sessionstore-windows-restored"); | ||||
|           Services.obs.addObserver(this, "quit-application"); | ||||
|  | @ -345,7 +338,7 @@ class RemoteAgentClass { | |||
|               logger.debug("CDP enabled"); | ||||
|             } | ||||
|           } | ||||
| 
 | ||||
|         } | ||||
|         break; | ||||
| 
 | ||||
|       case "final-ui-startup": | ||||
|  | @ -353,7 +346,7 @@ class RemoteAgentClass { | |||
| 
 | ||||
|         try { | ||||
|           let address = Services.io.newURI(`http://localhost:${this.#port}`); | ||||
|           await this.listen(address); | ||||
|           await this.#listen(address); | ||||
|         } catch (e) { | ||||
|           throw Error(`Unable to start remote agent: ${e}`); | ||||
|         } | ||||
|  | @ -372,7 +365,7 @@ class RemoteAgentClass { | |||
|       case "quit-application": | ||||
|         Services.obs.removeObserver(this, "quit-application"); | ||||
| 
 | ||||
|         this.close(); | ||||
|         this.#stop(); | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| var EXPORTED_SYMBOLS = ["allowNullOrigin", "WebSocketHandshake"]; | ||||
| var EXPORTED_SYMBOLS = ["WebSocketHandshake"]; | ||||
| 
 | ||||
| // This file is an XPCOM service-ified copy of ../devtools/server/socket/websocket-server.js.
 | ||||
| 
 | ||||
|  | @ -32,14 +32,6 @@ XPCOMUtils.defineLazyGetter(this, "threadManager", () => { | |||
|   return Cc["@mozilla.org/thread-manager;1"].getService(); | ||||
| }); | ||||
| 
 | ||||
| // This should only be used by the CDP browser mochitests which create a
 | ||||
| // websocket handshake with a non-null origin. It can be removed once
 | ||||
| // Mochitest supports custom arguments in browser.ini (bug 1762647)
 | ||||
| let nullOriginAllowed = false; | ||||
| function allowNullOrigin(allowed) { | ||||
|   nullOriginAllowed = allowed; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Allowed origins are exposed through 2 separate getters because while most | ||||
|  * of the values should be valid URIs, `null` is also a valid origin and cannot | ||||
|  | @ -154,7 +146,7 @@ function isOriginValid(originHeader) { | |||
| 
 | ||||
|   // Special case "null" origins, used for privacy sensitive or opaque origins.
 | ||||
|   if (originHeader === "null") { | ||||
|     return allowedOrigins.includes("null") || nullOriginAllowed; | ||||
|     return allowedOrigins.includes("null"); | ||||
|   } | ||||
| 
 | ||||
|   try { | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Henrik Skupin
						Henrik Skupin