tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 0f883d56b31373cd28d83958610735cd83048f40
parent a689946d0f7a6ca9b5b7aee00826cac863a6c63b
Author: Alexandra Borovova <aborovova@mozilla.com>
Date:   Thu,  4 Dec 2025 12:27:58 +0000

Bug 2000651 - [webdriver-bidi] Implement "emulation.setScreenSettingsOverride" command. r=whimboo

Differential Revision: https://phabricator.services.mozilla.com/D273426

Diffstat:
Mremote/webdriver-bidi/modules/root/emulation.sys.mjs | 558++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mremote/webdriver-bidi/modules/windowglobal/_configuration.sys.mjs | 193++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
2 files changed, 497 insertions(+), 254 deletions(-)

diff --git a/remote/webdriver-bidi/modules/root/emulation.sys.mjs b/remote/webdriver-bidi/modules/root/emulation.sys.mjs @@ -453,42 +453,16 @@ class EmulationModule extends RootBiDiModule { ); } - const sessionDataItems = []; - // In case of resetting the override, remove existing session data items - // for the required context descriptors. - const onlyRemoveSessionDataItem = locale === ""; - - if (userContextIds !== null) { - for (const userContext of userContexts) { - sessionDataItems.push( - ...this.messageHandler.sessionData.generateSessionDataItemUpdate( - "_configuration", - "locale-override", - { - type: lazy.ContextDescriptorType.UserContext, - id: userContext, - }, - onlyRemoveSessionDataItem, - locale - ) - ); - } - } else { - for (const navigable of navigables) { - sessionDataItems.push( - ...this.messageHandler.sessionData.generateSessionDataItemUpdate( - "_configuration", - "locale-override", - { - type: lazy.ContextDescriptorType.TopBrowsingContext, - id: navigable.browserId, - }, - onlyRemoveSessionDataItem, - locale - ) - ); - } - } + const sessionDataItems = this.#generateSessionDataUpdate({ + category: "locale-override", + contextOverride: contextIds !== null, + hasGlobalOverride: false, + navigables, + resetValue: "", + userContexts, + userContextOverride: userContextIds !== null, + value: locale, + }); if (sessionDataItems.length) { // TODO: Bug 1953079. Saving the locale override in the session data works fine @@ -497,30 +471,15 @@ class EmulationModule extends RootBiDiModule { await this.messageHandler.updateSessionData(sessionDataItems); } - const commands = []; - - for (const navigable of navigables) { - const overrideValue = this.#getOverrideValue({ - category: "locale-override", - context: navigable, - contextIds, - userContextIds, - value: locale, - }); - - if (overrideValue === null) { - continue; - } - - commands.push( - this._setLocaleForBrowsingContext({ - locale: overrideValue, - context: navigable, - }) - ); - } - - await Promise.all(commands); + await this.#applyOverride({ + async: true, + callback: this._setLocaleForBrowsingContext.bind(this), + category: "locale-override", + contextIds, + navigables, + userContextIds, + value: locale, + }); } /** @@ -710,6 +669,157 @@ class EmulationModule extends RootBiDiModule { } /** + * Used as an argument for emulation.setScreenSettingsOverride command + * to represent an object which holds screen area settings which + * should override screen dimensions. + * + * @typedef {object} ScreenArea + * + * @property {number} height + * @property {number} width + */ + + /** + * Set the screen settings override to the list of top-level navigables + * or user contexts. + * + * @param {object=} options + * @param {Array<string>=} options.contexts + * Optional list of browsing context ids. + * @param {(ScreenArea|null)} options.screenArea + * An object which has to override + * the return result of JavaScript APIs which return + * screen dimensions. Null value resets the override. + * @param {Array<string>=} options.userContexts + * Optional list of user context ids. + * + * @throws {InvalidArgumentError} + * Raised if an argument is of an invalid type or value. + * @throws {NoSuchFrameError} + * If the browsing context cannot be found. + * @throws {NoSuchUserContextError} + * Raised if the user context id could not be found. + */ + async setScreenSettingsOverride(options = {}) { + const { + contexts: contextIds = null, + screenArea, + userContexts: userContextIds = null, + } = options; + + if (screenArea !== null) { + lazy.assert.object( + screenArea, + lazy.pprint`Expected "screenArea" to be an object, got ${screenArea}` + ); + + const { height, width } = screenArea; + lazy.assert.positiveNumber( + height, + lazy.pprint`Expected "screenArea.height" to be a positive number, got ${height}` + ); + lazy.assert.positiveNumber( + width, + lazy.pprint`Expected "screenArea.width" to be a positive number, got ${width}` + ); + } + + if (contextIds !== null && userContextIds !== null) { + throw new lazy.error.InvalidArgumentError( + `Providing both "contexts" and "userContexts" arguments is not supported` + ); + } + + const navigables = new Set(); + const userContexts = new Set(); + if (contextIds !== null) { + lazy.assert.isNonEmptyArray( + contextIds, + lazy.pprint`Expected "contexts" to be a non-empty array, got ${contextIds}` + ); + + for (const contextId of contextIds) { + lazy.assert.string( + contextId, + lazy.pprint`Expected elements of "contexts" to be a string, got ${contextId}` + ); + + const context = this._getNavigable(contextId); + + lazy.assert.topLevel( + context, + `Browsing context with id ${contextId} is not top-level` + ); + + navigables.add(context); + } + } else if (userContextIds !== null) { + lazy.assert.isNonEmptyArray( + userContextIds, + lazy.pprint`Expected "userContexts" to be a non-empty array, got ${userContextIds}` + ); + + for (const userContextId of userContextIds) { + lazy.assert.string( + userContextId, + lazy.pprint`Expected elements of "userContexts" to be a string, got ${userContextId}` + ); + + const internalId = + lazy.UserContextManager.getInternalIdById(userContextId); + + if (internalId === null) { + throw new lazy.error.NoSuchUserContextError( + `User context with id: ${userContextId} doesn't exist` + ); + } + + userContexts.add(internalId); + + // Prepare the list of navigables to update. + lazy.UserContextManager.getTabsForUserContext(internalId).forEach( + tab => { + const contentBrowser = lazy.TabManager.getBrowserForTab(tab); + navigables.add(contentBrowser.browsingContext); + } + ); + } + } else { + throw new lazy.error.InvalidArgumentError( + `At least one of "contexts" or "userContexts" arguments should be provided` + ); + } + + const sessionDataItems = this.#generateSessionDataUpdate({ + category: "screen-settings-override", + contextOverride: contextIds !== null, + hasGlobalOverride: false, + navigables, + resetValue: null, + userContexts, + userContextOverride: userContextIds !== null, + value: screenArea, + }); + + if (sessionDataItems.length) { + // TODO: Bug 1953079. Saving the locale override in the session data works fine + // with one session, but when we start supporting multiple BiDi session, we will + // have to rethink this approach. + await this.messageHandler.updateSessionData(sessionDataItems); + } + + this.#applyOverride({ + callback: this._setScreenSettingsOverride, + category: "screen-settings-override", + contextIds, + navigables, + resetValue: null, + userContextIds, + value: screenArea, + }); + } + + /** * Set the timezone override to the list of top-level navigables * or user contexts. * @@ -829,42 +939,16 @@ class EmulationModule extends RootBiDiModule { ); } - const sessionDataItems = []; - // In case of resetting the override, remove existing session data items - // for the required context descriptors. - const onlyRemoveSessionDataItem = timezone === ""; - - if (userContextIds !== null) { - for (const userContext of userContexts) { - sessionDataItems.push( - ...this.messageHandler.sessionData.generateSessionDataItemUpdate( - "_configuration", - "timezone-override", - { - type: lazy.ContextDescriptorType.UserContext, - id: userContext, - }, - onlyRemoveSessionDataItem, - timezone - ) - ); - } - } else { - for (const navigable of navigables) { - sessionDataItems.push( - ...this.messageHandler.sessionData.generateSessionDataItemUpdate( - "_configuration", - "timezone-override", - { - type: lazy.ContextDescriptorType.TopBrowsingContext, - id: navigable.browserId, - }, - onlyRemoveSessionDataItem, - timezone - ) - ); - } - } + const sessionDataItems = this.#generateSessionDataUpdate({ + category: "timezone-override", + contextOverride: contextIds !== null, + hasGlobalOverride: false, + navigables, + resetValue: "", + userContexts, + userContextOverride: userContextIds !== null, + value: timezone, + }); if (sessionDataItems.length) { // TODO: Bug 1953079. Saving the timezone override in the session data works fine @@ -873,30 +957,15 @@ class EmulationModule extends RootBiDiModule { await this.messageHandler.updateSessionData(sessionDataItems); } - const commands = []; - - for (const navigable of navigables) { - const overrideValue = this.#getOverrideValue({ - category: "timezone-override", - context: navigable, - contextIds, - userContextIds, - value: timezone, - }); - - if (overrideValue === null) { - continue; - } - - commands.push( - this._setTimezoneOverride({ - context: navigable, - timezone: overrideValue, - }) - ); - } - - await Promise.all(commands); + await this.#applyOverride({ + async: true, + callback: this._setTimezoneOverride.bind(this), + category: "timezone-override", + contextIds, + navigables, + userContextIds, + value: timezone, + }); } /** @@ -1006,54 +1075,16 @@ class EmulationModule extends RootBiDiModule { ); } - const sessionDataItems = []; - // In case of resetting the override, remove existing session data items - // for the required context descriptors. - const onlyRemoveSessionDataItem = userAgent === ""; - - if (userContextIds !== undefined) { - for (const userContext of userContexts) { - sessionDataItems.push( - ...this.messageHandler.sessionData.generateSessionDataItemUpdate( - "_configuration", - "user-agent-override", - { - type: lazy.ContextDescriptorType.UserContext, - id: userContext, - }, - onlyRemoveSessionDataItem, - userAgent - ) - ); - } - } else if (contextIds !== undefined) { - for (const navigable of navigables) { - sessionDataItems.push( - ...this.messageHandler.sessionData.generateSessionDataItemUpdate( - "_configuration", - "user-agent-override", - { - type: lazy.ContextDescriptorType.TopBrowsingContext, - id: navigable.browserId, - }, - onlyRemoveSessionDataItem, - userAgent - ) - ); - } - } else { - sessionDataItems.push( - ...this.messageHandler.sessionData.generateSessionDataItemUpdate( - "_configuration", - "user-agent-override", - { - type: lazy.ContextDescriptorType.All, - }, - onlyRemoveSessionDataItem, - userAgent - ) - ); - } + const sessionDataItems = this.#generateSessionDataUpdate({ + category: "user-agent-override", + contextOverride: contextIds !== undefined, + hasGlobalOverride: true, + navigables, + resetValue: "", + userContexts, + userContextOverride: userContextIds !== undefined, + value: userAgent, + }); if (sessionDataItems.length) { // TODO: Bug 1953079. Saving the user agent override in the session data works fine @@ -1062,24 +1093,14 @@ class EmulationModule extends RootBiDiModule { await this.messageHandler.updateSessionData(sessionDataItems); } - for (const navigable of navigables) { - const overrideValue = this.#getOverrideValue({ - category: "user-agent-override", - context: navigable, - contextIds, - userContextIds, - value: userAgent, - }); - - if (overrideValue === null) { - continue; - } - - this._setUserAgentOverride({ - context: navigable, - userAgent: overrideValue, - }); - } + this.#applyOverride({ + callback: this._setUserAgentOverride, + category: "user-agent-override", + contextIds, + navigables, + userContextIds, + value: userAgent, + }); } /** @@ -1111,15 +1132,15 @@ class EmulationModule extends RootBiDiModule { * @param {BrowsingContext} options.context * Top-level browsing context object which is a target * for the locale override. - * @param {(string|null)} options.locale + * @param {(string|null)} options.value * Locale string which have to override * the return result of JavaScript Intl APIs. * Null value resets the override. */ async _setLocaleForBrowsingContext(options) { - const { context, locale } = options; + const { context, value } = options; - context.languageOverride = locale; + context.languageOverride = value; await this.messageHandler.handleCommand({ moduleName: "emulation", @@ -1132,27 +1153,50 @@ class EmulationModule extends RootBiDiModule { }, }, params: { - locale, + locale: value, }, }); } /** + * Set the screen settings override to the top-level browsing context. + * + * @param {object} options + * @param {BrowsingContext} options.context + * Top-level browsing context object which is a target + * for the locale override. + * @param {(ScreenArea|null)} options.value + * An object which has to override + * the return result of JavaScript APIs which return + * screen dimensions. Null value resets the override. + */ + _setScreenSettingsOverride(options) { + const { context, value } = options; + + if (value === null) { + context.resetScreenAreaOverride(); + } else { + const { height, width } = value; + context.setScreenAreaOverride(width, height); + } + } + + /** * Set the timezone override to the top-level browsing context. * * @param {object} options * @param {BrowsingContext} options.context * Top-level browsing context object which is a target * for the locale override. - * @param {(string|null)} options.timezone + * @param {(string|null)} options.value * Timezone string which has to override * the return result of JavaScript Intl/Date APIs. * Null value resets the override. */ async _setTimezoneOverride(options) { - const { context, timezone } = options; + const { context, value } = options; - context.timezoneOverride = timezone; + context.timezoneOverride = value; await this.messageHandler.handleCommand({ moduleName: "emulation", @@ -1165,7 +1209,7 @@ class EmulationModule extends RootBiDiModule { }, }, params: { - timezone, + timezone: value, }, }); } @@ -1177,15 +1221,15 @@ class EmulationModule extends RootBiDiModule { * @param {BrowsingContext} options.context * Top-level browsing context object which is a target * for the locale override. - * @param {string} options.userAgent + * @param {string} options.value * User agent string which has to override * the browser user agent. */ _setUserAgentOverride(options) { - const { context, userAgent } = options; + const { context, value } = options; try { - context.customUserAgent = userAgent; + context.customUserAgent = value; } catch (e) { const contextId = lazy.NavigableManager.getIdForBrowsingContext(context); @@ -1195,34 +1239,142 @@ class EmulationModule extends RootBiDiModule { } } - #getOverrideValue(params) { + async #applyOverride(options) { + const { + async = false, + callback, + category, + contextIds, + navigables, + resetValue = "", + userContextIds, + value, + } = options; + + const commands = []; + + for (const navigable of navigables) { + const overrideValue = this.#getOverrideValue( + { + category, + context: navigable, + contextIds, + userContextIds, + value, + }, + resetValue + ); + + if (overrideValue === undefined) { + continue; + } + + const commandArgs = { + context: navigable, + value: overrideValue, + }; + + if (async) { + commands.push(callback(commandArgs)); + } else { + callback(commandArgs); + } + } + + if (async) { + await Promise.all(commands); + } + } + + #generateSessionDataUpdate(options) { + const { + category, + contextOverride, + hasGlobalOverride, + navigables, + resetValue, + userContexts, + userContextOverride, + value, + } = options; + const sessionDataItems = []; + const onlyRemoveSessionDataItem = value === resetValue; + + if (userContextOverride) { + for (const userContext of userContexts) { + sessionDataItems.push( + ...this.messageHandler.sessionData.generateSessionDataItemUpdate( + "_configuration", + category, + { + type: lazy.ContextDescriptorType.UserContext, + id: userContext, + }, + onlyRemoveSessionDataItem, + value + ) + ); + } + } else if (contextOverride) { + for (const navigable of navigables) { + sessionDataItems.push( + ...this.messageHandler.sessionData.generateSessionDataItemUpdate( + "_configuration", + category, + { + type: lazy.ContextDescriptorType.TopBrowsingContext, + id: navigable.browserId, + }, + onlyRemoveSessionDataItem, + value + ) + ); + } + } else if (hasGlobalOverride) { + sessionDataItems.push( + ...this.messageHandler.sessionData.generateSessionDataItemUpdate( + "_configuration", + category, + { + type: lazy.ContextDescriptorType.All, + }, + onlyRemoveSessionDataItem, + value + ) + ); + } + + return sessionDataItems; + } + + #getOverrideValue(params, resetValue = "") { const { category, context, contextIds, userContextIds, value } = params; const [overridePerContext, overridePerUserContext, overrideGlobal] = this.#findExistingOverrideForContext(category, context); if (contextIds) { - if (value === "") { + if (value === resetValue) { // In case of resetting an override for navigable, // if there is an existing override for user context or global, // we should apply it to browsing context. - return overridePerUserContext || overrideGlobal || ""; + return overridePerUserContext || overrideGlobal || resetValue; } } else if (userContextIds) { // No need to do anything if there is an override // for the browsing context. if (overridePerContext) { - return null; + return undefined; } // In case of resetting an override for user context, // apply a global override if it exists - if (value === "" && overrideGlobal) { + if (value === resetValue && overrideGlobal) { return overrideGlobal; } } else if (overridePerContext || overridePerUserContext) { // No need to do anything if there is an override // for the browsing or user context. - return null; + return undefined; } return value; diff --git a/remote/webdriver-bidi/modules/windowglobal/_configuration.sys.mjs b/remote/webdriver-bidi/modules/windowglobal/_configuration.sys.mjs @@ -24,6 +24,7 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { #preloadScripts; #resolveBlockerPromise; #screenOrientationOverride; + #screenSettingsOverride; #timezoneOverride; #userAgentOverride; #viewportConfiguration; @@ -35,6 +36,7 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { this.#localeOverride = null; this.#preloadScripts = new Set(); this.#screenOrientationOverride = undefined; + this.#screenSettingsOverride = undefined; this.#timezoneOverride = null; this.#userAgentOverride = null; this.#viewportConfiguration = new Map(); @@ -69,6 +71,7 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { this.#geolocationConfiguration === undefined && this.#localeOverride === null && this.#screenOrientationOverride === undefined && + this.#screenSettingsOverride === undefined && this.#timezoneOverride === null && this.#userAgentOverride === null ) { @@ -114,7 +117,22 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { }, params: { context: this.messageHandler.context, - locale: this.#localeOverride, + value: this.#localeOverride, + }, + }); + } + + // Compare with `undefined`, since `null` value is used as a reset value. + if (this.#screenSettingsOverride !== undefined) { + await this.messageHandler.forwardCommand({ + moduleName: "emulation", + commandName: "_setScreenSettingsOverride", + destination: { + type: lazy.RootMessageHandler.type, + }, + params: { + context: this.messageHandler.context, + value: this.#screenSettingsOverride, }, }); } @@ -128,7 +146,7 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { }, params: { context: this.messageHandler.context, - timezone: this.#timezoneOverride, + value: this.#timezoneOverride, }, }); } @@ -142,7 +160,7 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { }, params: { context: this.messageHandler.context, - userAgent: this.#userAgentOverride, + value: this.#userAgentOverride, }, }); } @@ -196,6 +214,85 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { } /** + * Check if the provided value matches the provided type. + * + * @param {*} value + * The value to verify. + * @param {string} type + * The type to match. + * + * @returns {boolean} + * Returns true if the value type is the same as + * the provided type. False, otherwise. + */ + #isOfType(value, type) { + if (type === "object") { + return typeof value === "object" && value !== null; + } + + return typeof value === type; + } + + /** + * For some emulations a value set per a browsing context overrides + * a value set per a user context or set globally. And a value set per + * a user context overrides a global value. + * + * @param {string} type + * The type to verify that the value was set. + * @param {*} contextValue + * The override value set per browsing context. + * @param {*} userContextValue + * The override value set per user context. + * @param {*} globalValue + * The override value set globally. + * + * @returns {*} + * Returns the override value which should be applied. + */ + #findCorrectOverrideValue(type, contextValue, userContextValue, globalValue) { + if (this.#isOfType(contextValue, type)) { + return contextValue; + } + if (this.#isOfType(userContextValue, type)) { + return userContextValue; + } + if (this.#isOfType(globalValue, type)) { + return globalValue; + } + return null; + } + + async #onConfigurationComplete(window) { + // parser blocking doesn't work for initial about:blank, so ensure + // browsing_context.create waits for configuration to complete + if (window.document.isInitialDocument) { + await this.messageHandler.forwardCommand({ + moduleName: "browsingContext", + commandName: "_onConfigurationComplete", + destination: { + type: lazy.RootMessageHandler.type, + }, + params: { + navigable: this.messageHandler.context, + }, + }); + } + } + + #updatePreloadScripts(sessionData) { + this.#preloadScripts.clear(); + + for (const { contextDescriptor, value } of sessionData) { + if (!this.messageHandler.matchesContext(contextDescriptor)) { + continue; + } + + this.#preloadScripts.add(value); + } + } + + /** * Internal commands */ @@ -203,30 +300,28 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { const { category, sessionData } = params; if (category === "preload-script") { - this.#preloadScripts.clear(); - - for (const { contextDescriptor, value } of sessionData) { - if (!this.messageHandler.matchesContext(contextDescriptor)) { - continue; - } - - this.#preloadScripts.add(value); - } + this.#updatePreloadScripts(sessionData); } // The following overrides apply only to top-level traversables. if ( - (category === "geolocation-override" || - category === "viewport-overrides" || - category === "locale-override" || - category === "screen-orientation-override" || - category === "timezone-override" || - category === "user-agent-override") && + [ + "geolocation-override", + "locale-override", + "screen-orientation-override", + "screen-settings-override", + "timezone-override", + "user-agent-override", + "viewport-overrides", + ].includes(category) && !this.messageHandler.context.parent ) { let localeOverridePerContext = null; let localeOverridePerUserContext = null; + let screenSettingsOverridePerContext = null; + let screenSettingsOverridePerUserContext = null; + let timezoneOverridePerContext = null; let timezoneOverridePerUserContext = null; @@ -270,6 +365,19 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { } break; } + case "screen-settings-override": { + switch (contextDescriptor.type) { + case lazy.ContextDescriptorType.TopBrowsingContext: { + screenSettingsOverridePerContext = value; + break; + } + case lazy.ContextDescriptorType.UserContext: { + screenSettingsOverridePerUserContext = value; + break; + } + } + break; + } case "screen-orientation-override": { this.#screenOrientationOverride = value; break; @@ -306,16 +414,31 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { } } + // For the following emulations on the previous step, we found session items + // that would apply an override for a browsing context,a user context, and in some cases globally. + // Now from these items we have to choose the one that would take precedence. + // The order is the user context item overrides the global one, and the browsing context overrides the user context item. switch (category) { case "locale-override": { this.#localeOverride = this.#findCorrectOverrideValue( + "string", localeOverridePerContext, localeOverridePerUserContext ); break; } + case "screen-settings-override": { + this.#screenSettingsOverride = this.#findCorrectOverrideValue( + "object", + screenSettingsOverridePerContext, + screenSettingsOverridePerUserContext + ); + + break; + } case "timezone-override": { this.#timezoneOverride = this.#findCorrectOverrideValue( + "string", timezoneOverridePerContext, timezoneOverridePerUserContext ); @@ -324,6 +447,7 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { } case "user-agent-override": { this.#userAgentOverride = this.#findCorrectOverrideValue( + "string", userAgentOverridePerContext, userAgentOverridePerUserContext, userAgentOverrideGlobal @@ -334,39 +458,6 @@ class _ConfigurationModule extends WindowGlobalBiDiModule { } } } - - // For some emulations a value set per a browsing context overrides - // a value set per a user context or set globally. And a value set per - // a user context overrides a global value. - #findCorrectOverrideValue(contextValue, userContextValue, globalValue) { - if (typeof contextValue === "string") { - return contextValue; - } - if (typeof userContextValue === "string") { - return userContextValue; - } - if (typeof globalValue === "string") { - return globalValue; - } - return null; - } - - async #onConfigurationComplete(window) { - // parser blocking doesn't work for initial about:blank, so ensure - // browsing_context.create waits for configuration to complete - if (window.document.isInitialDocument) { - await this.messageHandler.forwardCommand({ - moduleName: "browsingContext", - commandName: "_onConfigurationComplete", - destination: { - type: lazy.RootMessageHandler.type, - }, - params: { - navigable: this.messageHandler.context, - }, - }); - } - } } export const _configuration = _ConfigurationModule;