Bug 1367077 - 3. Move form fill event listeners out of browser.js; r=sebastian

Move the form fill event listeners out of browser.js and into
BrowserCLH.js, and update them to support chrome windows, so we can
handle form fill events for Fennec, custom tabs, and PWAs.

MozReview-Commit-ID: Fb5gWmGvxfE
This commit is contained in:
Jim Chen 2017-09-14 17:50:57 -04:00
parent 2ea84d0359
commit 2da0bfd1b8
3 changed files with 72 additions and 31 deletions

View File

@ -46,12 +46,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
XPCOMUtils.defineLazyModuleGetter(this, "UserAgentOverrides",
"resource://gre/modules/UserAgentOverrides.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerContent",
"resource://gre/modules/LoginManagerContent.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerParent",
"resource://gre/modules/LoginManagerParent.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
@ -556,9 +550,6 @@ var BrowserApp = {
// Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
InitLater(() => SafeBrowsing.init(), window, "SafeBrowsing");
InitLater(() => Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager));
InitLater(() => LoginManagerParent.init(), window, "LoginManagerParent");
}, {once: true});
// Pass caret StateChanged events to ActionBarHandler.
@ -3659,7 +3650,6 @@ Tab.prototype = {
this.browser.addEventListener("DOMContentLoaded", this, true);
this.browser.addEventListener("DOMFormHasPassword", this, true);
this.browser.addEventListener("DOMInputPasswordAdded", this, true);
this.browser.addEventListener("DOMLinkAdded", this, true);
this.browser.addEventListener("DOMLinkChanged", this, true);
this.browser.addEventListener("DOMMetaAdded", this);
@ -3668,8 +3658,6 @@ Tab.prototype = {
this.browser.addEventListener("DOMAudioPlaybackStopped", this, true);
this.browser.addEventListener("DOMWindowClose", this, true);
this.browser.addEventListener("DOMWillOpenModalDialog", this, true);
this.browser.addEventListener("DOMAutoComplete", this, true);
this.browser.addEventListener("blur", this, true);
this.browser.addEventListener("pageshow", this, true);
this.browser.addEventListener("MozApplicationManifest", this, true);
this.browser.addEventListener("TabPreZombify", this, true);
@ -3774,7 +3762,6 @@ Tab.prototype = {
this.browser.removeEventListener("DOMContentLoaded", this, true);
this.browser.removeEventListener("DOMFormHasPassword", this, true);
this.browser.removeEventListener("DOMInputPasswordAdded", this, true);
this.browser.removeEventListener("DOMLinkAdded", this, true);
this.browser.removeEventListener("DOMLinkChanged", this, true);
this.browser.removeEventListener("DOMMetaAdded", this);
@ -3783,8 +3770,6 @@ Tab.prototype = {
this.browser.removeEventListener("DOMAudioPlaybackStopped", this, true);
this.browser.removeEventListener("DOMWindowClose", this, true);
this.browser.removeEventListener("DOMWillOpenModalDialog", this, true);
this.browser.removeEventListener("DOMAutoComplete", this, true);
this.browser.removeEventListener("blur", this, true);
this.browser.removeEventListener("pageshow", this, true);
this.browser.removeEventListener("MozApplicationManifest", this, true);
this.browser.removeEventListener("TabPreZombify", this, true);
@ -4144,9 +4129,6 @@ Tab.prototype = {
}
case "DOMFormHasPassword": {
LoginManagerContent.onDOMFormHasPassword(aEvent,
this.browser.contentWindow);
// Send logins for this hostname to Java.
let hostname = aEvent.target.baseURIObject.prePath;
let foundLogins = Services.logins.findLogins({}, hostname, "", "");
@ -4162,11 +4144,6 @@ Tab.prototype = {
break;
}
case "DOMInputPasswordAdded": {
LoginManagerContent.onDOMInputPasswordAdded(aEvent,
this.browser.contentWindow);
}
case "DOMMetaAdded":
let target = aEvent.originalTarget;
let browser = BrowserApp.getBrowserForDocument(target.ownerDocument);
@ -4296,12 +4273,6 @@ Tab.prototype = {
break;
}
case "DOMAutoComplete":
case "blur": {
LoginManagerContent.onUsernameInput(aEvent);
break;
}
case "VideoBindingAttached": {
CastingApps.handleVideoBindingAttached(this, aEvent);
break;
@ -4327,8 +4298,6 @@ Tab.prototype = {
}
case "pageshow": {
LoginManagerContent.onPageShow(aEvent, this.browser.contentWindow);
// The rest of this only handles pageshow for the top-level document.
if (aEvent.originalTarget.defaultView != this.browser.contentWindow)
return;

View File

@ -8,6 +8,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetters(this, {
AppConstants: "resource://gre/modules/AppConstants.jsm",
DelayedInit: "resource://gre/modules/DelayedInit.jsm",
GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm",
Services: "resource://gre/modules/Services.jsm",
});
@ -74,6 +75,33 @@ BrowserCLH.prototype = {
GeckoViewUtils.addLazyGetter(this, "InputWidgetHelper", {
script: "chrome://browser/content/InputWidgetHelper.js",
});
GeckoViewUtils.addLazyGetter(this, "LoginManagerParent", {
module: "resource://gre/modules/LoginManagerParent.jsm",
mm: [
// PLEASE KEEP THIS LIST IN SYNC WITH THE DESKTOP LIST IN nsBrowserGlue.js
"RemoteLogins:findLogins",
"RemoteLogins:findRecipes",
"RemoteLogins:onFormSubmit",
"RemoteLogins:autoCompleteLogins",
"RemoteLogins:removeLogin",
"RemoteLogins:insecureLoginFormPresent",
// PLEASE KEEP THIS LIST IN SYNC WITH THE DESKTOP LIST IN nsBrowserGlue.js
],
});
GeckoViewUtils.addLazyGetter(this, "LoginManagerContent", {
module: "resource://gre/modules/LoginManagerContent.jsm",
});
// Once the first chrome window is loaded, schedule a list of startup
// tasks to be performed on idle.
GeckoViewUtils.addLazyGetter(this, "DelayedStartup", {
observers: ["chrome-document-loaded"],
once: true,
handler: _ => DelayedInit.scheduleList([
_ => Services.logins,
], 10000 /* 10 seconds maximum wait. */),
});
break;
}
@ -92,11 +120,49 @@ BrowserCLH.prototype = {
mozSystemGroup: true,
},
});
this._initLoginManagerEvents(win);
break;
}
}
},
_initLoginManagerEvents: function(aWindow) {
if (Services.prefs.getBoolPref("reftest.remote", false)) {
// XXX known incompatibility between reftest harness and form-fill.
return;
}
let options = {
capture: true,
mozSystemGroup: true,
};
aWindow.addEventListener("DOMFormHasPassword", event => {
this.LoginManagerContent.onDOMFormHasPassword(event, event.target.ownerGlobal.top);
}, options);
aWindow.addEventListener("DOMInputPasswordAdded", event => {
this.LoginManagerContent.onDOMInputPasswordAdded(event, event.target.ownerGlobal.top);
}, options);
aWindow.addEventListener("DOMAutoComplete", event => {
this.LoginManagerContent.onUsernameInput(event);
}, options);
aWindow.addEventListener("blur", event => {
if (event.target instanceof Ci.nsIDOMHTMLInputElement) {
this.LoginManagerContent.onUsernameInput(event);
}
}, options);
aWindow.addEventListener("pageshow", event => {
if (event.target instanceof Ci.nsIDOMHTMLDocument) {
this.LoginManagerContent.onPageShow(event, event.target.defaultView.top);
}
}, options);
},
// QI
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),

View File

@ -52,6 +52,12 @@ var DelayedInit = {
schedule: function(fn, object, name, maxWait) {
return Impl.scheduleInit(fn, object, name, maxWait);
},
scheduleList: function(fns, maxWait) {
for (let fn of fns) {
Impl.scheduleInit(fn, null, null, maxWait);
}
},
};
// Maximum duration for each idling period. Pending inits are run until this