123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- /* 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";
- this.EXPORTED_SYMBOLS = [
- "MockRegistrar",
- ];
- const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr, manager: Cm} = Components;
- Cu.import("resource://gre/modules/XPCOMUtils.jsm");
- Cu.import("resource://gre/modules/Log.jsm");
- var logger = Log.repository.getLogger("MockRegistrar");
- this.MockRegistrar = Object.freeze({
- _registeredComponents: new Map(),
- _originalCIDs: new Map(),
- get registrar() {
- return Cm.QueryInterface(Ci.nsIComponentRegistrar);
- },
- /**
- * Register a mock to override target interfaces.
- * The target interface may be accessed through _genuine property of the mock.
- * If you register multiple mocks to the same contract ID, you have to call
- * unregister in reverse order. Otherwise the previous factory will not be
- * restored.
- *
- * @param contractID The contract ID of the interface which is overridden by
- the mock.
- * e.g. "@mozilla.org/file/directory_service;1"
- * @param mock An object which implements interfaces for the contract ID.
- * @param args An array which is passed in the constructor of mock.
- *
- * @return The CID of the mock.
- */
- register(contractID, mock, args) {
- let originalCID = this._originalCIDs.get(contractID);
- if (!originalCID) {
- originalCID = this.registrar.contractIDToCID(contractID);
- this._originalCIDs.set(contractID, originalCID);
- }
- let originalFactory = Cm.getClassObject(originalCID, Ci.nsIFactory);
- let factory = {
- createInstance(outer, iid) {
- if (outer) {
- throw Cr.NS_ERROR_NO_AGGREGATION;
- }
- let wrappedMock;
- if (mock.prototype && mock.prototype.constructor) {
- wrappedMock = Object.create(mock.prototype);
- mock.apply(wrappedMock, args);
- } else {
- wrappedMock = mock;
- }
- try {
- let genuine = originalFactory.createInstance(outer, iid);
- wrappedMock._genuine = genuine;
- } catch(ex) {
- logger.info("Creating original instance failed", ex);
- }
- return wrappedMock.QueryInterface(iid);
- },
- lockFactory(lock) {
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
- },
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory])
- };
- this.registrar.unregisterFactory(originalCID, originalFactory);
- this.registrar.registerFactory(originalCID,
- "A Mock for " + contractID,
- contractID,
- factory);
- this._registeredComponents.set(originalCID, {
- contractID: contractID,
- factory: factory,
- originalFactory: originalFactory
- });
- return originalCID;
- },
- /**
- * Unregister the mock.
- *
- * @param cid The CID of the mock.
- */
- unregister(cid) {
- let component = this._registeredComponents.get(cid);
- if (!component) {
- return;
- }
- this.registrar.unregisterFactory(cid, component.factory);
- if (component.originalFactory) {
- this.registrar.registerFactory(cid,
- "",
- component.contractID,
- component.originalFactory);
- }
- this._registeredComponents.delete(cid);
- },
- /**
- * Unregister all registered mocks.
- */
- unregisterAll() {
- for (let cid of this._registeredComponents.keys()) {
- this.unregister(cid);
- }
- }
- });
|