/* 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/. */ "use strict"; const { getAdHocFrontOrPrimitiveGrip, // eslint-disable-next-line mozilla/reject-some-requires } = require("resource://devtools/client/fronts/object.js"); /** * For now, this class is mostly a wrapper around webExtInspectedWindow actor. */ class InspectedWindowCommand { constructor({ commands }) { this.commands = commands; } /** * Return a promise that resolves to the related target actor's front. * The Web Extension inspected window actor. * * @return {Promise} */ getFront() { return this.commands.targetCommand.targetFront.getFront( "webExtensionInspectedWindow" ); } /** * Evaluate the provided javascript code in a target window. * * @param {Object} webExtensionCallerInfo - The addonId and the url (the addon base url * or the url of the actual caller filename and lineNumber) used to log useful * debugging information in the produced error logs and eval stack trace. * @param {String} expression - The expression to evaluate. * @param {Object} options - An option object. Check the actor method definition to see * what properties it can hold (minus the `consoleFront` property which is defined * below). * @param {WebConsoleFront} options.consoleFront - An optional webconsole front. When * set, the result will be either a primitive, a LongStringFront or an * ObjectFront, and the WebConsoleActor corresponding to the console front will * be used to generate those, which is needed if we want to handle ObjectFronts * on the client. */ async eval(webExtensionCallerInfo, expression, options = {}) { const { consoleFront } = options; if (consoleFront) { options.evalResultAsGrip = true; options.toolboxConsoleActorID = consoleFront.actor; delete options.consoleFront; } const front = await this.getFront(); const response = await front.eval( webExtensionCallerInfo, expression, options ); // If no consoleFront was provided, we can directly return the response. if (!consoleFront) { return response; } if ( !response.hasOwnProperty("exceptionInfo") && !response.hasOwnProperty("valueGrip") ) { throw new Error( "Response does not have `exceptionInfo` or `valueGrip` property" ); } if (response.exceptionInfo) { console.error( response.exceptionInfo.description, ...(response.exceptionInfo.details || []) ); return response; } // On the server, the valueGrip is created from the toolbox webconsole actor. // If we want since the ObjectFront connection is inherited from the parent front, we // need to set the console front as the parent front. return getAdHocFrontOrPrimitiveGrip( response.valueGrip, consoleFront || this ); } /** * Reload the target tab, optionally bypass cache, customize the userAgent and/or * inject a script in targeted document or any of its sub-frame. * * @param {WebExtensionCallerInfo} callerInfo * the addonId and the url (the addon base url or the url of the actual caller * filename and lineNumber) used to log useful debugging information in the * produced error logs and eval stack trace. * @param {Object} options * @param {boolean|undefined} options.ignoreCache * Enable/disable the cache bypass headers. * @param {string|undefined} options.injectedScript * Evaluate the provided javascript code in the top level and every sub-frame * created during the page reload, before any other script in the page has been * executed. * @param {string|undefined} options.userAgent * Customize the userAgent during the page reload. * @returns {Promise} A promise that resolves once the page is done loading when userAgent * or injectedScript option are passed. If those options are not provided, the * Promise will resolve after the reload was initiated. */ async reload(callerInfo, options = {}) { if (this._reloadPending) { return null; } this._reloadPending = true; try { // We always want to update the target configuration to set the user agent if one is // passed, or to reset a potential existing override if userAgent isn't defined. await this.commands.targetConfigurationCommand.updateConfiguration({ customUserAgent: options.userAgent, }); const front = await this.getFront(); const result = await front.reload(callerInfo, options); this._reloadPending = false; return result; } catch (e) { this._reloadPending = false; console.error(e); return Promise.reject({ message: "An unexpected error occurred", }); } } } module.exports = InspectedWindowCommand;