Bug 913280 - Electrolysis: Refactor RemoteWebProgress to use a Manager that owns the toplevel and all the sublevel WebProgress objects. r=felipe

This commit is contained in:
Tom Schuster 2013-09-06 13:10:11 -04:00
parent c23a49081b
commit 2f28506505
3 changed files with 104 additions and 89 deletions

View File

@ -38,7 +38,7 @@
<![CDATA[
if (!this._remoteWebNavigation) {
let jsm = "resource://gre/modules/RemoteWebNavigation.jsm";
let RemoteWebNavigation = Components.utils.import(jsm, {}).RemoteWebNavigation;
let RemoteWebNavigation = Cu.import(jsm, {}).RemoteWebNavigation;
this._remoteWebNavigation = new RemoteWebNavigation(this);
}
return this._remoteWebNavigation;
@ -53,8 +53,9 @@
<![CDATA[
if (!this._remoteWebProgress) {
let jsm = "resource://gre/modules/RemoteWebProgress.jsm";
let RemoteWebProgress = Components.utils.import(jsm, {}).RemoteWebProgress;
this._remoteWebProgress = new RemoteWebProgress(this);
let RemoteWebProgressManager = Cu.import(jsm, {}).RemoteWebProgressManager;
this._remoteWebProgress = new RemoteWebProgressManager(this)
.topLevelWebProgress;
}
return this._remoteWebProgress;
]]>
@ -107,8 +108,6 @@
this.messageManager.loadFrameScript("chrome://global/content/select-child.js", true);
}
this.webProgress._init();
let jsm = "resource://gre/modules/RemoteController.jsm";
let RemoteController = Components.utils.import(jsm, {}).RemoteController;
this._controller = new RemoteController(this);

View File

@ -13,36 +13,22 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function RemoteSecurityUI()
{
this._state = 0;
this._SSLStatus = null;
this._state = 0;
}
RemoteSecurityUI.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsISSLStatusProvider, Ci.nsISecureBrowserUI]),
// nsISSLStatusProvider
get SSLStatus() { return this._SSLStatus; },
// nsISecureBrowserUI
get state() { return this._state; },
get tooltipText() { return ""; },
// nsISSLStatusProvider
get SSLStatus() { return this._SSLStatus; },
_update: function (state, status) {
let deserialized = null;
if (status) {
let helper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Components.interfaces.nsISerializationHelper);
deserialized = helper.deserializeObject(status)
deserialized.QueryInterface(Ci.nsISSLStatus);
}
// We must check the Extended Validation (EV) state here, on the chrome
// process, because NSS is needed for that determination.
if (deserialized && deserialized.isExtendedValidation)
state |= Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL;
this._state = state;
this._SSLStatus = deserialized;
_update: function (aStatus, aState) {
this._SSLStatus = aStatus;
this._state = aState;
}
};

View File

