Bug 1478124: Part 1 - Update component mocks to replace and restore components sanely. r=froydnj

For static components, I don't intend to allow removing or replacing CID
entries, only contract ID entries. And I would generally prefer, when
restoring overrides of those classes, to not create a new dynamic factory
entry for the contract ID.

We already have the ability to mock components without either of those issues,
but registering a new CID entry for the mock (without unregistering the
original), and then restoring the original by calling `registerFactory` with a
null factory object.

This patch updates our existing mocks to behave that way, and paves the way
for the rest of the patches.

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

--HG--
extra : rebase_source : 449f37ae8a3cc970e5f864d10e43e88d9e7e4bf6
extra : source : bedaa9c437ad30ea88bdc0e8fc83f4a2e980812e
This commit is contained in:
Kris Maglione 2018-12-19 15:49:48 -08:00
Родитель 0482099be6
Коммит ee6633da5c
3 изменённых файлов: 32 добавлений и 27 удалений

Просмотреть файл

@ -25,9 +25,6 @@ function registerMockedFactory(contractId, mockedClassId, mockedFactory) {
originalClassId = "";
originalFactory = null;
}
if (originalFactory) {
registrar.unregisterFactory(originalClassId, originalFactory);
}
registrar.registerFactory(mockedClassId, "", contractId, mockedFactory);
}
@ -42,7 +39,9 @@ function registerOriginalFactory(contractId, mockedClassId, mockedFactory, origi
if (originalFactory) {
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
registrar.unregisterFactory(mockedClassId, mockedFactory);
registrar.registerFactory(originalClassId, "", contractId, originalFactory);
// Passing null for the factory remaps the original CID to the
// contract ID.
registrar.registerFactory(originalClassId, "", contractId, null);
}
}

Просмотреть файл

@ -11,8 +11,13 @@ var EXPORTED_SYMBOLS = [
const Cm = Components.manager;
const {Log} = ChromeUtils.import("resource://gre/modules/Log.jsm");
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
var logger = Log.repository.getLogger("MockRegistrar");
XPCOMUtils.defineLazyServiceGetter(this, "UUIDGen",
"@mozilla.org/uuid-generator;1",
"nsIUUIDGenerator");
var MockRegistrar = Object.freeze({
_registeredComponents: new Map(),
_originalCIDs: new Map(),
@ -44,6 +49,8 @@ var MockRegistrar = Object.freeze({
let originalFactory = Cm.getClassObject(originalCID, Ci.nsIFactory);
let cid = UUIDGen.generateUUID();
let factory = {
createInstance(outer, iid) {
if (outer) {
@ -73,19 +80,18 @@ var MockRegistrar = Object.freeze({
QueryInterface: ChromeUtils.generateQI([Ci.nsIFactory]),
};
this.registrar.unregisterFactory(originalCID, originalFactory);
this.registrar.registerFactory(originalCID,
this.registrar.registerFactory(cid,
"A Mock for " + contractID,
contractID,
factory);
this._registeredComponents.set(originalCID, {
this._registeredComponents.set(cid, {
contractID,
factory,
originalFactory,
originalCID,
});
return originalCID;
return cid;
},
/**
@ -100,11 +106,12 @@ var MockRegistrar = Object.freeze({
}
this.registrar.unregisterFactory(cid, component.factory);
if (component.originalFactory) {
this.registrar.registerFactory(cid,
"",
if (component.originalCID) {
// Passing `null` for the factory re-maps the contract ID to the
// entry for its original CID.
this.registrar.registerFactory(component.originalCID, "",
component.contractID,
component.originalFactory);
null);
}
this._registeredComponents.delete(cid);

Просмотреть файл

@ -248,18 +248,17 @@ var _fakeIdleService = {
Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
},
contractID: "@mozilla.org/widget/idleservice;1",
get CID() {
return this.registrar.contractIDToCID(this.contractID);
},
CID: Components.ID("{9163a4ae-70c2-446c-9ac1-bbe4ab93004e}"),
activate: function FIS_activate() {
if (!this.originalFactory) {
// Save original factory.
this.originalFactory =
Components.manager.getClassObject(Cc[this.contractID],
Ci.nsIFactory);
// Unregister original factory.
this.registrar.unregisterFactory(this.CID, this.originalFactory);
if (!this.originalCID) {
// This is useless, except to the extent that it has the
// side-effect of initializing the widget module, which some
// callers unfortunately accidentally rely on.
void Components.manager.getClassObject(Cc[this.contractID],
Ci.nsIFactory);
this.originalCID = this.registrar.contractIDToCID(this.contractID);
// Replace with the mock.
this.registrar.registerFactory(this.CID, "Fake Idle Service",
this.contractID, this.factory
@ -268,13 +267,13 @@ var _fakeIdleService = {
},
deactivate: function FIS_deactivate() {
if (this.originalFactory) {
if (this.originalCID) {
// Unregister the mock.
this.registrar.unregisterFactory(this.CID, this.factory);
// Restore original factory.
this.registrar.registerFactory(this.CID, "Idle Service",
this.contractID, this.originalFactory);
delete this.originalFactory;
this.registrar.registerFactory(this.originalCID, "Idle Service",
this.contractID, null);
delete this.originalCID;
}
},