зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1474143 - Switch earlyformsubmit satchel observer to DOMFormBeforeSubmit listener. r=Felipe
Extend ActorChild for satchel's formSubmitListener in order to listen to the event. Differential Revision: https://phabricator.services.mozilla.com/D16655 --HG-- rename : toolkit/components/satchel/formSubmitListener.js => toolkit/components/satchel/FormSubmitChild.jsm extra : moz-landing-system : lando
This commit is contained in:
Родитель
a3c141f088
Коммит
f325e844bc
|
@ -88,7 +88,6 @@ const whitelist = {
|
|||
"chrome://global/content/process-content.js",
|
||||
"resource:///modules/ContentObservers.js",
|
||||
"data:,ChromeUtils.import('resource://gre/modules/ExtensionProcessScript.jsm')",
|
||||
"chrome://satchel/content/formSubmitListener.js",
|
||||
"resource://devtools/client/jsonview/converter-observer.js",
|
||||
"resource://gre/modules/WebRequestContent.js",
|
||||
"data:,new function() {\n ChromeUtils.import(\"resource://formautofill/FormAutofillContent.jsm\");\n }",
|
||||
|
|
|
@ -47,8 +47,7 @@ FormHistoryStartup.prototype = {
|
|||
Services.obs.addObserver(this, "idle-daily", true);
|
||||
Services.obs.addObserver(this, "formhistory-expire-now", true);
|
||||
|
||||
Services.ppmm.loadProcessScript("chrome://satchel/content/formSubmitListener.js", true);
|
||||
Services.ppmm.addMessageListener("FormHistory:FormSubmitEntries", this);
|
||||
Services.mm.addMessageListener("FormHistory:FormSubmitEntries", this);
|
||||
|
||||
// For each of these messages, we could receive them from content,
|
||||
// or we might receive them from the ppmm if the searchbar is
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["FormSubmitChild"];
|
||||
|
||||
const {ActorChild} = ChromeUtils.import("resource://gre/modules/ActorChild.jsm");
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "CreditCard",
|
||||
"resource://gre/modules/CreditCard.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
class FormSubmitChild extends ActorChild {
|
||||
constructor(dispatcher) {
|
||||
super(dispatcher);
|
||||
|
||||
this.QueryInterface = ChromeUtils.generateQI([
|
||||
Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference,
|
||||
]);
|
||||
|
||||
Services.prefs.addObserver("browser.formfill.", this);
|
||||
this.updatePrefs();
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
super.cleanup();
|
||||
Services.prefs.removeObserver("browser.formfill.", this);
|
||||
}
|
||||
|
||||
updatePrefs() {
|
||||
this.debug = Services.prefs.getBoolPref("browser.formfill.debug");
|
||||
this.enabled = Services.prefs.getBoolPref("browser.formfill.enable");
|
||||
}
|
||||
|
||||
log(message) {
|
||||
if (!this.debug) {
|
||||
return;
|
||||
}
|
||||
dump("satchelFormListener: " + message + "\n");
|
||||
Services.console.logStringMessage("satchelFormListener: " + message);
|
||||
}
|
||||
|
||||
/* ---- nsIObserver interface ---- */
|
||||
|
||||
observe(subject, topic, data) {
|
||||
if (topic == "nsPref:changed") {
|
||||
this.updatePrefs();
|
||||
} else {
|
||||
this.log("Oops! Unexpected notification: " + topic);
|
||||
}
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "DOMFormBeforeSubmit": {
|
||||
this.onDOMFormBeforeSubmit(event);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Error("Unexpected event");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onDOMFormBeforeSubmit(event) {
|
||||
let form = event.target;
|
||||
if (!this.enabled || PrivateBrowsingUtils.isContentWindowPrivate(form.ownerGlobal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.log("Form submit observer notified.");
|
||||
|
||||
if (form.hasAttribute("autocomplete") &&
|
||||
form.getAttribute("autocomplete").toLowerCase() == "off") {
|
||||
return;
|
||||
}
|
||||
|
||||
let entries = [];
|
||||
for (let input of form.elements) {
|
||||
if (ChromeUtils.getClassName(input) !== "HTMLInputElement") {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only use inputs that hold text values (not including type="password")
|
||||
if (!input.mozIsTextField(true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't save fields that were previously type=password such as on sites
|
||||
// that allow the user to toggle password visibility.
|
||||
if (input.hasBeenTypePassword) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Bug 394612: If Login Manager marked this input, don't save it.
|
||||
// The login manager will deal with remembering it.
|
||||
|
||||
// Don't save values when @autocomplete is "off" or has a sensitive field name.
|
||||
let autocompleteInfo = input.getAutocompleteInfo();
|
||||
if (autocompleteInfo && !autocompleteInfo.canAutomaticallyPersist) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let value = input.value.trim();
|
||||
|
||||
// Don't save empty or unchanged values.
|
||||
if (!value || value == input.defaultValue.trim()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't save credit card numbers.
|
||||
if (CreditCard.isValidNumber(value)) {
|
||||
this.log("skipping saving a credit card number");
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = input.name || input.id;
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name == "searchbar-history") {
|
||||
this.log('addEntry for input name "' + name + '" is denied');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Limit stored data to 200 characters.
|
||||
if (name.length > 200 || value.length > 200) {
|
||||
this.log("skipping input that has a name/value too large");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Limit number of fields stored per form.
|
||||
if (entries.length >= 100) {
|
||||
this.log("not saving any more entries for this form.");
|
||||
break;
|
||||
}
|
||||
|
||||
entries.push({ name, value });
|
||||
}
|
||||
|
||||
if (entries.length) {
|
||||
this.log("sending entries to parent process for form " + form.id);
|
||||
this.sendAsyncMessage("FormHistory:FormSubmitEntries", entries);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
/* eslint-env mozilla/frame-script */
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "CreditCard",
|
||||
"resource://gre/modules/CreditCard.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
(function() {
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let satchelFormListener = {
|
||||
QueryInterface: ChromeUtils.generateQI([
|
||||
Ci.nsIFormSubmitObserver,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference,
|
||||
]),
|
||||
|
||||
debug: true,
|
||||
enabled: true,
|
||||
|
||||
init() {
|
||||
Services.obs.addObserver(this, "earlyformsubmit");
|
||||
Services.obs.addObserver(this, "xpcom-shutdown");
|
||||
Services.prefs.addObserver("browser.formfill.", this);
|
||||
this.updatePrefs();
|
||||
},
|
||||
|
||||
updatePrefs() {
|
||||
this.debug = Services.prefs.getBoolPref("browser.formfill.debug");
|
||||
this.enabled = Services.prefs.getBoolPref("browser.formfill.enable");
|
||||
},
|
||||
|
||||
log(message) {
|
||||
if (!this.debug) {
|
||||
return;
|
||||
}
|
||||
dump("satchelFormListener: " + message + "\n");
|
||||
Services.console.logStringMessage("satchelFormListener: " + message);
|
||||
},
|
||||
|
||||
/* ---- nsIObserver interface ---- */
|
||||
|
||||
observe(subject, topic, data) {
|
||||
if (topic == "nsPref:changed") {
|
||||
this.updatePrefs();
|
||||
} else if (topic == "xpcom-shutdown") {
|
||||
Services.obs.removeObserver(this, "earlyformsubmit");
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
Services.prefs.removeObserver("browser.formfill.", this);
|
||||
} else {
|
||||
this.log("Oops! Unexpected notification: " + topic);
|
||||
}
|
||||
},
|
||||
|
||||
/* ---- nsIFormSubmitObserver interfaces ---- */
|
||||
|
||||
notify(form, domWin, actionURI, cancelSubmit) {
|
||||
try {
|
||||
if (!this.enabled || PrivateBrowsingUtils.isContentWindowPrivate(domWin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.log("Form submit observer notified.");
|
||||
|
||||
if (form.hasAttribute("autocomplete") &&
|
||||
form.getAttribute("autocomplete").toLowerCase() == "off") {
|
||||
return;
|
||||
}
|
||||
|
||||
let entries = [];
|
||||
for (let i = 0; i < form.elements.length; i++) {
|
||||
let input = form.elements[i];
|
||||
if (ChromeUtils.getClassName(input) !== "HTMLInputElement") {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only use inputs that hold text values (not including type="password")
|
||||
if (!input.mozIsTextField(true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't save fields that were previously type=password such as on sites
|
||||
// that allow the user to toggle password visibility.
|
||||
if (input.hasBeenTypePassword) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Bug 394612: If Login Manager marked this input, don't save it.
|
||||
// The login manager will deal with remembering it.
|
||||
|
||||
// Don't save values when @autocomplete is "off" or has a sensitive field name.
|
||||
let autocompleteInfo = input.getAutocompleteInfo();
|
||||
if (autocompleteInfo && !autocompleteInfo.canAutomaticallyPersist) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let value = input.value.trim();
|
||||
|
||||
// Don't save empty or unchanged values.
|
||||
if (!value || value == input.defaultValue.trim()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't save credit card numbers.
|
||||
if (CreditCard.isValidNumber(value)) {
|
||||
this.log("skipping saving a credit card number");
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = input.name || input.id;
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name == "searchbar-history") {
|
||||
this.log('addEntry for input name "' + name + '" is denied');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Limit stored data to 200 characters.
|
||||
if (name.length > 200 || value.length > 200) {
|
||||
this.log("skipping input that has a name/value too large");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Limit number of fields stored per form.
|
||||
if (entries.length >= 100) {
|
||||
this.log("not saving any more entries for this form.");
|
||||
break;
|
||||
}
|
||||
|
||||
entries.push({ name, value });
|
||||
}
|
||||
|
||||
if (entries.length) {
|
||||
this.log("sending entries to parent process for form " + form.id);
|
||||
sendAsyncMessage("FormHistory:FormSubmitEntries", entries);
|
||||
}
|
||||
} catch (e) {
|
||||
this.log("notify failed: " + e);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
satchelFormListener.init();
|
||||
})();
|
|
@ -1,7 +0,0 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# 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/.
|
||||
|
||||
toolkit.jar:
|
||||
% content satchel %content/satchel/
|
||||
content/satchel/formSubmitListener.js
|
|
@ -40,6 +40,8 @@ XPCOM_MANIFESTS += [
|
|||
'components.conf',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
FINAL_TARGET_FILES.actors += [
|
||||
'FormSubmitChild.jsm',
|
||||
]
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
|
|
@ -31,10 +31,12 @@ function runTests() {
|
|||
var target = document.getElementById("input");
|
||||
|
||||
// Register a word to the form history.
|
||||
let chromeScript = SpecialPowers.loadChromeScript(function addEntry() {
|
||||
let {FormHistory} = ChromeUtils.import("resource://gre/modules/FormHistory.jsm");
|
||||
FormHistory.update({ op: "add", fieldname: "test", value: "Mozilla" });
|
||||
});
|
||||
chromeScript.destroy();
|
||||
target.focus();
|
||||
target.value = "Mozilla";
|
||||
synthesizeKey("KEY_Enter");
|
||||
target.value = "";
|
||||
|
||||
new nsDoTestsForAutoCompleteWithComposition(
|
||||
"Testing on HTML input (asynchronously search)",
|
||||
|
|
|
@ -23,9 +23,13 @@ SimpleTest.waitForExplicitFinish();
|
|||
|
||||
async function registerWord(aTarget, aAutoCompleteController) {
|
||||
// Register a word to the form history.
|
||||
let chromeScript = SpecialPowers.loadChromeScript(function addEntry() {
|
||||
let {FormHistory} = ChromeUtils.import("resource://gre/modules/FormHistory.jsm");
|
||||
FormHistory.update({ op: "add", fieldname: "test", value: "Mozilla" });
|
||||
});
|
||||
aTarget.focus();
|
||||
aTarget.value = "Mozilla";
|
||||
synthesizeKey("KEY_Enter");
|
||||
|
||||
await waitForCondition(() => {
|
||||
if (aAutoCompleteController.searchStatus == aAutoCompleteController.STATUS_NONE ||
|
||||
aAutoCompleteController.searchStatus == aAutoCompleteController.STATUS_COMPLETE_NO_MATCH) {
|
||||
|
@ -33,6 +37,7 @@ async function registerWord(aTarget, aAutoCompleteController) {
|
|||
}
|
||||
return aAutoCompleteController.matchCount > 0;
|
||||
});
|
||||
chromeScript.destroy();
|
||||
aTarget.value = "";
|
||||
synthesizeKey("KEY_Escape");
|
||||
}
|
||||
|
|
|
@ -186,6 +186,16 @@ let ACTORS = {
|
|||
},
|
||||
},
|
||||
|
||||
FormSubmit: {
|
||||
child: {
|
||||
module: "resource://gre/actors/FormSubmitChild.jsm",
|
||||
allFrames: true,
|
||||
events: {
|
||||
"DOMFormBeforeSubmit": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
KeyPressEventModelChecker: {
|
||||
child: {
|
||||
module: "resource://gre/actors/KeyPressEventModelCheckerChild.jsm",
|
||||
|
|
Загрузка…
Ссылка в новой задаче