1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 ChromeUtils.defineESModuleGetters(lazy, {
8 JSONHandler: "chrome://remote/content/cdp/JSONHandler.sys.mjs",
9 Log: "chrome://remote/content/shared/Log.sys.mjs",
10 RecommendedPreferences:
11 "chrome://remote/content/shared/RecommendedPreferences.sys.mjs",
12 TargetList: "chrome://remote/content/cdp/targets/TargetList.sys.mjs",
15 ChromeUtils.defineLazyGetter(lazy, "logger", () =>
16 lazy.Log.get(lazy.Log.TYPES.CDP)
18 ChromeUtils.defineLazyGetter(lazy, "textEncoder", () => new TextEncoder());
20 // Map of CDP-specific preferences that should be set via
21 // RecommendedPreferences.
22 const RECOMMENDED_PREFS = new Map([
23 // Prevent various error message on the console
24 // jest-puppeteer asserts that no error message is emitted by the console
26 "browser.contentblocking.features.standard",
27 "-tp,tpPrivate,cookieBehavior0,-cm,-fp",
29 // Accept all cookies (see behavior definitions in nsICookieService.idl)
30 ["network.cookie.cookieBehavior", 0],
34 * Entry class for the Chrome DevTools Protocol support.
36 * It holds the list of available targets (tabs, main browser), and also
37 * sets up the necessary handlers for the HTTP server.
39 * @see https://chromedevtools.github.io/devtools-protocol
43 * Creates a new instance of the CDP class.
45 * @param {RemoteAgent} agent
46 * Reference to the Remote Agent instance.
50 this.targetList = null;
52 this._running = false;
57 const mainTarget = this.targetList.getMainProcessTarget();
58 return mainTarget.wsDebuggerURL;
61 get mainTargetPath() {
62 const mainTarget = this.targetList.getMainProcessTarget();
63 return mainTarget.path;
67 * Starts the CDP support.
74 // Note: Ideally this would only be set at the end of the method. However
75 // since start() is async, we prefer to set the flag early in order to
76 // avoid potential race conditions.
79 lazy.RecommendedPreferences.applyPreferences(RECOMMENDED_PREFS);
81 // Starting CDP too early can cause issues with clients in not being able
82 // to find any available target. Also when closing the application while
83 // it's still starting up can cause shutdown hangs. As such CDP will be
84 // started when the initial application window has finished initializing.
85 lazy.logger.debug(`Waiting for initial application window`);
86 await this.agent.browserStartupFinished;
88 this.agent.server.registerPrefixHandler("/", new lazy.JSONHandler(this));
90 this.targetList = new lazy.TargetList();
91 this.targetList.on("target-created", (eventName, target) => {
92 this.agent.server.registerPathHandler(target.path, target);
94 this.targetList.on("target-destroyed", (eventName, target) => {
95 this.agent.server.registerPathHandler(target.path, null);
98 await this.targetList.watchForTargets();
100 Cu.printStderr(`DevTools listening on ${this.address}\n`);
102 // Write connection details to DevToolsActivePort file within the profile.
103 this._activePortPath = PathUtils.join(
104 PathUtils.profileDir,
108 const data = `${this.agent.port}\n${this.mainTargetPath}`;
110 await IOUtils.write(this._activePortPath, lazy.textEncoder.encode(data));
113 `Failed to create ${this._activePortPath} (${e.message})`
119 * Stops the CDP support.
122 if (!this._running) {
127 await IOUtils.remove(this._activePortPath);
130 `Failed to remove ${this._activePortPath} (${e.message})`
135 this.targetList?.destructor();
136 this.targetList = null;
138 lazy.RecommendedPreferences.restorePreferences(RECOMMENDED_PREFS);
140 lazy.logger.error("Failed to stop protocol", e);
142 this._running = false;