mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Merge autoland to mozilla-central. a=merge
This commit is contained in:
commit
dfdddff94d
@ -118,8 +118,9 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
|
||||
this.addressAddLink.textContent = this.dataset.addressAddLinkLabel;
|
||||
this.addressEditLink.textContent = this.dataset.addressEditLinkLabel;
|
||||
|
||||
// The back button is temporarily hidden(See Bug 1462461).
|
||||
this.backButton.hidden = !!page.onboardingWizard;
|
||||
// The next line needs an onboarding check since we don't set previousId
|
||||
// when navigating to add/edit directly from the summary page.
|
||||
this.backButton.hidden = !page.previousId && page.onboardingWizard;
|
||||
this.cancelButton.hidden = !page.onboardingWizard;
|
||||
|
||||
let record = {};
|
||||
@ -210,11 +211,39 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
|
||||
break;
|
||||
}
|
||||
case this.backButton: {
|
||||
this.requestStore.setState({
|
||||
let {
|
||||
page,
|
||||
request,
|
||||
"address-page": addressPage,
|
||||
"basic-card-page": basicCardPage,
|
||||
selectedShippingAddress,
|
||||
} = this.requestStore.getState();
|
||||
|
||||
let nextState = {
|
||||
page: {
|
||||
id: "payment-summary",
|
||||
id: page.previousId || "payment-summary",
|
||||
onboardingWizard: page.onboardingWizard,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
let addressPageState;
|
||||
if (page.onboardingWizard) {
|
||||
if (request.paymentOptions.requestShipping) {
|
||||
addressPageState = Object.assign({}, addressPage, {guid: selectedShippingAddress});
|
||||
} else {
|
||||
addressPageState =
|
||||
Object.assign({}, addressPage, {guid: basicCardPage.billingAddressGUID});
|
||||
}
|
||||
|
||||
let basicCardPageState = Object.assign({}, basicCardPage, {preserveFieldValues: true});
|
||||
|
||||
Object.assign(nextState, {
|
||||
"address-page": addressPageState,
|
||||
"basic-card-page": basicCardPageState,
|
||||
});
|
||||
}
|
||||
|
||||
this.requestStore.setState(nextState);
|
||||
break;
|
||||
}
|
||||
case this.saveButton: {
|
||||
|
@ -406,3 +406,98 @@ add_task(async function test_on_boarding_wizard_with_requestShipping_turned_off_
|
||||
cleanupFormAutofillStorage();
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_back_button_on_basic_card_page_during_onboarding() {
|
||||
await BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: BLANK_PAGE_URL,
|
||||
}, async browser => {
|
||||
cleanupFormAutofillStorage();
|
||||
|
||||
info("Opening the payment dialog");
|
||||
let {win, frame} =
|
||||
await setupPaymentDialog(browser, {
|
||||
methodData: [PTU.MethodData.basicCard],
|
||||
details: PTU.Details.total60USD,
|
||||
merchantTaskFn: PTU.ContentTasks.createAndShowRequest,
|
||||
});
|
||||
|
||||
await spawnPaymentDialogTask(frame, async function() {
|
||||
let {
|
||||
PaymentTestUtils: PTU,
|
||||
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
|
||||
|
||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||
return state.page.id == "address-page";
|
||||
}, "Address page is shown first if there are saved addresses during on boarding");
|
||||
|
||||
info("Checking if the address page has been rendered");
|
||||
let addressSaveButton = content.document.querySelector("address-form .save-button");
|
||||
ok(content.isVisible(addressSaveButton), "Address save button is rendered");
|
||||
|
||||
for (let [key, val] of Object.entries(PTU.Addresses.TimBL2)) {
|
||||
let field = content.document.getElementById(key);
|
||||
if (!field) {
|
||||
ok(false, `${key} field not found`);
|
||||
}
|
||||
field.value = val;
|
||||
ok(!field.disabled, `Field #${key} shouldn't be disabled`);
|
||||
}
|
||||
content.document.querySelector("address-form .save-button").click();
|
||||
|
||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||
return state.page.id == "basic-card-page";
|
||||
}, "Basic card page is shown next");
|
||||
|
||||
info("Checking if basic card page is rendered");
|
||||
let basicCardBackButton = content.document.querySelector("basic-card-form .back-button");
|
||||
ok(content.isVisible(basicCardBackButton), "Back button is visible on the basic card page");
|
||||
|
||||
info("Partially fill basic card form");
|
||||
let field = content.document.getElementById("cc-number");
|
||||
field.value = PTU.BasicCards.JohnDoe["cc-number"];
|
||||
|
||||
info("Clicking on the back button to edit address saved in the previous step");
|
||||
basicCardBackButton.click();
|
||||
|
||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||
return state.page.id == "address-page" &&
|
||||
state["address-page"].guid == state["basic-card-page"].billingAddressGUID;
|
||||
}, "Address page is shown again");
|
||||
|
||||
info("Checking if the address page has been rendered");
|
||||
addressSaveButton = content.document.querySelector("address-form .save-button");
|
||||
ok(content.isVisible(addressSaveButton), "Address save button is rendered");
|
||||
|
||||
info("Checking if the address saved in the last step is correctly loaded in the form");
|
||||
field = content.document.getElementById("given-name");
|
||||
ok(field.value, PTU.Addresses.TimBL2["given-name"],
|
||||
"Given name field value is correctly loaded");
|
||||
|
||||
info("Editing the address and saving again");
|
||||
field.value = "John";
|
||||
addressSaveButton.click();
|
||||
|
||||
info("Checking if the address was correctly edited");
|
||||
await PTU.DialogContentUtils.waitForState(content, (state) => {
|
||||
return state.page.id == "basic-card-page" &&
|
||||
// eslint-disable-next-line max-len
|
||||
state.savedAddresses[state["basic-card-page"].billingAddressGUID]["given-name"] == "John";
|
||||
}, "Address was correctly edited and saved");
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
info("Checking if the basic card form is now rendered and if the field values from before are preserved");
|
||||
let basicCardCancelButton = content.document.querySelector("basic-card-form .cancel-button");
|
||||
ok(content.isVisible(basicCardCancelButton),
|
||||
"Cancel button is visible on the basic card page");
|
||||
field = content.document.getElementById("cc-number");
|
||||
ok(field.value, PTU.BasicCards.JohnDoe["cc-number"], "Values in the form are preserved");
|
||||
});
|
||||
|
||||
info("Closing the payment dialog");
|
||||
spawnPaymentDialogTask(frame, PTU.DialogContentTasks.manuallyClickCancel);
|
||||
await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
|
||||
|
||||
cleanupFormAutofillStorage();
|
||||
});
|
||||
});
|
||||
|
@ -34,16 +34,13 @@ class AnimationItem extends Component {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isSelected: false,
|
||||
isSelected: this.isSelected(props),
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { animation } = this.props;
|
||||
|
||||
this.setState({
|
||||
isSelected: nextProps.selectedAnimation &&
|
||||
animation.actorID === nextProps.selectedAnimation.actorID
|
||||
isSelected: this.isSelected(nextProps),
|
||||
});
|
||||
}
|
||||
|
||||
@ -53,6 +50,11 @@ class AnimationItem extends Component {
|
||||
this.props.timeScale !== nextProps.timeScale;
|
||||
}
|
||||
|
||||
isSelected(props) {
|
||||
return props.selectedAnimation &&
|
||||
props.animation.actorID === props.selectedAnimation.actorID;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
animation,
|
||||
|
@ -48,8 +48,12 @@ const reducers = {
|
||||
},
|
||||
|
||||
[UPDATE_DETAIL_VISIBILITY](state, { detailVisibility }) {
|
||||
const selectedAnimation =
|
||||
detailVisibility ? state.selectedAnimation : null;
|
||||
|
||||
return Object.assign({}, state, {
|
||||
detailVisibility
|
||||
detailVisibility,
|
||||
selectedAnimation,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -26,6 +26,8 @@ support-files =
|
||||
[browser_animation_animation-detail_title.js]
|
||||
[browser_animation_animation-detail_visibility.js]
|
||||
[browser_animation_animation-list.js]
|
||||
[browser_animation_animation-list_one-animation-select.js]
|
||||
[browser_animation_animation-list_select.js]
|
||||
[browser_animation_animation-target.js]
|
||||
[browser_animation_animation-target_highlight.js]
|
||||
[browser_animation_animation-target_select.js]
|
||||
|
@ -38,17 +38,5 @@ add_task(async function() {
|
||||
is(itemEls.length, expectedNumber,
|
||||
`The number of animated-property-list should be ${ expectedNumber } ` +
|
||||
`at ${ targetClass }`);
|
||||
|
||||
if (itemEls.length < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
info("Checking the background color for " +
|
||||
`the animated property item at ${ targetClass }`);
|
||||
const evenColor = panel.ownerGlobal.getComputedStyle(itemEls[0]).backgroundColor;
|
||||
const oddColor = panel.ownerGlobal.getComputedStyle(itemEls[1]).backgroundColor;
|
||||
isnot(evenColor, oddColor,
|
||||
"Background color of an even animated property item " +
|
||||
"should be different from odd");
|
||||
}
|
||||
});
|
||||
|
@ -17,15 +17,6 @@ add_task(async function() {
|
||||
animationInspector.state.animations.length,
|
||||
"The number of animations displayed matches the number of animations");
|
||||
|
||||
info("Checking the background color for the animation list items");
|
||||
const animationItemEls = panel.querySelectorAll(".animation-list .animation-item");
|
||||
const evenColor =
|
||||
panel.ownerGlobal.getComputedStyle(animationItemEls[0]).backgroundColor;
|
||||
const oddColor =
|
||||
panel.ownerGlobal.getComputedStyle(animationItemEls[1]).backgroundColor;
|
||||
isnot(evenColor, oddColor,
|
||||
"Background color of an even animation should be different from odd");
|
||||
|
||||
info("Checking list and items existence after select a element which has an animation");
|
||||
await selectNodeAndWaitForAnimations(".animated", inspector);
|
||||
is(panel.querySelectorAll(".animation-list .animation-item").length, 1,
|
||||
|
@ -0,0 +1,22 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test whether the animation item has been selected from first time
|
||||
// if count of the animations is one.
|
||||
|
||||
add_task(async function() {
|
||||
await addTab(URL_ROOT + "doc_simple_animation.html");
|
||||
await removeAnimatedElementsExcept([".animated"]);
|
||||
const { panel } = await openAnimationInspector();
|
||||
|
||||
info("Checking whether an item element has been selected");
|
||||
is(panel.querySelector(".animation-item").classList.contains("selected"), true,
|
||||
"The animation item should have 'selected' class");
|
||||
|
||||
info("Checking whether the element will be unselected after closing the detail pane");
|
||||
clickOnDetailCloseButton(panel);
|
||||
is(panel.querySelector(".animation-item").classList.contains("selected"), false,
|
||||
"The animation item should not have 'selected' class");
|
||||
});
|
@ -0,0 +1,33 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test whether the animation items in the list were selectable.
|
||||
|
||||
add_task(async function() {
|
||||
await addTab(URL_ROOT + "doc_simple_animation.html");
|
||||
await removeAnimatedElementsExcept([".animated", ".long"]);
|
||||
const { animationInspector, panel } = await openAnimationInspector();
|
||||
|
||||
info("Checking whether 1st element will be selected");
|
||||
await clickOnAnimation(animationInspector, panel, 0);
|
||||
assertSelection(panel, [true, false]);
|
||||
|
||||
info("Checking whether 2nd element will be selected");
|
||||
await clickOnAnimation(animationInspector, panel, 1);
|
||||
assertSelection(panel, [false, true]);
|
||||
|
||||
info("Checking whether all elements will be unselected after closing the detail pane");
|
||||
clickOnDetailCloseButton(panel);
|
||||
assertSelection(panel, [false, false]);
|
||||
});
|
||||
|
||||
function assertSelection(panel, expectedResult) {
|
||||
panel.querySelectorAll(".animation-item").forEach((item, index) => {
|
||||
const shouldSelected = expectedResult[index];
|
||||
is(item.classList.contains("selected"), shouldSelected,
|
||||
`Animation item[${ index }] should ` +
|
||||
`${ shouldSelected ? "" : "not" } have 'selected' class`);
|
||||
});
|
||||
}
|
@ -5,31 +5,33 @@
|
||||
/* Animation-inspector specific theme variables */
|
||||
|
||||
:root {
|
||||
--animation-even-background-color: rgba(0, 0, 0, 0.05);
|
||||
--animation-item-hover-color: var(--grey-30-a40);
|
||||
--animation-item-selected-color: var(--grey-30-a90);
|
||||
--command-pick-image: url(chrome://devtools/skin/images/command-pick.svg);
|
||||
--cssanimation-color: var(--purple-50);
|
||||
--csstransition-color: var(--blue-55);
|
||||
--devtools-toolbar-height: 24px;
|
||||
--fast-track-image: url("images/animation-fast-track.svg");
|
||||
--fill-color-cssanimation: var(--theme-contrast-background);
|
||||
--fill-color-csstransition: var(--theme-highlight-blue);
|
||||
--fill-color-scriptanimation: var(--theme-graphs-green);
|
||||
--graph-height: 30px;
|
||||
--graph-right-offset: 10px;
|
||||
--keyframe-marker-shadow-color: #c4c4c4;
|
||||
--pause-image: url(chrome://devtools/skin/images/pause.svg);
|
||||
--progress-bar-color: #909090;
|
||||
--progress-bar-color: var(--grey-40);
|
||||
--resume-image: url(chrome://devtools/skin/images/play.svg);
|
||||
--rewind-image: url(chrome://devtools/skin/images/rewind.svg);
|
||||
--scrubber-color: #dd00a9;
|
||||
--scriptanimation-color: var(--green-60);
|
||||
--scrubber-color: var(--magenta-65);
|
||||
--sidebar-width: 200px;
|
||||
--stroke-color-cssanimation: var(--theme-highlight-lightorange);
|
||||
--stroke-color-csstransition: var(--theme-highlight-bluegrey);
|
||||
--stroke-color-scriptanimation: var(--theme-highlight-green);
|
||||
--tick-line-style: 0.5px solid rgba(128, 136, 144, 0.5);
|
||||
--tick-line-style: 0.5px solid var(--theme-splitter-color);
|
||||
}
|
||||
|
||||
:root.theme-dark {
|
||||
--animation-even-background-color: rgba(255, 255, 255, 0.05);
|
||||
--animation-item-hover-color: var(--grey-60-a50);
|
||||
--animation-item-selected-color: var(--grey-60);
|
||||
--csstransition-color: var(--blue-50);
|
||||
--keyframe-marker-shadow-color: #818181;
|
||||
--progress-bar-color: var(--grey-50);
|
||||
--scrubber-color: var(--magenta-50);
|
||||
}
|
||||
|
||||
/* Root element of animation inspector */
|
||||
@ -132,27 +134,27 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
|
||||
}
|
||||
|
||||
/* Animation Item */
|
||||
.animation-item:nth-child(2n+1) {
|
||||
background-color: var(--animation-even-background-color);
|
||||
}
|
||||
|
||||
.animation-item.cssanimation {
|
||||
--computed-timing-graph-color: var(--fill-color-cssanimation);
|
||||
--effect-timing-graph-color: var(--stroke-color-cssanimation);
|
||||
--graph-color: var(--cssanimation-color);
|
||||
--graph-opacity: 0.7;
|
||||
}
|
||||
|
||||
.animation-item.csstransition {
|
||||
--computed-timing-graph-color: var(--fill-color-csstransition);
|
||||
--effect-timing-graph-color: var(--stroke-color-csstransition);
|
||||
--graph-color: var(--csstransition-color);
|
||||
--graph-opacity: 0.8;
|
||||
}
|
||||
|
||||
.animation-item.scriptanimation {
|
||||
--computed-timing-graph-color: var(--fill-color-scriptanimation);
|
||||
--effect-timing-graph-color: var(--stroke-color-scriptanimation);
|
||||
--graph-color: var(--scriptanimation-color);
|
||||
--graph-opacity: 0.5;
|
||||
}
|
||||
|
||||
.animation-item:hover {
|
||||
background-color: var(--animation-item-hover-color);
|
||||
}
|
||||
|
||||
.animation-item.selected {
|
||||
background-color: var(--theme-selection-background-hover);
|
||||
background-color: var(--animation-item-selected-color);
|
||||
}
|
||||
|
||||
/* Animation Target */
|
||||
@ -191,7 +193,8 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
|
||||
cursor: pointer;
|
||||
grid-column: 2 / 3;
|
||||
height: var(--graph-height);
|
||||
padding-top: 5px;
|
||||
padding-bottom: 3px;
|
||||
padding-top: 3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@ -215,7 +218,8 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
|
||||
}
|
||||
|
||||
.animation-computed-timing-path path {
|
||||
fill: var(--computed-timing-graph-color);
|
||||
fill: var(--graph-color);
|
||||
fill-opacity: var(--graph-opacity);
|
||||
vector-effect: non-scaling-stroke;
|
||||
transform: scale(1, -1);
|
||||
}
|
||||
@ -226,7 +230,7 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
|
||||
|
||||
.animation-effect-timing-path path {
|
||||
fill: none;
|
||||
stroke: var(--effect-timing-graph-color);
|
||||
stroke: var(--graph-color);
|
||||
stroke-dasharray: 2px 2px;
|
||||
transform: scale(1, -1);
|
||||
vector-effect: non-scaling-stroke;
|
||||
@ -250,7 +254,7 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
|
||||
background-color: var(--theme-graphs-grey);
|
||||
height: 3px;
|
||||
position: absolute;
|
||||
top: calc(100% - 1.5px);
|
||||
bottom: 2px;
|
||||
}
|
||||
|
||||
.animation-delay-sign::before,
|
||||
@ -266,7 +270,7 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
|
||||
|
||||
.animation-delay-sign.fill,
|
||||
.animation-end-delay-sign.fill {
|
||||
background-color: var(--effect-timing-graph-color);
|
||||
background-color: var(--graph-color);
|
||||
}
|
||||
|
||||
.animation-delay-sign.negative::before {
|
||||
@ -305,7 +309,7 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
|
||||
|
||||
/* Animation Detail */
|
||||
.animation-detail-container {
|
||||
background-color: var(--theme-body-background);
|
||||
background-color: var(--theme-sidebar-background);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
@ -365,10 +369,6 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
|
||||
}
|
||||
|
||||
/* Animated Property Item */
|
||||
.animated-property-item:nth-child(2n+1) {
|
||||
background-color: var(--animation-even-background-color);
|
||||
}
|
||||
|
||||
.animated-property-item.unchanged {
|
||||
opacity: 0.6;
|
||||
}
|
||||
@ -388,15 +388,15 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
|
||||
}
|
||||
|
||||
.animated-property-list-container.cssanimation .animated-property-name.compositor {
|
||||
--fast-track-color: var(--stroke-color-cssanimation);
|
||||
--fast-track-color: var(--cssanimation-color);
|
||||
}
|
||||
|
||||
.animated-property-list-container.csstransition .animated-property-name.compositor {
|
||||
--fast-track-color: var(--stroke-color-csstransition);
|
||||
--fast-track-color: var(--csstransition-color);
|
||||
}
|
||||
|
||||
.animated-property-list-container.scriptanimation .animated-property-name.compositor {
|
||||
--fast-track-color: var(--stroke-color-scriptanimation);
|
||||
--fast-track-color: var(--scriptanimation-color);
|
||||
}
|
||||
|
||||
.animated-property-name.compositor span::before {
|
||||
@ -430,20 +430,21 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
|
||||
}
|
||||
|
||||
.keyframes-graph-path path {
|
||||
fill: #00b0bd88;
|
||||
stroke: #00b0bd;
|
||||
fill: var(--teal-60);
|
||||
fill-opacity: 0.5;
|
||||
stroke: var(--teal-70);
|
||||
vector-effect: non-scaling-stroke;
|
||||
transform: scale(1, -1);
|
||||
}
|
||||
|
||||
.keyframes-graph.opacity .keyframes-graph-path path {
|
||||
fill: #df00a988;
|
||||
stroke: #df00a9;
|
||||
fill: var(--magenta-50);
|
||||
stroke: var(--magenta-70);
|
||||
}
|
||||
|
||||
.keyframes-graph.transform .keyframes-graph-path path {
|
||||
fill: #ea800088;
|
||||
stroke: #ea8000;
|
||||
fill: var(--yellow-50);
|
||||
stroke: var(--yellow-60);
|
||||
}
|
||||
|
||||
.keyframes-graph-path .color-path path {
|
||||
@ -496,15 +497,15 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
|
||||
}
|
||||
|
||||
.animated-property-list-container.cssanimation .keyframe-marker-item {
|
||||
background-color: var(--fill-color-cssanimation);
|
||||
background-color: var(--cssanimation-color);
|
||||
}
|
||||
|
||||
.animated-property-list-container.csstransition .keyframe-marker-item {
|
||||
background-color: var(--fill-color-csstransition);
|
||||
background-color: var(--csstransition-color);
|
||||
}
|
||||
|
||||
.animated-property-list-container.scriptanimation .keyframe-marker-item {
|
||||
background-color: var(--fill-color-scriptanimation);
|
||||
background-color: var(--scriptanimation-color);
|
||||
}
|
||||
|
||||
/* Common Components */
|
||||
|
@ -213,8 +213,11 @@
|
||||
|
||||
/* Firefox Colors CSS Variables v1.0.3
|
||||
* Colors are taken from: https://github.com/FirefoxUX/design-tokens */
|
||||
--magenta-50: #ff1ad9;
|
||||
--magenta-65: #dd00a9;
|
||||
--magenta-70: #b5007f;
|
||||
|
||||
--purple-50: #9400ff;
|
||||
--purple-60: #8000d7;
|
||||
|
||||
--blue-40: #45a1ff;
|
||||
@ -223,20 +226,28 @@
|
||||
--blue-60: #0060df;
|
||||
--blue-70: #003eaa;
|
||||
|
||||
--teal-60: #00c8d7;
|
||||
--teal-70: #008ea4;
|
||||
|
||||
--red-70: #a4000f;
|
||||
|
||||
--green-50: #30e60b;
|
||||
--green-60: #12bc00;
|
||||
--green-70: #058b00;
|
||||
|
||||
--yellow-50: #ffe900;
|
||||
--yellow-60: #d7b600;
|
||||
--yellow-80: #715100;
|
||||
|
||||
--grey-10: #f9f9fa;
|
||||
--grey-20: #ededf0;
|
||||
--grey-30: #d7d7db;
|
||||
--grey-30-a40: rgba(215, 215, 219, 0.4);
|
||||
--grey-30-a90: rgba(215, 215, 219, 0.9);
|
||||
--grey-40: #b1b1b3;
|
||||
--grey-50: #737373;
|
||||
--grey-60: #4a4a4f;
|
||||
--grey-60-a50: rgba(74, 74, 79, 0.5);
|
||||
--grey-70: #38383d;
|
||||
--grey-80: #2a2a2e;
|
||||
--grey-90: #0c0c0d;
|
||||
|
@ -649,11 +649,12 @@ PaymentRequest::CanMakePayment(ErrorResult& aRv)
|
||||
}
|
||||
|
||||
if (mResultPromise) {
|
||||
// XXX This doesn't match the spec but does match Chromium.
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
|
||||
nsIGlobalObject* global = GetOwnerGlobal();
|
||||
ErrorResult result;
|
||||
RefPtr<Promise> promise = Promise::Create(global, result);
|
||||
if (result.Failed()) {
|
||||
@ -662,10 +663,7 @@ PaymentRequest::CanMakePayment(ErrorResult& aRv)
|
||||
}
|
||||
|
||||
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
|
||||
if (NS_WARN_IF(!manager)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(manager);
|
||||
nsresult rv = manager->CanMakePayment(this);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
promise->MaybeReject(NS_ERROR_FAILURE);
|
||||
@ -687,27 +685,28 @@ already_AddRefed<Promise>
|
||||
PaymentRequest::Show(const Optional<OwningNonNull<Promise>>& aDetailsPromise,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (mState != eCreated) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!EventStateManager::IsHandlingUserInput()) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
|
||||
ErrorResult result;
|
||||
RefPtr<Promise> promise = Promise::Create(global, result);
|
||||
if (result.Failed()) {
|
||||
mState = eClosed;
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
nsIGlobalObject* global = GetOwnerGlobal();
|
||||
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(global);
|
||||
MOZ_ASSERT(win);
|
||||
nsIDocument* doc = win->GetExtantDoc();
|
||||
if (!doc || !doc->IsCurrentActiveDocument()) {
|
||||
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
|
||||
if (NS_WARN_IF(!manager)) {
|
||||
if (mState != eCreated) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ErrorResult result;
|
||||
RefPtr<Promise> promise = Promise::Create(global, result);
|
||||
if (result.Failed()) {
|
||||
mState = eClosed;
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
@ -719,6 +718,8 @@ PaymentRequest::Show(const Optional<OwningNonNull<Promise>>& aDetailsPromise,
|
||||
mDeferredShow = true;
|
||||
}
|
||||
|
||||
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
|
||||
MOZ_ASSERT(manager);
|
||||
nsresult rv = manager->ShowPayment(this);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (rv == NS_ERROR_ABORT) {
|
||||
@ -794,11 +795,11 @@ PaymentRequest::Abort(ErrorResult& aRv)
|
||||
}
|
||||
|
||||
if (mAbortPromise) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
|
||||
nsIGlobalObject* global = GetOwnerGlobal();
|
||||
ErrorResult result;
|
||||
RefPtr<Promise> promise = Promise::Create(global, result);
|
||||
if (result.Failed()) {
|
||||
@ -807,12 +808,8 @@ PaymentRequest::Abort(ErrorResult& aRv)
|
||||
}
|
||||
|
||||
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
|
||||
if (NS_WARN_IF(!manager)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// It's possible for to call this between show and its promise resolving.
|
||||
MOZ_ASSERT(manager);
|
||||
// It's possible to be called between show and its promise resolving.
|
||||
nsresult rv = manager->AbortPayment(this, mDeferredShow);
|
||||
mDeferredShow = false;
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@ -1060,7 +1057,9 @@ PaymentRequest::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
||||
PaymentRequest::~PaymentRequest()
|
||||
{
|
||||
if (mIPC) {
|
||||
mIPC->MaybeDelete();
|
||||
// If we're being destroyed, the PaymentRequestManager isn't holding any
|
||||
// references to us and we can't be waiting for any replies.
|
||||
mIPC->MaybeDelete(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,6 +309,17 @@ PaymentRequestManager::NotifyRequestDone(PaymentRequest* aRequest)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PaymentRequestManager::RequestIPCOver(PaymentRequest* aRequest)
|
||||
{
|
||||
// This must only be called from ActorDestroy or if we're sure we won't
|
||||
// receive any more IPC for aRequest.
|
||||
mActivePayments.Remove(aRequest);
|
||||
if (aRequest == mShowingRequest) {
|
||||
mShowingRequest = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<PaymentRequestManager>
|
||||
PaymentRequestManager::GetSingleton()
|
||||
{
|
||||
|
@ -64,6 +64,10 @@ public:
|
||||
nsresult ChangeShippingOption(PaymentRequest* aRequest,
|
||||
const nsAString& aOption);
|
||||
|
||||
// Called to ensure that we don't "leak" aRequest if we shut down while it had
|
||||
// an active request to the parent.
|
||||
void RequestIPCOver(PaymentRequest* aRequest);
|
||||
|
||||
private:
|
||||
PaymentRequestManager() = default;
|
||||
~PaymentRequestManager()
|
||||
|
@ -86,34 +86,31 @@ void
|
||||
PaymentRequestChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
if (mRequest) {
|
||||
DetachFromRequest();
|
||||
DetachFromRequest(true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PaymentRequestChild::MaybeDelete()
|
||||
PaymentRequestChild::MaybeDelete(bool aCanBeInManager)
|
||||
{
|
||||
if (mRequest) {
|
||||
DetachFromRequest();
|
||||
DetachFromRequest(aCanBeInManager);
|
||||
Send__delete__(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PaymentRequestChild::SendRequestPayment(const IPCPaymentActionRequest& aAction)
|
||||
{
|
||||
return PPaymentRequestChild::SendRequestPayment(aAction);
|
||||
}
|
||||
|
||||
void
|
||||
PaymentRequestChild::DetachFromRequest()
|
||||
PaymentRequestChild::DetachFromRequest(bool aCanBeInManager)
|
||||
{
|
||||
MOZ_ASSERT(mRequest);
|
||||
nsAutoString id;
|
||||
mRequest->GetInternalId(id);
|
||||
|
||||
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
|
||||
MOZ_ASSERT(manager);
|
||||
if (aCanBeInManager) {
|
||||
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
|
||||
MOZ_ASSERT(manager);
|
||||
|
||||
RefPtr<PaymentRequest> request(mRequest);
|
||||
manager->RequestIPCOver(request);
|
||||
}
|
||||
|
||||
mRequest->SetIPC(nullptr);
|
||||
mRequest = nullptr;
|
||||
|
@ -19,7 +19,7 @@ class PaymentRequestChild final : public PPaymentRequestChild
|
||||
public:
|
||||
explicit PaymentRequestChild(PaymentRequest* aRequest);
|
||||
|
||||
void MaybeDelete();
|
||||
void MaybeDelete(bool aCanBeInManager);
|
||||
|
||||
nsresult RequestPayment(const IPCPaymentActionRequest& aAction);
|
||||
|
||||
@ -40,8 +40,8 @@ protected:
|
||||
private:
|
||||
~PaymentRequestChild() = default;
|
||||
|
||||
bool SendRequestPayment(const IPCPaymentActionRequest& aAction);
|
||||
void DetachFromRequest();
|
||||
void DetachFromRequest(bool aCanBeInManager);
|
||||
|
||||
PaymentRequest* MOZ_NON_OWNING_REF mRequest;
|
||||
};
|
||||
|
||||
|
@ -263,7 +263,6 @@ VRPose::VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState)
|
||||
: Pose(aParent)
|
||||
, mVRState(aState)
|
||||
{
|
||||
mFrameId = aState.inputFrameID;
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
@ -273,7 +272,6 @@ VRPose::VRPose(nsISupports* aParent)
|
||||
mVRState.inputFrameID = 0;
|
||||
mVRState.timestamp = 0.0;
|
||||
mVRState.flags = gfx::VRDisplayCapabilityFlags::Cap_None;
|
||||
mFrameId = 0;
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
|
@ -103,8 +103,6 @@ public:
|
||||
VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState);
|
||||
explicit VRPose(nsISupports* aParent);
|
||||
|
||||
uint64_t FrameID() const { return mFrameId; }
|
||||
|
||||
virtual void GetPosition(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv) override;
|
||||
@ -129,7 +127,6 @@ public:
|
||||
protected:
|
||||
~VRPose();
|
||||
|
||||
uint64_t mFrameId;
|
||||
gfx::VRHMDSensorState mVRState;
|
||||
};
|
||||
|
||||
|
@ -272,7 +272,6 @@ class MachCommands(MachCommandBase):
|
||||
help='Action callback name (Python function name)')
|
||||
def test_action_callback(self, **options):
|
||||
import taskgraph.parameters
|
||||
from taskgraph.util.taskcluster import get_task_definition
|
||||
import taskgraph.actions
|
||||
import yaml
|
||||
|
||||
@ -288,12 +287,6 @@ class MachCommands(MachCommandBase):
|
||||
try:
|
||||
self.setup_logging()
|
||||
task_id = options['task_id']
|
||||
if options['task']:
|
||||
task = load_data(options['task'])
|
||||
elif task_id:
|
||||
task = get_task_definition(task_id)
|
||||
else:
|
||||
task = None
|
||||
|
||||
if options['input']:
|
||||
input = load_data(options['input'])
|
||||
@ -308,7 +301,6 @@ class MachCommands(MachCommandBase):
|
||||
return taskgraph.actions.trigger_action_callback(
|
||||
task_group_id=options['task_group_id'],
|
||||
task_id=task_id,
|
||||
task=task,
|
||||
input=input,
|
||||
callback=options['callback'],
|
||||
parameters=parameters,
|
||||
|
@ -44,6 +44,23 @@ logger = logging.getLogger(__name__)
|
||||
'title': 'Depth',
|
||||
'description': ('The number of previous pushes before the current '
|
||||
'push to attempt to trigger this task on.')
|
||||
},
|
||||
'inclusive': {
|
||||
'type': 'boolean',
|
||||
'default': False,
|
||||
'title': 'Inclusive Range',
|
||||
'description': ('If true, the backfill will also retrigger the task '
|
||||
'on the selected push.')
|
||||
},
|
||||
'addGeckoProfile': {
|
||||
'type': 'boolean',
|
||||
'default': False,
|
||||
'title': 'Add Gecko Profile',
|
||||
'description': 'If true, appends --geckoProfile to mozharness options.'
|
||||
},
|
||||
'testPath': {
|
||||
'type': 'string',
|
||||
'title': 'Test Path',
|
||||
}
|
||||
},
|
||||
'additionalProperties': False
|
||||
@ -53,8 +70,9 @@ logger = logging.getLogger(__name__)
|
||||
def backfill_action(parameters, graph_config, input, task_group_id, task_id, task):
|
||||
label = task['metadata']['name']
|
||||
pushes = []
|
||||
depth = input.get('depth', 5)
|
||||
end_id = int(parameters['pushlog_id']) - 1
|
||||
inclusive_tweak = 1 if input.get('inclusive') else 0
|
||||
depth = input.get('depth', 5) + inclusive_tweak
|
||||
end_id = int(parameters['pushlog_id']) - (1 - inclusive_tweak)
|
||||
|
||||
while True:
|
||||
start_id = max(end_id - depth, 0)
|
||||
@ -90,8 +108,22 @@ def backfill_action(parameters, graph_config, input, task_group_id, task_id, tas
|
||||
continue
|
||||
|
||||
if label in full_task_graph.tasks.keys():
|
||||
create_tasks(
|
||||
[label], full_task_graph, label_to_taskid,
|
||||
push_params, push_decision_task_id, push)
|
||||
def modifier(task):
|
||||
if task.label != label:
|
||||
return task
|
||||
if input.get('addGeckoProfile'):
|
||||
mh = task.task['payload'].setdefault('env', {}) \
|
||||
.get('MOZHARNESS_OPTIONS', '')
|
||||
task.task['payload']['env']['MOZHARNESS_OPTIONS'] = mh + ' --geckoProfile'
|
||||
task.task['extra']['treeherder']['symbol'] += '-p'
|
||||
|
||||
if input.get('testPath'):
|
||||
env = task.task['payload'].setdefault('env', {})
|
||||
env['MOZHARNESS_TEST_PATHS'] = input.get('testPath')
|
||||
task.task['extra']['treeherder']['symbol'] += '-b'
|
||||
return task
|
||||
|
||||
create_tasks([label], full_task_graph, label_to_taskid,
|
||||
push_params, push_decision_task_id, push, modifier=modifier)
|
||||
else:
|
||||
logging.info('Could not find {} on {}. Skipping.'.format(label, push))
|
||||
|
@ -111,13 +111,18 @@ def update_parent(task, graph):
|
||||
|
||||
|
||||
def create_tasks(to_run, full_task_graph, label_to_taskid,
|
||||
params, decision_task_id=None, suffix=''):
|
||||
params, decision_task_id=None, suffix='', modifier=lambda t: t):
|
||||
"""Create new tasks. The task definition will have {relative-datestamp':
|
||||
'..'} rendered just like in a decision task. Action callbacks should use
|
||||
this function to create new tasks,
|
||||
allowing easy debugging with `mach taskgraph action-callback --test`.
|
||||
This builds up all required tasks to run in order to run the tasks requested.
|
||||
|
||||
Optionally this function takes a `modifier` function that is passed in each
|
||||
task before it is put into a new graph. It should return a valid task. Note
|
||||
that this is passed _all_ tasks in the graph, not just the set in to_run. You
|
||||
may want to skip modifying tasks not in your to_run list.
|
||||
|
||||
If you wish to create the tasks in a new group, leave out decision_task_id."""
|
||||
if suffix != '':
|
||||
suffix = '-{}'.format(suffix)
|
||||
@ -129,7 +134,7 @@ def create_tasks(to_run, full_task_graph, label_to_taskid,
|
||||
|
||||
target_graph = full_task_graph.graph.transitive_closure(to_run)
|
||||
target_task_graph = TaskGraph(
|
||||
{l: full_task_graph[l] for l in target_graph.nodes},
|
||||
{l: modifier(full_task_graph[l]) for l in target_graph.nodes},
|
||||
target_graph)
|
||||
target_task_graph.for_each_task(update_parent)
|
||||
optimized_task_graph, label_to_taskid = optimize_task_graph(target_task_graph,
|
||||
|
@ -21,7 +21,7 @@ class Task(object):
|
||||
|
||||
- task_id -- TaskCluster taskId under which this task will be created
|
||||
|
||||
This class is just a convenience wraper for the data type and managing
|
||||
This class is just a convenience wrapper for the data type and managing
|
||||
display, comparison, serialization, etc. It has no functionality of its own.
|
||||
"""
|
||||
def __init__(self, kind, label, attributes, task,
|
||||
|
@ -597463,7 +597463,7 @@
|
||||
"testharness"
|
||||
],
|
||||
"payment-request/payment-request-canmakepayment-method-manual.https.html": [
|
||||
"7531ea3b11f6e8de8cf71666b19861dbc5267cf7",
|
||||
"11df3310832e043e533a11245b012b9de1c0bb26",
|
||||
"manual"
|
||||
],
|
||||
"payment-request/payment-request-constructor-crash.https.html": [
|
||||
|
@ -126,9 +126,12 @@ promise_test(async t => {
|
||||
|
||||
function manualTest1(elem){
|
||||
elem.disabled = true;
|
||||
|
||||
// NB: request.show has to be called outside of promise_test to ensure the
|
||||
// user's click is still visible to PaymentRequest.show.
|
||||
const request = new PaymentRequest(defaultMethods, defaultDetails);
|
||||
const acceptPromise = request.show(); // Sets state to "interactive"
|
||||
promise_test(async t => {
|
||||
const request = new PaymentRequest(defaultMethods, defaultDetails);
|
||||
const acceptPromise = request.show(); // Sets state to "interactive"
|
||||
const canMakePaymentPromise = request.canMakePayment();
|
||||
try {
|
||||
const result = await canMakePaymentPromise;
|
||||
@ -148,11 +151,14 @@ function manualTest1(elem){
|
||||
}
|
||||
|
||||
function manualTest2(elem){
|
||||
elem.disabled = true;
|
||||
elem.disabled = true;
|
||||
|
||||
// See above for why it's important for these lines to be outside of
|
||||
// promise_test.
|
||||
const request = new PaymentRequest(defaultMethods, defaultDetails);
|
||||
const acceptPromise = request.show(); // The state is now "interactive"
|
||||
acceptPromise.catch(() => {}); // no-op, just to silence unhandled rejection in devtools.
|
||||
promise_test(async t => {
|
||||
const request = new PaymentRequest(defaultMethods, defaultDetails);
|
||||
const acceptPromise = request.show(); // The state is now "interactive"
|
||||
acceptPromise.catch(() => {}); // no-op, just to silence unhandled rejection in devtools.
|
||||
await request.abort(); // The state is now "closed"
|
||||
await promise_rejects(t, "InvalidStateError", request.canMakePayment());
|
||||
try {
|
||||
|
@ -24,6 +24,8 @@ def Libxul(name):
|
||||
|
||||
DELAYLOAD_DLLS += [
|
||||
'comdlg32.dll',
|
||||
'hid.dll',
|
||||
'msimg32.dll',
|
||||
'netapi32.dll',
|
||||
'secur32.dll',
|
||||
'wininet.dll',
|
||||
|
Loading…
Reference in New Issue
Block a user