mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Merge inbound to mozilla-central. a=merge
This commit is contained in:
commit
3e61ab4489
2
CLOBBER
2
CLOBBER
@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1433158 - libvpx library update requires a clobber
|
||||
Bug 1346211 - Modifying ICU data file requires a clobber.
|
||||
|
@ -239,7 +239,7 @@ ROLE(TABLE,
|
||||
ROLE_SYSTEM_TABLE,
|
||||
ROLE_SYSTEM_TABLE,
|
||||
"android.widget.GridView",
|
||||
eNoNameRule)
|
||||
eNameFromSubtreeIfReqRule)
|
||||
|
||||
ROLE(COLUMNHEADER,
|
||||
"columnheader",
|
||||
|
@ -37,6 +37,11 @@
|
||||
// more own inner text, separated by 1 space.
|
||||
testName("chkbx", "Flash the screen 5 times");
|
||||
|
||||
// Example 4 from section 4.3.1 under 2.F.
|
||||
// Name from content should include all the child nodes, including
|
||||
// table cells.
|
||||
testName("input_with_html_label", "foo bar baz");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -73,5 +78,14 @@
|
||||
<!-- Label from combined text and subtree -->
|
||||
<div id="chkbx" role="checkbox" aria-checked="false">Flash the screen
|
||||
<span role="textbox" aria-multiline="false"> 5 </span> times</div>
|
||||
|
||||
<!-- Label with name from content should include table -->
|
||||
<input id="input_with_html_label" />
|
||||
<label for="input_with_html_label" id="label">
|
||||
<div>foo</div>
|
||||
<table><tr><td>bar</td></tr></table>
|
||||
<div>baz</div>
|
||||
</label>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,55 +1,28 @@
|
||||
/* 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";
|
||||
|
||||
/*
|
||||
* Handles the validation callback from nsIFormFillController and
|
||||
* the display of the help panel on invalid elements.
|
||||
*
|
||||
* FormSubmitObserver implements the nsIFormSubmitObserver interface
|
||||
* to get notifications about invalid forms. See HTMLFormElement
|
||||
* for details.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
var EXPORTED_SYMBOLS = ["FormSubmitChild"];
|
||||
|
||||
var EXPORTED_SYMBOLS = [ "FormSubmitObserver" ];
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/ActorChild.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/BrowserUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function FormSubmitObserver(aWindow, aTabChildGlobal) {
|
||||
this.init(aWindow, aTabChildGlobal);
|
||||
}
|
||||
class FormSubmitChild extends ActorChild {
|
||||
constructor(mm) {
|
||||
super(mm);
|
||||
|
||||
FormSubmitObserver.prototype =
|
||||
{
|
||||
_validationMessage: "",
|
||||
_content: null,
|
||||
_element: null,
|
||||
|
||||
/*
|
||||
* Public apis
|
||||
*/
|
||||
|
||||
init(aWindow, aTabChildGlobal) {
|
||||
this._content = aWindow;
|
||||
this._tab = aTabChildGlobal;
|
||||
this._mm =
|
||||
this._content.docShell.messageManager;
|
||||
|
||||
this._tab.addEventListener("pageshow", this);
|
||||
this._tab.addEventListener("unload", this);
|
||||
},
|
||||
|
||||
uninit() {
|
||||
this._content.removeEventListener("pageshow", this);
|
||||
this._content.removeEventListener("unload", this);
|
||||
this._mm = null;
|
||||
this._validationMessage = "";
|
||||
this._element = null;
|
||||
this._content = null;
|
||||
this._tab = null;
|
||||
},
|
||||
|
||||
this.mm.addEventListener("pageshow", this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Events
|
||||
@ -57,14 +30,15 @@ FormSubmitObserver.prototype =
|
||||
|
||||
handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "MozInvalidForm":
|
||||
aEvent.preventDefault();
|
||||
this.notifyInvalidSubmit(aEvent.target, aEvent.detail);
|
||||
break;
|
||||
case "pageshow":
|
||||
if (this._isRootDocumentEvent(aEvent)) {
|
||||
this._hidePopup();
|
||||
}
|
||||
break;
|
||||
case "unload":
|
||||
this.uninit();
|
||||
break;
|
||||
case "input":
|
||||
this._onInput(aEvent);
|
||||
break;
|
||||
@ -72,26 +46,18 @@ FormSubmitObserver.prototype =
|
||||
this._onBlur(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/*
|
||||
* nsIFormSubmitObserver
|
||||
*/
|
||||
|
||||
notifyInvalidSubmit(aFormElement, aInvalidElements) {
|
||||
// We are going to handle invalid form submission attempt by focusing the
|
||||
// first invalid element and show the corresponding validation message in a
|
||||
// panel attached to the element.
|
||||
if (!aInvalidElements.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Show a validation message on the first focusable element.
|
||||
for (let i = 0; i < aInvalidElements.length; i++) {
|
||||
for (let element of aInvalidElements) {
|
||||
// Insure that this is the FormSubmitObserver associated with the
|
||||
// element / window this notification is about.
|
||||
let element = aInvalidElements.queryElementAt(i, Ci.nsISupports);
|
||||
if (this._content != element.ownerGlobal.top.document.defaultView) {
|
||||
if (this.content != element.ownerGlobal.top.document.defaultView) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -128,7 +94,7 @@ FormSubmitObserver.prototype =
|
||||
this._showPopup(element);
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal
|
||||
@ -154,7 +120,7 @@ FormSubmitObserver.prototype =
|
||||
this._validationMessage = element.validationMessage;
|
||||
this._showPopup(element);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/*
|
||||
* Blur event handler in which we disconnect from the form element and
|
||||
@ -165,7 +131,7 @@ FormSubmitObserver.prototype =
|
||||
aEvent.originalTarget.removeEventListener("blur", this);
|
||||
this._element = null;
|
||||
this._hidePopup();
|
||||
},
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the show popup message to chrome with appropriate position
|
||||
@ -197,25 +163,23 @@ FormSubmitObserver.prototype =
|
||||
} else {
|
||||
offset = parseInt(style.paddingLeft) + parseInt(style.borderLeftWidth);
|
||||
}
|
||||
let zoomFactor = this._content.windowUtils.fullZoom;
|
||||
let zoomFactor = this.content.windowUtils.fullZoom;
|
||||
panelData.offset = Math.round(offset * zoomFactor);
|
||||
panelData.position = "after_start";
|
||||
}
|
||||
this._mm.sendAsyncMessage("FormValidation:ShowPopup", panelData);
|
||||
},
|
||||
this.mm.sendAsyncMessage("FormValidation:ShowPopup", panelData);
|
||||
}
|
||||
|
||||
_hidePopup() {
|
||||
this._mm.sendAsyncMessage("FormValidation:HidePopup", {});
|
||||
},
|
||||
this.mm.sendAsyncMessage("FormValidation:HidePopup", {});
|
||||
}
|
||||
|
||||
_isRootDocumentEvent(aEvent) {
|
||||
if (this._content == null) {
|
||||
if (this.content == null) {
|
||||
return true;
|
||||
}
|
||||
let target = aEvent.originalTarget;
|
||||
return (target == this._content.document ||
|
||||
(target.ownerDocument && target.ownerDocument == this._content.document));
|
||||
},
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIFormSubmitObserver, Ci.nsISupportsWeakReference])
|
||||
};
|
||||
return (target == this.content.document ||
|
||||
(target.ownerDocument && target.ownerDocument == this.content.document));
|
||||
}
|
||||
}
|
72
browser/actors/LightweightThemeChild.jsm
Normal file
72
browser/actors/LightweightThemeChild.jsm
Normal file
@ -0,0 +1,72 @@
|
||||
/* 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 = ["LightweightThemeChild"];
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/ActorChild.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
/**
|
||||
* LightweightThemeChild forwards theme data to in-content pages.
|
||||
*/
|
||||
class LightweightThemeChild extends ActorChild {
|
||||
constructor(mm) {
|
||||
super(mm);
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the actor for the current page, sending it any existing
|
||||
* theme data, and adding shared data change listeners so it can
|
||||
* notify the page of future updates.
|
||||
*
|
||||
* This is called when the actor is constructed, and any time
|
||||
* ActorManagerChild receives a pageshow event for the page we're
|
||||
* attached to.
|
||||
*/
|
||||
init() {
|
||||
Services.cpmm.sharedData.addEventListener("change", this);
|
||||
this.update(this.mm.chromeOuterWindowID, this.content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up any global listeners registered by the actor.
|
||||
*
|
||||
* This is called by ActorManagerChild any time it receives a pagehide
|
||||
* event for the page we're attached to.
|
||||
*/
|
||||
cleanup() {
|
||||
Services.cpmm.sharedData.removeEventListener("change", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles "change" events on the child sharedData map, and notifies
|
||||
* our content page if its theme data was among the changed keys.
|
||||
*/
|
||||
handleEvent(event) {
|
||||
if (event.type === "change") {
|
||||
if (event.changedKeys.includes(`theme/${this.mm.chromeOuterWindowID}`)) {
|
||||
this.update(this.mm.chromeOuterWindowID, this.content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward the theme data to the page.
|
||||
* @param {Object} outerWindowID The outerWindowID the parent process window has.
|
||||
* @param {Object} content The receiving global
|
||||
*/
|
||||
update(outerWindowID, content) {
|
||||
const event = Cu.cloneInto({
|
||||
detail: {
|
||||
data: Services.cpmm.sharedData.get(`theme/${outerWindowID}`)
|
||||
},
|
||||
}, content);
|
||||
content.dispatchEvent(new content.CustomEvent("LightweightTheme:Set",
|
||||
event));
|
||||
}
|
||||
}
|
@ -42,8 +42,8 @@ class PluginChild extends ActorChild {
|
||||
// Cache of plugin crash information sent from the parent
|
||||
this.pluginCrashData = new Map();
|
||||
|
||||
this.mm.addEventListener("pagehide", this, true);
|
||||
this.mm.addEventListener("pageshow", this, true);
|
||||
this.mm.addEventListener("pagehide", this, {capture: true, mozSystemGroup: true});
|
||||
this.mm.addEventListener("pageshow", this, {capture: true, mozSystemGroup: true});
|
||||
}
|
||||
|
||||
receiveMessage(msg) {
|
||||
|
@ -7,6 +7,9 @@
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "General")
|
||||
|
||||
with Files("LightweightThemeChild.jsm"):
|
||||
BUG_COMPONENT = ("WebExtensions", "Themes")
|
||||
|
||||
with Files("LightWeightThemeInstallChild.jsm"):
|
||||
BUG_COMPONENT = ("Firefox", "Theme")
|
||||
|
||||
@ -30,6 +33,8 @@ FINAL_TARGET_FILES.actors += [
|
||||
'ContentSearchChild.jsm',
|
||||
'ContextMenuChild.jsm',
|
||||
'DOMFullscreenChild.jsm',
|
||||
'FormSubmitChild.jsm',
|
||||
'LightweightThemeChild.jsm',
|
||||
'LightWeightThemeInstallChild.jsm',
|
||||
'LinkHandlerChild.jsm',
|
||||
'NetErrorChild.jsm',
|
||||
|
@ -10,7 +10,6 @@
|
||||
/* eslint no-unused-vars: ["error", {args: "none"}] */
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// TabChildGlobal
|
||||
var global = this;
|
||||
@ -19,7 +18,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
ContentMetaHandler: "resource:///modules/ContentMetaHandler.jsm",
|
||||
LoginFormFactory: "resource://gre/modules/LoginManagerContent.jsm",
|
||||
InsecurePasswordUtils: "resource://gre/modules/InsecurePasswordUtils.jsm",
|
||||
FormSubmitObserver: "resource:///modules/FormSubmitObserver.jsm",
|
||||
ContextMenuChild: "resource:///actors/ContextMenuChild.jsm",
|
||||
});
|
||||
|
||||
@ -30,15 +28,6 @@ XPCOMUtils.defineLazyGetter(this, "LoginManagerContent", () => {
|
||||
return tmp.LoginManagerContent;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyProxy(this, "formSubmitObserver", () => {
|
||||
return new FormSubmitObserver(content, this);
|
||||
}, {
|
||||
// stub QI
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIFormSubmitObserver, Ci.nsISupportsWeakReference])
|
||||
});
|
||||
|
||||
Services.obs.addObserver(formSubmitObserver, "invalidformsubmit", true);
|
||||
|
||||
// NOTE: Much of this logic is duplicated in BrowserCLH.js for Android.
|
||||
addMessageListener("RemoteLogins:fillForm", function(message) {
|
||||
// intercept if ContextMenu.jsm had sent a plain object for remote targets
|
||||
|
@ -22,22 +22,6 @@ ActorManagerChild.attach(this, "browsers");
|
||||
// TabChildGlobal
|
||||
var global = this;
|
||||
|
||||
XPCOMUtils.defineLazyProxy(this, "LightweightThemeChildHelper",
|
||||
"resource:///modules/LightweightThemeChildHelper.jsm");
|
||||
|
||||
let themeablePagesWhitelist = new Set([
|
||||
"about:home",
|
||||
"about:newtab",
|
||||
"about:welcome",
|
||||
]);
|
||||
|
||||
addEventListener("pageshow", function({ originalTarget }) {
|
||||
if (originalTarget.defaultView == content && themeablePagesWhitelist.has(content.document.documentURI)) {
|
||||
LightweightThemeChildHelper.listen(themeablePagesWhitelist);
|
||||
LightweightThemeChildHelper.update(chromeOuterWindowID, content);
|
||||
}
|
||||
}, false, true);
|
||||
|
||||
// Keep a reference to the translation content handler to avoid it it being GC'ed.
|
||||
var trHandler = null;
|
||||
if (Services.prefs.getBoolPref("browser.translation.detectLanguage")) {
|
||||
|
@ -39,7 +39,7 @@ support-files =
|
||||
file_bug1045809_1.html
|
||||
file_bug1045809_2.html
|
||||
[browser_csp_block_all_mixedcontent.js]
|
||||
skip-if = (verify && debug && (os == 'mac'))
|
||||
skip-if = (verify && debug && (os == 'mac')) || (os == 'linux') || (os == 'mac') # Bug 1438402
|
||||
tags = mcb
|
||||
support-files =
|
||||
file_csp_block_all_mixedcontent.html
|
||||
|
@ -19,8 +19,8 @@ let ACTORS = {
|
||||
events: {
|
||||
"AboutReaderContentLoaded": {wantUntrusted: true},
|
||||
"DOMContentLoaded": {},
|
||||
"pageshow": {},
|
||||
"pagehide": {},
|
||||
"pageshow": {mozSystemGroup: true},
|
||||
"pagehide": {mozSystemGroup: true},
|
||||
},
|
||||
messages: [
|
||||
"Reader:ToggleReaderMode",
|
||||
@ -120,6 +120,15 @@ let ACTORS = {
|
||||
},
|
||||
},
|
||||
|
||||
FormSubmit: {
|
||||
child: {
|
||||
module: "resource:///actors/FormSubmitChild.jsm",
|
||||
events: {
|
||||
"MozInvalidForm": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
LightWeightThemeInstall: {
|
||||
child: {
|
||||
module: "resource:///actors/LightWeightThemeInstallChild.jsm",
|
||||
@ -131,6 +140,16 @@ let ACTORS = {
|
||||
},
|
||||
},
|
||||
|
||||
LightweightTheme: {
|
||||
child: {
|
||||
module: "resource:///actors/LightweightThemeChild.jsm",
|
||||
matches: ["about:home", "about:newtab", "about:welcome"],
|
||||
events: {
|
||||
"pageshow": {mozSystemGroup: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
LinkHandler: {
|
||||
child: {
|
||||
module: "resource:///actors/LinkHandlerChild.jsm",
|
||||
|
@ -109,7 +109,7 @@ export default class AddressForm extends PaymentStateSubscriberMixin(PaymentRequ
|
||||
}
|
||||
|
||||
render(state) {
|
||||
let record = {};
|
||||
let record;
|
||||
let {
|
||||
page,
|
||||
"address-page": addressPage,
|
||||
@ -286,7 +286,6 @@ export default class AddressForm extends PaymentStateSubscriberMixin(PaymentRequ
|
||||
|
||||
updateSaveButtonState() {
|
||||
this.saveButton.disabled = !this.form.checkValidity();
|
||||
log.debug("updateSaveButtonState", this.saveButton.disabled);
|
||||
}
|
||||
|
||||
async saveRecord() {
|
||||
|
@ -188,6 +188,9 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRe
|
||||
billingAddressSelect.value = Object.keys(addresses)[0];
|
||||
}
|
||||
}
|
||||
// Need to recalculate the populated state since
|
||||
// billingAddressSelect is updated after loadRecord.
|
||||
this.formHandler.updatePopulatedState(billingAddressSelect);
|
||||
|
||||
this.updateRequiredState();
|
||||
this.updateSaveButtonState();
|
||||
|
@ -1,8 +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/. */
|
||||
|
||||
div[required] > label > span:first-of-type::after,
|
||||
:-moz-any(label, div)[required] > span:first-of-type::after {
|
||||
content: attr(fieldRequiredSymbol);
|
||||
}
|
@ -204,19 +204,13 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
||||
}
|
||||
|
||||
// Ensure `selectedShippingOption` never refers to a deleted shipping option and
|
||||
// refers to a shipping option if one exists.
|
||||
// matches the merchant's selected option if the user hasn't made a choice.
|
||||
if (shippingOptions && (!selectedShippingOption ||
|
||||
!shippingOptions.find(option => option.id == selectedShippingOption))) {
|
||||
// Use the DOM's computed selected shipping option:
|
||||
selectedShippingOption = state.request.shippingOption;
|
||||
|
||||
// Otherwise, default to selecting the first option:
|
||||
if (!selectedShippingOption && shippingOptions.length) {
|
||||
selectedShippingOption = shippingOptions[0].id;
|
||||
}
|
||||
this._cachedState.selectedShippingOption = selectedShippingOption;
|
||||
this.requestStore.setState({
|
||||
selectedShippingOption,
|
||||
// Use the DOM's computed selected shipping option:
|
||||
selectedShippingOption: state.request.shippingOption,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,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/. */
|
||||
|
||||
html {
|
||||
:root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@ -159,7 +159,7 @@ payment-dialog[changes-prevented][complete-status="success"] #pay {
|
||||
}
|
||||
|
||||
#cancel {
|
||||
margin-left: auto;
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
|
||||
#disabled-overlay {
|
||||
|
@ -84,13 +84,16 @@
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self' chrome:"/>
|
||||
|
||||
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css"/>
|
||||
<link rel="stylesheet" href="resource://formautofill/editDialog-shared.css"/>
|
||||
<link rel="stylesheet" href="resource://formautofill/editAddress.css"/>
|
||||
<link rel="stylesheet" href="resource://formautofill/editCreditCard.css"/>
|
||||
<link rel="stylesheet" href="resource://formautofill/editDialog.css"/>
|
||||
<link rel="stylesheet" href="paymentRequest.css"/>
|
||||
<link rel="stylesheet" href="components/rich-select.css"/>
|
||||
<link rel="stylesheet" href="components/address-option.css"/>
|
||||
<link rel="stylesheet" href="components/basic-card-option.css"/>
|
||||
<link rel="stylesheet" href="components/shipping-option.css"/>
|
||||
<link rel="stylesheet" href="components/payment-details-item.css"/>
|
||||
<link rel="stylesheet" href="containers/form.css"/>
|
||||
<link rel="stylesheet" href="containers/address-form.css"/>
|
||||
<link rel="stylesheet" href="containers/basic-card-form.css"/>
|
||||
<link rel="stylesheet" href="containers/order-details.css"/>
|
||||
|
@ -112,14 +112,21 @@ var PaymentTestUtils = {
|
||||
let popupBox = Cu.waiveXrays(picker).dropdown.popupBox;
|
||||
let selectedOptionIndex = popupBox.selectedIndex;
|
||||
let selectedOption = Cu.waiveXrays(picker).dropdown.selectedOption;
|
||||
return {
|
||||
|
||||
let result = {
|
||||
optionCount: popupBox.children.length,
|
||||
selectedOptionIndex,
|
||||
};
|
||||
if (!selectedOption) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return Object.assign(result, {
|
||||
selectedOptionID: selectedOption.getAttribute("value"),
|
||||
selectedOptionLabel: selectedOption.getAttribute("label"),
|
||||
selectedOptionCurrency: selectedOption.getAttribute("amount-currency"),
|
||||
selectedOptionValue: selectedOption.getAttribute("amount-value"),
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
getShippingAddresses: () => {
|
||||
|
@ -145,10 +145,9 @@ add_task(async function test_default_shippingOptions_noneSelected() {
|
||||
);
|
||||
|
||||
let shippingOptions =
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.getShippingOptions);
|
||||
is(shippingOptions.selectedOptionCurrency, "USD", "Shipping options should be in USD");
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.getShippingOptions);
|
||||
is(shippingOptions.optionCount, 2, "there should be two shipping options");
|
||||
is(shippingOptions.selectedOptionID, "1", "default selected should be the first");
|
||||
is(shippingOptions.selectedOptionIndex, "-1", "no options should be selected");
|
||||
|
||||
let shippingOptionDetailsEUR = deepClone(PTU.Details.twoShippingOptionsEUR);
|
||||
info("prepare EUR options by deselecting all and giving unique IDs");
|
||||
@ -157,6 +156,8 @@ add_task(async function test_default_shippingOptions_noneSelected() {
|
||||
opt.id += "-EUR";
|
||||
});
|
||||
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.selectShippingOptionById, "1");
|
||||
|
||||
await ContentTask.spawn(browser, {
|
||||
eventName: "shippingaddresschange",
|
||||
details: Object.assign(shippingOptionDetailsEUR, PTU.Details.total1pt75EUR),
|
||||
@ -173,10 +174,8 @@ add_task(async function test_default_shippingOptions_noneSelected() {
|
||||
|
||||
shippingOptions =
|
||||
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.getShippingOptions);
|
||||
is(shippingOptions.selectedOptionCurrency, "EUR", "Shipping options should be in EUR");
|
||||
is(shippingOptions.optionCount, 2, "there should be two shipping options");
|
||||
is(shippingOptions.selectedOptionID, "1-EUR",
|
||||
"default selected should be the first");
|
||||
is(shippingOptions.selectedOptionIndex, "-1", "no options should be selected again");
|
||||
|
||||
spawnPaymentDialogTask(frame, PTU.DialogContentTasks.manuallyClickCancel);
|
||||
await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
|
||||
|
@ -31,6 +31,8 @@ add_task(async function test_dropdown() {
|
||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||
return state.page.id == "address-page" && !state.page.guid;
|
||||
}, "Check add page state");
|
||||
|
||||
content.document.querySelector("#country").scrollIntoView();
|
||||
});
|
||||
|
||||
info("going to open the country <select>");
|
||||
|
@ -276,8 +276,8 @@ async function setupPaymentDialog(browser, {methodData, details, options, mercha
|
||||
return;
|
||||
}
|
||||
field.value = value;
|
||||
field.dispatchEvent(new content.window.Event("input"));
|
||||
field.dispatchEvent(new content.window.Event("change"));
|
||||
field.dispatchEvent(new content.window.Event("input", {bubbles: true}));
|
||||
field.dispatchEvent(new content.window.Event("change", {bubbles: true}));
|
||||
return;
|
||||
}
|
||||
while (field.value) {
|
||||
|
@ -5,6 +5,7 @@ support-files =
|
||||
!/browser/extensions/formautofill/content/editAddress.xhtml
|
||||
!/browser/extensions/formautofill/content/editCreditCard.xhtml
|
||||
../../../../../browser/extensions/formautofill/content/autofillEditForms.js
|
||||
../../../../../browser/extensions/formautofill/skin/shared/editDialog-shared.css
|
||||
../../../../../testing/modules/sinon-2.3.2.js
|
||||
../../res/**
|
||||
payments_common.js
|
||||
|
@ -61,8 +61,8 @@ async function fillField(field, value) {
|
||||
return;
|
||||
}
|
||||
field.value = value;
|
||||
field.dispatchEvent(new Event("input"));
|
||||
field.dispatchEvent(new Event("change"));
|
||||
field.dispatchEvent(new Event("input", {bubbles: true}));
|
||||
field.dispatchEvent(new Event("change", {bubbles: true}));
|
||||
return;
|
||||
}
|
||||
while (field.value) {
|
||||
|
@ -17,7 +17,7 @@ Test the address-form element
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../../res/paymentRequest.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../../res/containers/form.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="editDialog-shared.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="../../res/containers/address-form.css"/>
|
||||
</head>
|
||||
<body>
|
||||
@ -72,6 +72,11 @@ add_task(async function test_initialState() {
|
||||
display.appendChild(form);
|
||||
await asyncElementRendered();
|
||||
is(page.id, "payment-summary", "Check initial page after appending");
|
||||
|
||||
// :-moz-ui-invalid, unlike :invalid, only applies to fields showing the error outline.
|
||||
let fieldsVisiblyInvalid = form.querySelectorAll(":-moz-ui-invalid");
|
||||
is(fieldsVisiblyInvalid.length, 0, "Check no fields are visibly invalid on an empty 'add' form");
|
||||
|
||||
form.remove();
|
||||
});
|
||||
|
||||
@ -117,10 +122,9 @@ add_task(async function test_saveButton() {
|
||||
fillField(form.form.querySelector("#organization"), "Allizom");
|
||||
fillField(form.form.querySelector("#street-address"), "404 Internet Super Highway");
|
||||
fillField(form.form.querySelector("#address-level2"), "Firefoxity City");
|
||||
fillField(form.form.querySelector("#country"), "US");
|
||||
fillField(form.form.querySelector("#address-level1"), "CA");
|
||||
fillField(form.form.querySelector("#postal-code"), "00001");
|
||||
fillField(form.form.querySelector("#country"), "US");
|
||||
fillField(form.form.querySelector("#email"), "test@example.com");
|
||||
fillField(form.form.querySelector("#tel"), "+15555551212");
|
||||
|
||||
ok(!form.saveButton.disabled, "Save button is enabled after filling");
|
||||
@ -128,8 +132,13 @@ add_task(async function test_saveButton() {
|
||||
info("blanking the street-address");
|
||||
fillField(form.form.querySelector("#street-address"), "");
|
||||
ok(form.saveButton.disabled, "Save button is disabled after blanking street-address");
|
||||
form.form.querySelector("#street-address").blur();
|
||||
let fieldsVisiblyInvalid = form.querySelectorAll(":-moz-ui-invalid");
|
||||
is(fieldsVisiblyInvalid.length, 1, "Check 1 field visibly invalid after blanking and blur");
|
||||
is(fieldsVisiblyInvalid[0].id, "street-address", "Check #street-address is visibly invalid");
|
||||
|
||||
fillField(form.form.querySelector("#street-address"), "404 Internet Super Highway");
|
||||
is(form.querySelectorAll(":-moz-ui-invalid").length, 0, "Check no fields visibly invalid");
|
||||
ok(!form.saveButton.disabled, "Save button is enabled after re-filling street-address");
|
||||
|
||||
let messagePromise = promiseContentToChromeMessage("updateAutofillRecord");
|
||||
@ -200,6 +209,8 @@ add_task(async function test_edit() {
|
||||
},
|
||||
});
|
||||
await asyncElementRendered();
|
||||
is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
|
||||
"Check no fields are visibly invalid on an 'edit' form with a complete address");
|
||||
checkAddressForm(form, address1);
|
||||
|
||||
ok(!form.saveButton.disabled, "Save button should be enabled upon edit for a valid address");
|
||||
@ -224,6 +235,10 @@ add_task(async function test_edit() {
|
||||
is(form.saveButton.textContent, "Update", "Check label");
|
||||
checkAddressForm(form, minimalAddress);
|
||||
ok(form.saveButton.disabled, "Save button should be disabled if only the name is filled");
|
||||
ok(form.querySelectorAll(":-moz-ui-invalid").length > 3,
|
||||
"Check fields are visibly invalid on an 'edit' form with only the given-name filled");
|
||||
ok(form.querySelectorAll("#country:-moz-ui-invalid").length, 1,
|
||||
"Check that the country `select` is marked as invalid");
|
||||
|
||||
info("change to no selected address");
|
||||
await form.requestStore.setState({
|
||||
@ -233,7 +248,11 @@ add_task(async function test_edit() {
|
||||
"address-page": {},
|
||||
});
|
||||
await asyncElementRendered();
|
||||
checkAddressForm(form, {});
|
||||
is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
|
||||
"Check no fields are visibly invalid on an empty 'add' form after being an edit form");
|
||||
checkAddressForm(form, {
|
||||
country: "US",
|
||||
});
|
||||
ok(form.saveButton.disabled, "Save button should be disabled for an empty form");
|
||||
|
||||
form.remove();
|
||||
@ -355,7 +374,7 @@ add_task(async function test_field_validation() {
|
||||
form.remove();
|
||||
});
|
||||
|
||||
add_task(async function test_customValidity() {
|
||||
add_task(async function test_customMerchantValidity() {
|
||||
let form = new AddressForm();
|
||||
await form.promiseReady;
|
||||
const state = {
|
||||
@ -406,6 +425,49 @@ add_task(async function test_customValidity() {
|
||||
form.remove();
|
||||
});
|
||||
|
||||
add_task(async function test_customMerchantValidity_reset() {
|
||||
let form = new AddressForm();
|
||||
await form.promiseReady;
|
||||
const state = {
|
||||
page: {
|
||||
id: "address-page",
|
||||
},
|
||||
"address-page": {
|
||||
title: "Sample page title",
|
||||
},
|
||||
request: {
|
||||
paymentDetails: {
|
||||
shippingAddressErrors: {
|
||||
addressLine: "Street address needs to start with a D",
|
||||
city: "City needs to start with a B",
|
||||
country: "Country needs to start with a C",
|
||||
organization: "organization needs to start with an A",
|
||||
phone: "Telephone needs to start with a 9",
|
||||
postalCode: "Postal code needs to start with a 0",
|
||||
recipient: "Name needs to start with a Z",
|
||||
region: "Region needs to start with a Y",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
await form.requestStore.setState(state);
|
||||
display.appendChild(form);
|
||||
await asyncElementRendered();
|
||||
|
||||
ok(form.querySelectorAll(":-moz-ui-invalid").length > 0, "Check fields are visibly invalid");
|
||||
info("merchant cleared the errors");
|
||||
await form.requestStore.setState({
|
||||
request: {
|
||||
paymentDetails: {
|
||||
shippingAddressErrors: {},
|
||||
},
|
||||
},
|
||||
});
|
||||
await asyncElementRendered();
|
||||
is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
|
||||
"Check fields are visibly valid - custom validity cleared");
|
||||
});
|
||||
|
||||
add_task(async function test_field_validation() {
|
||||
sinon.stub(PaymentDialogUtils, "getFormFormat").returns({
|
||||
addressLevel1Label: "state",
|
||||
|
@ -122,6 +122,9 @@ add_task(async function test_update() {
|
||||
ok(options[1].textContent.includes("Mrs. Bar"), "Check that name is the same in second address");
|
||||
ok(options[1].getAttribute("street-address").includes("P.O. Box 123"),
|
||||
"Check second address is the same");
|
||||
ok(options[2].textContent.includes("Mrs. Fields"),
|
||||
"Check that name is the same in third address");
|
||||
is(options[2].getAttribute("street-address"), null, "Check third address is missing");
|
||||
});
|
||||
|
||||
add_task(async function test_change_selected_address() {
|
||||
|
@ -59,6 +59,11 @@ add_task(async function test_initialState() {
|
||||
display.appendChild(form);
|
||||
await asyncElementRendered();
|
||||
is(page.id, "payment-summary", "Check initial page after appending");
|
||||
|
||||
// :-moz-ui-invalid, unlike :invalid, only applies to fields showing the error outline.
|
||||
let fieldsVisiblyInvalid = form.querySelectorAll(":-moz-ui-invalid");
|
||||
is(fieldsVisiblyInvalid.length, 0, "Check no fields are visibly invalid on an empty 'add' form");
|
||||
|
||||
form.remove();
|
||||
});
|
||||
|
||||
@ -97,21 +102,30 @@ add_task(async function test_saveButton() {
|
||||
await asyncElementRendered();
|
||||
|
||||
ok(form.saveButton.disabled, "Save button should initially be disabled");
|
||||
form.form.querySelector("#cc-number").focus();
|
||||
sendString("4111 1111-1111 1111");
|
||||
fillField(form.form.querySelector("#cc-number"), "4111 1111-1111 1111");
|
||||
form.form.querySelector("#cc-name").focus();
|
||||
// Check .disabled after .focus() so that it's after both "input" and "change" events.
|
||||
ok(form.saveButton.disabled, "Save button should still be disabled without a name");
|
||||
sendString("J. Smith");
|
||||
form.form.querySelector("#cc-exp-month").focus();
|
||||
sendString("11");
|
||||
form.form.querySelector("#cc-exp-year").focus();
|
||||
fillField(form.form.querySelector("#cc-exp-month"), "11");
|
||||
let year = (new Date()).getFullYear().toString();
|
||||
sendString(year);
|
||||
fillField(form.form.querySelector("#cc-exp-year"), year);
|
||||
form.saveButton.focus();
|
||||
ok(!form.saveButton.disabled,
|
||||
"Save button should be enabled since the required fields are filled");
|
||||
|
||||
info("blanking the cc-number field");
|
||||
fillField(form.form.querySelector("#cc-number"), "");
|
||||
ok(form.saveButton.disabled, "Save button is disabled after blanking cc-number");
|
||||
form.form.querySelector("#cc-number").blur();
|
||||
let fieldsVisiblyInvalid = form.querySelectorAll(":-moz-ui-invalid");
|
||||
is(fieldsVisiblyInvalid.length, 1, "Check 1 field visibly invalid after blanking and blur");
|
||||
is(fieldsVisiblyInvalid[0].id, "cc-number", "Check #cc-number is visibly invalid");
|
||||
|
||||
fillField(form.form.querySelector("#cc-number"), "4111 1111-1111 1111");
|
||||
is(form.querySelectorAll(":-moz-ui-invalid").length, 0, "Check no fields visibly invalid");
|
||||
ok(!form.saveButton.disabled, "Save button is enabled after re-filling cc-number");
|
||||
|
||||
let messagePromise = promiseContentToChromeMessage("updateAutofillRecord");
|
||||
is(form.saveButton.textContent, "Add", "Check label");
|
||||
synthesizeMouseAtCenter(form.saveButton, {});
|
||||
@ -292,7 +306,10 @@ add_task(async function test_edit() {
|
||||
});
|
||||
await asyncElementRendered();
|
||||
is(form.saveButton.textContent, "Update", "Check label");
|
||||
is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
|
||||
"Check no fields are visibly invalid on an 'edit' form with a complete card");
|
||||
checkCCForm(form, card1);
|
||||
ok(!form.saveButton.disabled, "Save button should be enabled upon edit for a valid card");
|
||||
|
||||
let requiredElements = [...form.form.elements].filter(e => e.required && !e.disabled);
|
||||
ok(requiredElements.length, "There should be at least one required element");
|
||||
@ -331,6 +348,8 @@ add_task(async function test_edit() {
|
||||
},
|
||||
});
|
||||
await asyncElementRendered();
|
||||
ok(form.querySelectorAll(":-moz-ui-invalid").length > 0,
|
||||
"Check fields are visibly invalid on an 'edit' form with missing fields");
|
||||
checkCCForm(form, minimalCard);
|
||||
|
||||
info("change to no selected card");
|
||||
@ -343,6 +362,8 @@ add_task(async function test_edit() {
|
||||
},
|
||||
});
|
||||
await asyncElementRendered();
|
||||
is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
|
||||
"Check no fields are visibly invalid after converting to an 'add' form");
|
||||
checkCCForm(form, {});
|
||||
|
||||
form.remove();
|
||||
@ -359,15 +380,13 @@ add_task(async function test_field_validity_updates() {
|
||||
let nameInput = form.form.querySelector("#cc-name");
|
||||
|
||||
info("test with valid cc-number but missing cc-name");
|
||||
ccNumber.focus();
|
||||
sendString("4111111111111111");
|
||||
fillField(ccNumber, "4111111111111111");
|
||||
ok(ccNumber.checkValidity(), "cc-number field is valid with good input");
|
||||
ok(!nameInput.checkValidity(), "cc-name field is invalid when empty");
|
||||
ok(form.saveButton.disabled, "Save button should be disabled with incomplete input");
|
||||
|
||||
info("correct by adding cc-name value");
|
||||
nameInput.focus();
|
||||
sendString("First");
|
||||
fillField(nameInput, "First");
|
||||
ok(ccNumber.checkValidity(), "cc-number field is valid with good input");
|
||||
ok(nameInput.checkValidity(), "cc-name field is valid with a value");
|
||||
ok(!form.saveButton.disabled, "Save button should not be disabled with good input");
|
||||
@ -379,6 +398,7 @@ add_task(async function test_field_validity_updates() {
|
||||
sendString("Surname");
|
||||
|
||||
ok(!ccNumber.checkValidity(), "cc-number field becomes invalid with bad input");
|
||||
ok(form.querySelector("#cc-number:-moz-ui-invalid"), "cc-number field is visibly invalid");
|
||||
ok(nameInput.checkValidity(), "cc-name field is valid with a value");
|
||||
ok(form.saveButton.disabled, "Save button becomes disabled with bad input");
|
||||
|
||||
@ -394,6 +414,31 @@ add_task(async function test_field_validity_updates() {
|
||||
|
||||
form.remove();
|
||||
});
|
||||
|
||||
add_task(async function test_numberCustomValidityReset() {
|
||||
let form = new BasicCardForm();
|
||||
form.dataset.updateButtonLabel = "Add";
|
||||
await form.promiseReady;
|
||||
display.appendChild(form);
|
||||
await asyncElementRendered();
|
||||
|
||||
fillField(form.querySelector("#cc-number"), "junk");
|
||||
sendKey("TAB");
|
||||
ok(form.querySelector("#cc-number:-moz-ui-invalid"), "cc-number field is visibly invalid");
|
||||
|
||||
info("simulate triggering an add again to reset the form");
|
||||
await form.requestStore.setState({
|
||||
page: {
|
||||
id: "basic-card-page",
|
||||
},
|
||||
"basic-card-page": {
|
||||
},
|
||||
});
|
||||
|
||||
ok(!form.querySelector("#cc-number:-moz-ui-invalid"), "cc-number field is not visibly invalid");
|
||||
|
||||
form.remove();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
@ -22,7 +22,8 @@ add_task(async function test_timezone() {
|
||||
let dateObj = new Date();
|
||||
let dateString = dateObj.toString();
|
||||
|
||||
ok(dateString.endsWith("(UTC)"), "The date string is in UTC timezone.");
|
||||
ok(dateString.endsWith("(Coordinated Universal Time)"),
|
||||
"The date string is in UTC timezone.");
|
||||
is(dateObj.getFullYear(), dateObj.getUTCFullYear(),
|
||||
"The full year reports in UTC timezone.");
|
||||
is(dateObj.getMonth(), dateObj.getUTCMonth(), "The month reports in UTC timezone.");
|
||||
|
@ -5,6 +5,7 @@ CARGO="${TOOLTOOL_DIR}/rustc/bin/cargo"
|
||||
RUSTC="${TOOLTOOL_DIR}/rustc/bin/rustc"
|
||||
RUSTDOC="${TOOLTOOL_DIR}/rustc/bin/rustdoc"
|
||||
RUSTFMT="${TOOLTOOL_DIR}/rustc/bin/rustfmt"
|
||||
CBINDGEN="${TOOLTOOL_DIR}/cbindgen/cbindgen"
|
||||
|
||||
export NODEJS="${TOOLTOOL_DIR}/node/bin/node"
|
||||
|
||||
|
@ -6,6 +6,7 @@ RUSTC="${TOOLTOOL_DIR}/rustc/bin/rustc"
|
||||
CARGO="${TOOLTOOL_DIR}/rustc/bin/cargo"
|
||||
RUSTDOC="${TOOLTOOL_DIR}/rustc/bin/rustdoc"
|
||||
RUSTFMT="${TOOLTOOL_DIR}/rustc/bin/rustfmt"
|
||||
CBINDGEN="${TOOLTOOL_DIR}/cbindgen/cbindgen"
|
||||
|
||||
NODEJS="${TOOLTOOL_DIR}/node/node.exe"
|
||||
|
||||
|
@ -18,7 +18,7 @@ const EDIT_ADDRESS_KEYWORDS = [
|
||||
"state", "province", "city", "country", "zip", "postalCode", "email", "tel",
|
||||
];
|
||||
const MANAGE_CREDITCARDS_KEYWORDS = ["manageCreditCardsTitle", "addNewCreditCardTitle", "showCreditCardsBtnLabel"];
|
||||
const EDIT_CREDITCARD_KEYWORDS = ["cardNumber", "nameOnCard", "cardExpires"];
|
||||
const EDIT_CREDITCARD_KEYWORDS = ["cardNumber", "nameOnCard", "cardExpiresMonth", "cardExpiresYear"];
|
||||
const FIELD_STATES = {
|
||||
NORMAL: "NORMAL",
|
||||
AUTO_FILLED: "AUTO_FILLED",
|
||||
|
@ -19,7 +19,31 @@ class EditAutofillForm {
|
||||
loadRecord(record = {}) {
|
||||
for (let field of this._elements.form.elements) {
|
||||
let value = record[field.id];
|
||||
field.value = typeof(value) == "undefined" ? "" : value;
|
||||
value = typeof(value) == "undefined" ? "" : value;
|
||||
|
||||
if (record.guid) {
|
||||
field.value = value;
|
||||
} else if (field.localName == "select") {
|
||||
this.setDefaultSelectedOptionByValue(field, value);
|
||||
} else {
|
||||
// Use .defaultValue instead of .value to avoid setting the `dirty` flag
|
||||
// which triggers form validation UI.
|
||||
field.defaultValue = value;
|
||||
}
|
||||
}
|
||||
if (!record.guid) {
|
||||
// Reset the dirty value flag and validity state.
|
||||
this._elements.form.reset();
|
||||
}
|
||||
|
||||
for (let field of this._elements.form.elements) {
|
||||
this.updatePopulatedState(field);
|
||||
}
|
||||
}
|
||||
|
||||
setDefaultSelectedOptionByValue(select, value) {
|
||||
for (let option of select.options) {
|
||||
option.defaultSelected = option.value == value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,17 +67,26 @@ class EditAutofillForm {
|
||||
*/
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "input": {
|
||||
this.handleInput(event);
|
||||
break;
|
||||
}
|
||||
case "change": {
|
||||
this.handleChange(event);
|
||||
break;
|
||||
}
|
||||
case "input": {
|
||||
this.handleInput(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle change events
|
||||
*
|
||||
* @param {DOMEvent} event
|
||||
*/
|
||||
handleChange(event) {
|
||||
this.updatePopulatedState(event.target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle input events
|
||||
*
|
||||
@ -68,8 +101,18 @@ class EditAutofillForm {
|
||||
this._elements.form.addEventListener("input", this);
|
||||
}
|
||||
|
||||
// An interface to be inherited.
|
||||
handleChange(event) {}
|
||||
/**
|
||||
* Set the field-populated attribute if the field has a value.
|
||||
*
|
||||
* @param {DOMElement} field The field that will be checked for a value.
|
||||
*/
|
||||
updatePopulatedState(field) {
|
||||
let span = field.parentNode.querySelector(".label-text");
|
||||
if (!span) {
|
||||
return;
|
||||
}
|
||||
span.toggleAttribute("field-populated", !!field.value.trim());
|
||||
}
|
||||
}
|
||||
|
||||
class EditAddress extends EditAutofillForm {
|
||||
@ -239,11 +282,14 @@ class EditAddress extends EditAutofillForm {
|
||||
}
|
||||
|
||||
handleChange(event) {
|
||||
this.formatForm(event.target.value);
|
||||
if (event.target == this._elements.country) {
|
||||
this.formatForm(event.target.value);
|
||||
}
|
||||
super.handleChange(event);
|
||||
}
|
||||
|
||||
attachEventListeners() {
|
||||
this._elements.country.addEventListener("change", this);
|
||||
this._elements.form.addEventListener("change", this);
|
||||
super.attachEventListeners();
|
||||
}
|
||||
}
|
||||
@ -264,6 +310,7 @@ class EditCreditCard extends EditAutofillForm {
|
||||
Object.assign(this._elements, {
|
||||
ccNumber: this._elements.form.querySelector("#cc-number"),
|
||||
invalidCardNumberStringElement: this._elements.form.querySelector("#invalidCardNumberString"),
|
||||
month: this._elements.form.querySelector("#cc-exp-month"),
|
||||
year: this._elements.form.querySelector("#cc-exp-year"),
|
||||
billingAddress: this._elements.form.querySelector("#billingAddressGUID"),
|
||||
billingAddressRow: this._elements.form.querySelector(".billingAddressRow"),
|
||||
@ -282,6 +329,11 @@ class EditCreditCard extends EditAutofillForm {
|
||||
// Re-generating the years will reset the selected option.
|
||||
this.generateYears();
|
||||
super.loadRecord(record);
|
||||
|
||||
// Resetting the form in the super.loadRecord won't clear custom validity
|
||||
// state so reset it here. Since the cc-number field is disabled upon editing
|
||||
// we don't need to recaclulate its validity here.
|
||||
this._elements.ccNumber.setCustomValidity("");
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,7 +382,7 @@ class EditCreditCard extends EditAutofillForm {
|
||||
}
|
||||
|
||||
attachEventListeners() {
|
||||
this._elements.ccNumber.addEventListener("change", this);
|
||||
this._elements.form.addEventListener("change", this);
|
||||
super.attachEventListeners();
|
||||
}
|
||||
|
||||
|
@ -17,45 +17,45 @@
|
||||
<script src="chrome://formautofill/content/autofillEditForms.js"></script>
|
||||
</head>
|
||||
<body dir="&locale.dir;">
|
||||
<form id="form" autocomplete="off">
|
||||
<form id="form" class="editAddressForm" autocomplete="off">
|
||||
<div>
|
||||
<div id="name-container">
|
||||
<label id="given-name-container">
|
||||
<span data-localization="givenName"/>
|
||||
<span data-localization="givenName" class="label-text"/>
|
||||
<input id="given-name" type="text" required="required"/>
|
||||
</label>
|
||||
<label id="additional-name-container">
|
||||
<span data-localization="additionalName"/>
|
||||
<span data-localization="additionalName" class="label-text"/>
|
||||
<input id="additional-name" type="text"/>
|
||||
</label>
|
||||
<label id="family-name-container">
|
||||
<span data-localization="familyName"/>
|
||||
<span data-localization="familyName" class="label-text"/>
|
||||
<input id="family-name" type="text"/>
|
||||
</label>
|
||||
</div>
|
||||
<label id="organization-container">
|
||||
<span data-localization="organization2"/>
|
||||
<span data-localization="organization2" class="label-text"/>
|
||||
<input id="organization" type="text"/>
|
||||
</label>
|
||||
<label id="street-address-container">
|
||||
<span data-localization="streetAddress"/>
|
||||
<span data-localization="streetAddress" class="label-text"/>
|
||||
<textarea id="street-address" rows="3" required="required"/>
|
||||
</label>
|
||||
<label id="address-level2-container">
|
||||
<span data-localization="city"/>
|
||||
<span data-localization="city" class="label-text"/>
|
||||
<input id="address-level2" type="text" required="required"/>
|
||||
</label>
|
||||
<label id="address-level1-container">
|
||||
<span/>
|
||||
<span class="label-text"/>
|
||||
<input id="address-level1" type="text" required="required"/>
|
||||
</label>
|
||||
<label id="postal-code-container">
|
||||
<span/>
|
||||
<span class="label-text"/>
|
||||
<input id="postal-code" type="text" required="required"/>
|
||||
</label>
|
||||
<div id="country-container">
|
||||
<label id="country-label">
|
||||
<span data-localization="country"/>
|
||||
<span data-localization="country" class="label-text"/>
|
||||
<select id="country" required="required">
|
||||
<option/>
|
||||
</select>
|
||||
@ -63,11 +63,11 @@
|
||||
<p id="country-warning-message" data-localization="countryWarningMessage2"/>
|
||||
</div>
|
||||
<label id="tel-container">
|
||||
<span data-localization="tel"/>
|
||||
<span data-localization="tel" class="label-text"/>
|
||||
<input id="tel" type="tel"/>
|
||||
</label>
|
||||
<label id="email-container">
|
||||
<span data-localization="email"/>
|
||||
<span data-localization="email" class="label-text"/>
|
||||
<input id="email" type="email" required="required"/>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -17,18 +17,18 @@
|
||||
<script src="chrome://formautofill/content/autofillEditForms.js"></script>
|
||||
</head>
|
||||
<body dir="&locale.dir;">
|
||||
<form id="form" autocomplete="off">
|
||||
<form id="form" class="editCreditCardForm" autocomplete="off">
|
||||
<label>
|
||||
<span data-localization="cardNumber"/>
|
||||
<span data-localization="cardNumber" class="label-text"/>
|
||||
<span id="invalidCardNumberString" hidden="hidden" data-localization="invalidCardNumber"></span>
|
||||
<input id="cc-number" type="text" required="required" minlength="9" pattern="[- 0-9]+"/>
|
||||
</label>
|
||||
<label>
|
||||
<span data-localization="nameOnCard"/>
|
||||
<span data-localization="nameOnCard" class="label-text"/>
|
||||
<input id="cc-name" type="text" required="required"/>
|
||||
</label>
|
||||
<div>
|
||||
<span data-localization="cardExpires"/>
|
||||
<label>
|
||||
<span data-localization="cardExpiresMonth" class="label-text"/>
|
||||
<select id="cc-exp-month">
|
||||
<option/>
|
||||
<option value="1">01</option>
|
||||
@ -44,12 +44,15 @@
|
||||
<option value="11">11</option>
|
||||
<option value="12">12</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span data-localization="cardExpiresYear" class="label-text"/>
|
||||
<select id="cc-exp-year">
|
||||
<option/>
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
<label class="billingAddressRow">
|
||||
<span data-localization="billingAddress"/>
|
||||
<span data-localization="billingAddress" class="label-text"/>
|
||||
<select id="billingAddressGUID">
|
||||
</select>
|
||||
</label>
|
||||
|
@ -138,5 +138,6 @@ editCreditCardTitle = Edit Credit Card
|
||||
cardNumber = Card Number
|
||||
invalidCardNumber = Please enter a valid card number
|
||||
nameOnCard = Name on Card
|
||||
cardExpires = Expires
|
||||
cardExpiresMonth = Exp. Month
|
||||
cardExpiresYear = Exp. Year
|
||||
billingAddress = Billing Address
|
||||
|
@ -3,6 +3,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Linux specific rules */
|
||||
body {
|
||||
:root[subdialog] body {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
}
|
||||
|
@ -2,18 +2,9 @@
|
||||
* 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/. */
|
||||
|
||||
html {
|
||||
width: 620px;
|
||||
}
|
||||
|
||||
label > span {
|
||||
flex: 0 0 9.5em;
|
||||
}
|
||||
|
||||
input,
|
||||
select {
|
||||
.editAddressForm input,
|
||||
.editAddressForm select {
|
||||
flex: 1 0 auto;
|
||||
width: calc(50% - 9.5em);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -27,11 +18,16 @@ select {
|
||||
#organization-container,
|
||||
#address-level2-container,
|
||||
#tel-container {
|
||||
display: flex;
|
||||
flex: 0 1 50%;
|
||||
}
|
||||
|
||||
#tel-container {
|
||||
padding-inline-end: 50%;
|
||||
#given-name-container,
|
||||
#additional-name-container,
|
||||
#family-name-container {
|
||||
display: flex;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#name-container,
|
||||
|
@ -2,32 +2,28 @@
|
||||
* 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/. */
|
||||
|
||||
html {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
form {
|
||||
.editCreditCardForm {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
form > label,
|
||||
form > div {
|
||||
.editCreditCardForm > label,
|
||||
.editCreditCardForm > div {
|
||||
flex: 1 0 100%;
|
||||
align-self: center;
|
||||
margin: 0 0 0.5em !important;
|
||||
}
|
||||
|
||||
#billingAddressGUID,
|
||||
input {
|
||||
.editCreditCardForm #billingAddressGUID,
|
||||
.editCreditCardForm input {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
select {
|
||||
.editCreditCardForm select {
|
||||
margin: 0;
|
||||
margin-inline-end: 0.7em;
|
||||
}
|
||||
|
||||
label > span,
|
||||
div > span {
|
||||
.editCreditCardForm label > span,
|
||||
.editCreditCardForm div > span {
|
||||
flex: 0 0 9.5em;
|
||||
}
|
||||
|
@ -2,53 +2,66 @@
|
||||
* 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/. */
|
||||
|
||||
form,
|
||||
label,
|
||||
div,
|
||||
p {
|
||||
display: flex;
|
||||
:root {
|
||||
--in-field-label-size: .8em;
|
||||
/* Use the animation-easing-function that is defined in xul.css. */
|
||||
--animation-easing-function: cubic-bezier(.07,.95,0,1);
|
||||
}
|
||||
|
||||
form,
|
||||
div {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
form {
|
||||
:root[subdialog] form {
|
||||
/* Add extra space to ensure invalid input box is displayed properly */
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
form label,
|
||||
form > p {
|
||||
:root[subdialog] form label,
|
||||
:root[subdialog] form > p {
|
||||
margin: 0 0 0.5em !important;
|
||||
}
|
||||
|
||||
label > span,
|
||||
div > span {
|
||||
box-sizing: border-box;
|
||||
padding-inline-end: 0.7em;
|
||||
align-self: center;
|
||||
text-align: end;
|
||||
-moz-user-select: none;
|
||||
form input[type="email"],
|
||||
form input[type="tel"],
|
||||
form input[type="text"],
|
||||
form textarea,
|
||||
form select {
|
||||
padding-top: calc(var(--in-field-label-size) + .4em);
|
||||
}
|
||||
|
||||
option {
|
||||
padding: 0.3em 0.5em;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
}
|
||||
|
||||
button {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
input,
|
||||
select {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
form :-moz-any(label, div) {
|
||||
position: relative;
|
||||
display: block;
|
||||
line-height: 1em;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
form :-moz-any(label, div) > .label-text {
|
||||
position: absolute;
|
||||
color: GrayText;
|
||||
pointer-events: none;
|
||||
left: 10px;
|
||||
top: .2em;
|
||||
transition: top .2s var(--animation-easing-function),
|
||||
font-size .2s var(--animation-easing-function);
|
||||
}
|
||||
|
||||
form :-moz-any(label, div):focus-within > .label-text,
|
||||
form :-moz-any(label, div) > .label-text[field-populated] {
|
||||
top: 0;
|
||||
font-size: var(--in-field-label-size);
|
||||
}
|
||||
|
||||
form :-moz-any(label, div):focus-within > .label-text {
|
||||
color: var(--in-content-item-selected);
|
||||
}
|
||||
|
||||
form div[required] > label > .label-text::after,
|
||||
form :-moz-any(label, div)[required] > .label-text::after {
|
||||
content: attr(fieldRequiredSymbol);
|
||||
}
|
||||
|
||||
#controls-container {
|
||||
|
@ -3,10 +3,10 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* The save button should be on the left and cancel on the right for Windows */
|
||||
#save {
|
||||
#controlsContainer > #save {
|
||||
order: 0;
|
||||
}
|
||||
|
||||
#cancel {
|
||||
#controlsContainer > #cancel {
|
||||
order: 1;
|
||||
}
|
||||
|
@ -1,68 +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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["LightweightThemeChildHelper"];
|
||||
|
||||
/**
|
||||
* LightweightThemeChildHelper forwards theme data to in-content pages.
|
||||
*/
|
||||
var LightweightThemeChildHelper = {
|
||||
listener: null,
|
||||
whitelist: null,
|
||||
|
||||
/**
|
||||
* Listen to theme updates for the current process
|
||||
* @param {Array} whitelist The pages that can receive theme updates.
|
||||
*/
|
||||
listen(whitelist) {
|
||||
if (!this.listener) {
|
||||
// Clone the whitelist to avoid leaking the global the whitelist
|
||||
// originates from.
|
||||
this.whitelist = new Set([...whitelist]);
|
||||
this.listener = ({ changedKeys }) => {
|
||||
if (changedKeys.find(change => change.startsWith("theme/"))) {
|
||||
this._updateProcess(changedKeys);
|
||||
}
|
||||
};
|
||||
Services.cpmm.sharedData.addEventListener("change", this.listener);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the theme data for the whole process
|
||||
* @param {Array} changedKeys The sharedData keys that were changed.
|
||||
*/
|
||||
_updateProcess(changedKeys) {
|
||||
const windowEnumerator = Services.ww.getWindowEnumerator();
|
||||
while (windowEnumerator.hasMoreElements()) {
|
||||
const {
|
||||
chromeOuterWindowID,
|
||||
content,
|
||||
} = windowEnumerator.getNext().docShell.messageManager;
|
||||
if (changedKeys.includes(`theme/${chromeOuterWindowID}`) &&
|
||||
content && this.whitelist.has(content.document.documentURI)) {
|
||||
this.update(chromeOuterWindowID, content);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Forward the theme data to the page.
|
||||
* @param {Object} outerWindowID The outerWindowID the parent process window has.
|
||||
* @param {Object} content The receiving global
|
||||
*/
|
||||
update(outerWindowID, content) {
|
||||
const event = Cu.cloneInto({
|
||||
detail: {
|
||||
data: Services.cpmm.sharedData.get(`theme/${outerWindowID}`)
|
||||
},
|
||||
}, content);
|
||||
content.dispatchEvent(new content.CustomEvent("LightweightTheme:Set",
|
||||
event));
|
||||
},
|
||||
};
|
@ -61,9 +61,6 @@ with Files("ExtensionsUI.jsm"):
|
||||
with Files("LaterRun.jsm"):
|
||||
BUG_COMPONENT = ("Firefox", "Tours")
|
||||
|
||||
with Files("LightweightThemeChildHelper.jsm"):
|
||||
BUG_COMPONENT = ("WebExtensions", "Themes")
|
||||
|
||||
with Files("OpenInTabsUtils.jsm"):
|
||||
BUG_COMPONENT = ("Firefox", "Tabbed Browser")
|
||||
|
||||
@ -130,11 +127,9 @@ EXTRA_JS_MODULES += [
|
||||
'ExtensionsUI.jsm',
|
||||
'FaviconLoader.jsm',
|
||||
'Feeds.jsm',
|
||||
'FormSubmitObserver.jsm',
|
||||
'FormValidationHandler.jsm',
|
||||
'HomePage.jsm',
|
||||
'LaterRun.jsm',
|
||||
'LightweightThemeChildHelper.jsm',
|
||||
'OpenInTabsUtils.jsm',
|
||||
'PageActions.jsm',
|
||||
'PermissionUI.jsm',
|
||||
|
@ -65,7 +65,7 @@ def nodejs_suitability(require, node, version):
|
||||
MAYBE_FILE_A_BUG = '''
|
||||
|
||||
If you believe this is a bug, <https://mzl.la/2vLbXAv> is a good way
|
||||
to file. Executing `mach bootstrap --no-system changes` should
|
||||
to file. Executing `mach bootstrap --no-system-changes` should
|
||||
install a compatible version in ~/.mozbuild on most platforms.
|
||||
More details: <https://bit.ly/2BbyD1E>
|
||||
'''
|
||||
|
@ -284,6 +284,11 @@ def rust_tests(enable_rust_tests, rustdoc):
|
||||
|
||||
set_config('MOZ_RUST_TESTS', rust_tests)
|
||||
|
||||
# cbindgen is needed by the style system build.
|
||||
cbindgen = check_prog('CBINDGEN', add_rustup_path('cbindgen'), paths=toolchain_search_path,
|
||||
when=depends(build_project)
|
||||
(lambda build_project: build_project != 'js'))
|
||||
|
||||
# Bindgen can use rustfmt to format Rust file, but it's not required.
|
||||
js_option(env='RUSTFMT', nargs=1, help='Path to the rustfmt program')
|
||||
|
||||
|
@ -654,6 +654,9 @@ def toolchain_search_path(vc_compiler_path):
|
||||
bootstrap_clang_path = os.path.join(mozbuild_state_dir, 'clang', 'bin')
|
||||
result.append(bootstrap_clang_path)
|
||||
|
||||
bootstrap_cbindgen_path = os.path.join(mozbuild_state_dir, 'cbindgen')
|
||||
result.append(bootstrap_cbindgen_path)
|
||||
|
||||
if vc_compiler_path:
|
||||
# We're going to alter PATH for good in windows.configure, but we also
|
||||
# need to do it for the valid_compiler() check below. This is only needed
|
||||
|
@ -16,6 +16,7 @@ unset RUSTC
|
||||
unset CARGO
|
||||
unset RUSTDOC
|
||||
unset RUSTFMT
|
||||
unset CBINDGEN
|
||||
unset MAKECAB
|
||||
unset TOOLCHAIN_PREFIX
|
||||
unset BINDGEN_CFLAGS
|
||||
|
@ -7,5 +7,6 @@ RUSTC="$TOOLTOOL_DIR/rustc/bin/rustc"
|
||||
CARGO="$TOOLTOOL_DIR/rustc/bin/cargo"
|
||||
RUSTDOC="$TOOLTOOL_DIR/rustc/bin/rustdoc"
|
||||
RUSTFMT="$TOOLTOOL_DIR/rustc/bin/rustfmt"
|
||||
CBINDGEN="$TOOLTOOL_DIR/cbindgen/cbindgen"
|
||||
|
||||
ac_add_options --enable-rust-simd
|
||||
|
@ -84,8 +84,10 @@ included_inclnames_to_ignore = set([
|
||||
'prtypes.h', # NSPR
|
||||
'selfhosted.out.h', # generated in $OBJDIR
|
||||
'shellmoduleloader.out.h', # generated in $OBJDIR
|
||||
'unicode/timezone.h', # ICU
|
||||
'unicode/basictz.h', # ICU
|
||||
'unicode/locid.h', # ICU
|
||||
'unicode/plurrule.h', # ICU
|
||||
'unicode/timezone.h', # ICU
|
||||
'unicode/ucal.h', # ICU
|
||||
'unicode/uchar.h', # ICU
|
||||
'unicode/uclean.h', # ICU
|
||||
@ -103,6 +105,7 @@ included_inclnames_to_ignore = set([
|
||||
'unicode/ureldatefmt.h', # ICU
|
||||
'unicode/ustring.h', # ICU
|
||||
'unicode/utypes.h', # ICU
|
||||
'unicode/uversion.h', # ICU
|
||||
'vtune/VTuneWrapper.h' # VTune
|
||||
])
|
||||
|
||||
|
BIN
config/external/icu/data/icudt62l.dat
vendored
BIN
config/external/icu/data/icudt62l.dat
vendored
Binary file not shown.
@ -1,9 +1,9 @@
|
||||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Version 82
|
||||
Version 83
|
||||
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-81...release-82
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-82...release-83
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
|
||||
|
@ -1406,6 +1406,12 @@ html .toggle-button.end.vertical svg {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.sources-list .tree .label .suffix {
|
||||
font-style: italic;
|
||||
font-size: 0.9em;
|
||||
color: var(--theme-comment);
|
||||
}
|
||||
|
||||
.sources-list .tree img.arrow.expanded {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
@ -25259,7 +25259,6 @@ const isControlFlow = node => isForStatement(node) || t.isWhileStatement(node) |
|
||||
const isAssignment = node => t.isVariableDeclarator(node) || t.isAssignmentExpression(node) || t.isAssignmentPattern(node);
|
||||
|
||||
const isImport = node => t.isImport(node) || t.isImportDeclaration(node);
|
||||
const isReturn = node => t.isReturnStatement(node);
|
||||
const isCall = node => t.isCallExpression(node) || t.isJSXElement(node);
|
||||
|
||||
const inStepExpression = parent => t.isArrayExpression(parent) || t.isObjectProperty(parent) || t.isCallExpression(parent) || t.isJSXElement(parent) || t.isSequenceExpression(parent);
|
||||
@ -25268,10 +25267,6 @@ const inExpression = (parent, grandParent) => inStepExpression(parent) || t.isJS
|
||||
|
||||
const isExport = node => t.isExportNamedDeclaration(node) || t.isExportDefaultDeclaration(node);
|
||||
|
||||
function getStartLine(node) {
|
||||
return node.loc.start.line;
|
||||
}
|
||||
|
||||
// Finds the first call item in a step expression so that we can step
|
||||
// to the beginning of the list and either step in or over. e.g. [], x(), { }
|
||||
function isFirstCall(node, parentNode, grandParentNode) {
|
||||
@ -25295,29 +25290,6 @@ function isFirstCall(node, parentNode, grandParentNode) {
|
||||
return children.find(child => isCall(child)) === node;
|
||||
}
|
||||
|
||||
// Check to see if the node is a step expression and if any of its children
|
||||
// expressions include calls. e.g. [ a() ], { a: a() }
|
||||
function hasCall(node) {
|
||||
let children = [];
|
||||
if (t.isArrayExpression(node)) {
|
||||
children = node.elements;
|
||||
}
|
||||
|
||||
if (t.isObjectExpression(node)) {
|
||||
children = node.properties.map(({ value }) => value);
|
||||
}
|
||||
|
||||
if (t.isSequenceExpression(node)) {
|
||||
children = node.expressions;
|
||||
}
|
||||
|
||||
if (t.isCallExpression(node)) {
|
||||
children = node.arguments;
|
||||
}
|
||||
|
||||
return children.find(child => isCall(child));
|
||||
}
|
||||
|
||||
function getPausePoints(sourceId) {
|
||||
const state = {};
|
||||
(0, _ast.traverseAst)(sourceId, { enter: onEnter }, state);
|
||||
@ -25332,7 +25304,7 @@ function onEnter(node, ancestors, state) {
|
||||
const grandParentNode = grandParent && grandParent.node;
|
||||
const startLocation = node.loc.start;
|
||||
|
||||
if (isImport(node) || t.isClassDeclaration(node) || isExport(node) || t.isDebuggerStatement(node) || t.isThrowStatement(node) || t.isBreakStatement(node) || t.isContinueStatement(node)) {
|
||||
if (isImport(node) || t.isClassDeclaration(node) || isExport(node) || t.isDebuggerStatement(node) || t.isThrowStatement(node) || t.isBreakStatement(node) || t.isContinueStatement(node) || t.isReturnStatement(node)) {
|
||||
return addStopPoint(state, startLocation);
|
||||
}
|
||||
|
||||
@ -25352,20 +25324,12 @@ function onEnter(node, ancestors, state) {
|
||||
return addEmptyPoint(state, startLocation);
|
||||
}
|
||||
|
||||
if (isReturn(node)) {
|
||||
// We do not want to pause at the return if the
|
||||
// argument is a call on the same line e.g. return foo()
|
||||
return addPoint(state, startLocation, !isCall(node.argument) || getStartLine(node) != getStartLine(node.argument));
|
||||
}
|
||||
|
||||
if (isAssignment(node)) {
|
||||
// step at assignments unless the right side is a call or default assignment
|
||||
// e.g. `var a = b()`, `a = b(c = 2)`, `a = [ b() ]`
|
||||
const value = node.right || node.init;
|
||||
// step at assignments unless the right side is a default assignment
|
||||
// e.g. `( b = 2 ) => {}`
|
||||
const defaultAssignment = t.isFunction(parentNode) && parent.key === "params";
|
||||
const includesCall = isCall(value) || hasCall(value);
|
||||
|
||||
return addPoint(state, startLocation, !includesCall && !defaultAssignment);
|
||||
return addPoint(state, startLocation, !defaultAssignment);
|
||||
}
|
||||
|
||||
if (isCall(node)) {
|
||||
|
@ -24,8 +24,6 @@ var _selectors = require("../selectors/index");
|
||||
|
||||
var _select = require("../actions/sources/select");
|
||||
|
||||
var _ui = require("../reducers/ui");
|
||||
|
||||
var _editor = require("../utils/editor/index");
|
||||
|
||||
var _fileSearch = require("./file-search");
|
||||
@ -224,7 +222,7 @@ function setProjectDirectoryRoot(newRoot) {
|
||||
dispatch,
|
||||
getState
|
||||
}) => {
|
||||
const curRoot = (0, _ui.getProjectDirectoryRoot)(getState());
|
||||
const curRoot = (0, _selectors.getProjectDirectoryRoot)(getState());
|
||||
|
||||
if (newRoot && curRoot) {
|
||||
const newRootArr = newRoot.replace(/\/+/g, "/").split("/");
|
||||
|
@ -204,7 +204,7 @@ class SourceTreeItem extends _react.Component {
|
||||
} = this.props;
|
||||
const suffix = hasMatchingGeneratedSource ? _react2.default.createElement("span", {
|
||||
className: "suffix"
|
||||
}, "[sm]") : null;
|
||||
}, L10N.getStr("sourceFooter.mappedSuffix")) : null;
|
||||
return _react2.default.createElement("div", {
|
||||
className: (0, _classnames2.default)("node", {
|
||||
focused
|
||||
|
@ -73,9 +73,9 @@ var _initialiseProps = function () {
|
||||
})), _react2.default.createElement("div", {
|
||||
id: `${item.id}-title`,
|
||||
className: "title"
|
||||
}, item.title), _react2.default.createElement("div", {
|
||||
}, item.title), item.subtitle != item.title ? _react2.default.createElement("div", {
|
||||
id: `${item.id}-subtitle`,
|
||||
className: "subtitle"
|
||||
}, item.subtitle));
|
||||
}, item.subtitle) : null);
|
||||
};
|
||||
};
|
@ -20,6 +20,8 @@ exports.getSourceInSources = getSourceInSources;
|
||||
exports.getSources = getSources;
|
||||
exports.getUrls = getUrls;
|
||||
exports.getSourceList = getSourceList;
|
||||
exports.getProjectDirectoryRoot = getProjectDirectoryRoot;
|
||||
exports.getRelativeSources = getRelativeSources;
|
||||
|
||||
var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"];
|
||||
|
||||
@ -41,8 +43,10 @@ function initialSourcesState() {
|
||||
return {
|
||||
sources: {},
|
||||
urls: {},
|
||||
relativeSources: {},
|
||||
selectedLocation: undefined,
|
||||
pendingSelectedLocation: _prefs.prefs.pendingSelectedLocation
|
||||
pendingSelectedLocation: _prefs.prefs.pendingSelectedLocation,
|
||||
projectDirectoryRoot: _prefs.prefs.projectDirectoryRoot
|
||||
};
|
||||
}
|
||||
|
||||
@ -137,6 +141,9 @@ function update(state = initialSourcesState(), action) {
|
||||
|
||||
break;
|
||||
|
||||
case "SET_PROJECT_DIRECTORY_ROOT":
|
||||
return recalculateRelativeSources(state, action.url);
|
||||
|
||||
case "NAVIGATE":
|
||||
const source = state.selectedLocation && state.sources[state.selectedLocation.sourceId];
|
||||
const url = source && source.url;
|
||||
@ -200,6 +207,8 @@ function updateSource(state, source) {
|
||||
const existingUrls = state.urls[source.url];
|
||||
const urls = existingUrls ? [...existingUrls, source.id] : [source.id];
|
||||
return { ...state,
|
||||
relativeSources: updateRelativeSource({ ...state.relativeSources
|
||||
}, updatedSource, state.projectDirectoryRoot),
|
||||
sources: { ...state.sources,
|
||||
[source.id]: updatedSource
|
||||
},
|
||||
@ -209,6 +218,27 @@ function updateSource(state, source) {
|
||||
};
|
||||
}
|
||||
|
||||
function updateRelativeSource(relativeSources, source, root) {
|
||||
if (!(0, _source.underRoot)(source, root)) {
|
||||
return relativeSources;
|
||||
}
|
||||
|
||||
const relativeSource = { ...source,
|
||||
relativeUrl: (0, _source.getRelativeUrl)(source, root)
|
||||
};
|
||||
relativeSources[source.id] = relativeSource;
|
||||
return relativeSources;
|
||||
}
|
||||
|
||||
function recalculateRelativeSources(state, root) {
|
||||
_prefs.prefs.projectDirectoryRoot = root;
|
||||
const relativeSources = Object.values(state.sources).reduce((sources, source) => updateRelativeSource(sources, source, root), {});
|
||||
return { ...state,
|
||||
projectDirectoryRoot: root,
|
||||
relativeSources
|
||||
};
|
||||
}
|
||||
|
||||
function updateBlackBoxList(url, isBlackBoxed) {
|
||||
const tabs = getBlackBoxList();
|
||||
const i = tabs.indexOf(url);
|
||||
@ -323,4 +353,13 @@ const getSelectedSource = exports.getSelectedSource = (0, _reselect.createSelect
|
||||
|
||||
return sources[selectedLocation.sourceId];
|
||||
});
|
||||
|
||||
function getProjectDirectoryRoot(state) {
|
||||
return state.sources.projectDirectoryRoot;
|
||||
}
|
||||
|
||||
function getRelativeSources(state) {
|
||||
return state.sources.relativeSources;
|
||||
}
|
||||
|
||||
exports.default = update;
|
@ -12,7 +12,6 @@ exports.getShownSource = getShownSource;
|
||||
exports.getPaneCollapse = getPaneCollapse;
|
||||
exports.getHighlightedLineRange = getHighlightedLineRange;
|
||||
exports.getConditionalPanelLine = getConditionalPanelLine;
|
||||
exports.getProjectDirectoryRoot = getProjectDirectoryRoot;
|
||||
exports.getOrientation = getOrientation;
|
||||
|
||||
var _makeRecord = require("../utils/makeRecord");
|
||||
@ -36,7 +35,6 @@ const createUIState = exports.createUIState = (0, _makeRecord2.default)({
|
||||
activeSearch: null,
|
||||
contextMenu: {},
|
||||
shownSource: null,
|
||||
projectDirectoryRoot: _prefs.prefs.projectDirectoryRoot,
|
||||
startPanelCollapsed: _prefs.prefs.startPanelCollapsed,
|
||||
endPanelCollapsed: _prefs.prefs.endPanelCollapsed,
|
||||
frameworkGroupingOn: _prefs.prefs.frameworkGroupingOn,
|
||||
@ -112,10 +110,6 @@ function update(state = createUIState(), action) {
|
||||
case "CLOSE_CONDITIONAL_PANEL":
|
||||
return state.set("conditionalPanelLine", null);
|
||||
|
||||
case "SET_PROJECT_DIRECTORY_ROOT":
|
||||
_prefs.prefs.projectDirectoryRoot = action.url;
|
||||
return state.set("projectDirectoryRoot", action.url);
|
||||
|
||||
case "SET_PRIMARY_PANE_TAB":
|
||||
return state.set("selectedPrimaryPaneTab", action.tabName);
|
||||
|
||||
@ -178,10 +172,6 @@ function getConditionalPanelLine(state) {
|
||||
return state.ui.get("conditionalPanelLine");
|
||||
}
|
||||
|
||||
function getProjectDirectoryRoot(state) {
|
||||
return state.ui.get("projectDirectoryRoot");
|
||||
}
|
||||
|
||||
function getOrientation(state) {
|
||||
return state.ui.get("orientation");
|
||||
}
|
||||
|
@ -1,52 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getRelativeSources = undefined;
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
var _sourcesTree = require("../utils/sources-tree/index");
|
||||
|
||||
var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"];
|
||||
|
||||
/* 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/>. */
|
||||
function getRelativeUrl(source, root) {
|
||||
const {
|
||||
group,
|
||||
path
|
||||
} = (0, _sourcesTree.getURL)(source);
|
||||
|
||||
if (!root) {
|
||||
return path;
|
||||
} // + 1 removes the leading "/"
|
||||
|
||||
|
||||
const url = group + path;
|
||||
return url.slice(url.indexOf(root) + root.length + 1);
|
||||
}
|
||||
|
||||
function formatSource(source, root) {
|
||||
// NOTE: Flow https://github.com/facebook/flow/issues/6342 issue
|
||||
return { ...source,
|
||||
relativeUrl: getRelativeUrl(source, root)
|
||||
};
|
||||
}
|
||||
|
||||
function underRoot(source, root) {
|
||||
return source.url && source.url.includes(root);
|
||||
}
|
||||
/*
|
||||
* Gets the sources that are below a project root
|
||||
*/
|
||||
|
||||
|
||||
const getRelativeSources = exports.getRelativeSources = (0, _reselect.createSelector)(_selectors.getSources, _selectors.getProjectDirectoryRoot, (sources, root) => {
|
||||
const relativeSources = (0, _lodash.chain)(sources).pickBy(source => underRoot(source, root)).mapValues(source => formatSource(source, root)).value();
|
||||
return relativeSources;
|
||||
});
|
@ -262,15 +262,6 @@ Object.defineProperty(exports, "getVisibleSelectedFrame", {
|
||||
}
|
||||
});
|
||||
|
||||
var _getRelativeSources = require("./getRelativeSources");
|
||||
|
||||
Object.defineProperty(exports, "getRelativeSources", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _getRelativeSources.getRelativeSources;
|
||||
}
|
||||
});
|
||||
|
||||
var _breakpointSources = require("./breakpointSources");
|
||||
|
||||
Object.defineProperty(exports, "getBreakpointSources", {
|
||||
|
@ -11,7 +11,6 @@ DevToolsModules(
|
||||
'breakpointAtLocation.js',
|
||||
'breakpointSources.js',
|
||||
'getCallStackFrames.js',
|
||||
'getRelativeSources.js',
|
||||
'inComponent.js',
|
||||
'index.js',
|
||||
'isSelectedFrameVisible.js',
|
||||
|
@ -32,6 +32,8 @@ exports.isLoaded = isLoaded;
|
||||
exports.isLoading = isLoading;
|
||||
exports.getTextAtPosition = getTextAtPosition;
|
||||
exports.getSourceClassnames = getSourceClassnames;
|
||||
exports.getRelativeUrl = getRelativeUrl;
|
||||
exports.underRoot = underRoot;
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
@ -497,4 +499,23 @@ function getSourceClassnames(source, sourceMetaData) {
|
||||
}
|
||||
|
||||
return sourceTypes[(0, _sourcesTree.getFileExtension)(source)] || defaultClassName;
|
||||
}
|
||||
|
||||
function getRelativeUrl(source, root) {
|
||||
const {
|
||||
group,
|
||||
path
|
||||
} = (0, _sourcesTree.getURL)(source);
|
||||
|
||||
if (!root) {
|
||||
return path;
|
||||
} // + 1 removes the leading "/"
|
||||
|
||||
|
||||
const url = group + path;
|
||||
return url.slice(url.indexOf(root) + root.length + 1);
|
||||
}
|
||||
|
||||
function underRoot(source, root) {
|
||||
return source.url && source.url.includes(root);
|
||||
}
|
@ -46,8 +46,9 @@ add_task(async function test() {
|
||||
|
||||
await testCase(dbg, {
|
||||
name: "sequences",
|
||||
count: 4,
|
||||
steps: [[23,2], [25,8], [31,4], [34,2], [37,0]]
|
||||
count: 5,
|
||||
steps: [[23,2], [25,8], [29,8], [31,4], [34,2], [37,0]]
|
||||
|
||||
});
|
||||
|
||||
await testCase(dbg, {
|
||||
|
@ -549,6 +549,10 @@ sourceFooter.mappedSource=(From %S)
|
||||
# with a mapped source. %S is replaced by the source map origin.
|
||||
sourceFooter.mappedSourceTooltip=(Source mapped from %S)
|
||||
|
||||
# LOCALIZATION NOTE (sourceFooter.mappedSuffix): Text associated
|
||||
# with a mapped source. Displays next to URLs in tree and tabs.
|
||||
sourceFooter.mappedSuffix=(mapped)
|
||||
|
||||
# LOCALIZATION NOTE (sourceFooter.codeCoverage): Text associated
|
||||
# with a code coverage button
|
||||
sourceFooter.codeCoverage=Code coverage
|
||||
|
@ -2913,11 +2913,11 @@ function getType(item) {
|
||||
}
|
||||
|
||||
function getValue(item) {
|
||||
if (item && item.contents && item.contents.hasOwnProperty("value")) {
|
||||
if (nodeHasValue(item)) {
|
||||
return item.contents.value;
|
||||
}
|
||||
|
||||
if (item && item.contents && item.contents.hasOwnProperty("getterValue")) {
|
||||
if (nodeHasGetterValue(item)) {
|
||||
return item.contents.getterValue;
|
||||
}
|
||||
|
||||
@ -2944,6 +2944,14 @@ function nodeHasChildren(item) {
|
||||
return Array.isArray(item.contents);
|
||||
}
|
||||
|
||||
function nodeHasValue(item) {
|
||||
return item && item.contents && item.contents.hasOwnProperty("value");
|
||||
}
|
||||
|
||||
function nodeHasGetterValue(item) {
|
||||
return item && item.contents && item.contents.hasOwnProperty("getterValue");
|
||||
}
|
||||
|
||||
function nodeIsObject(item) {
|
||||
const value = getValue(item);
|
||||
return value && value.type === "object";
|
||||
@ -3391,18 +3399,15 @@ function makeNodesForProperties(objProps, parent) {
|
||||
}
|
||||
|
||||
function setNodeFullText(loadedProps, node) {
|
||||
if (nodeHasFullText(node)) {
|
||||
if (nodeHasFullText(node) || !nodeIsLongString(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (nodeIsLongString(node)) {
|
||||
const {fullText} = loadedProps;
|
||||
|
||||
if (node.contents.value) {
|
||||
node.contents.value.fullText = fullText;
|
||||
} else if (node.contents.getterValue) {
|
||||
node.contents.getterValue.fullText = fullText;
|
||||
}
|
||||
const { fullText } = loadedProps;
|
||||
if (nodeHasValue(node)) {
|
||||
node.contents.value.fullText = fullText;
|
||||
} else if (nodeHasGetterValue(node)) {
|
||||
node.contents.getterValue.fullText = fullText;
|
||||
}
|
||||
|
||||
return node;
|
||||
|
@ -8503,11 +8503,12 @@ nsContentUtils::SendMouseEvent(const nsCOMPtr<nsIPresShell>& aPresShell,
|
||||
/* static */
|
||||
void
|
||||
nsContentUtils::FirePageHideEvent(nsIDocShellTreeItem* aItem,
|
||||
EventTarget* aChromeEventHandler)
|
||||
EventTarget* aChromeEventHandler,
|
||||
bool aOnlySystemGroup)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = aItem->GetDocument();
|
||||
NS_ASSERTION(doc, "What happened here?");
|
||||
doc->OnPageHide(true, aChromeEventHandler);
|
||||
doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup);
|
||||
|
||||
int32_t childCount = 0;
|
||||
aItem->GetChildCount(&childCount);
|
||||
@ -8519,7 +8520,7 @@ nsContentUtils::FirePageHideEvent(nsIDocShellTreeItem* aItem,
|
||||
|
||||
for (uint32_t i = 0; i < kids.Length(); ++i) {
|
||||
if (kids[i]) {
|
||||
FirePageHideEvent(kids[i], aChromeEventHandler);
|
||||
FirePageHideEvent(kids[i], aChromeEventHandler, aOnlySystemGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8532,7 +8533,8 @@ nsContentUtils::FirePageHideEvent(nsIDocShellTreeItem* aItem,
|
||||
void
|
||||
nsContentUtils::FirePageShowEvent(nsIDocShellTreeItem* aItem,
|
||||
EventTarget* aChromeEventHandler,
|
||||
bool aFireIfShowing)
|
||||
bool aFireIfShowing,
|
||||
bool aOnlySystemGroup)
|
||||
{
|
||||
int32_t childCount = 0;
|
||||
aItem->GetChildCount(&childCount);
|
||||
@ -8544,14 +8546,15 @@ nsContentUtils::FirePageShowEvent(nsIDocShellTreeItem* aItem,
|
||||
|
||||
for (uint32_t i = 0; i < kids.Length(); ++i) {
|
||||
if (kids[i]) {
|
||||
FirePageShowEvent(kids[i], aChromeEventHandler, aFireIfShowing);
|
||||
FirePageShowEvent(kids[i], aChromeEventHandler, aFireIfShowing,
|
||||
aOnlySystemGroup);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = aItem->GetDocument();
|
||||
NS_ASSERTION(doc, "What happened here?");
|
||||
if (doc->IsShowing() == aFireIfShowing) {
|
||||
doc->OnPageShow(true, aChromeEventHandler);
|
||||
doc->OnPageShow(true, aChromeEventHandler, aOnlySystemGroup);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2850,10 +2850,12 @@ public:
|
||||
|
||||
static void FirePageShowEvent(nsIDocShellTreeItem* aItem,
|
||||
mozilla::dom::EventTarget* aChromeEventHandler,
|
||||
bool aFireIfShowing);
|
||||
bool aFireIfShowing,
|
||||
bool aOnlySystemGroup = false);
|
||||
|
||||
static void FirePageHideEvent(nsIDocShellTreeItem* aItem,
|
||||
mozilla::dom::EventTarget* aChromeEventHandler);
|
||||
mozilla::dom::EventTarget* aChromeEventHandler,
|
||||
bool aOnlySystemGroup = false);
|
||||
|
||||
static already_AddRefed<nsPIWindowRoot> GetWindowRoot(nsIDocument* aDoc);
|
||||
|
||||
|
@ -8320,7 +8320,8 @@ nsIDocument::GetContentInThisDocument(nsIFrame* aFrame) const
|
||||
void
|
||||
nsIDocument::DispatchPageTransition(EventTarget* aDispatchTarget,
|
||||
const nsAString& aType,
|
||||
bool aPersisted)
|
||||
bool aPersisted,
|
||||
bool aOnlySystemGroup)
|
||||
{
|
||||
if (!aDispatchTarget) {
|
||||
return;
|
||||
@ -8339,6 +8340,9 @@ nsIDocument::DispatchPageTransition(EventTarget* aDispatchTarget,
|
||||
|
||||
event->SetTrusted(true);
|
||||
event->SetTarget(this);
|
||||
if (aOnlySystemGroup) {
|
||||
event->WidgetEventPtr()->mFlags.mOnlySystemGroupDispatchInContent = true;
|
||||
}
|
||||
EventDispatcher::DispatchDOMEvent(aDispatchTarget, nullptr, event,
|
||||
nullptr, nullptr);
|
||||
}
|
||||
@ -8352,7 +8356,8 @@ NotifyPageShow(nsIDocument* aDocument, void* aData)
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::OnPageShow(bool aPersisted, EventTarget* aDispatchStartTarget)
|
||||
nsIDocument::OnPageShow(bool aPersisted, EventTarget* aDispatchStartTarget,
|
||||
bool aOnlySystemGroup)
|
||||
{
|
||||
mVisible = true;
|
||||
|
||||
@ -8405,7 +8410,8 @@ nsIDocument::OnPageShow(bool aPersisted, EventTarget* aDispatchStartTarget)
|
||||
if (!target) {
|
||||
target = do_QueryInterface(GetWindow());
|
||||
}
|
||||
DispatchPageTransition(target, NS_LITERAL_STRING("pageshow"), aPersisted);
|
||||
DispatchPageTransition(target, NS_LITERAL_STRING("pageshow"), aPersisted,
|
||||
aOnlySystemGroup);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8452,7 +8458,8 @@ HasHttpScheme(nsIURI* aURI)
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::OnPageHide(bool aPersisted, EventTarget* aDispatchStartTarget)
|
||||
nsIDocument::OnPageHide(bool aPersisted, EventTarget* aDispatchStartTarget,
|
||||
bool aOnlySystemGroup)
|
||||
{
|
||||
if (IsTopLevelContentDocument() && GetDocGroup() &&
|
||||
Telemetry::CanRecordExtended()) {
|
||||
@ -8524,7 +8531,8 @@ nsIDocument::OnPageHide(bool aPersisted, EventTarget* aDispatchStartTarget)
|
||||
}
|
||||
{
|
||||
PageUnloadingEventTimeStamp timeStamp(this);
|
||||
DispatchPageTransition(target, NS_LITERAL_STRING("pagehide"), aPersisted);
|
||||
DispatchPageTransition(target, NS_LITERAL_STRING("pagehide"), aPersisted,
|
||||
aOnlySystemGroup);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1341,7 +1341,8 @@ protected:
|
||||
|
||||
void DispatchPageTransition(mozilla::dom::EventTarget* aDispatchTarget,
|
||||
const nsAString& aType,
|
||||
bool aPersisted);
|
||||
bool aPersisted,
|
||||
bool aOnlySystemGroup = false);
|
||||
|
||||
// Call this before the document does something that will unbind all content.
|
||||
// That will stop us from doing a lot of work as each element is removed.
|
||||
@ -2197,12 +2198,14 @@ public:
|
||||
* PageTransitionEvent.webidl for a description of the |aPersisted|
|
||||
* parameter. If aDispatchStartTarget is null, the pageshow event is
|
||||
* dispatched on the ScriptGlobalObject for this document, otherwise it's
|
||||
* dispatched on aDispatchStartTarget.
|
||||
* dispatched on aDispatchStartTarget. If |aOnlySystemGroup| is true, the
|
||||
* event is only dispatched to listeners in the system group.
|
||||
* Note: if aDispatchStartTarget isn't null, the showing state of the
|
||||
* document won't be altered.
|
||||
*/
|
||||
virtual void OnPageShow(bool aPersisted,
|
||||
mozilla::dom::EventTarget* aDispatchStartTarget);
|
||||
mozilla::dom::EventTarget* aDispatchStartTarget,
|
||||
bool aOnlySystemGroup = false);
|
||||
|
||||
/**
|
||||
* Notification that the page has been hidden, for documents which are loaded
|
||||
@ -2212,12 +2215,14 @@ public:
|
||||
* window. See PageTransitionEvent.webidl for a description of the
|
||||
* |aPersisted| parameter. If aDispatchStartTarget is null, the pagehide
|
||||
* event is dispatched on the ScriptGlobalObject for this document,
|
||||
* otherwise it's dispatched on aDispatchStartTarget.
|
||||
* otherwise it's dispatched on aDispatchStartTarget. If |aOnlySystemGroup| is
|
||||
* true, the event is only dispatched to listeners in the system group.
|
||||
* Note: if aDispatchStartTarget isn't null, the showing state of the
|
||||
* document won't be altered.
|
||||
*/
|
||||
void OnPageHide(bool aPersisted,
|
||||
mozilla::dom::EventTarget* aDispatchStartTarget);
|
||||
mozilla::dom::EventTarget* aDispatchStartTarget,
|
||||
bool aOnlySystemGroup = false);
|
||||
|
||||
/*
|
||||
* We record the set of links in the document that are relevant to
|
||||
|
@ -51,10 +51,12 @@ function prepareForVisibilityEvents(browser, expectedOrder) {
|
||||
|
||||
rmvHide = BrowserTestUtils.addContentEventListener(browser, "pagehide",
|
||||
() => eventListener("pagehide"),
|
||||
false, checkFn, false, false);
|
||||
{}, checkFn,
|
||||
false, false);
|
||||
rmvShow = BrowserTestUtils.addContentEventListener(browser, "pageshow",
|
||||
() => eventListener("pageshow"),
|
||||
false, checkFn, false, false);
|
||||
{}, checkFn,
|
||||
false, false);
|
||||
});
|
||||
}
|
||||
|
||||
@ -93,7 +95,7 @@ add_task(async function test_swap_frameloader_pagevisibility_events() {
|
||||
await ContentTask.spawn(emptyBrowser, {}, async() => {
|
||||
if (content.document.visibilityState === "hidden") {
|
||||
info("waiting for hidden emptyBrowser to pageshow");
|
||||
await ContentTaskUtils.waitForEvent(content, "pageshow");
|
||||
await ContentTaskUtils.waitForEvent(content, "pageshow", {});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -129,7 +129,7 @@ Test swapFrameLoaders with different frame types and remoteness
|
||||
});
|
||||
addEventListener("pagehide", function({ inFrameSwap }) {
|
||||
sendAsyncMessage("pagehide", inFrameSwap);
|
||||
});
|
||||
}, {mozSystemGroup: true});
|
||||
}`;
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "AnimationEvent.h"
|
||||
#include "BeforeUnloadEvent.h"
|
||||
@ -104,22 +105,23 @@ static bool IsEventTargetChrome(EventTarget* aEventTarget,
|
||||
}
|
||||
|
||||
nsIDocument* doc = nullptr;
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aEventTarget);
|
||||
if (node) {
|
||||
if (nsCOMPtr<nsINode> node = do_QueryInterface(aEventTarget)) {
|
||||
doc = node->OwnerDoc();
|
||||
} else {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aEventTarget);
|
||||
if (!window) {
|
||||
return false;
|
||||
}
|
||||
} else if (nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aEventTarget)) {
|
||||
doc = window->GetExtantDoc();
|
||||
}
|
||||
|
||||
// nsContentUtils::IsChromeDoc is null-safe.
|
||||
bool isChrome = nsContentUtils::IsChromeDoc(doc);
|
||||
if (aDocument && doc) {
|
||||
nsCOMPtr<nsIDocument> retVal = doc;
|
||||
retVal.swap(*aDocument);
|
||||
bool isChrome = false;
|
||||
if (doc) {
|
||||
isChrome = nsContentUtils::IsChromeDoc(doc);
|
||||
if (aDocument) {
|
||||
nsCOMPtr<nsIDocument> retVal = doc;
|
||||
retVal.swap(*aDocument);
|
||||
}
|
||||
} else if (nsCOMPtr<nsIScriptObjectPrincipal> sop =
|
||||
do_QueryInterface(aEventTarget->GetOwnerGlobal())) {
|
||||
isChrome = nsContentUtils::IsSystemPrincipal(sop->GetPrincipal());
|
||||
}
|
||||
return isChrome;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "mozilla/dom/nsCSPUtils.h"
|
||||
#include "mozilla/dom/nsCSPContext.h"
|
||||
#include "mozilla/dom/nsMixedContentBlocker.h"
|
||||
#include "mozilla/dom/CustomEvent.h"
|
||||
#include "mozilla/dom/HTMLFormControlsCollection.h"
|
||||
#include "mozilla/dom/HTMLFormElementBinding.h"
|
||||
#include "mozilla/Move.h"
|
||||
@ -1826,7 +1827,7 @@ HTMLFormElement::ForgetCurrentSubmission()
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLFormElement::CheckFormValidity(nsIMutableArray* aInvalidElements) const
|
||||
HTMLFormElement::CheckFormValidity(nsTArray<RefPtr<Element>>* aInvalidElements) const
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
@ -1854,7 +1855,7 @@ HTMLFormElement::CheckFormValidity(nsIMutableArray* aInvalidElements) const
|
||||
// Add all unhandled invalid controls to aInvalidElements if the caller
|
||||
// requested them.
|
||||
if (defaultAction && aInvalidElements) {
|
||||
aInvalidElements->AppendElement(ToSupports(sortedControls[i]));
|
||||
aInvalidElements->AppendElement(sortedControls[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1891,87 +1892,105 @@ HTMLFormElement::CheckValidFormSubmission()
|
||||
return true;
|
||||
}
|
||||
|
||||
AutoTArray<RefPtr<Element>, 32> invalidElements;
|
||||
if (CheckFormValidity(&invalidElements)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// For the first invalid submission, we should update element states.
|
||||
// We have to do that _before_ calling the observers so we are sure they
|
||||
// will not interfere (like focusing the element).
|
||||
if (!mEverTriedInvalidSubmit) {
|
||||
mEverTriedInvalidSubmit = true;
|
||||
|
||||
/*
|
||||
* We are going to call update states assuming elements want to
|
||||
* be notified because we can't know.
|
||||
* Submissions shouldn't happen during parsing so it _should_ be safe.
|
||||
*/
|
||||
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
|
||||
for (uint32_t i = 0, length = mControls->mElements.Length();
|
||||
i < length; ++i) {
|
||||
// Input elements can trigger a form submission and we want to
|
||||
// update the style in that case.
|
||||
if (mControls->mElements[i]->IsHTMLElement(nsGkAtoms::input) &&
|
||||
// We don't use nsContentUtils::IsFocusedContent here, because it
|
||||
// doesn't really do what we want for number controls: it's true
|
||||
// for the anonymous textnode inside, but not the number control
|
||||
// itself. We can use the focus state, though, because that gets
|
||||
// synced to the number control by the anonymous text control.
|
||||
mControls->mElements[i]->State().HasState(NS_EVENT_STATE_FOCUS)) {
|
||||
static_cast<HTMLInputElement*>(mControls->mElements[i])
|
||||
->UpdateValidityUIBits(true);
|
||||
}
|
||||
|
||||
mControls->mElements[i]->UpdateState(true);
|
||||
}
|
||||
|
||||
// Because of backward compatibility, <input type='image'> is not in
|
||||
// elements but can be invalid.
|
||||
// TODO: should probably be removed when bug 606491 will be fixed.
|
||||
for (uint32_t i = 0, length = mControls->mNotInElements.Length();
|
||||
i < length; ++i) {
|
||||
mControls->mNotInElements[i]->UpdateState(true);
|
||||
}
|
||||
}
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(GetOwnerGlobal())) {
|
||||
return false;
|
||||
}
|
||||
JS::Rooted<JS::Value> detail(jsapi.cx());
|
||||
if (!ToJSValue(jsapi.cx(), invalidElements, &detail)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<CustomEvent> event = NS_NewDOMCustomEvent(OwnerDoc(),
|
||||
nullptr, nullptr);
|
||||
event->InitCustomEvent(jsapi.cx(),
|
||||
NS_LITERAL_STRING("MozInvalidForm"),
|
||||
/* CanBubble */ true,
|
||||
/* Cancelable */ true,
|
||||
detail);
|
||||
event->SetTrusted(true);
|
||||
event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
|
||||
|
||||
DispatchEvent(*event);
|
||||
|
||||
bool result = !event->DefaultPrevented();
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> theEnum;
|
||||
nsresult rv = service->EnumerateObservers(NS_INVALIDFORMSUBMIT_SUBJECT,
|
||||
getter_AddRefs(theEnum));
|
||||
// Return true on error here because that's what we always did
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
NS_ENSURE_SUCCESS(rv, result);
|
||||
|
||||
bool hasObserver = false;
|
||||
rv = theEnum->HasMoreElements(&hasObserver);
|
||||
|
||||
// Do not check form validity if there is no observer for
|
||||
// NS_INVALIDFORMSUBMIT_SUBJECT.
|
||||
if (NS_SUCCEEDED(rv) && hasObserver) {
|
||||
nsCOMPtr<nsIMutableArray> invalidElements =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
// Return true on error here because that's what we always did
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
result = false;
|
||||
|
||||
if (!CheckFormValidity(invalidElements.get())) {
|
||||
// For the first invalid submission, we should update element states.
|
||||
// We have to do that _before_ calling the observers so we are sure they
|
||||
// will not interfere (like focusing the element).
|
||||
if (!mEverTriedInvalidSubmit) {
|
||||
mEverTriedInvalidSubmit = true;
|
||||
nsCOMPtr<nsISupports> inst;
|
||||
nsCOMPtr<nsIFormSubmitObserver> observer;
|
||||
bool more = true;
|
||||
while (NS_SUCCEEDED(theEnum->HasMoreElements(&more)) && more) {
|
||||
theEnum->GetNext(getter_AddRefs(inst));
|
||||
observer = do_QueryInterface(inst);
|
||||
|
||||
/*
|
||||
* We are going to call update states assuming elements want to
|
||||
* be notified because we can't know.
|
||||
* Submissions shouldn't happen during parsing so it _should_ be safe.
|
||||
*/
|
||||
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
|
||||
for (uint32_t i = 0, length = mControls->mElements.Length();
|
||||
i < length; ++i) {
|
||||
// Input elements can trigger a form submission and we want to
|
||||
// update the style in that case.
|
||||
if (mControls->mElements[i]->IsHTMLElement(nsGkAtoms::input) &&
|
||||
// We don't use nsContentUtils::IsFocusedContent here, because it
|
||||
// doesn't really do what we want for number controls: it's true
|
||||
// for the anonymous textnode inside, but not the number control
|
||||
// itself. We can use the focus state, though, because that gets
|
||||
// synced to the number control by the anonymous text control.
|
||||
mControls->mElements[i]->State().HasState(NS_EVENT_STATE_FOCUS)) {
|
||||
static_cast<HTMLInputElement*>(mControls->mElements[i])
|
||||
->UpdateValidityUIBits(true);
|
||||
}
|
||||
|
||||
mControls->mElements[i]->UpdateState(true);
|
||||
}
|
||||
|
||||
// Because of backward compatibility, <input type='image'> is not in
|
||||
// elements but can be invalid.
|
||||
// TODO: should probably be removed when bug 606491 will be fixed.
|
||||
for (uint32_t i = 0, length = mControls->mNotInElements.Length();
|
||||
i < length; ++i) {
|
||||
mControls->mNotInElements[i]->UpdateState(true);
|
||||
}
|
||||
if (observer) {
|
||||
observer->NotifyInvalidSubmit(this, invalidElements);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> inst;
|
||||
nsCOMPtr<nsIFormSubmitObserver> observer;
|
||||
bool more = true;
|
||||
while (NS_SUCCEEDED(theEnum->HasMoreElements(&more)) && more) {
|
||||
theEnum->GetNext(getter_AddRefs(inst));
|
||||
observer = do_QueryInterface(inst);
|
||||
|
||||
if (observer) {
|
||||
observer->NotifyInvalidSubmit(this,
|
||||
static_cast<nsIArray*>(invalidElements));
|
||||
}
|
||||
}
|
||||
|
||||
// The form is invalid. Observers have been alerted. Do not submit.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if (result) {
|
||||
NS_WARNING("There is no observer for \"invalidformsubmit\". \
|
||||
One should be implemented!");
|
||||
}
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -517,7 +517,7 @@ protected:
|
||||
*
|
||||
* @return Whether the form is currently valid.
|
||||
*/
|
||||
bool CheckFormValidity(nsIMutableArray* aInvalidElements) const;
|
||||
bool CheckFormValidity(nsTArray<RefPtr<Element>>* aInvalidElements) const;
|
||||
|
||||
// Clear the mImageNameLookupTable and mImageElements.
|
||||
void Clear();
|
||||
|
@ -304,7 +304,8 @@ ImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject)
|
||||
|
||||
void
|
||||
ImageDocument::OnPageShow(bool aPersisted,
|
||||
EventTarget* aDispatchStartTarget)
|
||||
EventTarget* aDispatchStartTarget,
|
||||
bool aOnlySystemGroup)
|
||||
{
|
||||
if (aPersisted) {
|
||||
mOriginalZoomLevel = IsSiteSpecific() ? 1.0 : GetZoomLevel();
|
||||
@ -315,7 +316,8 @@ ImageDocument::OnPageShow(bool aPersisted,
|
||||
RefPtr<ImageDocument> kungFuDeathGrip(this);
|
||||
UpdateSizeFromLayout();
|
||||
|
||||
MediaDocument::OnPageShow(aPersisted, aDispatchStartTarget);
|
||||
MediaDocument::OnPageShow(aPersisted, aDispatchStartTarget,
|
||||
aOnlySystemGroup);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -43,7 +43,8 @@ public:
|
||||
virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject) override;
|
||||
virtual void Destroy() override;
|
||||
virtual void OnPageShow(bool aPersisted,
|
||||
EventTarget* aDispatchStartTarget) override;
|
||||
EventTarget* aDispatchStartTarget,
|
||||
bool aOnlySystemGroup = false) override;
|
||||
|
||||
NS_DECL_NSIIMAGEDOCUMENT
|
||||
NS_DECL_IMGINOTIFICATIONOBSERVER
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "nsAString.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/CustomEvent.h"
|
||||
#include "mozilla/dom/HTMLFormElement.h"
|
||||
#include "mozilla/dom/HTMLFieldSetElement.h"
|
||||
#include "mozilla/dom/HTMLInputElement.h"
|
||||
@ -145,6 +146,30 @@ nsIConstraintValidation::ReportValidity()
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoTArray<RefPtr<Element>, 1> invalidElements;
|
||||
invalidElements.AppendElement(element);
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(element->GetOwnerGlobal())) {
|
||||
return false;
|
||||
}
|
||||
JS::Rooted<JS::Value> detail(jsapi.cx());
|
||||
if (!ToJSValue(jsapi.cx(), invalidElements, &detail)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<CustomEvent> event = NS_NewDOMCustomEvent(element->OwnerDoc(),
|
||||
nullptr, nullptr);
|
||||
event->InitCustomEvent(jsapi.cx(),
|
||||
NS_LITERAL_STRING("MozInvalidForm"),
|
||||
/* CanBubble */ true,
|
||||
/* Cancelable */ true,
|
||||
detail);
|
||||
event->SetTrusted(true);
|
||||
event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
|
||||
|
||||
element->DispatchEvent(*event);
|
||||
|
||||
nsCOMPtr<nsIObserverService> service =
|
||||
mozilla::services::GetObserverService();
|
||||
if (!service) {
|
||||
@ -162,10 +187,6 @@ nsIConstraintValidation::ReportValidity()
|
||||
bool hasObserver = false;
|
||||
rv = theEnum->HasMoreElements(&hasObserver);
|
||||
|
||||
nsCOMPtr<nsIMutableArray> invalidElements =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
invalidElements->AppendElement(element);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
nsCOMPtr<nsISupports> inst;
|
||||
nsCOMPtr<nsIFormSubmitObserver> observer;
|
||||
|
@ -11,6 +11,7 @@ interface nsIURI;
|
||||
interface nsIArray;
|
||||
|
||||
webidl HTMLFormElement;
|
||||
webidl Element;
|
||||
|
||||
[scriptable, uuid(867cb7e7-835d-408b-9788-d2834d284e03)]
|
||||
interface nsIFormSubmitObserver: nsISupports
|
||||
@ -18,7 +19,7 @@ interface nsIFormSubmitObserver: nsISupports
|
||||
void notify(in HTMLFormElement formNode, in mozIDOMWindow window, in nsIURI actionURL, out boolean cancelSubmit);
|
||||
|
||||
void notifyInvalidSubmit(in HTMLFormElement formNode,
|
||||
in nsIArray invalidElements);
|
||||
in Array<Element> invalidElements);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -47,18 +47,6 @@ function runTest()
|
||||
var formSubmitted = [ false, false ];
|
||||
var invalidHandled = false;
|
||||
|
||||
var os = SpecialPowers.Cc['@mozilla.org/observer-service;1']
|
||||
.getService(SpecialPowers.Ci.nsIObserverService);
|
||||
var observers = os.enumerateObservers("invalidformsubmit");
|
||||
|
||||
// The following test should not be done if there is no observer for
|
||||
// "invalidformsubmit" because the form submission will not be canceled in that
|
||||
// case.
|
||||
if (!observers.hasMoreElements()) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize
|
||||
document.forms[0].addEventListener('submit', function(aEvent) {
|
||||
formSubmitted[0] = true;
|
||||
|
@ -2377,12 +2377,12 @@ TabChild::RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext)
|
||||
|
||||
RefPtr<nsDocShell> docShell = static_cast<nsDocShell*>(ourDocShell.get());
|
||||
|
||||
nsCOMPtr<EventTarget> ourEventTarget = ourWindow->GetParentTarget();
|
||||
nsCOMPtr<EventTarget> ourEventTarget = nsGlobalWindowOuter::Cast(ourWindow);
|
||||
|
||||
docShell->SetInFrameSwap(true);
|
||||
|
||||
nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, false);
|
||||
nsContentUtils::FirePageHideEvent(ourDocShell, ourEventTarget);
|
||||
nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, false, true);
|
||||
nsContentUtils::FirePageHideEvent(ourDocShell, ourEventTarget, true);
|
||||
|
||||
// Owner content type may have changed, so store the possibly updated context
|
||||
// and notify others.
|
||||
@ -2410,7 +2410,7 @@ TabChild::RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext)
|
||||
RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
|
||||
}
|
||||
|
||||
nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, true);
|
||||
nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, true, true);
|
||||
|
||||
docShell->SetInFrameSwap(false);
|
||||
|
||||
|
@ -2756,14 +2756,7 @@ HTMLEditor::GetSelectedElement(Selection& aSelection,
|
||||
return selectedElement.forget();
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIContentIterator> iter =
|
||||
do_CreateInstance("@mozilla.org/content/post-content-iterator;1",
|
||||
&rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
|
||||
|
||||
bool found = !!selectedElement;
|
||||
const nsAtom* tagNameLookingFor = aTagName;
|
||||
@ -3016,28 +3009,24 @@ HTMLEditor::GetLinkedObjects(nsIArray** aNodeList)
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentIterator> iter =
|
||||
do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &rv);
|
||||
NS_ENSURE_TRUE(iter, NS_ERROR_NULL_POINTER);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
iter->Init(doc->GetRootElement());
|
||||
iter->Init(doc->GetRootElement());
|
||||
|
||||
// loop through the content iterator for each content node
|
||||
while (!iter->IsDone()) {
|
||||
nsCOMPtr<nsINode> node = iter->GetCurrentNode();
|
||||
if (node) {
|
||||
// Let nsURIRefObject make the hard decisions:
|
||||
nsCOMPtr<nsIURIRefObject> refObject;
|
||||
rv = NS_NewHTMLURIRefObject(getter_AddRefs(refObject), node);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nodes->AppendElement(refObject);
|
||||
}
|
||||
// loop through the content iterator for each content node
|
||||
while (!iter->IsDone()) {
|
||||
nsCOMPtr<nsINode> node = iter->GetCurrentNode();
|
||||
if (node) {
|
||||
// Let nsURIRefObject make the hard decisions:
|
||||
nsCOMPtr<nsIURIRefObject> refObject;
|
||||
rv = NS_NewHTMLURIRefObject(getter_AddRefs(refObject), node);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nodes->AppendElement(refObject);
|
||||
}
|
||||
iter->Next();
|
||||
}
|
||||
iter->Next();
|
||||
}
|
||||
|
||||
nodes.forget(aNodeList);
|
||||
@ -3275,14 +3264,7 @@ HTMLEditor::GetEmbeddedObjects(nsIArray** aNodeList)
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentIterator> iter =
|
||||
do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &rv);
|
||||
if (NS_WARN_IF(!iter)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
@ -3802,10 +3784,7 @@ HTMLEditor::CollapseAdjacentTextNodes(nsRange* aInRange)
|
||||
|
||||
|
||||
// build a list of editable text nodes
|
||||
nsresult rv = NS_ERROR_UNEXPECTED;
|
||||
nsCOMPtr<nsIContentIterator> iter =
|
||||
do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentSubtreeIterator();
|
||||
|
||||
iter->Init(aInRange);
|
||||
|
||||
@ -3830,7 +3809,7 @@ HTMLEditor::CollapseAdjacentTextNodes(nsRange* aInRange)
|
||||
// get the prev sibling of the right node, and see if its leftTextNode
|
||||
nsCOMPtr<nsINode> prevSibOfRightNode = rightTextNode->GetPreviousSibling();
|
||||
if (prevSibOfRightNode && prevSibOfRightNode == leftTextNode) {
|
||||
rv = JoinNodesWithTransaction(*leftTextNode, *rightTextNode);
|
||||
nsresult rv = JoinNodesWithTransaction(*leftTextNode, *rightTextNode);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1485,11 +1485,7 @@ TextEditor::GetTextLength(int32_t* aCount)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentIterator> iter =
|
||||
do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
|
||||
|
||||
uint32_t totalLength = 0;
|
||||
iter->Init(rootElement);
|
||||
|
@ -23,13 +23,13 @@ using namespace mozilla;
|
||||
|
||||
//------------------------------------------------------------
|
||||
nsFilteredContentIterator::nsFilteredContentIterator(nsComposeTxtSrvFilter* aFilter) :
|
||||
mIterator(NS_NewContentIterator()),
|
||||
mPreIterator(NS_NewPreContentIterator()),
|
||||
mFilter(aFilter),
|
||||
mDidSkip(false),
|
||||
mIsOutOfRange(false),
|
||||
mDirection(eDirNotSet)
|
||||
{
|
||||
mIterator = do_CreateInstance("@mozilla.org/content/post-content-iterator;1");
|
||||
mPreIterator = do_CreateInstance("@mozilla.org/content/pre-content-iterator;1");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
@ -130,7 +130,10 @@ ImageCacheKey::SchemeIs(const char* aScheme)
|
||||
/* static */ void*
|
||||
ImageCacheKey::GetSpecialCaseDocumentToken(nsIDocument* aDocument, nsIURI* aURI)
|
||||
{
|
||||
if (!aDocument) {
|
||||
// Cookie-averse documents can never have storage granted to them. Since they
|
||||
// may not have inner windows, they would require special handling below, so
|
||||
// just bail out early here.
|
||||
if (!aDocument || aDocument->IsCookieAverse()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -141,10 +144,11 @@ ImageCacheKey::GetSpecialCaseDocumentToken(nsIDocument* aDocument, nsIURI* aURI)
|
||||
return aDocument;
|
||||
}
|
||||
|
||||
// If we must disable the storage, we want to create a unique cache key for
|
||||
// this image.
|
||||
if (nsContentUtils::StorageDisabledByAntiTracking(aDocument, aURI)) {
|
||||
return aDocument;
|
||||
// If the window is 3rd party resource, let's see if first-party storage
|
||||
// access is granted for this image.
|
||||
if (nsContentUtils::IsTrackingResourceWindow(aDocument->GetInnerWindow())) {
|
||||
return nsContentUtils::StorageDisabledByAntiTracking(aDocument, aURI) ?
|
||||
aDocument : nullptr;
|
||||
}
|
||||
|
||||
// Another scenario is if this image is a 3rd party resource loaded by a
|
||||
@ -153,8 +157,7 @@ ImageCacheKey::GetSpecialCaseDocumentToken(nsIDocument* aDocument, nsIURI* aURI)
|
||||
// this point. The best approach here is to be conservative: if we are sure
|
||||
// that the permission is granted, let's return a nullptr. Otherwise, let's
|
||||
// make a unique image cache.
|
||||
if (!aDocument->IsCookieAverse() &&
|
||||
!AntiTrackingCommon::MaybeIsFirstPartyStorageAccessGrantedFor(aDocument->GetInnerWindow(),
|
||||
if (!AntiTrackingCommon::MaybeIsFirstPartyStorageAccessGrantedFor(aDocument->GetInnerWindow(),
|
||||
aURI)) {
|
||||
return aDocument;
|
||||
}
|
||||
|
7
intl/icu/GIT-INFO
Normal file
7
intl/icu/GIT-INFO
Normal file
@ -0,0 +1,7 @@
|
||||
commit 4a3ba8eee90ea1414d4f7ee36563e6c9b28fda96
|
||||
Author: Yoshito Umaoka <y.umaoka@gmail.com>
|
||||
Date: Wed Jun 20 05:34:56 2018 +0000
|
||||
|
||||
ICU-13823 Merged #13840 number parser memory overflow fix (r41541) to maint-62 for 62.1 GA.
|
||||
|
||||
X-SVN-Rev: 41542
|
@ -1,10 +0,0 @@
|
||||
Path: icu4c
|
||||
URL: https://ssl.icu-project.org/repos/icu/tags/release-62-1/icu4c
|
||||
Relative URL: ^/tags/release-62-1/icu4c
|
||||
Repository Root: https://ssl.icu-project.org/repos/icu
|
||||
Repository UUID: 251d0590-4201-4cf1-90de-194747b24ca1
|
||||
Node Kind: directory
|
||||
Last Changed Author: yoshito
|
||||
Last Changed Rev: 41542
|
||||
Last Changed Date: 2018-06-20 05:34:56 +0000 (Wed, 20 Jun 2018)
|
||||
|
@ -14,7 +14,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="de"/>
|
||||
</identity>
|
||||
</ldml>
|
||||
|
@ -12,7 +12,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="el"/>
|
||||
</identity>
|
||||
<special xmlns:icu="http://www.icu-project.org/">
|
||||
|
@ -12,7 +12,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="en"/>
|
||||
</identity>
|
||||
</ldml>
|
||||
|
@ -12,7 +12,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="en"/>
|
||||
<territory type="US"/>
|
||||
</identity>
|
||||
|
@ -12,7 +12,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="en"/>
|
||||
<territory type="US"/>
|
||||
<variant type="POSIX"/>
|
||||
|
@ -14,7 +14,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="es"/>
|
||||
</identity>
|
||||
</ldml>
|
||||
|
@ -12,7 +12,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="fi"/>
|
||||
</identity>
|
||||
<special xmlns:icu="http://www.icu-project.org/">
|
||||
|
@ -14,7 +14,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="fr"/>
|
||||
</identity>
|
||||
</ldml>
|
||||
|
@ -14,7 +14,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="it"/>
|
||||
</identity>
|
||||
</ldml>
|
||||
|
@ -12,7 +12,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="ja"/>
|
||||
</identity>
|
||||
<special xmlns:icu="http://www.icu-project.org/">
|
||||
|
@ -14,7 +14,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="pt"/>
|
||||
</identity>
|
||||
</ldml>
|
||||
|
@ -12,7 +12,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="root"/>
|
||||
</identity>
|
||||
<special xmlns:icu="http://www.icu-project.org/">
|
||||
|
@ -14,7 +14,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="ru"/>
|
||||
</identity>
|
||||
</ldml>
|
||||
|
@ -12,7 +12,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="root"/>
|
||||
</identity>
|
||||
<special xmlns:icu="http://www.icu-project.org/">
|
||||
|
@ -12,7 +12,7 @@
|
||||
>
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="root"/>
|
||||
</identity>
|
||||
</ldml>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<!DOCTYPE ldml SYSTEM "http://www.unicode.org/repos/cldr/trunk/common/dtd/ldml.dtd">
|
||||
<ldml>
|
||||
<identity>
|
||||
<version number="$Revision: 40674 $"/>
|
||||
<version number="$Revision$"/>
|
||||
<language type="be"/>
|
||||
</identity>
|
||||
<rbnf>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user