Merge autoland to mozilla-central a=merge

This commit is contained in:
dluca 2017-11-09 15:52:42 +02:00
Родитель 6d9443afa6 315a813f56
Коммит c748db6076
260 изменённых файлов: 1277 добавлений и 880 удалений

Просмотреть файл

@ -1698,6 +1698,14 @@ pref("extensions.formautofill.creditCards.available", true);
pref("extensions.formautofill.creditCards.available", false);
#endif
pref("extensions.formautofill.creditCards.enabled", true);
// Pref for shield/heartbeat to recognize users who have used Credit Card
// Autofill. The valid values can be:
// 0: none
// 1: submitted a manually-filled credit card form (but didn't see the doorhanger
// because of a duplicate profile in the storage)
// 2: saw the doorhanger
// 3: submitted an autofill'ed credit card form
pref("extensions.formautofill.creditCards.used", 0);
pref("extensions.formautofill.firstTimeUse", true);
pref("extensions.formautofill.heuristics.enabled", true);
pref("extensions.formautofill.loglevel", "Warn");

Просмотреть файл

@ -105,7 +105,6 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "newtab", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "preferences", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "downloads", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "accounts", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#ifdef MOZ_SERVICES_HEALTHREPORT
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "healthreport", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#endif

Просмотреть файл

