mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
commit
e154ee4c06
@ -75,11 +75,6 @@ tasks:
|
|||||||
- $if: 'repository.project == "try"'
|
- $if: 'repository.project == "try"'
|
||||||
then:
|
then:
|
||||||
"notify.email.${ownerEmail}.on-completed"
|
"notify.email.${ownerEmail}.on-completed"
|
||||||
# BUG 1500166 Notify ciduty by email if a nightly hook fails
|
|
||||||
- "notify.email.ciduty+failedcron@mozilla.com.on-failed"
|
|
||||||
- "notify.email.ciduty+exceptioncron@mozilla.com.on-exception"
|
|
||||||
- "notify.email.sheriffs+failedcron@mozilla.com.on-failed"
|
|
||||||
- "notify.email.sheriffs+exceptioncron@mozilla.com.on-exception"
|
|
||||||
# These are the old index routes for the decision task.
|
# These are the old index routes for the decision task.
|
||||||
# They are still here so external tools that referenced them continue to work.
|
# They are still here so external tools that referenced them continue to work.
|
||||||
- "index.gecko.v2.${repository.project}.latest.firefox.decision"
|
- "index.gecko.v2.${repository.project}.latest.firefox.decision"
|
||||||
@ -96,6 +91,11 @@ tasks:
|
|||||||
- "index.gecko.v2.${repository.project}.pushlog-id.${push.pushlog_id}.decision-${cron.job_name}"
|
- "index.gecko.v2.${repository.project}.pushlog-id.${push.pushlog_id}.decision-${cron.job_name}"
|
||||||
# list each cron task on this revision, so actions can find them
|
# list each cron task on this revision, so actions can find them
|
||||||
- 'index.gecko.v2.${repository.project}.revision.${push.revision}.cron.${as_slugid("decision")}'
|
- 'index.gecko.v2.${repository.project}.revision.${push.revision}.cron.${as_slugid("decision")}'
|
||||||
|
# BUG 1500166 Notify ciduty by email if a nightly hook fails
|
||||||
|
- "notify.email.ciduty+failedcron@mozilla.com.on-failed"
|
||||||
|
- "notify.email.ciduty+exceptioncron@mozilla.com.on-exception"
|
||||||
|
- "notify.email.sheriffs+failedcron@mozilla.org.on-failed"
|
||||||
|
- "notify.email.sheriffs+exceptioncron@mozilla.org.on-exception"
|
||||||
# These are the old index routes for the decision task.
|
# These are the old index routes for the decision task.
|
||||||
- "index.gecko.v2.${repository.project}.latest.firefox.decision-${cron.job_name}"
|
- "index.gecko.v2.${repository.project}.latest.firefox.decision-${cron.job_name}"
|
||||||
|
|
||||||
|
@ -1515,8 +1515,11 @@ pref("browser.ping-centre.production.endpoint", "https://tiles.services.mozilla.
|
|||||||
// Enable GMP support in the addon manager.
|
// Enable GMP support in the addon manager.
|
||||||
pref("media.gmp-provider.enabled", true);
|
pref("media.gmp-provider.enabled", true);
|
||||||
|
|
||||||
// Enable blocking access to storage from tracking resources by default
|
// Enable blocking access to storage from tracking resources only in nightly
|
||||||
|
// and early beta. By default the value is 0: BEHAVIOR_ACCEPT
|
||||||
|
#ifdef NIGHTLY_OR_EARLY_BETA
|
||||||
pref("network.cookie.cookieBehavior", 4 /* BEHAVIOR_REJECT_TRACKER */);
|
pref("network.cookie.cookieBehavior", 4 /* BEHAVIOR_REJECT_TRACKER */);
|
||||||
|
#endif
|
||||||
|
|
||||||
pref("browser.contentblocking.allowlist.storage.enabled", true);
|
pref("browser.contentblocking.allowlist.storage.enabled", true);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import HandleEventMixin from "../mixins/HandleEventMixin.js";
|
||||||
import ObservedPropertiesMixin from "../mixins/ObservedPropertiesMixin.js";
|
import ObservedPropertiesMixin from "../mixins/ObservedPropertiesMixin.js";
|
||||||
import RichOption from "./rich-option.js";
|
import RichOption from "./rich-option.js";
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ import RichOption from "./rich-option.js";
|
|||||||
* Note: The only supported way to change the selected option is via the
|
* Note: The only supported way to change the selected option is via the
|
||||||
* `value` setter.
|
* `value` setter.
|
||||||
*/
|
*/
|
||||||
export default class RichSelect extends ObservedPropertiesMixin(HTMLElement) {
|
export default class RichSelect extends HandleEventMixin(ObservedPropertiesMixin(HTMLElement)) {
|
||||||
static get observedAttributes() {
|
static get observedAttributes() {
|
||||||
return [
|
return [
|
||||||
"disabled",
|
"disabled",
|
||||||
@ -57,15 +58,10 @@ export default class RichSelect extends ObservedPropertiesMixin(HTMLElement) {
|
|||||||
return this.popupBox.querySelector(`:scope > [value="${CSS.escape(value)}"]`);
|
return this.popupBox.querySelector(`:scope > [value="${CSS.escape(value)}"]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEvent(event) {
|
onChange(event) {
|
||||||
switch (event.type) {
|
|
||||||
case "change": {
|
|
||||||
// Since the render function depends on the popupBox's value, we need to
|
// Since the render function depends on the popupBox's value, we need to
|
||||||
// re-render if the value changes.
|
// re-render if the value changes.
|
||||||
this.render();
|
this.render();
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -7,6 +7,7 @@ import LabelledCheckbox from "../components/labelled-checkbox.js";
|
|||||||
import PaymentRequestPage from "../components/payment-request-page.js";
|
import PaymentRequestPage from "../components/payment-request-page.js";
|
||||||
import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
|
import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
|
||||||
import paymentRequest from "../paymentRequest.js";
|
import paymentRequest from "../paymentRequest.js";
|
||||||
|
import HandleEventMixin from "../mixins/HandleEventMixin.js";
|
||||||
/* import-globals-from ../unprivileged-fallbacks.js */
|
/* import-globals-from ../unprivileged-fallbacks.js */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,7 +21,8 @@ import paymentRequest from "../paymentRequest.js";
|
|||||||
* as it will be much easier to share the logic once we switch to Fluent.
|
* as it will be much easier to share the logic once we switch to Fluent.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class AddressForm extends PaymentStateSubscriberMixin(PaymentRequestPage) {
|
export default class AddressForm extends
|
||||||
|
HandleEventMixin(PaymentStateSubscriberMixin(PaymentRequestPage)) {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -216,32 +218,18 @@ export default class AddressForm extends PaymentStateSubscriberMixin(PaymentRequ
|
|||||||
this.updateSaveButtonState();
|
this.updateSaveButtonState();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEvent(event) {
|
onChange(event) {
|
||||||
switch (event.type) {
|
|
||||||
case "change": {
|
|
||||||
if (event.target.id == "country") {
|
if (event.target.id == "country") {
|
||||||
this.updateRequiredState();
|
this.updateRequiredState();
|
||||||
}
|
}
|
||||||
this.updateSaveButtonState();
|
this.updateSaveButtonState();
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "click": {
|
|
||||||
this.onClick(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "input": {
|
|
||||||
this.onInput(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "invalid": {
|
|
||||||
if (event.target instanceof HTMLFormElement) {
|
|
||||||
this.onInvalidForm(event);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onInvalid(event) {
|
||||||
|
if (event.target instanceof HTMLFormElement) {
|
||||||
|
this.onInvalidForm(event);
|
||||||
|
} else {
|
||||||
this.onInvalidField(event);
|
this.onInvalidField(event);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import AddressForm from "./address-form.js";
|
|||||||
import AddressOption from "../components/address-option.js";
|
import AddressOption from "../components/address-option.js";
|
||||||
import RichPicker from "./rich-picker.js";
|
import RichPicker from "./rich-picker.js";
|
||||||
import paymentRequest from "../paymentRequest.js";
|
import paymentRequest from "../paymentRequest.js";
|
||||||
|
import HandleEventMixin from "../mixins/HandleEventMixin.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <address-picker></address-picker>
|
* <address-picker></address-picker>
|
||||||
@ -13,7 +14,7 @@ import paymentRequest from "../paymentRequest.js";
|
|||||||
* <address-option> listening to savedAddresses & tempAddresses.
|
* <address-option> listening to savedAddresses & tempAddresses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class AddressPicker extends RichPicker {
|
export default class AddressPicker extends HandleEventMixin(RichPicker) {
|
||||||
static get pickerAttributes() {
|
static get pickerAttributes() {
|
||||||
return [
|
return [
|
||||||
"address-fields",
|
"address-fields",
|
||||||
@ -197,18 +198,6 @@ export default class AddressPicker extends RichPicker {
|
|||||||
}) || "";
|
}) || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEvent(event) {
|
|
||||||
switch (event.type) {
|
|
||||||
case "change": {
|
|
||||||
this.onChange(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "click": {
|
|
||||||
this.onClick(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange(event) {
|
onChange(event) {
|
||||||
let [selectedKey, selectedLeaf] = this.selectedStateKey.split("|");
|
let [selectedKey, selectedLeaf] = this.selectedStateKey.split("|");
|
||||||
if (!selectedKey) {
|
if (!selectedKey) {
|
||||||
|
@ -10,6 +10,7 @@ import LabelledCheckbox from "../components/labelled-checkbox.js";
|
|||||||
import PaymentRequestPage from "../components/payment-request-page.js";
|
import PaymentRequestPage from "../components/payment-request-page.js";
|
||||||
import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
|
import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
|
||||||
import paymentRequest from "../paymentRequest.js";
|
import paymentRequest from "../paymentRequest.js";
|
||||||
|
import HandleEventMixin from "../mixins/HandleEventMixin.js";
|
||||||
|
|
||||||
/* import-globals-from ../unprivileged-fallbacks.js */
|
/* import-globals-from ../unprivileged-fallbacks.js */
|
||||||
|
|
||||||
@ -20,7 +21,8 @@ import paymentRequest from "../paymentRequest.js";
|
|||||||
* as it will be much easier to share the logic once we switch to Fluent.
|
* as it will be much easier to share the logic once we switch to Fluent.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRequestPage) {
|
export default class BasicCardForm extends
|
||||||
|
HandleEventMixin(PaymentStateSubscriberMixin(PaymentRequestPage)) {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -268,32 +270,6 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRe
|
|||||||
this.updateSaveButtonState();
|
this.updateSaveButtonState();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEvent(event) {
|
|
||||||
switch (event.type) {
|
|
||||||
case "change": {
|
|
||||||
this.onChange(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "click": {
|
|
||||||
this.onClick(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "input": {
|
|
||||||
this.onInput(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "invalid": {
|
|
||||||
if (event.target instanceof HTMLFormElement) {
|
|
||||||
this.onInvalidForm(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onInvalidField(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange(evt) {
|
onChange(evt) {
|
||||||
let ccType = this.form.querySelector("#cc-type");
|
let ccType = this.form.querySelector("#cc-type");
|
||||||
this.cscInput.setAttribute("card-type", ccType.value);
|
this.cscInput.setAttribute("card-type", ccType.value);
|
||||||
@ -390,6 +366,14 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRe
|
|||||||
this.updateSaveButtonState();
|
this.updateSaveButtonState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onInvalid(event) {
|
||||||
|
if (event.target instanceof HTMLFormElement) {
|
||||||
|
this.onInvalidForm(event);
|
||||||
|
} else {
|
||||||
|
this.onInvalidField(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Event} event - "invalid" event
|
* @param {Event} event - "invalid" event
|
||||||
* Note: Keep this in-sync with the equivalent version in address-form.js
|
* Note: Keep this in-sync with the equivalent version in address-form.js
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import HandleEventMixin from "../mixins/HandleEventMixin.js";
|
||||||
import PaymentRequestPage from "../components/payment-request-page.js";
|
import PaymentRequestPage from "../components/payment-request-page.js";
|
||||||
import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
|
import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
|
||||||
import paymentRequest from "../paymentRequest.js";
|
import paymentRequest from "../paymentRequest.js";
|
||||||
@ -15,7 +16,8 @@ import paymentRequest from "../paymentRequest.js";
|
|||||||
* as it will be much easier to implement and share the logic once we switch to Fluent.
|
* as it will be much easier to implement and share the logic once we switch to Fluent.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class CompletionErrorPage extends PaymentStateSubscriberMixin(PaymentRequestPage) {
|
export default class CompletionErrorPage extends
|
||||||
|
HandleEventMixin(PaymentStateSubscriberMixin(PaymentRequestPage)) {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -80,8 +82,7 @@ export default class CompletionErrorPage extends PaymentStateSubscriberMixin(Pay
|
|||||||
this.suggestionsList.appendChild(suggestionsFragment);
|
this.suggestionsList.appendChild(suggestionsFragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEvent(event) {
|
onClick(event) {
|
||||||
if (event.type == "click") {
|
|
||||||
switch (event.target) {
|
switch (event.target) {
|
||||||
case this.doneButton: {
|
case this.doneButton: {
|
||||||
this.onDoneButtonClick(event);
|
this.onDoneButtonClick(event);
|
||||||
@ -92,7 +93,6 @@ export default class CompletionErrorPage extends PaymentStateSubscriberMixin(Pay
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
onDoneButtonClick(event) {
|
onDoneButtonClick(event) {
|
||||||
paymentRequest.closeDialog();
|
paymentRequest.closeDialog();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import HandleEventMixin from "../mixins/HandleEventMixin.js";
|
||||||
import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
|
import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
|
||||||
import paymentRequest from "../paymentRequest.js";
|
import paymentRequest from "../paymentRequest.js";
|
||||||
|
|
||||||
@ -26,7 +27,8 @@ import "./shipping-option-picker.js";
|
|||||||
* being exported once tests stop depending on it.
|
* being exported once tests stop depending on it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLElement) {
|
export default class PaymentDialog extends
|
||||||
|
HandleEventMixin(PaymentStateSubscriberMixin(HTMLElement)) {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this._template = document.getElementById("payment-dialog-template");
|
this._template = document.getElementById("payment-dialog-template");
|
||||||
@ -77,8 +79,7 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
|||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEvent(event) {
|
onClick(event) {
|
||||||
if (event.type == "click") {
|
|
||||||
switch (event.currentTarget) {
|
switch (event.currentTarget) {
|
||||||
case this._viewAllButton:
|
case this._viewAllButton:
|
||||||
let orderDetailsShowing = !this.requestStore.getState().orderDetailsShowing;
|
let orderDetailsShowing = !this.requestStore.getState().orderDetailsShowing;
|
||||||
@ -94,7 +95,6 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
openPreferences(event) {
|
openPreferences(event) {
|
||||||
paymentRequest.openPreferences();
|
paymentRequest.openPreferences();
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
|
|
||||||
import BasicCardOption from "../components/basic-card-option.js";
|
import BasicCardOption from "../components/basic-card-option.js";
|
||||||
import CscInput from "../components/csc-input.js";
|
import CscInput from "../components/csc-input.js";
|
||||||
|
import HandleEventMixin from "../mixins/HandleEventMixin.js";
|
||||||
import RichPicker from "./rich-picker.js";
|
import RichPicker from "./rich-picker.js";
|
||||||
import paymentRequest from "../paymentRequest.js";
|
import paymentRequest from "../paymentRequest.js";
|
||||||
|
|
||||||
/* import-globals-from ../unprivileged-fallbacks.js */
|
/* import-globals-from ../unprivileged-fallbacks.js */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,7 +16,7 @@ import paymentRequest from "../paymentRequest.js";
|
|||||||
* <basic-card-option> listening to savedBasicCards.
|
* <basic-card-option> listening to savedBasicCards.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class PaymentMethodPicker extends RichPicker {
|
export default class PaymentMethodPicker extends HandleEventMixin(RichPicker) {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.dropdown.setAttribute("option-type", "basic-card-option");
|
this.dropdown.setAttribute("option-type", "basic-card-option");
|
||||||
@ -115,18 +117,12 @@ export default class PaymentMethodPicker extends RichPicker {
|
|||||||
return this.getAttribute("selected-state-key");
|
return this.getAttribute("selected-state-key");
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEvent(event) {
|
onInput(event) {
|
||||||
switch (event.type) {
|
|
||||||
case "input":
|
|
||||||
case "change": {
|
|
||||||
this.onInputOrChange(event);
|
this.onInputOrChange(event);
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "click": {
|
|
||||||
this.onClick(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onChange(event) {
|
||||||
|
this.onInputOrChange(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
onInputOrChange({currentTarget}) {
|
onInputOrChange({currentTarget}) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
import RichPicker from "./rich-picker.js";
|
import RichPicker from "./rich-picker.js";
|
||||||
import ShippingOption from "../components/shipping-option.js";
|
import ShippingOption from "../components/shipping-option.js";
|
||||||
|
import HandleEventMixin from "../mixins/HandleEventMixin.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <shipping-option-picker></shipping-option-picker>
|
* <shipping-option-picker></shipping-option-picker>
|
||||||
@ -11,7 +12,7 @@ import ShippingOption from "../components/shipping-option.js";
|
|||||||
* <option> listening to shippingOptions.
|
* <option> listening to shippingOptions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class ShippingOptionPicker extends RichPicker {
|
export default class ShippingOptionPicker extends HandleEventMixin(RichPicker) {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.dropdown.setAttribute("option-type", "shipping-option");
|
this.dropdown.setAttribute("option-type", "shipping-option");
|
||||||
@ -55,15 +56,6 @@ export default class ShippingOptionPicker extends RichPicker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEvent(event) {
|
|
||||||
switch (event.type) {
|
|
||||||
case "change": {
|
|
||||||
this.onChange(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange(event) {
|
onChange(event) {
|
||||||
let selectedOptionId = this.dropdown.value;
|
let selectedOptionId = this.dropdown.value;
|
||||||
this.requestStore.setState({
|
this.requestStore.setState({
|
||||||
|
28
browser/components/payments/res/mixins/HandleEventMixin.js
Normal file
28
browser/components/payments/res/mixins/HandleEventMixin.js
Normal file
@ -0,0 +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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A mixin to forward events to on* methods if defined.
|
||||||
|
*
|
||||||
|
* @param {string} superclass The class to extend.
|
||||||
|
* @returns {class}
|
||||||
|
*/
|
||||||
|
export default function HandleEventMixin(superclass) {
|
||||||
|
return class HandleEvent extends superclass {
|
||||||
|
handleEvent(evt) {
|
||||||
|
function capitalize(str) {
|
||||||
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||||
|
}
|
||||||
|
if (super.handleEvent) {
|
||||||
|
super.handleEvent(evt);
|
||||||
|
}
|
||||||
|
// Check whether event name is a defined function in object.
|
||||||
|
let fn = "on" + capitalize(evt.type);
|
||||||
|
if (this[fn] && typeof(this[fn]) === "function") {
|
||||||
|
return this[fn](evt);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -232,7 +232,7 @@ add_task(async function testContentBlockingCustomCategory() {
|
|||||||
|
|
||||||
// Changing the NCB_PREF should necessarily set CAT_PREF to "custom"
|
// Changing the NCB_PREF should necessarily set CAT_PREF to "custom"
|
||||||
Services.prefs.setIntPref(NCB_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT);
|
Services.prefs.setIntPref(NCB_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT);
|
||||||
await TestUtils.waitForCondition(() => Services.prefs.prefHasUserValue(NCB_PREF));
|
await TestUtils.waitForCondition(() => !Services.prefs.prefHasUserValue(NCB_PREF));
|
||||||
is(Services.prefs.getStringPref(CAT_PREF), "custom", `${CAT_PREF} has been set to custom`);
|
is(Services.prefs.getStringPref(CAT_PREF), "custom", `${CAT_PREF} has been set to custom`);
|
||||||
|
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
|
@ -3,8 +3,5 @@
|
|||||||
ac_add_options --target=aarch64-windows-mingw32
|
ac_add_options --target=aarch64-windows-mingw32
|
||||||
ac_add_options --host=x86_64-pc-mingw32
|
ac_add_options --host=x86_64-pc-mingw32
|
||||||
|
|
||||||
# WebRTC is busted in various ways.
|
|
||||||
ac_add_options --disable-webrtc
|
|
||||||
|
|
||||||
# Accessibility doesn't work.
|
# Accessibility doesn't work.
|
||||||
ac_add_options --disable-accessibility
|
ac_add_options --disable-accessibility
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -25,6 +27,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -40,6 +44,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -55,6 +61,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -70,6 +78,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -85,6 +95,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -100,6 +112,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -115,6 +129,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -130,6 +146,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -145,6 +163,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -160,6 +180,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -175,6 +197,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -190,6 +214,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -205,6 +231,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -220,6 +248,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -235,6 +265,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -250,6 +282,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -265,6 +299,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -280,6 +316,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -295,6 +333,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -310,6 +350,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -325,6 +367,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -340,6 +384,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -355,6 +401,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -370,6 +418,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -385,6 +435,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -400,6 +452,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -415,6 +469,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -430,6 +486,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -445,6 +503,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -460,6 +520,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -475,6 +537,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -490,6 +554,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -505,6 +571,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -520,6 +588,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -535,6 +605,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -550,6 +622,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -565,6 +639,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -580,6 +656,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -595,6 +673,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -610,6 +690,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -625,6 +707,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -640,6 +724,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -655,6 +741,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -670,6 +758,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -685,6 +775,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -700,6 +792,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -715,6 +809,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -730,6 +826,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -745,6 +843,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -760,6 +860,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -775,6 +877,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -788,6 +892,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -810,6 +916,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -825,6 +933,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -840,6 +950,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -855,6 +967,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -870,6 +984,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -885,6 +1001,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -900,6 +1018,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -915,6 +1035,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -930,6 +1052,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -945,6 +1069,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -960,6 +1086,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -975,6 +1103,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -990,6 +1120,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1005,6 +1137,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1020,6 +1154,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1035,6 +1171,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1050,6 +1188,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1065,6 +1205,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1080,6 +1222,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1095,6 +1239,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1110,6 +1256,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1125,6 +1273,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1140,6 +1290,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1155,6 +1307,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1170,6 +1324,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1185,6 +1341,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1200,6 +1358,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1215,6 +1375,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1230,6 +1392,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1245,6 +1409,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1260,6 +1426,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1275,6 +1443,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1290,6 +1460,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1305,6 +1477,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1320,6 +1494,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1335,6 +1511,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1350,6 +1528,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1365,6 +1545,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1380,6 +1562,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1395,6 +1579,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1410,6 +1596,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1425,6 +1613,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1440,6 +1630,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1455,6 +1647,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1470,6 +1664,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1485,6 +1681,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1500,6 +1698,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1515,6 +1715,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1530,6 +1732,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1545,6 +1749,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
@ -1560,6 +1766,8 @@
|
|||||||
"win32",
|
"win32",
|
||||||
"win32-devedition",
|
"win32-devedition",
|
||||||
"win64",
|
"win64",
|
||||||
|
"win64-aarch64-msvc",
|
||||||
|
"win64-aarch64-msvc-devedition",
|
||||||
"win64-devedition"
|
"win64-devedition"
|
||||||
],
|
],
|
||||||
"revision": "default"
|
"revision": "default"
|
||||||
|
@ -4330,6 +4330,9 @@ bool Datastore::UpdateUsage(int64_t aDelta) {
|
|||||||
|
|
||||||
// Check internal LocalStorage origin limit.
|
// Check internal LocalStorage origin limit.
|
||||||
int64_t newUsage = mUsage + aDelta;
|
int64_t newUsage = mUsage + aDelta;
|
||||||
|
|
||||||
|
MOZ_ASSERT(newUsage >= 0);
|
||||||
|
|
||||||
if (newUsage > gOriginLimitKB * 1024) {
|
if (newUsage > gOriginLimitKB * 1024) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -5625,7 +5628,8 @@ nsresult PrepareDatastoreOp::DatabaseWork() {
|
|||||||
|
|
||||||
if (alreadyExisted) {
|
if (alreadyExisted) {
|
||||||
MOZ_ASSERT(gUsages);
|
MOZ_ASSERT(gUsages);
|
||||||
MOZ_ASSERT(gUsages->Get(mOrigin, &mUsage));
|
DebugOnly<bool> hasUsage = gUsages->Get(mOrigin, &mUsage);
|
||||||
|
MOZ_ASSERT(hasUsage);
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(mUsage == 0);
|
MOZ_ASSERT(mUsage == 0);
|
||||||
InitUsageForOrigin(mOrigin, mUsage);
|
InitUsageForOrigin(mOrigin, mUsage);
|
||||||
@ -6911,6 +6915,8 @@ nsresult QuotaClient::InitOrigin(PersistenceType aPersistenceType,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(usage >= 0);
|
||||||
|
|
||||||
InitUsageForOrigin(aOrigin, usage);
|
InitUsageForOrigin(aOrigin, usage);
|
||||||
|
|
||||||
aUsageInfo->AppendToDatabaseUsage(uint64_t(usage));
|
aUsageInfo->AppendToDatabaseUsage(uint64_t(usage));
|
||||||
@ -6988,6 +6994,7 @@ nsresult QuotaClient::GetUsageForOrigin(PersistenceType aPersistenceType,
|
|||||||
if (gUsages) {
|
if (gUsages) {
|
||||||
int64_t usage;
|
int64_t usage;
|
||||||
if (gUsages->Get(aOrigin, &usage)) {
|
if (gUsages->Get(aOrigin, &usage)) {
|
||||||
|
MOZ_ASSERT(usage >= 0);
|
||||||
aUsageInfo->AppendToDatabaseUsage(usage);
|
aUsageInfo->AppendToDatabaseUsage(usage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
66
dom/localstorage/test/unit/test_usage.js
Normal file
66
dom/localstorage/test/unit/test_usage.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
async function testSteps() {
|
||||||
|
const data = {};
|
||||||
|
data.key = "key1";
|
||||||
|
data.value = "value1";
|
||||||
|
data.usage = data.key.length + data.value.length;
|
||||||
|
|
||||||
|
const principal = getPrincipal("http://example.com");
|
||||||
|
|
||||||
|
info("Setting prefs");
|
||||||
|
|
||||||
|
Services.prefs.setBoolPref("dom.storage.next_gen", true);
|
||||||
|
|
||||||
|
info("Stage 1 - Testing usage after adding item");
|
||||||
|
|
||||||
|
info("Getting storage");
|
||||||
|
|
||||||
|
let storage = getLocalStorage(principal);
|
||||||
|
|
||||||
|
info("Adding item");
|
||||||
|
|
||||||
|
storage.setItem(data.key, data.value);
|
||||||
|
|
||||||
|
info("Resetting origin");
|
||||||
|
|
||||||
|
let request = resetOrigin(principal);
|
||||||
|
await requestFinished(request);
|
||||||
|
|
||||||
|
info("Getting usage");
|
||||||
|
|
||||||
|
request = getOriginUsage(principal);
|
||||||
|
await requestFinished(request);
|
||||||
|
|
||||||
|
is(request.result.usage, data.usage, "Correct usage");
|
||||||
|
|
||||||
|
info("Resetting");
|
||||||
|
|
||||||
|
request = reset();
|
||||||
|
await requestFinished(request);
|
||||||
|
|
||||||
|
info("Stage 2 - Testing usage after removing item");
|
||||||
|
|
||||||
|
info("Getting storage");
|
||||||
|
|
||||||
|
storage = getLocalStorage(principal);
|
||||||
|
|
||||||
|
info("Removing item");
|
||||||
|
|
||||||
|
storage.removeItem(data.key);
|
||||||
|
|
||||||
|
info("Resetting origin");
|
||||||
|
|
||||||
|
request = resetOrigin(principal);
|
||||||
|
await requestFinished(request);
|
||||||
|
|
||||||
|
info("Getting usage");
|
||||||
|
|
||||||
|
request = getOriginUsage(principal);
|
||||||
|
await requestFinished(request);
|
||||||
|
|
||||||
|
is(request.result.usage, 0, "Correct usage");
|
||||||
|
}
|
@ -29,3 +29,4 @@ run-sequentially = this test depends on a file produced by test_databaseShadowin
|
|||||||
[test_groupLimit.js]
|
[test_groupLimit.js]
|
||||||
[test_migration.js]
|
[test_migration.js]
|
||||||
[test_snapshotting.js]
|
[test_snapshotting.js]
|
||||||
|
[test_usage.js]
|
||||||
|
@ -40,6 +40,7 @@ run-if = nightly_build # Bug 1390737: Depends on the Nightly-only UI service
|
|||||||
skip-if = debug # Bug 1507251 - Leak
|
skip-if = debug # Bug 1507251 - Leak
|
||||||
[test_closePayment.html]
|
[test_closePayment.html]
|
||||||
[test_constructor.html]
|
[test_constructor.html]
|
||||||
|
skip-if = (os == "linux") # Bug 1514425
|
||||||
[test_currency_amount_validation.html]
|
[test_currency_amount_validation.html]
|
||||||
skip-if = (verify && debug)
|
skip-if = (verify && debug)
|
||||||
[test_payerDetails.html]
|
[test_payerDetails.html]
|
||||||
|
@ -25,7 +25,6 @@ namespace detail {
|
|||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
UniquePtr<BumpChunk> BumpChunk::newWithCapacity(size_t size) {
|
UniquePtr<BumpChunk> BumpChunk::newWithCapacity(size_t size) {
|
||||||
MOZ_DIAGNOSTIC_ASSERT(RoundUpPow2(size) == size);
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(size >= sizeof(BumpChunk));
|
MOZ_DIAGNOSTIC_ASSERT(size >= sizeof(BumpChunk));
|
||||||
void* mem = js_malloc(size);
|
void* mem = js_malloc(size);
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
@ -104,12 +103,17 @@ void LifoAlloc::reset(size_t defaultChunkSize) {
|
|||||||
while (!chunks_.empty()) {
|
while (!chunks_.empty()) {
|
||||||
chunks_.popFirst();
|
chunks_.popFirst();
|
||||||
}
|
}
|
||||||
|
while (!oversize_.empty()) {
|
||||||
|
chunks_.popFirst();
|
||||||
|
}
|
||||||
while (!unused_.empty()) {
|
while (!unused_.empty()) {
|
||||||
unused_.popFirst();
|
unused_.popFirst();
|
||||||
}
|
}
|
||||||
defaultChunkSize_ = defaultChunkSize;
|
defaultChunkSize_ = defaultChunkSize;
|
||||||
|
oversizeThreshold_ = defaultChunkSize;
|
||||||
markCount = 0;
|
markCount = 0;
|
||||||
curSize_ = 0;
|
curSize_ = 0;
|
||||||
|
oversizeSize_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LifoAlloc::freeAll() {
|
void LifoAlloc::freeAll() {
|
||||||
@ -117,6 +121,11 @@ void LifoAlloc::freeAll() {
|
|||||||
UniqueBumpChunk bc = chunks_.popFirst();
|
UniqueBumpChunk bc = chunks_.popFirst();
|
||||||
decrementCurSize(bc->computedSizeOfIncludingThis());
|
decrementCurSize(bc->computedSizeOfIncludingThis());
|
||||||
}
|
}
|
||||||
|
while (!oversize_.empty()) {
|
||||||
|
UniqueBumpChunk bc = oversize_.popFirst();
|
||||||
|
decrementCurSize(bc->computedSizeOfIncludingThis());
|
||||||
|
oversizeSize_ -= bc->computedSizeOfIncludingThis();
|
||||||
|
}
|
||||||
while (!unused_.empty()) {
|
while (!unused_.empty()) {
|
||||||
UniqueBumpChunk bc = unused_.popFirst();
|
UniqueBumpChunk bc = unused_.popFirst();
|
||||||
decrementCurSize(bc->computedSizeOfIncludingThis());
|
decrementCurSize(bc->computedSizeOfIncludingThis());
|
||||||
@ -125,9 +134,36 @@ void LifoAlloc::freeAll() {
|
|||||||
// Nb: maintaining curSize_ correctly isn't easy. Fortunately, this is an
|
// Nb: maintaining curSize_ correctly isn't easy. Fortunately, this is an
|
||||||
// excellent sanity check.
|
// excellent sanity check.
|
||||||
MOZ_ASSERT(curSize_ == 0);
|
MOZ_ASSERT(curSize_ == 0);
|
||||||
|
MOZ_ASSERT(oversizeSize_ == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
LifoAlloc::UniqueBumpChunk LifoAlloc::newChunkWithCapacity(size_t n) {
|
// Round at the same page granularity used by malloc.
|
||||||
|
static size_t MallocGoodSize(size_t aSize) {
|
||||||
|
#if defined(MOZ_MEMORY)
|
||||||
|
return malloc_good_size(aSize);
|
||||||
|
#else
|
||||||
|
return aSize;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Heuristic to choose the size of the next BumpChunk for small allocations.
|
||||||
|
// `start` is the size of the first chunk. `used` is the total size of all
|
||||||
|
// BumpChunks in this LifoAlloc so far.
|
||||||
|
static size_t NextSize(size_t start, size_t used) {
|
||||||
|
// Double the size, up to 1 MB.
|
||||||
|
const size_t mb = 1 * 1024 * 1024;
|
||||||
|
if (used < mb) {
|
||||||
|
return Max(start, used);
|
||||||
|
}
|
||||||
|
|
||||||
|
// After 1 MB, grow more gradually, to waste less memory.
|
||||||
|
// The sequence (in megabytes) begins:
|
||||||
|
// 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, ...
|
||||||
|
return JS_ROUNDUP(used / 8, mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
LifoAlloc::UniqueBumpChunk LifoAlloc::newChunkWithCapacity(size_t n,
|
||||||
|
bool oversize) {
|
||||||
MOZ_ASSERT(fallibleScope_,
|
MOZ_ASSERT(fallibleScope_,
|
||||||
"[OOM] Cannot allocate a new chunk in an infallible scope.");
|
"[OOM] Cannot allocate a new chunk in an infallible scope.");
|
||||||
|
|
||||||
@ -140,8 +176,11 @@ LifoAlloc::UniqueBumpChunk LifoAlloc::newChunkWithCapacity(size_t n) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(curSize_ >= oversizeSize_);
|
||||||
const size_t chunkSize =
|
const size_t chunkSize =
|
||||||
minSize > defaultChunkSize_ ? RoundUpPow2(minSize) : defaultChunkSize_;
|
(oversize || minSize > defaultChunkSize_)
|
||||||
|
? MallocGoodSize(minSize)
|
||||||
|
: NextSize(defaultChunkSize_, curSize_ - oversizeSize_);
|
||||||
|
|
||||||
// Create a new BumpChunk, and allocate space for it.
|
// Create a new BumpChunk, and allocate space for it.
|
||||||
UniqueBumpChunk result = detail::BumpChunk::newWithCapacity(chunkSize);
|
UniqueBumpChunk result = detail::BumpChunk::newWithCapacity(chunkSize);
|
||||||
@ -152,14 +191,13 @@ LifoAlloc::UniqueBumpChunk LifoAlloc::newChunkWithCapacity(size_t n) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LifoAlloc::getOrCreateChunk(size_t n) {
|
LifoAlloc::UniqueBumpChunk LifoAlloc::getOrCreateChunk(size_t n) {
|
||||||
// Look for existing unused BumpChunks to satisfy the request, and pick the
|
// Look for existing unused BumpChunks to satisfy the request, and pick the
|
||||||
// first one which is large enough, and move it into the list of used
|
// first one which is large enough, and move it into the list of used
|
||||||
// chunks.
|
// chunks.
|
||||||
if (!unused_.empty()) {
|
if (!unused_.empty()) {
|
||||||
if (unused_.begin()->canAlloc(n)) {
|
if (unused_.begin()->canAlloc(n)) {
|
||||||
chunks_.append(unused_.popFirst());
|
return unused_.popFirst();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BumpChunkList::Iterator e(unused_.end());
|
BumpChunkList::Iterator e(unused_.end());
|
||||||
@ -169,32 +207,171 @@ bool LifoAlloc::getOrCreateChunk(size_t n) {
|
|||||||
MOZ_ASSERT(elem->empty());
|
MOZ_ASSERT(elem->empty());
|
||||||
if (elem->canAlloc(n)) {
|
if (elem->canAlloc(n)) {
|
||||||
BumpChunkList temp = unused_.splitAfter(i.get());
|
BumpChunkList temp = unused_.splitAfter(i.get());
|
||||||
chunks_.append(temp.popFirst());
|
UniqueBumpChunk newChunk = temp.popFirst();
|
||||||
unused_.appendAll(std::move(temp));
|
unused_.appendAll(std::move(temp));
|
||||||
return true;
|
return newChunk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new BumpChunk with enough space for the next allocation.
|
// Allocate a new BumpChunk with enough space for the next allocation.
|
||||||
UniqueBumpChunk newChunk = newChunkWithCapacity(n);
|
UniqueBumpChunk newChunk = newChunkWithCapacity(n, false);
|
||||||
|
if (!newChunk) {
|
||||||
|
return newChunk;
|
||||||
|
}
|
||||||
|
size_t size = newChunk->computedSizeOfIncludingThis();
|
||||||
|
incrementCurSize(size);
|
||||||
|
return newChunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* LifoAlloc::allocImplColdPath(size_t n) {
|
||||||
|
void* result;
|
||||||
|
UniqueBumpChunk newChunk = getOrCreateChunk(n);
|
||||||
|
if (!newChunk) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since we just created a large enough chunk, this can't fail.
|
||||||
|
chunks_.append(std::move(newChunk));
|
||||||
|
result = chunks_.last()->tryAlloc(n);
|
||||||
|
MOZ_ASSERT(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* LifoAlloc::allocImplOversize(size_t n) {
|
||||||
|
void* result;
|
||||||
|
UniqueBumpChunk newChunk = newChunkWithCapacity(n, true);
|
||||||
|
if (!newChunk) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
incrementCurSize(newChunk->computedSizeOfIncludingThis());
|
||||||
|
oversizeSize_ += newChunk->computedSizeOfIncludingThis();
|
||||||
|
|
||||||
|
// Since we just created a large enough chunk, this can't fail.
|
||||||
|
oversize_.append(std::move(newChunk));
|
||||||
|
result = oversize_.last()->tryAlloc(n);
|
||||||
|
MOZ_ASSERT(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LifoAlloc::ensureUnusedApproximateColdPath(size_t n, size_t total) {
|
||||||
|
for (detail::BumpChunk& bc : unused_) {
|
||||||
|
total += bc.unused();
|
||||||
|
if (total >= n) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UniqueBumpChunk newChunk = newChunkWithCapacity(n, false);
|
||||||
if (!newChunk) {
|
if (!newChunk) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
size_t size = newChunk->computedSizeOfIncludingThis();
|
size_t size = newChunk->computedSizeOfIncludingThis();
|
||||||
chunks_.append(std::move(newChunk));
|
unused_.pushFront(std::move(newChunk));
|
||||||
incrementCurSize(size);
|
incrementCurSize(size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LifoAlloc::Mark LifoAlloc::mark() {
|
||||||
|
markCount++;
|
||||||
|
Mark res;
|
||||||
|
if (!chunks_.empty()) {
|
||||||
|
res.chunk = chunks_.last()->mark();
|
||||||
|
}
|
||||||
|
if (!oversize_.empty()) {
|
||||||
|
res.oversize = oversize_.last()->mark();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LifoAlloc::release(Mark mark) {
|
||||||
|
markCount--;
|
||||||
|
#ifdef DEBUG
|
||||||
|
auto assertIsContained = [](const detail::BumpChunk::Mark& m,
|
||||||
|
BumpChunkList& list) {
|
||||||
|
if (m.markedChunk()) {
|
||||||
|
bool contained = false;
|
||||||
|
for (const detail::BumpChunk& chunk : list) {
|
||||||
|
if (&chunk == m.markedChunk() && chunk.contains(m)) {
|
||||||
|
contained = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(contained);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
assertIsContained(mark.chunk, chunks_);
|
||||||
|
assertIsContained(mark.oversize, oversize_);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BumpChunkList released;
|
||||||
|
auto cutAtMark = [&released](const detail::BumpChunk::Mark& m,
|
||||||
|
BumpChunkList& list) {
|
||||||
|
// Move the blocks which are after the mark to the set released chunks.
|
||||||
|
if (!m.markedChunk()) {
|
||||||
|
released = std::move(list);
|
||||||
|
} else {
|
||||||
|
released = list.splitAfter(m.markedChunk());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release everything which follows the mark in the last chunk.
|
||||||
|
if (!list.empty()) {
|
||||||
|
list.last()->release(m);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Release the content of all the blocks which are after the marks, and keep
|
||||||
|
// blocks as unused.
|
||||||
|
cutAtMark(mark.chunk, chunks_);
|
||||||
|
for (detail::BumpChunk& bc : released) {
|
||||||
|
bc.release();
|
||||||
|
}
|
||||||
|
unused_.appendAll(std::move(released));
|
||||||
|
|
||||||
|
// Free the content of all the blocks which are after the marks.
|
||||||
|
cutAtMark(mark.oversize, oversize_);
|
||||||
|
while (!released.empty()) {
|
||||||
|
UniqueBumpChunk bc = released.popFirst();
|
||||||
|
decrementCurSize(bc->computedSizeOfIncludingThis());
|
||||||
|
oversizeSize_ -= bc->computedSizeOfIncludingThis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LifoAlloc::steal(LifoAlloc* other) {
|
||||||
|
MOZ_ASSERT(!other->markCount);
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(unused_.empty());
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(chunks_.empty());
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(oversize_.empty());
|
||||||
|
|
||||||
|
// Copy everything from |other| to |this| except for |peakSize_|, which
|
||||||
|
// requires some care.
|
||||||
|
chunks_ = std::move(other->chunks_);
|
||||||
|
oversize_ = std::move(other->oversize_);
|
||||||
|
unused_ = std::move(other->unused_);
|
||||||
|
markCount = other->markCount;
|
||||||
|
defaultChunkSize_ = other->defaultChunkSize_;
|
||||||
|
oversizeThreshold_ = other->oversizeThreshold_;
|
||||||
|
curSize_ = other->curSize_;
|
||||||
|
peakSize_ = Max(peakSize_, other->peakSize_);
|
||||||
|
oversizeSize_ = other->oversizeSize_;
|
||||||
|
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
||||||
|
fallibleScope_ = other->fallibleScope_;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
other->reset(defaultChunkSize_);
|
||||||
|
}
|
||||||
|
|
||||||
void LifoAlloc::transferFrom(LifoAlloc* other) {
|
void LifoAlloc::transferFrom(LifoAlloc* other) {
|
||||||
MOZ_ASSERT(!markCount);
|
MOZ_ASSERT(!markCount);
|
||||||
MOZ_ASSERT(!other->markCount);
|
MOZ_ASSERT(!other->markCount);
|
||||||
|
|
||||||
incrementCurSize(other->curSize_);
|
incrementCurSize(other->curSize_);
|
||||||
|
oversizeSize_ += other->oversizeSize_;
|
||||||
appendUnused(std::move(other->unused_));
|
appendUnused(std::move(other->unused_));
|
||||||
appendUsed(std::move(other->chunks_));
|
appendUsed(std::move(other->chunks_));
|
||||||
|
oversize_.appendAll(std::move(other->oversize_));
|
||||||
other->curSize_ = 0;
|
other->curSize_ = 0;
|
||||||
|
other->oversizeSize_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LifoAlloc::transferUnusedFrom(LifoAlloc* other) {
|
void LifoAlloc::transferUnusedFrom(LifoAlloc* other) {
|
||||||
@ -209,3 +386,29 @@ void LifoAlloc::transferUnusedFrom(LifoAlloc* other) {
|
|||||||
incrementCurSize(size);
|
incrementCurSize(size);
|
||||||
other->decrementCurSize(size);
|
other->decrementCurSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LIFO_CHUNK_PROTECT
|
||||||
|
void LifoAlloc::setReadOnly() {
|
||||||
|
for (detail::BumpChunk& bc : chunks_) {
|
||||||
|
bc.setReadOnly();
|
||||||
|
}
|
||||||
|
for (detail::BumpChunk& bc : oversize_) {
|
||||||
|
bc.setReadOnly();
|
||||||
|
}
|
||||||
|
for (detail::BumpChunk& bc : unused_) {
|
||||||
|
bc.setReadOnly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LifoAlloc::setReadWrite() {
|
||||||
|
for (detail::BumpChunk& bc : chunks_) {
|
||||||
|
bc.setReadWrite();
|
||||||
|
}
|
||||||
|
for (detail::BumpChunk& bc : oversize_) {
|
||||||
|
bc.setReadWrite();
|
||||||
|
}
|
||||||
|
for (detail::BumpChunk& bc : unused_) {
|
||||||
|
bc.setReadWrite();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -362,8 +362,7 @@ class BumpChunk : public SingleLinkedListElement<BumpChunk> {
|
|||||||
uint8_t* bump_;
|
uint8_t* bump_;
|
||||||
|
|
||||||
friend class BumpChunk;
|
friend class BumpChunk;
|
||||||
explicit Mark(BumpChunk* chunk, uint8_t* bump)
|
Mark(BumpChunk* chunk, uint8_t* bump) : chunk_(chunk), bump_(bump) {}
|
||||||
: chunk_(chunk), bump_(bump) {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Mark() : chunk_(nullptr), bump_(nullptr) {}
|
Mark() : chunk_(nullptr), bump_(nullptr) {}
|
||||||
@ -497,19 +496,29 @@ class LifoAlloc {
|
|||||||
using UniqueBumpChunk = js::UniquePtr<detail::BumpChunk>;
|
using UniqueBumpChunk = js::UniquePtr<detail::BumpChunk>;
|
||||||
using BumpChunkList = detail::SingleLinkedList<detail::BumpChunk>;
|
using BumpChunkList = detail::SingleLinkedList<detail::BumpChunk>;
|
||||||
|
|
||||||
// List of chunks containing allocated data. In the common case, the last
|
// List of chunks containing allocated data of size smaller than the default
|
||||||
// chunk of this list is always used to perform the allocations. When the
|
// chunk size. In the common case, the last chunk of this list is always
|
||||||
// allocation cannot be performed, we move a Chunk from the unused set to
|
// used to perform the allocations. When the allocation cannot be performed,
|
||||||
// the list of used chunks.
|
// we move a Chunk from the unused set to the list of used chunks.
|
||||||
BumpChunkList chunks_;
|
BumpChunkList chunks_;
|
||||||
|
|
||||||
|
// List of chunks containing allocated data where each allocation is larger
|
||||||
|
// than the oversize threshold. Each chunk contains exactly on allocation.
|
||||||
|
// This reduces wasted space in the normal chunk list.
|
||||||
|
//
|
||||||
|
// Oversize chunks are allocated on demand and freed as soon as they are
|
||||||
|
// released, instead of being pushed to the unused list.
|
||||||
|
BumpChunkList oversize_;
|
||||||
|
|
||||||
// Set of unused chunks, which can be reused for future allocations.
|
// Set of unused chunks, which can be reused for future allocations.
|
||||||
BumpChunkList unused_;
|
BumpChunkList unused_;
|
||||||
|
|
||||||
size_t markCount;
|
size_t markCount;
|
||||||
size_t defaultChunkSize_;
|
size_t defaultChunkSize_;
|
||||||
|
size_t oversizeThreshold_;
|
||||||
size_t curSize_;
|
size_t curSize_;
|
||||||
size_t peakSize_;
|
size_t peakSize_;
|
||||||
|
size_t oversizeSize_;
|
||||||
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
||||||
bool fallibleScope_;
|
bool fallibleScope_;
|
||||||
#endif
|
#endif
|
||||||
@ -518,11 +527,11 @@ class LifoAlloc {
|
|||||||
LifoAlloc(const LifoAlloc&) = delete;
|
LifoAlloc(const LifoAlloc&) = delete;
|
||||||
|
|
||||||
// Return a BumpChunk that can perform an allocation of at least size |n|.
|
// Return a BumpChunk that can perform an allocation of at least size |n|.
|
||||||
UniqueBumpChunk newChunkWithCapacity(size_t n);
|
UniqueBumpChunk newChunkWithCapacity(size_t n, bool oversize);
|
||||||
|
|
||||||
// Reuse or allocate a BumpChunk that can perform an allocation of at least
|
// Reuse or allocate a BumpChunk that can perform an allocation of at least
|
||||||
// size |n|, if successful it is placed at the end the list of |chunks_|.
|
// size |n|, if successful it is placed at the end the list of |chunks_|.
|
||||||
MOZ_MUST_USE bool getOrCreateChunk(size_t n);
|
UniqueBumpChunk getOrCreateChunk(size_t n);
|
||||||
|
|
||||||
void reset(size_t defaultChunkSize);
|
void reset(size_t defaultChunkSize);
|
||||||
|
|
||||||
@ -554,22 +563,26 @@ class LifoAlloc {
|
|||||||
curSize_ -= size;
|
curSize_ -= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* allocImplColdPath(size_t n);
|
||||||
|
void* allocImplOversize(size_t n);
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE
|
MOZ_ALWAYS_INLINE
|
||||||
void* allocImpl(size_t n) {
|
void* allocImpl(size_t n) {
|
||||||
void* result;
|
void* result;
|
||||||
if (!chunks_.empty() && (result = chunks_.last()->tryAlloc(n))) {
|
// Give oversized allocations their own chunk instead of wasting space
|
||||||
|
// due to fragmentation at the end of normal chunk.
|
||||||
|
if (MOZ_UNLIKELY(n > oversizeThreshold_)) {
|
||||||
|
return allocImplOversize(n);
|
||||||
|
}
|
||||||
|
if (MOZ_LIKELY(!chunks_.empty() &&
|
||||||
|
(result = chunks_.last()->tryAlloc(n)))) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
return allocImplColdPath(n);
|
||||||
if (!getOrCreateChunk(n)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we just created a large enough chunk, this can't fail.
|
// Check for space in unused chunks or allocate a new unused chunk.
|
||||||
result = chunks_.last()->tryAlloc(n);
|
MOZ_MUST_USE bool ensureUnusedApproximateColdPath(size_t n, size_t total);
|
||||||
MOZ_ASSERT(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LifoAlloc(size_t defaultChunkSize)
|
explicit LifoAlloc(size_t defaultChunkSize)
|
||||||
@ -582,27 +595,17 @@ class LifoAlloc {
|
|||||||
reset(defaultChunkSize);
|
reset(defaultChunkSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Steal allocated chunks from |other|.
|
// Set the threshold to allocate data in its own chunk outside the space for
|
||||||
void steal(LifoAlloc* other) {
|
// small allocations.
|
||||||
MOZ_ASSERT(!other->markCount);
|
void disableOversize() { oversizeThreshold_ = SIZE_MAX; }
|
||||||
MOZ_DIAGNOSTIC_ASSERT(unused_.empty());
|
void setOversizeThreshold(size_t oversizeThreshold) {
|
||||||
MOZ_DIAGNOSTIC_ASSERT(chunks_.empty());
|
MOZ_ASSERT(oversizeThreshold <= defaultChunkSize_);
|
||||||
|
oversizeThreshold_ = oversizeThreshold;
|
||||||
// Copy everything from |other| to |this| except for |peakSize_|, which
|
|
||||||
// requires some care.
|
|
||||||
chunks_ = std::move(other->chunks_);
|
|
||||||
unused_ = std::move(other->unused_);
|
|
||||||
markCount = other->markCount;
|
|
||||||
defaultChunkSize_ = other->defaultChunkSize_;
|
|
||||||
curSize_ = other->curSize_;
|
|
||||||
peakSize_ = Max(peakSize_, other->peakSize_);
|
|
||||||
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
|
||||||
fallibleScope_ = other->fallibleScope_;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
other->reset(defaultChunkSize_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Steal allocated chunks from |other|.
|
||||||
|
void steal(LifoAlloc* other);
|
||||||
|
|
||||||
// Append all chunks from |other|. They are removed from |other|.
|
// Append all chunks from |other|. They are removed from |other|.
|
||||||
void transferFrom(LifoAlloc* other);
|
void transferFrom(LifoAlloc* other);
|
||||||
|
|
||||||
@ -644,7 +647,7 @@ class LifoAlloc {
|
|||||||
JS_OOM_POSSIBLY_FAIL();
|
JS_OOM_POSSIBLY_FAIL();
|
||||||
MOZ_ASSERT(fallibleScope_);
|
MOZ_ASSERT(fallibleScope_);
|
||||||
|
|
||||||
detail::BumpChunk::Mark m = mark();
|
Mark m = mark();
|
||||||
void* result = allocImpl(n);
|
void* result = allocImpl(n);
|
||||||
if (!ensureUnusedApproximate(needed)) {
|
if (!ensureUnusedApproximate(needed)) {
|
||||||
release(m);
|
release(m);
|
||||||
@ -655,7 +658,7 @@ class LifoAlloc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
MOZ_ALWAYS_INLINE T* allocInSize(size_t n, Args&&... args) {
|
MOZ_ALWAYS_INLINE T* newWithSize(size_t n, Args&&... args) {
|
||||||
MOZ_ASSERT(n >= sizeof(T), "must request enough space to store a T");
|
MOZ_ASSERT(n >= sizeof(T), "must request enough space to store a T");
|
||||||
static_assert(alignof(T) <= detail::LIFO_ALLOC_ALIGN,
|
static_assert(alignof(T) <= detail::LIFO_ALLOC_ALIGN,
|
||||||
"LifoAlloc must provide enough alignment to store T");
|
"LifoAlloc must provide enough alignment to store T");
|
||||||
@ -691,21 +694,7 @@ class LifoAlloc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (detail::BumpChunk& bc : unused_) {
|
return ensureUnusedApproximateColdPath(n, total);
|
||||||
total += bc.unused();
|
|
||||||
if (total >= n) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UniqueBumpChunk newChunk = newChunkWithCapacity(n);
|
|
||||||
if (!newChunk) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
size_t size = newChunk->computedSizeOfIncludingThis();
|
|
||||||
unused_.pushFront(std::move(newChunk));
|
|
||||||
incrementCurSize(size);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE
|
MOZ_ALWAYS_INLINE
|
||||||
@ -756,38 +745,13 @@ class LifoAlloc {
|
|||||||
return static_cast<T*>(alloc(bytes));
|
return static_cast<T*>(alloc(bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
using Mark = detail::BumpChunk::Mark;
|
class Mark {
|
||||||
|
friend class LifoAlloc;
|
||||||
Mark mark() {
|
detail::BumpChunk::Mark chunk;
|
||||||
markCount++;
|
detail::BumpChunk::Mark oversize;
|
||||||
if (chunks_.empty()) {
|
};
|
||||||
return Mark();
|
Mark mark();
|
||||||
}
|
void release(Mark mark);
|
||||||
return chunks_.last()->mark();
|
|
||||||
}
|
|
||||||
|
|
||||||
void release(Mark mark) {
|
|
||||||
markCount--;
|
|
||||||
|
|
||||||
// Move the blocks which are after the mark to the set of unused chunks.
|
|
||||||
BumpChunkList released;
|
|
||||||
if (!mark.markedChunk()) {
|
|
||||||
released = std::move(chunks_);
|
|
||||||
} else {
|
|
||||||
released = chunks_.splitAfter(mark.markedChunk());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release the content of all the blocks which are after the marks.
|
|
||||||
for (detail::BumpChunk& bc : released) {
|
|
||||||
bc.release();
|
|
||||||
}
|
|
||||||
unused_.appendAll(std::move(released));
|
|
||||||
|
|
||||||
// Release everything which follows the mark in the last chunk.
|
|
||||||
if (!chunks_.empty()) {
|
|
||||||
chunks_.last()->release(mark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void cancelMark(Mark mark) { markCount--; }
|
void cancelMark(Mark mark) { markCount--; }
|
||||||
@ -799,26 +763,19 @@ class LifoAlloc {
|
|||||||
bc.release();
|
bc.release();
|
||||||
}
|
}
|
||||||
unused_.appendAll(std::move(chunks_));
|
unused_.appendAll(std::move(chunks_));
|
||||||
|
// On release, we free any oversize allocations instead of keeping them
|
||||||
|
// in unused chunks.
|
||||||
|
while (!oversize_.empty()) {
|
||||||
|
UniqueBumpChunk bc = oversize_.popFirst();
|
||||||
|
decrementCurSize(bc->computedSizeOfIncludingThis());
|
||||||
|
oversizeSize_ -= bc->computedSizeOfIncludingThis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Protect the content of the LifoAlloc chunks.
|
// Protect the content of the LifoAlloc chunks.
|
||||||
#ifdef LIFO_CHUNK_PROTECT
|
#ifdef LIFO_CHUNK_PROTECT
|
||||||
void setReadOnly() {
|
void setReadOnly();
|
||||||
for (detail::BumpChunk& bc : chunks_) {
|
void setReadWrite();
|
||||||
bc.setReadOnly();
|
|
||||||
}
|
|
||||||
for (detail::BumpChunk& bc : unused_) {
|
|
||||||
bc.setReadOnly();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void setReadWrite() {
|
|
||||||
for (detail::BumpChunk& bc : chunks_) {
|
|
||||||
bc.setReadWrite();
|
|
||||||
}
|
|
||||||
for (detail::BumpChunk& bc : unused_) {
|
|
||||||
bc.setReadWrite();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
void setReadOnly() const {}
|
void setReadOnly() const {}
|
||||||
void setReadWrite() const {}
|
void setReadWrite() const {}
|
||||||
@ -835,8 +792,10 @@ class LifoAlloc {
|
|||||||
|
|
||||||
// Return true if the LifoAlloc does not currently contain any allocations.
|
// Return true if the LifoAlloc does not currently contain any allocations.
|
||||||
bool isEmpty() const {
|
bool isEmpty() const {
|
||||||
return chunks_.empty() ||
|
bool empty = chunks_.empty() ||
|
||||||
(chunks_.begin() == chunks_.last() && chunks_.last()->empty());
|
(chunks_.begin() == chunks_.last() && chunks_.last()->empty());
|
||||||
|
MOZ_ASSERT_IF(!oversize_.empty(), !oversize_.last()->empty());
|
||||||
|
return empty && oversize_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the number of bytes remaining to allocate in the current chunk.
|
// Return the number of bytes remaining to allocate in the current chunk.
|
||||||
@ -854,6 +813,9 @@ class LifoAlloc {
|
|||||||
for (const detail::BumpChunk& chunk : chunks_) {
|
for (const detail::BumpChunk& chunk : chunks_) {
|
||||||
n += chunk.sizeOfIncludingThis(mallocSizeOf);
|
n += chunk.sizeOfIncludingThis(mallocSizeOf);
|
||||||
}
|
}
|
||||||
|
for (const detail::BumpChunk& chunk : oversize_) {
|
||||||
|
n += chunk.sizeOfIncludingThis(mallocSizeOf);
|
||||||
|
}
|
||||||
for (const detail::BumpChunk& chunk : unused_) {
|
for (const detail::BumpChunk& chunk : unused_) {
|
||||||
n += chunk.sizeOfIncludingThis(mallocSizeOf);
|
n += chunk.sizeOfIncludingThis(mallocSizeOf);
|
||||||
}
|
}
|
||||||
@ -866,6 +828,9 @@ class LifoAlloc {
|
|||||||
for (const detail::BumpChunk& chunk : chunks_) {
|
for (const detail::BumpChunk& chunk : chunks_) {
|
||||||
n += chunk.computedSizeOfIncludingThis();
|
n += chunk.computedSizeOfIncludingThis();
|
||||||
}
|
}
|
||||||
|
for (const detail::BumpChunk& chunk : oversize_) {
|
||||||
|
n += chunk.computedSizeOfIncludingThis();
|
||||||
|
}
|
||||||
for (const detail::BumpChunk& chunk : unused_) {
|
for (const detail::BumpChunk& chunk : unused_) {
|
||||||
n += chunk.computedSizeOfIncludingThis();
|
n += chunk.computedSizeOfIncludingThis();
|
||||||
}
|
}
|
||||||
@ -897,6 +862,11 @@ class LifoAlloc {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const detail::BumpChunk& chunk : oversize_) {
|
||||||
|
if (chunk.contains(ptr)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -935,6 +905,7 @@ class LifoAlloc {
|
|||||||
: chunkIt_(alloc.chunks_.begin()),
|
: chunkIt_(alloc.chunks_.begin()),
|
||||||
chunkEnd_(alloc.chunks_.end()),
|
chunkEnd_(alloc.chunks_.end()),
|
||||||
head_(nullptr) {
|
head_(nullptr) {
|
||||||
|
MOZ_RELEASE_ASSERT(alloc.oversize_.empty());
|
||||||
if (chunkIt_ != chunkEnd_) {
|
if (chunkIt_ != chunkEnd_) {
|
||||||
head_ = chunkIt_->begin();
|
head_ = chunkIt_->begin();
|
||||||
}
|
}
|
||||||
|
@ -1043,7 +1043,7 @@ typename Scope::Data* NewEmptyBindingData(JSContext* cx, LifoAlloc& alloc,
|
|||||||
uint32_t numBindings) {
|
uint32_t numBindings) {
|
||||||
using Data = typename Scope::Data;
|
using Data = typename Scope::Data;
|
||||||
size_t allocSize = SizeOfData<typename Scope::Data>(numBindings);
|
size_t allocSize = SizeOfData<typename Scope::Data>(numBindings);
|
||||||
auto* bindings = alloc.allocInSize<Data>(allocSize, numBindings);
|
auto* bindings = alloc.newWithSize<Data>(allocSize, numBindings);
|
||||||
if (!bindings) {
|
if (!bindings) {
|
||||||
ReportOutOfMemory(cx);
|
ReportOutOfMemory(cx);
|
||||||
}
|
}
|
||||||
|
@ -148,6 +148,12 @@ class StoreBuffer {
|
|||||||
MOZ_ASSERT(!head_);
|
MOZ_ASSERT(!head_);
|
||||||
if (!storage_) {
|
if (!storage_) {
|
||||||
storage_ = js_new<LifoAlloc>(LifoAllocBlockSize);
|
storage_ = js_new<LifoAlloc>(LifoAllocBlockSize);
|
||||||
|
// This prevents LifoAlloc::Enum from crashing with a release
|
||||||
|
// assertion if we ever allocate one entry larger than
|
||||||
|
// LifoAllocBlockSize.
|
||||||
|
if (storage_) {
|
||||||
|
storage_->disableOversize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
clear();
|
clear();
|
||||||
return bool(storage_);
|
return bool(storage_);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// |jit-test| allow-overrecursed
|
// |jit-test| slow; allow-overrecursed
|
||||||
|
|
||||||
(function f(x) {
|
(function f(x) {
|
||||||
f(x - 1);
|
f(x - 1);
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
|
|
||||||
#include "common_audio/fir_filter_neon.h"
|
#include "common_audio/fir_filter_neon.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
@ -13,7 +13,11 @@
|
|||||||
|
|
||||||
#include "common_audio/resampler/sinc_resampler.h"
|
#include "common_audio/resampler/sinc_resampler.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
|
|
||||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void DotProductWithScaleNeon(int32_t* cross_correlation,
|
static inline void DotProductWithScaleNeon(int32_t* cross_correlation,
|
||||||
const int16_t* vector1,
|
const int16_t* vector1,
|
||||||
@ -51,7 +55,7 @@ static inline void DotProductWithScaleNeon(int32_t* cross_correlation,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sum0 = vaddq_s64(sum0, sum1);
|
sum0 = vaddq_s64(sum0, sum1);
|
||||||
#if defined(WEBRTC_ARCH_ARM64)
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
int64_t sum2 = vaddvq_s64(sum0);
|
int64_t sum2 = vaddvq_s64(sum0);
|
||||||
*cross_correlation = (int32_t)((sum2 + sum_res) >> scaling);
|
*cross_correlation = (int32_t)((sum2 + sum_res) >> scaling);
|
||||||
#else
|
#else
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
|
|
||||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// NEON intrinsics version of WebRtcSpl_DownsampleFast()
|
// NEON intrinsics version of WebRtcSpl_DownsampleFast()
|
||||||
// for ARM 32-bit/64-bit platforms.
|
// for ARM 32-bit/64-bit platforms.
|
||||||
|
@ -8,7 +8,11 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
@ -37,7 +41,7 @@ int16_t WebRtcSpl_MaxAbsValueW16Neon(const int16_t* vector, size_t length) {
|
|||||||
p_start += 8;
|
p_start += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WEBRTC_ARCH_ARM64
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
maximum = (int)vmaxvq_u16(max_qv);
|
maximum = (int)vmaxvq_u16(max_qv);
|
||||||
#else
|
#else
|
||||||
uint16x4_t max_dv;
|
uint16x4_t max_dv;
|
||||||
@ -97,7 +101,7 @@ int32_t WebRtcSpl_MaxAbsValueW32Neon(const int32_t* vector, size_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32x4_t max32x4 = vmaxq_u32(max32x4_0, max32x4_1);
|
uint32x4_t max32x4 = vmaxq_u32(max32x4_0, max32x4_1);
|
||||||
#if defined(WEBRTC_ARCH_ARM64)
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
maximum = vmaxvq_u32(max32x4);
|
maximum = vmaxvq_u32(max32x4);
|
||||||
#else
|
#else
|
||||||
uint32x2_t max32x2 = vmax_u32(vget_low_u32(max32x4), vget_high_u32(max32x4));
|
uint32x2_t max32x2 = vmax_u32(vget_low_u32(max32x4), vget_high_u32(max32x4));
|
||||||
@ -140,7 +144,7 @@ int16_t WebRtcSpl_MaxValueW16Neon(const int16_t* vector, size_t length) {
|
|||||||
p_start += 8;
|
p_start += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WEBRTC_ARCH_ARM64)
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
maximum = vmaxvq_s16(max16x8);
|
maximum = vmaxvq_s16(max16x8);
|
||||||
#else
|
#else
|
||||||
int16x4_t max16x4 = vmax_s16(vget_low_s16(max16x8), vget_high_s16(max16x8));
|
int16x4_t max16x4 = vmax_s16(vget_low_s16(max16x8), vget_high_s16(max16x8));
|
||||||
@ -183,7 +187,7 @@ int32_t WebRtcSpl_MaxValueW32Neon(const int32_t* vector, size_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32x4_t max32x4 = vmaxq_s32(max32x4_0, max32x4_1);
|
int32x4_t max32x4 = vmaxq_s32(max32x4_0, max32x4_1);
|
||||||
#if defined(WEBRTC_ARCH_ARM64)
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
maximum = vmaxvq_s32(max32x4);
|
maximum = vmaxvq_s32(max32x4);
|
||||||
#else
|
#else
|
||||||
int32x2_t max32x2 = vmax_s32(vget_low_s32(max32x4), vget_high_s32(max32x4));
|
int32x2_t max32x2 = vmax_s32(vget_low_s32(max32x4), vget_high_s32(max32x4));
|
||||||
@ -220,7 +224,7 @@ int16_t WebRtcSpl_MinValueW16Neon(const int16_t* vector, size_t length) {
|
|||||||
p_start += 8;
|
p_start += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WEBRTC_ARCH_ARM64)
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
minimum = vminvq_s16(min16x8);
|
minimum = vminvq_s16(min16x8);
|
||||||
#else
|
#else
|
||||||
int16x4_t min16x4 = vmin_s16(vget_low_s16(min16x8), vget_high_s16(min16x8));
|
int16x4_t min16x4 = vmin_s16(vget_low_s16(min16x8), vget_high_s16(min16x8));
|
||||||
@ -263,7 +267,7 @@ int32_t WebRtcSpl_MinValueW32Neon(const int32_t* vector, size_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32x4_t min32x4 = vminq_s32(min32x4_0, min32x4_1);
|
int32x4_t min32x4 = vminq_s32(min32x4_0, min32x4_1);
|
||||||
#if defined(WEBRTC_ARCH_ARM64)
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
minimum = vminvq_s32(min32x4);
|
minimum = vminvq_s32(min32x4);
|
||||||
#else
|
#else
|
||||||
int32x2_t min32x2 = vmin_s32(vget_low_s32(min32x4), vget_high_s32(min32x4));
|
int32x2_t min32x2 = vmin_s32(vget_low_s32(min32x4), vget_high_s32(min32x4));
|
||||||
|
@ -16,7 +16,11 @@
|
|||||||
|
|
||||||
#include "entropy_coding.h"
|
#include "entropy_coding.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "signal_processing_library.h"
|
#include "signal_processing_library.h"
|
||||||
|
@ -13,7 +13,11 @@
|
|||||||
// WebRtcIsacfix_AllpassFilter2FixDec16C() in filterbanks.c. Prototype
|
// WebRtcIsacfix_AllpassFilter2FixDec16C() in filterbanks.c. Prototype
|
||||||
// C code is at end of this file.
|
// C code is at end of this file.
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
|
||||||
|
@ -8,7 +8,11 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
|
#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
|
||||||
@ -44,7 +48,7 @@ int WebRtcIsacfix_AutocorrNeon(int32_t* __restrict r,
|
|||||||
x_start += 4;
|
x_start += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WEBRTC_ARCH_ARM64
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
prod = vaddvq_s64(tmpb_v);
|
prod = vaddvq_s64(tmpb_v);
|
||||||
#else
|
#else
|
||||||
prod = vget_lane_s64(vadd_s64(vget_low_s64(tmpb_v), vget_high_s64(tmpb_v)),
|
prod = vget_lane_s64(vadd_s64(vget_low_s64(tmpb_v), vget_high_s64(tmpb_v)),
|
||||||
@ -90,7 +94,7 @@ int WebRtcIsacfix_AutocorrNeon(int32_t* __restrict r,
|
|||||||
x_start += 4;
|
x_start += 4;
|
||||||
y_start += 4;
|
y_start += 4;
|
||||||
}
|
}
|
||||||
#ifdef WEBRTC_ARCH_ARM64
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
prod = vaddvq_s64(tmpb_v);
|
prod = vaddvq_s64(tmpb_v);
|
||||||
#else
|
#else
|
||||||
prod = vget_lane_s64(vadd_s64(vget_low_s64(tmpb_v), vget_high_s64(tmpb_v)),
|
prod = vget_lane_s64(vadd_s64(vget_low_s64(tmpb_v), vget_high_s64(tmpb_v)),
|
||||||
|
@ -8,7 +8,11 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
|
#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
|
||||||
#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
|
#include "modules/audio_coding/codecs/isac/fix/source/settings.h"
|
||||||
|
@ -11,8 +11,12 @@
|
|||||||
#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
|
#include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
|
||||||
|
|
||||||
#ifdef WEBRTC_HAS_NEON
|
#ifdef WEBRTC_HAS_NEON
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||||
#include "rtc_base/compile_assert_c.h"
|
#include "rtc_base/compile_assert_c.h"
|
||||||
|
@ -8,7 +8,11 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
|
#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
|
||||||
#include "modules/audio_coding/codecs/isac/fix/source/fft.h"
|
#include "modules/audio_coding/codecs/isac/fix/source/fft.h"
|
||||||
@ -51,7 +55,7 @@ static inline int32_t ComplexMulAndFindMaxNeon(int16_t* inre1Q9,
|
|||||||
int32x4_t tmp1 = vmull_s16(vget_low_s16(tmpr), vget_low_s16(inre2));
|
int32x4_t tmp1 = vmull_s16(vget_low_s16(tmpr), vget_low_s16(inre2));
|
||||||
tmp0 = vmlal_s16(tmp0, vget_low_s16(tmpi), vget_low_s16(inre2));
|
tmp0 = vmlal_s16(tmp0, vget_low_s16(tmpi), vget_low_s16(inre2));
|
||||||
tmp1 = vmlsl_s16(tmp1, vget_low_s16(tmpi), vget_low_s16(inre1));
|
tmp1 = vmlsl_s16(tmp1, vget_low_s16(tmpi), vget_low_s16(inre1));
|
||||||
#if defined(WEBRTC_ARCH_ARM64)
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
int32x4_t tmp2 = vmull_high_s16(tmpr, inre1);
|
int32x4_t tmp2 = vmull_high_s16(tmpr, inre1);
|
||||||
int32x4_t tmp3 = vmull_high_s16(tmpr, inre2);
|
int32x4_t tmp3 = vmull_high_s16(tmpr, inre2);
|
||||||
tmp2 = vmlal_high_s16(tmp2, tmpi, inre2);
|
tmp2 = vmlal_high_s16(tmp2, tmpi, inre2);
|
||||||
@ -90,7 +94,7 @@ static inline int32_t ComplexMulAndFindMaxNeon(int16_t* inre1Q9,
|
|||||||
}
|
}
|
||||||
|
|
||||||
max_r = vmaxq_u32(max_r, max_i);
|
max_r = vmaxq_u32(max_r, max_i);
|
||||||
#if defined(WEBRTC_ARCH_ARM64)
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
uint32_t maximum = vmaxvq_u32(max_r);
|
uint32_t maximum = vmaxvq_u32(max_r);
|
||||||
#else
|
#else
|
||||||
uint32x2_t max32x2_r = vmax_u32(vget_low_u32(max_r), vget_high_u32(max_r));
|
uint32x2_t max32x2_r = vmax_u32(vget_low_u32(max_r), vget_high_u32(max_r));
|
||||||
@ -331,7 +335,7 @@ static inline int32_t TransformAndFindMaxNeon(int16_t* inre,
|
|||||||
}
|
}
|
||||||
|
|
||||||
max_r = vmaxq_u32(max_r, max_i);
|
max_r = vmaxq_u32(max_r, max_i);
|
||||||
#if defined(WEBRTC_ARCH_ARM64)
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
uint32_t maximum = vmaxvq_u32(max_r);
|
uint32_t maximum = vmaxvq_u32(max_r);
|
||||||
#else
|
#else
|
||||||
uint32x2_t max32x2_r = vmax_u32(vget_low_u32(max_r), vget_high_u32(max_r));
|
uint32x2_t max32x2_r = vmax_u32(vget_low_u32(max_r), vget_high_u32(max_r));
|
||||||
|
@ -14,7 +14,11 @@
|
|||||||
* Based on aec_core_sse2.c.
|
* Based on aec_core_sse2.c.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h> // memset
|
#include <string.h> // memset
|
||||||
|
|
||||||
@ -99,7 +103,8 @@ static float32x4_t vdivq_f32(float32x4_t a, float32x4_t b) {
|
|||||||
// a/b = a*(1/b)
|
// a/b = a*(1/b)
|
||||||
return vmulq_f32(a, x);
|
return vmulq_f32(a, x);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if !defined(WEBRTC_ARCH_ARM64) || (defined(_MSC_VER) && !defined(__clang__))
|
||||||
static float32x4_t vsqrtq_f32(float32x4_t s) {
|
static float32x4_t vsqrtq_f32(float32x4_t s) {
|
||||||
int i;
|
int i;
|
||||||
float32x4_t x = vrsqrteq_f32(s);
|
float32x4_t x = vrsqrteq_f32(s);
|
||||||
|
@ -11,8 +11,12 @@
|
|||||||
#include "modules/audio_processing/aec3/adaptive_fir_filter.h"
|
#include "modules/audio_processing/aec3/adaptive_fir_filter.h"
|
||||||
|
|
||||||
#if defined(WEBRTC_HAS_NEON)
|
#if defined(WEBRTC_HAS_NEON)
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#include "typedefs.h" // NOLINT(build/include)
|
#include "typedefs.h" // NOLINT(build/include)
|
||||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
|
@ -10,8 +10,12 @@
|
|||||||
#include "modules/audio_processing/aec3/matched_filter.h"
|
#include "modules/audio_processing/aec3/matched_filter.h"
|
||||||
|
|
||||||
#if defined(WEBRTC_HAS_NEON)
|
#if defined(WEBRTC_HAS_NEON)
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#include "typedefs.h" // NOLINT(build/include)
|
#include "typedefs.h" // NOLINT(build/include)
|
||||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
|
@ -13,8 +13,12 @@
|
|||||||
|
|
||||||
#include "typedefs.h" // NOLINT(build/include)
|
#include "typedefs.h" // NOLINT(build/include)
|
||||||
#if defined(WEBRTC_HAS_NEON)
|
#if defined(WEBRTC_HAS_NEON)
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
#endif
|
#endif
|
||||||
@ -64,7 +68,7 @@ class VectorMath {
|
|||||||
int j = 0;
|
int j = 0;
|
||||||
for (; j < vector_limit * 4; j += 4) {
|
for (; j < vector_limit * 4; j += 4) {
|
||||||
float32x4_t g = vld1q_f32(&x[j]);
|
float32x4_t g = vld1q_f32(&x[j]);
|
||||||
#if !defined(WEBRTC_ARCH_ARM64)
|
#if !defined(WEBRTC_ARCH_ARM64) || (defined(_MSC_VER) && !defined(__clang__))
|
||||||
float32x4_t y = vrsqrteq_f32(g);
|
float32x4_t y = vrsqrteq_f32(g);
|
||||||
|
|
||||||
// Code to handle sqrt(0).
|
// Code to handle sqrt(0).
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
|
|
||||||
#include "modules/audio_processing/aecm/aecm_core.h"
|
#include "modules/audio_processing/aecm/aecm_core.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common_audio/signal_processing/include/real_fft.h"
|
#include "common_audio/signal_processing/include/real_fft.h"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
@ -19,7 +23,7 @@
|
|||||||
// generating script and makefile, to replace these C functions.
|
// generating script and makefile, to replace these C functions.
|
||||||
|
|
||||||
static inline void AddLanes(uint32_t* ptr, uint32x4_t v) {
|
static inline void AddLanes(uint32_t* ptr, uint32x4_t v) {
|
||||||
#if defined(WEBRTC_ARCH_ARM64)
|
#if defined(WEBRTC_ARCH_ARM64) && (!defined(_MSC_VER) || defined(__clang__))
|
||||||
*(ptr) = vaddvq_u32(v);
|
*(ptr) = vaddvq_u32(v);
|
||||||
#else
|
#else
|
||||||
uint32x2_t tmp_v;
|
uint32x2_t tmp_v;
|
||||||
|
@ -10,7 +10,11 @@
|
|||||||
|
|
||||||
#include "modules/audio_processing/ns/nsx_core.h"
|
#include "modules/audio_processing/ns/nsx_core.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
|
||||||
|
@ -16,7 +16,11 @@
|
|||||||
|
|
||||||
#include "modules/audio_processing/utility/ooura_fft.h"
|
#include "modules/audio_processing/utility/ooura_fft.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "modules/audio_processing/utility/ooura_fft_tables_common.h"
|
#include "modules/audio_processing/utility/ooura_fft_tables_common.h"
|
||||||
#include "modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h"
|
#include "modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h"
|
||||||
|
@ -8,7 +8,11 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <arm64_neon.h>
|
||||||
|
#else
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "modules/video_processing/util/denoiser_filter_neon.h"
|
#include "modules/video_processing/util/denoiser_filter_neon.h"
|
||||||
|
|
||||||
|
@ -12,8 +12,7 @@ const {
|
|||||||
UnsupportedOperationError,
|
UnsupportedOperationError,
|
||||||
} = ChromeUtils.import("chrome://marionette/content/error.js", {});
|
} = ChromeUtils.import("chrome://marionette/content/error.js", {});
|
||||||
const {
|
const {
|
||||||
waitForEvent,
|
MessageManagerDestroyedPromise,
|
||||||
waitForObserverTopic,
|
|
||||||
} = ChromeUtils.import("chrome://marionette/content/sync.js", {});
|
} = ChromeUtils.import("chrome://marionette/content/sync.js", {});
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["browser", "Context", "WindowState"];
|
this.EXPORTED_SYMBOLS = ["browser", "Context", "WindowState"];
|
||||||
@ -71,11 +70,11 @@ this.Context = Context;
|
|||||||
*/
|
*/
|
||||||
browser.getBrowserForTab = function(tab) {
|
browser.getBrowserForTab = function(tab) {
|
||||||
// Fennec
|
// Fennec
|
||||||
if (tab && "browser" in tab) {
|
if ("browser" in tab) {
|
||||||
return tab.browser;
|
return tab.browser;
|
||||||
|
|
||||||
// Firefox
|
// Firefox
|
||||||
} else if (tab && "linkedBrowser" in tab) {
|
} else if ("linkedBrowser" in tab) {
|
||||||
return tab.linkedBrowser;
|
return tab.linkedBrowser;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,59 +287,17 @@ browser.Context = class {
|
|||||||
* A promise which is resolved when the current window has been closed.
|
* A promise which is resolved when the current window has been closed.
|
||||||
*/
|
*/
|
||||||
closeWindow() {
|
closeWindow() {
|
||||||
// Create a copy of the messageManager before it is disconnected
|
return new Promise(resolve => {
|
||||||
let messageManager = this.window.messageManager;
|
// Wait for the window message manager to be destroyed
|
||||||
let disconnected = waitForObserverTopic("message-manager-disconnect",
|
let destroyed = new MessageManagerDestroyedPromise(
|
||||||
subject => subject === messageManager);
|
this.window.messageManager);
|
||||||
let unloaded = waitForEvent(this.window, "unload");
|
|
||||||
|
|
||||||
|
this.window.addEventListener("unload", async () => {
|
||||||
|
await destroyed;
|
||||||
|
resolve();
|
||||||
|
}, {once: true});
|
||||||
this.window.close();
|
this.window.close();
|
||||||
|
});
|
||||||
return Promise.all([disconnected, unloaded]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a new browser window.
|
|
||||||
*
|
|
||||||
* @return {Promise}
|
|
||||||
* A promise resolving to the newly created chrome window.
|
|
||||||
*/
|
|
||||||
async openBrowserWindow(focus = false) {
|
|
||||||
switch (this.driver.appName) {
|
|
||||||
case "firefox":
|
|
||||||
// Open new browser window, and wait until it is fully loaded.
|
|
||||||
// Also wait for the window to be focused and activated to prevent a
|
|
||||||
// race condition when promptly focusing to the original window again.
|
|
||||||
let win = this.window.OpenBrowserWindow();
|
|
||||||
|
|
||||||
// Bug 1509380 - Missing focus/activate event when Firefox is not
|
|
||||||
// the top-most application. As such wait for the next tick, and
|
|
||||||
// manually focus the newly opened window.
|
|
||||||
win.setTimeout(() => win.focus(), 0);
|
|
||||||
|
|
||||||
let activated = waitForEvent(win, "activate");
|
|
||||||
let focused = waitForEvent(win, "focus", {capture: true});
|
|
||||||
let startup = waitForObserverTopic("browser-delayed-startup-finished",
|
|
||||||
subject => subject == win);
|
|
||||||
await Promise.all([activated, focused, startup]);
|
|
||||||
|
|
||||||
if (!focus) {
|
|
||||||
// The new window shouldn't get focused. As such set the
|
|
||||||
// focus back to the currently selected window.
|
|
||||||
activated = waitForEvent(this.window, "activate");
|
|
||||||
focused = waitForEvent(this.window, "focus", {capture: true});
|
|
||||||
|
|
||||||
this.window.focus();
|
|
||||||
|
|
||||||
await Promise.all([activated, focused]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return win;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationError(
|
|
||||||
`openWindow() not supported in ${this.driver.appName}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -362,65 +319,40 @@ browser.Context = class {
|
|||||||
return this.closeWindow();
|
return this.closeWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a copy of the messageManager before it is disconnected
|
return new Promise((resolve, reject) => {
|
||||||
let messageManager = this.messageManager;
|
// Wait for the browser message manager to be destroyed
|
||||||
let disconnected = waitForObserverTopic("message-manager-disconnect",
|
let browserDetached = async () => {
|
||||||
subject => subject === messageManager);
|
await new MessageManagerDestroyedPromise(this.messageManager);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
let tabClosed;
|
if (this.tabBrowser.closeTab) {
|
||||||
|
|
||||||
switch (this.driver.appName) {
|
|
||||||
case "fennec":
|
|
||||||
// Fennec
|
// Fennec
|
||||||
tabClosed = waitForEvent(this.tabBrowser.deck, "TabClose");
|
this.tabBrowser.deck.addEventListener(
|
||||||
|
"TabClose", browserDetached, {once: true});
|
||||||
this.tabBrowser.closeTab(this.tab);
|
this.tabBrowser.closeTab(this.tab);
|
||||||
break;
|
|
||||||
|
|
||||||
case "firefox":
|
} else if (this.tabBrowser.removeTab) {
|
||||||
tabClosed = waitForEvent(this.tab, "TabClose");
|
// Firefox
|
||||||
|
this.tab.addEventListener(
|
||||||
|
"TabClose", browserDetached, {once: true});
|
||||||
this.tabBrowser.removeTab(this.tab);
|
this.tabBrowser.removeTab(this.tab);
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
} else {
|
||||||
throw new UnsupportedOperationError(
|
reject(new UnsupportedOperationError(
|
||||||
`closeTab() not supported in ${this.driver.appName}`);
|
`closeTab() not supported in ${this.driver.appName}`));
|
||||||
}
|
}
|
||||||
|
});
|
||||||
return Promise.all([disconnected, tabClosed]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a new tab in the currently selected chrome window.
|
* Opens a tab with given URI.
|
||||||
|
*
|
||||||
|
* @param {string} uri
|
||||||
|
* URI to open.
|
||||||
*/
|
*/
|
||||||
async openTab(focus = false) {
|
addTab(uri) {
|
||||||
let tab = null;
|
return this.tabBrowser.addTab(uri, true);
|
||||||
let tabOpened = waitForEvent(this.window, "TabOpen");
|
|
||||||
|
|
||||||
switch (this.driver.appName) {
|
|
||||||
case "fennec":
|
|
||||||
tab = this.tabBrowser.addTab(null, {selected: focus});
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "firefox":
|
|
||||||
this.window.BrowserOpenTab();
|
|
||||||
tab = this.tabBrowser.selectedTab;
|
|
||||||
|
|
||||||
// The new tab is always selected by default. If focus is not wanted,
|
|
||||||
// the previously tab needs to be selected again.
|
|
||||||
if (!focus) {
|
|
||||||
this.tabBrowser.selectedTab = this.tab;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationError(
|
|
||||||
`openTab() not supported in ${this.driver.appName}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
await tabOpened;
|
|
||||||
|
|
||||||
return tab;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -454,18 +386,16 @@ browser.Context = class {
|
|||||||
this.tab = this.tabBrowser.tabs[index];
|
this.tab = this.tabBrowser.tabs[index];
|
||||||
|
|
||||||
if (focus) {
|
if (focus) {
|
||||||
switch (this.driver.appName) {
|
if (this.tabBrowser.selectTab) {
|
||||||
case "fennec":
|
// Fennec
|
||||||
this.tabBrowser.selectTab(this.tab);
|
this.tabBrowser.selectTab(this.tab);
|
||||||
break;
|
|
||||||
|
|
||||||
case "firefox":
|
} else if ("selectedTab" in this.tabBrowser) {
|
||||||
|
// Firefox
|
||||||
this.tabBrowser.selectedTab = this.tab;
|
this.tabBrowser.selectedTab = this.tab;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
} else {
|
||||||
throw new UnsupportedOperationError(
|
throw new UnsupportedOperationError("switchToTab() not supported");
|
||||||
`switchToTab() not supported in ${this.driver.appName}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1428,20 +1428,6 @@ class Marionette(object):
|
|||||||
return self._send_message("WebDriver:GetPageSource",
|
return self._send_message("WebDriver:GetPageSource",
|
||||||
key="value")
|
key="value")
|
||||||
|
|
||||||
def open(self, type=None, focus=False):
|
|
||||||
"""Open a new window, or tab based on the specified context type.
|
|
||||||
|
|
||||||
If no context type is given the application will choose the best
|
|
||||||
option based on tab and window support.
|
|
||||||
|
|
||||||
:param type: Type of window to be opened. Can be one of "tab" or "window"
|
|
||||||
:param focus: If true, the opened window will be focused
|
|
||||||
|
|
||||||
:returns: Dict with new window handle, and type of opened window
|
|
||||||
"""
|
|
||||||
body = {"type": type, "focus": focus}
|
|
||||||
return self._send_message("WebDriver:NewWindow", body)
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""Close the current window, ending the session if it's the last
|
"""Close the current window, ending the session if it's the last
|
||||||
window currently open.
|
window currently open.
|
||||||
|
@ -3,7 +3,8 @@ sync module
|
|||||||
|
|
||||||
Provides an assortment of synchronisation primitives.
|
Provides an assortment of synchronisation primitives.
|
||||||
|
|
||||||
.. js:autofunction:: executeSoon
|
.. js:autoclass:: MessageManagerDestroyedPromise
|
||||||
|
:members:
|
||||||
|
|
||||||
.. js:autoclass:: PollPromise
|
.. js:autoclass:: PollPromise
|
||||||
:members:
|
:members:
|
||||||
@ -13,9 +14,3 @@ Provides an assortment of synchronisation primitives.
|
|||||||
|
|
||||||
.. js:autoclass:: TimedPromise
|
.. js:autoclass:: TimedPromise
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. js:autofunction:: waitForEvent
|
|
||||||
|
|
||||||
.. js:autofunction:: waitForMessage
|
|
||||||
|
|
||||||
.. js:autofunction:: waitForObserverTopic
|
|
||||||
|
@ -62,8 +62,6 @@ const {
|
|||||||
IdlePromise,
|
IdlePromise,
|
||||||
PollPromise,
|
PollPromise,
|
||||||
TimedPromise,
|
TimedPromise,
|
||||||
waitForEvent,
|
|
||||||
waitForObserverTopic,
|
|
||||||
} = ChromeUtils.import("chrome://marionette/content/sync.js", {});
|
} = ChromeUtils.import("chrome://marionette/content/sync.js", {});
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "logger", Log.get);
|
XPCOMUtils.defineLazyGetter(this, "logger", Log.get);
|
||||||
@ -108,12 +106,13 @@ const globalMessageManager = Services.mm;
|
|||||||
*
|
*
|
||||||
* @class GeckoDriver
|
* @class GeckoDriver
|
||||||
*
|
*
|
||||||
|
* @param {string} appId
|
||||||
|
* Unique identifier of the application.
|
||||||
* @param {MarionetteServer} server
|
* @param {MarionetteServer} server
|
||||||
* The instance of Marionette server.
|
* The instance of Marionette server.
|
||||||
*/
|
*/
|
||||||
this.GeckoDriver = function(server) {
|
this.GeckoDriver = function(appId, server) {
|
||||||
this.appId = Services.appinfo.ID;
|
this.appId = appId;
|
||||||
this.appName = Services.appinfo.name.toLowerCase();
|
|
||||||
this._server = server;
|
this._server = server;
|
||||||
|
|
||||||
this.sessionID = null;
|
this.sessionID = null;
|
||||||
@ -1308,7 +1307,6 @@ GeckoDriver.prototype.getIdForBrowser = function(browser) {
|
|||||||
if (browser === null) {
|
if (browser === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let permKey = browser.permanentKey;
|
let permKey = browser.permanentKey;
|
||||||
if (this._browserIds.has(permKey)) {
|
if (this._browserIds.has(permKey)) {
|
||||||
return this._browserIds.get(permKey);
|
return this._browserIds.get(permKey);
|
||||||
@ -2724,73 +2722,6 @@ GeckoDriver.prototype.deleteCookie = async function(cmd) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a new top-level browsing context.
|
|
||||||
*
|
|
||||||
* @param {string=} type
|
|
||||||
* Optional type of the new top-level browsing context. Can be one of
|
|
||||||
* `tab` or `window`.
|
|
||||||
* @param {boolean=} focus
|
|
||||||
* Optional flag if the new top-level browsing context should be opened
|
|
||||||
* in foreground (focused) or background (not focused).
|
|
||||||
*
|
|
||||||
* @return {Object.<string, string>}
|
|
||||||
* Handle and type of the new browsing context.
|
|
||||||
*/
|
|
||||||
GeckoDriver.prototype.newWindow = async function(cmd) {
|
|
||||||
assert.open(this.getCurrentWindow(Context.Content));
|
|
||||||
await this._handleUserPrompts();
|
|
||||||
|
|
||||||
let focus = false;
|
|
||||||
if (typeof cmd.parameters.focus != "undefined") {
|
|
||||||
focus = assert.boolean(cmd.parameters.focus,
|
|
||||||
pprint`Expected "focus" to be a boolean, got ${cmd.parameters.focus}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let type;
|
|
||||||
if (typeof cmd.parameters.type != "undefined") {
|
|
||||||
type = assert.string(cmd.parameters.type,
|
|
||||||
pprint`Expected "type" to be a string, got ${cmd.parameters.type}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let types = ["tab", "window"];
|
|
||||||
switch (this.appName) {
|
|
||||||
case "firefox":
|
|
||||||
if (typeof type == "undefined" || !types.includes(type)) {
|
|
||||||
type = "window";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "fennec":
|
|
||||||
if (typeof type == "undefined" || !types.includes(type)) {
|
|
||||||
type = "tab";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
let contentBrowser;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case "tab":
|
|
||||||
let tab = await this.curBrowser.openTab(focus);
|
|
||||||
contentBrowser = browser.getBrowserForTab(tab);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
let win = await this.curBrowser.openBrowserWindow(focus);
|
|
||||||
contentBrowser = browser.getTabBrowser(win).selectedBrowser;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Even with the framescript registered, the browser might not be known to
|
|
||||||
// the parent process yet. Wait until it is available.
|
|
||||||
// TODO: Fix by using `Browser:Init` or equivalent on bug 1311041
|
|
||||||
let windowId = await new PollPromise((resolve, reject) => {
|
|
||||||
let id = this.getIdForBrowser(contentBrowser);
|
|
||||||
this.windowHandles.includes(id) ? resolve(id) : reject();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {"handle": windowId.toString(), type};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the currently selected tab/window.
|
* Close the currently selected tab/window.
|
||||||
*
|
*
|
||||||
@ -3170,14 +3101,16 @@ GeckoDriver.prototype.dismissDialog = async function() {
|
|||||||
let win = assert.open(this.getCurrentWindow());
|
let win = assert.open(this.getCurrentWindow());
|
||||||
this._checkIfAlertIsPresent();
|
this._checkIfAlertIsPresent();
|
||||||
|
|
||||||
let dialogClosed = waitForEvent(win, "DOMModalDialogClosed");
|
await new Promise(resolve => {
|
||||||
|
win.addEventListener("DOMModalDialogClosed", async () => {
|
||||||
|
await new IdlePromise(win);
|
||||||
|
this.dialog = null;
|
||||||
|
resolve();
|
||||||
|
}, {once: true});
|
||||||
|
|
||||||
let {button0, button1} = this.dialog.ui;
|
let {button0, button1} = this.dialog.ui;
|
||||||
(button1 ? button1 : button0).click();
|
(button1 ? button1 : button0).click();
|
||||||
|
});
|
||||||
await dialogClosed;
|
|
||||||
|
|
||||||
this.dialog = null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3188,14 +3121,16 @@ GeckoDriver.prototype.acceptDialog = async function() {
|
|||||||
let win = assert.open(this.getCurrentWindow());
|
let win = assert.open(this.getCurrentWindow());
|
||||||
this._checkIfAlertIsPresent();
|
this._checkIfAlertIsPresent();
|
||||||
|
|
||||||
let dialogClosed = waitForEvent(win, "DOMModalDialogClosed");
|
await new Promise(resolve => {
|
||||||
|
win.addEventListener("DOMModalDialogClosed", async () => {
|
||||||
|
await new IdlePromise(win);
|
||||||
|
this.dialog = null;
|
||||||
|
resolve();
|
||||||
|
}, {once: true});
|
||||||
|
|
||||||
let {button0} = this.dialog.ui;
|
let {button0} = this.dialog.ui;
|
||||||
button0.click();
|
button0.click();
|
||||||
|
});
|
||||||
await dialogClosed;
|
|
||||||
|
|
||||||
this.dialog = null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3366,10 +3301,15 @@ GeckoDriver.prototype.quit = async function(cmd) {
|
|||||||
this.deleteSession();
|
this.deleteSession();
|
||||||
|
|
||||||
// delay response until the application is about to quit
|
// delay response until the application is about to quit
|
||||||
let quitApplication = waitForObserverTopic("quit-application");
|
let quitApplication = new Promise(resolve => {
|
||||||
|
Services.obs.addObserver(
|
||||||
|
(subject, topic, data) => resolve(data),
|
||||||
|
"quit-application");
|
||||||
|
});
|
||||||
|
|
||||||
Services.startup.quit(mode);
|
Services.startup.quit(mode);
|
||||||
|
|
||||||
return {cause: (await quitApplication).data};
|
return {cause: await quitApplication};
|
||||||
};
|
};
|
||||||
|
|
||||||
GeckoDriver.prototype.installAddon = function(cmd) {
|
GeckoDriver.prototype.installAddon = function(cmd) {
|
||||||
@ -3631,7 +3571,6 @@ GeckoDriver.prototype.commands = {
|
|||||||
"WebDriver:MaximizeWindow": GeckoDriver.prototype.maximizeWindow,
|
"WebDriver:MaximizeWindow": GeckoDriver.prototype.maximizeWindow,
|
||||||
"WebDriver:Navigate": GeckoDriver.prototype.get,
|
"WebDriver:Navigate": GeckoDriver.prototype.get,
|
||||||
"WebDriver:NewSession": GeckoDriver.prototype.newSession,
|
"WebDriver:NewSession": GeckoDriver.prototype.newSession,
|
||||||
"WebDriver:NewWindow": GeckoDriver.prototype.newWindow,
|
|
||||||
"WebDriver:PerformActions": GeckoDriver.prototype.performActions,
|
"WebDriver:PerformActions": GeckoDriver.prototype.performActions,
|
||||||
"WebDriver:Refresh": GeckoDriver.prototype.refresh,
|
"WebDriver:Refresh": GeckoDriver.prototype.refresh,
|
||||||
"WebDriver:ReleaseActions": GeckoDriver.prototype.releaseActions,
|
"WebDriver:ReleaseActions": GeckoDriver.prototype.releaseActions,
|
||||||
|
@ -6,12 +6,14 @@ from __future__ import absolute_import
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from marionette_driver import Wait
|
from marionette_driver import By, Wait
|
||||||
from six import reraise
|
from six import reraise
|
||||||
|
|
||||||
|
|
||||||
class WindowManagerMixin(object):
|
class WindowManagerMixin(object):
|
||||||
|
|
||||||
|
_menu_item_new_tab = (By.ID, "menu_newNavigatorTab")
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(WindowManagerMixin, self).setUp()
|
super(WindowManagerMixin, self).setUp()
|
||||||
|
|
||||||
@ -58,18 +60,15 @@ class WindowManagerMixin(object):
|
|||||||
|
|
||||||
self.marionette.switch_to_window(self.start_window)
|
self.marionette.switch_to_window(self.start_window)
|
||||||
|
|
||||||
def open_tab(self, callback=None, focus=False):
|
def open_tab(self, trigger="menu"):
|
||||||
current_tabs = self.marionette.window_handles
|
current_tabs = self.marionette.window_handles
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if callable(callback):
|
if callable(trigger):
|
||||||
callback()
|
trigger()
|
||||||
else:
|
elif trigger == 'menu':
|
||||||
result = self.marionette.open(type="tab", focus=focus)
|
with self.marionette.using_context("chrome"):
|
||||||
if result["type"] != "tab":
|
self.marionette.find_element(*self._menu_item_new_tab).click()
|
||||||
raise Exception(
|
|
||||||
"Newly opened browsing context is of type {} and not tab.".format(
|
|
||||||
result["type"]))
|
|
||||||
except Exception:
|
except Exception:
|
||||||
exc, val, tb = sys.exc_info()
|
exc, val, tb = sys.exc_info()
|
||||||
reraise(exc, 'Failed to trigger opening a new tab: {}'.format(val), tb)
|
reraise(exc, 'Failed to trigger opening a new tab: {}'.format(val), tb)
|
||||||
@ -83,9 +82,8 @@ class WindowManagerMixin(object):
|
|||||||
|
|
||||||
return new_tab
|
return new_tab
|
||||||
|
|
||||||
def open_window(self, callback=None, focus=False):
|
def open_window(self, trigger=None):
|
||||||
current_windows = self.marionette.chrome_window_handles
|
current_windows = self.marionette.chrome_window_handles
|
||||||
current_tabs = self.marionette.window_handles
|
|
||||||
|
|
||||||
def loaded(handle):
|
def loaded(handle):
|
||||||
with self.marionette.using_context("chrome"):
|
with self.marionette.using_context("chrome"):
|
||||||
@ -97,14 +95,11 @@ class WindowManagerMixin(object):
|
|||||||
""", script_args=[handle])
|
""", script_args=[handle])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if callable(callback):
|
if callable(trigger):
|
||||||
callback()
|
trigger()
|
||||||
else:
|
else:
|
||||||
result = self.marionette.open(type="window", focus=focus)
|
with self.marionette.using_context("chrome"):
|
||||||
if result["type"] != "window":
|
self.marionette.execute_script("OpenBrowserWindow();")
|
||||||
raise Exception(
|
|
||||||
"Newly opened browsing context is of type {} and not window.".format(
|
|
||||||
result["type"]))
|
|
||||||
except Exception:
|
except Exception:
|
||||||
exc, val, tb = sys.exc_info()
|
exc, val, tb = sys.exc_info()
|
||||||
reraise(exc, 'Failed to trigger opening a new window: {}'.format(val), tb)
|
reraise(exc, 'Failed to trigger opening a new window: {}'.format(val), tb)
|
||||||
@ -121,16 +116,9 @@ class WindowManagerMixin(object):
|
|||||||
lambda _: loaded(new_window),
|
lambda _: loaded(new_window),
|
||||||
message="Window with handle '{}'' did not finish loading".format(new_window))
|
message="Window with handle '{}'' did not finish loading".format(new_window))
|
||||||
|
|
||||||
# Bug 1507771 - Return the correct handle based on the currently selected context
|
|
||||||
# as long as "WebDriver:NewWindow" is not handled separtely in chrome context
|
|
||||||
context = self.marionette._send_message("Marionette:GetContext", key="value")
|
|
||||||
if context == "chrome":
|
|
||||||
return new_window
|
return new_window
|
||||||
elif context == "content":
|
|
||||||
[new_tab] = list(set(self.marionette.window_handles) - set(current_tabs))
|
|
||||||
return new_tab
|
|
||||||
|
|
||||||
def open_chrome_window(self, url, focus=False):
|
def open_chrome_window(self, url):
|
||||||
"""Open a new chrome window with the specified chrome URL.
|
"""Open a new chrome window with the specified chrome URL.
|
||||||
|
|
||||||
Can be replaced with "WebDriver:NewWindow" once the command
|
Can be replaced with "WebDriver:NewWindow" once the command
|
||||||
@ -178,5 +166,4 @@ class WindowManagerMixin(object):
|
|||||||
})();
|
})();
|
||||||
""", script_args=(url,))
|
""", script_args=(url,))
|
||||||
|
|
||||||
with self.marionette.using_context("chrome"):
|
return self.open_window(trigger=open_with_js)
|
||||||
return self.open_window(callback=open_with_js, focus=focus)
|
|
||||||
|
@ -1,5 +1,22 @@
|
|||||||
|
#Copyright 2007-2009 WebDriver committers
|
||||||
|
#Copyright 2007-2009 Google Inc.
|
||||||
|
#
|
||||||
|
#Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
#you may not use this file except in compliance with the License.
|
||||||
|
#You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
#Unless required by applicable law or agreed to in writing, software
|
||||||
|
#distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
#See the License for the specific language governing permissions and
|
||||||
|
#limitations under the License.
|
||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from marionette_driver import By
|
||||||
|
|
||||||
from marionette_harness import MarionetteTestCase, WindowManagerMixin
|
from marionette_harness import MarionetteTestCase, WindowManagerMixin
|
||||||
|
|
||||||
|
|
||||||
@ -8,13 +25,18 @@ class ChromeTests(WindowManagerMixin, MarionetteTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ChromeTests, self).setUp()
|
super(ChromeTests, self).setUp()
|
||||||
|
|
||||||
|
self.marionette.set_context('chrome')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.close_all_windows()
|
self.close_all_windows()
|
||||||
super(ChromeTests, self).tearDown()
|
super(ChromeTests, self).tearDown()
|
||||||
|
|
||||||
def test_hang_until_timeout(self):
|
def test_hang_until_timeout(self):
|
||||||
with self.marionette.using_context("chrome"):
|
def open_with_menu():
|
||||||
new_window = self.open_window()
|
menu = self.marionette.find_element(By.ID, 'aboutName')
|
||||||
|
menu.click()
|
||||||
|
|
||||||
|
new_window = self.open_window(trigger=open_with_menu)
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(new_window)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -23,8 +45,7 @@ class ChromeTests(WindowManagerMixin, MarionetteTestCase):
|
|||||||
# while running this test. Otherwise it would mask eg. IOError as
|
# while running this test. Otherwise it would mask eg. IOError as
|
||||||
# thrown for a socket timeout.
|
# thrown for a socket timeout.
|
||||||
raise NotImplementedError('Exception should not cause a hang when '
|
raise NotImplementedError('Exception should not cause a hang when '
|
||||||
'closing the chrome window in content '
|
'closing the chrome window')
|
||||||
'context')
|
|
||||||
finally:
|
finally:
|
||||||
self.marionette.close_chrome_window()
|
self.marionette.close_chrome_window()
|
||||||
self.marionette.switch_to_window(self.start_window)
|
self.marionette.switch_to_window(self.start_window)
|
||||||
|
@ -449,16 +449,20 @@ class TestClickCloseContext(WindowManagerMixin, MarionetteTestCase):
|
|||||||
super(TestClickCloseContext, self).tearDown()
|
super(TestClickCloseContext, self).tearDown()
|
||||||
|
|
||||||
def test_click_close_tab(self):
|
def test_click_close_tab(self):
|
||||||
new_tab = self.open_tab()
|
self.marionette.navigate(self.marionette.absolute_url("windowHandles.html"))
|
||||||
self.marionette.switch_to_window(new_tab)
|
tab = self.open_tab(
|
||||||
|
lambda: self.marionette.find_element(By.ID, "new-tab").click())
|
||||||
|
self.marionette.switch_to_window(tab)
|
||||||
|
|
||||||
self.marionette.navigate(self.test_page)
|
self.marionette.navigate(self.test_page)
|
||||||
self.marionette.find_element(By.ID, "close-window").click()
|
self.marionette.find_element(By.ID, "close-window").click()
|
||||||
|
|
||||||
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
||||||
def test_click_close_window(self):
|
def test_click_close_window(self):
|
||||||
new_tab = self.open_window()
|
self.marionette.navigate(self.marionette.absolute_url("windowHandles.html"))
|
||||||
self.marionette.switch_to_window(new_tab)
|
win = self.open_window(
|
||||||
|
lambda: self.marionette.find_element(By.ID, "new-window").click())
|
||||||
|
self.marionette.switch_to_window(win)
|
||||||
|
|
||||||
self.marionette.navigate(self.test_page)
|
self.marionette.navigate(self.test_page)
|
||||||
self.marionette.find_element(By.ID, "close-window").click()
|
self.marionette.find_element(By.ID, "close-window").click()
|
||||||
|
@ -77,3 +77,22 @@ class TestKeyActions(WindowManagerMixin, MarionetteTestCase):
|
|||||||
.key_down("x")
|
.key_down("x")
|
||||||
.perform())
|
.perform())
|
||||||
self.assertEqual(self.key_reporter_value, "")
|
self.assertEqual(self.key_reporter_value, "")
|
||||||
|
|
||||||
|
@skip_if_mobile("Interacting with chrome windows not available for Fennec")
|
||||||
|
def test_open_in_new_window_shortcut(self):
|
||||||
|
|
||||||
|
def open_window_with_action():
|
||||||
|
el = self.marionette.find_element(By.TAG_NAME, "a")
|
||||||
|
(self.key_action.key_down(Keys.SHIFT)
|
||||||
|
.press(el)
|
||||||
|
.release()
|
||||||
|
.key_up(Keys.SHIFT)
|
||||||
|
.perform())
|
||||||
|
|
||||||
|
self.marionette.navigate(inline("<a href='#'>Click</a>"))
|
||||||
|
new_window = self.open_window(trigger=open_window_with_action)
|
||||||
|
|
||||||
|
self.marionette.switch_to_window(new_window)
|
||||||
|
self.marionette.close_chrome_window()
|
||||||
|
|
||||||
|
self.marionette.switch_to_window(self.start_window)
|
||||||
|
@ -55,8 +55,13 @@ class BaseNavigationTestCase(WindowManagerMixin, MarionetteTestCase):
|
|||||||
else:
|
else:
|
||||||
self.mod_key = Keys.CONTROL
|
self.mod_key = Keys.CONTROL
|
||||||
|
|
||||||
|
def open_with_link():
|
||||||
|
link = self.marionette.find_element(By.ID, "new-blank-tab")
|
||||||
|
link.click()
|
||||||
|
|
||||||
# Always use a blank new tab for an empty history
|
# Always use a blank new tab for an empty history
|
||||||
self.new_tab = self.open_tab()
|
self.marionette.navigate(self.marionette.absolute_url("windowHandles.html"))
|
||||||
|
self.new_tab = self.open_tab(open_with_link)
|
||||||
self.marionette.switch_to_window(self.new_tab)
|
self.marionette.switch_to_window(self.new_tab)
|
||||||
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
|
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
|
||||||
lambda _: self.history_length == 1,
|
lambda _: self.history_length == 1,
|
||||||
@ -293,6 +298,7 @@ class TestNavigate(BaseNavigationTestCase):
|
|||||||
focus_el = self.marionette.find_element(By.CSS_SELECTOR, ":focus")
|
focus_el = self.marionette.find_element(By.CSS_SELECTOR, ":focus")
|
||||||
self.assertEqual(self.marionette.get_active_element(), focus_el)
|
self.assertEqual(self.marionette.get_active_element(), focus_el)
|
||||||
|
|
||||||
|
@skip_if_mobile("Needs application independent method to open a new tab")
|
||||||
def test_no_hang_when_navigating_after_closing_original_tab(self):
|
def test_no_hang_when_navigating_after_closing_original_tab(self):
|
||||||
# Close the start tab
|
# Close the start tab
|
||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
@ -334,6 +340,22 @@ class TestNavigate(BaseNavigationTestCase):
|
|||||||
message="'{}' hasn't been loaded".format(self.test_page_remote))
|
message="'{}' hasn't been loaded".format(self.test_page_remote))
|
||||||
self.assertTrue(self.is_remote_tab)
|
self.assertTrue(self.is_remote_tab)
|
||||||
|
|
||||||
|
@skip_if_mobile("On Android no shortcuts are available")
|
||||||
|
def test_navigate_shortcut_key(self):
|
||||||
|
|
||||||
|
def open_with_shortcut():
|
||||||
|
self.marionette.navigate(self.test_page_remote)
|
||||||
|
with self.marionette.using_context("chrome"):
|
||||||
|
main_win = self.marionette.find_element(By.ID, "main-window")
|
||||||
|
main_win.send_keys(self.mod_key, Keys.SHIFT, "a")
|
||||||
|
|
||||||
|
new_tab = self.open_tab(trigger=open_with_shortcut)
|
||||||
|
self.marionette.switch_to_window(new_tab)
|
||||||
|
|
||||||
|
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
|
||||||
|
lambda mn: mn.get_url() == "about:addons",
|
||||||
|
message="'about:addons' hasn't been loaded")
|
||||||
|
|
||||||
|
|
||||||
class TestBackForwardNavigation(BaseNavigationTestCase):
|
class TestBackForwardNavigation(BaseNavigationTestCase):
|
||||||
|
|
||||||
@ -801,7 +823,7 @@ class TestPageLoadStrategy(BaseNavigationTestCase):
|
|||||||
@skip("Bug 1422741 - Causes following tests to fail in loading remote browser")
|
@skip("Bug 1422741 - Causes following tests to fail in loading remote browser")
|
||||||
@run_if_e10s("Requires e10s mode enabled")
|
@run_if_e10s("Requires e10s mode enabled")
|
||||||
def test_strategy_after_remoteness_change(self):
|
def test_strategy_after_remoteness_change(self):
|
||||||
"""Bug 1378191 - Reset of capabilities after listener reload."""
|
"""Bug 1378191 - Reset of capabilities after listener reload"""
|
||||||
self.marionette.delete_session()
|
self.marionette.delete_session()
|
||||||
self.marionette.start_session({"pageLoadStrategy": "eager"})
|
self.marionette.start_session({"pageLoadStrategy": "eager"})
|
||||||
|
|
||||||
|
@ -253,8 +253,7 @@ class TestScreenCaptureChrome(WindowManagerMixin, ScreenCaptureTestCase):
|
|||||||
|
|
||||||
chrome_document_element = self.document_element
|
chrome_document_element = self.document_element
|
||||||
with self.marionette.using_context('content'):
|
with self.marionette.using_context('content'):
|
||||||
self.assertRaisesRegexp(NoSuchElementException,
|
self.assertRaisesRegexp(NoSuchElementException, "Web element reference not seen before",
|
||||||
"Web element reference not seen before",
|
|
||||||
self.marionette.screenshot,
|
self.marionette.screenshot,
|
||||||
highlights=[chrome_document_element])
|
highlights=[chrome_document_element])
|
||||||
|
|
||||||
@ -275,9 +274,10 @@ class TestScreenCaptureContent(WindowManagerMixin, ScreenCaptureTestCase):
|
|||||||
return [document.body.scrollWidth, document.body.scrollHeight]
|
return [document.body.scrollWidth, document.body.scrollHeight]
|
||||||
"""))
|
"""))
|
||||||
|
|
||||||
|
@skip_if_mobile("Needs application independent method to open a new tab")
|
||||||
def test_capture_tab_already_closed(self):
|
def test_capture_tab_already_closed(self):
|
||||||
new_tab = self.open_tab()
|
tab = self.open_tab()
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(tab)
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
|
|
||||||
self.assertRaises(NoSuchWindowException, self.marionette.screenshot)
|
self.assertRaises(NoSuchWindowException, self.marionette.screenshot)
|
||||||
|
@ -6,9 +6,10 @@ from __future__ import absolute_import
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from unittest import skipIf
|
from unittest import skipIf
|
||||||
|
|
||||||
|
from marionette_driver import By
|
||||||
|
|
||||||
# add this directory to the path
|
# add this directory to the path
|
||||||
sys.path.append(os.path.dirname(__file__))
|
sys.path.append(os.path.dirname(__file__))
|
||||||
|
|
||||||
@ -27,70 +28,119 @@ class TestSwitchWindowChrome(TestSwitchToWindowContent):
|
|||||||
|
|
||||||
super(TestSwitchWindowChrome, self).tearDown()
|
super(TestSwitchWindowChrome, self).tearDown()
|
||||||
|
|
||||||
@skipIf(sys.platform.startswith("linux"),
|
def open_window_in_background(self):
|
||||||
"Bug 1511970 - New window isn't moved to the background on Linux")
|
with self.marionette.using_context("chrome"):
|
||||||
|
self.marionette.execute_async_script("""
|
||||||
|
let callback = arguments[0];
|
||||||
|
(async function() {
|
||||||
|
function promiseEvent(target, type, args) {
|
||||||
|
return new Promise(r => {
|
||||||
|
let params = Object.assign({once: true}, args);
|
||||||
|
target.addEventListener(type, r, params);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function promiseWindowFocus(w) {
|
||||||
|
return Promise.all([
|
||||||
|
promiseEvent(w, "focus", {capture: true}),
|
||||||
|
promiseEvent(w, "activate"),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
// Open a window, wait for it to receive focus
|
||||||
|
let win = OpenBrowserWindow();
|
||||||
|
await promiseWindowFocus(win);
|
||||||
|
|
||||||
|
// Now refocus our original window and wait for that to happen.
|
||||||
|
let windowFocusPromise = promiseWindowFocus(window);
|
||||||
|
window.focus();
|
||||||
|
return windowFocusPromise;
|
||||||
|
})().then(() => {
|
||||||
|
// can't just pass `callback`, as we can't JSON-ify the events it'd get passed.
|
||||||
|
callback()
|
||||||
|
});
|
||||||
|
""")
|
||||||
|
|
||||||
|
def open_window_in_foreground(self):
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.marionette.navigate(self.test_page)
|
||||||
|
link = self.marionette.find_element(By.ID, "new-window")
|
||||||
|
link.click()
|
||||||
|
|
||||||
def test_switch_tabs_for_new_background_window_without_focus_change(self):
|
def test_switch_tabs_for_new_background_window_without_focus_change(self):
|
||||||
# Open an additional tab in the original window so we can better check
|
# Open an addition tab in the original window so we can better check
|
||||||
# the selected index in thew new window to be opened.
|
# the selected index in thew new window to be opened.
|
||||||
second_tab = self.open_tab(focus=True)
|
second_tab = self.open_tab(trigger=self.open_tab_in_foreground)
|
||||||
self.marionette.switch_to_window(second_tab, focus=True)
|
self.marionette.switch_to_window(second_tab, focus=True)
|
||||||
second_tab_index = self.get_selected_tab_index()
|
second_tab_index = self.get_selected_tab_index()
|
||||||
self.assertNotEqual(second_tab_index, self.selected_tab_index)
|
self.assertNotEqual(second_tab_index, self.selected_tab_index)
|
||||||
|
|
||||||
# Open a new background window, but we are interested in the tab
|
# Opens a new background window, but we are interested in the tab
|
||||||
with self.marionette.using_context("content"):
|
tab_in_new_window = self.open_tab(trigger=self.open_window_in_background)
|
||||||
tab_in_new_window = self.open_window()
|
|
||||||
self.assertEqual(self.marionette.current_window_handle, second_tab)
|
self.assertEqual(self.marionette.current_window_handle, second_tab)
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
self.assertEqual(self.get_selected_tab_index(), second_tab_index)
|
self.assertEqual(self.get_selected_tab_index(), second_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.empty_page)
|
||||||
|
|
||||||
# Switch to the tab in the new window but don't focus it
|
# Switch to the tab in the new window but don't focus it
|
||||||
self.marionette.switch_to_window(tab_in_new_window, focus=False)
|
self.marionette.switch_to_window(tab_in_new_window, focus=False)
|
||||||
self.assertEqual(self.marionette.current_window_handle, tab_in_new_window)
|
self.assertEqual(self.marionette.current_window_handle, tab_in_new_window)
|
||||||
self.assertNotEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertNotEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
self.assertEqual(self.get_selected_tab_index(), second_tab_index)
|
self.assertEqual(self.get_selected_tab_index(), second_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), "about:blank")
|
||||||
|
|
||||||
def test_switch_tabs_for_new_foreground_window_with_focus_change(self):
|
def test_switch_tabs_for_new_foreground_window_with_focus_change(self):
|
||||||
# Open an addition tab in the original window so we can better check
|
# Open an addition tab in the original window so we can better check
|
||||||
# the selected index in thew new window to be opened.
|
# the selected index in thew new window to be opened.
|
||||||
second_tab = self.open_tab()
|
second_tab = self.open_tab(trigger=self.open_tab_in_foreground)
|
||||||
self.marionette.switch_to_window(second_tab, focus=True)
|
self.marionette.switch_to_window(second_tab, focus=True)
|
||||||
second_tab_index = self.get_selected_tab_index()
|
second_tab_index = self.get_selected_tab_index()
|
||||||
self.assertNotEqual(second_tab_index, self.selected_tab_index)
|
self.assertNotEqual(second_tab_index, self.selected_tab_index)
|
||||||
|
|
||||||
# Opens a new window, but we are interested in the tab
|
# Opens a new window, but we are interested in the tab
|
||||||
with self.marionette.using_context("content"):
|
tab_in_new_window = self.open_tab(trigger=self.open_window_in_foreground)
|
||||||
tab_in_new_window = self.open_window(focus=True)
|
|
||||||
self.assertEqual(self.marionette.current_window_handle, second_tab)
|
self.assertEqual(self.marionette.current_window_handle, second_tab)
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
self.assertNotEqual(self.get_selected_tab_index(), second_tab_index)
|
self.assertNotEqual(self.get_selected_tab_index(), second_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
self.marionette.switch_to_window(tab_in_new_window)
|
self.marionette.switch_to_window(tab_in_new_window)
|
||||||
self.assertEqual(self.marionette.current_window_handle, tab_in_new_window)
|
self.assertEqual(self.marionette.current_window_handle, tab_in_new_window)
|
||||||
self.assertNotEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertNotEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
self.assertNotEqual(self.get_selected_tab_index(), second_tab_index)
|
self.assertNotEqual(self.get_selected_tab_index(), second_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.empty_page)
|
||||||
|
|
||||||
self.marionette.switch_to_window(second_tab, focus=True)
|
self.marionette.switch_to_window(second_tab, focus=True)
|
||||||
self.assertEqual(self.marionette.current_window_handle, second_tab)
|
self.assertEqual(self.marionette.current_window_handle, second_tab)
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
# Bug 1335085 - The focus doesn't change even as requested so.
|
# Bug 1335085 - The focus doesn't change even as requested so.
|
||||||
# self.assertEqual(self.get_selected_tab_index(), second_tab_index)
|
# self.assertEqual(self.get_selected_tab_index(), second_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
def test_switch_tabs_for_new_foreground_window_without_focus_change(self):
|
def test_switch_tabs_for_new_foreground_window_without_focus_change(self):
|
||||||
# Open an addition tab in the original window so we can better check
|
# Open an addition tab in the original window so we can better check
|
||||||
# the selected index in thew new window to be opened.
|
# the selected index in thew new window to be opened.
|
||||||
second_tab = self.open_tab()
|
second_tab = self.open_tab(trigger=self.open_tab_in_foreground)
|
||||||
self.marionette.switch_to_window(second_tab, focus=True)
|
self.marionette.switch_to_window(second_tab, focus=True)
|
||||||
second_tab_index = self.get_selected_tab_index()
|
second_tab_index = self.get_selected_tab_index()
|
||||||
self.assertNotEqual(second_tab_index, self.selected_tab_index)
|
self.assertNotEqual(second_tab_index, self.selected_tab_index)
|
||||||
|
|
||||||
self.open_window(focus=True)
|
# Opens a new window, but we are interested in the tab which automatically
|
||||||
|
# gets the focus.
|
||||||
|
self.open_tab(trigger=self.open_window_in_foreground)
|
||||||
self.assertEqual(self.marionette.current_window_handle, second_tab)
|
self.assertEqual(self.marionette.current_window_handle, second_tab)
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
self.assertNotEqual(self.get_selected_tab_index(), second_tab_index)
|
self.assertNotEqual(self.get_selected_tab_index(), second_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
# Switch to the second tab in the first window, but don't focus it.
|
# Switch to the second tab in the first window, but don't focus it.
|
||||||
self.marionette.switch_to_window(second_tab, focus=False)
|
self.marionette.switch_to_window(second_tab, focus=False)
|
||||||
self.assertEqual(self.marionette.current_window_handle, second_tab)
|
self.assertEqual(self.marionette.current_window_handle, second_tab)
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
self.assertNotEqual(self.get_selected_tab_index(), second_tab_index)
|
self.assertNotEqual(self.get_selected_tab_index(), second_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from marionette_driver import By
|
from marionette_driver import Actions, By, Wait
|
||||||
from marionette_driver.keys import Keys
|
from marionette_driver.keys import Keys
|
||||||
|
|
||||||
from marionette_harness import MarionetteTestCase, WindowManagerMixin
|
from marionette_harness import MarionetteTestCase, skip_if_mobile, WindowManagerMixin
|
||||||
|
|
||||||
|
|
||||||
class TestSwitchToWindowContent(WindowManagerMixin, MarionetteTestCase):
|
class TestSwitchToWindowContent(WindowManagerMixin, MarionetteTestCase):
|
||||||
@ -20,8 +20,14 @@ class TestSwitchToWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
else:
|
else:
|
||||||
self.mod_key = Keys.CONTROL
|
self.mod_key = Keys.CONTROL
|
||||||
|
|
||||||
|
self.empty_page = self.marionette.absolute_url("empty.html")
|
||||||
|
self.test_page = self.marionette.absolute_url("windowHandles.html")
|
||||||
|
|
||||||
self.selected_tab_index = self.get_selected_tab_index()
|
self.selected_tab_index = self.get_selected_tab_index()
|
||||||
|
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.marionette.navigate(self.test_page)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.close_all_tabs()
|
self.close_all_tabs()
|
||||||
|
|
||||||
@ -63,51 +69,78 @@ class TestSwitchToWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
def open_tab_in_background(self):
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
link = self.marionette.find_element(By.ID, "new-tab")
|
||||||
|
|
||||||
|
action = Actions(self.marionette)
|
||||||
|
action.key_down(self.mod_key).click(link).perform()
|
||||||
|
|
||||||
|
def open_tab_in_foreground(self):
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
link = self.marionette.find_element(By.ID, "new-tab")
|
||||||
|
link.click()
|
||||||
|
|
||||||
def test_switch_tabs_with_focus_change(self):
|
def test_switch_tabs_with_focus_change(self):
|
||||||
new_tab = self.open_tab(focus=True)
|
new_tab = self.open_tab(self.open_tab_in_foreground)
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
self.assertNotEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
self.assertNotEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
# Switch to new tab first because it is already selected
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||||
self.assertNotEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
self.assertNotEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
||||||
|
|
||||||
# Switch to original tab by explicitely setting the focus
|
with self.marionette.using_context("content"):
|
||||||
|
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
|
||||||
|
lambda _: self.marionette.get_url() == self.empty_page,
|
||||||
|
message="{} has been loaded in the newly opened tab.".format(self.empty_page))
|
||||||
|
|
||||||
self.marionette.switch_to_window(self.start_tab, focus=True)
|
self.marionette.switch_to_window(self.start_tab, focus=True)
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
self.assertEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
self.assertEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
|
|
||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
|
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
self.assertEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
self.assertEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
def test_switch_tabs_without_focus_change(self):
|
def test_switch_tabs_without_focus_change(self):
|
||||||
new_tab = self.open_tab(focus=True)
|
new_tab = self.open_tab(self.open_tab_in_foreground)
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
self.assertNotEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
self.assertNotEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
# Switch to new tab first because it is already selected
|
# Switch to new tab first because it is already selected
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||||
|
|
||||||
# Switch to original tab by explicitely not setting the focus
|
|
||||||
self.marionette.switch_to_window(self.start_tab, focus=False)
|
self.marionette.switch_to_window(self.start_tab, focus=False)
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
self.assertNotEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
self.assertNotEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
||||||
|
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
|
|
||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
self.assertEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
self.assertEqual(self.get_selected_tab_index(), self.selected_tab_index)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
def test_switch_from_content_to_chrome_window_should_not_change_selected_tab(self):
|
def test_switch_from_content_to_chrome_window_should_not_change_selected_tab(self):
|
||||||
new_tab = self.open_tab(focus=True)
|
new_tab = self.open_tab(self.open_tab_in_foreground)
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||||
@ -117,31 +150,24 @@ class TestSwitchToWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||||
self.assertEqual(self.get_selected_tab_index(), new_tab_index)
|
self.assertEqual(self.get_selected_tab_index(), new_tab_index)
|
||||||
|
|
||||||
def test_switch_to_new_private_browsing_tab(self):
|
@skip_if_mobile("New windows not supported in Fennec")
|
||||||
|
def test_switch_to_new_private_browsing_window_has_to_register_browsers(self):
|
||||||
# Test that tabs (browsers) are correctly registered for a newly opened
|
# Test that tabs (browsers) are correctly registered for a newly opened
|
||||||
# private browsing window/tab. This has to also happen without explicitely
|
# private browsing window. This has to also happen without explicitely
|
||||||
# switching to the tab itself before using any commands in content scope.
|
# switching to the tab itself before using any commands in content scope.
|
||||||
#
|
#
|
||||||
# Note: Not sure why this only affects private browsing windows only.
|
# Note: Not sure why this only affects private browsing windows only.
|
||||||
new_tab = self.open_tab(focus=True)
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
|
||||||
|
|
||||||
def open_private_browsing_window_firefox():
|
|
||||||
with self.marionette.using_context("content"):
|
|
||||||
self.marionette.find_element(By.ID, "startPrivateBrowsing").click()
|
|
||||||
|
|
||||||
def open_private_browsing_tab_fennec():
|
|
||||||
with self.marionette.using_context("content"):
|
|
||||||
self.marionette.find_element(By.ID, "newPrivateTabLink").click()
|
|
||||||
|
|
||||||
|
def open_private_browsing_window():
|
||||||
with self.marionette.using_context("content"):
|
with self.marionette.using_context("content"):
|
||||||
self.marionette.navigate("about:privatebrowsing")
|
self.marionette.navigate("about:privatebrowsing")
|
||||||
if self.marionette.session_capabilities["browserName"] == "fennec":
|
button = self.marionette.find_element(By.ID, "startPrivateBrowsing")
|
||||||
new_pb_tab = self.open_tab(open_private_browsing_tab_fennec)
|
button.click()
|
||||||
else:
|
|
||||||
new_pb_tab = self.open_tab(open_private_browsing_window_firefox)
|
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_pb_tab)
|
new_window = self.open_window(open_private_browsing_window)
|
||||||
self.assertEqual(self.marionette.current_window_handle, new_pb_tab)
|
self.marionette.switch_to_window(new_window)
|
||||||
|
self.assertEqual(self.marionette.current_chrome_window_handle, new_window)
|
||||||
|
self.assertNotEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
self.marionette.execute_script(" return true; ")
|
self.marionette.execute_script(" return true; ")
|
||||||
|
@ -21,14 +21,14 @@ class TestCloseWindow(WindowManagerMixin, MarionetteTestCase):
|
|||||||
super(TestCloseWindow, self).tearDown()
|
super(TestCloseWindow, self).tearDown()
|
||||||
|
|
||||||
def test_close_chrome_window_for_browser_window(self):
|
def test_close_chrome_window_for_browser_window(self):
|
||||||
new_window = self.open_window()
|
win = self.open_window()
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(win)
|
||||||
|
|
||||||
self.assertNotIn(new_window, self.marionette.window_handles)
|
self.assertNotIn(win, self.marionette.window_handles)
|
||||||
chrome_window_handles = self.marionette.close_chrome_window()
|
chrome_window_handles = self.marionette.close_chrome_window()
|
||||||
self.assertNotIn(new_window, chrome_window_handles)
|
self.assertNotIn(win, chrome_window_handles)
|
||||||
self.assertListEqual(self.start_windows, chrome_window_handles)
|
self.assertListEqual(self.start_windows, chrome_window_handles)
|
||||||
self.assertNotIn(new_window, self.marionette.window_handles)
|
self.assertNotIn(win, self.marionette.window_handles)
|
||||||
|
|
||||||
def test_close_chrome_window_for_non_browser_window(self):
|
def test_close_chrome_window_for_non_browser_window(self):
|
||||||
win = self.open_chrome_window("chrome://marionette/content/test.xul")
|
win = self.open_chrome_window("chrome://marionette/content/test.xul")
|
||||||
@ -50,20 +50,20 @@ class TestCloseWindow(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.assertIsNotNone(self.marionette.session)
|
self.assertIsNotNone(self.marionette.session)
|
||||||
|
|
||||||
def test_close_window_for_browser_tab(self):
|
def test_close_window_for_browser_tab(self):
|
||||||
new_tab = self.open_tab()
|
tab = self.open_tab()
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(tab)
|
||||||
|
|
||||||
window_handles = self.marionette.close()
|
window_handles = self.marionette.close()
|
||||||
self.assertNotIn(new_tab, window_handles)
|
self.assertNotIn(tab, window_handles)
|
||||||
self.assertListEqual(self.start_tabs, window_handles)
|
self.assertListEqual(self.start_tabs, window_handles)
|
||||||
|
|
||||||
def test_close_window_for_browser_window_with_single_tab(self):
|
def test_close_window_for_browser_window_with_single_tab(self):
|
||||||
new_window = self.open_window()
|
win = self.open_window()
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(win)
|
||||||
|
|
||||||
self.assertEqual(len(self.start_tabs) + 1, len(self.marionette.window_handles))
|
self.assertEqual(len(self.start_tabs) + 1, len(self.marionette.window_handles))
|
||||||
window_handles = self.marionette.close()
|
window_handles = self.marionette.close()
|
||||||
self.assertNotIn(new_window, window_handles)
|
self.assertNotIn(win, window_handles)
|
||||||
self.assertListEqual(self.start_tabs, window_handles)
|
self.assertListEqual(self.start_tabs, window_handles)
|
||||||
self.assertListEqual(self.start_windows, self.marionette.chrome_window_handles)
|
self.assertListEqual(self.start_windows, self.marionette.chrome_window_handles)
|
||||||
|
|
||||||
|
@ -24,27 +24,26 @@ class TestCloseWindow(WindowManagerMixin, MarionetteTestCase):
|
|||||||
|
|
||||||
@skip_if_mobile("Interacting with chrome windows not available for Fennec")
|
@skip_if_mobile("Interacting with chrome windows not available for Fennec")
|
||||||
def test_close_chrome_window_for_browser_window(self):
|
def test_close_chrome_window_for_browser_window(self):
|
||||||
with self.marionette.using_context("chrome"):
|
win = self.open_window()
|
||||||
new_window = self.open_window()
|
self.marionette.switch_to_window(win)
|
||||||
self.marionette.switch_to_window(new_window)
|
|
||||||
|
|
||||||
self.assertIn(new_window, self.marionette.chrome_window_handles)
|
self.assertNotIn(win, self.marionette.window_handles)
|
||||||
chrome_window_handles = self.marionette.close_chrome_window()
|
chrome_window_handles = self.marionette.close_chrome_window()
|
||||||
self.assertNotIn(new_window, chrome_window_handles)
|
self.assertNotIn(win, chrome_window_handles)
|
||||||
self.assertListEqual(self.start_windows, chrome_window_handles)
|
self.assertListEqual(self.start_windows, chrome_window_handles)
|
||||||
self.assertNotIn(new_window, self.marionette.window_handles)
|
self.assertNotIn(win, self.marionette.window_handles)
|
||||||
|
|
||||||
@skip_if_mobile("Interacting with chrome windows not available for Fennec")
|
@skip_if_mobile("Interacting with chrome windows not available for Fennec")
|
||||||
def test_close_chrome_window_for_non_browser_window(self):
|
def test_close_chrome_window_for_non_browser_window(self):
|
||||||
new_window = self.open_chrome_window("chrome://marionette/content/test.xul")
|
win = self.open_chrome_window("chrome://marionette/content/test.xul")
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(win)
|
||||||
|
|
||||||
self.assertIn(new_window, self.marionette.chrome_window_handles)
|
self.assertIn(win, self.marionette.chrome_window_handles)
|
||||||
self.assertNotIn(new_window, self.marionette.window_handles)
|
self.assertNotIn(win, self.marionette.window_handles)
|
||||||
chrome_window_handles = self.marionette.close_chrome_window()
|
chrome_window_handles = self.marionette.close_chrome_window()
|
||||||
self.assertNotIn(new_window, chrome_window_handles)
|
self.assertNotIn(win, chrome_window_handles)
|
||||||
self.assertListEqual(self.start_windows, chrome_window_handles)
|
self.assertListEqual(self.start_windows, chrome_window_handles)
|
||||||
self.assertNotIn(new_window, self.marionette.window_handles)
|
self.assertNotIn(win, self.marionette.window_handles)
|
||||||
|
|
||||||
@skip_if_mobile("Interacting with chrome windows not available for Fennec")
|
@skip_if_mobile("Interacting with chrome windows not available for Fennec")
|
||||||
def test_close_chrome_window_for_last_open_window(self):
|
def test_close_chrome_window_for_last_open_window(self):
|
||||||
@ -55,17 +54,19 @@ class TestCloseWindow(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.assertListEqual([self.start_window], self.marionette.chrome_window_handles)
|
self.assertListEqual([self.start_window], self.marionette.chrome_window_handles)
|
||||||
self.assertIsNotNone(self.marionette.session)
|
self.assertIsNotNone(self.marionette.session)
|
||||||
|
|
||||||
|
@skip_if_mobile("Needs application independent method to open a new tab")
|
||||||
def test_close_window_for_browser_tab(self):
|
def test_close_window_for_browser_tab(self):
|
||||||
new_tab = self.open_tab()
|
tab = self.open_tab()
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(tab)
|
||||||
|
|
||||||
window_handles = self.marionette.close()
|
window_handles = self.marionette.close()
|
||||||
self.assertNotIn(new_tab, window_handles)
|
self.assertNotIn(tab, window_handles)
|
||||||
self.assertListEqual(self.start_tabs, window_handles)
|
self.assertListEqual(self.start_tabs, window_handles)
|
||||||
|
|
||||||
|
@skip_if_mobile("Needs application independent method to open a new tab")
|
||||||
def test_close_window_with_dismissed_beforeunload_prompt(self):
|
def test_close_window_with_dismissed_beforeunload_prompt(self):
|
||||||
new_tab = self.open_tab()
|
tab = self.open_tab()
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(tab)
|
||||||
|
|
||||||
self.marionette.navigate(inline("""
|
self.marionette.navigate(inline("""
|
||||||
<input type="text">
|
<input type="text">
|
||||||
@ -81,12 +82,12 @@ class TestCloseWindow(WindowManagerMixin, MarionetteTestCase):
|
|||||||
|
|
||||||
@skip_if_mobile("Interacting with chrome windows not available for Fennec")
|
@skip_if_mobile("Interacting with chrome windows not available for Fennec")
|
||||||
def test_close_window_for_browser_window_with_single_tab(self):
|
def test_close_window_for_browser_window_with_single_tab(self):
|
||||||
new_tab = self.open_window()
|
win = self.open_window()
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(win)
|
||||||
|
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
self.assertEqual(len(self.start_tabs) + 1, len(self.marionette.window_handles))
|
||||||
window_handles = self.marionette.close()
|
window_handles = self.marionette.close()
|
||||||
self.assertNotIn(new_tab, window_handles)
|
self.assertNotIn(win, window_handles)
|
||||||
self.assertListEqual(self.start_tabs, window_handles)
|
self.assertListEqual(self.start_tabs, window_handles)
|
||||||
self.assertListEqual(self.start_windows, self.marionette.chrome_window_handles)
|
self.assertListEqual(self.start_windows, self.marionette.chrome_window_handles)
|
||||||
|
|
||||||
@ -103,8 +104,8 @@ class TestCloseWindow(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.close_all_tabs()
|
self.close_all_tabs()
|
||||||
|
|
||||||
test_page = self.marionette.absolute_url("windowHandles.html")
|
test_page = self.marionette.absolute_url("windowHandles.html")
|
||||||
new_tab = self.open_tab()
|
tab = self.open_tab()
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(tab)
|
||||||
self.marionette.navigate(test_page)
|
self.marionette.navigate(test_page)
|
||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ from __future__ import absolute_import
|
|||||||
|
|
||||||
import types
|
import types
|
||||||
|
|
||||||
from marionette_driver import errors
|
from marionette_driver import By, errors, Wait
|
||||||
|
|
||||||
from marionette_harness import MarionetteTestCase, WindowManagerMixin
|
from marionette_harness import MarionetteTestCase, WindowManagerMixin
|
||||||
|
|
||||||
@ -16,7 +16,9 @@ class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestWindowHandles, self).setUp()
|
super(TestWindowHandles, self).setUp()
|
||||||
|
|
||||||
self.xul_dialog = "chrome://marionette/content/test_dialog.xul"
|
self.empty_page = self.marionette.absolute_url("empty.html")
|
||||||
|
self.test_page = self.marionette.absolute_url("windowHandles.html")
|
||||||
|
self.marionette.navigate(self.test_page)
|
||||||
|
|
||||||
self.marionette.set_context("chrome")
|
self.marionette.set_context("chrome")
|
||||||
|
|
||||||
@ -40,16 +42,17 @@ class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.assertIsInstance(handle, types.StringTypes)
|
self.assertIsInstance(handle, types.StringTypes)
|
||||||
|
|
||||||
def test_chrome_window_handles_with_scopes(self):
|
def test_chrome_window_handles_with_scopes(self):
|
||||||
new_browser = self.open_window()
|
# Open a browser and a non-browser (about window) chrome window
|
||||||
|
self.open_window(
|
||||||
|
trigger=lambda: self.marionette.execute_script("OpenBrowserWindow();"))
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 1)
|
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 1)
|
||||||
self.assertIn(new_browser, self.marionette.chrome_window_handles)
|
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
|
|
||||||
new_dialog = self.open_chrome_window(self.xul_dialog)
|
self.open_window(
|
||||||
|
trigger=lambda: self.marionette.find_element(By.ID, "aboutName").click())
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 2)
|
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 2)
|
||||||
self.assertIn(new_dialog, self.marionette.chrome_window_handles)
|
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
|
|
||||||
chrome_window_handles_in_chrome_scope = self.marionette.chrome_window_handles
|
chrome_window_handles_in_chrome_scope = self.marionette.chrome_window_handles
|
||||||
@ -61,112 +64,117 @@ class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.assertEqual(self.marionette.window_handles,
|
self.assertEqual(self.marionette.window_handles,
|
||||||
window_handles_in_chrome_scope)
|
window_handles_in_chrome_scope)
|
||||||
|
|
||||||
def test_chrome_window_handles_after_opening_new_chrome_window(self):
|
def test_chrome_window_handles_after_opening_new_dialog(self):
|
||||||
new_window = self.open_chrome_window(self.xul_dialog)
|
xul_dialog = "chrome://marionette/content/test_dialog.xul"
|
||||||
|
new_win = self.open_chrome_window(xul_dialog)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 1)
|
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 1)
|
||||||
self.assertIn(new_window, self.marionette.chrome_window_handles)
|
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
|
|
||||||
# Check that the new chrome window has the correct URL loaded
|
# Check that the new tab has the correct page loaded
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(new_win)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, new_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, new_win)
|
||||||
self.assertEqual(self.marionette.get_url(), self.xul_dialog)
|
self.assertEqual(self.marionette.get_url(), xul_dialog)
|
||||||
|
|
||||||
# Close the chrome window, and carry on in our original window.
|
# Close the opened dialog and carry on in our original tab.
|
||||||
self.marionette.close_chrome_window()
|
self.marionette.close_chrome_window()
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows))
|
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows))
|
||||||
self.assertNotIn(new_window, self.marionette.chrome_window_handles)
|
|
||||||
|
|
||||||
self.marionette.switch_to_window(self.start_window)
|
self.marionette.switch_to_window(self.start_window)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
def test_chrome_window_handles_after_opening_new_window(self):
|
def test_chrome_window_handles_after_opening_new_window(self):
|
||||||
new_window = self.open_window()
|
def open_with_link():
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
link = self.marionette.find_element(By.ID, "new-window")
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
# We open a new window but are actually interested in the new tab
|
||||||
|
new_win = self.open_window(trigger=open_with_link)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 1)
|
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 1)
|
||||||
self.assertIn(new_window, self.marionette.chrome_window_handles)
|
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_window)
|
# Check that the new tab has the correct page loaded
|
||||||
|
self.marionette.switch_to_window(new_win)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, new_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, new_win)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
|
||||||
|
lambda mn: mn.get_url() == self.empty_page,
|
||||||
|
message="{} did not load after opening a new tab".format(self.empty_page))
|
||||||
|
|
||||||
# Close the opened window and carry on in our original window.
|
# Ensure navigate works in our current window
|
||||||
|
other_page = self.marionette.absolute_url("test.html")
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.marionette.navigate(other_page)
|
||||||
|
self.assertEqual(self.marionette.get_url(), other_page)
|
||||||
|
|
||||||
|
# Close the opened window and carry on in our original tab.
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows))
|
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows))
|
||||||
self.assertNotIn(new_window, self.marionette.chrome_window_handles)
|
|
||||||
|
|
||||||
self.marionette.switch_to_window(self.start_window)
|
self.marionette.switch_to_window(self.start_window)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
def test_window_handles_after_opening_new_tab(self):
|
def test_window_handles_after_opening_new_tab(self):
|
||||||
|
def open_with_link():
|
||||||
with self.marionette.using_context("content"):
|
with self.marionette.using_context("content"):
|
||||||
new_tab = self.open_tab()
|
link = self.marionette.find_element(By.ID, "new-tab")
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
new_tab = self.open_tab(trigger=open_with_link)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||||
self.assertIn(new_tab, self.marionette.window_handles)
|
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
|
||||||
|
lambda mn: mn.get_url() == self.empty_page,
|
||||||
|
message="{} did not load after opening a new tab".format(self.empty_page))
|
||||||
|
|
||||||
|
# Ensure navigate works in our current tab
|
||||||
|
other_page = self.marionette.absolute_url("test.html")
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.marionette.navigate(other_page)
|
||||||
|
self.assertEqual(self.marionette.get_url(), other_page)
|
||||||
|
|
||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||||
self.assertNotIn(new_tab, self.marionette.window_handles)
|
|
||||||
|
|
||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
self.assert_window_handles()
|
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
def test_window_handles_after_opening_new_foreground_tab(self):
|
def test_window_handles_after_opening_new_dialog(self):
|
||||||
with self.marionette.using_context("content"):
|
xul_dialog = "chrome://marionette/content/test_dialog.xul"
|
||||||
new_tab = self.open_tab(focus=True)
|
new_win = self.open_chrome_window(xul_dialog)
|
||||||
self.assert_window_handles()
|
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
|
||||||
self.assertIn(new_tab, self.marionette.window_handles)
|
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
|
||||||
|
|
||||||
# We still have the default tab set as our window handle. This
|
|
||||||
# get_url command should be sent immediately, and not be forever-queued.
|
|
||||||
with self.marionette.using_context("content"):
|
|
||||||
self.marionette.get_url()
|
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
|
||||||
self.assert_window_handles()
|
|
||||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
|
||||||
|
|
||||||
self.marionette.close()
|
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||||
self.assertNotIn(new_tab, self.marionette.window_handles)
|
|
||||||
|
|
||||||
self.marionette.switch_to_window(self.start_tab)
|
|
||||||
self.assert_window_handles()
|
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
def test_window_handles_after_opening_new_chrome_window(self):
|
self.marionette.switch_to_window(new_win)
|
||||||
new_window = self.open_chrome_window(self.xul_dialog)
|
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
self.assertEqual(self.marionette.get_url(), xul_dialog)
|
||||||
self.assertNotIn(new_window, self.marionette.window_handles)
|
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_window)
|
|
||||||
self.assert_window_handles()
|
|
||||||
self.assertEqual(self.marionette.get_url(), self.xul_dialog)
|
|
||||||
|
|
||||||
# Check that the opened dialog is not accessible via window handles
|
# Check that the opened dialog is not accessible via window handles
|
||||||
with self.assertRaises(errors.NoSuchWindowException):
|
with self.assertRaises(errors.NoSuchWindowException):
|
||||||
@ -182,24 +190,112 @@ class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
def test_window_handles_after_closing_original_tab(self):
|
|
||||||
with self.marionette.using_context("content"):
|
with self.marionette.using_context("content"):
|
||||||
new_tab = self.open_tab()
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
|
def test_window_handles_after_opening_new_window(self):
|
||||||
|
def open_with_link():
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
link = self.marionette.find_element(By.ID, "new-window")
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
# We open a new window but are actually interested in the new tab
|
||||||
|
new_tab = self.open_tab(trigger=open_with_link)
|
||||||
|
self.assert_window_handles()
|
||||||
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||||
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
|
# Check that the new tab has the correct page loaded
|
||||||
|
self.marionette.switch_to_window(new_tab)
|
||||||
|
self.assert_window_handles()
|
||||||
|
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
|
||||||
|
lambda mn: mn.get_url() == self.empty_page,
|
||||||
|
message="{} did not load after opening a new tab".format(self.empty_page))
|
||||||
|
|
||||||
|
# Ensure navigate works in our current window
|
||||||
|
other_page = self.marionette.absolute_url("test.html")
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.marionette.navigate(other_page)
|
||||||
|
self.assertEqual(self.marionette.get_url(), other_page)
|
||||||
|
|
||||||
|
# Close the opened window and carry on in our original tab.
|
||||||
|
self.marionette.close()
|
||||||
|
self.assert_window_handles()
|
||||||
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||||
|
|
||||||
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
|
self.assert_window_handles()
|
||||||
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
|
def test_window_handles_after_closing_original_tab(self):
|
||||||
|
def open_with_link():
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
link = self.marionette.find_element(By.ID, "new-tab")
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
new_tab = self.open_tab(trigger=open_with_link)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||||
self.assertIn(new_tab, self.marionette.window_handles)
|
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||||
self.assertIn(new_tab, self.marionette.window_handles)
|
|
||||||
|
self.marionette.switch_to_window(new_tab)
|
||||||
|
self.assert_window_handles()
|
||||||
|
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
|
||||||
|
lambda mn: mn.get_url() == self.empty_page,
|
||||||
|
message="{} did not load after opening a new tab".format(self.empty_page))
|
||||||
|
|
||||||
|
def test_window_handles_no_switch(self):
|
||||||
|
"""Regression test for bug 1294456.
|
||||||
|
This test is testing the case where Marionette attempts to send a
|
||||||
|
command to a window handle when the browser has opened and selected
|
||||||
|
a new tab. Before bug 1294456 landed, the Marionette driver was getting
|
||||||
|
confused about which window handle the client cared about, and assumed
|
||||||
|
it was the window handle for the newly opened and selected tab.
|
||||||
|
|
||||||
|
This caused Marionette to think that the browser needed to do a remoteness
|
||||||
|
flip in the e10s case, since the tab opened by menu_newNavigatorTab is
|
||||||
|
about:newtab (which is currently non-remote). This meant that commands
|
||||||
|
sent to what should have been the original window handle would be
|
||||||
|
queued and never sent, since the remoteness flip in the new tab was
|
||||||
|
never going to happen.
|
||||||
|
"""
|
||||||
|
def open_with_menu():
|
||||||
|
menu_new_tab = self.marionette.find_element(By.ID, 'menu_newNavigatorTab')
|
||||||
|
menu_new_tab.click()
|
||||||
|
|
||||||
|
new_tab = self.open_tab(trigger=open_with_menu)
|
||||||
|
self.assert_window_handles()
|
||||||
|
|
||||||
|
# We still have the default tab set as our window handle. This
|
||||||
|
# get_url command should be sent immediately, and not be forever-queued.
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||||
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||||
|
|
||||||
|
self.marionette.close()
|
||||||
|
self.assert_window_handles()
|
||||||
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||||
|
|
||||||
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
|
self.assert_window_handles()
|
||||||
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
def test_window_handles_after_closing_last_window(self):
|
def test_window_handles_after_closing_last_window(self):
|
||||||
self.close_all_windows()
|
self.close_all_windows()
|
||||||
self.assertEqual(self.marionette.close_chrome_window(), [])
|
self.assertEqual(self.marionette.close_chrome_window(), [])
|
||||||
|
@ -7,7 +7,7 @@ from __future__ import absolute_import
|
|||||||
import types
|
import types
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
from marionette_driver import errors
|
from marionette_driver import By, errors, Wait
|
||||||
|
|
||||||
from marionette_harness import MarionetteTestCase, skip_if_mobile, WindowManagerMixin
|
from marionette_harness import MarionetteTestCase, skip_if_mobile, WindowManagerMixin
|
||||||
|
|
||||||
@ -21,7 +21,9 @@ class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestWindowHandles, self).setUp()
|
super(TestWindowHandles, self).setUp()
|
||||||
|
|
||||||
self.xul_dialog = "chrome://marionette/content/test_dialog.xul"
|
self.empty_page = self.marionette.absolute_url("empty.html")
|
||||||
|
self.test_page = self.marionette.absolute_url("windowHandles.html")
|
||||||
|
self.marionette.navigate(self.test_page)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.close_all_tabs()
|
self.close_all_tabs()
|
||||||
@ -37,8 +39,12 @@ class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
|||||||
for handle in self.marionette.window_handles:
|
for handle in self.marionette.window_handles:
|
||||||
self.assertIsInstance(handle, types.StringTypes)
|
self.assertIsInstance(handle, types.StringTypes)
|
||||||
|
|
||||||
def tst_window_handles_after_opening_new_tab(self):
|
def test_window_handles_after_opening_new_tab(self):
|
||||||
new_tab = self.open_tab()
|
def open_with_link():
|
||||||
|
link = self.marionette.find_element(By.ID, "new-tab")
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
new_tab = self.open_tab(trigger=open_with_link)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
@ -46,9 +52,13 @@ class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||||
|
Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
|
||||||
|
lambda mn: mn.get_url() == self.empty_page,
|
||||||
|
message="{} did not load after opening a new tab".format(self.empty_page))
|
||||||
|
|
||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
@ -59,15 +69,29 @@ class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
def tst_window_handles_after_opening_new_browser_window(self):
|
def test_window_handles_after_opening_new_browser_window(self):
|
||||||
new_tab = self.open_window()
|
def open_with_link():
|
||||||
|
link = self.marionette.find_element(By.ID, "new-window")
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
# We open a new window but are actually interested in the new tab
|
||||||
|
new_tab = self.open_tab(trigger=open_with_link)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
|
# Check that the new tab has the correct page loaded
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||||
|
Wait(self.marionette, self.marionette.timeout.page_load).until(
|
||||||
|
lambda _: self.marionette.get_url() == self.empty_page,
|
||||||
|
message="The expected page '{}' has not been loaded".format(self.empty_page))
|
||||||
|
|
||||||
|
# Ensure navigate works in our current window
|
||||||
|
other_page = self.marionette.absolute_url("test.html")
|
||||||
|
self.marionette.navigate(other_page)
|
||||||
|
self.assertEqual(self.marionette.get_url(), other_page)
|
||||||
|
|
||||||
# Close the opened window and carry on in our original tab.
|
# Close the opened window and carry on in our original tab.
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
@ -77,16 +101,31 @@ class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||||
|
|
||||||
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
||||||
def tst_window_handles_after_opening_new_non_browser_window(self):
|
def test_window_handles_after_opening_new_non_browser_window(self):
|
||||||
new_window = self.open_chrome_window(self.xul_dialog)
|
def open_with_link():
|
||||||
|
self.marionette.navigate(inline("""
|
||||||
|
<a id="blob-download" download="foo.html">Download</a>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const string = "test";
|
||||||
|
const blob = new Blob([string], { type: "text/html" });
|
||||||
|
|
||||||
|
const link = document.getElementById("blob-download");
|
||||||
|
link.href = URL.createObjectURL(blob);
|
||||||
|
</script>
|
||||||
|
"""))
|
||||||
|
link = self.marionette.find_element(By.ID, "blob-download")
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
new_win = self.open_window(trigger=open_with_link)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
self.assertNotIn(new_window, self.marionette.window_handles)
|
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(new_win)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
|
|
||||||
# Check that the opened window is not accessible via window handles
|
# Check that the opened window is not accessible via window handles
|
||||||
@ -105,21 +144,26 @@ class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
|
|
||||||
def test_window_handles_after_closing_original_tab(self):
|
def test_window_handles_after_closing_original_tab(self):
|
||||||
new_tab = self.open_tab()
|
def open_with_link():
|
||||||
|
link = self.marionette.find_element(By.ID, "new-tab")
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
new_tab = self.open_tab(trigger=open_with_link)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||||
self.assertIn(new_tab, self.marionette.window_handles)
|
|
||||||
|
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||||
self.assertNotIn(self.start_tab, self.marionette.window_handles)
|
|
||||||
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(new_tab)
|
||||||
self.assert_window_handles()
|
self.assert_window_handles()
|
||||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||||
|
Wait(self.marionette, self.marionette.timeout.page_load).until(
|
||||||
|
lambda _: self.marionette.get_url() == self.empty_page,
|
||||||
|
message="The expected page '{}' has not been loaded".format(self.empty_page))
|
||||||
|
|
||||||
def tst_window_handles_after_closing_last_tab(self):
|
def test_window_handles_after_closing_last_tab(self):
|
||||||
self.close_all_tabs()
|
self.close_all_tabs()
|
||||||
self.assertEqual(self.marionette.close(), [])
|
self.assertEqual(self.marionette.close(), [])
|
||||||
|
@ -21,9 +21,15 @@ class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
|
|
||||||
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
||||||
def test_closed_chrome_window(self):
|
def test_closed_chrome_window(self):
|
||||||
with self.marionette.using_context("chrome"):
|
|
||||||
new_window = self.open_window()
|
def open_with_link():
|
||||||
self.marionette.switch_to_window(new_window)
|
with self.marionette.using_context("content"):
|
||||||
|
test_page = self.marionette.absolute_url("windowHandles.html")
|
||||||
|
self.marionette.navigate(test_page)
|
||||||
|
self.marionette.find_element(By.ID, "new-window").click()
|
||||||
|
|
||||||
|
win = self.open_window(open_with_link)
|
||||||
|
self.marionette.switch_to_window(win)
|
||||||
self.marionette.close_chrome_window()
|
self.marionette.close_chrome_window()
|
||||||
|
|
||||||
# When closing a browser window both handles are not available
|
# When closing a browser window both handles are not available
|
||||||
@ -37,12 +43,12 @@ class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.marionette.switch_to_window(self.start_window)
|
self.marionette.switch_to_window(self.start_window)
|
||||||
|
|
||||||
with self.assertRaises(NoSuchWindowException):
|
with self.assertRaises(NoSuchWindowException):
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(win)
|
||||||
|
|
||||||
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
||||||
def test_closed_chrome_window_while_in_frame(self):
|
def test_closed_chrome_window_while_in_frame(self):
|
||||||
new_window = self.open_chrome_window("chrome://marionette/content/test.xul")
|
win = self.open_chrome_window("chrome://marionette/content/test.xul")
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(win)
|
||||||
with self.marionette.using_context("chrome"):
|
with self.marionette.using_context("chrome"):
|
||||||
self.marionette.switch_to_frame("iframe")
|
self.marionette.switch_to_frame("iframe")
|
||||||
self.marionette.close_chrome_window()
|
self.marionette.close_chrome_window()
|
||||||
@ -55,11 +61,12 @@ class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.marionette.switch_to_window(self.start_window)
|
self.marionette.switch_to_window(self.start_window)
|
||||||
|
|
||||||
with self.assertRaises(NoSuchWindowException):
|
with self.assertRaises(NoSuchWindowException):
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(win)
|
||||||
|
|
||||||
def test_closed_tab(self):
|
def test_closed_tab(self):
|
||||||
new_tab = self.open_tab()
|
with self.marionette.using_context("content"):
|
||||||
self.marionette.switch_to_window(new_tab)
|
tab = self.open_tab()
|
||||||
|
self.marionette.switch_to_window(tab)
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
|
|
||||||
# Check that only the content window is not available in both contexts
|
# Check that only the content window is not available in both contexts
|
||||||
@ -72,13 +79,12 @@ class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
|
|
||||||
with self.assertRaises(NoSuchWindowException):
|
with self.assertRaises(NoSuchWindowException):
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(tab)
|
||||||
|
|
||||||
def test_closed_tab_while_in_frame(self):
|
def test_closed_tab_while_in_frame(self):
|
||||||
new_tab = self.open_tab()
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
|
||||||
|
|
||||||
with self.marionette.using_context("content"):
|
with self.marionette.using_context("content"):
|
||||||
|
tab = self.open_tab()
|
||||||
|
self.marionette.switch_to_window(tab)
|
||||||
self.marionette.navigate(self.marionette.absolute_url("test_iframe.html"))
|
self.marionette.navigate(self.marionette.absolute_url("test_iframe.html"))
|
||||||
frame = self.marionette.find_element(By.ID, "test_iframe")
|
frame = self.marionette.find_element(By.ID, "test_iframe")
|
||||||
self.marionette.switch_to_frame(frame)
|
self.marionette.switch_to_frame(frame)
|
||||||
@ -91,7 +97,7 @@ class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
|
|
||||||
with self.assertRaises(NoSuchWindowException):
|
with self.assertRaises(NoSuchWindowException):
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(tab)
|
||||||
|
|
||||||
|
|
||||||
class TestNoSuchWindowChrome(TestNoSuchWindowContent):
|
class TestNoSuchWindowChrome(TestNoSuchWindowContent):
|
||||||
@ -115,22 +121,42 @@ class TestSwitchWindow(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.close_all_windows()
|
self.close_all_windows()
|
||||||
super(TestSwitchWindow, self).tearDown()
|
super(TestSwitchWindow, self).tearDown()
|
||||||
|
|
||||||
def test_switch_window_after_open_and_close(self):
|
def test_windows(self):
|
||||||
with self.marionette.using_context("chrome"):
|
def open_browser_with_js():
|
||||||
new_window = self.open_window()
|
self.marionette.execute_script(" window.open(); ")
|
||||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 1)
|
|
||||||
self.assertIn(new_window, self.marionette.chrome_window_handles)
|
new_window = self.open_window(trigger=open_browser_with_js)
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
|
|
||||||
# switch to the new chrome window and close it
|
# switch to the other window
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(new_window)
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, new_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, new_window)
|
||||||
self.assertNotEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertNotEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
|
|
||||||
self.marionette.close_chrome_window()
|
# switch back and close original window
|
||||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows))
|
|
||||||
self.assertNotIn(new_window, self.marionette.chrome_window_handles)
|
|
||||||
|
|
||||||
# switch back to the original chrome window
|
|
||||||
self.marionette.switch_to_window(self.start_window)
|
self.marionette.switch_to_window(self.start_window)
|
||||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||||
|
self.marionette.close_chrome_window()
|
||||||
|
|
||||||
|
self.assertNotIn(self.start_window, self.marionette.chrome_window_handles)
|
||||||
|
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows))
|
||||||
|
|
||||||
|
def test_should_load_and_close_a_window(self):
|
||||||
|
def open_window_with_link():
|
||||||
|
test_html = self.marionette.absolute_url("test_windows.html")
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.marionette.navigate(test_html)
|
||||||
|
self.marionette.find_element(By.LINK_TEXT, "Open new window").click()
|
||||||
|
|
||||||
|
new_window = self.open_window(trigger=open_window_with_link)
|
||||||
|
self.marionette.switch_to_window(new_window)
|
||||||
|
self.assertEqual(self.marionette.current_chrome_window_handle, new_window)
|
||||||
|
self.assertEqual(len(self.marionette.chrome_window_handles), 2)
|
||||||
|
|
||||||
|
with self.marionette.using_context('content'):
|
||||||
|
self.assertEqual(self.marionette.title, "We Arrive Here")
|
||||||
|
|
||||||
|
# Let's close and check
|
||||||
|
self.marionette.close_chrome_window()
|
||||||
|
self.marionette.switch_to_window(self.start_window)
|
||||||
|
self.assertEqual(len(self.marionette.chrome_window_handles), 1)
|
||||||
|
@ -15,15 +15,30 @@ class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestNoSuchWindowContent, self).setUp()
|
super(TestNoSuchWindowContent, self).setUp()
|
||||||
|
|
||||||
|
self.test_page = self.marionette.absolute_url("windowHandles.html")
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
self.marionette.navigate(self.test_page)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.close_all_windows()
|
self.close_all_windows()
|
||||||
super(TestNoSuchWindowContent, self).tearDown()
|
super(TestNoSuchWindowContent, self).tearDown()
|
||||||
|
|
||||||
|
def open_tab_in_foreground(self):
|
||||||
|
with self.marionette.using_context("content"):
|
||||||
|
link = self.marionette.find_element(By.ID, "new-tab")
|
||||||
|
link.click()
|
||||||
|
|
||||||
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
||||||
def test_closed_chrome_window(self):
|
def test_closed_chrome_window(self):
|
||||||
with self.marionette.using_context("chrome"):
|
|
||||||
new_window = self.open_window()
|
def open_with_link():
|
||||||
self.marionette.switch_to_window(new_window)
|
with self.marionette.using_context("content"):
|
||||||
|
test_page = self.marionette.absolute_url("windowHandles.html")
|
||||||
|
self.marionette.navigate(test_page)
|
||||||
|
self.marionette.find_element(By.ID, "new-window").click()
|
||||||
|
|
||||||
|
win = self.open_window(open_with_link)
|
||||||
|
self.marionette.switch_to_window(win)
|
||||||
self.marionette.close_chrome_window()
|
self.marionette.close_chrome_window()
|
||||||
|
|
||||||
# When closing a browser window both handles are not available
|
# When closing a browser window both handles are not available
|
||||||
@ -37,13 +52,12 @@ class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.marionette.switch_to_window(self.start_window)
|
self.marionette.switch_to_window(self.start_window)
|
||||||
|
|
||||||
with self.assertRaises(NoSuchWindowException):
|
with self.assertRaises(NoSuchWindowException):
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(win)
|
||||||
|
|
||||||
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
@skip_if_mobile("Fennec doesn't support other chrome windows")
|
||||||
def test_closed_chrome_window_while_in_frame(self):
|
def test_closed_chrome_window_while_in_frame(self):
|
||||||
new_window = self.open_chrome_window("chrome://marionette/content/test.xul")
|
win = self.open_chrome_window("chrome://marionette/content/test.xul")
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(win)
|
||||||
|
|
||||||
with self.marionette.using_context("chrome"):
|
with self.marionette.using_context("chrome"):
|
||||||
self.marionette.switch_to_frame("iframe")
|
self.marionette.switch_to_frame("iframe")
|
||||||
self.marionette.close_chrome_window()
|
self.marionette.close_chrome_window()
|
||||||
@ -56,11 +70,12 @@ class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.marionette.switch_to_window(self.start_window)
|
self.marionette.switch_to_window(self.start_window)
|
||||||
|
|
||||||
with self.assertRaises(NoSuchWindowException):
|
with self.assertRaises(NoSuchWindowException):
|
||||||
self.marionette.switch_to_window(new_window)
|
self.marionette.switch_to_window(win)
|
||||||
|
|
||||||
def test_closed_tab(self):
|
def test_closed_tab(self):
|
||||||
new_tab = self.open_tab(focus=True)
|
with self.marionette.using_context("content"):
|
||||||
self.marionette.switch_to_window(new_tab)
|
tab = self.open_tab(self.open_tab_in_foreground)
|
||||||
|
self.marionette.switch_to_window(tab)
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
|
|
||||||
# Check that only the content window is not available in both contexts
|
# Check that only the content window is not available in both contexts
|
||||||
@ -73,17 +88,15 @@ class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
|
|
||||||
with self.assertRaises(NoSuchWindowException):
|
with self.assertRaises(NoSuchWindowException):
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(tab)
|
||||||
|
|
||||||
def test_closed_tab_while_in_frame(self):
|
def test_closed_tab_while_in_frame(self):
|
||||||
new_tab = self.open_tab()
|
|
||||||
self.marionette.switch_to_window(new_tab)
|
|
||||||
|
|
||||||
with self.marionette.using_context("content"):
|
with self.marionette.using_context("content"):
|
||||||
|
tab = self.open_tab(self.open_tab_in_foreground)
|
||||||
|
self.marionette.switch_to_window(tab)
|
||||||
self.marionette.navigate(self.marionette.absolute_url("test_iframe.html"))
|
self.marionette.navigate(self.marionette.absolute_url("test_iframe.html"))
|
||||||
frame = self.marionette.find_element(By.ID, "test_iframe")
|
frame = self.marionette.find_element(By.ID, "test_iframe")
|
||||||
self.marionette.switch_to_frame(frame)
|
self.marionette.switch_to_frame(frame)
|
||||||
|
|
||||||
self.marionette.close()
|
self.marionette.close()
|
||||||
|
|
||||||
with self.assertRaises(NoSuchWindowException):
|
with self.assertRaises(NoSuchWindowException):
|
||||||
@ -93,4 +106,4 @@ class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
|
|||||||
self.marionette.switch_to_window(self.start_tab)
|
self.marionette.switch_to_window(self.start_tab)
|
||||||
|
|
||||||
with self.assertRaises(NoSuchWindowException):
|
with self.assertRaises(NoSuchWindowException):
|
||||||
self.marionette.switch_to_window(new_tab)
|
self.marionette.switch_to_window(tab)
|
||||||
|
@ -15,7 +15,7 @@ ChromeUtils.import("chrome://marionette/content/evaluate.js");
|
|||||||
const {Log} = ChromeUtils.import("chrome://marionette/content/log.js", {});
|
const {Log} = ChromeUtils.import("chrome://marionette/content/log.js", {});
|
||||||
ChromeUtils.import("chrome://marionette/content/modal.js");
|
ChromeUtils.import("chrome://marionette/content/modal.js");
|
||||||
const {
|
const {
|
||||||
waitForObserverTopic,
|
MessageManagerDestroyedPromise,
|
||||||
} = ChromeUtils.import("chrome://marionette/content/sync.js", {});
|
} = ChromeUtils.import("chrome://marionette/content/sync.js", {});
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["proxy"];
|
this.EXPORTED_SYMBOLS = ["proxy"];
|
||||||
@ -156,9 +156,7 @@ proxy.AsyncMessageChannel = class {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
await waitForObserverTopic("message-manager-disconnect",
|
await new MessageManagerDestroyedPromise(messageManager);
|
||||||
subject => subject === messageManager);
|
|
||||||
|
|
||||||
this.removeHandlers();
|
this.removeHandlers();
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
|
@ -11,6 +11,7 @@ const ServerSocket = CC(
|
|||||||
"nsIServerSocket",
|
"nsIServerSocket",
|
||||||
"initSpecialConnection");
|
"initSpecialConnection");
|
||||||
|
|
||||||
|
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
ChromeUtils.import("chrome://marionette/content/assert.js");
|
ChromeUtils.import("chrome://marionette/content/assert.js");
|
||||||
@ -73,7 +74,7 @@ class TCPListener {
|
|||||||
*/
|
*/
|
||||||
driverFactory() {
|
driverFactory() {
|
||||||
MarionettePrefs.contentListener = false;
|
MarionettePrefs.contentListener = false;
|
||||||
return new GeckoDriver(this);
|
return new GeckoDriver(Services.appinfo.ID, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
set acceptConnections(value) {
|
set acceptConnections(value) {
|
||||||
|
@ -13,42 +13,23 @@ const {
|
|||||||
stack,
|
stack,
|
||||||
TimeoutError,
|
TimeoutError,
|
||||||
} = ChromeUtils.import("chrome://marionette/content/error.js", {});
|
} = ChromeUtils.import("chrome://marionette/content/error.js", {});
|
||||||
const {truncate} = ChromeUtils.import("chrome://marionette/content/format.js", {});
|
|
||||||
const {Log} = ChromeUtils.import("chrome://marionette/content/log.js", {});
|
const {Log} = ChromeUtils.import("chrome://marionette/content/log.js", {});
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "log", Log.get);
|
XPCOMUtils.defineLazyGetter(this, "log", Log.get);
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = [
|
this.EXPORTED_SYMBOLS = [
|
||||||
"executeSoon",
|
|
||||||
"DebounceCallback",
|
"DebounceCallback",
|
||||||
"IdlePromise",
|
"IdlePromise",
|
||||||
|
"MessageManagerDestroyedPromise",
|
||||||
"PollPromise",
|
"PollPromise",
|
||||||
"Sleep",
|
"Sleep",
|
||||||
"TimedPromise",
|
"TimedPromise",
|
||||||
"waitForEvent",
|
|
||||||
"waitForMessage",
|
|
||||||
"waitForObserverTopic",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const {TYPE_ONE_SHOT, TYPE_REPEATING_SLACK} = Ci.nsITimer;
|
const {TYPE_ONE_SHOT, TYPE_REPEATING_SLACK} = Ci.nsITimer;
|
||||||
|
|
||||||
const PROMISE_TIMEOUT = AppConstants.DEBUG ? 4500 : 1500;
|
const PROMISE_TIMEOUT = AppConstants.DEBUG ? 4500 : 1500;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatch a function to be executed on the main thread.
|
|
||||||
*
|
|
||||||
* @param {function} func
|
|
||||||
* Function to be executed.
|
|
||||||
*/
|
|
||||||
function executeSoon(func) {
|
|
||||||
if (typeof func != "function") {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
|
|
||||||
Services.tm.dispatchToMainThread(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @callback Condition
|
* @callback Condition
|
||||||
*
|
*
|
||||||
@ -255,6 +236,46 @@ function Sleep(timeout) {
|
|||||||
return new TimedPromise(() => {}, {timeout, throws: null});
|
return new TimedPromise(() => {}, {timeout, throws: null});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects when the specified message manager has been destroyed.
|
||||||
|
*
|
||||||
|
* One can observe the removal and detachment of a content browser
|
||||||
|
* (`<xul:browser>`) or a chrome window by its message manager
|
||||||
|
* disconnecting.
|
||||||
|
*
|
||||||
|
* When a browser is associated with a tab, this is safer than only
|
||||||
|
* relying on the event `TabClose` which signalises the _intent to_
|
||||||
|
* remove a tab and consequently would lead to the destruction of
|
||||||
|
* the content browser and its browser message manager.
|
||||||
|
*
|
||||||
|
* When closing a chrome window it is safer than only relying on
|
||||||
|
* the event 'unload' which signalises the _intent to_ close the
|
||||||
|
* chrome window and consequently would lead to the destruction of
|
||||||
|
* the window and its window message manager.
|
||||||
|
*
|
||||||
|
* @param {MessageListenerManager} messageManager
|
||||||
|
* The message manager to observe for its disconnect state.
|
||||||
|
* Use the browser message manager when closing a content browser,
|
||||||
|
* and the window message manager when closing a chrome window.
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
* A promise that resolves when the message manager has been destroyed.
|
||||||
|
*/
|
||||||
|
function MessageManagerDestroyedPromise(messageManager) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
function observe(subject, topic) {
|
||||||
|
log.trace(`Received observer notification ${topic}`);
|
||||||
|
|
||||||
|
if (subject == messageManager) {
|
||||||
|
Services.obs.removeObserver(this, "message-manager-disconnect");
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.obs.addObserver(observe, "message-manager-disconnect");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throttle until the main thread is idle and `window` has performed
|
* Throttle until the main thread is idle and `window` has performed
|
||||||
* an animation frame (in that order).
|
* an animation frame (in that order).
|
||||||
@ -330,192 +351,3 @@ class DebounceCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.DebounceCallback = DebounceCallback;
|
this.DebounceCallback = DebounceCallback;
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for an event to be fired on a specified element.
|
|
||||||
*
|
|
||||||
* This method has been duplicated from BrowserTestUtils.jsm.
|
|
||||||
*
|
|
||||||
* Because this function is intended for testing, any error in checkFn
|
|
||||||
* will cause the returned promise to be rejected instead of waiting for
|
|
||||||
* the next event, since this is probably a bug in the test.
|
|
||||||
*
|
|
||||||
* Usage::
|
|
||||||
*
|
|
||||||
* let promiseEvent = waitForEvent(element, "eventName");
|
|
||||||
* // Do some processing here that will cause the event to be fired
|
|
||||||
* // ...
|
|
||||||
* // Now wait until the Promise is fulfilled
|
|
||||||
* let receivedEvent = await promiseEvent;
|
|
||||||
*
|
|
||||||
* The promise resolution/rejection handler for the returned promise is
|
|
||||||
* guaranteed not to be called until the next event tick after the event
|
|
||||||
* listener gets called, so that all other event listeners for the element
|
|
||||||
* are executed before the handler is executed::
|
|
||||||
*
|
|
||||||
* let promiseEvent = waitForEvent(element, "eventName");
|
|
||||||
* // Same event tick here.
|
|
||||||
* await promiseEvent;
|
|
||||||
* // Next event tick here.
|
|
||||||
*
|
|
||||||
* If some code, such like adding yet another event listener, needs to be
|
|
||||||
* executed in the same event tick, use raw addEventListener instead and
|
|
||||||
* place the code inside the event listener::
|
|
||||||
*
|
|
||||||
* element.addEventListener("load", () => {
|
|
||||||
* // Add yet another event listener in the same event tick as the load
|
|
||||||
* // event listener.
|
|
||||||
* p = waitForEvent(element, "ready");
|
|
||||||
* }, { once: true });
|
|
||||||
*
|
|
||||||
* @param {Element} subject
|
|
||||||
* The element that should receive the event.
|
|
||||||
* @param {string} eventName
|
|
||||||
* Name of the event to listen to.
|
|
||||||
* @param {Object=} options
|
|
||||||
* Extra options.
|
|
||||||
* @param {boolean=} options.capture
|
|
||||||
* True to use a capturing listener.
|
|
||||||
* @param {function(Event)=} options.checkFn
|
|
||||||
* Called with the ``Event`` object as argument, should return ``true``
|
|
||||||
* if the event is the expected one, or ``false`` if it should be
|
|
||||||
* ignored and listening should continue. If not specified, the first
|
|
||||||
* event with the specified name resolves the returned promise.
|
|
||||||
* @param {boolean=} options.wantsUntrusted
|
|
||||||
* True to receive synthetic events dispatched by web content.
|
|
||||||
*
|
|
||||||
* @return {Promise.<Event>}
|
|
||||||
* Promise which resolves to the received ``Event`` object, or rejects
|
|
||||||
* in case of a failure.
|
|
||||||
*/
|
|
||||||
function waitForEvent(subject, eventName,
|
|
||||||
{capture = false, checkFn = null, wantsUntrusted = false} = {}) {
|
|
||||||
if (subject == null || !("addEventListener" in subject)) {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
if (typeof eventName != "string") {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
if (capture != null && typeof capture != "boolean") {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
if (checkFn != null && typeof checkFn != "function") {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
if (wantsUntrusted != null && typeof wantsUntrusted != "boolean") {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
subject.addEventListener(eventName, function listener(event) {
|
|
||||||
log.trace(`Received DOM event ${event.type} for ${event.target}`);
|
|
||||||
try {
|
|
||||||
if (checkFn && !checkFn(event)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
subject.removeEventListener(eventName, listener, capture);
|
|
||||||
executeSoon(() => resolve(event));
|
|
||||||
} catch (ex) {
|
|
||||||
try {
|
|
||||||
subject.removeEventListener(eventName, listener, capture);
|
|
||||||
} catch (ex2) {
|
|
||||||
// Maybe the provided object does not support removeEventListener.
|
|
||||||
}
|
|
||||||
executeSoon(() => reject(ex));
|
|
||||||
}
|
|
||||||
}, capture, wantsUntrusted);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for a message to be fired from a particular message manager.
|
|
||||||
*
|
|
||||||
* This method has been duplicated from BrowserTestUtils.jsm.
|
|
||||||
*
|
|
||||||
* @param {nsIMessageManager} messageManager
|
|
||||||
* The message manager that should be used.
|
|
||||||
* @param {string} messageName
|
|
||||||
* The message to wait for.
|
|
||||||
* @param {Object=} options
|
|
||||||
* Extra options.
|
|
||||||
* @param {function(Message)=} options.checkFn
|
|
||||||
* Called with the ``Message`` object as argument, should return ``true``
|
|
||||||
* if the message is the expected one, or ``false`` if it should be
|
|
||||||
* ignored and listening should continue. If not specified, the first
|
|
||||||
* message with the specified name resolves the returned promise.
|
|
||||||
*
|
|
||||||
* @return {Promise.<Object>}
|
|
||||||
* Promise which resolves to the data property of the received
|
|
||||||
* ``Message``.
|
|
||||||
*/
|
|
||||||
function waitForMessage(messageManager, messageName,
|
|
||||||
{checkFn = undefined} = {}) {
|
|
||||||
if (messageManager == null || !("addMessageListener" in messageManager)) {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
if (typeof messageName != "string") {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
if (checkFn && typeof checkFn != "function") {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise(resolve => {
|
|
||||||
messageManager.addMessageListener(messageName, function onMessage(msg) {
|
|
||||||
log.trace(`Received ${messageName} for ${msg.target}`);
|
|
||||||
if (checkFn && !checkFn(msg)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
messageManager.removeMessageListener(messageName, onMessage);
|
|
||||||
resolve(msg.data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for the specified observer topic to be observed.
|
|
||||||
*
|
|
||||||
* This method has been duplicated from TestUtils.jsm.
|
|
||||||
*
|
|
||||||
* Because this function is intended for testing, any error in checkFn
|
|
||||||
* will cause the returned promise to be rejected instead of waiting for
|
|
||||||
* the next notification, since this is probably a bug in the test.
|
|
||||||
*
|
|
||||||
* @param {string} topic
|
|
||||||
* The topic to observe.
|
|
||||||
* @param {Object=} options
|
|
||||||
* Extra options.
|
|
||||||
* @param {function(String,Object)=} options.checkFn
|
|
||||||
* Called with ``subject``, and ``data`` as arguments, should return true
|
|
||||||
* if the notification is the expected one, or false if it should be
|
|
||||||
* ignored and listening should continue. If not specified, the first
|
|
||||||
* notification for the specified topic resolves the returned promise.
|
|
||||||
*
|
|
||||||
* @return {Promise.<Array<String, Object>>}
|
|
||||||
* Promise which resolves to an array of ``subject``, and ``data`` from
|
|
||||||
* the observed notification.
|
|
||||||
*/
|
|
||||||
function waitForObserverTopic(topic, {checkFn = null} = {}) {
|
|
||||||
if (typeof topic != "string") {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
if (checkFn != null && typeof checkFn != "function") {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
Services.obs.addObserver(function observer(subject, topic, data) {
|
|
||||||
log.trace(`Received observer notification ${topic}`);
|
|
||||||
try {
|
|
||||||
if (checkFn && !checkFn(subject, data)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Services.obs.removeObserver(observer, topic);
|
|
||||||
resolve({subject, data});
|
|
||||||
} catch (ex) {
|
|
||||||
Services.obs.removeObserver(observer, topic);
|
|
||||||
reject(ex);
|
|
||||||
}
|
|
||||||
}, topic);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -2,93 +2,16 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
DebounceCallback,
|
DebounceCallback,
|
||||||
IdlePromise,
|
IdlePromise,
|
||||||
PollPromise,
|
PollPromise,
|
||||||
Sleep,
|
Sleep,
|
||||||
TimedPromise,
|
TimedPromise,
|
||||||
waitForEvent,
|
|
||||||
waitForMessage,
|
|
||||||
waitForObserverTopic,
|
|
||||||
} = ChromeUtils.import("chrome://marionette/content/sync.js", {});
|
} = ChromeUtils.import("chrome://marionette/content/sync.js", {});
|
||||||
|
|
||||||
const DEFAULT_TIMEOUT = 2000;
|
const DEFAULT_TIMEOUT = 2000;
|
||||||
|
|
||||||
/**
|
|
||||||
* Mimic a DOM node for listening for events.
|
|
||||||
*/
|
|
||||||
class MockElement {
|
|
||||||
constructor() {
|
|
||||||
this.capture = false;
|
|
||||||
this.func = null;
|
|
||||||
this.eventName = null;
|
|
||||||
this.untrusted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
addEventListener(name, func, capture, untrusted) {
|
|
||||||
this.eventName = name;
|
|
||||||
this.func = func;
|
|
||||||
if (capture != null) {
|
|
||||||
this.capture = capture;
|
|
||||||
}
|
|
||||||
if (untrusted != null) {
|
|
||||||
this.untrusted = untrusted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
click() {
|
|
||||||
if (this.func) {
|
|
||||||
let details = {
|
|
||||||
capture: this.capture,
|
|
||||||
target: this,
|
|
||||||
type: this.eventName,
|
|
||||||
untrusted: this.untrusted,
|
|
||||||
};
|
|
||||||
this.func(details);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
removeEventListener(name, func) {
|
|
||||||
this.capture = false;
|
|
||||||
this.func = null;
|
|
||||||
this.eventName = null;
|
|
||||||
this.untrusted = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mimic a message manager for sending messages.
|
|
||||||
*/
|
|
||||||
class MessageManager {
|
|
||||||
constructor() {
|
|
||||||
this.func = null;
|
|
||||||
this.message = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
addMessageListener(message, func) {
|
|
||||||
this.func = func;
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
removeMessageListener(message) {
|
|
||||||
this.func = null;
|
|
||||||
this.message = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
send(message, data) {
|
|
||||||
if (this.func) {
|
|
||||||
this.func({
|
|
||||||
data,
|
|
||||||
message,
|
|
||||||
target: this,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mimics nsITimer, but instead of using a system clock you can
|
* Mimics nsITimer, but instead of using a system clock you can
|
||||||
* preprogram it to invoke the callback after a given number of ticks.
|
* preprogram it to invoke the callback after a given number of ticks.
|
||||||
@ -112,23 +35,6 @@ class MockTimer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add_test(function test_executeSoon_callback() {
|
|
||||||
// executeSoon() is already defined for xpcshell in head.js. As such import
|
|
||||||
// our implementation into a custom namespace.
|
|
||||||
let sync = {};
|
|
||||||
ChromeUtils.import("chrome://marionette/content/sync.js", sync);
|
|
||||||
|
|
||||||
for (let func of ["foo", null, true, [], {}]) {
|
|
||||||
Assert.throws(() => sync.executeSoon(func), /TypeError/);
|
|
||||||
}
|
|
||||||
|
|
||||||
let a;
|
|
||||||
sync.executeSoon(() => { a = 1; });
|
|
||||||
executeSoon(() => equal(1, a));
|
|
||||||
|
|
||||||
run_next_test();
|
|
||||||
});
|
|
||||||
|
|
||||||
add_test(function test_PollPromise_funcTypes() {
|
add_test(function test_PollPromise_funcTypes() {
|
||||||
for (let type of ["foo", 42, null, undefined, true, [], {}]) {
|
for (let type of ["foo", 42, null, undefined, true, [], {}]) {
|
||||||
Assert.throws(() => new PollPromise(type), /TypeError/);
|
Assert.throws(() => new PollPromise(type), /TypeError/);
|
||||||
@ -307,155 +213,3 @@ add_task(async function test_DebounceCallback_repeatedCallback() {
|
|||||||
equal(ncalls, 1);
|
equal(ncalls, 1);
|
||||||
ok(debouncer.timer.cancelled);
|
ok(debouncer.timer.cancelled);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_waitForEvent_subjectAndEventNameTypes() {
|
|
||||||
let element = new MockElement();
|
|
||||||
|
|
||||||
for (let subject of ["foo", 42, null, undefined, true, [], {}]) {
|
|
||||||
Assert.throws(() => waitForEvent(subject, "click"), /TypeError/);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let eventName of [42, null, undefined, true, [], {}]) {
|
|
||||||
Assert.throws(() => waitForEvent(element, eventName), /TypeError/);
|
|
||||||
}
|
|
||||||
|
|
||||||
let clicked = waitForEvent(element, "click");
|
|
||||||
element.click();
|
|
||||||
let event = await clicked;
|
|
||||||
equal(element, event.target);
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_waitForEvent_captureTypes() {
|
|
||||||
let element = new MockElement();
|
|
||||||
|
|
||||||
for (let capture of ["foo", 42, [], {}]) {
|
|
||||||
Assert.throws(() => waitForEvent(
|
|
||||||
element, "click", {capture}), /TypeError/);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let capture of [null, undefined, false, true]) {
|
|
||||||
let expected_capture = (capture == null) ? false : capture;
|
|
||||||
|
|
||||||
element = new MockElement();
|
|
||||||
let clicked = waitForEvent(element, "click", {capture});
|
|
||||||
element.click();
|
|
||||||
let event = await clicked;
|
|
||||||
equal(element, event.target);
|
|
||||||
equal(expected_capture, event.capture);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_waitForEvent_checkFnTypes() {
|
|
||||||
let element = new MockElement();
|
|
||||||
|
|
||||||
for (let checkFn of ["foo", 42, true, [], {}]) {
|
|
||||||
Assert.throws(() => waitForEvent(
|
|
||||||
element, "click", {checkFn}), /TypeError/);
|
|
||||||
}
|
|
||||||
|
|
||||||
let count;
|
|
||||||
for (let checkFn of [null, undefined, event => count++ > 0]) {
|
|
||||||
let expected_count = (checkFn == null) ? 0 : 2;
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
element = new MockElement();
|
|
||||||
let clicked = waitForEvent(element, "click", {checkFn});
|
|
||||||
element.click();
|
|
||||||
element.click();
|
|
||||||
let event = await clicked;
|
|
||||||
equal(element, event.target);
|
|
||||||
equal(expected_count, count);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_waitForEvent_wantsUntrustedTypes() {
|
|
||||||
let element = new MockElement();
|
|
||||||
|
|
||||||
for (let wantsUntrusted of ["foo", 42, [], {}]) {
|
|
||||||
Assert.throws(() => waitForEvent(
|
|
||||||
element, "click", {wantsUntrusted}), /TypeError/);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let wantsUntrusted of [null, undefined, false, true]) {
|
|
||||||
let expected_untrusted = (wantsUntrusted == null) ? false : wantsUntrusted;
|
|
||||||
|
|
||||||
element = new MockElement();
|
|
||||||
let clicked = waitForEvent(element, "click", {wantsUntrusted});
|
|
||||||
element.click();
|
|
||||||
let event = await clicked;
|
|
||||||
equal(element, event.target);
|
|
||||||
equal(expected_untrusted, event.untrusted);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_waitForMessage_messageManagerAndMessageTypes() {
|
|
||||||
let messageManager = new MessageManager();
|
|
||||||
|
|
||||||
for (let manager of ["foo", 42, null, undefined, true, [], {}]) {
|
|
||||||
Assert.throws(() => waitForMessage(manager, "message"), /TypeError/);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let message of [42, null, undefined, true, [], {}]) {
|
|
||||||
Assert.throws(() => waitForEvent(messageManager, message), /TypeError/);
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = {"foo": "bar"};
|
|
||||||
let sent = waitForMessage(messageManager, "message");
|
|
||||||
messageManager.send("message", data);
|
|
||||||
equal(data, await sent);
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_waitForMessage_checkFnTypes() {
|
|
||||||
let messageManager = new MessageManager();
|
|
||||||
|
|
||||||
for (let checkFn of ["foo", 42, true, [], {}]) {
|
|
||||||
Assert.throws(() => waitForMessage(
|
|
||||||
messageManager, "message", {checkFn}), /TypeError/);
|
|
||||||
}
|
|
||||||
|
|
||||||
let data1 = {"fo": "bar"};
|
|
||||||
let data2 = {"foo": "bar"};
|
|
||||||
|
|
||||||
for (let checkFn of [null, undefined, msg => "foo" in msg.data]) {
|
|
||||||
let expected_data = (checkFn == null) ? data1 : data2;
|
|
||||||
|
|
||||||
messageManager = new MessageManager();
|
|
||||||
let sent = waitForMessage(messageManager, "message", {checkFn});
|
|
||||||
messageManager.send("message", data1);
|
|
||||||
messageManager.send("message", data2);
|
|
||||||
equal(expected_data, await sent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_waitForObserverTopic_topicTypes() {
|
|
||||||
for (let topic of [42, null, undefined, true, [], {}]) {
|
|
||||||
Assert.throws(() => waitForObserverTopic(topic), /TypeError/);
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = {"foo": "bar"};
|
|
||||||
let sent = waitForObserverTopic("message");
|
|
||||||
Services.obs.notifyObservers(this, "message", data);
|
|
||||||
let result = await sent;
|
|
||||||
equal(this, result.subject);
|
|
||||||
equal(data, result.data);
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_waitForObserverTopic_checkFnTypes() {
|
|
||||||
for (let checkFn of ["foo", 42, true, [], {}]) {
|
|
||||||
Assert.throws(() => waitForObserverTopic(
|
|
||||||
"message", {checkFn}), /TypeError/);
|
|
||||||
}
|
|
||||||
|
|
||||||
let data1 = {"fo": "bar"};
|
|
||||||
let data2 = {"foo": "bar"};
|
|
||||||
|
|
||||||
for (let checkFn of [null, undefined, (subject, data) => data == data2]) {
|
|
||||||
let expected_data = (checkFn == null) ? data1 : data2;
|
|
||||||
|
|
||||||
let sent = waitForObserverTopic("message");
|
|
||||||
Services.obs.notifyObservers(this, "message", data1);
|
|
||||||
Services.obs.notifyObservers(this, "message", data2);
|
|
||||||
let result = await sent;
|
|
||||||
equal(expected_data, result.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
@ -10,17 +10,14 @@ const CC = Components.Constructor;
|
|||||||
|
|
||||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
ChromeUtils.import("resource://gre/modules/EventEmitter.jsm");
|
ChromeUtils.import("resource://gre/modules/EventEmitter.jsm");
|
||||||
const {
|
const {StreamUtils} =
|
||||||
StreamUtils,
|
ChromeUtils.import("chrome://marionette/content/stream-utils.js", {});
|
||||||
} = ChromeUtils.import("chrome://marionette/content/stream-utils.js", {});
|
const {Packet, JSONPacket, BulkPacket} =
|
||||||
const {
|
ChromeUtils.import("chrome://marionette/content/packets.js", {});
|
||||||
BulkPacket,
|
|
||||||
JSONPacket,
|
const executeSoon = function(func) {
|
||||||
Packet,
|
Services.tm.dispatchToMainThread(func);
|
||||||
} = ChromeUtils.import("chrome://marionette/content/packets.js", {});
|
};
|
||||||
const {
|
|
||||||
executeSoon,
|
|
||||||
} = ChromeUtils.import("chrome://marionette/content/sync.js", {});
|
|
||||||
|
|
||||||
const flags = {wantVerbose: false, wantLogging: false};
|
const flags = {wantVerbose: false, wantLogging: false};
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
[promise.py]
|
[promise.py]
|
||||||
|
expected: TIMEOUT
|
||||||
[test_promise_timeout]
|
[test_promise_timeout]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ skip-if = appname == "thunderbird" || os == "android"
|
|||||||
[test_ext_cookieBehaviors.js]
|
[test_ext_cookieBehaviors.js]
|
||||||
[test_ext_cookies_samesite.js]
|
[test_ext_cookies_samesite.js]
|
||||||
[test_ext_content_security_policy.js]
|
[test_ext_content_security_policy.js]
|
||||||
|
skip-if = (os == "win" && debug) #Bug 1485567
|
||||||
[test_ext_contentscript_api_injection.js]
|
[test_ext_contentscript_api_injection.js]
|
||||||
[test_ext_contentscript_async_loading.js]
|
[test_ext_contentscript_async_loading.js]
|
||||||
skip-if = os == 'android' && debug # The generated script takes too long to load on Android debug
|
skip-if = os == 'android' && debug # The generated script takes too long to load on Android debug
|
||||||
|
Loading…
Reference in New Issue
Block a user