/* 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/. */
// List of options supported by this target configuration actor. /* eslint sort-keys: "error" */ const SUPPORTED_OPTIONS = { // Disable network request caching.
cacheDisabled: true, // Enable color scheme simulation.
colorSchemeSimulation: true, // Enable custom formatters
customFormatters: true, // Set a custom user agent
customUserAgent: true, // Is the tracer experimental feature manually enabled by the user?
isTracerFeatureEnabled: true, // Enable JavaScript
javascriptEnabled: true, // Force a custom device pixel ratio (used in RDM). Set to null to restore origin ratio.
overrideDPPX: true, // Enable print simulation mode.
printSimulationEnabled: true, // Override navigator.maxTouchPoints (used in RDM and doesn't apply if RDM isn't enabled)
rdmPaneMaxTouchPoints: true, // Page orientation (used in RDM and doesn't apply if RDM isn't enabled)
rdmPaneOrientation: true, // Enable allocation tracking, if set, contains an object defining the tracking configurations
recordAllocations: true, // Reload the page when the touch simulation state changes (only works alongside touchEventsOverride)
reloadOnTouchSimulationToggle: true, // Restore focus in the page after closing DevTools.
restoreFocus: true, // Enable service worker testing over HTTP (instead of HTTPS only).
serviceWorkersTestingEnabled: true, // Set the current tab offline
setTabOffline: true, // Enable touch events simulation
touchEventsOverride: true, // Used to configure and start/stop the JavaScript tracer
tracerOptions: true, // Use simplified highlighters when prefers-reduced-motion is enabled.
useSimpleHighlightersForReducedMotion: true,
}; /* eslint-disable sort-keys */
/** * This actor manages the configuration flags which apply to DevTools targets. * * Configuration flags should be applied to all concerned targets when the * configuration is updated, and new targets should also be able to read the * flags when they are created. The flags will be forwarded to the WatcherActor * and stored as TARGET_CONFIGURATION data entries. * Some flags will be set directly set from this actor, in the parent process * (see _updateParentProcessConfiguration), and others will be set from the target actor, * in the content process. * * @constructor *
*/ class TargetConfigurationActor extends Actor {
constructor(watcherActor) { super(watcherActor.conn, targetConfigurationSpec); this.watcherActor = watcherActor;
this._onBrowsingContextAttached = this._onBrowsingContextAttached.bind(this); // We need to be notified of new browsing context being created so we can re-set flags // we already set on the "previous" browsing context. We're using this event as it's // emitted very early in the document lifecycle (i.e. before any script on the page is // executed), which is not the case for "window-global-created" for example.
Services.obs.addObserver( this._onBrowsingContextAttached, "browsing-context-attached"
);
// When we perform a bfcache navigation, the current browsing context gets // replaced with a browsing which was previously stored in bfcache and we // should update our reference accordingly. this._onBfCacheNavigation = this._onBfCacheNavigation.bind(this); this.watcherActor.on( "bf-cache-navigation-pageshow", this._onBfCacheNavigation
);
/** * Returns whether or not this actor should handle the flag that should be set on the * BrowsingContext in the parent process. * * @returns {Boolean}
*/
_shouldHandleConfigurationInParentProcess() { // Only handle parent process configuration if the watcherActor is tied to a // browser element. // For now, the Browser Toolbox and Web Extension are having a unique target // which applies the configuration by itself on new documents. returnthis.watcherActor.sessionContext.type == "browser-element";
}
/** * Event handler for attached browsing context. This will be called when * a new browsing context is created that we might want to handle * (e.g. when navigating to a page with Cross-Origin-Opener-Policy header)
*/
_onBrowsingContextAttached(browsingContext) { if (!this._shouldHandleConfigurationInParentProcess()) { return;
}
// We only want to set flags on top-level browsing context. The platform // will take care of propagating it to the entire browsing contexts tree. if (browsingContext.parent) { return;
}
// Only process BrowsingContexts which are related to the debugged scope. // As this callback fires very early, the BrowsingContext may not have // any WindowGlobal yet and so we ignore all checks dones against the WindowGlobal // if there is none. Meaning we might accept more BrowsingContext than expected. if (
!isBrowsingContextPartOfContext(
browsingContext, this.watcherActor.sessionContext,
{ acceptNoWindowGlobal: true, forceAcceptTopLevelTarget: true }
)
) { return;
}
// Before replacing the target browsing context, restore the configuration // on the previous one if they share the same browser. if ( this._browsingContext && this._browsingContext.browserId === browsingContext.browserId &&
!this._browsingContext.isDiscarded
) { // For now this should always be true as long as we already had a browsing // context set, but the same logic should be used when supporting EFT on // toolboxes with several top level browsing contexts: when a new browsing // context attaches, only reset the browsing context with the same browserId this._restoreParentProcessConfiguration();
}
// We need to store the browsing context as this.watcherActor.browserElement.browsingContext // can still refer to the previous browsing context at this point. this._browsingContext = browsingContext;
// If `inRDMPane` was set in the previous browsing context, set it again on the new one, // otherwise some RDM-related configuration won't be applied (e.g. orientation). if (rdmEnabledInPreviousBrowsingContext) { this._browsingContext.inRDMPane = true;
} this._updateParentProcessConfiguration(this._getConfiguration());
}
/** * * @param {Object} configuration: See `updateConfiguration`
*/
_updateParentProcessConfiguration(configuration) { // Process "tracerOptions" for all session types, as this isn't specific to tab debugging if ("tracerOptions" in configuration) { this._setTracerOptions(configuration.tracerOptions);
}
if (!this._shouldHandleConfigurationInParentProcess()) { return;
}
let shouldReload = false; for (const [key, value] of Object.entries(configuration)) { switch (key) { case"colorSchemeSimulation": this._setColorSchemeSimulation(value); break; case"customUserAgent": this._setCustomUserAgent(value); break; case"javascriptEnabled": if (value !== undefined) { // This flag requires a reload in order to take full effect, // so reload if it has changed. if (value != this.isJavascriptEnabled()) {
shouldReload = true;
} this._setJavascriptEnabled(value);
} break; case"overrideDPPX": this._setDPPXOverride(value); break; case"printSimulationEnabled": this._setPrintSimulationEnabled(value); break; case"rdmPaneMaxTouchPoints": this._setRDMPaneMaxTouchPoints(value); break; case"rdmPaneOrientation": this._setRDMPaneOrientation(value); break; case"serviceWorkersTestingEnabled": this._setServiceWorkersTestingEnabled(value); break; case"touchEventsOverride": this._setTouchEventsOverride(value); break; case"cacheDisabled": this._setCacheDisabled(value); break; case"setTabOffline": this._setTabOffline(value); break;
}
}
if (shouldReload) { this._browsingContext.reload(Ci.nsIWebNavigation.LOAD_FLAGS_NONE);
}
}
_restoreParentProcessConfiguration() { // Always process tracer options as this isn't specific to tab debugging if (this.#consolePrefValue !== undefined) { this._setTracerOptions();
}
if (!this._shouldHandleConfigurationInParentProcess()) { return;
}
// Restore the color scheme simulation only if it was explicitly updated // by this actor. This will avoid side effects caused when destroying additional // targets (e.g. RDM target, WebExtension target, …). // TODO: We may want to review other configuration values to see if we should use // the same pattern (Bug 1701553). if (this._resetColorSchemeSimulationOnDestroy) { this._setColorSchemeSimulation(null);
}
// Restore the user agent only if it was explicitly updated by this specific actor. if (this._initialUserAgent !== undefined) { this._setCustomUserAgent(this._initialUserAgent);
}
// Restore the origin device pixel ratio only if it was explicitly updated by this // specific actor. if (this._initialDPPXOverride !== undefined) { this._setDPPXOverride(this._initialDPPXOverride);
}
if (this._initialJavascriptEnabled !== undefined) { this._setJavascriptEnabled(this._initialJavascriptEnabled);
}
if (this._initialTouchEventsOverride !== undefined) { this._setTouchEventsOverride(this._initialTouchEventsOverride);
}
}
/** * Disable or enable the service workers testing features.
*/
_setServiceWorkersTestingEnabled(enabled) { if (this._browsingContext.serviceWorkersTestingEnabled != enabled) { this._browsingContext.serviceWorkersTestingEnabled = enabled;
}
}
/** * Disable or enable the print simulation.
*/
_setPrintSimulationEnabled(enabled) { const value = enabled ? "print" : ""; if (this._browsingContext.mediumOverride != value) { this._browsingContext.mediumOverride = value;
}
}
/** * Disable or enable the color-scheme simulation.
*/
_setColorSchemeSimulation(override) { const value = override || "none"; if (this._browsingContext.prefersColorSchemeOverride != value) { this._browsingContext.prefersColorSchemeOverride = value; this._resetColorSchemeSimulationOnDestroy = true;
}
}
/** * Set a custom user agent on the page * * @param {String} userAgent: The user agent to set on the page. If null, will reset the * user agent to its original value. * @returns {Boolean} Whether the user agent was changed or not.
*/
_setCustomUserAgent(userAgent = "") { if (this._browsingContext.customUserAgent === userAgent) { return;
}
if (this._initialUserAgent === undefined) { this._initialUserAgent = this._browsingContext.customUserAgent;
}
if (dppx !== undefined) { this._browsingContext.overrideDPPX = dppx;
}
}
/** * Set the touchEventsOverride on the browsing context. * * @param {String} flag: See BrowsingContext.webidl `TouchEventsOverride` enum for values.
*/
_setTouchEventsOverride(flag) { if (this._browsingContext.touchEventsOverride === flag) { return;
}
if (!flag && this._initialTouchEventsOverride) {
flag = this._initialTouchEventsOverride;
} elseif (
flag !== undefined && this._initialTouchEventsOverride === undefined
) { this._initialTouchEventsOverride = this._browsingContext.touchEventsOverride;
}
if (flag !== undefined) { this._browsingContext.touchEventsOverride = flag;
}
}
/** * Overrides navigator.maxTouchPoints. * Note that we don't need to reset the original value when the actor is destroyed, * as it's directly handled by the platform when RDM is closed. * * @param {Integer} maxTouchPoints
*/
_setRDMPaneMaxTouchPoints(maxTouchPoints) { this._browsingContext.setRDMPaneMaxTouchPoints(maxTouchPoints);
}
/** * Set an orientation and an angle on the browsing context. This will be applied only * if Responsive Design Mode is enabled. * * @param {Object} options * @param {String} options.type: The orientation type of the rotated device. * @param {Number} options.angle: The rotated angle of the device.
*/
_setRDMPaneOrientation({ type, angle }) { this._browsingContext.setRDMPaneOrientation(type, angle);
}
/** * Disable or enable the cache via the browsing context. * * @param {Boolean} disabled: The state the cache should be changed to
*/
_setCacheDisabled(disabled) { const value = disabled
? Ci.nsIRequest.LOAD_BYPASS_CACHE
: Ci.nsIRequest.LOAD_NORMAL; if (this._browsingContext.defaultLoadFlags != value) { this._browsingContext.defaultLoadFlags = value;
}
}
/** * Set the browsing context to offline. * * @param {Boolean} offline: Whether the network throttling is set to offline
*/
_setTabOffline(offline) { if (!this._browsingContext.isDiscarded) { this._browsingContext.forceOffline = offline;
}
}
destroy() {
Services.obs.removeObserver( this._onBrowsingContextAttached, "browsing-context-attached"
); this.watcherActor.off( "bf-cache-navigation-pageshow", this._onBfCacheNavigation
); // Avoid trying to restore if the related context is already being destroyed if (this._browsingContext && !this._browsingContext.isDiscarded) { this._restoreParentProcessConfiguration();
} super.destroy();
}
/** * Called when the tracer is toggled on/off by the frontend. * Note that when `options` is defined, it is meant to be enabled. * It may not actually be tracing yet depending on the passed options. * * @param {Object} options
*/
_setTracerOptions(options) { if (!options) { if (this.#consolePrefValue === -1) {
Services.prefs.clearUserPref("logging.console");
} else {
Services.prefs.setIntPref("logging.console", this.#consolePrefValue);
} this.#consolePrefValue = undefined; return;
} // Enable `MOZ_LOG=console:5` via the logging.console so that all console API calls // are stored in the profiler when recording JS Traces via the profiler. // // We do this from here as TargetConfiguration runs in the parent process, // where we can set preferences. Whereas the profiler tracer actor runs in the content process. const LOG_DISABLED = -1; const LOG_VERBOSE = 5; this.#consolePrefValue = Services.prefs.getIntPref( "logging.console",
LOG_DISABLED
);
Services.prefs.setIntPref("logging.console", LOG_VERBOSE);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.