Bug 1753131 - use MediaManager device list change coalescing for MediaDevices r=jib
[gecko.git] / testing / modules / MockRegistrar.jsm
blob7e05fe14fc3fb9300f23c08114d7b473ef845eb8
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 "use strict";
7 var EXPORTED_SYMBOLS = ["MockRegistrar"];
9 const Cm = Components.manager;
11 const { Log } = ChromeUtils.import("resource://gre/modules/Log.jsm");
12 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
13 var logger = Log.repository.getLogger("MockRegistrar");
15 var MockRegistrar = Object.freeze({
16   _registeredComponents: new Map(),
17   _originalCIDs: new Map(),
18   get registrar() {
19     return Cm.QueryInterface(Ci.nsIComponentRegistrar);
20   },
22   /**
23    * Register a mock to override target interfaces.
24    * The target interface may be accessed through _genuine property of the mock.
25    * If you register multiple mocks to the same contract ID, you have to call
26    * unregister in reverse order. Otherwise the previous factory will not be
27    * restored.
28    *
29    * @param contractID The contract ID of the interface which is overridden by
30                        the mock.
31    *                   e.g. "@mozilla.org/file/directory_service;1"
32    * @param mock       An object which implements interfaces for the contract ID.
33    * @param args       An array which is passed in the constructor of mock.
34    *
35    * @return           The CID of the mock.
36    */
37   register(contractID, mock, args) {
38     let originalCID = this._originalCIDs.get(contractID);
39     if (!originalCID) {
40       originalCID = this.registrar.contractIDToCID(contractID);
41       this._originalCIDs.set(contractID, originalCID);
42     }
44     let originalFactory = Cm.getClassObject(originalCID, Ci.nsIFactory);
46     let cid = Services.uuid.generateUUID();
48     let factory = {
49       createInstance(outer, iid) {
50         if (outer) {
51           throw Components.Exception("", Cr.NS_ERROR_NO_AGGREGATION);
52         }
54         let wrappedMock;
55         if (mock.prototype && mock.prototype.constructor) {
56           wrappedMock = Object.create(mock.prototype);
57           mock.apply(wrappedMock, args);
58         } else {
59           wrappedMock = mock;
60         }
62         try {
63           let genuine = originalFactory.createInstance(outer, iid);
64           wrappedMock._genuine = genuine;
65         } catch (ex) {
66           logger.info("Creating original instance failed", ex);
67         }
69         return wrappedMock.QueryInterface(iid);
70       },
71       lockFactory(lock) {
72         throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
73       },
74       QueryInterface: ChromeUtils.generateQI(["nsIFactory"]),
75     };
77     this.registrar.registerFactory(
78       cid,
79       "A Mock for " + contractID,
80       contractID,
81       factory
82     );
84     this._registeredComponents.set(cid, {
85       contractID,
86       factory,
87       originalCID,
88     });
90     return cid;
91   },
93   /**
94    * Unregister the mock.
95    *
96    * @param cid The CID of the mock.
97    */
98   unregister(cid) {
99     let component = this._registeredComponents.get(cid);
100     if (!component) {
101       return;
102     }
104     this.registrar.unregisterFactory(cid, component.factory);
105     if (component.originalCID) {
106       // Passing `null` for the factory re-maps the contract ID to the
107       // entry for its original CID.
108       this.registrar.registerFactory(
109         component.originalCID,
110         "",
111         component.contractID,
112         null
113       );
114     }
116     this._registeredComponents.delete(cid);
117   },
119   /**
120    * Unregister all registered mocks.
121    */
122   unregisterAll() {
123     for (let cid of this._registeredComponents.keys()) {
124       this.unregister(cid);
125     }
126   },