@ -3,7 +3,7 @@
// 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/.
this.EXPORTED_SYMBOLS = ["RemoteWebProgress"];
this.EXPORTED_SYMBOLS = ["RemoteWebProgressManager"];
const Ci = Components.interfaces;
const Cc = Components.classes;
@ -28,14 +28,13 @@ RemoteWebProgressRequest.prototype = {
get URI() { return this.uri.clone(); }
};
function RemoteWebProgress(browser)
{
this._browser = browser;
function RemoteWebProgress(aManager, aIsTopLevel) {
this._manager = aManager;
this._isLoadingDocument = false;
this._DOMWindow = null;
this._isTopLevel = null;
this._isTopLevel = aIsTopLevel;
this._loadType = 0;
this._progressListeners = [];
}
RemoteWebProgress.prototype = {
@ -51,101 +50,132 @@ RemoteWebProgress.prototype = {
NOTIFY_REFRESH: 0x00000100,
NOTIFY_ALL: 0x000001ff,
_init: function WP_Init() {
this._browser.messageManager.addMessageListener("Content:StateChange", this);
this._browser.messageManager.addMessageListener("Content:LocationChange", this);
this._browser.messageManager.addMessageListener("Content:SecurityChange", this);
this._browser.messageManager.addMessageListener("Content:StatusChange", this);
},
_destroy: function WP_Destroy() {
this._browser = null;
},
get isLoadingDocument() { return this._isLoadingDocument },
get DOMWindow() { return this._DOMWindow; },
get DOMWindowID() { return 0; },
get isTopLevel() {
// When this object is accessed directly, it's usually obtained
// through browser.webProgress and thus represents the top-level
// document.
// However, during message handling it temporarily represents
// the webProgress that generated the notification, which may or
// may not be a toplevel frame.
return this._isTopLevel === null ? true : this._isTopLevel;
},
get isTopLevel() { return this._isTopLevel },
get loadType() { return this._loadType; },
addProgressListener: function WP_AddProgressListener (aListener) {
addProgressListener: function (aListener) {
this._manager.addProgressListener(aListener);
},
removeProgressListener: function (aListener) {
this._manager.removeProgressListener(aListener);
}
};
function RemoteWebProgressManager (aBrowser) {
this._browser = aBrowser;
this._topLevelWebProgress = new RemoteWebProgress(this, true);
this._progressListeners = [];
this._browser.messageManager.addMessageListener("Content:StateChange", this);
this._browser.messageManager.addMessageListener("Content:LocationChange", this);
this._browser.messageManager.addMessageListener("Content:SecurityChange", this);
this._browser.messageManager.addMessageListener("Content:StatusChange", this);
}
RemoteWebProgressManager.prototype = {
get topLevelWebProgress() {
return this._topLevelWebProgress;
},
addProgressListener: function (aListener) {
let listener = aListener.QueryInterface(Ci.nsIWebProgressListener);
this._progressListeners.push(listener);
},
removeProgressListener: function WP_RemoveProgressListener (aListener) {
removeProgressListener: function (aListener) {
this._progressListeners =
this._progressListeners.filter(function (l) l != aListener);
this._progressListeners.filter(l => l != aListener);
},
_uriSpec: function (spec) {
if (!spec)
return null;
return new RemoteWebProgressRequest(spec);
_fixSSLStatusAndState: function (aStatus, aState) {
let deserialized = null;
if (aStatus) {
let helper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Components.interfaces.nsISerializationHelper);
deserialized = helper.deserializeObject(aStatus)
deserialized.QueryInterface(Ci.nsISSLStatus);
}
// We must check the Extended Validation (EV) state here, on the chrome
// process, because NSS is needed for that determination.
if (deserialized && deserialized.isExtendedValidation)
aState |= Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL;
return [deserialized, aState];
},
receiveMessage: function WP_ReceiveMessage(aMessage) {
this._isLoadingDocument = aMessage.json.isLoadingDocument;
this._DOMWindow = aMessage.objects.DOMWindow;
this._isTopLevel = aMessage.json.isTopLevel;
this._loadType = aMessage.json.loadType;
receiveMessage: function (aMessage) {
let json = aMessage.json;
let objects = aMessage.objects;
this._browser._contentWindow = aMessage.objects.contentWindow;
// The top-level WebProgress is always the same, but because we don't
// really have a concept of subframes/content we always creat a new object
// for those.
let webProgress = json.isTopLevel ? this._topLevelWebProgress
: new RemoteWebProgress(this, false);
// The WebProgressRequest object however is always dynamic.
let request = json.requestURI ? new RemoteWebProgressRequest(json.requestURI)
: null;
// Update the actual WebProgress fields.
webProgress._isLoadingDocument = json.isLoadingDocument;
webProgress._DOMWindow = objects.DOMWindow;
webProgress._loadType = json.loadType;
if (json.isTopLevel)
this._browser._contentWindow = objects.contentWindow;
let req = this._uriSpec(aMessage.json.requestURI);
switch (aMessage.name) {
case "Content:StateChange":
for each (let p in this._progressListeners) {
p.onStateChange(this, req, aMessage.json.stateFlags, aMessage.json.status);
for (let p of this._progressListeners) {
p.onStateChange(webProgress, request, json.stateFlags, json.status);
}
break;
case "Content:LocationChange":
let location = newURI(aMessage.json.location);
let location = newURI(json.location);
if (aMessage.json.isTopLevel) {
if (json.isTopLevel) {
this._browser.webNavigation._currentURI = location;
this._browser.webNavigation.canGoBack = aMessage.json.canGoBack;
this._browser.webNavigation.canGoForward = aMessage.json.canGoForward;
this._browser._characterSet = aMessage.json.charset;
this._browser._documentURI = newURI(aMessage.json.documentURI);
this._browser.webNavigation.canGoBack = json.canGoBack;
this._browser.webNavigation.canGoForward = json.canGoForward;
this._browser._characterSet = json.charset;
this._browser._documentURI = newURI(json.documentURI);
this._browser._imageDocument = null;
}
for each (let p in this._progressListeners) {
p.onLocationChange(this, req, location);
for (let p of this._progressListeners) {
p.onLocationChange(webProgress, request, location);
}
break;
case "Content:SecurityChange":
// Invoking this getter triggers the generation of the underlying object,
// which we need to access with ._securityUI, because .securityUI returns
// a wrapper that makes _update inaccessible.
void this._browser.securityUI;
this._browser._securityUI._update(aMessage.json.state, aMessage.json.status);
let [status, state] = this._fixSSLStatusAndState(json.status, json.state);
// The state passed might not be correct due to checks performed
// on the chrome side. _update fixes that.
for each (let p in this._progressListeners) {
p.onSecurityChange(this, req, this._browser.securityUI.state);
if (json.isTopLevel) {
// Invoking this getter triggers the generation of the underlying object,
// which we need to access with ._securityUI, because .securityUI returns
// a wrapper that makes _update inaccessible.
void this._browser.securityUI;
this._browser._securityUI._update(status, state);
}
for (let p of this._progressListeners) {
p.onSecurityChange(webProgress, request, state);
}
break;
case "Content:StatusChange":
for each (let p in this._progressListeners) {
p.onStatusChange(this, req, aMessage.json.status, aMessage.json.message);
for (let p of this._progressListeners) {
p.onStatusChange(webProgress, request, json.status, json.message);
}
break;
}
this._isTopLevel = null;
}
};