@ -71,7 +71,7 @@ const CONTENT = {
hideClose: true,
},
},
update: {
updateAddress: {
notificationId: "autofill-address",
message: GetStringFromName("updateAddressMessage"),
linkMessage: GetStringFromName(autofillOptsKey),
@ -96,7 +96,7 @@ const CONTENT = {
hideClose: true,
},
},
creditCard: {
addCreditCard: {
notificationId: "autofill-credit-card",
message: formatStringFromName("saveCreditCardMessage", [brandShortName], 1),
linkMessage: GetStringFromName(autofillSecurityOptionsKey),
@ -149,6 +149,31 @@ const CONTENT = {
},
},
},
updateCreditCard: {
notificationId: "autofill-credit-card",
message: GetStringFromName("updateCreditCardMessage"),
linkMessage: GetStringFromName(autofillOptsKey),
anchor: {
id: "autofill-credit-card-notification-icon",
URL: "chrome://formautofill/content/formfill-anchor.svg",
tooltiptext: GetStringFromName("openAutofillMessagePanel"),
},
mainAction: {
label: GetStringFromName("updateCreditCardLabel"),
accessKey: "U",
callbackState: "update",
},
secondaryActions: [{
label: GetStringFromName("createCreditCardLabel"),
accessKey: "C",
callbackState: "create",
}],
options: {
persistWhileVisible: true,
popupIconURL: "chrome://formautofill/content/icon-credit-card.svg",
hideClose: true,
},
},
};
let FormAutofillDoorhanger = {

Просмотреть файл

@ -375,7 +375,7 @@ FormAutofillParent.prototype = {
if (!this.profileStorage.addresses.mergeIfPossible(address.guid, address.record, true)) {
this._recordFormFillingTime("address", "autofill-update", timeStartedFillingMS);
FormAutofillDoorhanger.show(target, "update").then((state) => {
FormAutofillDoorhanger.show(target, "updateAddress").then((state) => {
let changedGUIDs = this.profileStorage.addresses.mergeToStorage(address.record, true);
switch (state) {
case "create":
@ -411,8 +411,8 @@ FormAutofillParent.prototype = {
this._recordFormFillingTime("address", "manual", timeStartedFillingMS);
// Show first time use doorhanger
if (Services.prefs.getBoolPref("extensions.formautofill.firstTimeUse")) {
Services.prefs.setBoolPref("extensions.formautofill.firstTimeUse", false);
if (FormAutofillUtils.isAutofillAddressesFirstTimeUse) {
Services.prefs.setBoolPref(FormAutofillUtils.ADDRESSES_FIRST_TIME_USE_PREF, false);
FormAutofillDoorhanger.show(target, "firstTimeUse").then((state) => {
if (state !== "open-pref") {
return;
@ -429,10 +429,21 @@ FormAutofillParent.prototype = {
},
async _onCreditCardSubmit(creditCard, target, timeStartedFillingMS) {
// Updates the used status for shield/heartbeat to recognize users who have
// used Credit Card Autofill.
let setUsedStatus = status => {
if (FormAutofillUtils.AutofillCreditCardsUsedStatus < status) {
Services.prefs.setIntPref(FormAutofillUtils.CREDITCARDS_USED_STATUS_PREF, status);
}
};
// We'll show the credit card doorhanger if:
// - User applys autofill and changed
// - User fills form manually and the filling data is not duplicated to storage
if (creditCard.guid) {
// Indicate that the user has used Credit Card Autofill to fill in a form.
setUsedStatus(3);
let originalCCData = this.profileStorage.creditCards.get(creditCard.guid);
let unchanged = Object.keys(creditCard.record).every(field => {
if (creditCard.record[field] === "" && !originalCCData[field]) {
@ -457,6 +468,11 @@ FormAutofillParent.prototype = {
Services.telemetry.scalarAdd("formautofill.creditCards.fill_type_autofill_modified", 1);
this._recordFormFillingTime("creditCard", "autofill-update", timeStartedFillingMS);
} else {
// Indicate that the user neither sees the doorhanger nor uses Autofill
// but somehow has a duplicate record in the storage. Will be reset to 2
// if the doorhanger actually shows below.
setUsedStatus(1);
// Add the probe to record credit card manual filling.
Services.telemetry.scalarAdd("formautofill.creditCards.fill_type_manual", 1);
this._recordFormFillingTime("creditCard", "manual", timeStartedFillingMS);
@ -469,7 +485,10 @@ FormAutofillParent.prototype = {
return;
}
let state = await FormAutofillDoorhanger.show(target, "creditCard");
// Indicate that the user has seen the doorhanger.
setUsedStatus(2);
let state = await FormAutofillDoorhanger.show(target, creditCard.guid ? "updateCreditCard" : "addCreditCard");
if (state == "cancel") {
return;
}
@ -487,10 +506,13 @@ FormAutofillParent.prototype = {
}
let changedGUIDs = [];
// TODO: Autofill(with guid) case should show update doorhanger with update/create new.
// It'll be implemented in bug 1403881 and only avoid mergering for now.
if (creditCard.guid) {
changedGUIDs.push(this.profileStorage.creditCards.add(creditCard.record));
if (state == "update") {
this.profileStorage.creditCards.update(creditCard.guid, creditCard.record, true);
changedGUIDs.push(creditCard.guid);
} else if ("create") {
changedGUIDs.push(this.profileStorage.creditCards.add(creditCard.record));
}
} else {
changedGUIDs.push(...this.profileStorage.creditCards.mergeToStorage(creditCard.record));
if (!changedGUIDs.length) {

Просмотреть файл

@ -18,7 +18,9 @@ const ALTERNATIVE_COUNTRY_NAMES = {
const ADDRESSES_COLLECTION_NAME = "addresses";
const CREDITCARDS_COLLECTION_NAME = "creditCards";
const ADDRESSES_FIRST_TIME_USE_PREF = "extensions.formautofill.firstTimeUse";
const ENABLED_AUTOFILL_ADDRESSES_PREF = "extensions.formautofill.addresses.enabled";
const CREDITCARDS_USED_STATUS_PREF = "extensions.formautofill.creditCards.used";
const AUTOFILL_CREDITCARDS_AVAILABLE_PREF = "extensions.formautofill.creditCards.available";
const ENABLED_AUTOFILL_CREDITCARDS_PREF = "extensions.formautofill.creditCards.enabled";
const MANAGE_ADDRESSES_KEYWORDS = ["manageAddressesTitle", "addNewAddressTitle"];
@ -45,6 +47,8 @@ this.FormAutofillUtils = {
CREDITCARDS_COLLECTION_NAME,
ENABLED_AUTOFILL_ADDRESSES_PREF,
ENABLED_AUTOFILL_CREDITCARDS_PREF,
ADDRESSES_FIRST_TIME_USE_PREF,
CREDITCARDS_USED_STATUS_PREF,
MANAGE_ADDRESSES_KEYWORDS,
EDIT_ADDRESS_KEYWORDS,
MANAGE_CREDITCARDS_KEYWORDS,
@ -608,3 +612,7 @@ XPCOMUtils.defineLazyPreferenceGetter(this.FormAutofillUtils,
"isAutofillCreditCardsAvailable", AUTOFILL_CREDITCARDS_AVAILABLE_PREF);
XPCOMUtils.defineLazyPreferenceGetter(this.FormAutofillUtils,
"_isAutofillCreditCardsEnabled", ENABLED_AUTOFILL_CREDITCARDS_PREF);
XPCOMUtils.defineLazyPreferenceGetter(this.FormAutofillUtils,
"isAutofillAddressesFirstTimeUse", ADDRESSES_FIRST_TIME_USE_PREF);
XPCOMUtils.defineLazyPreferenceGetter(this.FormAutofillUtils,
"AutofillCreditCardsUsedStatus", CREDITCARDS_USED_STATUS_PREF);

Просмотреть файл

@ -35,6 +35,11 @@ saveCreditCardMessage = Would you like %S to save this credit card? (Security co
saveCreditCardLabel = Save Credit Card
cancelCreditCardLabel = Dont Save
neverSaveCreditCardLabel = Never Save Credit Cards
# LOCALIZATION NOTE (updateCreditCardMessage, createCreditCardLabel, updateCreditCardLabel): Used on the doorhanger
# when an credit card change is detected.
updateCreditCardMessage = Would you like to update your credit card with this new information?
createCreditCardLabel = Create New Credit Card
updateCreditCardLabel = Update Credit Card
# LOCALIZATION NOTE (openAutofillMessagePanel): Tooltip label for Form Autofill doorhanger icon on address bar.
openAutofillMessagePanel = Open Form Autofill message panel

Просмотреть файл

@ -20,27 +20,6 @@ add_task(async function setup_storage() {
await saveAddress(TEST_ADDRESS_5);
});
add_task(async function test_click_on_footer() {
await BrowserTestUtils.withNewTab({gBrowser, url: URL}, async function(browser) {
const {autoCompletePopup: {richlistbox: itemsBox}} = browser;
await openPopupOn(browser, "#organization");
// Click on the footer
const optionButton = itemsBox.querySelector(".autocomplete-richlistitem:last-child")._optionButton;
const prefTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, PRIVACY_PREF_URL);
// Wait for dropdown animation finished to continue mouse synthesizing.
await sleep(1000);
await EventUtils.synthesizeMouseAtCenter(optionButton, {});
info(`expecting tab: about:preferences#privacy opened`);
const prefTab = await prefTabPromise;
info(`expecting tab: about:preferences#privacy removed`);
await BrowserTestUtils.removeTab(prefTab);
ok(true, "Tab: preferences#privacy was successfully opened by clicking on the footer");
await closePopup(browser);
});
});
add_task(async function test_press_enter_on_footer() {
await BrowserTestUtils.withNewTab({gBrowser, url: URL}, async function(browser) {
const {autoCompletePopup: {richlistbox: itemsBox}} = browser;
@ -63,6 +42,27 @@ add_task(async function test_press_enter_on_footer() {
});
});
add_task(async function test_click_on_footer() {
await BrowserTestUtils.withNewTab({gBrowser, url: URL}, async function(browser) {
const {autoCompletePopup: {richlistbox: itemsBox}} = browser;
await openPopupOn(browser, "#organization");
// Click on the footer
const optionButton = itemsBox.querySelector(".autocomplete-richlistitem:last-child")._optionButton;
const prefTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, PRIVACY_PREF_URL);
// Wait for dropdown animation finished to continue mouse synthesizing.
await sleep(3000);
await EventUtils.synthesizeMouseAtCenter(optionButton, {});
info(`expecting tab: about:preferences#privacy opened`);
const prefTab = await prefTabPromise;
info(`expecting tab: about:preferences#privacy removed`);
await BrowserTestUtils.removeTab(prefTab);
ok(true, "Tab: preferences#privacy was successfully opened by clicking on the footer");
await closePopup(browser);
});
});
add_task(async function test_phishing_warning_single_category() {
await BrowserTestUtils.withNewTab({gBrowser, url: URL}, async function(browser) {
const {autoCompletePopup: {richlistbox: itemsBox}} = browser;

Просмотреть файл

@ -2,6 +2,11 @@
"use strict";
add_task(async function test_submit_creditCard_cancel_saving() {
await SpecialPowers.pushPrefEnv({
"set": [
[CREDITCARDS_USED_STATUS_PREF, 0],
],
});
await BrowserTestUtils.withNewTab({gBrowser, url: CREDITCARD_FORM_URL},
async function(browser) {
let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
@ -32,9 +37,16 @@ add_task(async function test_submit_creditCard_cancel_saving() {
await sleep(1000);
let creditCards = await getCreditCards();
is(creditCards.length, 0, "No credit card saved");
is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 2, "User has seen the doorhanger");
SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
});
add_task(async function test_submit_creditCard_saved() {
await SpecialPowers.pushPrefEnv({
"set": [
[CREDITCARDS_USED_STATUS_PREF, 0],
],
});
await BrowserTestUtils.withNewTab({gBrowser, url: CREDITCARD_FORM_URL},
async function(browser) {
let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
@ -62,10 +74,17 @@ add_task(async function test_submit_creditCard_saved() {
let creditCards = await getCreditCards();
is(creditCards.length, 1, "1 credit card in storage");
is(creditCards[0]["cc-name"], "User 1", "Verify the name field");
is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 2, "User has seen the doorhanger");
SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
await removeAllRecords();
});
add_task(async function test_submit_untouched_creditCard_form() {
await SpecialPowers.pushPrefEnv({
"set": [
[CREDITCARDS_USED_STATUS_PREF, 0],
],
});
await saveCreditCard(TEST_CREDIT_CARD_1);
let creditCards = await getCreditCards();
is(creditCards.length, 1, "1 credit card in storage");
@ -90,10 +109,17 @@ add_task(async function test_submit_untouched_creditCard_form() {
creditCards = await getCreditCards();
is(creditCards.length, 1, "Still 1 credit card");
is(creditCards[0].timesUsed, 1, "timesUsed field set to 1");
is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 3, "User has used autofill");
SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
await removeAllRecords();
});
add_task(async function test_submit_changed_subset_creditCard_form() {
await SpecialPowers.pushPrefEnv({
"set": [
[CREDITCARDS_USED_STATUS_PREF, 0],
],
});
await saveCreditCard(TEST_CREDIT_CARD_1);
let creditCards = await getCreditCards();
is(creditCards.length, 1, "1 credit card in storage");
@ -125,10 +151,17 @@ add_task(async function test_submit_changed_subset_creditCard_form() {
creditCards = await getCreditCards();
is(creditCards.length, 1, "Still 1 credit card in storage");
is(creditCards[0]["cc-name"], TEST_CREDIT_CARD_1["cc-name"], "name field still exists");
is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 2, "User has seen the doorhanger");
SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
await removeAllRecords();
});
add_task(async function test_submit_duplicate_creditCard_form() {
await SpecialPowers.pushPrefEnv({
"set": [
[CREDITCARDS_USED_STATUS_PREF, 0],
],
});
await saveCreditCard(TEST_CREDIT_CARD_1);
let creditCards = await getCreditCards();
is(creditCards.length, 1, "1 credit card in storage");
@ -158,6 +191,9 @@ add_task(async function test_submit_duplicate_creditCard_form() {
is(creditCards.length, 1, "Still 1 credit card in storage");
is(creditCards[0]["cc-name"], TEST_CREDIT_CARD_1["cc-name"], "Verify the name field");
is(creditCards[0].timesUsed, 1, "timesUsed field set to 1");
is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 1,
"User neither sees the doorhanger nor uses autofill but somehow has a record in the storage");
SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
await removeAllRecords();
});
@ -195,6 +231,11 @@ add_task(async function test_submit_unnormailzed_creditCard_form() {
});
add_task(async function test_submit_creditCard_never_save() {
await SpecialPowers.pushPrefEnv({
"set": [
[CREDITCARDS_USED_STATUS_PREF, 0],
],
});
await BrowserTestUtils.withNewTab({gBrowser, url: CREDITCARD_FORM_URL},
async function(browser) {
let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
@ -224,6 +265,8 @@ add_task(async function test_submit_creditCard_never_save() {
let creditCardPref = SpecialPowers.getBoolPref(ENABLED_AUTOFILL_CREDITCARDS_PREF);
is(creditCards.length, 0, "No credit card in storage");
is(creditCardPref, false, "Credit card is disabled");
is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 2, "User has seen the doorhanger");
SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
SpecialPowers.clearUserPref(ENABLED_AUTOFILL_CREDITCARDS_PREF);
});
@ -390,6 +433,11 @@ add_task(async function test_submit_creditCard_with_synced_already() {
});
add_task(async function test_submit_manual_mergeable_creditCard_form() {
await SpecialPowers.pushPrefEnv({
"set": [
[CREDITCARDS_USED_STATUS_PREF, 0],
],
});
await saveCreditCard(TEST_CREDIT_CARD_3);
let creditCards = await getCreditCards();
is(creditCards.length, 1, "1 credit card in storage");
@ -419,5 +467,131 @@ add_task(async function test_submit_manual_mergeable_creditCard_form() {
creditCards = await getCreditCards();
is(creditCards.length, 1, "Still 1 credit card in storage");
is(creditCards[0]["cc-name"], "User 3", "Verify the name field");
is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 2, "User has seen the doorhanger");
SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
await removeAllRecords();
});
add_task(async function test_update_autofill_form() {
await SpecialPowers.pushPrefEnv({
"set": [
[CREDITCARDS_USED_STATUS_PREF, 0],
],
});
await saveCreditCard(TEST_CREDIT_CARD_1);
let creditCards = await getCreditCards();
is(creditCards.length, 1, "1 credit card in storage");
await BrowserTestUtils.withNewTab({gBrowser, url: CREDITCARD_FORM_URL},
async function(browser) {
let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
"popupshown");
await openPopupOn(browser, "form #cc-name");
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser);
await ContentTask.spawn(browser, null, async function() {
let form = content.document.getElementById("form");
let name = form.querySelector("#cc-name");
name.setUserInput("User 1");
// Wait 1000ms before submission to make sure the input value applied
await new Promise(resolve => setTimeout(resolve, 1000));
form.querySelector("input[type=submit]").click();
});
await promiseShown;
await clickDoorhangerButton(MAIN_BUTTON);
}
);
creditCards = await getCreditCards();
is(creditCards.length, 1, "Still 1 credit card");
is(creditCards[0]["cc-name"], "User 1", "cc-name field is updated");
is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 3, "User has used autofill");
SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
await removeAllRecords();
});
add_task(async function test_create_new_autofill_form() {
await SpecialPowers.pushPrefEnv({
"set": [
[CREDITCARDS_USED_STATUS_PREF, 0],
],
});
await saveCreditCard(TEST_CREDIT_CARD_1);
let creditCards = await getCreditCards();
is(creditCards.length, 1, "1 credit card in storage");
await BrowserTestUtils.withNewTab({gBrowser, url: CREDITCARD_FORM_URL},
async function(browser) {
let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
"popupshown");
await openPopupOn(browser, "form #cc-name");
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser);
await ContentTask.spawn(browser, null, async function() {
let form = content.document.getElementById("form");
let name = form.querySelector("#cc-name");
name.setUserInput("User 1");
// Wait 1000ms before submission to make sure the input value applied
await new Promise(resolve => setTimeout(resolve, 1000));
form.querySelector("input[type=submit]").click();
});
await promiseShown;
await clickDoorhangerButton(SECONDARY_BUTTON);
}
);
creditCards = await getCreditCards();
is(creditCards.length, 2, "2 credit cards in storage");
is(creditCards[0]["cc-name"], TEST_CREDIT_CARD_1["cc-name"],
"Original record's cc-name field is unchanged");
is(creditCards[1]["cc-name"], "User 1", "cc-name field in the new record");
is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 3, "User has used autofill");
SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
await removeAllRecords();
});
add_task(async function test_update_duplicate_autofill_form() {
await SpecialPowers.pushPrefEnv({
"set": [
[CREDITCARDS_USED_STATUS_PREF, 0],
],
});
await saveCreditCard({
"cc-number": "1234123412341234",
});
await saveCreditCard({
"cc-number": "1111222233334444",
});
let creditCards = await getCreditCards();
is(creditCards.length, 2, "2 credit card in storage");
await BrowserTestUtils.withNewTab({gBrowser, url: CREDITCARD_FORM_URL},
async function(browser) {
await openPopupOn(browser, "form #cc-number");
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser);
await ContentTask.spawn(browser, null, async function() {
let form = content.document.getElementById("form");
let number = form.querySelector("#cc-number");
is(number.value, "1234123412341234", "Should be the first credit card number");
// Change number to the second credit card number
number.setUserInput("1111222233334444");
// Wait 1000ms before submission to make sure the input value applied
await new Promise(resolve => setTimeout(resolve, 1000));
form.querySelector("input[type=submit]").click();
});
await sleep(1000);
is(PopupNotifications.panel.state, "closed", "Doorhanger is hidden");
}
);
creditCards = await getCreditCards();
is(creditCards.length, 2, "Still 2 credit card");
is(SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF), 1,
"User neither sees the doorhanger nor uses autofill but somehow has a record in the storage");
SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
await removeAllRecords();
});

Просмотреть файл

@ -2,7 +2,7 @@
BASE_URL, TEST_ADDRESS_1, TEST_ADDRESS_2, TEST_ADDRESS_3, TEST_ADDRESS_4, TEST_ADDRESS_5,
TEST_CREDIT_CARD_1, TEST_CREDIT_CARD_2, TEST_CREDIT_CARD_3, FORM_URL, CREDITCARD_FORM_URL,
FTU_PREF, ENABLED_AUTOFILL_ADDRESSES_PREF, AUTOFILL_CREDITCARDS_AVAILABLE_PREF, ENABLED_AUTOFILL_CREDITCARDS_PREF,
SYNC_USERNAME_PREF, SYNC_ADDRESSES_PREF, SYNC_CREDITCARDS_PREF, SYNC_CREDITCARDS_AVAILABLE_PREF,
SYNC_USERNAME_PREF, SYNC_ADDRESSES_PREF, SYNC_CREDITCARDS_PREF, SYNC_CREDITCARDS_AVAILABLE_PREF, CREDITCARDS_USED_STATUS_PREF,
sleep, expectPopupOpen, openPopupOn, expectPopupClose, closePopup, clickDoorhangerButton,
getAddresses, saveAddress, removeAddresses, saveCreditCard,
getDisplayedPopupItems, getDoorhangerCheckbox, waitForMasterPasswordDialog,
@ -21,6 +21,7 @@ const FORM_URL = "http://mochi.test:8888/browser/browser/extensions/formautofill
const CREDITCARD_FORM_URL =
"https://example.org/browser/browser/extensions/formautofill/test/browser/autocomplete_creditcard_basic.html";
const FTU_PREF = "extensions.formautofill.firstTimeUse";
const CREDITCARDS_USED_STATUS_PREF = "extensions.formautofill.creditCards.used";
const ENABLED_AUTOFILL_ADDRESSES_PREF = "extensions.formautofill.addresses.enabled";
const AUTOFILL_CREDITCARDS_AVAILABLE_PREF = "extensions.formautofill.creditCards.available";
const ENABLED_AUTOFILL_CREDITCARDS_PREF = "extensions.formautofill.creditCards.enabled";

Просмотреть файл

@ -170,8 +170,9 @@ class HeadersPanel extends Component {
this.getProperties(uploadHeaders, REQUEST_HEADERS_FROM_UPLOAD),
);
// not showing #hash in url
let summaryUrl = urlDetails.unicodeUrl ?
this.renderSummary(SUMMARY_URL, new URL(urlDetails.unicodeUrl).origin) : null;
this.renderSummary(SUMMARY_URL, urlDetails.unicodeUrl.split("#")[0]) : null;
let summaryMethod = method ?
this.renderSummary(SUMMARY_METHOD, method) : null;

Просмотреть файл

@ -30,6 +30,7 @@ add_task(function* () {
// request #0
method: "GET",
uri: STATUS_CODES_SJS + "?sts=100",
correctUri: STATUS_CODES_SJS + "?sts=100",
details: {
status: 101,
statusText: "Switching Protocols",
@ -42,7 +43,8 @@ add_task(function* () {
{
// request #1
method: "GET",
uri: STATUS_CODES_SJS + "?sts=200",
uri: STATUS_CODES_SJS + "?sts=200#doh",
correctUri: STATUS_CODES_SJS + "?sts=200",
details: {
status: 202,
statusText: "Created",
@ -56,6 +58,7 @@ add_task(function* () {
// request #2
method: "GET",
uri: STATUS_CODES_SJS + "?sts=300",
correctUri: STATUS_CODES_SJS + "?sts=300",
details: {
status: 303,
statusText: "See Other",
@ -69,6 +72,7 @@ add_task(function* () {
// request #3
method: "GET",
uri: STATUS_CODES_SJS + "?sts=400",
correctUri: STATUS_CODES_SJS + "?sts=400",
details: {
status: 404,
statusText: "Not Found",
@ -82,6 +86,7 @@ add_task(function* () {
// request #4
method: "GET",
uri: STATUS_CODES_SJS + "?sts=500",
correctUri: STATUS_CODES_SJS + "?sts=500",
details: {
status: 501,
statusText: "Not Implemented",
@ -169,9 +174,9 @@ add_task(function* () {
let panel = document.querySelector("#headers-panel");
let summaryValues = panel.querySelectorAll(".tabpanel-summary-value.textbox-input");
let { method, uri, details: { status, statusText } } = data;
let { method, correctUri, details: { status, statusText } } = data;
is(summaryValues[0].value, new URL(uri).origin,
is(summaryValues[0].value, correctUri,
"The url summary value is incorrect.");
is(summaryValues[1].value, method, "The method summary value is incorrect.");
is(panel.querySelector(".requests-list-status-icon").dataset.code, status,
@ -190,7 +195,8 @@ add_task(function* () {
document.querySelector("#params-tab"));
let panel = document.querySelector("#params-panel");
let statusParamValue = data.uri.split("=").pop();
// Bug 1414981 - Request URL should not show #hash
let statusParamValue = data.uri.split("=").pop().split("#")[0];
let treeSections = panel.querySelectorAll(".tree-section");
is(treeSections.length, 1,

Просмотреть файл

@ -402,7 +402,8 @@ function verifyRequestItemTarget(document, requestList, requestItem, method,
transferred, size, time, displayedStatus } = data;
let target = document.querySelectorAll(".request-list-item")[visibleIndex];
let unicodeUrl = decodeUnicodeUrl(url);
// Bug 1414981 - Request URL should not show #hash
let unicodeUrl = decodeUnicodeUrl(url).split("#")[0];
let name = getUrlBaseName(url);
let query = getUrlQuery(url);
let host = getUrlHost(url);
@ -424,7 +425,7 @@ function verifyRequestItemTarget(document, requestList, requestItem, method,
ok(requestItem.url.startsWith(url), "The attached url is correct.");
} else {
is(requestItem.method, method, "The attached method is correct.");
is(requestItem.url, url, "The attached url is correct.");
is(requestItem.url, url.split("#")[0], "The attached url is correct.");
}
is(target.querySelector(".requests-list-method").textContent,

Просмотреть файл

@ -294,6 +294,7 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest,
UpdatePrincipal();
mCacheStream.NotifyDataStarted(mLoadID, startOffset, seekable);
mIsTransportSeekable = seekable;
mChannelStatistics.Start();
mReopenOnError = false;
@ -318,7 +319,8 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest,
bool
ChannelMediaResource::IsTransportSeekable()
{
return mCacheStream.IsTransportSeekable();
MOZ_ASSERT(NS_IsMainThread());
return mIsTransportSeekable;
}
nsresult
@ -387,7 +389,7 @@ ChannelMediaResource::OnStopRequest(nsIRequest* aRequest, nsresult aStatus)
if (mReopenOnError && aStatus != NS_ERROR_PARSED_DATA_CACHED &&
aStatus != NS_BINDING_ABORTED &&
(GetOffset() == 0 || (GetLength() > 0 && GetOffset() != GetLength() &&
mCacheStream.IsTransportSeekable()))) {
mIsTransportSeekable))) {
// If the stream did close normally, restart the channel if we're either
// at the start of the resource, or if the server is seekable and we're
// not at the end of stream. We don't restart the stream if we're at the
@ -600,6 +602,8 @@ ChannelMediaResource::CloneData(MediaResourceCallback* aCallback)
RefPtr<ChannelMediaResource> resource =
new ChannelMediaResource(aCallback, nullptr, mURI, mChannelStatistics);
resource->mIsTransportSeekable = mIsTransportSeekable;
// Initially the clone is treated as suspended by the cache, because
// we don't have a channel. If the cache needs to read data from the clone
// it will call CacheClientResume (or CacheClientSeek with aResume true)
@ -692,7 +696,7 @@ ChannelMediaResource::Suspend(bool aCloseImmediately)
dom::HTMLMediaElement* element = owner->GetMediaElement();
MOZ_DIAGNOSTIC_ASSERT(element);
if (mChannel && aCloseImmediately && mCacheStream.IsTransportSeekable()) {
if (mChannel && aCloseImmediately && mIsTransportSeekable) {
CloseChannel();
element->DownloadSuspended();
}

Просмотреть файл

@ -247,6 +247,8 @@ protected:
// Main thread access only
// True if Close() has been called.
bool mClosed = false;
// The last reported seekability state for the underlying channel
bool mIsTransportSeekable = false;
RefPtr<Listener> mListener;
// A mono-increasing integer to uniquely identify the channel we are loading.
uint32_t mLoadID = 0;

Просмотреть файл

@ -14,6 +14,7 @@
#include "MemoryBlockCache.h"
#include "mozilla/Attributes.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/ErrorNames.h"
#include "mozilla/Logging.h"
#include "mozilla/Preferences.h"
#include "mozilla/ReentrantMonitor.h"
@ -24,7 +25,6 @@
#include "nsContentUtils.h"
#include "nsIObserverService.h"
#include "nsIPrincipal.h"
#include "nsISeekableStream.h"
#include "nsPrintfCString.h"
#include "nsProxyRelease.h"
#include "nsThreadUtils.h"
@ -35,9 +35,11 @@ namespace mozilla {
#undef LOG
#undef LOGI
#undef LOGE
LazyLogModule gMediaCacheLog("MediaCache");
#define LOG(...) MOZ_LOG(gMediaCacheLog, LogLevel::Debug, (__VA_ARGS__))
#define LOGI(...) MOZ_LOG(gMediaCacheLog, LogLevel::Info, (__VA_ARGS__))
#define LOGE(...) NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString(__VA_ARGS__).get(), nullptr, __FILE__, __LINE__)
// For HTTP seeking, if number of bytes needing to be
// seeked forward is less than this value then a read is
@ -2198,13 +2200,6 @@ MediaCacheStream::~MediaCacheStream()
lengthKb);
}
bool
MediaCacheStream::IsTransportSeekable()
{
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
return mIsTransportSeekable;
}
bool
MediaCacheStream::AreAllStreamsForResourceSuspended()
{
@ -2411,41 +2406,22 @@ MediaCacheStream::SetPlaybackRate(uint32_t aBytesPerSecond)
}
nsresult
MediaCacheStream::Seek(int32_t aWhence, int64_t aOffset)
MediaCacheStream::Seek(int64_t aOffset)
{
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
MOZ_ASSERT(!NS_IsMainThread());
mMediaCache->GetReentrantMonitor().AssertCurrentThreadIn();
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
if (mClosed)
return NS_ERROR_FAILURE;
if (!IsOffsetAllowed(aOffset)) {
return NS_ERROR_ILLEGAL_VALUE;
}
if (mClosed) {
return NS_ERROR_ABORT;
}
int64_t oldOffset = mStreamOffset;
int64_t newOffset = mStreamOffset;
switch (aWhence) {
case PR_SEEK_END:
if (mStreamLength < 0)
return NS_ERROR_FAILURE;
newOffset = mStreamLength + aOffset;
break;
case PR_SEEK_CUR:
newOffset += aOffset;
break;
case PR_SEEK_SET:
newOffset = aOffset;
break;
default:
NS_ERROR("Unknown whence");
return NS_ERROR_FAILURE;
}
if (!IsOffsetAllowed(newOffset)) {
return NS_ERROR_FAILURE;
}
mStreamOffset = newOffset;
mStreamOffset = aOffset;
LOG("Stream %p Seek to %" PRId64, this, mStreamOffset);
mMediaCache->NoteSeek(this, oldOffset);
mMediaCache->QueueUpdate();
return NS_OK;
}
@ -2462,6 +2438,72 @@ MediaCacheStream::ThrottleReadahead(bool bThrottle)
}
}
uint32_t
MediaCacheStream::ReadPartialBlock(int64_t aOffset, Span<char> aBuffer)
{
mMediaCache->GetReentrantMonitor().AssertCurrentThreadIn();
MOZ_ASSERT(IsOffsetAllowed(aOffset));
if (OffsetToBlockIndexUnchecked(mChannelOffset) !=
OffsetToBlockIndexUnchecked(aOffset) ||
aOffset >= mChannelOffset) {
// Not in the partial block or no data to read.
return 0;
}
auto source = MakeSpan<const uint8_t>(
mPartialBlockBuffer.get() + OffsetInBlock(aOffset),
OffsetInBlock(mChannelOffset) - OffsetInBlock(aOffset));
// We have |source.Length() <= BLOCK_SIZE < INT32_MAX| to guarantee
// that |bytesToRead| can fit into a uint32_t.
uint32_t bytesToRead = std::min(aBuffer.Length(), source.Length());
memcpy(aBuffer.Elements(), source.Elements(), bytesToRead);
return bytesToRead;
}
Result<uint32_t, nsresult>
MediaCacheStream::ReadBlockFromCache(int64_t aOffset, Span<char> aBuffer)
{
mMediaCache->GetReentrantMonitor().AssertCurrentThreadIn();
MOZ_ASSERT(IsOffsetAllowed(aOffset));
// OffsetToBlockIndexUnchecked() is always non-negative.
uint32_t index = OffsetToBlockIndexUnchecked(aOffset);
int32_t cacheBlock = index < mBlocks.Length() ? mBlocks[index] : -1;
if (cacheBlock < 0) {
// Not in the cache.
return 0;
}
if (aBuffer.Length() > size_t(BLOCK_SIZE)) {
// Clamp the buffer to avoid overflow below since we will read at most
// BLOCK_SIZE bytes.
aBuffer = aBuffer.First(BLOCK_SIZE);
}
// |BLOCK_SIZE - OffsetInBlock(aOffset)| <= BLOCK_SIZE
int32_t bytesToRead =
std::min<int32_t>(BLOCK_SIZE - OffsetInBlock(aOffset), aBuffer.Length());
int32_t bytesRead = 0;
nsresult rv =
mMediaCache->ReadCacheFile(cacheBlock * BLOCK_SIZE + OffsetInBlock(aOffset),
aBuffer.Elements(),
bytesToRead,
&bytesRead);
// Ensure |cacheBlock * BLOCK_SIZE + OffsetInBlock(aOffset)| won't overflow.
static_assert(INT64_MAX >= BLOCK_SIZE * (uint32_t(INT32_MAX) + 1),
"BLOCK_SIZE too large!");
if (NS_FAILED(rv)) {
nsCString name;
GetErrorName(rv, name);
LOGE("Stream %p ReadCacheFile failed, rv=%s", this, name.Data());
return mozilla::Err(rv);
}
return bytesRead;
}
int64_t
MediaCacheStream::Tell()
{
@ -2600,73 +2642,55 @@ MediaCacheStream::ReadAt(int64_t aOffset, char* aBuffer,
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
nsresult rv = Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
nsresult rv = Seek(aOffset);
if (NS_FAILED(rv)) return rv;
return Read(aBuffer, aCount, aBytes);
}
nsresult
MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount)
MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount)
{
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
// The buffer we are about to fill.
auto buffer = MakeSpan<char>(aBuffer, aCount);
// Read one block (or part of a block) at a time
uint32_t count = 0;
int64_t streamOffset = aOffset;
while (count < aCount) {
while (!buffer.IsEmpty()) {
if (mClosed) {
// We need to check |mClosed| in each iteration which might be changed
// after calling |mMediaCache->ReadCacheFile|.
return NS_ERROR_FAILURE;
}
int32_t streamBlock = OffsetToBlockIndex(streamOffset);
if (streamBlock < 0) {
break;
}
uint32_t offsetInStreamBlock =
uint32_t(streamOffset - streamBlock*BLOCK_SIZE);
int64_t size = std::min<int64_t>(aCount - count, BLOCK_SIZE - offsetInStreamBlock);
if (mStreamLength >= 0) {
// Don't try to read beyond the end of the stream
int64_t bytesRemaining = mStreamLength - streamOffset;
if (bytesRemaining <= 0) {
return NS_ERROR_FAILURE;
}
size = std::min(size, bytesRemaining);
// Clamp size until 64-bit file size issues are fixed.
size = std::min(size, int64_t(INT32_MAX));
if (!IsOffsetAllowed(streamOffset)) {
LOGE("Stream %p invalid offset=%" PRId64, this, streamOffset);
return NS_ERROR_ILLEGAL_VALUE;
}
int32_t bytes;
int32_t channelBlock = OffsetToBlockIndexUnchecked(mChannelOffset);
int32_t cacheBlock =
size_t(streamBlock) < mBlocks.Length() ? mBlocks[streamBlock] : -1;
if (channelBlock == streamBlock && streamOffset < mChannelOffset) {
// We can just use the data in mPartialBlockBuffer. In fact we should
// use it rather than waiting for the block to fill and land in
// the cache.
// Clamp bytes until 64-bit file size issues are fixed.
int64_t toCopy = std::min<int64_t>(size, mChannelOffset - streamOffset);
bytes = std::min(toCopy, int64_t(INT32_MAX));
MOZ_ASSERT(bytes >= 0 && bytes <= toCopy, "Bytes out of range.");
memcpy(aBuffer + count,
mPartialBlockBuffer.get() + offsetInStreamBlock, bytes);
} else {
if (cacheBlock < 0) {
// We expect all blocks to be cached! Fail!
return NS_ERROR_FAILURE;
}
int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock;
MOZ_ASSERT(size >= 0 && size <= INT32_MAX, "Size out of range.");
nsresult rv = mMediaCache->ReadCacheFile(
offset, aBuffer + count, int32_t(size), &bytes);
if (NS_FAILED(rv)) {
return rv;
}
Result<uint32_t, nsresult> rv = ReadBlockFromCache(streamOffset, buffer);
if (rv.isErr()) {
return rv.unwrapErr();
}
streamOffset += bytes;
count += bytes;
uint32_t bytes = rv.unwrap();
if (bytes > 0) {
// Read data from the cache successfully. Let's try next block.
streamOffset += bytes;
buffer = buffer.From(bytes);
continue;
}
// The partial block is our last chance to get data.
bytes = ReadPartialBlock(streamOffset, buffer);
if (bytes < buffer.Length()) {
// Not enough data to read.
return NS_ERROR_FAILURE;
}
// Return for we've got all the requested bytes.
return NS_OK;
}
return NS_OK;

Просмотреть файл

@ -8,6 +8,7 @@
#define MediaCache_h_
#include "Intervals.h"
#include "mozilla/Result.h"
#include "mozilla/UniquePtr.h"
#include "nsCOMPtr.h"
#include "nsHashKeys.h"
@ -314,9 +315,7 @@ public:
// in the cache. Will not mark blocks as read. Can be called from the main
// thread. It's the caller's responsibility to wrap the call in a pin/unpin,
// and also to check that the range they want is cached before calling this.
nsresult ReadFromCache(char* aBuffer,
int64_t aOffset,
int64_t aCount);
nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount);
// IsDataCachedToEndOfStream returns true if all the data from
// aOffset to the end of the stream (the server-reported end, if the
@ -330,8 +329,6 @@ public:
// because it doesn't know when the decoder was paused, buffering, etc.
// Do not pass zero.
void SetPlaybackRate(uint32_t aBytesPerSecond);
// Returns the last set value of SetTransportSeekable.
bool IsTransportSeekable();
// Returns true when all streams for this resource are suspended or their
// channel has ended.
@ -340,9 +337,6 @@ public:
// These methods must be called on a different thread from the main
// thread. They should always be called on the same thread for a given
// stream.
// This can fail when aWhence is NS_SEEK_END and no stream length
// is known.
nsresult Seek(int32_t aWhence, int64_t aOffset);
int64_t Tell();
// *aBytes gets the number of bytes that were actually read. This can
// be less than aCount. If the first byte of data is not in the cache,
@ -426,6 +420,19 @@ private:
int32_t mCount;
};
// Read data from the partial block and return the number of bytes read
// successfully. 0 if aOffset is not an offset in the partial block or there
// is nothing to read.
uint32_t ReadPartialBlock(int64_t aOffset, Span<char> aBuffer);
// Read data from the cache block specified by aOffset. Return the number of
// bytes read successfully or an error code if any failure.
Result<uint32_t, nsresult> ReadBlockFromCache(int64_t aOffset,
Span<char> aBuffer);
// Non-main thread only.
nsresult Seek(int64_t aOffset);
// Returns the end of the bytes starting at the given offset
// which are in cache.
// This method assumes that the cache monitor is held and can be called on

Просмотреть файл

@ -560,6 +560,7 @@ ChromiumCDMChild::RecvLoadSession(const uint32_t& aPromiseId,
const uint32_t& aSessionType,
const nsCString& aSessionId)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvLoadSession(pid=%u, type=%u, sessionId=%s)",
aPromiseId,
aSessionType,
@ -737,6 +738,11 @@ ChromiumCDMChild::RecvInitializeVideoDecoder(
{
MOZ_ASSERT(IsOnMessageLoopThread());
MOZ_ASSERT(!mDecoderInitialized);
if (!mCDM) {
GMP_LOG("ChromiumCDMChild::RecvInitializeVideoDecoder() no CDM");
Unused << SendOnDecoderInitDone(cdm::kInitializationError);
return IPC_OK();
}
cdm::VideoDecoderConfig config;
config.codec =
static_cast<cdm::VideoDecoderConfig::VideoCodec>(aConfig.mCodec());
@ -761,10 +767,10 @@ ChromiumCDMChild::RecvDeinitializeVideoDecoder()
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvDeinitializeVideoDecoder()");
MOZ_ASSERT(mDecoderInitialized);
if (mDecoderInitialized) {
mDecoderInitialized = false;
if (mDecoderInitialized && mCDM) {
mCDM->DeinitializeDecoder(cdm::kStreamTypeVideo);
}
mDecoderInitialized = false;
PurgeShmems();
return IPC_OK();
}
@ -774,7 +780,7 @@ ChromiumCDMChild::RecvResetVideoDecoder()
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvResetVideoDecoder()");
if (mDecoderInitialized) {
if (mDecoderInitialized && mCDM) {
mCDM->ResetDecoder(cdm::kStreamTypeVideo);
}
Unused << SendResetVideoDecoderComplete();
@ -789,6 +795,12 @@ ChromiumCDMChild::RecvDecryptAndDecodeFrame(const CDMInputBuffer& aBuffer)
aBuffer.mTimestamp());
MOZ_ASSERT(mDecoderInitialized);
if (!mCDM) {
GMP_LOG("ChromiumCDMChild::RecvDecryptAndDecodeFrame() no CDM");
Unused << SendDecodeFailed(cdm::kDecodeError);
return IPC_OK();
}
RefPtr<ChromiumCDMChild> self = this;
auto autoDeallocateShmem = MakeScopeExit([&, self] {
self->DeallocShmem(aBuffer.mData());
@ -882,6 +894,11 @@ mozilla::ipc::IPCResult
ChromiumCDMChild::RecvDrain()
{
MOZ_ASSERT(IsOnMessageLoopThread());
if (!mCDM) {
GMP_LOG("ChromiumCDMChild::RecvDrain() no CDM");
Unused << SendDrainComplete();
return IPC_OK();
}
WidevineVideoFrame frame;
cdm::InputBuffer sample;
cdm::Status rv = mCDM->DecryptAndDecodeFrame(sample, &frame);

Просмотреть файл

@ -149,7 +149,7 @@ function UpdateSessionFunc(test, token, sessionType, resolve, reject) {
function MaybeCrossOriginURI(test, uri)
{
if (test.crossOrigin) {
return "http://test2.mochi.test:8888/tests/dom/media/test/allowed.sjs?" + uri;
return "https://example.com:443/tests/dom/media/test/allowed.sjs?" + uri;
} else {
return uri;
}

Просмотреть файл

@ -753,44 +753,63 @@ skip-if = android_version == '17' # android(bug 1232305)
[test_duration_after_error.html]
[test_eme_autoplay.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_pssh_in_moof.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_session_callable_value.html]
scheme=https
[test_eme_canvas_blocked.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_detach_media_keys.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_detach_reattach_same_mediakeys_during_playback.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_initDataTypes.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_missing_pssh.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_non_mse_fails.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_request_notifications.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_playback.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_requestKeySystemAccess.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_sample_groups_playback.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_setMediaKeys_before_attach_MediaSource.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_stream_capture_blocked_case1.html]
tags=msg capturestream
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_stream_capture_blocked_case2.html]
tags=msg capturestream
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_stream_capture_blocked_case3.html]
tags=msg capturestream
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_unsetMediaKeys_then_capture.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_waitingforkey.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_empty_resource.html]
[test_error_in_video_document.html]
[test_error_on_404.html]

Просмотреть файл

@ -5,7 +5,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
<script type="text/javascript" src="http://test1.mochi.test:8888/tests/dom/media/test/eme.js"></script>
<script type="text/javascript" src="https://example.com:443/tests/dom/media/test/eme.js"></script>
</head>
<body>
<pre id="test">

Просмотреть файл

@ -5,7 +5,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
<script type="text/javascript" src="http://test1.mochi.test:8888/tests/dom/media/test/eme.js"></script>
<script type="text/javascript" src="https://example.com:443/tests/dom/media/test/eme.js"></script>
</head>
<body>
<pre id="test">

Просмотреть файл

@ -5,7 +5,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
<script type="text/javascript" src="http://test1.mochi.test:8888/tests/dom/media/test/eme.js"></script>
<script type="text/javascript" src="https://example.com:443/tests/dom/media/test/eme.js"></script>
</head>
<body>
<pre id="test">

Просмотреть файл

@ -5,7 +5,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
<script type="text/javascript" src="http://test1.mochi.test:8888/tests/dom/media/test/eme.js"></script>
<script type="text/javascript" src="https://example.com:443/tests/dom/media/test/eme.js"></script>
</head>
<body>
<pre id="test">

Просмотреть файл

@ -5,7 +5,7 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
<script type="text/javascript" src="http://test1.mochi.test:8888/tests/dom/media/test/eme.js"></script>
<script type="text/javascript" src="https://example.com:443/tests/dom/media/test/eme.js"></script>
</head>
<body>
<pre id="test">

Просмотреть файл

@ -188,8 +188,8 @@ function testInitExpr(type, initialValue, nextValue, coercion, assertFunc = asse
var module = wasmEvalText(`(module
(import "globals" "a" (global ${type}))
(global (mut ${type}) (get_global 0))
(global ${type} (get_global 0))
(global $glob_mut (mut ${type}) (get_global 0))
(global $glob_imm ${type} (get_global 0))
(func $get0 (result ${type}) (get_global 0))
@ -203,6 +203,7 @@ function testInitExpr(type, initialValue, nextValue, coercion, assertFunc = asse
(export "get_cst" $get_cst)
(export "set1" $set1)
(export "global_imm" (global $glob_imm))
)`, {
globals: {
a: coercion(initialValue)
@ -211,10 +212,12 @@ function testInitExpr(type, initialValue, nextValue, coercion, assertFunc = asse
assertFunc(module.get0(), coercion(initialValue));
assertFunc(module.get1(), coercion(initialValue));
assertFunc(module.global_imm, coercion(initialValue));
assertEq(module.set1(coercion(nextValue)), undefined);
assertFunc(module.get1(), coercion(nextValue));
assertFunc(module.get0(), coercion(initialValue));
assertFunc(module.global_imm, coercion(initialValue));
assertFunc(module.get_cst(), coercion(initialValue));
}

Просмотреть файл

@ -0,0 +1,10 @@
assertErrorMessage(() => {
var desc = {
element: "anyfunc",
};
var proxy = new Proxy({}, {
has: true
});
Object.setPrototypeOf(desc, proxy);
let table = new WebAssembly.Table(desc);
}, TypeError, /proxy handler's has trap/);

Просмотреть файл

@ -788,6 +788,8 @@ class AstModule : public AstNode
AstElemSegmentVector elemSegments_;
AstGlobalVector globals_;
size_t numGlobalImports_;
public:
explicit AstModule(LifoAlloc& lifo)
: lifo_(lifo),
@ -801,7 +803,8 @@ class AstModule : public AstNode
funcs_(lifo),
dataSegments_(lifo),
elemSegments_(lifo),
globals_(lifo)
globals_(lifo),
numGlobalImports_(0)
{}
bool init() {
return sigMap_.init();
@ -891,9 +894,9 @@ class AstModule : public AstNode
return false;
break;
case DefinitionKind::Global:
numGlobalImports_++;
break;
}
return imports_.append(imp);
}
const ImportVector& imports() const {
@ -917,6 +920,9 @@ class AstModule : public AstNode
const AstGlobalVector& globals() const {
return globals_;
}
size_t numGlobalImports() const {
return numGlobalImports_;
}
};
class AstUnaryOperator final : public AstExpr

Просмотреть файл

@ -454,7 +454,10 @@ GetLimits(JSContext* cx, HandleObject obj, uint32_t maxInitial, uint32_t maxMaxi
RootedId maximumId(cx, AtomToId(maximumAtom));
bool found;
if (HasProperty(cx, obj, maximumId, &found) && found) {
if (!HasProperty(cx, obj, maximumId, &found))
return false;
if (found) {
RootedValue maxVal(cx);
if (!GetProperty(cx, obj, obj, maximumId, &maxVal))
return false;

Просмотреть файл

@ -988,9 +988,29 @@ GetGlobalExport(JSContext* cx, const GlobalDescVector& globals, uint32_t globalI
// Imports are located upfront in the globals array.
Val val;
switch (global.kind()) {
case GlobalKind::Import: val = globalImports[globalIndex]; break;
case GlobalKind::Variable: MOZ_CRASH("mutable variables can't be exported");
case GlobalKind::Constant: val = global.constantValue(); break;
case GlobalKind::Import: {
val = globalImports[globalIndex];
break;
}
case GlobalKind::Variable: {
MOZ_ASSERT(!global.isMutable(), "mutable variables can't be exported");
const InitExpr& init = global.initExpr();
switch (init.kind()) {
case InitExpr::Kind::Constant: {
val = init.val();
break;
}
case InitExpr::Kind::GetGlobal: {
val = globalImports[init.globalIndex()];
break;
}
}
break;
}
case GlobalKind::Constant: {
val = global.constantValue();
break;
}
}
switch (global.type()) {

Просмотреть файл

@ -2660,7 +2660,7 @@ ParseFunc(WasmParseContext& c, AstModule* module)
if (c.ts.getIf(WasmToken::Export)) {
AstRef ref = funcName.empty()
? AstRef(module->funcImportNames().length() + module->funcs().length())
? AstRef(module->numFuncImports() + module->funcs().length())
: AstRef(funcName);
if (!ParseInlineExport(c, DefinitionKind::Function, module, ref))
return false;
@ -3227,7 +3227,8 @@ ParseGlobal(WasmParseContext& c, AstModule* module)
}
if (c.ts.getIf(WasmToken::Export)) {
AstRef ref = name.empty() ? AstRef(module->globals().length()) : AstRef(name);
size_t refIndex = module->numGlobalImports() + module->globals().length();
AstRef ref = name.empty() ? AstRef(refIndex) : AstRef(name);
if (!ParseInlineExport(c, DefinitionKind::Global, module, ref))
return false;
if (!c.ts.match(WasmToken::CloseParen, c.error))

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
#include "mozilla/dom/HTMLAreaElement.h"
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/UniquePtr.h"
#include "nsString.h"
@ -30,10 +31,11 @@
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::dom;
class Area {
public:
explicit Area(nsIContent* aArea);
explicit Area(HTMLAreaElement* aArea);
virtual ~Area();
virtual void ParseCoords(const nsAString& aSpec);
@ -46,17 +48,17 @@ public:
void HasFocus(bool aHasFocus);
nsCOMPtr<nsIContent> mArea;
RefPtr<HTMLAreaElement> mArea;
UniquePtr<nscoord[]> mCoords;
int32_t mNumCoords;
bool mHasFocus;
};
Area::Area(nsIContent* aArea)
Area::Area(HTMLAreaElement* aArea)
: mArea(aArea)
{
MOZ_COUNT_CTOR(Area);
NS_PRECONDITION(mArea, "How did that happen?");
MOZ_ASSERT(mArea, "How did that happen?");
mNumCoords = 0;
mHasFocus = false;
}
@ -267,7 +269,7 @@ void Area::HasFocus(bool aHasFocus)
class DefaultArea : public Area {
public:
explicit DefaultArea(nsIContent* aArea);
explicit DefaultArea(HTMLAreaElement* aArea);
virtual bool IsInside(nscoord x, nscoord y) const override;
virtual void Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
@ -276,7 +278,7 @@ public:
virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) override;
};
DefaultArea::DefaultArea(nsIContent* aArea)
DefaultArea::DefaultArea(HTMLAreaElement* aArea)
: Area(aArea)
{
}
@ -311,7 +313,7 @@ void DefaultArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
class RectArea : public Area {
public:
explicit RectArea(nsIContent* aArea);
explicit RectArea(HTMLAreaElement* aArea);
virtual void ParseCoords(const nsAString& aSpec) override;
virtual bool IsInside(nscoord x, nscoord y) const override;
@ -321,7 +323,7 @@ public:
virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) override;
};
RectArea::RectArea(nsIContent* aArea)
RectArea::RectArea(HTMLAreaElement* aArea)
: Area(aArea)
{
}
@ -417,7 +419,7 @@ void RectArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
class PolyArea : public Area {
public:
explicit PolyArea(nsIContent* aArea);
explicit PolyArea(HTMLAreaElement* aArea);
virtual void ParseCoords(const nsAString& aSpec) override;
virtual bool IsInside(nscoord x, nscoord y) const override;
@ -427,7 +429,7 @@ public:
virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) override;
};
PolyArea::PolyArea(nsIContent* aArea)
PolyArea::PolyArea(HTMLAreaElement* aArea)
: Area(aArea)
{
}
@ -574,7 +576,7 @@ void PolyArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
class CircleArea : public Area {
public:
explicit CircleArea(nsIContent* aArea);
explicit CircleArea(HTMLAreaElement* aArea);
virtual void ParseCoords(const nsAString& aSpec) override;
virtual bool IsInside(nscoord x, nscoord y) const override;
@ -584,7 +586,7 @@ public:
virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) override;
};
CircleArea::CircleArea(nsIContent* aArea)
CircleArea::CircleArea(HTMLAreaElement* aArea)
: Area(aArea)
{
}
@ -677,9 +679,9 @@ void CircleArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
//----------------------------------------------------------------------
nsImageMap::nsImageMap() :
mImageFrame(nullptr),
mContainsBlockContents(false)
nsImageMap::nsImageMap()
: mImageFrame(nullptr)
, mConsiderWholeSubtree(false)
{
}
@ -747,38 +749,25 @@ nsImageMap::Init(nsImageFrame* aImageFrame, nsIContent* aMap)
}
void
nsImageMap::SearchForAreas(nsIContent* aParent, bool& aFoundArea,
bool& aFoundAnchor)
nsImageMap::SearchForAreas(nsIContent* aParent)
{
uint32_t i, n = aParent->GetChildCount();
// Look for <area> elements.
for (nsIContent* child = aParent->GetFirstChild();
child;
child = child->GetNextSibling()) {
if (auto* area = HTMLAreaElement::FromContent(child)) {
AddArea(area);
// Look for <area> or <a> elements. We'll use whichever type we find first.
for (i = 0; i < n; i++) {
nsIContent *child = aParent->GetChildAt(i);
// If we haven't determined that the map element contains an
// <a> element yet, then look for <area>.
if (!aFoundAnchor && child->IsHTMLElement(nsGkAtoms::area)) {
aFoundArea = true;
AddArea(child);
// Continue to next child. This stops mContainsBlockContents from
// Continue to next child. This stops mConsiderWholeSubtree from
// getting set. It also makes us ignore children of <area>s which
// is consistent with how we react to dynamic insertion of such
// children.
continue;
}
// If we haven't determined that the map element contains an
// <area> element yet, then look for <a>.
if (!aFoundArea && child->IsHTMLElement(nsGkAtoms::a)) {
aFoundAnchor = true;
AddArea(child);
}
if (child->IsElement()) {
mContainsBlockContents = true;
SearchForAreas(child, aFoundArea, aFoundAnchor);
mConsiderWholeSubtree = true;
SearchForAreas(child);
}
}
}
@ -789,11 +778,9 @@ nsImageMap::UpdateAreas()
// Get rid of old area data
FreeAreas();
bool foundArea = false;
bool foundAnchor = false;
mContainsBlockContents = false;
mConsiderWholeSubtree = false;
SearchForAreas(mMap);
SearchForAreas(mMap, foundArea, foundAnchor);
#ifdef ACCESSIBILITY
if (nsAccessibilityService* accService = GetAccService()) {
accService->UpdateImageMap(mImageFrame);
@ -802,7 +789,7 @@ nsImageMap::UpdateAreas()
}
void
nsImageMap::AddArea(nsIContent* aArea)
nsImageMap::AddArea(HTMLAreaElement* aArea)
{
static nsIContent::AttrValuesArray strings[] =
{&nsGkAtoms::rect, &nsGkAtoms::rectangle,
@ -888,7 +875,7 @@ nsImageMap::Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget,
void
nsImageMap::MaybeUpdateAreas(nsIContent *aContent)
{
if (aContent == mMap || mContainsBlockContents) {
if (aContent == mMap || mConsiderWholeSubtree) {
UpdateAreas();
}
}

Просмотреть файл

@ -22,6 +22,12 @@ class nsIFrame;
class nsIContent;
struct nsRect;
namespace mozilla {
namespace dom {
class HTMLAreaElement;
}
}
class nsImageMap final : public nsStubMutationObserver,
public nsIDOMEventListener
{
@ -82,18 +88,21 @@ protected:
void FreeAreas();
void UpdateAreas();
void SearchForAreas(nsIContent* aParent,
bool& aFoundArea,
bool& aFoundAnchor);
void AddArea(nsIContent* aArea);
void SearchForAreas(nsIContent* aParent);
void AddArea(mozilla::dom::HTMLAreaElement* aArea);
void MaybeUpdateAreas(nsIContent *aContent);
nsImageFrame* mImageFrame; // the frame that owns us
nsCOMPtr<nsIContent> mMap;
AutoTArray<Area*, 8> mAreas; // almost always has some entries
bool mContainsBlockContents;
// This is set when we search for all area children and tells us whether we
// should consider the whole subtree or just direct children when we get
// content notifications about changes inside the map subtree.
bool mConsiderWholeSubtree;
};
#endif /* nsImageMap_h */

Просмотреть файл

@ -7,6 +7,7 @@
#ifndef Utils_h
#define Utils_h
#include "mozilla/CheckedInt.h"
#include "mozilla/TemplateLib.h"
// Helper for log2 of powers of 2 at compile time.
@ -41,4 +42,86 @@ constexpr unsigned long long int operator"" _MiB(unsigned long long int aNum)
return aNum * 1024_KiB;
}
constexpr long double operator""_percent(long double aPercent)
{
return aPercent / 100;
}
// Helper for (fast) comparison of fractions without involving divisions or
// floats.
class Fraction
{
public:
explicit constexpr Fraction(size_t aNumerator, size_t aDenominator)
: mNumerator(aNumerator)
, mDenominator(aDenominator)
{
}
MOZ_IMPLICIT constexpr Fraction(long double aValue)
// We use an arbitrary power of two as denominator that provides enough
// precision for our use case.
: mNumerator(aValue * 4096)
, mDenominator(4096)
{
}
inline bool operator<(const Fraction& aOther) const
{
#ifndef MOZ_DEBUG
// We are comparing A / B < C / D, with all A, B, C and D being positive
// numbers. Multiplying both sides with B * D, we have:
// (A * B * D) / B < (C * B * D) / D, which can then be simplified as
// A * D < C * B. When can thus compare our fractions without actually
// doing any division.
// This however assumes the multiplied quantities are small enough not
// to overflow the multiplication. We use CheckedInt on debug builds
// to enforce the assumption.
return mNumerator * aOther.mDenominator < aOther.mNumerator * mDenominator;
#else
mozilla::CheckedInt<size_t> numerator(mNumerator);
mozilla::CheckedInt<size_t> denominator(mDenominator);
// value() asserts when the multiplication overflowed.
size_t lhs = (numerator * aOther.mDenominator).value();
size_t rhs = (aOther.mNumerator * denominator).value();
return lhs < rhs;
#endif
}
inline bool operator>(const Fraction& aOther) const { return aOther < *this; }
inline bool operator>=(const Fraction& aOther) const
{
return !(*this < aOther);
}
inline bool operator<=(const Fraction& aOther) const
{
return !(*this > aOther);
}
inline bool operator==(const Fraction& aOther) const
{
#ifndef MOZ_DEBUG
// Same logic as operator<
return mNumerator * aOther.mDenominator == aOther.mNumerator * mDenominator;
#else
mozilla::CheckedInt<size_t> numerator(mNumerator);
mozilla::CheckedInt<size_t> denominator(mDenominator);
size_t lhs = (numerator * aOther.mDenominator).value();
size_t rhs = (aOther.mNumerator * denominator).value();
return lhs == rhs;
#endif
}
inline bool operator!=(const Fraction& aOther) const
{
return !(*this == aOther);
}
private:
size_t mNumerator;
size_t mDenominator;
};
#endif

Просмотреть файл

@ -514,25 +514,6 @@ static Atomic<size_t, ReleaseAcquire> gRecycledSize;
static size_t opt_dirty_max = DIRTY_MAX_DEFAULT;
// RUN_MAX_OVRHD indicates maximum desired run header overhead. Runs are sized
// as small as possible such that this setting is still honored, without
// violating other constraints. The goal is to make runs as small as possible
// without exceeding a per run external fragmentation threshold.
//
// We use binary fixed point math for overhead computations, where the binary
// point is implicitly RUN_BFP bits to the left.
//
// Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be
// honored for some/all object sizes, since there is one bit of header overhead
// per object (plus a constant). This constraint is relaxed (ignored) for runs
// that are so small that the per-region overhead is greater than:
//
// (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP))
#define RUN_BFP 12
// \/ Implicit binary fixed point.
#define RUN_MAX_OVRHD 0x0000003dU
#define RUN_MAX_OVRHD_RELAX 0x00001800U
// Return the smallest chunk multiple that is >= s.
#define CHUNK_CEILING(s) (((s) + kChunkSizeMask) & ~kChunkSizeMask)
@ -856,21 +837,35 @@ struct GetDoublyLinkedListElement<arena_chunk_t>
struct arena_run_t
{
#if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
uint32_t magic;
uint32_t mMagic;
#define ARENA_RUN_MAGIC 0x384adf93
// On 64-bit platforms, having the arena_bin_t pointer following
// the mMagic field means there's padding between both fields, making
// the run header larger than necessary.
// But when MOZ_DIAGNOSTIC_ASSERT_ENABLED is not set, starting the
// header with this field followed by the arena_bin_t pointer yields
// the same padding. We do want the mMagic field to appear first, so
// depending whether MOZ_DIAGNOSTIC_ASSERT_ENABLED is set or not, we
// move some field to avoid padding.
// Number of free regions in run.
unsigned mNumFree;
#endif
// Bin this run is associated with.
arena_bin_t* bin;
arena_bin_t* mBin;
// Index of first element that might have a free region.
unsigned regs_minelm;
unsigned mRegionsMinElement;
#if !defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
// Number of free regions in run.
unsigned nfree;
unsigned mNumFree;
#endif
// Bitmask of in-use regions (0: in use, 1: free).
unsigned regs_mask[1]; // Dynamically sized.
unsigned mRegionsMask[1]; // Dynamically sized.
};
struct arena_bin_t
@ -895,7 +890,7 @@ struct arena_bin_t
// Total number of regions in a run for this bin's size class.
uint32_t mRunNumRegions;
// Number of elements in a run's regs_mask for this bin's size class.
// Number of elements in a run's mRegionsMask for this bin's size class.
uint32_t mRunNumRegionsMask;
// Offset of first region in a run for this bin's size class.
@ -903,6 +898,25 @@ struct arena_bin_t
// Current number of runs in this bin, full or otherwise.
unsigned long mNumRuns;
// Amount of overhead runs are allowed to have.
static constexpr long double kRunOverhead = 1.6_percent;
static constexpr long double kRunRelaxedOverhead = 2.4_percent;
// Initialize a bin for the given size class.
// The generated run sizes, for a page size of 4 KiB, are:
// size|run size|run size|run size|run
// class|size class|size class|size class|size
// 4 4 KiB 8 4 KiB 16 4 KiB 32 4 KiB
// 48 4 KiB 64 4 KiB 80 4 KiB 96 4 KiB
// 112 4 KiB 128 8 KiB 144 4 KiB 160 8 KiB
// 176 4 KiB 192 4 KiB 208 8 KiB 224 4 KiB
// 240 4 KiB 256 16 KiB 272 4 KiB 288 4 KiB
// 304 12 KiB 320 12 KiB 336 4 KiB 352 8 KiB
// 368 4 KiB 384 8 KiB 400 20 KiB 416 16 KiB
// 432 12 KiB 448 4 KiB 464 16 KiB 480 8 KiB
// 496 20 KiB 512 32 KiB 1024 64 KiB 2048 128 KiB
inline void Init(SizeClass aSizeClass);
};
struct arena_t
@ -987,10 +1001,7 @@ private:
void DeallocChunk(arena_chunk_t* aChunk);
arena_run_t* AllocRun(arena_bin_t* aBin,
size_t aSize,
bool aLarge,
bool aZero);
arena_run_t* AllocRun(size_t aSize, bool aLarge, bool aZero);
void DallocRun(arena_run_t* aRun, bool aDirty);
@ -1010,10 +1021,6 @@ private:
size_t aNewSize,
bool dirty);
inline void* MallocBinEasy(arena_bin_t* aBin, arena_run_t* aRun);
void* MallocBinHard(arena_bin_t* aBin);
arena_run_t* GetNonFullBinRun(arena_bin_t* aBin);
inline void* MallocSmall(size_t aSize, bool aZero);
@ -2264,14 +2271,14 @@ arena_run_reg_alloc(arena_run_t* run, arena_bin_t* bin)
void* ret;
unsigned i, mask, bit, regind;
MOZ_DIAGNOSTIC_ASSERT(run->magic == ARENA_RUN_MAGIC);
MOZ_ASSERT(run->regs_minelm < bin->mRunNumRegionsMask);
MOZ_DIAGNOSTIC_ASSERT(run->mMagic == ARENA_RUN_MAGIC);
MOZ_ASSERT(run->mRegionsMinElement < bin->mRunNumRegionsMask);
// Move the first check outside the loop, so that run->regs_minelm can
// Move the first check outside the loop, so that run->mRegionsMinElement can
// be updated unconditionally, without the possibility of updating it
// multiple times.
i = run->regs_minelm;
mask = run->regs_mask[i];
i = run->mRegionsMinElement;
mask = run->mRegionsMask[i];
if (mask != 0) {
// Usable allocation found.
bit = CountTrailingZeroes32(mask);
@ -2283,13 +2290,13 @@ arena_run_reg_alloc(arena_run_t* run, arena_bin_t* bin)
// Clear bit.
mask ^= (1U << bit);
run->regs_mask[i] = mask;
run->mRegionsMask[i] = mask;
return ret;
}
for (i++; i < bin->mRunNumRegionsMask; i++) {
mask = run->regs_mask[i];
mask = run->mRegionsMask[i];
if (mask != 0) {
// Usable allocation found.
bit = CountTrailingZeroes32(mask);
@ -2301,11 +2308,11 @@ arena_run_reg_alloc(arena_run_t* run, arena_bin_t* bin)
// Clear bit.
mask ^= (1U << bit);
run->regs_mask[i] = mask;
run->mRegionsMask[i] = mask;
// Make a note that nothing before this element
// contains a free region.
run->regs_minelm = i; // Low payoff: + (mask == 0);
run->mRegionsMinElement = i; // Low payoff: + (mask == 0);
return ret;
}
@ -2343,7 +2350,7 @@ arena_run_reg_dalloc(arena_run_t* run, arena_bin_t* bin, void* ptr, size_t size)
// clang-format on
unsigned diff, regind, elm, bit;
MOZ_DIAGNOSTIC_ASSERT(run->magic == ARENA_RUN_MAGIC);
MOZ_DIAGNOSTIC_ASSERT(run->mMagic == ARENA_RUN_MAGIC);
static_assert(((sizeof(size_invs)) / sizeof(unsigned)) + 3 >=
kNumQuantumClasses,
"size_invs doesn't have enough values");
@ -2352,33 +2359,8 @@ arena_run_reg_dalloc(arena_run_t* run, arena_bin_t* bin, void* ptr, size_t size)
// actual division here can reduce allocator throughput by over 20%!
diff =
(unsigned)((uintptr_t)ptr - (uintptr_t)run - bin->mRunFirstRegionOffset);
if ((size & (size - 1)) == 0) {
// log2_table allows fast division of a power of two in the
// [1..128] range.
//
// (x / divisor) becomes (x >> log2_table[divisor - 1]).
// clang-format off
static const unsigned char log2_table[] = {
0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7
};
// clang-format on
if (size <= 128) {
regind = (diff >> log2_table[size - 1]);
} else if (size <= 32768) {
regind = diff >> (8 + log2_table[(size >> 8) - 1]);
} else {
// The run size is too large for us to use the lookup
// table. Use real division.
regind = diff / size;
}
if (mozilla::IsPowerOfTwo(size)) {
regind = diff >> FloorLog2(size);
} else if (size <= ((sizeof(size_invs) / sizeof(unsigned)) * kQuantum) + 2) {
regind = size_invs[(size / kQuantum) - 3] * diff;
regind >>= SIZE_INV_SHIFT;
@ -2393,12 +2375,12 @@ arena_run_reg_dalloc(arena_run_t* run, arena_bin_t* bin, void* ptr, size_t size)
MOZ_DIAGNOSTIC_ASSERT(regind < bin->mRunNumRegions);
elm = regind >> (LOG2(sizeof(int)) + 3);
if (elm < run->regs_minelm) {
run->regs_minelm = elm;
if (elm < run->mRegionsMinElement) {
run->mRegionsMinElement = elm;
}
bit = regind - (elm << (LOG2(sizeof(int)) + 3));
MOZ_DIAGNOSTIC_ASSERT((run->regs_mask[elm] & (1U << bit)) == 0);
run->regs_mask[elm] |= (1U << bit);
MOZ_DIAGNOSTIC_ASSERT((run->mRegionsMask[elm] & (1U << bit)) == 0);
run->mRegionsMask[elm] |= (1U << bit);
#undef SIZE_INV
#undef SIZE_INV_SHIFT
}
@ -2595,7 +2577,7 @@ arena_t::DeallocChunk(arena_chunk_t* aChunk)
}
arena_run_t*
arena_t::AllocRun(arena_bin_t* aBin, size_t aSize, bool aLarge, bool aZero)
arena_t::AllocRun(size_t aSize, bool aLarge, bool aZero)
{
arena_run_t* run;
arena_chunk_map_t* mapelm;
@ -2739,7 +2721,7 @@ arena_t::DallocRun(arena_run_t* aRun, bool aDirty)
if ((chunk->map[run_ind].bits & CHUNK_MAP_LARGE) != 0) {
size = chunk->map[run_ind].bits & ~gPageSizeMask;
} else {
size = aRun->bin->mRunSize;
size = aRun->mBin->mRunSize;
}
run_pages = (size >> gPageSize2Pow);
@ -2886,7 +2868,7 @@ arena_t::GetNonFullBinRun(arena_bin_t* aBin)
// No existing runs have any space available.
// Allocate a new run.
run = AllocRun(aBin, aBin->mRunSize, false, false);
run = AllocRun(aBin->mRunSize, false, false);
if (!run) {
return nullptr;
}
@ -2897,135 +2879,110 @@ arena_t::GetNonFullBinRun(arena_bin_t* aBin)
}
// Initialize run internals.
run->bin = aBin;
run->mBin = aBin;
for (i = 0; i < aBin->mRunNumRegionsMask - 1; i++) {
run->regs_mask[i] = UINT_MAX;
run->mRegionsMask[i] = UINT_MAX;
}
remainder = aBin->mRunNumRegions & ((1U << (LOG2(sizeof(int)) + 3)) - 1);
if (remainder == 0) {
run->regs_mask[i] = UINT_MAX;
run->mRegionsMask[i] = UINT_MAX;
} else {
// The last element has spare bits that need to be unset.
run->regs_mask[i] =
run->mRegionsMask[i] =
(UINT_MAX >> ((1U << (LOG2(sizeof(int)) + 3)) - remainder));
}
run->regs_minelm = 0;
run->mRegionsMinElement = 0;
run->nfree = aBin->mRunNumRegions;
run->mNumFree = aBin->mRunNumRegions;
#if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
run->magic = ARENA_RUN_MAGIC;
run->mMagic = ARENA_RUN_MAGIC;
#endif
aBin->mNumRuns++;
return run;
}
// bin->mCurrentRun must have space available before this function is called.
void*
arena_t::MallocBinEasy(arena_bin_t* aBin, arena_run_t* aRun)
void
arena_bin_t::Init(SizeClass aSizeClass)
{
void* ret;
MOZ_DIAGNOSTIC_ASSERT(aRun->magic == ARENA_RUN_MAGIC);
MOZ_DIAGNOSTIC_ASSERT(aRun->nfree > 0);
ret = arena_run_reg_alloc(aRun, aBin);
MOZ_DIAGNOSTIC_ASSERT(ret);
aRun->nfree--;
return ret;
}
// Re-fill aBin->mCurrentRun, then call arena_t::MallocBinEasy().
void*
arena_t::MallocBinHard(arena_bin_t* aBin)
{
aBin->mCurrentRun = GetNonFullBinRun(aBin);
if (!aBin->mCurrentRun) {
return nullptr;
}
MOZ_DIAGNOSTIC_ASSERT(aBin->mCurrentRun->magic == ARENA_RUN_MAGIC);
MOZ_DIAGNOSTIC_ASSERT(aBin->mCurrentRun->nfree > 0);
return MallocBinEasy(aBin, aBin->mCurrentRun);
}
// Calculate bin->mRunSize such that it meets the following constraints:
//
// *) bin->mRunSize >= min_run_size
// *) bin->mRunSize <= gMaxLargeClass
// *) bin->mRunSize <= gMaxBinClass
// *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed).
//
// bin->mRunNumRegions, bin->mRunNumRegionsMask, and bin->mRunFirstRegionOffset are
// also calculated here, since these settings are all interdependent.
static size_t
arena_bin_run_size_calc(arena_bin_t* bin, size_t min_run_size)
{
size_t try_run_size, good_run_size;
unsigned good_nregs, good_mask_nelms, good_reg0_offset;
size_t try_run_size;
unsigned try_nregs, try_mask_nelms, try_reg0_offset;
// Size of the run header, excluding mRegionsMask.
static const size_t kFixedHeaderSize = offsetof(arena_run_t, mRegionsMask);
MOZ_ASSERT(min_run_size >= gPageSize);
MOZ_ASSERT(min_run_size <= gMaxLargeClass);
MOZ_ASSERT(aSizeClass.Size() <= gMaxBinClass);
// Calculate known-valid settings before entering the mRunSize
// expansion loop, so that the first part of the loop always copies
// valid settings.
//
// The do..while loop iteratively reduces the number of regions until
// the run header and the regions no longer overlap. A closed formula
// would be quite messy, since there is an interdependency between the
// header's mask length and the number of regions.
try_run_size = min_run_size;
try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->mSizeClass) +
1; // Counter-act try_nregs-- in loop.
do {
try_nregs--;
try_mask_nelms =
(try_nregs >> (LOG2(sizeof(int)) + 3)) +
((try_nregs & ((1U << (LOG2(sizeof(int)) + 3)) - 1)) ? 1 : 0);
try_reg0_offset = try_run_size - (try_nregs * bin->mSizeClass);
} while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1)) >
try_reg0_offset);
try_run_size = gPageSize;
mCurrentRun = nullptr;
mNonFullRuns.Init();
mSizeClass = aSizeClass.Size();
mNumRuns = 0;
// mRunSize expansion loop.
do {
// Copy valid settings before trying more aggressive settings.
good_run_size = try_run_size;
good_nregs = try_nregs;
good_mask_nelms = try_mask_nelms;
good_reg0_offset = try_reg0_offset;
// Try more aggressive settings.
try_run_size += gPageSize;
try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->mSizeClass) +
while (true) {
try_nregs = ((try_run_size - kFixedHeaderSize) / mSizeClass) +
1; // Counter-act try_nregs-- in loop.
// The do..while loop iteratively reduces the number of regions until
// the run header and the regions no longer overlap. A closed formula
// would be quite messy, since there is an interdependency between the
// header's mask length and the number of regions.
do {
try_nregs--;
try_mask_nelms =
(try_nregs >> (LOG2(sizeof(int)) + 3)) +
((try_nregs & ((1U << (LOG2(sizeof(int)) + 3)) - 1)) ? 1 : 0);
try_reg0_offset = try_run_size - (try_nregs * bin->mSizeClass);
} while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1)) >
try_reg0_offset = try_run_size - (try_nregs * mSizeClass);
} while (kFixedHeaderSize + (sizeof(unsigned) * try_mask_nelms) >
try_reg0_offset);
} while (try_run_size <= gMaxLargeClass &&
RUN_MAX_OVRHD * (bin->mSizeClass << 3) > RUN_MAX_OVRHD_RELAX &&
(try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size);
MOZ_ASSERT(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1)) <=
good_reg0_offset);
MOZ_ASSERT((good_mask_nelms << (LOG2(sizeof(int)) + 3)) >= good_nregs);
// Don't allow runs larger than the largest possible large size class.
if (try_run_size > gMaxLargeClass) {
break;
}
// Try to keep the run overhead below kRunOverhead.
if (Fraction(try_reg0_offset, try_run_size) <= kRunOverhead) {
break;
}
// If the overhead is larger than the size class, it means the size class
// is small and doesn't align very well with the header. It's desirable to
// have smaller run sizes for them, so relax the overhead requirement.
if (try_reg0_offset > mSizeClass) {
if (Fraction(try_reg0_offset, try_run_size) <= kRunRelaxedOverhead) {
break;
}
}
// The run header includes one bit per region of the given size. For sizes
// small enough, the number of regions is large enough that growing the run
// size barely moves the needle for the overhead because of all those bits.
// For example, for a size of 8 bytes, adding 4KiB to the run size adds
// close to 512 bits to the header, which is 64 bytes.
// With such overhead, there is no way to get to the wanted overhead above,
// so we give up if the required size for mRegionsMask more than doubles the
// size of the run header.
if (try_mask_nelms * sizeof(unsigned) >= kFixedHeaderSize) {
break;
}
// Try more aggressive settings.
try_run_size += gPageSize;
}
MOZ_ASSERT(kFixedHeaderSize + (sizeof(unsigned) * try_mask_nelms) <=
try_reg0_offset);
MOZ_ASSERT((try_mask_nelms << (LOG2(sizeof(int)) + 3)) >= try_nregs);
// Copy final settings.
bin->mRunSize = good_run_size;
bin->mRunNumRegions = good_nregs;
bin->mRunNumRegionsMask = good_mask_nelms;
bin->mRunFirstRegionOffset = good_reg0_offset;
return good_run_size;
mRunSize = try_run_size;
mRunNumRegions = try_nregs;
mRunNumRegionsMask = try_mask_nelms;
mRunFirstRegionOffset = try_reg0_offset;
}
void*
@ -3055,12 +3012,18 @@ arena_t::MallocSmall(size_t aSize, bool aZero)
{
MutexAutoLock lock(mLock);
if ((run = bin->mCurrentRun) && run->nfree > 0) {
ret = MallocBinEasy(bin, run);
} else {
ret = MallocBinHard(bin);
run = bin->mCurrentRun;
if (MOZ_UNLIKELY(!run || run->mNumFree == 0)) {
run = bin->mCurrentRun = GetNonFullBinRun(bin);
}
if (MOZ_UNLIKELY(!run)) {
return nullptr;
}
MOZ_DIAGNOSTIC_ASSERT(run->mMagic == ARENA_RUN_MAGIC);
MOZ_DIAGNOSTIC_ASSERT(run->mNumFree > 0);
ret = arena_run_reg_alloc(run, bin);
MOZ_DIAGNOSTIC_ASSERT(ret);
run->mNumFree--;
if (!ret) {
return nullptr;
}
@ -3091,7 +3054,7 @@ arena_t::MallocLarge(size_t aSize, bool aZero)
{
MutexAutoLock lock(mLock);
ret = AllocRun(nullptr, aSize, true, aZero);
ret = AllocRun(aSize, true, aZero);
if (!ret) {
return nullptr;
}
@ -3145,7 +3108,7 @@ arena_t::Palloc(size_t aAlignment, size_t aSize, size_t aAllocSize)
{
MutexAutoLock lock(mLock);
ret = AllocRun(nullptr, aAllocSize, true, false);
ret = AllocRun(aAllocSize, true, false);
if (!ret) {
return nullptr;
}
@ -3290,8 +3253,8 @@ arena_salloc(const void* ptr)
MOZ_DIAGNOSTIC_ASSERT((mapbits & CHUNK_MAP_ALLOCATED) != 0);
if ((mapbits & CHUNK_MAP_LARGE) == 0) {
arena_run_t* run = (arena_run_t*)(mapbits & ~gPageSizeMask);
MOZ_DIAGNOSTIC_ASSERT(run->magic == ARENA_RUN_MAGIC);
ret = run->bin->mSizeClass;
MOZ_DIAGNOSTIC_ASSERT(run->mMagic == ARENA_RUN_MAGIC);
ret = run->mBin->mSizeClass;
} else {
ret = mapbits & ~gPageSizeMask;
MOZ_DIAGNOSTIC_ASSERT(ret != 0);
@ -3470,13 +3433,13 @@ MozJemalloc::jemalloc_ptr_info(const void* aPtr, jemalloc_ptr_info_t* aInfo)
// It must be a small allocation.
auto run = (arena_run_t*)(mapbits & ~gPageSizeMask);
MOZ_DIAGNOSTIC_ASSERT(run->magic == ARENA_RUN_MAGIC);
MOZ_DIAGNOSTIC_ASSERT(run->mMagic == ARENA_RUN_MAGIC);
// The allocation size is stored in the run metadata.
size_t size = run->bin->mSizeClass;
size_t size = run->mBin->mSizeClass;
// Address of the first possible pointer in the run after its headers.
uintptr_t reg0_addr = (uintptr_t)run + run->bin->mRunFirstRegionOffset;
uintptr_t reg0_addr = (uintptr_t)run + run->mBin->mRunFirstRegionOffset;
if (aPtr < (void*)reg0_addr) {
// In the run header.
*aInfo = { TagUnknown, nullptr, 0 };
@ -3493,7 +3456,7 @@ MozJemalloc::jemalloc_ptr_info(const void* aPtr, jemalloc_ptr_info_t* aInfo)
unsigned elm = regind >> (LOG2(sizeof(int)) + 3);
unsigned bit = regind - (elm << (LOG2(sizeof(int)) + 3));
PtrInfoTag tag =
((run->regs_mask[elm] & (1U << bit))) ? TagFreedSmall : TagLiveSmall;
((run->mRegionsMask[elm] & (1U << bit))) ? TagFreedSmall : TagLiveSmall;
*aInfo = { tag, addr, size };
}
@ -3519,8 +3482,8 @@ arena_t::DallocSmall(arena_chunk_t* aChunk,
size_t size;
run = (arena_run_t*)(aMapElm->bits & ~gPageSizeMask);
MOZ_DIAGNOSTIC_ASSERT(run->magic == ARENA_RUN_MAGIC);
bin = run->bin;
MOZ_DIAGNOSTIC_ASSERT(run->mMagic == ARENA_RUN_MAGIC);
bin = run->mBin;
size = bin->mSizeClass;
MOZ_DIAGNOSTIC_ASSERT(uintptr_t(aPtr) >=
uintptr_t(run) + bin->mRunFirstRegionOffset);
@ -3531,9 +3494,9 @@ arena_t::DallocSmall(arena_chunk_t* aChunk,
memset(aPtr, kAllocPoison, size);
arena_run_reg_dalloc(run, bin, aPtr, size);
run->nfree++;
run->mNumFree++;
if (run->nfree == bin->mRunNumRegions) {
if (run->mNumFree == bin->mRunNumRegions) {
// Deallocate run.
if (run == bin->mCurrentRun) {
bin->mCurrentRun = nullptr;
@ -3549,18 +3512,18 @@ arena_t::DallocSmall(arena_chunk_t* aChunk,
bin->mNonFullRuns.Remove(run_mapelm);
}
#if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
run->magic = 0;
run->mMagic = 0;
#endif
DallocRun(run, true);
bin->mNumRuns--;
} else if (run->nfree == 1 && run != bin->mCurrentRun) {
} else if (run->mNumFree == 1 && run != bin->mCurrentRun) {
// Make sure that bin->mCurrentRun always refers to the lowest
// non-full run, if one exists.
if (!bin->mCurrentRun) {
bin->mCurrentRun = run;
} else if (uintptr_t(run) < uintptr_t(bin->mCurrentRun)) {
// Switch mCurrentRun.
if (bin->mCurrentRun->nfree > 0) {
if (bin->mCurrentRun->mNumFree > 0) {
arena_chunk_t* runcur_chunk = GetChunkForPtr(bin->mCurrentRun);
size_t runcur_pageind =
(uintptr_t(bin->mCurrentRun) - uintptr_t(runcur_chunk)) >>
@ -3792,8 +3755,6 @@ iralloc(void* aPtr, size_t aSize, arena_t* aArena)
arena_t::arena_t()
{
unsigned i;
arena_bin_t* bin;
size_t prev_run_size;
MOZ_RELEASE_ASSERT(mLock.Init());
@ -3815,19 +3776,11 @@ arena_t::arena_t()
mRunsAvail.Init();
// Initialize bins.
prev_run_size = gPageSize;
SizeClass sizeClass(1);
for (i = 0;; i++) {
bin = &mBins[i];
bin->mCurrentRun = nullptr;
bin->mNonFullRuns.Init();
bin->mSizeClass = sizeClass.Size();
prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
bin->mNumRuns = 0;
arena_bin_t& bin = mBins[i];
bin.Init(sizeClass);
// SizeClass doesn't want sizes larger than gMaxSubPageClass for now.
if (sizeClass.Size() == gMaxSubPageClass) {
@ -4577,11 +4530,11 @@ MozJemalloc::jemalloc_stats(jemalloc_stats_t* aStats)
for (auto mapelm : bin->mNonFullRuns.iter()) {
run = (arena_run_t*)(mapelm->bits & ~gPageSizeMask);
bin_unused += run->nfree * bin->mSizeClass;
bin_unused += run->mNumFree * bin->mSizeClass;
}
if (bin->mCurrentRun) {
bin_unused += bin->mCurrentRun->nfree * bin->mSizeClass;
bin_unused += bin->mCurrentRun->mNumFree * bin->mSizeClass;
}
arena_unused += bin_unused;

Просмотреть файл

@ -193,7 +193,7 @@ this.FxAccountsStorageManager.prototype = {
result[fieldName] = this.cachedSecure[fieldName];
}
} else {
throw new Error("unexpected field '" + name + "'");
throw new Error("unexpected field '" + fieldName + "'");
}
}
return result;

Просмотреть файл

@ -510,8 +510,7 @@ this.FxAccountsWebChannelHelpers.prototype = {
ps.BUTTON_POS_1_DEFAULT;
// If running in context of the browser chrome, window does not exist.
var targetWindow = typeof window === "undefined" ? null : window;
let pressed = Services.prompt.confirmEx(targetWindow, title, body, buttonFlags,
let pressed = Services.prompt.confirmEx(null, title, body, buttonFlags,
continueLabel, null, null, null,
{});
return pressed === 0; // 0 is the "continue" button

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-events-session-closed-event.html]
[clearkey-events-session-closed-event.https.html]
type: testharness
[org.w3.clearkey test MediaKeySession closed event.]
expected:

Просмотреть файл

@ -0,0 +1,3 @@
[clearkey-mp4-playback-destroy-persistent-license.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[clearkey-mp4-playback-persistent-license-events.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[clearkey-mp4-playback-persistent-license.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[clearkey-mp4-playback-persistent-usage-record-events.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[clearkey-mp4-playback-persistent-usage-record.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[clearkey-mp4-playback-retrieve-persistent-license.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[clearkey-mp4-playback-retrieve-persistent-license.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[clearkey-mp4-playback-retrieve-persistent-usage-record.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[clearkey-mp4-playback-retrieve-persistent-usage-record.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-clear-encrypted.html]
[clearkey-mp4-playback-temporary-clear-encrypted.https.html]
type: testharness
[org.w3.clearkey, temporary, mp4, playback, single key, clear then encrypted content]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-encrypted-clear-sources.html]
[clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html]
type: testharness
[org.w3.clearkey, temporary, mp4, playback, encrypted and clear sources]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-encrypted-clear.html]
[clearkey-mp4-playback-temporary-encrypted-clear.https.html]
type: testharness
disabled:
if os == "linux": https://bugzilla.mozilla.org/show_bug.cgi?id=1301418

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-events.html]
[clearkey-mp4-playback-temporary-events.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1312914
[org.w3.clearkey, sucessful playback and events, temporary, mp4, set src before setMediaKeys]

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-multikey-sequential-readyState.html]
[clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html]
type: testharness
[org.w3.clearkey, successful playback, temporary, mp4, multiple keys, sequential, readyState]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-multikey.html]
[clearkey-mp4-playback-temporary-multikey.https.html]
type: testharness
[org.w3.clearkey, successful playback, temporary, mp4, multiple keys, single session, audio/video]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-multisession.html]
[clearkey-mp4-playback-temporary-multisession.https.html]
type: testharness
[org.w3.clearkey, temporary, mp4, playback with multiple sessions, multikey video]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-setMediaKeys-after-src.html]
[clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html]
type: testharness
[org.w3.clearkey, temporary, mp4, playback, setMediaKeys after setting video.src]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-setMediaKeys-after-update.html]
[clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html]
type: testharness
[org.w3.clearkey, temporary, mp4, playback, setMediaKeys after updating session]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-setMediaKeys-immediately.html]
[clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html]
type: testharness
[org.w3.clearkey, temporary, mp4, playback, setMediaKeys first]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html]
[clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html]
type: testharness
[org.w3.clearkey, temporary, mp4, playback, setMediaKeys in encrypted event]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-two-videos.html]
[clearkey-mp4-playback-temporary-two-videos.https.html]
type: testharness
[org.w3.clearkey, sucessful playback, temporary, mp4, set src before setMediaKeys]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary-waitingforkey.html]
[clearkey-mp4-playback-temporary-waitingforkey.https.html]
type: testharness
[org.w3.clearkey, successful playback, temporary, mp4, waitingforkey event, 1 key]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-playback-temporary.html]
[clearkey-mp4-playback-temporary.https.html]
type: testharness
[org.w3.clearkey, sucessful playback, temporary, mp4, set src before setMediaKeys]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-requestmediakeysystemaccess.html]
[clearkey-mp4-requestmediakeysystemaccess.https.html]
type: testharness
[Basic supported configuration]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-reset-src-after-setmediakeys.html]
[clearkey-mp4-reset-src-after-setmediakeys.https.html]
type: testharness
[Reset src after setMediaKeys().]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-setmediakeys-again-after-resetting-src.html]
[clearkey-mp4-setmediakeys-again-after-resetting-src.https.html]
type: testharness
[org.w3.clearkey, setmediakeys again after resetting src]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html]
[clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html]
type: testharness
[org.w3.clearkey, setmediakeys multiple times with different mediakeys]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html]
[clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html]
type: testharness
[org.w3.clearkey, setmediakeys multiple times with the same mediakeys]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-syntax-mediakeys.html]
[clearkey-mp4-syntax-mediakeys.https.html]
type: testharness
[org.w3.clearkey test MediaKeys attribute syntax]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-syntax-mediakeysystemaccess.html]
[clearkey-mp4-syntax-mediakeysystemaccess.https.html]
type: testharness
[org.w3.clearkey test MediaKeySystemAccess attribute syntax.]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-unique-origin.html]
[clearkey-mp4-unique-origin.https.html]
type: testharness
[Unique origin is unable to create MediaKeys]
expected: FAIL

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-mp4-waiting-for-a-key.html]
[clearkey-mp4-waiting-for-a-key.https.html]
type: testharness
[Waiting for a key.]
expected:

Просмотреть файл

@ -1,4 +1,4 @@
[clearkey-update-non-ascii-input.html]
[clearkey-update-non-ascii-input.https.html]
type: testharness
[org.w3.clearkey test handling of non-ASCII responses for update()]
expected:

Просмотреть файл

@ -0,0 +1,3 @@
[drm-check-initdata-type.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[drm-events-session-closed-event.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +1,3 @@
[drm-events.html]
[drm-events.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +1,3 @@
[drm-keystatuses.html]
[drm-expiration.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[drm-generate-request-disallowed-input.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[drm-generate-request-disallowed-input.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +1,3 @@
[drm-check-initdata-type.html]
[drm-invalid-license.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[drm-keystatuses-multiple-sessions.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[drm-keystatuses-multiple-sessions.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +1,3 @@
[drm-invalid-license.html]
[drm-keystatuses.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[drm-mp4-onencrypted.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +1,3 @@
[drm-expiration.html]
[drm-mp4-onencrypted.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[drm-mp4-playback-destroy-persistent-license.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[drm-mp4-playback-destroy-persistent-license.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[drm-mp4-playback-persistent-license-events.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +1,3 @@
[clearkey-mp4-playback-destroy-persistent-license.html]
[drm-mp4-playback-persistent-license-events.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[drm-mp4-playback-persistent-license.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[drm-mp4-playback-persistent-license.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[drm-mp4-playback-persistent-usage-record-events.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[drm-mp4-playback-persistent-usage-record-events.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[drm-mp4-playback-persistent-usage-record.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[drm-mp4-playback-persistent-usage-record.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[drm-mp4-playback-retrieve-destroy-persistent-license.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[drm-mp4-playback-retrieve-destroy-persistent-license.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[drm-mp4-playback-retrieve-persistent-license.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[drm-mp4-playback-retrieve-persistent-license.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -1,3 +0,0 @@
[drm-mp4-playback-retrieve-persistent-usage-record.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Просмотреть файл

@ -0,0 +1,3 @@
[drm-mp4-playback-retrieve-persistent-usage-record.https.html]
type: testharness
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1313284

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше