зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1458327 - 2. Let ModuleManager manage more aspects of modules; r=esawin
Let ModuleManager keep the current settings and enabled states for modules. It initializes settings and module states from the window init-data, and then listens to changes in them. Having ModuleManager manage these states helps keeping things consistent, and makes it possible for future optimizations like delay-loading modules. MozReview-Commit-ID: AM6lAxnUGhd --HG-- extra : rebase_source : 2751990bec6054cc36104957690d8fce6d3da399
This commit is contained in:
Родитель
ad471d48f6
Коммит
46997650b0
|
@ -15,39 +15,172 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
XPCOMUtils.defineLazyGetter(this, "WindowEventDispatcher",
|
||||
() => EventDispatcher.for(window));
|
||||
|
||||
// Creates and manages GeckoView modules.
|
||||
// A module must extend GeckoViewModule.
|
||||
// Instantiate a module by calling
|
||||
// add(<resource path>, <type name>)
|
||||
// and remove by calling
|
||||
// remove(<type name>)
|
||||
/**
|
||||
* ModuleManager creates and manages GeckoView modules. Each GeckoView module
|
||||
* normally consists of a JSM file with an optional frame script file. The JSM
|
||||
* file contains a class that extends GeckoViewModule. A module usually pairs
|
||||
* with a particular GeckoSessionHandler or delegate on the Java side, and
|
||||
* automatically receives module lifetime events such as initialization, change
|
||||
* in enabled state, and change in settings.
|
||||
*/
|
||||
var ModuleManager = {
|
||||
init: function(aBrowser) {
|
||||
this.browser = aBrowser;
|
||||
this.modules = new Map();
|
||||
get _initData() {
|
||||
return window.arguments[0].QueryInterface(Ci.nsIAndroidView).initData;
|
||||
},
|
||||
|
||||
add: function(aResource, aType, ...aArgs) {
|
||||
this.remove(aType);
|
||||
init(aBrowser, aModules) {
|
||||
const initData = this._initData;
|
||||
this._browser = aBrowser;
|
||||
this._settings = initData.settings;
|
||||
this._frozenSettings = Object.freeze(Object.assign({}, this._settings));
|
||||
|
||||
const self = this;
|
||||
this._modules = new Map((function* () {
|
||||
for (const module of aModules) {
|
||||
yield [
|
||||
module.name,
|
||||
new ModuleInfo({
|
||||
manager: self,
|
||||
...module,
|
||||
}),
|
||||
];
|
||||
}
|
||||
})());
|
||||
|
||||
WindowEventDispatcher.registerListener(this, [
|
||||
"GeckoView:EnableModule",
|
||||
"GeckoView:UpdateInitData",
|
||||
"GeckoView:UpdateSettings",
|
||||
]);
|
||||
},
|
||||
|
||||
get window() {
|
||||
return window;
|
||||
},
|
||||
|
||||
get browser() {
|
||||
return this._browser;
|
||||
},
|
||||
|
||||
get messageManager() {
|
||||
return this._browser.messageManager;
|
||||
},
|
||||
|
||||
get eventDispatcher() {
|
||||
return WindowEventDispatcher;
|
||||
},
|
||||
|
||||
get settings() {
|
||||
return this._frozenSettings;
|
||||
},
|
||||
|
||||
forEach(aCallback) {
|
||||
this._modules.forEach(aCallback, this);
|
||||
},
|
||||
|
||||
_updateSettings(aSettings) {
|
||||
Object.assign(this._settings, aSettings);
|
||||
this._frozenSettings = Object.freeze(Object.assign({}, this._settings));
|
||||
|
||||
this.forEach(module => {
|
||||
if (!module.enabled) {
|
||||
return;
|
||||
}
|
||||
module.impl.onSettingsUpdate();
|
||||
this._browser.messageManager.sendAsyncMessage("GeckoView:UpdateSettings",
|
||||
this._settings);
|
||||
});
|
||||
},
|
||||
|
||||
onEvent(aEvent, aData, aCallback) {
|
||||
switch (aEvent) {
|
||||
case "GeckoView:EnableModule": {
|
||||
const module = this._modules.get(aData.module);
|
||||
if (module) {
|
||||
module.enabled = aData.enabled;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "GeckoView:UpdateInitData": {
|
||||
// Replace all sett_onSettingsUpdateings during a transfer.
|
||||
const initData = this._initData;
|
||||
this._updateSettings(initData.settings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "GeckoView:UpdateSettings": {
|
||||
this._updateSettings(aData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* ModuleInfo is the structure used by ModuleManager to represent individual
|
||||
* modules. It is responsible for loading the module JSM file if necessary,
|
||||
* and it acts as the intermediary between ModuleManager and the module
|
||||
* object that extends GeckoViewModule.
|
||||
*/
|
||||
class ModuleInfo {
|
||||
constructor({manager, name, resource}) {
|
||||
this._manager = manager;
|
||||
this._name = name;
|
||||
|
||||
const scope = {};
|
||||
const global = ChromeUtils.import(aResource, scope);
|
||||
const tag = aType.replace("GeckoView", "GeckoView.");
|
||||
const global = ChromeUtils.import(resource, scope);
|
||||
const tag = name.replace("GeckoView", "GeckoView.");
|
||||
GeckoViewUtils.initLogging(tag, global);
|
||||
|
||||
this.modules.set(aType, new scope[aType](
|
||||
aType, window, this.browser, WindowEventDispatcher, ...aArgs
|
||||
));
|
||||
},
|
||||
|
||||
remove: function(aType) {
|
||||
this.modules.delete(aType);
|
||||
},
|
||||
|
||||
forEach: function(aCallback) {
|
||||
this.modules.forEach(aCallback, this);
|
||||
this._impl = new scope[name](this);
|
||||
this._enabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
onInit() {
|
||||
this._impl.onInit();
|
||||
}
|
||||
|
||||
get manager() {
|
||||
return this._manager;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get impl() {
|
||||
return this._impl;
|
||||
}
|
||||
|
||||
get enabled() {
|
||||
return this._enabled;
|
||||
}
|
||||
|
||||
set enabled(aEnabled) {
|
||||
if (aEnabled === this._enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aEnabled) {
|
||||
this._manager.messageManager.sendAsyncMessage("GeckoView:Unregister", {
|
||||
module: this._name,
|
||||
});
|
||||
this._impl.onDisable();
|
||||
}
|
||||
|
||||
this._enabled = aEnabled;
|
||||
|
||||
if (aEnabled) {
|
||||
this._impl.onEnable();
|
||||
this._impl.onSettingsUpdate();
|
||||
this._manager.messageManager.sendAsyncMessage("GeckoView:Register", {
|
||||
module: this._name,
|
||||
settings: this._manager.settings,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createBrowser() {
|
||||
const browser = window.browser = document.createElement("browser");
|
||||
|
@ -61,32 +194,39 @@ function startup() {
|
|||
GeckoViewUtils.initLogging("GeckoView.XUL", window);
|
||||
|
||||
const browser = createBrowser();
|
||||
ModuleManager.init(browser);
|
||||
|
||||
ModuleManager.add("resource://gre/modules/GeckoViewNavigation.jsm",
|
||||
"GeckoViewNavigation");
|
||||
ModuleManager.add("resource://gre/modules/GeckoViewSettings.jsm",
|
||||
"GeckoViewSettings");
|
||||
ModuleManager.add("resource://gre/modules/GeckoViewContent.jsm",
|
||||
"GeckoViewContent");
|
||||
ModuleManager.add("resource://gre/modules/GeckoViewProgress.jsm",
|
||||
"GeckoViewProgress");
|
||||
ModuleManager.add("resource://gre/modules/GeckoViewScroll.jsm",
|
||||
"GeckoViewScroll");
|
||||
ModuleManager.add("resource://gre/modules/GeckoViewTab.jsm",
|
||||
"GeckoViewTab");
|
||||
ModuleManager.add("resource://gre/modules/GeckoViewTrackingProtection.jsm",
|
||||
"GeckoViewTrackingProtection");
|
||||
ModuleManager.add("resource://gre/modules/GeckoViewSelectionAction.jsm",
|
||||
"GeckoViewSelectionAction");
|
||||
ModuleManager.add("resource://gre/modules/GeckoViewAccessibility.jsm",
|
||||
"GeckoViewAccessibility");
|
||||
ModuleManager.init(browser, [{
|
||||
name: "GeckoViewAccessibility",
|
||||
resource: "resource://gre/modules/GeckoViewAccessibility.jsm",
|
||||
}, {
|
||||
name: "GeckoViewContent",
|
||||
resource: "resource://gre/modules/GeckoViewContent.jsm",
|
||||
}, {
|
||||
name: "GeckoViewNavigation",
|
||||
resource: "resource://gre/modules/GeckoViewNavigation.jsm",
|
||||
}, {
|
||||
name: "GeckoViewProgress",
|
||||
resource: "resource://gre/modules/GeckoViewProgress.jsm",
|
||||
}, {
|
||||
name: "GeckoViewScroll",
|
||||
resource: "resource://gre/modules/GeckoViewScroll.jsm",
|
||||
}, {
|
||||
name: "GeckoViewSelectionAction",
|
||||
resource: "resource://gre/modules/GeckoViewSelectionAction.jsm",
|
||||
}, {
|
||||
name: "GeckoViewSettings",
|
||||
resource: "resource://gre/modules/GeckoViewSettings.jsm",
|
||||
}, {
|
||||
name: "GeckoViewTab",
|
||||
resource: "resource://gre/modules/GeckoViewTab.jsm",
|
||||
}, {
|
||||
name: "GeckoViewTrackingProtection",
|
||||
resource: "resource://gre/modules/GeckoViewTrackingProtection.jsm",
|
||||
}]);
|
||||
|
||||
window.document.documentElement.appendChild(browser);
|
||||
|
||||
ModuleManager.forEach(module => {
|
||||
module.onInit();
|
||||
module.onSettingsUpdate();
|
||||
});
|
||||
|
||||
// Move focus to the content window at the end of startup,
|
||||
|
|
|
@ -12,45 +12,43 @@ ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
|
|||
GeckoViewUtils.initLogging("GeckoView.Module", this);
|
||||
|
||||
class GeckoViewModule {
|
||||
constructor(aModuleName, aWindow, aBrowser, aEventDispatcher) {
|
||||
this.isRegistered = false;
|
||||
this.window = aWindow;
|
||||
this.browser = aBrowser;
|
||||
this.eventDispatcher = aEventDispatcher;
|
||||
this.moduleName = aModuleName;
|
||||
constructor(aModuleInfo) {
|
||||
this._info = aModuleInfo;
|
||||
|
||||
this._isContentLoaded = false;
|
||||
this._eventProxy = new EventProxy(this, this.eventDispatcher);
|
||||
|
||||
this.eventDispatcher.registerListener(
|
||||
(aEvent, aData, aCallback) => {
|
||||
this.messageManager.sendAsyncMessage("GeckoView:UpdateSettings",
|
||||
this.settings);
|
||||
this.onSettingsUpdate();
|
||||
}, "GeckoView:UpdateSettings"
|
||||
);
|
||||
|
||||
this.eventDispatcher.registerListener(
|
||||
(aEvent, aData, aCallback) => {
|
||||
if (aData.module == this.moduleName) {
|
||||
this._register();
|
||||
aData.settings = this.settings;
|
||||
this.messageManager.sendAsyncMessage("GeckoView:Register", aData);
|
||||
}
|
||||
}, "GeckoView:Register"
|
||||
);
|
||||
|
||||
this.eventDispatcher.registerListener(
|
||||
(aEvent, aData, aCallback) => {
|
||||
if (aData.module == this.moduleName) {
|
||||
this.messageManager.sendAsyncMessage("GeckoView:Unregister", aData);
|
||||
this._unregister();
|
||||
}
|
||||
}, "GeckoView:Unregister"
|
||||
);
|
||||
|
||||
this.onInitBrowser();
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._info.name;
|
||||
}
|
||||
|
||||
get enabled() {
|
||||
return this._info.enabled;
|
||||
}
|
||||
|
||||
get window() {
|
||||
return this._info.manager.window;
|
||||
}
|
||||
|
||||
get browser() {
|
||||
return this._info.manager.browser;
|
||||
}
|
||||
|
||||
get messageManager() {
|
||||
return this._info.manager.messageManager;
|
||||
}
|
||||
|
||||
get eventDispatcher() {
|
||||
return this._info.manager.eventDispatcher;
|
||||
}
|
||||
|
||||
get settings() {
|
||||
return this._info.manager.settings;
|
||||
}
|
||||
|
||||
// Override to initialize the browser before it is bound to the window.
|
||||
onInitBrowser() {}
|
||||
|
||||
|
@ -66,22 +64,6 @@ class GeckoViewModule {
|
|||
// Override to disable module after clearing the Java delegate.
|
||||
onDisable() {}
|
||||
|
||||
_register() {
|
||||
if (this.isRegistered) {
|
||||
return;
|
||||
}
|
||||
this.onEnable();
|
||||
this.isRegistered = true;
|
||||
}
|
||||
|
||||
_unregister() {
|
||||
if (!this.isRegistered) {
|
||||
return;
|
||||
}
|
||||
this.onDisable();
|
||||
this.isRegistered = false;
|
||||
}
|
||||
|
||||
registerContent(aUri) {
|
||||
if (this._isContentLoaded) {
|
||||
return;
|
||||
|
@ -92,7 +74,7 @@ class GeckoViewModule {
|
|||
let self = this;
|
||||
this.messageManager.addMessageListener("GeckoView:ContentRegistered",
|
||||
function listener(aMsg) {
|
||||
if (aMsg.data.module !== self.moduleName) {
|
||||
if (aMsg.data.module !== self.name) {
|
||||
return;
|
||||
}
|
||||
self.messageManager.removeMessageListener("GeckoView:ContentRegistered",
|
||||
|
@ -110,15 +92,6 @@ class GeckoViewModule {
|
|||
unregisterListener() {
|
||||
this._eventProxy.unregisterListener();
|
||||
}
|
||||
|
||||
get settings() {
|
||||
let view = this.window.arguments[0].QueryInterface(Ci.nsIAndroidView);
|
||||
return Object.freeze(view.settings);
|
||||
}
|
||||
|
||||
get messageManager() {
|
||||
return this.browser.messageManager;
|
||||
}
|
||||
}
|
||||
|
||||
class EventProxy {
|
||||
|
|
|
@ -123,7 +123,7 @@ class GeckoViewNavigation extends GeckoViewModule {
|
|||
debug `handleNewSession: uri=${aUri && aUri.spec}
|
||||
where=${aWhere} flags=${aFlags}`;
|
||||
|
||||
if (!this.isRegistered) {
|
||||
if (!this.enabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче