From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../browser/shared-modules/MockObjectHelpers.jsm | 161 +++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 comm/mail/test/browser/shared-modules/MockObjectHelpers.jsm (limited to 'comm/mail/test/browser/shared-modules/MockObjectHelpers.jsm') diff --git a/comm/mail/test/browser/shared-modules/MockObjectHelpers.jsm b/comm/mail/test/browser/shared-modules/MockObjectHelpers.jsm new file mode 100644 index 0000000000..3b4ed91e53 --- /dev/null +++ b/comm/mail/test/browser/shared-modules/MockObjectHelpers.jsm @@ -0,0 +1,161 @@ +/* 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 EXPORTED_SYMBOLS = ["MockObjectReplacer", "MockObjectRegisterer"]; + +var Cm = Components.manager; + +function MockObjectRegisterer(aContractID, aCID, aComponent) { + this._contractID = aContractID; + this._cid = Components.ID("{" + aCID + "}"); + this._component = aComponent; +} + +MockObjectRegisterer.prototype = { + register() { + let providedConstructor = this._component; + this._mockFactory = { + createInstance(aIid) { + return new providedConstructor().QueryInterface(aIid); + }, + }; + + let componentRegistrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); + + componentRegistrar.registerFactory( + this._cid, + "", + this._contractID, + this._mockFactory + ); + }, + + unregister() { + let componentRegistrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); + + componentRegistrar.unregisterFactory(this._cid, this._mockFactory); + }, +}; + +/** + * Allows registering a mock XPCOM component, that temporarily replaces the + * original one when an object implementing a given ContractID is requested + * using createInstance. + * + * @param aContractID + * The ContractID of the component to replace, for example + * "@mozilla.org/filepicker;1". + * + * @param aReplacementCtor + * The constructor function for the JavaScript object that will be + * created every time createInstance is called. This object must + * implement QueryInterface and provide the XPCOM interfaces required by + * the specified ContractID (for example + * Ci.nsIFilePicker). + */ + +function MockObjectReplacer(aContractID, aReplacementCtor) { + this._contractID = aContractID; + this._replacementCtor = aReplacementCtor; + this._cid = null; +} + +MockObjectReplacer.prototype = { + /** + * Replaces the current factory with one that returns a new mock object. + * + * After register() has been called, it is mandatory to call unregister() to + * restore the original component. Usually, you should use a try-catch block + * to ensure that unregister() is called. + */ + register() { + if (this._cid) { + throw Error("Invalid object state when calling register()"); + } + + // Define a factory that creates a new object using the given constructor. + var providedConstructor = this._replacementCtor; + this._mockFactory = { + createInstance(aIid) { + return new providedConstructor().QueryInterface(aIid); + }, + }; + + var retVal = swapFactoryRegistration( + this._cid, + this._originalCID, + this._contractID, + this._mockFactory + ); + if ("error" in retVal) { + throw new Error("ERROR: " + retVal.error); + } else { + this._cid = retVal.cid; + this._originalCID = retVal.originalCID; + } + }, + + /** + * Restores the original factory. + */ + unregister() { + if (!this._cid) { + throw Error("Invalid object state when calling unregister()"); + } + + // Free references to the mock factory. + swapFactoryRegistration( + this._cid, + this._originalCID, + this._contractID, + this._mockFactory + ); + + // Allow registering a mock factory again later. + this._cid = null; + this._originalCID = null; + this._mockFactory = null; + }, + + // --- Private methods and properties --- + + /** + * The CID under which the mock contractID was registered. + */ + _cid: null, + + /** + * The nsIFactory that was automatically generated by this object. + */ + _mockFactory: null, +}; + +/** + * Swiped from mozilla/testing/mochitest/tests/SimpleTest/specialpowersAPI.js + */ +function swapFactoryRegistration(CID, originalCID, contractID, newFactory) { + let componentRegistrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); + + if (originalCID == null) { + if (contractID != null) { + originalCID = componentRegistrar.contractIDToCID(contractID); + void Cm.getClassObject(Cc[contractID], Ci.nsIFactory); + } else { + return { + error: "trying to register a new contract ID: Missing contractID", + }; + } + CID = Services.uuid.generateUUID(); + + componentRegistrar.registerFactory(CID, "", contractID, newFactory); + } else { + componentRegistrar.unregisterFactory(CID, newFactory); + // Restore the original factory. + componentRegistrar.registerFactory(originalCID, "", contractID, null); + } + + return { cid: CID, originalCID }; +} -- cgit v1.2.3