Merge autoland to mozilla-central. a=merge

This commit is contained in:
Marian-Vasile Laza 2022-04-14 14:44:12 -07:00
Родитель e28a51a54d 92dd774844
Коммит 489ae24cb0
133 изменённых файлов: 11312 добавлений и 1063 удалений

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

@ -5,6 +5,12 @@ const { TelemetryTestUtils } = ChromeUtils.import(
"resource://testing-common/TelemetryTestUtils.jsm" "resource://testing-common/TelemetryTestUtils.jsm"
); );
ChromeUtils.defineModuleGetter(
this,
"BrowserGlue",
"resource:///modules/BrowserGlue.jsm"
);
const PREF_DFPI_ENABLED_BY_DEFAULT = const PREF_DFPI_ENABLED_BY_DEFAULT =
"privacy.restrict3rdpartystorage.rollout.enabledByDefault"; "privacy.restrict3rdpartystorage.rollout.enabledByDefault";
const COOKIE_BEHAVIOR_PREF = "network.cookie.cookieBehavior"; const COOKIE_BEHAVIOR_PREF = "network.cookie.cookieBehavior";
@ -24,14 +30,22 @@ const SEARCH_PREFS_OPT_OUT = [
["browser.search.param.bing_ptag", "MOZZ0000000032"], ["browser.search.param.bing_ptag", "MOZZ0000000032"],
]; ];
registerCleanupFunction(function() { function cleanup() {
[...SEARCH_PREFS_OPT_IN, ...SEARCH_PREFS_OPT_OUT].forEach(([key]) =>
Services.prefs.clearUserPref(key)
);
[COOKIE_BEHAVIOR_PREF, PREF_DFPI_ENABLED_BY_DEFAULT].forEach(
Services.prefs.clearUserPref
);
BrowserGlue._defaultCookieBehaviorAtStartup = previousDefaultCB;
defaultPrefs.setIntPref(COOKIE_BEHAVIOR_PREF, previousDefaultCB); defaultPrefs.setIntPref(COOKIE_BEHAVIOR_PREF, previousDefaultCB);
[
PREF_DFPI_ENABLED_BY_DEFAULT, // Reset the rollout scalar back to 2 = unset. We have to simulate this on
...SEARCH_PREFS_OPT_IN, // test cleanup, because BrowserGlue only sets this once initially.
...SEARCH_PREFS_OPT_OUT, Services.telemetry.scalarSet("privacy.dfpi_rollout_enabledByDefault", 2);
].forEach(([key]) => Services.prefs.clearUserPref(key)); }
});
function testSearchPrefState(optIn) { function testSearchPrefState(optIn) {
let expectedPrefs = optIn ? SEARCH_PREFS_OPT_IN : SEARCH_PREFS_OPT_OUT; let expectedPrefs = optIn ? SEARCH_PREFS_OPT_IN : SEARCH_PREFS_OPT_OUT;
@ -68,6 +82,11 @@ function testTelemetryState(optIn) {
// Tests that the dFPI rollout pref updates the default cookieBehavior to 5, // Tests that the dFPI rollout pref updates the default cookieBehavior to 5,
// sets the correct search prefs and records telemetry. // sets the correct search prefs and records telemetry.
add_task(async function testdFPIRolloutPref() { add_task(async function testdFPIRolloutPref() {
// The BrowserGlue code which computes this flag runs before we can set the
// default cookie behavior for this test. Thus we need to overwrite it in
// order for the opt-out to work correctly.
BrowserGlue._defaultCookieBehaviorAtStartup =
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER;
defaultPrefs.setIntPref( defaultPrefs.setIntPref(
COOKIE_BEHAVIOR_PREF, COOKIE_BEHAVIOR_PREF,
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER
@ -107,4 +126,77 @@ add_task(async function testdFPIRolloutPref() {
); );
testSearchPrefState(true); testSearchPrefState(true);
testTelemetryState(true); testTelemetryState(true);
cleanup();
});
/**
* Setting the rollout pref to false should revert to the initial default cookie
* behavior, not always BEHAVIOR_REJECT_TRACKER.
*/
add_task(async function testdFPIRolloutPrefNonDefaultCookieBehavior() {
BrowserGlue._defaultCookieBehaviorAtStartup =
Ci.nsICookieService.BEHAVIOR_ACCEPT;
defaultPrefs.setIntPref(
COOKIE_BEHAVIOR_PREF,
Ci.nsICookieService.BEHAVIOR_ACCEPT
);
is(
Services.prefs.getIntPref(COOKIE_BEHAVIOR_PREF),
Ci.nsICookieService.BEHAVIOR_ACCEPT,
"Initial cookie behavior should be BEHAVIOR_ACCEPT"
);
Services.prefs.setBoolPref(PREF_DFPI_ENABLED_BY_DEFAULT, true);
is(
defaultPrefs.getIntPref(COOKIE_BEHAVIOR_PREF),
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
"Default cookie behavior should be set to dFPI."
);
Services.prefs.setBoolPref(PREF_DFPI_ENABLED_BY_DEFAULT, false);
is(
defaultPrefs.getIntPref(COOKIE_BEHAVIOR_PREF),
Ci.nsICookieService.BEHAVIOR_ACCEPT,
"Default cookie behavior should be set to BEHAVIOR_ACCEPT."
);
cleanup();
});
/**
* When a client already ships with dFPI enabled, toggling the rollout pref
* should not change cookie behavior.
*/
add_task(async function testdFPIRolloutPrefDFPIAlreadyEnabled() {
// Simulate TCP enabled by default.
BrowserGlue._defaultCookieBehaviorAtStartup =
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN;
defaultPrefs.setIntPref(
COOKIE_BEHAVIOR_PREF,
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN
);
is(
Services.prefs.getIntPref(COOKIE_BEHAVIOR_PREF),
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
"Initial cookie behavior should be BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN"
);
Services.prefs.setBoolPref(PREF_DFPI_ENABLED_BY_DEFAULT, true);
is(
defaultPrefs.getIntPref(COOKIE_BEHAVIOR_PREF),
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
"Default cookie behavior should still be BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN."
);
Services.prefs.setBoolPref(PREF_DFPI_ENABLED_BY_DEFAULT, false);
is(
defaultPrefs.getIntPref(COOKIE_BEHAVIOR_PREF),
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
"Default cookie behavior should still be BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN."
);
cleanup();
}); });

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

@ -889,6 +889,7 @@ BrowserGlue.prototype = {
_migrationImportsDefaultBookmarks: false, _migrationImportsDefaultBookmarks: false,
_placesBrowserInitComplete: false, _placesBrowserInitComplete: false,
_isNewProfile: undefined, _isNewProfile: undefined,
_defaultCookieBehaviorAtStartup: null,
_setPrefToSaveSession: function BG__setPrefToSaveSession(aForce) { _setPrefToSaveSession: function BG__setPrefToSaveSession(aForce) {
if (!this._saveSession && !aForce) { if (!this._saveSession && !aForce) {
@ -1675,9 +1676,16 @@ BrowserGlue.prototype = {
PlacesUtils.favicons.setDefaultIconURIPreferredSize( PlacesUtils.favicons.setDefaultIconURIPreferredSize(
16 * aWindow.devicePixelRatio 16 * aWindow.devicePixelRatio
); );
// Keep track of the initial default cookie behavior to revert to when
// users opt-out. This is used by _setDefaultCookieBehavior.
BrowserGlue._defaultCookieBehaviorAtStartup = Services.prefs
.getDefaultBranch("")
.getIntPref("network.cookie.cookieBehavior");
// _setDefaultCookieBehavior needs to run before other functions that modify // _setDefaultCookieBehavior needs to run before other functions that modify
// privacy preferences such as _setPrefExpectationsAndUpdate and _matchCBCategory // privacy preferences such as _setPrefExpectationsAndUpdate and _matchCBCategory
this._setDefaultCookieBehavior(); this._setDefaultCookieBehavior();
this._setPrefExpectationsAndUpdate(); this._setPrefExpectationsAndUpdate();
this._matchCBCategory(); this._matchCBCategory();
@ -1753,7 +1761,7 @@ BrowserGlue.prototype = {
"network.cookie.cookieBehavior", "network.cookie.cookieBehavior",
dFPIEnabled dFPIEnabled
? Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN ? Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN
: Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER : BrowserGlue._defaultCookieBehaviorAtStartup
); );
Services.telemetry.scalarSet( Services.telemetry.scalarSet(

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

@ -1438,6 +1438,12 @@ var Policies = {
}, },
}, },
PasswordManagerExceptions: {
onBeforeUIStartup(manager, param) {
addAllowDenyPermissions("login-saving", null, param);
},
},
PDFjs: { PDFjs: {
onBeforeAddons(manager, param) { onBeforeAddons(manager, param) {
if ("Enabled" in param) { if ("Enabled" in param) {

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

@ -787,6 +787,14 @@
"type": "boolean" "type": "boolean"
}, },
"PasswordManagerExceptions": {
"type": "array",
"strict": false,
"items": {
"type": "origin"
}
},
"PDFjs": { "PDFjs": {
"type": "object", "type": "object",
"properties": { "properties": {

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

@ -336,3 +336,20 @@ add_task(async function test_autolaunchprotocolsfromorigins() {
Ci.nsIPermissionManager.ALLOW_ACTION Ci.nsIPermissionManager.ALLOW_ACTION
); );
}); });
// This again seems out of places, but PasswordManagerExceptions
// is all permissions.
add_task(async function test_passwordmanagerexceptions() {
await setupPolicyEngineWithJson({
policies: {
PasswordManagerExceptions: ["https://pwexception.example.com"],
},
});
equal(
PermissionTestUtils.testPermission(
URI("https://pwexception.example.com"),
"login-saving"
),
Ci.nsIPermissionManager.DENY_ACTION
);
});

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

@ -49,6 +49,10 @@ XPCOMUtils.defineLazyPreferenceGetter(
* This title should only be used if `title` is not present. * This title should only be used if `title` is not present.
* @property {string} imageUrl * @property {string} imageUrl
* The image url to use for the group. * The image url to use for the group.
* @property {string} faviconDataUrl
* The data url to use for the favicon, null if not available.
* @property {string} imagePageUrl
* The url of the snapshot used to get the image and favicon urls.
* @property {number} lastAccessed * @property {number} lastAccessed
* The last access time of the most recently accessed snapshot. * The last access time of the most recently accessed snapshot.
* Stored as the number of milliseconds since the epoch. * Stored as the number of milliseconds since the epoch.
@ -372,7 +376,7 @@ const SnapshotGroups = new (class SnapshotGroups {
params params
); );
return rows.map(row => this.#translateSnapshotGroupRow(row)); return Promise.all(rows.map(row => this.#translateSnapshotGroupRow(row)));
} }
/** /**
@ -499,7 +503,7 @@ const SnapshotGroups = new (class SnapshotGroups {
* The database row to translate. * The database row to translate.
* @returns {SnapshotGroup} * @returns {SnapshotGroup}
*/ */
#translateSnapshotGroupRow(row) { async #translateSnapshotGroupRow(row) {
// Group image selection should be done in this order: // Group image selection should be done in this order:
// 1. Oldest view in group featured image // 1. Oldest view in group featured image
// 2. Second Oldest View in group featured image // 2. Second Oldest View in group featured image
@ -512,7 +516,7 @@ const SnapshotGroups = new (class SnapshotGroups {
// available. // available.
// The query returns featured1|featured2|url1|url2 // The query returns featured1|featured2|url1|url2
let imageUrls = row.getResultByName("image_urls")?.split("|"); let imageUrls = row.getResultByName("image_urls")?.split("|");
let imageUrl = null; let imageUrl, faviconDataUrl, imagePageUrl;
if (imageUrls) { if (imageUrls) {
imageUrl = imageUrls[0] || imageUrls[1]; imageUrl = imageUrls[0] || imageUrls[1];
if (!imageUrl && imageUrls[2]) { if (!imageUrl && imageUrls[2]) {
@ -524,11 +528,41 @@ const SnapshotGroups = new (class SnapshotGroups {
imageUrl = PageThumbs.getThumbnailURL(imageUrl); imageUrl = PageThumbs.getThumbnailURL(imageUrl);
} }
} }
// The favicon is for the same page we return a preview image for.
imagePageUrl =
imageUrls[2] && !imageUrls[0] && imageUrls[1]
? imageUrls[3]
: imageUrls[2];
if (imagePageUrl) {
faviconDataUrl = await new Promise(resolve => {
PlacesUtils.favicons.getFaviconDataForPage(
Services.io.newURI(imagePageUrl),
(uri, dataLength, data, mimeType) => {
if (dataLength) {
// NOTE: honestly this is awkward and inefficient. We build a string
// with String.fromCharCode and then btoa that. It's a Uint8Array
// under the hood, and we should probably just expose something in
// ChromeUtils to Base64 encode a Uint8Array directly, but this is
// fine for now.
let b64 = btoa(
data.reduce((d, byte) => d + String.fromCharCode(byte), "")
);
resolve(`data:${mimeType};base64,${b64}`);
return;
}
resolve(undefined);
}
);
});
}
} }
let snapshotGroup = { let snapshotGroup = {
id: row.getResultByName("id"), id: row.getResultByName("id"),
faviconDataUrl,
imageUrl, imageUrl,
imagePageUrl,
title: row.getResultByName("title") || "", title: row.getResultByName("title") || "",
hidden: row.getResultByName("hidden") == 1, hidden: row.getResultByName("hidden") == 1,
builder: row.getResultByName("builder"), builder: row.getResultByName("builder"),

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

@ -1337,7 +1337,7 @@ PlacesToolbar.prototype = {
if (icon) { if (icon) {
child.setAttribute("image", icon); child.setAttribute("image", icon);
} }
child.style.visibility = "visible"; child.style.removeProperty("visibility");
} }
} }

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

@ -47,7 +47,7 @@ add_task(async function test_overflow() {
); );
let visibleNodes = []; let visibleNodes = [];
for (let node of children) { for (let node of children) {
if (node.style.visibility == "visible") { if (getComputedStyle(node).visibility == "visible") {
visibleNodes.push(node); visibleNodes.push(node);
} }
} }
@ -111,7 +111,7 @@ add_task(async function test_separator_first() {
"Found the first bookmark" "Found the first bookmark"
); );
Assert.equal( Assert.equal(
children[1].style.visibility, getComputedStyle(children[1]).visibility,
"visible", "visible",
"The first bookmark is visible" "The first bookmark is visible"
); );
@ -163,7 +163,8 @@ async function test_index(desc, index, expected) {
let originalLen = children.length; let originalLen = children.length;
let nodeExisted = children.length > index; let nodeExisted = children.length > index;
let previousNodeIsVisible = let previousNodeIsVisible =
nodeExisted && children[index - 1].style.visibility == "visible"; nodeExisted &&
getComputedStyle(children[index - 1]).visibility == "visible";
let promise = promiseUpdateVisibility( let promise = promiseUpdateVisibility(
expected == "visible" || previousNodeIsVisible expected == "visible" || previousNodeIsVisible
); );
@ -189,7 +190,7 @@ async function test_index(desc, index, expected) {
"Found the added bookmark at the expected position" "Found the added bookmark at the expected position"
); );
Assert.equal( Assert.equal(
children[index].style.visibility, getComputedStyle(children[index]).visibility,
expected, expected,
`The bookmark node should be ${expected}` `The bookmark node should be ${expected}`
); );
@ -214,7 +215,7 @@ async function test_index(desc, index, expected) {
"Found the previous bookmark at the expected position" "Found the previous bookmark at the expected position"
); );
Assert.equal( Assert.equal(
children[index].style.visibility, getComputedStyle(children[index]).visibility,
expected, expected,
`The bookmark node should be ${expected}` `The bookmark node should be ${expected}`
); );
@ -237,7 +238,7 @@ async function test_move_index(desc, fromIndex, toIndex, original, expected) {
let existingIndex = fromIndex < toIndex ? toIndex - 1 : toIndex + 1; let existingIndex = fromIndex < toIndex ? toIndex - 1 : toIndex + 1;
Assert.equal( Assert.equal(
children[fromIndex].style.visibility, getComputedStyle(children[fromIndex]).visibility,
original, original,
`The bookmark node should be ${original}` `The bookmark node should be ${original}`
); );
@ -268,13 +269,13 @@ async function test_move_index(desc, fromIndex, toIndex, original, expected) {
"Found the moved bookmark at the expected position" "Found the moved bookmark at the expected position"
); );
Assert.equal( Assert.equal(
children[toIndex].style.visibility, getComputedStyle(children[toIndex]).visibility,
expected, expected,
`The destination bookmark node should be ${expected}` `The destination bookmark node should be ${expected}`
); );
} }
Assert.equal( Assert.equal(
children[fromIndex].style.visibility, getComputedStyle(children[fromIndex]).visibility,
original, original,
`The origin bookmark node should be ${original}` `The origin bookmark node should be ${original}`
); );
@ -310,13 +311,13 @@ async function test_move_index(desc, fromIndex, toIndex, original, expected) {
); );
if (expected) { if (expected) {
Assert.equal( Assert.equal(
children[toIndex].style.visibility, getComputedStyle(children[toIndex]).visibility,
expected, expected,
`The bookmark node should be ${expected}` `The bookmark node should be ${expected}`
); );
} }
Assert.equal( Assert.equal(
children[fromIndex].style.visibility, getComputedStyle(children[fromIndex]).visibility,
original, original,
`The bookmark node should be ${original}` `The bookmark node should be ${original}`
); );
@ -353,12 +354,12 @@ add_task(async function test_separator_first() {
let children = getPlacesChildren(); let children = getPlacesChildren();
Assert.equal(children.length, 2, "The expected elements are visible"); Assert.equal(children.length, 2, "The expected elements are visible");
Assert.equal( Assert.equal(
children[0].style.visibility, getComputedStyle(children[0]).visibility,
"visible", "visible",
"The first bookmark is visible" "The first bookmark is visible"
); );
Assert.equal( Assert.equal(
children[1].style.visibility, getComputedStyle(children[1]).visibility,
"visible", "visible",
"The second bookmark is visible" "The second bookmark is visible"
); );

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

@ -5,6 +5,10 @@
* Tests for snapshot groups addition, update, and removal. * Tests for snapshot groups addition, update, and removal.
*/ */
const FAVICON_DATAURL1 =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==";
const FAVICON_DATAURL2 =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVBBBBCklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==";
const TEST_URL1 = "https://example.com/"; const TEST_URL1 = "https://example.com/";
const TEST_IMAGE_URL1 = "https://example.com/preview1.png"; const TEST_IMAGE_URL1 = "https://example.com/preview1.png";
const TEST_URL2 = "https://example.com/12345"; const TEST_URL2 = "https://example.com/12345";
@ -21,6 +25,26 @@ async function delete_all_groups() {
} }
} }
async function setIcon(pageUrl, iconUrl, dataUrl) {
PlacesUtils.favicons.replaceFaviconDataFromDataURL(
Services.io.newURI(iconUrl),
dataUrl,
(Date.now() + 8640000) * 1000,
Services.scriptSecurityManager.getSystemPrincipal()
);
await new Promise(resolve => {
PlacesUtils.favicons.setAndFetchFaviconForPage(
Services.io.newURI(pageUrl),
Services.io.newURI(iconUrl),
false,
PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
resolve,
Services.scriptSecurityManager.getSystemPrincipal()
);
});
}
/** /**
* Adds interactions and snapshots for the supplied data. * Adds interactions and snapshots for the supplied data.
* *
@ -83,6 +107,10 @@ add_task(async function test_add_and_query() {
data.map(d => d.url) data.map(d => d.url)
); );
info("add a favicon for both urls");
await setIcon(TEST_URL1, TEST_URL1 + "favicon.ico", FAVICON_DATAURL1);
await setIcon(TEST_URL2, TEST_URL2 + "/favicon.ico", FAVICON_DATAURL2);
let groups = await SnapshotGroups.query({ skipMinimum: true }); let groups = await SnapshotGroups.query({ skipMinimum: true });
Assert.equal(groups.length, 1, "Should return 1 SnapshotGroup"); Assert.equal(groups.length, 1, "Should return 1 SnapshotGroup");
assertSnapshotGroup(groups[0], { assertSnapshotGroup(groups[0], {
@ -93,6 +121,7 @@ add_task(async function test_add_and_query() {
snapshotCount: data.length, snapshotCount: data.length,
lastAccessed: now - 10000, lastAccessed: now - 10000,
imageUrl: getPageThumbURL(TEST_URL1), imageUrl: getPageThumbURL(TEST_URL1),
imagePageUrl: TEST_URL1,
}); });
info("add a featured image for second oldest snapshot"); info("add a featured image for second oldest snapshot");
@ -110,6 +139,8 @@ add_task(async function test_add_and_query() {
snapshotCount: data.length, snapshotCount: data.length,
lastAccessed: now - 10000, lastAccessed: now - 10000,
imageUrl: previewImageURL, imageUrl: previewImageURL,
faviconDataUrl: FAVICON_DATAURL2,
imagePageUrl: TEST_URL2,
}); });
info("add a featured image for the oldest snapshot"); info("add a featured image for the oldest snapshot");
@ -127,6 +158,8 @@ add_task(async function test_add_and_query() {
snapshotCount: data.length, snapshotCount: data.length,
lastAccessed: now - 10000, lastAccessed: now - 10000,
imageUrl: previewImageURL, imageUrl: previewImageURL,
faviconDataUrl: FAVICON_DATAURL1,
imagePageUrl: TEST_URL1,
}); });
}); });
@ -543,6 +576,7 @@ add_task(async function test_snapshot_image_with_hidden() {
// The images were set on TEST_URL1/TEST_URL2 in an earlier test. // The images were set on TEST_URL1/TEST_URL2 in an earlier test.
assertSnapshotGroup(groups[0], { assertSnapshotGroup(groups[0], {
imageUrl: TEST_IMAGE_URL1, imageUrl: TEST_IMAGE_URL1,
imagePageUrl: TEST_URL1,
}); });
await SnapshotGroups.setUrlHidden(groups[0].id, TEST_URL1, true); await SnapshotGroups.setUrlHidden(groups[0].id, TEST_URL1, true);
@ -551,6 +585,7 @@ add_task(async function test_snapshot_image_with_hidden() {
info("Should use the oldest non-hidden image"); info("Should use the oldest non-hidden image");
assertSnapshotGroup(groups[0], { assertSnapshotGroup(groups[0], {
imageUrl: TEST_IMAGE_URL2, imageUrl: TEST_IMAGE_URL2,
imagePageUrl: TEST_URL2,
}); });
}); });

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

@ -2247,7 +2247,7 @@ body.theme_dark .stp_article_list .stp_article_list_publisher {
width: 121px; width: 121px;
} }
body.theme_dark .stp_header .stp_header_logo { body.theme_dark .stp_header .stp_header_logo {
background: url(../img/pocketlogo-dark.svg) bottom center no-repeat; background-image: url(../img/pocketlogo-dark.svg);
} }
.stp_header .stp_button { .stp_header .stp_button {

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

@ -1,16 +1,14 @@
<svg width="91" height="24" viewBox="0 0 91 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<g clip-path="url(#clip0)"> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.0243 10.9259L7.67738 14.0734C7.59482 14.1599 7.49547 14.2286 7.38541 14.2752C7.27536 14.3219 7.15692 14.3456 7.03738 14.3449C6.91026 14.3482 6.78379 14.3258 6.66549 14.2792C6.5472 14.2326 6.43951 14.1626 6.34885 14.0734L3.0518 10.9259C2.87395 10.7405 2.77463 10.4936 2.77463 10.2367C2.77463 9.9798 2.87395 9.73286 3.0518 9.5475C3.42033 9.20259 4.03541 9.15406 4.40525 9.5475L7.03738 12.0826L9.71934 9.5475C10.0643 9.15406 10.6793 9.20259 11.0308 9.5475C11.1972 9.73853 11.2889 9.98333 11.2889 10.2367C11.2889 10.49 11.1972 10.7348 11.0308 10.9259H11.0243ZM12.7213 5.70881H1.35344C1.17883 5.70499 1.00519 5.73573 0.842512 5.79927C0.679831 5.86281 0.531322 5.9579 0.405531 6.07906C0.279741 6.20022 0.179152 6.34506 0.109555 6.50524C0.0399574 6.66543 0.00272483 6.83779 0 7.01242L0 11.2209C0 15.0347 3.14754 18.2098 7.03738 18.2098C8.88984 18.2043 10.6649 17.4664 11.9755 16.1571C13.286 14.8478 14.0255 13.0734 14.0328 11.2209V7.01242C14.0337 6.84032 14.0003 6.66976 13.9346 6.51069C13.8689 6.35161 13.7722 6.2072 13.6501 6.08588C13.5281 5.96455 13.3831 5.86872 13.2236 5.80399C13.0642 5.73925 12.8934 5.7069 12.7213 5.70881Z" fill="#EF4056"/> <svg width="100%" height="100%" viewBox="0 0 91 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<path fill-rule="evenodd" clip-rule="evenodd" d="M90.1613 15.8229C89.9241 15.8402 89.6992 15.9351 89.5213 16.0931C89.1764 16.3882 88.7581 16.6832 88.1679 16.6832C87.1594 16.6832 86.5941 16.0682 86.5941 14.6662V7.08192L89.7194 7.13045C90.1626 7.13045 90.4577 6.86028 90.4577 6.44192C90.4577 5.99865 90.1626 5.72848 89.7194 5.72848L86.5941 5.75209V3.22356C86.5941 2.73176 86.2492 2.38684 85.8308 2.38684C85.722 2.38661 85.6143 2.40828 85.5141 2.45056C85.4138 2.49285 85.3231 2.55488 85.2474 2.63296C85.1716 2.71104 85.1124 2.80357 85.0731 2.90503C85.0339 3.0065 85.0155 3.11483 85.019 3.22356V5.75733L83.6905 5.73373C83.5952 5.72756 83.4997 5.74179 83.4103 5.77546C83.321 5.80913 83.2398 5.86148 83.1723 5.929C83.1048 5.99652 83.0524 6.07766 83.0188 6.16702C82.9851 6.25637 82.9709 6.35188 82.977 6.44717C82.9755 6.54015 82.9931 6.63246 83.0287 6.71835C83.0643 6.80425 83.1172 6.8819 83.1841 6.94648C83.2511 7.01105 83.3305 7.06118 83.4176 7.09373C83.5047 7.12628 83.5976 7.14056 83.6905 7.13569L85.0177 7.08192V14.7147C85.0177 17.1016 86.4695 18.2098 88.143 18.2098C88.5814 18.2216 89.0176 18.1424 89.4239 17.9771C89.8302 17.8119 90.1978 17.5642 90.5036 17.2498C90.6767 17.0531 90.8485 16.8314 90.8485 16.5363C90.8554 16.443 90.8426 16.3493 90.8107 16.2613C90.7789 16.1732 90.7289 16.0929 90.6639 16.0256C90.5989 15.9583 90.5204 15.9054 90.4336 15.8705C90.3468 15.8355 90.2535 15.8193 90.16 15.8229" fill="#ffffff"/> <g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M82.484 11.2459C82.484 8.4918 80.0722 5.58557 76.8446 5.58557C73.3495 5.58557 70.7423 8.47082 70.7423 11.9344C70.7423 15.398 73.3994 18.2098 76.8695 18.2098C78.5915 18.2098 80.2649 17.5698 81.3718 16.4866C81.6184 16.2413 81.8151 15.9698 81.8151 15.6997C81.8213 15.6044 81.807 15.5089 81.7734 15.4195C81.7397 15.3302 81.6874 15.249 81.6198 15.1815C81.5523 15.114 81.4712 15.0616 81.3818 15.028C81.2925 14.9943 81.197 14.9801 81.1017 14.9862C80.8467 14.9906 80.6019 15.0865 80.4118 15.2564C79.3784 16.1666 78.3213 16.6833 76.8708 16.6833C74.6112 16.6833 72.5954 14.9639 72.3856 12.4013H81.1725C82.0158 12.4013 82.484 11.9593 82.484 11.2459ZM72.4315 11.0492C72.7935 8.46557 74.7017 7.11475 76.8485 7.11475C79.1371 7.11475 80.7358 9.03475 80.8341 11.0492H72.4315Z" fill="#ffffff"/> <rect x="2.51" y="8.703" width="9.226" height="6.26" style="fill:white;"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M64.9587 11.3115L69.5397 7.18557C69.958 6.81574 70.0079 6.27541 69.6879 5.93049C69.343 5.56066 68.8262 5.66033 68.4577 6.00393L62.2321 11.8452V0.935082C62.2321 0.368525 61.9856 0 61.4689 0C60.9023 0 60.6321 0.368525 60.6321 0.935082V17.2984C60.6321 17.84 60.9521 18.2098 61.4689 18.2098C61.9357 18.2098 62.2321 17.84 62.2321 17.2984V13.7705L63.8269 12.3279L68.8525 17.9134C69.1725 18.2584 69.7141 18.3816 70.0577 18.0616C70.4511 17.6931 70.3292 17.2 70.0341 16.8564L64.9587 11.3115Z" fill="#ffffff"/> <path d="M12.721,5.709L1.353,5.709C1.179,5.705 1.005,5.736 0.843,5.799C0.68,5.863 0.531,5.958 0.406,6.079C0.28,6.2 0.179,6.345 0.11,6.505C0.04,6.665 0.003,6.838 0,7.012L0,11.221C0,15.035 3.148,18.21 7.037,18.21C8.89,18.204 10.665,17.466 11.976,16.157C13.286,14.848 14.025,13.073 14.033,11.221L14.033,7.012C14.034,6.84 14,6.67 13.935,6.511C13.869,6.352 13.772,6.207 13.65,6.086C13.528,5.965 13.383,5.869 13.224,5.804C13.064,5.739 12.893,5.707 12.721,5.709ZM11.024,10.926L7.677,14.073C7.595,14.16 7.495,14.229 7.385,14.275C7.275,14.322 7.157,14.346 7.037,14.345C6.91,14.348 6.784,14.326 6.665,14.279C6.547,14.233 6.44,14.163 6.349,14.073L3.052,10.926C2.874,10.741 2.775,10.494 2.775,10.237C2.775,9.98 2.874,9.733 3.052,9.548C3.42,9.203 4.035,9.154 4.405,9.548L7.037,12.083L9.719,9.548C10.064,9.154 10.679,9.203 11.031,9.548C11.197,9.739 11.289,9.983 11.289,10.237C11.289,10.49 11.197,10.735 11.031,10.926L11.024,10.926Z" style="fill:rgb(239,64,86);"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M57.7285 14.3213C57.5069 14.3213 57.2616 14.4932 57.1135 14.6899C56.4249 15.6013 54.9482 16.6833 53.2997 16.6833C50.838 16.6833 48.7226 14.7397 48.7226 11.9345C48.7226 8.9325 50.838 7.13578 53.2997 7.13578C55.0951 7.13578 56.08 7.99742 56.9167 9.00594C56.9923 9.10609 57.0886 9.18874 57.1991 9.24827C57.3095 9.30779 57.4315 9.34279 57.5567 9.35086C57.9253 9.35086 58.2951 9.08069 58.2951 8.71086C58.2951 8.4407 58.122 8.16922 57.9751 7.94758C56.9653 6.49578 55.2682 5.65906 53.2997 5.65906C51.6427 5.66808 50.0569 6.33372 48.8899 7.51006C47.7229 8.6864 47.0699 10.2775 47.0741 11.9345C47.0741 15.3548 49.8794 18.2099 53.2997 18.2099C55.4151 18.2099 57.2341 16.9784 58.1954 15.6997C58.353 15.5215 58.4483 15.2969 58.4669 15.0597C58.4708 14.9617 58.4543 14.864 58.4186 14.7726C58.3829 14.6813 58.3286 14.5983 58.2593 14.529C58.1899 14.4596 58.1069 14.4054 58.0156 14.3697C57.9243 14.3339 57.8265 14.3175 57.7285 14.3213Z" fill="#ffffff"/> <path d="M90.161,15.823C89.924,15.84 89.699,15.935 89.521,16.093C89.176,16.388 88.758,16.683 88.168,16.683C87.159,16.683 86.594,16.068 86.594,14.666L86.594,7.082L89.719,7.13C90.163,7.13 90.458,6.86 90.458,6.442C90.458,5.999 90.163,5.728 89.719,5.728L86.594,5.752L86.594,3.224C86.594,2.732 86.249,2.387 85.831,2.387C85.722,2.387 85.614,2.408 85.514,2.451C85.414,2.493 85.323,2.555 85.247,2.633C85.172,2.711 85.112,2.804 85.073,2.905C85.034,3.007 85.016,3.115 85.019,3.224L85.019,5.757L83.691,5.734C83.595,5.728 83.5,5.742 83.41,5.775C83.321,5.809 83.24,5.861 83.172,5.929C83.105,5.997 83.052,6.078 83.019,6.167C82.985,6.256 82.971,6.352 82.977,6.447C82.976,6.54 82.993,6.632 83.029,6.718C83.064,6.804 83.117,6.882 83.184,6.946C83.251,7.011 83.331,7.061 83.418,7.094C83.505,7.126 83.598,7.141 83.691,7.136L85.018,7.082L85.018,14.715C85.018,17.102 86.47,18.21 88.143,18.21C88.581,18.222 89.018,18.142 89.424,17.977C89.83,17.812 90.198,17.564 90.504,17.25C90.677,17.053 90.849,16.831 90.849,16.536C90.855,16.443 90.843,16.349 90.811,16.261C90.779,16.173 90.729,16.093 90.664,16.026C90.599,15.958 90.52,15.905 90.434,15.871C90.347,15.836 90.254,15.819 90.16,15.823" style="fill:white;"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M39.3718 16.6833C36.8367 16.6833 34.7213 14.543 34.7213 11.9344C34.7213 9.30099 36.8367 7.11083 39.3718 7.11083C41.9554 7.11083 44.0223 9.30099 44.0223 11.9344C44.0223 14.543 41.9554 16.6833 39.3718 16.6833ZM39.4203 5.58558C38.5873 5.58401 37.7622 5.74734 36.9927 6.06615C36.2231 6.38496 35.5242 6.85295 34.9363 7.44314C34.3485 8.03332 33.8832 8.73403 33.5674 9.50487C33.2517 10.2757 33.0916 11.1014 33.0964 11.9344C33.0964 15.4046 35.8505 18.2098 39.4203 18.2098C42.7672 18.2098 45.6708 15.4046 45.6708 11.9344C45.6708 8.46427 42.7423 5.58558 39.4203 5.58558Z" fill="#ffffff"/> <path d="M82.484,11.246C82.484,8.492 80.072,5.586 76.845,5.586C73.35,5.586 70.742,8.471 70.742,11.934C70.742,15.398 73.399,18.21 76.87,18.21C78.592,18.21 80.265,17.57 81.372,16.487C81.618,16.241 81.815,15.97 81.815,15.7C81.821,15.604 81.807,15.509 81.773,15.419C81.74,15.33 81.687,15.249 81.62,15.182C81.552,15.114 81.471,15.062 81.382,15.028C81.293,14.994 81.197,14.98 81.102,14.986C80.847,14.991 80.602,15.086 80.412,15.256C79.378,16.167 78.321,16.683 76.871,16.683C74.611,16.683 72.595,14.964 72.386,12.401L81.173,12.401C82.016,12.401 82.484,11.959 82.484,11.246ZM72.432,11.049C72.794,8.466 74.702,7.115 76.849,7.115C79.137,7.115 80.736,9.035 80.834,11.049L72.432,11.049Z" style="fill:white;"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.419 16.6832C22.8852 16.6832 20.7685 14.5429 20.7685 11.9344C20.7685 9.30095 22.8852 7.11079 25.419 7.11079C28.0026 7.11079 30.0695 9.30095 30.0695 11.9344C30.0695 14.5429 28.0026 16.6832 25.419 16.6832ZM25.4426 5.58554C23.5226 5.58554 21.8255 6.66882 20.619 8.12063L20.5704 6.39735C20.5455 5.78226 20.2504 5.48718 19.8072 5.48718C19.3403 5.48718 19.0203 5.85702 19.0203 6.37374V23.1606C19.0145 23.2699 19.0313 23.3792 19.0697 23.4817C19.1081 23.5842 19.1673 23.6777 19.2435 23.7562C19.3197 23.8348 19.4113 23.8967 19.5126 23.9382C19.6139 23.9797 19.7227 23.9998 19.8321 23.9973C20.3239 23.9973 20.619 23.6275 20.619 23.1357V15.798C21.8255 17.2249 23.5226 18.2098 25.4426 18.2098C26.2662 18.2123 27.0822 18.0514 27.8434 17.7366C28.6045 17.4218 29.2958 16.9593 29.8771 16.3758C30.4584 15.7923 30.9183 15.0993 31.2303 14.337C31.5422 13.5746 31.6999 12.7581 31.6944 11.9344C31.6944 8.46423 28.9403 5.58554 25.4439 5.58554" fill="#ffffff"/> <path d="M64.959,11.312L69.54,7.186C69.958,6.816 70.008,6.275 69.688,5.93C69.343,5.561 68.826,5.66 68.458,6.004L62.232,11.845L62.232,0.935C62.232,0.369 61.986,0 61.469,0C60.902,0 60.632,0.369 60.632,0.935L60.632,17.298C60.632,17.84 60.952,18.21 61.469,18.21C61.936,18.21 62.232,17.84 62.232,17.298L62.232,13.771L63.827,12.328L68.853,17.913C69.173,18.258 69.714,18.382 70.058,18.062C70.451,17.693 70.329,17.2 70.034,16.856L64.959,11.312Z" style="fill:white;"/>
</g> <path d="M57.728,14.321C57.507,14.321 57.262,14.493 57.114,14.69C56.425,15.601 54.948,16.683 53.3,16.683C50.838,16.683 48.723,14.74 48.723,11.935C48.723,8.932 50.838,7.136 53.3,7.136C55.095,7.136 56.08,7.997 56.917,9.006C56.992,9.106 57.089,9.189 57.199,9.248C57.31,9.308 57.432,9.343 57.557,9.351C57.925,9.351 58.295,9.081 58.295,8.711C58.295,8.441 58.122,8.169 57.975,7.948C56.965,6.496 55.268,5.659 53.3,5.659C51.643,5.668 50.057,6.334 48.89,7.51C47.723,8.686 47.07,10.278 47.074,11.935C47.074,15.355 49.879,18.21 53.3,18.21C55.415,18.21 57.234,16.978 58.195,15.7C58.353,15.522 58.448,15.297 58.467,15.06C58.471,14.962 58.454,14.864 58.419,14.773C58.383,14.681 58.329,14.598 58.259,14.529C58.19,14.46 58.107,14.405 58.016,14.37C57.924,14.334 57.827,14.318 57.728,14.321Z" style="fill:white;"/>
<defs> <path d="M39.372,16.683C36.837,16.683 34.721,14.543 34.721,11.934C34.721,9.301 36.837,7.111 39.372,7.111C41.955,7.111 44.022,9.301 44.022,11.934C44.022,14.543 41.955,16.683 39.372,16.683ZM39.42,5.586C38.587,5.584 37.762,5.747 36.993,6.066C36.223,6.385 35.524,6.853 34.936,7.443C34.349,8.033 33.883,8.734 33.567,9.505C33.252,10.276 33.092,11.101 33.096,11.934C33.096,15.405 35.85,18.21 39.42,18.21C42.767,18.21 45.671,15.405 45.671,11.934C45.671,8.464 42.742,5.586 39.42,5.586Z" style="fill:white;"/>
<clipPath id="clip0"> <path d="M25.419,16.683C22.885,16.683 20.769,14.543 20.769,11.934C20.769,9.301 22.885,7.111 25.419,7.111C28.003,7.111 30.07,9.301 30.07,11.934C30.07,14.543 28.003,16.683 25.419,16.683ZM25.443,5.586C23.523,5.586 21.826,6.669 20.619,8.121L20.57,6.397C20.546,5.782 20.25,5.487 19.807,5.487C19.34,5.487 19.02,5.857 19.02,6.374L19.02,23.161C19.015,23.27 19.031,23.379 19.07,23.482C19.108,23.584 19.167,23.678 19.244,23.756C19.32,23.835 19.411,23.897 19.513,23.938C19.614,23.98 19.723,24 19.832,23.997C20.324,23.997 20.619,23.628 20.619,23.136L20.619,15.798C21.826,17.225 23.523,18.21 25.443,18.21C26.266,18.212 27.082,18.051 27.843,17.737C28.605,17.422 29.296,16.959 29.877,16.376C30.458,15.792 30.918,15.099 31.23,14.337C31.542,13.575 31.7,12.758 31.694,11.934C31.694,8.464 28.94,5.586 25.444,5.586" style="fill:white;"/>
<rect width="90.8852" height="24" fill="white"/> </g>
</clipPath>
</defs>
</svg> </svg>

До

Ширина:  |  Высота:  |  Размер: 6.7 KiB

После

Ширина:  |  Высота:  |  Размер: 5.9 KiB

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

@ -12,7 +12,7 @@
width: 121px; width: 121px;
@include theme_dark { @include theme_dark {
background: url(../img/pocketlogo-dark.svg) bottom center no-repeat; background-image: url(../img/pocketlogo-dark.svg);
} }
} }

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

@ -351,6 +351,7 @@ var gPermissionManager = {
}, },
_createPermissionListItem(permission) { _createPermissionListItem(permission) {
let disabledByPolicy = this._permissionDisabledByPolicy(permission);
let richlistitem = document.createXULElement("richlistitem"); let richlistitem = document.createXULElement("richlistitem");
richlistitem.setAttribute("origin", permission.origin); richlistitem.setAttribute("origin", permission.origin);
let row = document.createXULElement("hbox"); let row = document.createXULElement("hbox");
@ -358,6 +359,8 @@ var gPermissionManager = {
let hbox = document.createXULElement("hbox"); let hbox = document.createXULElement("hbox");
let website = document.createXULElement("label"); let website = document.createXULElement("label");
website.setAttribute("disabled", disabledByPolicy);
website.setAttribute("class", "website-name-value");
website.setAttribute("value", permission.origin); website.setAttribute("value", permission.origin);
hbox.setAttribute("width", "0"); hbox.setAttribute("width", "0");
hbox.setAttribute("class", "website-name"); hbox.setAttribute("class", "website-name");
@ -368,6 +371,7 @@ var gPermissionManager = {
if (!this._hideStatusColumn) { if (!this._hideStatusColumn) {
hbox = document.createXULElement("hbox"); hbox = document.createXULElement("hbox");
let capability = document.createXULElement("label"); let capability = document.createXULElement("label");
capability.setAttribute("disabled", disabledByPolicy);
capability.setAttribute("class", "website-capability-value"); capability.setAttribute("class", "website-capability-value");
document.l10n.setAttributes( document.l10n.setAttributes(
capability, capability,
@ -439,15 +443,31 @@ var gPermissionManager = {
} }
let hasSelection = this._list.selectedIndex >= 0; let hasSelection = this._list.selectedIndex >= 0;
let hasRows = this._list.itemCount > 0;
this._removeButton.disabled = !hasSelection; let disabledByPolicy = false;
this._removeAllButton.disabled = !hasRows; if (Services.policies.status === Services.policies.ACTIVE && hasSelection) {
let origin = this._list.selectedItem.getAttribute("origin");
disabledByPolicy = this._permissionDisabledByPolicy(
this._permissions.get(origin)
);
}
this._removeButton.disabled = !hasSelection || disabledByPolicy;
let disabledItems = this._list.querySelectorAll(
"label.website-name-value[disabled='true']"
);
this._removeAllButton.disabled =
this._list.itemCount == disabledItems.length;
}, },
onPermissionDelete() { onPermissionDelete() {
let richlistitem = this._list.selectedItem; let richlistitem = this._list.selectedItem;
let origin = richlistitem.getAttribute("origin"); let origin = richlistitem.getAttribute("origin");
let permission = this._permissions.get(origin); let permission = this._permissions.get(origin);
if (this._permissionDisabledByPolicy(permission)) {
return;
}
this._removePermission(permission); this._removePermission(permission);
@ -456,6 +476,9 @@ var gPermissionManager = {
onAllPermissionsDelete() { onAllPermissionsDelete() {
for (let permission of this._permissions.values()) { for (let permission of this._permissions.values()) {
if (this._permissionDisabledByPolicy(permission)) {
continue;
}
this._removePermission(permission); this._removePermission(permission);
} }
@ -518,6 +541,17 @@ var gPermissionManager = {
this._setRemoveButtonState(); this._setRemoveButtonState();
}, },
_permissionDisabledByPolicy(permission) {
let permissionObject = Services.perms.getPermissionObject(
permission.principal,
this._type,
false
);
return (
permissionObject?.expireType == Ci.nsIPermissionManager.EXPIRE_POLICY
);
},
_sortPermissions(list, frag, column) { _sortPermissions(list, frag, column) {
let sortDirection; let sortDirection;

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

@ -121,6 +121,7 @@ skip-if =
[browser_security-2.js] [browser_security-2.js]
[browser_spotlight.js] [browser_spotlight.js]
[browser_site_login_exceptions.js] [browser_site_login_exceptions.js]
[browser_site_login_exceptions_policy.js]
[browser_permissions_dialog.js] [browser_permissions_dialog.js]
[browser_permissions_dialog_default_perm.js] [browser_permissions_dialog_default_perm.js]
[browser_statePartitioning_PBM_strings.js] [browser_statePartitioning_PBM_strings.js]

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

@ -6,6 +6,11 @@ ChromeUtils.defineModuleGetter(
"Preferences", "Preferences",
"resource://gre/modules/Preferences.jsm" "resource://gre/modules/Preferences.jsm"
); );
ChromeUtils.defineModuleGetter(
this,
"BrowserGlue",
"resource:///modules/BrowserGlue.jsm"
);
const { ExperimentFakes } = ChromeUtils.import( const { ExperimentFakes } = ChromeUtils.import(
"resource://testing-common/NimbusTestUtils.jsm" "resource://testing-common/NimbusTestUtils.jsm"
@ -70,7 +75,13 @@ add_setup(async function() {
registerCleanupFunction(function() { registerCleanupFunction(function() {
defaultPrefs.setIntPref(COOKIE_BEHAVIOR_PREF, previousDefaultCB); defaultPrefs.setIntPref(COOKIE_BEHAVIOR_PREF, previousDefaultCB);
BrowserGlue._defaultCookieBehaviorAtStartup = previousDefaultCB;
}); });
// The BrowserGlue code which computes this flag runs before we can set the
// default cookie behavior for this test. Thus we need to overwrite it in
// order for the opt-out to work correctly.
BrowserGlue._defaultCookieBehaviorAtStartup = BEHAVIOR_REJECT_TRACKER;
defaultPrefs.setIntPref( defaultPrefs.setIntPref(
COOKIE_BEHAVIOR_PREF, COOKIE_BEHAVIOR_PREF,
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER

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

@ -0,0 +1,65 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { EnterprisePolicyTesting } = ChromeUtils.import(
"resource://testing-common/EnterprisePolicyTesting.jsm"
);
const PERMISSIONS_URL =
"chrome://browser/content/preferences/dialogs/permissions.xhtml";
var exceptionsDialog;
add_task(async function openLoginExceptionsSubDialog() {
// ensure rememberSignons is off for this test;
ok(
!Services.prefs.getBoolPref("signon.rememberSignons"),
"Check initial value of signon.rememberSignons pref"
);
// Undo the save password change.
registerCleanupFunction(async function() {
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], function() {
let doc = content.document;
let savePasswordCheckBox = doc.getElementById("savePasswords");
if (savePasswordCheckBox.checked) {
savePasswordCheckBox.click();
}
});
gBrowser.removeCurrentTab();
await EnterprisePolicyTesting.setupPolicyEngineWithJson("");
});
await EnterprisePolicyTesting.setupPolicyEngineWithJson({
policies: {
PasswordManagerExceptions: ["https://pwexception.example.com"],
},
});
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
let dialogOpened = promiseLoadSubDialog(PERMISSIONS_URL);
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], function() {
let doc = content.document;
let savePasswordCheckBox = doc.getElementById("savePasswords");
savePasswordCheckBox.click();
let loginExceptionsButton = doc.getElementById("passwordExceptions");
loginExceptionsButton.click();
});
exceptionsDialog = await dialogOpened;
let doc = exceptionsDialog.document;
let richlistbox = doc.getElementById("permissionsBox");
Assert.equal(richlistbox.itemCount, 1, `Row count should initially be 1`);
richlistbox.focus();
richlistbox.selectedIndex = 0;
Assert.ok(doc.getElementById("removePermission").disabled);
});

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

До

Ширина:  |  Высота:  |  Размер: 23 KiB

После

Ширина:  |  Высота:  |  Размер: 22 KiB

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

@ -1042,6 +1042,13 @@ static nsresult GetMatchingShortcut(int aCSIDL, const nsAutoString& aAUMID,
} }
static nsresult PinCurrentAppToTaskbarWin7(bool aCheckOnly, static nsresult PinCurrentAppToTaskbarWin7(bool aCheckOnly,
nsAutoString aShortcutPath) { nsAutoString aShortcutPath) {
// Currently disabled due to
// https://bugzilla.mozilla.org/show_bug.cgi?id=1763573 At the time of
// writing, the only callers eat any errors from here so it's safe to return
// one. This is a short term workaround to confirm that this code is indeed
// causing the bug above. If it is, we'll rework this code to avoid it.
return NS_ERROR_ABORT;
// This is a less generalized version of the code from the NSIS // This is a less generalized version of the code from the NSIS
// Invoke Shell Verb plugin. // Invoke Shell Verb plugin.
// https://nsis.sourceforge.io/Invoke_Shell_Verb_plugin // https://nsis.sourceforge.io/Invoke_Shell_Verb_plugin

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

@ -36,6 +36,12 @@ let AVAILABLE_PIP_OVERRIDES;
}, },
}, },
airmozilla: {
"https://*.mozilla.hosted.panopto.com/*": {
videoWrapperScriptPath: "video-wrappers/airmozilla.js",
},
},
funimation: { funimation: {
"https://*.funimation.com/*": { "https://*.funimation.com/*": {
videoWrapperScriptPath: "video-wrappers/funimation.js", videoWrapperScriptPath: "video-wrappers/funimation.js",

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

@ -28,6 +28,7 @@ FINAL_TARGET_FILES.features["pictureinpicture@mozilla.org"]["lib"] += [
] ]
FINAL_TARGET_FILES.features["pictureinpicture@mozilla.org"]["video-wrappers"] += [ FINAL_TARGET_FILES.features["pictureinpicture@mozilla.org"]["video-wrappers"] += [
"video-wrappers/airmozilla.js",
"video-wrappers/funimation.js", "video-wrappers/funimation.js",
"video-wrappers/mock-wrapper.js", "video-wrappers/mock-wrapper.js",
"video-wrappers/netflix.js", "video-wrappers/netflix.js",

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

@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
class PictureInPictureVideoWrapper {
setCaptionContainerObserver(video, updateCaptionsFunction) {
let container = document.querySelector("#absoluteControls");
if (container) {
updateCaptionsFunction("");
const callback = function(mutationsList, observer) {
let text = container?.querySelector("#overlayCaption").innerText;
if (!text) {
updateCaptionsFunction("");
return;
}
updateCaptionsFunction(text);
};
// immediately invoke the callback function to add subtitles to the PiP window
callback([1], null);
let captionsObserver = new MutationObserver(callback);
captionsObserver.observe(container, {
attributes: false,
childList: true,
subtree: true,
});
}
}
}
this.PictureInPictureVideoWrapper = PictureInPictureVideoWrapper;

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

@ -608,21 +608,6 @@ const AVAILABLE_INJECTIONS = [
], ],
}, },
}, },
{
id: "bug1761930",
platform: "all",
domain: "instagram.com",
bug: "1761930",
contentScripts: {
matches: ["*://www.instagram.com/*"],
js: [
{
file:
"injections/js/bug1761930-instagram.com-readablestream-pipeto.js",
},
],
},
},
]; ];
module.exports = AVAILABLE_INJECTIONS; module.exports = AVAILABLE_INJECTIONS;

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

@ -714,8 +714,10 @@ const AVAILABLE_UA_OVERRIDES = [
bug: "1743429", bug: "1743429",
config: { config: {
matches: [ matches: [
"*://*.edf.com/*", // Bug 1764786
"*://*.wordpress.org/*", // Bug 1743431 "*://*.wordpress.org/*", // Bug 1743431
"*://bethesda.net/*", // #94607 "*://bethesda.net/*", // #94607
"*://cdn-vzn.yottaa.net/*", // Bug 1764795
"*://citoyens.telerecours.fr/*", // #101066 "*://citoyens.telerecours.fr/*", // #101066
"*://genehmigung.ahs-vwa.at/*", // #100063 "*://genehmigung.ahs-vwa.at/*", // #100063
"*://moje.pzu.pl/*", // #99772 "*://moje.pzu.pl/*", // #99772
@ -723,18 +725,95 @@ const AVAILABLE_UA_OVERRIDES = [
"*://online.citi.com/*", // #101268 "*://online.citi.com/*", // #101268
"*://simperium.com/*", // #98934 "*://simperium.com/*", // #98934
"*://wifi.sncf/*", // #100194 "*://wifi.sncf/*", // #100194
"*://www.brownells.com/*", // #90806 "*://www.accringtonobserver.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.bathchronicle.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.bedfordshirelive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.belfastlive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.birminghamlive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.birminghammail.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.birminghampost.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.bristol.live/*", // Bug 1762928 (Reach Plc)
"*://www.bristolpost.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.buckinghamshirelive.com/*", // Bug 1762928 (Reach Plc)
"*://www.burtonmail.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.business-live.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.cambridge-news.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.cambridgeshirelive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.cheshire-live.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.chesterchronicle.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.chroniclelive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.corkbeo.ie/*", // Bug 1762928 (Reach Plc)
"*://www.cornwalllive.com/*", // Bug 1762928 (Reach Plc)
"*://www.coventrytelegraph.net/*", // Bug 1762928 (Reach Plc)
"*://www.crewechronicle.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.croydonadvertiser.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.dailypost.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.dailyrecord.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.dailystar.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.derbytelegraph.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.devonlive.com/*", // Bug 1762928 (Reach Plc)
"*://www.discoveryplus.in/*", // #100389 "*://www.discoveryplus.in/*", // #100389
"*://www.dublinlive.ie/*", // Bug 1762928 (Reach Plc)
"*://www.edinburghlive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.essexlive.news/*", // Bug 1762928 (Reach Plc)
"*://www.eurosportplayer.com/*", // #91087 "*://www.eurosportplayer.com/*", // #91087
"*://www.examiner.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.examinerlive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.express.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.football.london/*", // Bug 1762928 (Reach Plc)
"*://www.footballscotland.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.gazettelive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.getbucks.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.gethampshire.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.getreading.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.getsurrey.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.getwestlondon.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.gismeteo.ru/*", // #101326 "*://www.gismeteo.ru/*", // #101326
"*://www.glasgowlive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.gloucestershirelive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.grimsbytelegraph.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.hampshirelive.news/*", // Bug 1762928 (Reach Plc)
"*://www.hannaandersson.com/*", // #95003 "*://www.hannaandersson.com/*", // #95003
"*://www.hertfordshiremercury.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.hinckleytimes.net/*", // Bug 1762928 (Reach Plc)
"*://www.hulldailymail.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.imb.com.au/*", // Bug 1762209 "*://www.imb.com.au/*", // Bug 1762209
"*://www.insider.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.irishmirror.ie/*", // Bug 1762928 (Reach Plc)
"*://www.kentlive.news/*", // Bug 1762928 (Reach Plc)
"*://www.lancs.live/*", // Bug 1762928 (Reach Plc)
"*://www.leeds-live.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.leicestermercury.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.lincolnshirelive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.liverpool.com/*", // Bug 1762928 (Reach Plc)
"*://www.liverpoolecho.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.loughboroughecho.net/*", // Bug 1762928 (Reach Plc)
"*://www.macclesfield-express.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.macclesfield-live.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.manchestereveningnews.co.uk/*", // #100923 "*://www.manchestereveningnews.co.uk/*", // #100923
"*://www.mirror.co.uk/*", // #100053 "*://www.mirror.co.uk/*", // #100053
"*://www.mylondon.news/*", // Bug 1762928 (Reach Plc)
"*://www.northantslive.news/*", // Bug 1762928 (Reach Plc)
"*://www.nottinghampost.com/*", // Bug 1762928 (Reach Plc)
"*://www.ok.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.petalmail.com/*", // #99339 "*://www.petalmail.com/*", // #99339
"*://www.plymouthherald.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.rossendalefreepress.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.rsvplive.ie/*", // Bug 1762928 (Reach Plc)
"*://www.scotlandnow.dailyrecord.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.screwfix.com/*", // #96959 "*://www.screwfix.com/*", // #96959
"*://www.scunthorpetelegraph.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.services.gov.on.ca/*", // #100926 "*://www.services.gov.on.ca/*", // #100926
"*://www.smsv.com.ar/*", // #90666 "*://www.smsv.com.ar/*", // #90666
"*://www.somersetlive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.southportvisiter.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.staffordshire-live.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.stokesentinel.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.sussexlive.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.tm-awx.com/*", // Bug 1762928 (Reach Plc)
"*://www.twitch.tv/*", // Bug 1764591
"*://www.walesonline.co.uk/*", // Bug 1762928 (Reach Plc)
"*://www.wharf.co.uk/*", // Bug 1762928 (Reach Plc)
], ],
uaTransformer: originalUA => { uaTransformer: originalUA => {
return UAHelpers.capVersionTo99(originalUA); return UAHelpers.capVersionTo99(originalUA);

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

@ -1,18 +0,0 @@
"use strict";
/**
* Bug 1761930 - Undefine ReadableStream.prototype.pipeTo for Instagram
*
* Instagram's ReadableStream feature detection only checks if .pipeTo exists,
* and if it does, it assumes .pipeThrough exists as well. Unfortuantely, that
* assumption is not yet true in Firefox, and thus, some video playbacks fail.
*/
console.info(
"ReadableStream.prototype.pipeTo has been overwritten for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1761343 for details."
);
Object.defineProperty(ReadableStream.prototype.wrappedJSObject, "pipeTo", {
get: undefined,
set: undefined,
});

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

@ -2,7 +2,7 @@
"manifest_version": 2, "manifest_version": 2,
"name": "Web Compatibility Interventions", "name": "Web Compatibility Interventions",
"description": "Urgent post-release fixes for web compatibility.", "description": "Urgent post-release fixes for web compatibility.",
"version": "100.1.0", "version": "100.2.0",
"applications": { "applications": {
"gecko": { "gecko": {
"id": "webcompat@mozilla.org", "id": "webcompat@mozilla.org",

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

@ -84,7 +84,6 @@ FINAL_TARGET_FILES.features["webcompat@mozilla.org"]["injections"]["js"] += [
"injections/js/bug1731825-office365-email-handling-prompt-autohide.js", "injections/js/bug1731825-office365-email-handling-prompt-autohide.js",
"injections/js/bug1739489-draftjs-beforeinput.js", "injections/js/bug1739489-draftjs-beforeinput.js",
"injections/js/bug1756692-effectiveType-shim.js", "injections/js/bug1756692-effectiveType-shim.js",
"injections/js/bug1761930-instagram.com-readablestream-pipeto.js",
] ]
FINAL_TARGET_FILES.features["webcompat@mozilla.org"]["shims"] += [ FINAL_TARGET_FILES.features["webcompat@mozilla.org"]["shims"] += [

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

@ -158,6 +158,8 @@ policy-OverridePostUpdatePage = Override the post-update “Whats New” page
policy-PasswordManagerEnabled = Enable saving passwords to the password manager. policy-PasswordManagerEnabled = Enable saving passwords to the password manager.
policy-PasswordManagerExceptions = Prevent { -brand-short-name } from saving passwords for specific sites.
# PDF.js and PDF should not be translated # PDF.js and PDF should not be translated
policy-PDFjs = Disable or configure PDF.js, the built-in PDF viewer in { -brand-short-name }. policy-PDFjs = Disable or configure PDF.js, the built-in PDF viewer in { -brand-short-name }.

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

@ -2009,9 +2009,11 @@ panelview:not([mainview]) #PanelUI-whatsNew-title {
} }
/* Override themes for the Pocket panel, because the Pocket /* Override themes for the Pocket panel, because the Pocket
panel doesn't currently support multiple themes. */ panel currently only supports dark and light themes. */
#customizationui-widget-panel[viewId="PanelUI-savetopocket"] { @media not (prefers-color-scheme: dark){
--arrowpanel-background: #fbfbfb; #customizationui-widget-panel[viewId="PanelUI-savetopocket"] {
--arrowpanel-background: #fbfbfb;
}
} }
#PanelUI-profiler-content { #PanelUI-profiler-content {

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

@ -10,7 +10,6 @@ from contextlib import contextmanager
import gzip import gzip
import io import io
import logging import logging
from mozbuild.base import MozbuildObject
from mozbuild.generated_sources import ( from mozbuild.generated_sources import (
get_filename_with_digest, get_filename_with_digest,
get_s3_region_and_bucket, get_s3_region_and_bucket,
@ -161,10 +160,6 @@ def main(argv):
args = parser.parse_args(argv) args = parser.parse_args(argv)
region, bucket = get_s3_region_and_bucket() region, bucket = get_s3_region_and_bucket()
config = MozbuildObject.from_environment()
config.activate_virtualenv()
config.virtualenv_manager.install_pip_package("boto3==1.4.4")
with timed() as elapsed: with timed() as elapsed:
do_work(region=region, bucket=bucket, artifact=args.artifact) do_work(region=region, bucket=bucket, artifact=args.artifact)
log.info("Finished in {:.03f}s".format(elapsed())) log.info("Finished in {:.03f}s".format(elapsed()))

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

@ -45,6 +45,10 @@ tags = webextensions
tags = webextensions tags = webextensions
[browser_aboutdebugging_addons_debug_storage.js] [browser_aboutdebugging_addons_debug_storage.js]
tags = webextensions tags = webextensions
[browser_aboutdebugging_addons_eventpage_actions_and_status.js]
tags = webextensions
[browser_aboutdebugging_addons_eventpage_terminate_on_idle.js]
tags = webextensions
[browser_aboutdebugging_addons_manifest_url.js] [browser_aboutdebugging_addons_manifest_url.js]
skip-if = (os == 'linux' && bits == 32) || (os == 'mac' && debug) # ADB start() fails on linux 32, see Bug 1499638, macosx1014 debug due to 1514751 skip-if = (os == 'linux' && bits == 32) || (os == 'mac' && debug) # ADB start() fails on linux 32, see Bug 1499638, macosx1014 debug due to 1514751
[browser_aboutdebugging_addons_remote_runtime.js] [browser_aboutdebugging_addons_remote_runtime.js]
@ -55,7 +59,6 @@ skip-if = (os == 'win') # On windows the AddonManager locks the XPI file loaded
[browser_aboutdebugging_addons_temporary_install_path.js] [browser_aboutdebugging_addons_temporary_install_path.js]
[browser_aboutdebugging_addons_temporary_reload_error.js] [browser_aboutdebugging_addons_temporary_reload_error.js]
skip-if = (os == 'win') # On windows the AddonManager locks the XPI file loaded as a temporary extension and we can not test the reload of the extension. skip-if = (os == 'win') # On windows the AddonManager locks the XPI file loaded as a temporary extension and we can not test the reload of the extension.
[browser_aboutdebugging_addons_terminate_background_script.js]
[browser_aboutdebugging_addons_warnings.js] [browser_aboutdebugging_addons_warnings.js]
[browser_aboutdebugging_connect_networklocations.js] [browser_aboutdebugging_connect_networklocations.js]
[browser_aboutdebugging_connect_toggle_usb_devices.js] [browser_aboutdebugging_connect_toggle_usb_devices.js]

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

@ -252,11 +252,3 @@ add_task(async function testWebExtensionsToolboxWebConsole() {
await removeTemporaryExtension(ADDON_NAME, document); await removeTemporaryExtension(ADDON_NAME, document);
await removeTab(tab); await removeTab(tab);
}); });
function findMessages(hud, text, selector = ".message") {
const messages = hud.ui.outputNode.querySelectorAll(selector);
const elements = Array.prototype.filter.call(messages, el =>
el.textContent.includes(text)
);
return elements;
}

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

@ -2,50 +2,18 @@
http://creativecommons.org/publicdomain/zero/1.0/ */ http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict"; "use strict";
const { Management } = ChromeUtils.import(
"resource://gre/modules/Extension.jsm"
);
/* import-globals-from helper-addons.js */ /* import-globals-from helper-addons.js */
Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "helper-addons.js", this); Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "helper-addons.js", this);
function promiseBackgroundContextEvent(extensionId, eventName) { add_setup(async function() {
return new Promise(resolve => {
Management.on(eventName, function listener(_evtName, context) {
if (context.extension.id === extensionId) {
Management.off(eventName, listener);
resolve();
}
});
});
}
function promiseBackgroundContextLoaded(extensionId) {
return promiseBackgroundContextEvent(extensionId, "proxy-context-load");
}
function promiseBackgroundContextUnloaded(extensionId) {
return promiseBackgroundContextEvent(extensionId, "proxy-context-unload");
}
async function assertBackgroundStatus(extName, { document, expectedStatus }) {
const target = findDebugTargetByText(extName, document);
const getBackgroundStatusElement = () =>
target.querySelector(".extension-backgroundscript__status");
await waitFor(
() =>
getBackgroundStatusElement()?.classList.contains(
`extension-backgroundscript__status--${expectedStatus}`
),
`Wait ${extName} Background script status "${expectedStatus}" to be rendered`
);
}
// Test that the reload button updates the addon list with the correct metadata.
add_task(async function() {
await SpecialPowers.pushPrefEnv({ await SpecialPowers.pushPrefEnv({
set: [["extensions.eventPages.enabled", true]], set: [["extensions.eventPages.enabled", true]],
}); });
});
// Test that the terminate button is shutting down the background script as expected
// and the background script status is updated occordingly.
add_task(async function test_eventpage_terminate_and_status_updates() {
const { document, tab, window } = await openAboutDebugging(); const { document, tab, window } = await openAboutDebugging();
await selectThisFirefoxPage(document, window.AboutDebugging.store); await selectThisFirefoxPage(document, window.AboutDebugging.store);
@ -61,10 +29,7 @@ add_task(async function() {
EXTENSION_ID EXTENSION_ID
); );
let waitForBGStatusUpdate = waitForDispatch( let waitForBGStatusUpdate = promiseBackgroundStatusUpdate(window);
window.AboutDebugging.store,
"EXTENSION_BGSCRIPT_STATUS_UPDATED"
);
// Install the extension using an event page (non persistent background page). // Install the extension using an event page (non persistent background page).
await installTemporaryExtensionFromXPI( await installTemporaryExtensionFromXPI(
@ -160,17 +125,13 @@ add_task(async function() {
window.AboutDebugging.store, window.AboutDebugging.store,
"TERMINATE_EXTENSION_BGSCRIPT_SUCCESS" "TERMINATE_EXTENSION_BGSCRIPT_SUCCESS"
); );
waitForBGStatusUpdate = waitForDispatch( waitForBGStatusUpdate = promiseBackgroundStatusUpdate(window);
window.AboutDebugging.store,
"EXTENSION_BGSCRIPT_STATUS_UPDATED"
);
terminateButton.click(); terminateButton.click();
await waitForTerminateSuccess; await waitForTerminateSuccess;
info("Wait for the extension background script to be unloaded"); info("Wait for the extension background script to be unloaded");
await promiseBackgroundUnloaded; await promiseBackgroundUnloaded;
await waitForBGStatusUpdate;
await assertBackgroundStatus(EXTENSION_NAME, { await assertBackgroundStatus(EXTENSION_NAME, {
document, document,
expectedStatus: "stopped", expectedStatus: "stopped",

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

@ -0,0 +1,203 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/* import-globals-from helper-addons.js */
Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "helper-addons.js", this);
add_setup(async function() {
await SpecialPowers.pushPrefEnv({
set: [["extensions.eventPages.enabled", true]],
});
});
// Test that an extension event page isn't terminated on idle when a DevTools
// Toolbox is attached to the extension.
add_task(
async function test_eventpage_no_idle_shutdown_with_toolbox_attached() {
const { document, tab, window } = await openAboutDebugging();
await selectThisFirefoxPage(document, window.AboutDebugging.store);
const EXTENSION_ID = "test-devtools-eventpage@mozilla.org";
const EXTENSION_NAME = "Temporary EventPage-based web extension";
const promiseBackgroundLoaded = promiseBackgroundContextLoaded(
EXTENSION_ID
);
let waitForBGStatusUpdate = promiseBackgroundStatusUpdate(window);
// Install the extension using an event page (non persistent background page).
await installTemporaryExtensionFromXPI(
{
id: EXTENSION_ID,
name: EXTENSION_NAME,
// The extension is expected to have a non persistent background script.
extraProperties: {
background: {
scripts: ["bgpage.js"],
persistent: false,
},
},
files: {
"bgpage.js": function() {
// Emit a dump when the script is loaded to make it easier
// to investigate intermittents.
dump(`Background script loaded: ${window.location}\n`);
},
},
},
document
);
const target = findDebugTargetByText(EXTENSION_NAME, document);
ok(
!!target,
"The EventPage-based extension is installed with the expected name"
);
info("Wait for the test extension background script to be loaded");
await promiseBackgroundLoaded;
info("Wait for the test extension background script status update");
await waitForBGStatusUpdate;
await assertBackgroundStatus(EXTENSION_NAME, {
document,
expectedStatus: "running",
});
waitForBGStatusUpdate = promiseBackgroundStatusUpdate(window);
await triggerExtensionEventPageIdleTimeout(EXTENSION_ID);
await waitForBGStatusUpdate;
await assertBackgroundStatus(EXTENSION_NAME, {
document,
expectedStatus: "stopped",
});
info(
"Respawn the extension background script on new WebExtension API event"
);
waitForBGStatusUpdate = promiseBackgroundStatusUpdate(window);
await wakeupExtensionEventPage(EXTENSION_ID);
await waitForBGStatusUpdate;
await assertBackgroundStatus(EXTENSION_NAME, {
document,
expectedStatus: "running",
});
info("Open a DevTools toolbox on the target extension");
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox(
document,
tab,
window,
EXTENSION_NAME
);
info(
"Verify event page terminated on terminate button clicked while the DevTools toolbox is open"
);
const terminateButton = target.querySelector(
".qa-temporary-extension-terminate-bgscript-button"
);
ok(
!!terminateButton,
`${EXTENSION_NAME} is expected to have a terminate button`
);
info(`Click on the terminate button for ${EXTENSION_NAME}`);
const promiseBackgroundUnloaded = promiseBackgroundContextUnloaded(
EXTENSION_ID
);
const waitForTerminateSuccess = waitForDispatch(
window.AboutDebugging.store,
"TERMINATE_EXTENSION_BGSCRIPT_SUCCESS"
);
waitForBGStatusUpdate = promiseBackgroundStatusUpdate(window);
terminateButton.click();
await waitForTerminateSuccess;
info("Wait for the extension background script to be unloaded");
await promiseBackgroundUnloaded;
await waitForBGStatusUpdate;
await assertBackgroundStatus(EXTENSION_NAME, {
document,
expectedStatus: "stopped",
targetElement: target,
});
info(
"Verify event page isn't terminated on idle while the DevTools toolbox is open"
);
// Make sure the event page is running again.
waitForBGStatusUpdate = promiseBackgroundStatusUpdate(window);
await wakeupExtensionEventPage(EXTENSION_ID);
await waitForBGStatusUpdate;
await assertBackgroundStatus(EXTENSION_NAME, {
document,
expectedStatus: "running",
targetElement: target,
});
const waitForBGSuspendIgnored = promiseTerminateBackgroundScriptIgnored(
EXTENSION_ID
);
waitForBGStatusUpdate = promiseBackgroundStatusUpdate(window);
await triggerExtensionEventPageIdleTimeout(EXTENSION_ID);
await Promise.race([waitForBGStatusUpdate, waitForBGSuspendIgnored]);
await assertBackgroundStatus(EXTENSION_NAME, {
document,
expectedStatus: "running",
// After opening the toolbox there will be an additional target listed
// for the devtools toolbox tab, its card includes the extension name
// and so while the toolbox is open we should make sure to look for
// the background status inside the extension target card instead of
// the one associated to the devtools toolbox tab.
targetElement: target,
});
info(
"Wait for warning message expected to be logged for the event page not terminated on idle"
);
const toolbox = getToolbox(devtoolsWindow);
const webconsole = await toolbox.selectTool("webconsole");
const { hud } = webconsole;
const expectedWarning =
"Background event page was not terminated on idle because a DevTools toolbox is attached to the extension.";
let consoleElements;
await waitUntil(() => {
consoleElements = findMessages(hud, expectedWarning);
return consoleElements.length > 0;
});
const locationElement = consoleElements[0].querySelector(
".frame-link-filename"
);
ok(
locationElement.textContent.endsWith("_generated_background_page.html"),
"The warning message is associated to the event page url"
);
info(
"Verify event page is terminated on idle after closing the DevTools toolbox"
);
await closeAboutDevtoolsToolbox(document, devtoolsTab, window);
await triggerExtensionEventPageIdleTimeout(EXTENSION_ID);
await waitForBGStatusUpdate;
await assertBackgroundStatus(EXTENSION_NAME, {
document,
expectedStatus: "stopped",
});
// Uninstall the test extensions.
info("Unload extension and remove about:debugging tab");
await AddonManager.getAddonByID(EXTENSION_ID).then(addon =>
addon.uninstall()
);
info("Wait until the debug targets with test extensions disappears");
await waitUntil(() => !findDebugTargetByText(EXTENSION_NAME, document));
await removeTab(tab);
}
);

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

@ -446,3 +446,26 @@ function clickOnAddonWidget(addonId) {
info("Show the web extension popup"); info("Show the web extension popup");
browserActionEl.click(); browserActionEl.click();
} }
/**
* Retrieve console panel messages that includes a given string.
*
* @param {WebConsole} hud
* The WebConsole instance.
* @param {string} text
* The string of text that should be used to select the
* console message elements to return.
* @param {string} [selector]
* An optional CSS selector string (defaults to .message).
*
* @returns {Array<DOMElement>}
* The console panel DOM elements which are matching the
* given text and selector.
*/
function findMessages(hud, text, selector = ".message") {
const messages = hud.ui.outputNode.querySelectorAll(selector);
const elements = Array.prototype.filter.call(messages, el =>
el.textContent.includes(text)
);
return elements;
}

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

@ -184,3 +184,79 @@ function prepareMockFilePicker(pathOrFile) {
MockFilePicker.setFiles([file]); MockFilePicker.setFiles([file]);
} }
/* exported prepareMockFilePicker */ /* exported prepareMockFilePicker */
function promiseBackgroundContextEvent(extensionId, eventName) {
const { Management } = ChromeUtils.import(
"resource://gre/modules/Extension.jsm"
);
return new Promise(resolve => {
Management.on(eventName, function listener(_evtName, context) {
if (context.extension.id === extensionId) {
Management.off(eventName, listener);
resolve();
}
});
});
}
function promiseBackgroundContextLoaded(extensionId) {
return promiseBackgroundContextEvent(extensionId, "proxy-context-load");
}
/* exported promiseBackgroundContextLoaded */
function promiseBackgroundContextUnloaded(extensionId) {
return promiseBackgroundContextEvent(extensionId, "proxy-context-unload");
}
/* exported promiseBackgroundContextUnloaded */
async function assertBackgroundStatus(
extName,
{ document, expectedStatus, targetElement }
) {
const target = targetElement || findDebugTargetByText(extName, document);
const getBackgroundStatusElement = () =>
target.querySelector(".extension-backgroundscript__status");
await waitFor(
() =>
getBackgroundStatusElement()?.classList.contains(
`extension-backgroundscript__status--${expectedStatus}`
),
`Wait ${extName} Background script status "${expectedStatus}" to be rendered`
);
}
/* exported assertBackgroundStatus */
function getExtensionInstance(extensionId) {
const policy = WebExtensionPolicy.getByID(extensionId);
ok(policy, `Got a WebExtensionPolicy instance for ${extensionId}`);
ok(policy.extension, `Got an Extension class instance for ${extensionId}`);
return policy.extension;
}
/* exported getExtensionInstance */
async function triggerExtensionEventPageIdleTimeout(extensionId) {
await getExtensionInstance(extensionId).terminateBackground();
}
/* exported triggerExtensionEventPageIdleTimeout */
async function wakeupExtensionEventPage(extensionId) {
await getExtensionInstance(extensionId).wakeupBackground();
}
/* exported wakeupExtensionEventPage */
function promiseTerminateBackgroundScriptIgnored(extensionId) {
const extension = getExtensionInstance(extensionId);
return new Promise(resolve => {
extension.once("background-script-suspend-ignored", resolve);
});
}
/* exported promiseTerminateBackgroundScriptIgnored */
async function promiseBackgroundStatusUpdate(window) {
waitForDispatch(
window.AboutDebugging.store,
"EXTENSION_BGSCRIPT_STATUS_UPDATED"
);
}
/* exported promiseBackgroundStatusUpdate */

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

@ -134,14 +134,7 @@ ClassList.prototype = {
* @return {Boolean} * @return {Boolean}
*/ */
function isXUL(window) { function isXUL(window) {
// XXX: We temporarily return true for HTML documents if the document disables return window.document.documentElement.namespaceURI === XUL_NS;
// scroll frames since the regular highlighter is broken in this case. This
// should be removed when bug 1594587 is fixed.
return (
window.document.documentElement.namespaceURI === XUL_NS ||
(window.isChromeWindow &&
window.document.documentElement.getAttribute("scrolling") === "false")
);
} }
exports.isXUL = isXUL; exports.isXUL = isXUL;

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

@ -45,6 +45,9 @@
#include "mozilla/dom/WindowGlobalParent.h" #include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/WorkerScope.h" #include "mozilla/dom/WorkerScope.h"
#include "mozilla/ipc/GeckoChildProcessHost.h" #include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/UtilityProcessSandboxing.h"
#include "mozilla/ipc/UtilityProcessManager.h"
#include "mozilla/ipc/UtilityProcessHost.h"
#include "mozilla/net/UrlClassifierFeatureFactory.h" #include "mozilla/net/UrlClassifierFeatureFactory.h"
#include "IOActivityMonitor.h" #include "IOActivityMonitor.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
@ -897,6 +900,30 @@ static WebIDLProcType ProcTypeToWebIDL(mozilla::ProcType aType) {
#undef PROCTYPE_TO_WEBIDL_CASE #undef PROCTYPE_TO_WEBIDL_CASE
#define UTILITYACTORNAME_TO_WEBIDL_CASE(_utilityActorName, _webidl) \
case mozilla::UtilityActorName::_utilityActorName: \
return WebIDLUtilityActorName::_webidl
static WebIDLUtilityActorName UtilityActorNameToWebIDL(
mozilla::UtilityActorName aType) {
// Max is the value of the last enum, not the length, so add one.
static_assert(WebIDLUtilityActorNameValues::Count ==
static_cast<size_t>(UtilityActorName::AudioDecoder) + 1,
"In order for this static cast to be okay, "
"UtilityActorName must match UtilityActorName exactly");
// These must match the similar ones in ProcInfo.h and ChromeUtils.webidl
switch (aType) {
UTILITYACTORNAME_TO_WEBIDL_CASE(Unknown, Unknown);
UTILITYACTORNAME_TO_WEBIDL_CASE(AudioDecoder, AudioDecoder);
}
MOZ_ASSERT(false, "Unhandled case in WebIDLUtilityActorName");
return WebIDLUtilityActorName::Unknown;
}
#undef UTILITYACTORNAME_TO_WEBIDL_CASE
/* static */ /* static */
already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal, already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
ErrorResult& aRv) { ErrorResult& aRv) {
@ -938,7 +965,8 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
/* aPid = */ base::GetCurrentProcId(), /* aPid = */ base::GetCurrentProcId(),
/* aProcessType = */ ProcType::Browser, /* aProcessType = */ ProcType::Browser,
/* aOrigin = */ ""_ns, /* aOrigin = */ ""_ns,
/* aWindowInfo = */ nsTArray<WindowInfo>()); /* aWindowInfo = */ nsTArray<WindowInfo>(),
/* aUtilityInfo = */ nsTArray<UtilityInfo>());
// First handle non-ContentParent processes. // First handle non-ContentParent processes.
mozilla::ipc::GeckoChildProcessHost::GetAll( mozilla::ipc::GeckoChildProcessHost::GetAll(
@ -957,6 +985,7 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
// These processes are handled separately. // These processes are handled separately.
return; return;
} }
#define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \ #define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
process_bin_type, procinfo_typename, \ process_bin_type, procinfo_typename, \
webidl_typename, allcaps_name) \ webidl_typename, allcaps_name) \
@ -979,6 +1008,19 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
break; break;
} }
// Attach utility actor information to the process.
nsTArray<UtilityInfo> utilityActors;
if (aGeckoProcess->GetProcessType() ==
GeckoProcessType::GeckoProcessType_Utility) {
RefPtr<mozilla::ipc::UtilityProcessManager> upm =
mozilla::ipc::UtilityProcessManager::GetSingleton();
if (!utilityActors.AppendElements(upm->GetActors(aGeckoProcess),
fallible)) {
NS_WARNING("Error adding actors");
return;
}
}
requests.EmplaceBack( requests.EmplaceBack(
/* aPid = */ childPid, /* aPid = */ childPid,
/* aProcessType = */ type, /* aProcessType = */ type,
@ -986,6 +1028,7 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
/* aWindowInfo = */ nsTArray<WindowInfo>(), // Without a /* aWindowInfo = */ nsTArray<WindowInfo>(), // Without a
// ContentProcess, no // ContentProcess, no
// DOM windows. // DOM windows.
/* aUtilityInfo = */ std::move(utilityActors),
/* aChild = */ 0 // Without a ContentProcess, no ChildId. /* aChild = */ 0 // Without a ContentProcess, no ChildId.
#ifdef XP_MACOSX #ifdef XP_MACOSX
, ,
@ -1087,6 +1130,7 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
/* aProcessType = */ type, /* aProcessType = */ type,
/* aOrigin = */ origin, /* aOrigin = */ origin,
/* aWindowInfo = */ std::move(windows), /* aWindowInfo = */ std::move(windows),
/* aUtilityInfo = */ nsTArray<UtilityInfo>(),
/* aChild = */ contentParent->ChildID() /* aChild = */ contentParent->ChildID()
#ifdef XP_MACOSX #ifdef XP_MACOSX
, ,
@ -1154,6 +1198,20 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
dest->mIsProcessRoot = source.isProcessRoot; dest->mIsProcessRoot = source.isProcessRoot;
dest->mIsInProcess = source.isInProcess; dest->mIsInProcess = source.isInProcess;
} }
if (sysProcInfo.type == ProcType::Utility) {
for (const auto& source : sysProcInfo.utilityActors) {
auto* dest =
childInfo->mUtilityActors.AppendElement(fallible);
if (!dest) {
domPromise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
return;
}
dest->mActorName =
UtilityActorNameToWebIDL(source.actorName);
}
}
} }
} }

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

@ -678,6 +678,20 @@ dictionary WindowInfoDictionary {
boolean isInProcess = false; boolean isInProcess = false;
}; };
/*
* Add new entry to WebIDLUtilityActorName here and update accordingly
* UtilityActorNameToWebIDL in dom/base/ChromeUtils.cpp as well as
* UtilityActorName in toolkit/components/processtools/ProcInfo.h
*/
enum WebIDLUtilityActorName {
"unknown",
"audioDecoder",
};
dictionary UtilityActorsDictionary {
WebIDLUtilityActorName actorName = "unknown";
};
/** /**
* Information on a child process. * Information on a child process.
* *
@ -725,6 +739,9 @@ dictionary ChildProcInfoDictionary {
// The windows implemented by this process. // The windows implemented by this process.
sequence<WindowInfoDictionary> windows = []; sequence<WindowInfoDictionary> windows = [];
// The utility process list of actors if any
sequence<UtilityActorsDictionary> utilityActors = [];
}; };
/** /**

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

@ -4914,7 +4914,6 @@ class QuotaClient final : public mozilla::dom::quota::Client {
RefPtr<nsThreadPool> mMaintenanceThreadPool; RefPtr<nsThreadPool> mMaintenanceThreadPool;
nsClassHashtable<nsRefPtrHashKey<DatabaseFileManager>, nsTArray<int64_t>> nsClassHashtable<nsRefPtrHashKey<DatabaseFileManager>, nsTArray<int64_t>>
mPendingDeleteInfos; mPendingDeleteInfos;
FlippedOnce<false> mShutdownRequested;
public: public:
QuotaClient(); QuotaClient();
@ -4925,33 +4924,11 @@ class QuotaClient final : public mozilla::dom::quota::Client {
return sInstance; return sInstance;
} }
static bool IsShuttingDownOnBackgroundThread() {
AssertIsOnBackgroundThread();
if (sInstance) {
return sInstance->IsShuttingDown();
}
return QuotaManager::IsShuttingDown();
}
static bool IsShuttingDownOnNonBackgroundThread() {
MOZ_ASSERT(!IsOnBackgroundThread());
return QuotaManager::IsShuttingDown();
}
nsIEventTarget* BackgroundThread() const { nsIEventTarget* BackgroundThread() const {
MOZ_ASSERT(mBackgroundThread); MOZ_ASSERT(mBackgroundThread);
return mBackgroundThread; return mBackgroundThread;
} }
bool IsShuttingDown() const {
AssertIsOnBackgroundThread();
return mShutdownRequested;
}
nsresult AsyncDeleteFile(DatabaseFileManager* aFileManager, int64_t aFileId); nsresult AsyncDeleteFile(DatabaseFileManager* aFileManager, int64_t aFileId);
nsresult FlushPendingFileDeletions(); nsresult FlushPendingFileDeletions();
@ -12481,7 +12458,7 @@ nsresult QuotaClient::AsyncDeleteFile(DatabaseFileManager* aFileManager,
int64_t aFileId) { int64_t aFileId) {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
if (mShutdownRequested) { if (IsShuttingDownOnBackgroundThread()) {
// Whoops! We want to delete an IndexedDB disk-backed File but it's too late // Whoops! We want to delete an IndexedDB disk-backed File but it's too late
// to actually delete the file! This means we're going to "leak" the file // to actually delete the file! This means we're going to "leak" the file
// and leave it around when we shouldn't! (The file will stay around until // and leave it around when we shouldn't! (The file will stay around until
@ -12515,7 +12492,7 @@ nsresult QuotaClient::FlushPendingFileDeletions() {
nsThreadPool* QuotaClient::GetOrCreateThreadPool() { nsThreadPool* QuotaClient::GetOrCreateThreadPool() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(!mShutdownRequested); MOZ_ASSERT(!IsShuttingDownOnBackgroundThread());
if (!mMaintenanceThreadPool) { if (!mMaintenanceThreadPool) {
RefPtr<nsThreadPool> threadPool = new nsThreadPool(); RefPtr<nsThreadPool> threadPool = new nsThreadPool();
@ -12892,7 +12869,10 @@ void QuotaClient::AbortAllOperations() {
void QuotaClient::StartIdleMaintenance() { void QuotaClient::StartIdleMaintenance() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(!mShutdownRequested); if (IsShuttingDownOnBackgroundThread()) {
MOZ_ASSERT(false, "!IsShuttingDownOnBackgroundThread()");
return;
}
mBackgroundThread = GetCurrentEventTarget(); mBackgroundThread = GetCurrentEventTarget();
@ -12902,7 +12882,6 @@ void QuotaClient::StartIdleMaintenance() {
void QuotaClient::StopIdleMaintenance() { void QuotaClient::StopIdleMaintenance() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(!mShutdownRequested);
if (mCurrentMaintenance) { if (mCurrentMaintenance) {
mCurrentMaintenance->Abort(); mCurrentMaintenance->Abort();
@ -12916,8 +12895,6 @@ void QuotaClient::StopIdleMaintenance() {
void QuotaClient::InitiateShutdown() { void QuotaClient::InitiateShutdown() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
mShutdownRequested.Flip();
AbortAllOperations(); AbortAllOperations();
} }

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

@ -2610,7 +2610,6 @@ class QuotaClient final : public mozilla::dom::quota::Client {
static QuotaClient* sInstance; static QuotaClient* sInstance;
Mutex mShadowDatabaseMutex MOZ_UNANNOTATED; Mutex mShadowDatabaseMutex MOZ_UNANNOTATED;
bool mShutdownRequested;
public: public:
QuotaClient(); QuotaClient();
@ -2623,34 +2622,12 @@ class QuotaClient final : public mozilla::dom::quota::Client {
return sInstance; return sInstance;
} }
static bool IsShuttingDownOnBackgroundThread() {
AssertIsOnBackgroundThread();
if (sInstance) {
return sInstance->IsShuttingDown();
}
return QuotaManager::IsShuttingDown();
}
static bool IsShuttingDownOnNonBackgroundThread() {
MOZ_ASSERT(!IsOnBackgroundThread());
return QuotaManager::IsShuttingDown();
}
mozilla::Mutex& ShadowDatabaseMutex() { mozilla::Mutex& ShadowDatabaseMutex() {
MOZ_ASSERT(IsOnIOThread() || IsOnGlobalConnectionThread()); MOZ_ASSERT(IsOnIOThread() || IsOnGlobalConnectionThread());
return mShadowDatabaseMutex; return mShadowDatabaseMutex;
} }
bool IsShuttingDown() const {
AssertIsOnBackgroundThread();
return mShutdownRequested;
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::dom::QuotaClient, override) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::dom::QuotaClient, override)
Type GetType() override; Type GetType() override;
@ -8328,8 +8305,7 @@ void ArchivedOriginScope::RemoveMatches(
QuotaClient* QuotaClient::sInstance = nullptr; QuotaClient* QuotaClient::sInstance = nullptr;
QuotaClient::QuotaClient() QuotaClient::QuotaClient()
: mShadowDatabaseMutex("LocalStorage mShadowDatabaseMutex"), : mShadowDatabaseMutex("LocalStorage mShadowDatabaseMutex") {
mShutdownRequested(false) {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(!sInstance, "We expect this to be a singleton!"); MOZ_ASSERT(!sInstance, "We expect this to be a singleton!");
@ -8784,9 +8760,6 @@ void QuotaClient::StartIdleMaintenance() { AssertIsOnBackgroundThread(); }
void QuotaClient::StopIdleMaintenance() { AssertIsOnBackgroundThread(); } void QuotaClient::StopIdleMaintenance() { AssertIsOnBackgroundThread(); }
void QuotaClient::InitiateShutdown() { void QuotaClient::InitiateShutdown() {
MOZ_ASSERT(!mShutdownRequested);
mShutdownRequested = true;
// gPrepareDatastoreOps are short lived objects running a state machine. // gPrepareDatastoreOps are short lived objects running a state machine.
// The shutdown flag is checked between states, so we don't have to notify // The shutdown flag is checked between states, so we don't have to notify
// all the objects here. // all the objects here.

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

@ -143,7 +143,8 @@ class D3D9DXVA2Manager : public DXVA2Manager {
HRESULT CopyToImage(IMFSample* aVideoSample, const gfx::IntRect& aRegion, HRESULT CopyToImage(IMFSample* aVideoSample, const gfx::IntRect& aRegion,
Image** aOutImage) override; Image** aOutImage) override;
bool SupportsConfig(IMFMediaType* aType, float aFramerate) override; bool SupportsConfig(IMFMediaType* aInputType, IMFMediaType* aOutputType,
float aFramerate) override;
private: private:
bool CanCreateDecoder(const DXVA2_VideoDesc& aDesc, bool CanCreateDecoder(const DXVA2_VideoDesc& aDesc,
@ -264,9 +265,19 @@ static const GUID DXVA2_ModeAV1_Profile0 = {
// DXVA2_ModeH264_VLD_NoFGT) as the H264 decoder MFT provided by windows // DXVA2_ModeH264_VLD_NoFGT) as the H264 decoder MFT provided by windows
// (CLSID_CMSH264DecoderMFT) uses, so we can use it to determine if the MFT will // (CLSID_CMSH264DecoderMFT) uses, so we can use it to determine if the MFT will
// use software fallback or not. // use software fallback or not.
bool D3D9DXVA2Manager::SupportsConfig(IMFMediaType* aType, float aFramerate) { bool D3D9DXVA2Manager::SupportsConfig(IMFMediaType* aInputType,
IMFMediaType* aOutputType,
float aFramerate) {
GUID inputSubtype;
HRESULT hr = aInputType->GetGUID(MF_MT_SUBTYPE, &inputSubtype);
if (FAILED(hr) || inputSubtype != MFVideoFormat_H264) {
return false;
}
DXVA2_VideoDesc desc; DXVA2_VideoDesc desc;
HRESULT hr = ConvertMFTypeToDXVAType(aType, &desc); // TODO Bug 1764823: ConvertMFTypeToDXVAType should accept the input type
// instead.
hr = ConvertMFTypeToDXVAType(aOutputType, &desc);
NS_ENSURE_TRUE(SUCCEEDED(hr), false); NS_ENSURE_TRUE(SUCCEEDED(hr), false);
return CanCreateDecoder(desc, aFramerate); return CanCreateDecoder(desc, aFramerate);
} }
@ -601,11 +612,10 @@ class D3D11DXVA2Manager : public DXVA2Manager {
bool IsD3D11() override { return true; } bool IsD3D11() override { return true; }
bool SupportsConfig(IMFMediaType* aType, float aFramerate) override; bool SupportsConfig(IMFMediaType* aInputType, IMFMediaType* aOutputType,
float aFramerate) override;
private: private:
HRESULT CreateFormatConverter();
HRESULT CreateOutputSample(RefPtr<IMFSample>& aSample, HRESULT CreateOutputSample(RefPtr<IMFSample>& aSample,
ID3D11Texture2D* aTexture); ID3D11Texture2D* aTexture);
@ -633,17 +643,19 @@ class D3D11DXVA2Manager : public DXVA2Manager {
gfx::ColorRange mColorRange = gfx::ColorRange::LIMITED; gfx::ColorRange mColorRange = gfx::ColorRange::LIMITED;
}; };
bool D3D11DXVA2Manager::SupportsConfig(IMFMediaType* aType, float aFramerate) { bool D3D11DXVA2Manager::SupportsConfig(IMFMediaType* aInputType,
IMFMediaType* aOutputType,
float aFramerate) {
D3D11_VIDEO_DECODER_DESC desc = {.OutputFormat = DXGI_FORMAT_NV12}; D3D11_VIDEO_DECODER_DESC desc = {.OutputFormat = DXGI_FORMAT_NV12};
GUID subtype; GUID subtype;
HRESULT hr = MFGetAttributeSize(aType, MF_MT_FRAME_SIZE, &desc.SampleWidth, HRESULT hr = MFGetAttributeSize(aInputType, MF_MT_FRAME_SIZE,
&desc.SampleHeight); &desc.SampleWidth, &desc.SampleHeight);
NS_ENSURE_TRUE(SUCCEEDED(hr), false); NS_ENSURE_TRUE(SUCCEEDED(hr), false);
NS_ENSURE_TRUE(desc.SampleWidth <= MAX_VIDEO_WIDTH, false); NS_ENSURE_TRUE(desc.SampleWidth <= MAX_VIDEO_WIDTH, false);
NS_ENSURE_TRUE(desc.SampleHeight <= MAX_VIDEO_HEIGHT, false); NS_ENSURE_TRUE(desc.SampleHeight <= MAX_VIDEO_HEIGHT, false);
hr = aType->GetGUID(MF_MT_SUBTYPE, &subtype); hr = aInputType->GetGUID(MF_MT_SUBTYPE, &subtype);
NS_ENSURE_TRUE(SUCCEEDED(hr), false); NS_ENSURE_TRUE(SUCCEEDED(hr), false);
if (subtype == MFVideoFormat_H264) { if (subtype == MFVideoFormat_H264) {

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

@ -68,7 +68,8 @@ class DXVA2Manager {
virtual ~DXVA2Manager(); virtual ~DXVA2Manager();
virtual bool SupportsConfig(IMFMediaType* aType, float aFramerate) = 0; virtual bool SupportsConfig(IMFMediaType* aInputType,
IMFMediaType* aOutputType, float aFramerate) = 0;
static bool IsNV12Supported(uint32_t aVendorID, uint32_t aDeviceID, static bool IsNV12Supported(uint32_t aVendorID, uint32_t aDeviceID,
const nsAString& aDriverVersionString); const nsAString& aDriverVersionString);

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

@ -227,8 +227,10 @@ bool WMFVideoMFTManager::InitializeDXVA() {
mDXVA2Manager.reset( mDXVA2Manager.reset(
DXVA2Manager::CreateD3D9DXVA(mKnowsCompositor, d3d9Failure)); DXVA2Manager::CreateD3D9DXVA(mKnowsCompositor, d3d9Failure));
// Make sure we include the messages from both attempts (if applicable). // Make sure we include the messages from both attempts (if applicable).
mDXVAFailureReason.AppendLiteral("; D3D9: "); if (!d3d9Failure.IsEmpty()) {
mDXVAFailureReason.Append(d3d9Failure); mDXVAFailureReason.AppendLiteral("; D3D9: ");
mDXVAFailureReason.Append(d3d9Failure);
}
return mDXVA2Manager != nullptr; return mDXVA2Manager != nullptr;
} }
@ -412,6 +414,12 @@ MediaResult WMFVideoMFTManager::InitInternal() {
} }
} }
if (!mDXVAFailureReason.IsEmpty()) {
// DXVA failure reason being set can mean that D3D11 failed, or that DXVA is
// entirely disabled.
LOG(nsPrintfCString("DXVA failure: %s", mDXVAFailureReason.get()).get());
}
if (!mUseHwAccel) { if (!mUseHwAccel) {
if (mDXVA2Manager) { if (mDXVA2Manager) {
// Either mDXVAEnabled was set to false prior the second call to // Either mDXVAEnabled was set to false prior the second call to
@ -419,7 +427,6 @@ MediaResult WMFVideoMFTManager::InitInternal() {
// MFT_MESSAGE_SET_D3D_MANAGER failed // MFT_MESSAGE_SET_D3D_MANAGER failed
mDXVA2Manager.reset(); mDXVA2Manager.reset();
} }
LOG(nsPrintfCString("DXVA failure: %s", mDXVAFailureReason.get()).get());
if (mStreamType == WMFStreamType::VP9 || if (mStreamType == WMFStreamType::VP9 ||
mStreamType == WMFStreamType::VP8 || mStreamType == WMFStreamType::VP8 ||
mStreamType == WMFStreamType::AV1) { mStreamType == WMFStreamType::AV1) {
@ -446,7 +453,16 @@ MediaResult WMFVideoMFTManager::InitInternal() {
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Fail to get the input media type."))); RESULT_DETAIL("Fail to get the input media type.")));
if (mUseHwAccel && !CanUseDXVA(inputType, mFramerate)) { RefPtr<IMFMediaType> outputType;
hr = mDecoder->GetOutputMediaType(outputType);
NS_ENSURE_TRUE(
SUCCEEDED(hr),
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Fail to get the output media type.")));
if (mUseHwAccel && !CanUseDXVA(inputType, outputType, mFramerate)) {
LOG("DXVA manager determined that the input type was unsupported in "
"hardware, retrying init without DXVA.");
mDXVAEnabled = false; mDXVAEnabled = false;
// DXVA initialization with current decoder actually failed, // DXVA initialization with current decoder actually failed,
// re-do initialization. // re-do initialization.
@ -456,13 +472,6 @@ MediaResult WMFVideoMFTManager::InitInternal() {
LOG("Video Decoder initialized, Using DXVA: %s", LOG("Video Decoder initialized, Using DXVA: %s",
(mUseHwAccel ? "Yes" : "No")); (mUseHwAccel ? "Yes" : "No"));
RefPtr<IMFMediaType> outputType;
hr = mDecoder->GetOutputMediaType(outputType);
NS_ENSURE_TRUE(
SUCCEEDED(hr),
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Fail to get the output media type.")));
if (mUseHwAccel) { if (mUseHwAccel) {
hr = mDXVA2Manager->ConfigureForSize( hr = mDXVA2Manager->ConfigureForSize(
outputType, outputType,
@ -605,12 +614,14 @@ WMFVideoMFTManager::Input(MediaRawData* aSample) {
// Ideally we'd know the framerate during initialization and would also ensure // Ideally we'd know the framerate during initialization and would also ensure
// that new decoders are created if the resolution changes. Then we could move // that new decoders are created if the resolution changes. Then we could move
// this check into Init and consolidate the main thread blocking code. // this check into Init and consolidate the main thread blocking code.
bool WMFVideoMFTManager::CanUseDXVA(IMFMediaType* aType, float aFramerate) { bool WMFVideoMFTManager::CanUseDXVA(IMFMediaType* aInputType,
IMFMediaType* aOutputType,
float aFramerate) {
MOZ_ASSERT(mDXVA2Manager); MOZ_ASSERT(mDXVA2Manager);
// Check if we're able to use hardware decoding with H264 or AV1. // Check if we're able to use hardware decoding with H264 or AV1.
// TODO: Do the same for VPX, if the VPX MFT has a slow software fallback? // TODO: Do the same for VPX, if the VPX MFT has a slow software fallback?
if (mStreamType == WMFStreamType::H264 || mStreamType == WMFStreamType::AV1) { if (mStreamType == WMFStreamType::H264 || mStreamType == WMFStreamType::AV1) {
return mDXVA2Manager->SupportsConfig(aType, aFramerate); return mDXVA2Manager->SupportsConfig(aInputType, aOutputType, aFramerate);
} }
return true; return true;

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

@ -64,7 +64,8 @@ class WMFVideoMFTManager : public MFTManager {
HRESULT SetDecoderMediaTypes(); HRESULT SetDecoderMediaTypes();
bool CanUseDXVA(IMFMediaType* aType, float aFramerate); bool CanUseDXVA(IMFMediaType* aInputType, IMFMediaType* aOutputType,
float aFramerate);
// Gets the duration from aSample, and if an unknown or invalid duration is // Gets the duration from aSample, and if an unknown or invalid duration is
// returned from WMF, this instead returns the last known input duration. // returned from WMF, this instead returns the last known input duration.

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

@ -3741,7 +3741,7 @@ void QuotaManager::MaybeRecordQuotaClientShutdownStep(
auto* const quotaManager = QuotaManager::Get(); auto* const quotaManager = QuotaManager::Get();
MOZ_DIAGNOSTIC_ASSERT(quotaManager); MOZ_DIAGNOSTIC_ASSERT(quotaManager);
if (quotaManager->ShutdownStarted()) { if (quotaManager->IsShuttingDown()) {
quotaManager->RecordShutdownStep(Some(aClientType), aStepDescription); quotaManager->RecordShutdownStep(Some(aClientType), aStepDescription);
} }
} }
@ -3753,7 +3753,7 @@ void QuotaManager::SafeMaybeRecordQuotaClientShutdownStep(
auto* const quotaManager = QuotaManager::Get(); auto* const quotaManager = QuotaManager::Get();
if (quotaManager && quotaManager->ShutdownStarted()) { if (quotaManager && quotaManager->IsShuttingDown()) {
quotaManager->RecordShutdownStep(Some(aClientType), aStepDescription); quotaManager->RecordShutdownStep(Some(aClientType), aStepDescription);
} }
} }
@ -3770,16 +3770,14 @@ void QuotaManager::MaybeRecordQuotaManagerShutdownStep(
const nsACString& aStepDescription) { const nsACString& aStepDescription) {
// Callable on any thread. // Callable on any thread.
if (ShutdownStarted()) { if (IsShuttingDown()) {
RecordQuotaManagerShutdownStep(aStepDescription); RecordQuotaManagerShutdownStep(aStepDescription);
} }
} }
bool QuotaManager::ShutdownStarted() const { return mShutdownStarted; }
void QuotaManager::RecordShutdownStep(const Maybe<Client::Type> aClientType, void QuotaManager::RecordShutdownStep(const Maybe<Client::Type> aClientType,
const nsACString& aStepDescription) { const nsACString& aStepDescription) {
MOZ_ASSERT(mShutdownStarted); MOZ_ASSERT(IsShuttingDown());
const TimeDuration elapsedSinceShutdownStart = const TimeDuration elapsedSinceShutdownStart =
TimeStamp::NowLoRes() - *mShutdownStartedAt; TimeStamp::NowLoRes() - *mShutdownStartedAt;
@ -3813,7 +3811,6 @@ void QuotaManager::RecordShutdownStep(const Maybe<Client::Type> aClientType,
void QuotaManager::Shutdown() { void QuotaManager::Shutdown() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(!mShutdownStarted);
MOZ_DIAGNOSTIC_ASSERT(!gShutdown); MOZ_DIAGNOSTIC_ASSERT(!gShutdown);
// Define some local helper functions // Define some local helper functions

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

@ -14,6 +14,7 @@
namespace mozilla::dom::quota { namespace mozilla::dom::quota {
using mozilla::ipc::AssertIsOnBackgroundThread; using mozilla::ipc::AssertIsOnBackgroundThread;
using mozilla::ipc::IsOnBackgroundThread;
namespace { namespace {
@ -246,4 +247,16 @@ void Client::FinalizeShutdownWorkThreads() {
FinalizeShutdown(); FinalizeShutdown();
} }
// static
bool Client::IsShuttingDownOnBackgroundThread() {
MOZ_ASSERT(IsOnBackgroundThread());
return QuotaManager::IsShuttingDown();
}
// static
bool Client::IsShuttingDownOnNonBackgroundThread() {
MOZ_ASSERT(!IsOnBackgroundThread());
return QuotaManager::IsShuttingDown();
}
} // namespace mozilla::dom::quota } // namespace mozilla::dom::quota

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

@ -157,6 +157,14 @@ class Client {
virtual void StopIdleMaintenance() = 0; virtual void StopIdleMaintenance() = 0;
// Both variants just check for QuotaManager::IsShuttingDown()
// but assert to be on the right thread.
// They must not be used for re-entrance checks.
// Deprecated: This distinction is not needed anymore.
// QuotaClients should call QuotaManager::IsShuttingDown instead.
static bool IsShuttingDownOnBackgroundThread();
static bool IsShuttingDownOnNonBackgroundThread();
// Returns true if there is work that needs to be waited for. // Returns true if there is work that needs to be waited for.
bool InitiateShutdownWorkThreads(); bool InitiateShutdownWorkThreads();
void FinalizeShutdownWorkThreads(); void FinalizeShutdownWorkThreads();

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

@ -15,7 +15,7 @@ template <typename F>
void QuotaManager::MaybeRecordQuotaManagerShutdownStepWith(F&& aFunc) { void QuotaManager::MaybeRecordQuotaManagerShutdownStepWith(F&& aFunc) {
// Callable on any thread. // Callable on any thread.
if (ShutdownStarted()) { if (IsShuttingDown()) {
RecordShutdownStep(Nothing{}, std::forward<F>(aFunc)()); RecordShutdownStep(Nothing{}, std::forward<F>(aFunc)());
} }
} }

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

@ -447,33 +447,9 @@ class CloseOp final : public ConnectionOperationBase {
class QuotaClient final : public mozilla::dom::quota::Client { class QuotaClient final : public mozilla::dom::quota::Client {
static QuotaClient* sInstance; static QuotaClient* sInstance;
bool mShutdownRequested;
public: public:
QuotaClient(); QuotaClient();
static bool IsShuttingDownOnBackgroundThread() {
AssertIsOnBackgroundThread();
if (sInstance) {
return sInstance->IsShuttingDown();
}
return QuotaManager::IsShuttingDown();
}
static bool IsShuttingDownOnNonBackgroundThread() {
MOZ_ASSERT(!IsOnBackgroundThread());
return QuotaManager::IsShuttingDown();
}
bool IsShuttingDown() const {
AssertIsOnBackgroundThread();
return mShutdownRequested;
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(QuotaClient, override) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(QuotaClient, override)
Type GetType() override; Type GetType() override;
@ -1639,7 +1615,7 @@ void CloseOp::OnSuccess() {
QuotaClient* QuotaClient::sInstance = nullptr; QuotaClient* QuotaClient::sInstance = nullptr;
QuotaClient::QuotaClient() : mShutdownRequested(false) { QuotaClient::QuotaClient() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(!sInstance, "We expect this to be a singleton!"); MOZ_ASSERT(!sInstance, "We expect this to be a singleton!");
@ -1760,9 +1736,6 @@ void QuotaClient::StopIdleMaintenance() { AssertIsOnBackgroundThread(); }
void QuotaClient::InitiateShutdown() { void QuotaClient::InitiateShutdown() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(!mShutdownRequested);
mShutdownRequested = true;
if (gOpenConnections) { if (gOpenConnections) {
for (const auto& connection : *gOpenConnections) { for (const auto& connection : *gOpenConnections) {

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

@ -251,13 +251,14 @@ Maybe<TextureHost::ResourceUpdateOp> AsyncImagePipelineManager::UpdateImageKeys(
// If we already had a texture and the format hasn't changed, better to reuse // If we already had a texture and the format hasn't changed, better to reuse
// the image keys than create new ones. // the image keys than create new ones.
auto backend = aSceneBuilderTxn.GetBackendType(); auto backend = aSceneBuilderTxn.GetBackendType();
bool canUpdate = !!previousTexture && bool canUpdate =
previousTexture->GetSize() == texture->GetSize() && !!previousTexture && previousTexture->GetSize() == texture->GetSize() &&
previousTexture->GetFormat() == texture->GetFormat() && previousTexture->GetFormat() == texture->GetFormat() &&
previousTexture->NeedsYFlip() == texture->NeedsYFlip() && previousTexture->GetColorDepth() == texture->GetColorDepth() &&
previousTexture->SupportsExternalCompositing(backend) == previousTexture->NeedsYFlip() == texture->NeedsYFlip() &&
texture->SupportsExternalCompositing(backend) && previousTexture->SupportsExternalCompositing(backend) ==
aPipeline->mKeys.Length() == numKeys; texture->SupportsExternalCompositing(backend) &&
aPipeline->mKeys.Length() == numKeys;
if (!canUpdate) { if (!canUpdate) {
for (auto key : aPipeline->mKeys) { for (auto key : aPipeline->mKeys) {

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

@ -79,6 +79,10 @@ already_AddRefed<gfx::DataSourceSurface> WebRenderTextureHost::GetAsSurface() {
return mWrappedTextureHost->GetAsSurface(); return mWrappedTextureHost->GetAsSurface();
} }
gfx::ColorDepth WebRenderTextureHost::GetColorDepth() const {
return mWrappedTextureHost->GetColorDepth();
}
gfx::YUVColorSpace WebRenderTextureHost::GetYUVColorSpace() const { gfx::YUVColorSpace WebRenderTextureHost::GetYUVColorSpace() const {
return mWrappedTextureHost->GetYUVColorSpace(); return mWrappedTextureHost->GetYUVColorSpace();
} }

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

@ -46,6 +46,7 @@ class WebRenderTextureHost : public TextureHost {
already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override; already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
gfx::ColorDepth GetColorDepth() const override;
gfx::YUVColorSpace GetYUVColorSpace() const override; gfx::YUVColorSpace GetYUVColorSpace() const override;
gfx::ColorRange GetColorRange() const override; gfx::ColorRange GetColorRange() const override;

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

@ -152,7 +152,7 @@ class GeckoChildProcessHost : public ChildProcessHost,
// For bug 943174: Skip the EnsureProcessTerminated call in the destructor. // For bug 943174: Skip the EnsureProcessTerminated call in the destructor.
void SetAlreadyDead(); void SetAlreadyDead();
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX) #if defined(MOZ_SANDBOX) && defined(XP_MACOSX)
// Start the sandbox from the child process. // Start the sandbox from the child process.
static bool StartMacSandbox(int aArgc, char** aArgv, static bool StartMacSandbox(int aArgc, char** aArgv,
std::string& aErrorMessage); std::string& aErrorMessage);
@ -171,7 +171,7 @@ class GeckoChildProcessHost : public ChildProcessHost,
// disabled to avoid connection attempts to diagnosticd(8) which are // disabled to avoid connection attempts to diagnosticd(8) which are
// blocked in child processes due to sandboxing. // blocked in child processes due to sandboxing.
void DisableOSActivityMode(); void DisableOSActivityMode();
#endif #endif // defined(MOZ_SANDBOX) && defined(XP_MACOSX)
typedef std::function<void(GeckoChildProcessHost*)> GeckoProcessCallback; typedef std::function<void(GeckoChildProcessHost*)> GeckoProcessCallback;
// Iterates over all instances and calls aCallback with each one of them. // Iterates over all instances and calls aCallback with each one of them.

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

@ -6,9 +6,11 @@
#ifndef _include_ipc_glue_UtilityAudioDecoderChild_h__ #ifndef _include_ipc_glue_UtilityAudioDecoderChild_h__
#define _include_ipc_glue_UtilityAudioDecoderChild_h__ #define _include_ipc_glue_UtilityAudioDecoderChild_h__
#include "mozilla/ProcInfo.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/UtilityProcessParent.h"
#include "mozilla/ipc/PUtilityAudioDecoderChild.h" #include "mozilla/ipc/PUtilityAudioDecoderChild.h"
#include "PDMFactory.h" #include "PDMFactory.h"
@ -24,6 +26,30 @@ class UtilityAudioDecoderChild final : public PUtilityAudioDecoderChild {
mozilla::ipc::IPCResult RecvUpdateMediaCodecsSupported( mozilla::ipc::IPCResult RecvUpdateMediaCodecsSupported(
const PDMFactory::MediaCodecsSupported& aSupported); const PDMFactory::MediaCodecsSupported& aSupported);
UtilityActorName GetActorName() { return UtilityActorName::AudioDecoder; }
nsresult BindToUtilityProcess(RefPtr<UtilityProcessParent> aUtilityParent) {
Endpoint<PUtilityAudioDecoderChild> utilityAudioDecoderChildEnd;
Endpoint<PUtilityAudioDecoderParent> utilityAudioDecoderParentEnd;
nsresult rv = PUtilityAudioDecoder::CreateEndpoints(
aUtilityParent->OtherPid(), base::GetCurrentProcId(),
&utilityAudioDecoderParentEnd, &utilityAudioDecoderChildEnd);
if (NS_FAILED(rv)) {
MOZ_ASSERT(false, "Protocol endpoints failure");
return NS_ERROR_FAILURE;
}
if (!aUtilityParent->SendStartUtilityAudioDecoderService(
std::move(utilityAudioDecoderParentEnd))) {
MOZ_ASSERT(false, "StartUtilityAudioDecoder service failure");
return NS_ERROR_FAILURE;
}
Bind(std::move(utilityAudioDecoderChildEnd));
return NS_OK;
}
void ActorDestroy(ActorDestroyReason aReason) override; void ActorDestroy(ActorDestroyReason aReason) override;
void Bind(Endpoint<PUtilityAudioDecoderChild>&& aEndpoint); void Bind(Endpoint<PUtilityAudioDecoderChild>&& aEndpoint);

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

@ -207,64 +207,83 @@ RefPtr<GenericNonExclusivePromise> UtilityProcessManager::LaunchProcess(
return p->mLaunchPromise; return p->mLaunchPromise;
} }
template <typename Actor>
RefPtr<GenericNonExclusivePromise> UtilityProcessManager::StartUtility(
RefPtr<Actor> aActor, SandboxingKind aSandbox) {
if (!aActor) {
MOZ_ASSERT(false, "Actor singleton failure");
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
}
if (aActor->CanSend()) {
// Actor has already been setup, so we:
// - know the process has been launched
// - the ipc actors are ready
return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
}
RefPtr<UtilityProcessManager> self = this;
return LaunchProcess(aSandbox)->Then(
GetMainThreadSerialEventTarget(), __func__,
[self, aActor, aSandbox]() {
RefPtr<UtilityProcessParent> utilityParent =
self->GetProcessParent(aSandbox);
// It is possible if multiple processes concurrently request a utility
// actor that the previous CanSend() check returned false for both but
// that by the time we have started our process for real, one of them
// has already been able to establish the IPC connection and thus we
// would perform more than one Open() call.
//
// The tests within browser_utility_multipleAudio.js should be able to
// catch that behavior.
if (!aActor->CanSend()) {
nsresult rv = aActor->BindToUtilityProcess(utilityParent);
if (NS_FAILED(rv)) {
MOZ_ASSERT(false, "Protocol endpoints failure");
return GenericNonExclusivePromise::CreateAndReject(rv, __func__);
}
MOZ_DIAGNOSTIC_ASSERT(aActor->CanSend(), "IPC established for actor");
self->RegisterActor(utilityParent, aActor->GetActorName());
}
return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
},
[](nsresult aError) {
MOZ_ASSERT_UNREACHABLE("Failure when starting actor");
return GenericNonExclusivePromise::CreateAndReject(aError, __func__);
});
}
RefPtr<UtilityProcessManager::AudioDecodingPromise> RefPtr<UtilityProcessManager::AudioDecodingPromise>
UtilityProcessManager::StartAudioDecoding(base::ProcessId aOtherProcess) { UtilityProcessManager::StartAudioDecoding(base::ProcessId aOtherProcess) {
RefPtr<UtilityProcessManager> self = this; RefPtr<UtilityProcessManager> self = this;
return LaunchProcess(SandboxingKind::UTILITY_AUDIO_DECODING) RefPtr<UtilityAudioDecoderChild> uadc =
UtilityAudioDecoderChild::GetSingleton();
MOZ_ASSERT(uadc, "Unable to get a singleton for UtilityAudioDecoderChild");
return StartUtility(uadc, SandboxingKind::UTILITY_AUDIO_DECODING)
->Then( ->Then(
GetMainThreadSerialEventTarget(), __func__, GetMainThreadSerialEventTarget(), __func__,
[self, aOtherProcess]() { [self, uadc, aOtherProcess]() {
RefPtr<UtilityProcessParent> utilityParent = base::ProcessId process =
self->GetProcessParent(SandboxingKind::UTILITY_AUDIO_DECODING); self->GetProcessParent(SandboxingKind::UTILITY_AUDIO_DECODING)
->OtherPid();
RefPtr<UtilityAudioDecoderChild> uadc = if (!uadc->CanSend()) {
UtilityAudioDecoderChild::GetSingleton(); MOZ_ASSERT(false, "UtilityAudioDecoderChild lost in the middle");
if (!uadc) {
MOZ_ASSERT(false, "UtilityAudioDecoderChild singleton failure");
return AudioDecodingPromise::CreateAndReject(NS_ERROR_FAILURE, return AudioDecodingPromise::CreateAndReject(NS_ERROR_FAILURE,
__func__); __func__);
} }
if (!uadc->CanSend()) {
NS_WARNING(
"UtilityProcessManager::StartAudioDecoding: "
"!uadc->CanSend()");
Endpoint<PUtilityAudioDecoderChild> utilityAudioDecoderChildEnd;
Endpoint<PUtilityAudioDecoderParent> utilityAudioDecoderParentEnd;
nsresult rv = PUtilityAudioDecoder::CreateEndpoints(
utilityParent->OtherPid(), base::GetCurrentProcId(),
&utilityAudioDecoderParentEnd, &utilityAudioDecoderChildEnd);
if (NS_FAILED(rv)) {
MOZ_ASSERT(false, "PUtilityAudioDecoder endpoints failure");
return AudioDecodingPromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
}
if (!utilityParent->SendStartUtilityAudioDecoderService(
std::move(utilityAudioDecoderParentEnd))) {
MOZ_ASSERT(false, "StartUtilityAudioDecoder service failure");
return AudioDecodingPromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
}
uadc->Bind(std::move(utilityAudioDecoderChildEnd));
}
MOZ_DIAGNOSTIC_ASSERT(uadc->CanSend(),
"IPC established for UtilityAudioDecoder");
Endpoint<PRemoteDecoderManagerChild> childPipe; Endpoint<PRemoteDecoderManagerChild> childPipe;
Endpoint<PRemoteDecoderManagerParent> parentPipe; Endpoint<PRemoteDecoderManagerParent> parentPipe;
nsresult rv = PRemoteDecoderManager::CreateEndpoints( nsresult rv = PRemoteDecoderManager::CreateEndpoints(
utilityParent->OtherPid(), aOtherProcess, &parentPipe, process, aOtherProcess, &parentPipe, &childPipe);
&childPipe);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
MOZ_ASSERT(false, "Could not create content remote decoder"); MOZ_ASSERT(false, "Could not create content remote decoder");
return AudioDecodingPromise::CreateAndReject(NS_ERROR_FAILURE, return AudioDecodingPromise::CreateAndReject(rv, __func__);
__func__);
} }
if (!uadc->SendNewContentRemoteDecoderManager( if (!uadc->SendNewContentRemoteDecoderManager(

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

@ -8,6 +8,7 @@
#include "mozilla/MozPromise.h" #include "mozilla/MozPromise.h"
#include "mozilla/ipc/UtilityProcessHost.h" #include "mozilla/ipc/UtilityProcessHost.h"
#include "mozilla/EnumeratedArray.h" #include "mozilla/EnumeratedArray.h"
#include "mozilla/ProcInfo.h"
#include "nsIObserver.h" #include "nsIObserver.h"
#include "nsTArray.h" #include "nsTArray.h"
@ -41,6 +42,10 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener {
// Launch a new Utility process asynchronously // Launch a new Utility process asynchronously
RefPtr<GenericNonExclusivePromise> LaunchProcess(SandboxingKind aSandbox); RefPtr<GenericNonExclusivePromise> LaunchProcess(SandboxingKind aSandbox);
template <typename Actor>
RefPtr<GenericNonExclusivePromise> StartUtility(RefPtr<Actor> aActor,
SandboxingKind aSandbox);
RefPtr<AudioDecodingPromise> StartAudioDecoding( RefPtr<AudioDecodingPromise> StartAudioDecoding(
base::ProcessId aOtherProcess); base::ProcessId aOtherProcess);
@ -83,6 +88,25 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener {
return p->mProcess; return p->mProcess;
} }
void RegisterActor(const RefPtr<UtilityProcessParent>& aParent,
UtilityActorName aActorName) {
for (auto& p : mProcesses) {
if (p && p->mProcessParent && p->mProcessParent == aParent) {
p->mActors.AppendElement(aActorName);
return;
}
}
}
Span<const UtilityActorName> GetActors(GeckoChildProcessHost* aHost) {
for (auto& p : mProcesses) {
if (p && p->mProcess == aHost) {
return p->mActors;
}
}
return {};
}
// Shutdown the Utility process for that sandbox. // Shutdown the Utility process for that sandbox.
void CleanShutdown(SandboxingKind aSandbox); void CleanShutdown(SandboxingKind aSandbox);
@ -142,6 +166,8 @@ class UtilityProcessManager final : public UtilityProcessHost::Listener {
// when the process can receive IPC messages. // when the process can receive IPC messages.
nsTArray<dom::Pref> mQueuedPrefs; nsTArray<dom::Pref> mQueuedPrefs;
nsTArray<UtilityActorName> mActors;
SandboxingKind mSandbox = SandboxingKind::COUNT; SandboxingKind mSandbox = SandboxingKind::COUNT;
protected: protected:

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

@ -5703,6 +5703,9 @@ GeneralParser<ParseHandler, Unit>::exportFrom(uint32_t begin, Node specList) {
ListNodeType importAssertionList = ListNodeType importAssertionList =
handler_.newList(ParseNodeKind::ImportAssertionList, pos()); handler_.newList(ParseNodeKind::ImportAssertionList, pos());
if (!importAssertionList) {
return null();
}
if (tt == TokenKind::Assert) { if (tt == TokenKind::Assert) {
tokenStream.consumeKnownToken(TokenKind::Assert, tokenStream.consumeKnownToken(TokenKind::Assert,
TokenStream::SlashIsRegExp); TokenStream::SlashIsRegExp);
@ -5718,6 +5721,9 @@ GeneralParser<ParseHandler, Unit>::exportFrom(uint32_t begin, Node specList) {
BinaryNodeType moduleRequest = handler_.newModuleRequest( BinaryNodeType moduleRequest = handler_.newModuleRequest(
moduleSpec, importAssertionList, TokenPos(moduleSpecPos, pos().end)); moduleSpec, importAssertionList, TokenPos(moduleSpecPos, pos().end));
if (!moduleRequest) {
return null();
}
BinaryNodeType node = BinaryNodeType node =
handler_.newExportFromDeclaration(begin, specList, moduleRequest); handler_.newExportFromDeclaration(begin, specList, moduleRequest);

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

@ -0,0 +1,35 @@
// Test inlining natives through Function.prototype.call
//
// Array() is inlined when there are 0-1 arguments.
function arrayThisAbsent() {
for (let i = 0; i < 400; ++i) {
let r = Array.call();
assertEq(r.length, 0);
}
}
for (let i = 0; i < 2; ++i) arrayThisAbsent();
function array0() {
for (let i = 0; i < 400; ++i) {
let r = Array.call(null);
assertEq(r.length, 0);
}
}
for (let i = 0; i < 2; ++i) array0();
function array1() {
for (let i = 0; i < 400; ++i) {
let r = Array.call(null, 5);
assertEq(r.length, 5);
}
}
for (let i = 0; i < 2; ++i) array1();
function array2() {
for (let i = 0; i < 400; ++i) {
let r = Array.call(null, 5, 10);
assertEq(r.length, 2);
}
}
for (let i = 0; i < 2; ++i) array2();

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

@ -0,0 +1,13 @@
function f() {
var res = 0;
for (var i = 0; i < 2000; i++) {
var res1 = Math.abs(i - 123.5); // Double
var res2 = Math.fround(i + 0.5); // Float32
if (i > 1900) {
bailout();
}
res += res1 + res2;
}
assertEq(res, 3767376);
}
f();

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

@ -0,0 +1,24 @@
var x = 0;
var o1 = {x: 1};
var o2 = {};
for (var o of [o1, o2]) {
Object.defineProperty(o, "thrower", {get: function() {
if (x++ > 1900) {
throw "error";
}
}});
}
function f() {
var res = 0;
try {
for (var i = 0; i < 2000; i++) {
res = Math.abs(i - 123456.7);
var o = (i & 1) ? o1 : o2;
o.thrower;
res++;
}
} catch(e) {}
assertEq(res, 121555.7);
return res;
}
f();

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

@ -0,0 +1,24 @@
var x = 0;
var o1 = {x: 1};
var o2 = {};
for (var o of [o1, o2]) {
Object.defineProperty(o, "thrower", {get: function() {
if (x++ > 1900) {
throw "error";
}
}});
}
function f() {
var res = 0;
try {
for (var i = 0; i < 2000; i++) {
res = Math.fround(i - 123456.7);
var o = (i & 1) ? o1 : o2;
o.thrower;
res++;
}
} catch(e) {}
assertEq(res, -121555.703125);
return res;
}
f();

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

@ -0,0 +1,9 @@
// |jit-test| skip-if: !('oomTest' in this); --fuzzing-safe; --ion-offthread-compile=off
function r(src) {
oomTest(function() {
parseModule(src);
});
}
r("export * from 'y';");
r("export * from 'y';");

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

@ -0,0 +1,11 @@
// |jit-test| skip-if: !this.hasOwnProperty("Tuple")
function f() {
var expected = #[1, "monkeys", 3];
assertEq(#[1,2,3].with(1, "monkeys"), expected);
assertEq(Object(#[1,2,3]).with(1, "monkeys"), expected);
}
for (i = 0; i < 500; i++) {
f();
}

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

@ -15,9 +15,9 @@
#include "jstypes.h" #include "jstypes.h"
#include "jit/IonTypes.h" // js::jit::Bailout{Id,Kind}, js::jit::SnapshotOffset #include "jit/IonTypes.h" // js::jit::Bailout{Id,Kind}, js::jit::SnapshotOffset
#include "jit/Registers.h" // js::jit::MachineState #include "jit/MachineState.h" // js::jit::MachineState
#include "js/TypeDecls.h" // jsbytecode #include "js/TypeDecls.h" // jsbytecode
#include "vm/JSContext.h" // JSContext #include "vm/JSContext.h" // JSContext
namespace js { namespace js {

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

@ -8885,8 +8885,15 @@ AttachDecision InlinableNativeIRGenerator::tryAttachArrayConstructor() {
Int32OperandId lengthId; Int32OperandId lengthId;
if (argc_ == 1) { if (argc_ == 1) {
// Use standard call flags when this is an inline Function.prototype.call(),
// because GetIndexOfArgument() doesn't yet support |CallFlags::FunCall|.
CallFlags flags = flags_;
if (flags.getArgFormat() == CallFlags::FunCall) {
flags = CallFlags(CallFlags::Standard);
}
ValOperandId arg0Id = ValOperandId arg0Id =
writer.loadArgumentFixedSlot(ArgumentKind::Arg0, argc_, flags_); writer.loadArgumentFixedSlot(ArgumentKind::Arg0, argc_, flags);
lengthId = writer.guardToInt32(arg0Id); lengthId = writer.guardToInt32(arg0Id);
} else { } else {
MOZ_ASSERT(argc_ == 0); MOZ_ASSERT(argc_ == 0);

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

@ -206,30 +206,16 @@ MachineState JSJitFrameIter::machineState() const {
} }
SafepointReader reader(ionScript(), safepoint()); SafepointReader reader(ionScript(), safepoint());
FloatRegisterSet fregs = reader.allFloatSpills().set().reduceSetForPush();
GeneralRegisterSet regs = reader.allGprSpills().set();
uintptr_t* spill = spillBase(); uintptr_t* spill = spillBase();
MachineState machine; uint8_t* spillAlign =
alignDoubleSpill(reinterpret_cast<uint8_t*>(spill - regs.size()));
for (GeneralRegisterBackwardIterator iter(reader.allGprSpills()); iter.more();
++iter) {
machine.setRegisterLocation(*iter, --spill);
}
uint8_t* spillAlign = alignDoubleSpill(reinterpret_cast<uint8_t*>(spill));
char* floatSpill = reinterpret_cast<char*>(spillAlign); char* floatSpill = reinterpret_cast<char*>(spillAlign);
FloatRegisterSet fregs = reader.allFloatSpills().set();
fregs = fregs.reduceSetForPush();
for (FloatRegisterBackwardIterator iter(fregs); iter.more(); ++iter) {
floatSpill -= (*iter).size();
for (uint32_t a = 0; a < (*iter).numAlignedAliased(); a++) {
// Only say that registers that actually start here start here.
// e.g. d0 should not start at s1, only at s0.
FloatRegister ftmp = (*iter).alignedAliased(a);
machine.setRegisterLocation(ftmp, (double*)floatSpill);
}
}
return machine; return MachineState::FromSafepoint(fregs, regs, floatSpill, spill);
} }
JitFrameLayout* JSJitFrameIter::jsFrame() const { JitFrameLayout* JSJitFrameIter::jsFrame() const {

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

@ -12,6 +12,7 @@
#include "jstypes.h" #include "jstypes.h"
#include "jit/JitCode.h" #include "jit/JitCode.h"
#include "jit/MachineState.h"
#include "jit/Snapshots.h" #include "jit/Snapshots.h"
#include "js/ProfilingFrameIterator.h" #include "js/ProfilingFrameIterator.h"
#include "vm/JSFunction.h" #include "vm/JSFunction.h"
@ -403,7 +404,10 @@ class SnapshotIterator {
uintptr_t fromRegister(Register reg) const { return machine_->read(reg); } uintptr_t fromRegister(Register reg) const { return machine_->read(reg); }
bool hasRegister(FloatRegister reg) const { return machine_->has(reg); } bool hasRegister(FloatRegister reg) const { return machine_->has(reg); }
double fromRegister(FloatRegister reg) const { return machine_->read(reg); } template <typename T>
T fromRegister(FloatRegister reg) const {
return machine_->read<T>(reg);
}
// Read an uintptr_t from the stack. // Read an uintptr_t from the stack.
bool hasStack(int32_t offset) const { return true; } bool hasStack(int32_t offset) const { return true; }

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

@ -1627,19 +1627,10 @@ Value SnapshotIterator::allocationValue(const RValueAllocation& alloc,
return NullValue(); return NullValue();
case RValueAllocation::DOUBLE_REG: case RValueAllocation::DOUBLE_REG:
return DoubleValue(fromRegister(alloc.fpuReg())); return DoubleValue(fromRegister<double>(alloc.fpuReg()));
case RValueAllocation::ANY_FLOAT_REG: { case RValueAllocation::ANY_FLOAT_REG:
union { return Float32Value(fromRegister<float>(alloc.fpuReg()));
double d;
float f;
} pun;
MOZ_ASSERT(alloc.fpuReg().isSingle());
pun.d = fromRegister(alloc.fpuReg());
// The register contains the encoding of a float32. We just read
// the bits without making any conversion.
return Float32Value(pun.f);
}
case RValueAllocation::ANY_FLOAT_STACK: case RValueAllocation::ANY_FLOAT_STACK:
return Float32Value(ReadFrameFloat32Slot(fp_, alloc.stackOffset())); return Float32Value(ReadFrameFloat32Slot(fp_, alloc.stackOffset()));
@ -2185,81 +2176,95 @@ bool InlineFrameIterator::isFunctionFrame() const { return !!calleeTemplate_; }
bool InlineFrameIterator::isModuleFrame() const { return script()->module(); } bool InlineFrameIterator::isModuleFrame() const { return script()->module(); }
MachineState MachineState::FromBailout(RegisterDump::GPRArray& regs, uintptr_t* MachineState::SafepointState::addressOfRegister(Register reg) const {
RegisterDump::FPUArray& fpregs) { size_t offset = regs.offsetOfPushedRegister(reg);
MachineState machine;
for (unsigned i = 0; i < Registers::Total; i++) { MOZ_ASSERT((offset % sizeof(uintptr_t)) == 0);
machine.setRegisterLocation(Register::FromCode(i), &regs[i].r); uint32_t index = offset / sizeof(uintptr_t);
}
#ifdef JS_CODEGEN_ARM
float* fbase = (float*)&fpregs[0];
for (unsigned i = 0; i < FloatRegisters::TotalDouble; i++) {
machine.setRegisterLocation(FloatRegister(i, FloatRegister::Double),
&fpregs[i].d);
}
for (unsigned i = 0; i < FloatRegisters::TotalSingle; i++) {
machine.setRegisterLocation(FloatRegister(i, FloatRegister::Single),
(double*)&fbase[i]);
# ifdef ENABLE_WASM_SIMD
# error "More care needed here"
# endif
}
#elif defined(JS_CODEGEN_MIPS32)
for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) {
machine.setRegisterLocation(
FloatRegister::FromIndex(i, FloatRegister::Double), &fpregs[i]);
machine.setRegisterLocation(
FloatRegister::FromIndex(i, FloatRegister::Single), &fpregs[i]);
# ifdef ENABLE_WASM_SIMD
# error "More care needed here"
# endif
}
#elif defined(JS_CODEGEN_MIPS64)
for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) {
machine.setRegisterLocation(FloatRegister(i, FloatRegisters::Double),
&fpregs[i]);
machine.setRegisterLocation(FloatRegister(i, FloatRegisters::Single),
&fpregs[i]);
# ifdef ENABLE_WASM_SIMD
# error "More care needed here"
# endif
}
#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) {
machine.setRegisterLocation(FloatRegister(i, FloatRegisters::Single),
&fpregs[i]);
machine.setRegisterLocation(FloatRegister(i, FloatRegisters::Double),
&fpregs[i]);
machine.setRegisterLocation(FloatRegister(i, FloatRegisters::Simd128),
&fpregs[i]);
}
#elif defined(JS_CODEGEN_ARM64)
for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) {
machine.setRegisterLocation(
FloatRegister(FloatRegisters::Encoding(i), FloatRegisters::Single),
&fpregs[i]);
machine.setRegisterLocation(
FloatRegister(FloatRegisters::Encoding(i), FloatRegisters::Double),
&fpregs[i]);
// No SIMD support in bailouts, SIMD is internal to wasm
}
#elif defined(JS_CODEGEN_LOONG64)
for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) {
machine.setRegisterLocation(
FloatRegister(FloatRegisters::Encoding(i), FloatRegisters::Single),
&fpregs[i]);
machine.setRegisterLocation(
FloatRegister(FloatRegisters::Encoding(i), FloatRegisters::Double),
&fpregs[i]);
}
#elif defined(JS_CODEGEN_NONE) #ifdef DEBUG
MOZ_CRASH(); // Assert correctness with a slower algorithm in debug builds.
#else uint32_t expectedIndex = 0;
# error "Unknown architecture!" bool found = false;
for (GeneralRegisterBackwardIterator iter(regs); iter.more(); ++iter) {
expectedIndex++;
if (*iter == reg) {
found = true;
break;
}
}
MOZ_ASSERT(found);
MOZ_ASSERT(expectedIndex == index);
#endif #endif
return machine;
return spillBase - index;
}
char* MachineState::SafepointState::addressOfRegister(FloatRegister reg) const {
// Note: this could be optimized similar to the GPR case above by implementing
// offsetOfPushedRegister for FloatRegisterSet. Float register sets are
// complicated though and this case is very uncommon: it's only reachable for
// exception bailouts with live float registers.
MOZ_ASSERT(!reg.isSimd128());
char* ptr = floatSpillBase;
for (FloatRegisterBackwardIterator iter(floatRegs); iter.more(); ++iter) {
ptr -= (*iter).size();
for (uint32_t a = 0; a < (*iter).numAlignedAliased(); a++) {
// Only say that registers that actually start here start here.
// e.g. d0 should not start at s1, only at s0.
FloatRegister ftmp = (*iter).alignedAliased(a);
if (ftmp == reg) {
return ptr;
}
}
}
MOZ_CRASH("Invalid register");
}
uintptr_t MachineState::read(Register reg) const {
if (state_.is<BailoutState>()) {
return state_.as<BailoutState>().regs[reg.code()].r;
}
if (state_.is<SafepointState>()) {
uintptr_t* addr = state_.as<SafepointState>().addressOfRegister(reg);
return *addr;
}
MOZ_CRASH("Invalid state");
}
template <typename T>
T MachineState::read(FloatRegister reg) const {
MOZ_ASSERT(reg.size() == sizeof(T));
if (state_.is<BailoutState>()) {
uint32_t offset = reg.getRegisterDumpOffsetInBytes();
MOZ_ASSERT((offset % sizeof(FloatRegisters::RegisterContent)) == 0);
uint32_t index = offset / sizeof(FloatRegisters::RegisterContent);
FloatRegisters::RegisterContent content =
state_.as<BailoutState>().floatRegs[index];
if constexpr (std::is_same_v<T, double>) {
return content.d;
} else {
static_assert(std::is_same_v<T, float>);
return content.s;
}
}
if (state_.is<SafepointState>()) {
char* addr = state_.as<SafepointState>().addressOfRegister(reg);
return *reinterpret_cast<T*>(addr);
}
MOZ_CRASH("Invalid state");
}
void MachineState::write(Register reg, uintptr_t value) const {
if (state_.is<SafepointState>()) {
uintptr_t* addr = state_.as<SafepointState>().addressOfRegister(reg);
*addr = value;
return;
}
MOZ_CRASH("Invalid state");
} }
bool InlineFrameIterator::isConstructing() const { bool InlineFrameIterator::isConstructing() const {

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

@ -13,6 +13,7 @@
#include <stdint.h> #include <stdint.h>
#include "jit/CalleeToken.h" #include "jit/CalleeToken.h"
#include "jit/MachineState.h"
#include "jit/Registers.h" #include "jit/Registers.h"
#include "js/Id.h" #include "js/Id.h"
#include "js/TypeDecls.h" #include "js/TypeDecls.h"

110
js/src/jit/MachineState.h Normal file
Просмотреть файл

@ -0,0 +1,110 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_MachineState_h
#define jit_MachineState_h
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Variant.h"
#include <stdint.h>
#include "jit/Registers.h"
#include "jit/RegisterSets.h"
namespace js::jit {
// Information needed to recover machine register state. This supports two
// different modes:
//
// * Bailouts: all registers are pushed on the stack as part of the bailout
// process, so MachineState simply points to these FPU/GPR arrays.
// See RegisterDump and BailoutStack.
//
// * Safepoints: live registers are pushed on the stack before a VM call, so
// MachineState stores the register sets and a pointer to the stack memory
// where these registers were pushed. This is also used by exception bailouts.
class MOZ_STACK_CLASS MachineState {
struct NullState {};
struct BailoutState {
RegisterDump::FPUArray& floatRegs;
RegisterDump::GPRArray& regs;
BailoutState(RegisterDump::FPUArray& floatRegs,
RegisterDump::GPRArray& regs)
: floatRegs(floatRegs), regs(regs) {}
};
struct SafepointState {
FloatRegisterSet floatRegs;
GeneralRegisterSet regs;
// Pointers to the start of the pushed |floatRegs| and |regs| on the stack.
// This is the value of the stack pointer right before the first register
// was pushed.
char* floatSpillBase;
uintptr_t* spillBase;
SafepointState(const FloatRegisterSet& floatRegs,
const GeneralRegisterSet& regs, char* floatSpillBase,
uintptr_t* spillBase)
: floatRegs(floatRegs),
regs(regs),
floatSpillBase(floatSpillBase),
spillBase(spillBase) {}
uintptr_t* addressOfRegister(Register reg) const;
char* addressOfRegister(FloatRegister reg) const;
};
using State = mozilla::Variant<NullState, BailoutState, SafepointState>;
State state_{NullState()};
public:
MachineState() = default;
MachineState(const MachineState& other) = default;
MachineState& operator=(const MachineState& other) = default;
static MachineState FromBailout(RegisterDump::GPRArray& regs,
RegisterDump::FPUArray& fpregs) {
MachineState res;
res.state_.emplace<BailoutState>(fpregs, regs);
return res;
}
static MachineState FromSafepoint(const FloatRegisterSet& floatRegs,
const GeneralRegisterSet& regs,
char* floatSpillBase,
uintptr_t* spillBase) {
MachineState res;
res.state_.emplace<SafepointState>(floatRegs, regs, floatSpillBase,
spillBase);
return res;
}
bool has(Register reg) const {
if (state_.is<BailoutState>()) {
return true;
}
return state_.as<SafepointState>().regs.hasRegisterIndex(reg);
}
bool has(FloatRegister reg) const {
if (state_.is<BailoutState>()) {
return true;
}
return state_.as<SafepointState>().floatRegs.hasRegisterIndex(reg);
}
uintptr_t read(Register reg) const;
template <typename T>
T read(FloatRegister reg) const;
// Used by moving GCs to update pointers.
void write(Register reg, uintptr_t value) const;
};
} // namespace js::jit
#endif /* jit_MachineState_h */

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

@ -9,6 +9,7 @@
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Variant.h"
#include <new> #include <new>
#include <stddef.h> #include <stddef.h>
@ -372,6 +373,11 @@ class TypedRegisterSet {
return T::ReduceSetForPush(*this); return T::ReduceSetForPush(*this);
} }
uint32_t getPushSizeInBytes() const { return T::GetPushSizeInBytes(*this); } uint32_t getPushSizeInBytes() const { return T::GetPushSizeInBytes(*this); }
size_t offsetOfPushedRegister(RegType reg) const {
MOZ_ASSERT(hasRegisterIndex(reg));
return T::OffsetOfPushedRegister(bits(), reg);
}
}; };
using GeneralRegisterSet = TypedRegisterSet<Register>; using GeneralRegisterSet = TypedRegisterSet<Register>;

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

@ -92,6 +92,13 @@ struct Register {
static uint32_t SetSize(SetType x) { return Codes::SetSize(x); } static uint32_t SetSize(SetType x) { return Codes::SetSize(x); }
static uint32_t FirstBit(SetType x) { return Codes::FirstBit(x); } static uint32_t FirstBit(SetType x) { return Codes::FirstBit(x); }
static uint32_t LastBit(SetType x) { return Codes::LastBit(x); } static uint32_t LastBit(SetType x) { return Codes::LastBit(x); }
// Returns the offset of |reg| on the stack, assuming all registers in |set|
// were pushed in order (e.g. by |PushRegsInMask|). This is computed by
// clearing the lower bits (registers that were pushed later).
static size_t OffsetOfPushedRegister(SetType set, Register reg) {
return sizeof(Codes::RegisterContent) * Codes::SetSize(set >> reg.code());
}
}; };
// Architectures where the stack pointer is not a plain register with a standard // Architectures where the stack pointer is not a plain register with a standard
@ -220,61 +227,6 @@ class RegisterDump {
} }
}; };
// Information needed to recover machine register state. This records the
// location of spilled register and not the content of the spilled
// registers. Thus we can safely assume that this structure is unchanged, even
// if the GC pointers mapped by this structure are relocated.
class MachineState {
mozilla::Array<Registers::RegisterContent*, Registers::Total> regs_;
mozilla::Array<FloatRegisters::RegisterContent*, FloatRegisters::Total>
fpregs_;
public:
MachineState() {
#ifndef JS_CODEGEN_NONE
for (uintptr_t i = 0; i < Registers::Total; i++) {
regs_[i] = reinterpret_cast<Registers::RegisterContent*>(i + 0x100);
}
for (uintptr_t i = 0; i < FloatRegisters::Total; i++) {
fpregs_[i] =
reinterpret_cast<FloatRegisters::RegisterContent*>(i + 0x200);
}
#endif
}
static MachineState FromBailout(RegisterDump::GPRArray& regs,
RegisterDump::FPUArray& fpregs);
void setRegisterLocation(Register reg, uintptr_t* up) {
regs_[reg.code()] = (Registers::RegisterContent*)up;
}
void setRegisterLocation(FloatRegister reg, float* fp) {
MOZ_ASSERT(reg.isSingle());
fpregs_[reg.code()] = (FloatRegisters::RegisterContent*)fp;
}
void setRegisterLocation(FloatRegister reg, double* dp) {
fpregs_[reg.code()] = (FloatRegisters::RegisterContent*)dp;
}
void setRegisterLocation(FloatRegister reg,
FloatRegisters::RegisterContent* rp) {
fpregs_[reg.code()] = rp;
}
bool has(Register reg) const { return regs_[reg.code()] != nullptr; }
bool has(FloatRegister reg) const { return fpregs_[reg.code()] != nullptr; }
uintptr_t read(Register reg) const { return regs_[reg.code()]->r; }
double read(FloatRegister reg) const { return fpregs_[reg.code()]->d; }
void write(Register reg, uintptr_t value) const {
regs_[reg.code()]->r = value;
}
const Registers::RegisterContent* address(Register reg) const {
return regs_[reg.code()];
}
const FloatRegisters::RegisterContent* address(FloatRegister reg) const {
return fpregs_[reg.code()];
}
};
// Class for mapping each register to an offset. // Class for mapping each register to an offset.
class RegisterOffsets { class RegisterOffsets {
mozilla::Array<uint32_t, Registers::Total> offsets_; mozilla::Array<uint32_t, Registers::Total> offsets_;

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

@ -235,6 +235,7 @@ class FloatRegisters {
// Content spilled during bailouts. // Content spilled during bailouts.
union RegisterContent { union RegisterContent {
float s;
double d; double d;
}; };

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

@ -69,6 +69,7 @@ class FloatRegisters {
typedef FPRegisterID Code; typedef FPRegisterID Code;
typedef FPRegisterID Encoding; typedef FPRegisterID Encoding;
union RegisterContent { union RegisterContent {
float s;
double d; double d;
}; };

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

@ -84,6 +84,7 @@ UNIFIED_SOURCES += [
"testNullRoot.cpp", "testNullRoot.cpp",
"testNumberToString.cpp", "testNumberToString.cpp",
"testObjectEmulatingUndefined.cpp", "testObjectEmulatingUndefined.cpp",
"testObjectSwap.cpp",
"testOOM.cpp", "testOOM.cpp",
"testParseJSON.cpp", "testParseJSON.cpp",
"testParserAtom.cpp", "testParserAtom.cpp",

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

@ -0,0 +1,324 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Test JSObject::swap.
*
* This test creates objects from a description of their configuration. Objects
* are given unique property names and values. A list of configurations is
* created and the result of swapping every combination checked.
*/
#include "js/AllocPolicy.h"
#include "js/Vector.h"
#include "jsapi-tests/tests.h"
#include "vm/JSObject-inl.h"
using namespace js;
struct NativeConfig {
uint32_t propCount;
bool inDictionaryMode;
};
struct ProxyConfig {
bool inlineValues;
};
struct ObjectConfig {
const JSClass* clasp;
bool isNative;
bool isPrototype;
union {
NativeConfig native;
ProxyConfig proxy;
};
};
using ObjectConfigVector = Vector<ObjectConfig, 0, SystemAllocPolicy>;
static const JSClass TestProxyClasses[] = {
PROXY_CLASS_DEF("TestProxy", JSCLASS_HAS_RESERVED_SLOTS(1 /* Min */)),
PROXY_CLASS_DEF("TestProxy", JSCLASS_HAS_RESERVED_SLOTS(2)),
PROXY_CLASS_DEF("TestProxy", JSCLASS_HAS_RESERVED_SLOTS(7)),
PROXY_CLASS_DEF("TestProxy", JSCLASS_HAS_RESERVED_SLOTS(8)),
PROXY_CLASS_DEF("TestProxy", JSCLASS_HAS_RESERVED_SLOTS(14 /* Max */))};
static const JSClass TestDOMClasses[] = {
{"TestDOMObject", JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(0)},
{"TestDOMObject", JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(1)},
{"TestDOMObject", JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2)},
{"TestDOMObject", JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(7)},
{"TestDOMObject", JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(8)},
{"TestDOMObject", JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(20)}};
static const uint32_t TestPropertyCounts[] = {0, 1, 2, 7, 8, 20};
static bool Verbose = false;
class DummyProxyHandler final : public ForwardingProxyHandler {
public:
static const DummyProxyHandler singleton;
static const char family;
constexpr DummyProxyHandler() : ForwardingProxyHandler(&family) {}
};
const DummyProxyHandler DummyProxyHandler::singleton;
const char DummyProxyHandler::family = 0;
BEGIN_TEST(testObjectSwap) {
ObjectConfigVector objectConfigs = CreateObjectConfigs();
for (const ObjectConfig& config1 : objectConfigs) {
for (const ObjectConfig& config2 : objectConfigs) {
uint32_t id1;
RootedObject obj1(cx, CreateObject(config1, &id1));
CHECK(obj1);
uint32_t id2;
RootedObject obj2(cx, CreateObject(config2, &id2));
CHECK(obj2);
if (Verbose) {
fprintf(stderr, "Swap %p and %p\n", obj1.get(), obj2.get());
}
{
AutoEnterOOMUnsafeRegion oomUnsafe;
JSObject::swap(cx, obj1, obj2, oomUnsafe);
}
CHECK(CheckObject(obj1, config2, id2));
CHECK(CheckObject(obj2, config1, id1));
if (Verbose) {
fprintf(stderr, "\n");
}
}
// JSObject::swap can suppress GC so ensure we clean up occasionally.
JS_GC(cx);
}
return true;
}
ObjectConfigVector CreateObjectConfigs() {
ObjectConfigVector configs;
ObjectConfig config;
config.isNative = true;
config.native = NativeConfig{0, false};
for (const JSClass& jsClass : TestDOMClasses) {
config.clasp = &jsClass;
for (uint32_t propCount : TestPropertyCounts) {
config.native.propCount = propCount;
for (bool inDictionaryMode : {false, true}) {
if (inDictionaryMode && propCount == 0) {
continue;
}
config.native.inDictionaryMode = inDictionaryMode;
MOZ_RELEASE_ASSERT(configs.append(config));
}
}
}
config.isNative = false;
config.proxy = ProxyConfig{false};
for (const JSClass& jsClass : TestProxyClasses) {
config.clasp = &jsClass;
for (bool inlineValues : {false, true}) {
config.proxy.inlineValues = inlineValues;
MOZ_RELEASE_ASSERT(configs.append(config));
}
}
return configs;
}
// Counter used to give slots and property names unique values.
uint32_t nextId = 0;
JSObject* CreateObject(const ObjectConfig& config, uint32_t* idOut) {
*idOut = nextId;
return config.isNative ? CreateNativeObject(config) : CreateProxy(config);
}
JSObject* CreateNativeObject(const ObjectConfig& config) {
MOZ_ASSERT(config.isNative);
RootedNativeObject obj(
cx, NewBuiltinClassInstance(cx, config.clasp, TenuredObject));
if (!obj) {
return nullptr;
}
for (uint32_t i = 0; i < JSCLASS_RESERVED_SLOTS(config.clasp); i++) {
JS::SetReservedSlot(obj, i, Int32Value(nextId++));
}
if (config.native.inDictionaryMode) {
// Put object in dictionary mode by defining a non-last property and
// deleting it later.
MOZ_RELEASE_ASSERT(config.native.propCount != 0);
if (!JS_DefineProperty(cx, obj, "dummy", 0, JSPROP_ENUMERATE)) {
return nullptr;
}
}
for (uint32_t i = 0; i < config.native.propCount; i++) {
RootedId name(cx, CreatePropName(nextId++));
if (name.isVoid()) {
return nullptr;
}
if (!JS_DefinePropertyById(cx, obj, name, nextId++, JSPROP_ENUMERATE)) {
return nullptr;
}
}
if (config.native.inDictionaryMode) {
JS::ObjectOpResult result;
JS_DeleteProperty(cx, obj, "dummy", result);
MOZ_RELEASE_ASSERT(result.ok());
}
MOZ_RELEASE_ASSERT(obj->inDictionaryMode() == config.native.inDictionaryMode);
return obj;
}
JSObject* CreateProxy(const ObjectConfig& config) {
RootedValue priv(cx, Int32Value(nextId++));
RootedObject expando(cx, NewPlainObject(cx));
RootedValue expandoId(cx, Int32Value(nextId++));
if (!expando || !JS_SetProperty(cx, expando, "id", expandoId)) {
return nullptr;
}
ProxyOptions options;
options.setClass(config.clasp);
options.setLazyProto(true);
RootedObject obj(cx, NewProxyObject(cx, &DummyProxyHandler::singleton, priv,
nullptr, options));
if (!obj) {
return nullptr;
}
Rooted<ProxyObject*> proxy(cx, &obj->as<ProxyObject>());
proxy->setExpando(expando);
for (uint32_t i = 0; i < JSCLASS_RESERVED_SLOTS(config.clasp); i++) {
JS::SetReservedSlot(proxy, i, Int32Value(nextId++));
}
if (!config.proxy.inlineValues) {
// To create a proxy with non-inline values we must swap the proxy with an
// object with a different size.
RootedObject dummy(
cx, NewBuiltinClassInstance(cx, &TestDOMClasses[0], TenuredObject));
if (!dummy) {
return nullptr;
}
AutoEnterOOMUnsafeRegion oomUnsafe;
JSObject::swap(cx, obj, dummy, oomUnsafe);
proxy = &dummy->as<ProxyObject>();
}
MOZ_RELEASE_ASSERT(proxy->usingInlineValueArray() ==
config.proxy.inlineValues);
return proxy;
}
bool CheckObject(HandleObject obj, const ObjectConfig& config, uint32_t id) {
CHECK(obj->is<NativeObject>() == config.isNative);
CHECK(obj->getClass() == config.clasp);
uint32_t reservedSlots = JSCLASS_RESERVED_SLOTS(config.clasp);
if (Verbose) {
fprintf(stderr, "Check %p is a %s object with %u reserved slots", obj.get(),
config.isNative ? "native" : "proxy", reservedSlots);
if (config.isNative) {
fprintf(stderr, ", %u properties and %s in dictionary mode",
config.native.propCount,
config.native.inDictionaryMode ? "is" : "is not");
} else {
fprintf(stderr, " with %s values",
config.proxy.inlineValues ? "inline" : "out-of-line");
}
fprintf(stderr, "\n");
}
if (!config.isNative) {
CHECK(GetProxyPrivate(obj) == Int32Value(id++));
Value expandoValue = GetProxyExpando(obj);
CHECK(expandoValue.isObject());
RootedObject expando(cx, &expandoValue.toObject());
RootedValue expandoId(cx);
JS_GetProperty(cx, expando, "id", &expandoId);
CHECK(expandoId == Int32Value(id++));
}
for (uint32_t i = 0; i < reservedSlots; i++) {
CHECK(JS::GetReservedSlot(obj, i) == Int32Value(id++));
}
if (config.isNative) {
NativeObject* nobj = &obj->as<NativeObject>();
uint32_t propCount = GetPropertyCount(nobj);
CHECK(propCount == config.native.propCount);
for (uint32_t i = 0; i < config.native.propCount; i++) {
RootedId name(cx, CreatePropName(id++));
CHECK(!name.isVoid());
RootedValue value(cx);
CHECK(JS_GetPropertyById(cx, obj, name, &value));
CHECK(value == Int32Value(id++));
}
}
return true;
}
uint32_t GetPropertyCount(NativeObject* obj) {
uint32_t count = 0;
for (ShapePropertyIter<NoGC> iter(obj->shape()); !iter.done(); iter++) {
count++;
}
return count;
}
jsid CreatePropName(uint32_t id) {
char buffer[32];
sprintf(buffer, "prop%u", id);
RootedString atom(cx, JS_AtomizeString(cx, buffer));
if (!atom) {
return jsid::Void();
}
return jsid::NonIntAtom(atom);
}
END_TEST(testObjectSwap)

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

@ -1032,14 +1032,25 @@ JS_PUBLIC_API bool JS_InitializePropertiesFromCompatibleNativeObject(
cx, dst.as<NativeObject>(), src.as<NativeObject>()); cx, dst.as<NativeObject>(), src.as<NativeObject>());
} }
void NativeObject::freeDynamicSlotsAfterSwap(NativeObject* old) {
if (!hasDynamicSlots()) {
return;
}
ObjectSlots* slotsHeader = getSlotsHeader();
size_t size = ObjectSlots::allocSize(slotsHeader->capacity());
zone()->removeCellMemory(old, size, MemoryUse::ObjectSlots);
js_free(slotsHeader);
setEmptyDynamicSlots(0);
}
/* static */ /* static */
bool NativeObject::fillInAfterSwap(JSContext* cx, HandleNativeObject obj, bool NativeObject::fillInAfterSwap(JSContext* cx, HandleNativeObject obj,
NativeObject* old,
HandleValueVector values) { HandleValueVector values) {
// This object has just been swapped with some other object, and its shape // This object has just been swapped with some other object, and its shape
// no longer reflects its allocated size. Correct this information and // no longer reflects its allocated size. Correct this information and
// fill the slots in with the specified values. // fill the slots in with the specified values.
MOZ_ASSERT(obj->slotSpan() == values.length()); MOZ_ASSERT_IF(!obj->inDictionaryMode(), obj->slotSpan() == values.length());
MOZ_ASSERT(!IsInsideNursery(obj)); MOZ_ASSERT(!IsInsideNursery(obj));
// Make sure the shape's numFixedSlots() is correct. // Make sure the shape's numFixedSlots() is correct.
@ -1052,16 +1063,7 @@ bool NativeObject::fillInAfterSwap(JSContext* cx, HandleNativeObject obj,
} }
uint32_t oldDictionarySlotSpan = uint32_t oldDictionarySlotSpan =
obj->inDictionaryMode() ? obj->dictionaryModeSlotSpan() : 0; obj->inDictionaryMode() ? values.length() : 0;
Zone* zone = obj->zone();
if (obj->hasDynamicSlots()) {
ObjectSlots* slotsHeader = obj->getSlotsHeader();
size_t size = ObjectSlots::allocSize(slotsHeader->capacity());
zone->removeCellMemory(old, size, MemoryUse::ObjectSlots);
js_free(slotsHeader);
obj->setEmptyDynamicSlots(0);
}
size_t ndynamic = size_t ndynamic =
calculateDynamicSlots(nfixed, values.length(), obj->getClass()); calculateDynamicSlots(nfixed, values.length(), obj->getClass());
@ -1171,7 +1173,8 @@ void JSObject::swap(JSContext* cx, HandleObject a, HandleObject b,
MOZ_ASSERT(cx->compartment() == a->compartment()); MOZ_ASSERT(cx->compartment() == a->compartment());
// Only certain types of objects are allowed to be swapped. This allows the // Only certain types of objects are allowed to be swapped. This allows the
// JITs to better optimize objects that can never swap. // JITs to better optimize objects that can never swap and rules out most
// builtin objects that have special behaviour.
MOZ_RELEASE_ASSERT(js::ObjectMayBeSwapped(a)); MOZ_RELEASE_ASSERT(js::ObjectMayBeSwapped(a));
MOZ_RELEASE_ASSERT(js::ObjectMayBeSwapped(b)); MOZ_RELEASE_ASSERT(js::ObjectMayBeSwapped(b));
@ -1193,22 +1196,6 @@ void JSObject::swap(JSContext* cx, HandleObject a, HandleObject b,
unsigned r = NotifyGCPreSwap(a, b); unsigned r = NotifyGCPreSwap(a, b);
// Do the fundamental swapping of the contents of two objects.
MOZ_ASSERT(a->compartment() == b->compartment());
MOZ_ASSERT(a->is<JSFunction>() == b->is<JSFunction>());
// Don't try to swap functions with different sizes.
MOZ_ASSERT_IF(a->is<JSFunction>(),
a->tenuredSizeOfThis() == b->tenuredSizeOfThis());
// Watch for oddball objects that have special organizational issues and
// can't be swapped.
MOZ_ASSERT(!a->is<RegExpObject>() && !b->is<RegExpObject>());
MOZ_ASSERT(!a->is<ArrayObject>() && !b->is<ArrayObject>());
MOZ_ASSERT(!a->is<ArrayBufferObject>() && !b->is<ArrayBufferObject>());
MOZ_ASSERT(!a->is<TypedArrayObject>() && !b->is<TypedArrayObject>());
MOZ_ASSERT(!a->is<TypedObject>() && !b->is<TypedObject>());
// Don't swap objects that may currently be participating in shape // Don't swap objects that may currently be participating in shape
// teleporting optimizations. // teleporting optimizations.
// //
@ -1239,8 +1226,7 @@ void JSObject::swap(JSContext* cx, HandleObject a, HandleObject b,
size_t size = a->tenuredSizeOfThis(); size_t size = a->tenuredSizeOfThis();
char tmp[mozilla::tl::Max<sizeof(JSFunction), char tmp[sizeof(JSObject_Slots16)];
sizeof(JSObject_Slots16)>::value];
MOZ_ASSERT(size <= sizeof(tmp)); MOZ_ASSERT(size <= sizeof(tmp));
js_memcpy(tmp, a, size); js_memcpy(tmp, a, size);
@ -1307,15 +1293,23 @@ void JSObject::swap(JSContext* cx, HandleObject a, HandleObject b,
js_memcpy(b, &tmp, sizeof tmp); js_memcpy(b, &tmp, sizeof tmp);
if (na) { if (na) {
if (!NativeObject::fillInAfterSwap(cx, b.as<NativeObject>(), na, avals)) { b.as<NativeObject>()->freeDynamicSlotsAfterSwap(na);
}
if (nb) {
a.as<NativeObject>()->freeDynamicSlotsAfterSwap(nb);
}
if (na) {
if (!NativeObject::fillInAfterSwap(cx, b.as<NativeObject>(), avals)) {
oomUnsafe.crash("fillInAfterSwap"); oomUnsafe.crash("fillInAfterSwap");
} }
} }
if (nb) { if (nb) {
if (!NativeObject::fillInAfterSwap(cx, a.as<NativeObject>(), nb, bvals)) { if (!NativeObject::fillInAfterSwap(cx, a.as<NativeObject>(), bvals)) {
oomUnsafe.crash("fillInAfterSwap"); oomUnsafe.crash("fillInAfterSwap");
} }
} }
if (aIsProxyWithInlineValues) { if (aIsProxyWithInlineValues) {
if (!b->as<ProxyObject>().initExternalValueArrayAfterSwap(cx, avals)) { if (!b->as<ProxyObject>().initExternalValueArrayAfterSwap(cx, avals)) {
oomUnsafe.crash("initExternalValueArray"); oomUnsafe.crash("initExternalValueArray");

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

@ -997,9 +997,9 @@ class NativeObject : public JSObject {
HandleNativeObject obj, HandleNativeObject obj,
uint32_t nfixed); uint32_t nfixed);
void freeDynamicSlotsAfterSwap(NativeObject* old);
[[nodiscard]] static bool fillInAfterSwap(JSContext* cx, [[nodiscard]] static bool fillInAfterSwap(JSContext* cx,
HandleNativeObject obj, HandleNativeObject obj,
NativeObject* old,
HandleValueVector values); HandleValueVector values);
public: public:

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

@ -97,8 +97,6 @@ bool js::tuple_with(JSContext* cx, unsigned argc, Value* vp) {
Rooted<TupleType*> tuple(cx, &(*maybeTuple)); Rooted<TupleType*> tuple(cx, &(*maybeTuple));
/* Step 2. */ /* Step 2. */
HeapSlotArray t = tuple->getDenseElements();
uint64_t length = tuple->getDenseInitializedLength(); uint64_t length = tuple->getDenseInitializedLength();
TupleType* list = TupleType::createUninitialized(cx, length); TupleType* list = TupleType::createUninitialized(cx, length);
if (!list) { if (!list) {
@ -126,10 +124,11 @@ bool js::tuple_with(JSContext* cx, unsigned argc, Value* vp) {
/* Step 7 */ /* Step 7 */
uint64_t before = index; uint64_t before = index;
uint64_t after = length - index - 1; uint64_t after = length - index - 1;
list->copyDenseElements(0, t, before); list->copyDenseElements(0, tuple->getDenseElements(), before);
list->setDenseInitializedLength(index + 1); list->setDenseInitializedLength(index + 1);
list->initDenseElement(index, value); list->initDenseElement(index, value);
list->copyDenseElements(index + 1, t + uint32_t(index + 1), after); list->copyDenseElements(
index + 1, tuple->getDenseElements() + uint32_t(index + 1), after);
list->setDenseInitializedLength(length); list->setDenseInitializedLength(length);
list->finishInitialization(cx); list->finishInitialization(cx);
/* Step 8 */ /* Step 8 */

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

@ -4,12 +4,19 @@
<title>Form Autofill Test: Credit Card</title> <title>Form Autofill Test: Credit Card</title>
</head> </head>
<body> <body>
<form> <form id="form1">
<input autocomplete="cc-name" id="name"> <input autocomplete="cc-name" id="name">
<input autocomplete="cc-number" id="number"> <input autocomplete="cc-number" id="number">
<input autocomplete="cc-exp-month" id="expMonth"> <input autocomplete="cc-exp-month" id="expMonth">
<input autocomplete="cc-exp-year" id="expYear"> <input autocomplete="cc-exp-year" id="expYear">
<input type="submit" value="Submit"> <input type="submit" value="Submit">
</form> </form>
<!-- form2 uses a single expiration date field -->
<form id="form2">
<input autocomplete="cc-name" id="name">
<input autocomplete="cc-number" id="number">
<input autocomplete="cc-exp" id="exp">
<input type="submit" value="Submit">
</form>
</body> </body>
</html> </html>

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

@ -766,6 +766,79 @@ class AutocompleteTest : BaseSessionTest() {
sessionRule.waitForResult(saveHandled) sessionRule.waitForResult(saveHandled)
} }
@Test
fun creditCardSaveAcceptForm2() {
// TODO Bug 1764709: Right now we fill normalized credit card data to match
// the expected result.
val ccName = "MyCard"
val ccNumber = "5105105105105100"
val ccExpMonth = "6"
val ccExpYear = "2024"
mainSession.loadTestPath(CC_FORM_HTML_PATH)
mainSession.waitForPageStop()
val saveHandled = GeckoResult<Void>()
sessionRule.delegateUntilTestEnd(object : StorageDelegate {
@AssertCalled
override fun onCreditCardSave(creditCard: CreditCard) {
assertThat("Credit card name should match", creditCard.name, equalTo(ccName))
assertThat("Credit card number should match", creditCard.number, equalTo(ccNumber))
assertThat("Credit card expiration month should match", creditCard.expirationMonth, equalTo(ccExpMonth))
assertThat("Credit card expiration year should match", creditCard.expirationYear, equalTo(ccExpYear))
saveHandled.complete(null)
}
})
sessionRule.delegateDuringNextWait(object : PromptDelegate {
@AssertCalled
override fun onCreditCardSave(
session: GeckoSession,
request: AutocompleteRequest<CreditCardSaveOption>)
: GeckoResult<PromptDelegate.PromptResponse> {
assertThat("Session should not be null", session, notNullValue())
val option = request.options[0]
val cc = option.value
assertThat("Credit card should not be null", cc, notNullValue())
assertThat(
"Credit card name should match",
cc.name,
equalTo(ccName))
assertThat(
"Credit card number should match",
cc.number,
equalTo(ccNumber))
assertThat(
"Credit card expiration month should match",
cc.expirationMonth,
equalTo(ccExpMonth))
assertThat(
"Credit card expiration year should match",
cc.expirationYear,
equalTo(ccExpYear))
return GeckoResult.fromValue(request.confirm(option))
}
})
// Enter the card values
mainSession.evaluateJS("document.querySelector('#form2 #name').value = '${ccName}'")
mainSession.evaluateJS("document.querySelector('#form2 #name').focus()")
mainSession.evaluateJS("document.querySelector('#form2 #number').value = '${ccNumber}'")
mainSession.evaluateJS("document.querySelector('#form2 #number').focus()")
mainSession.evaluateJS("document.querySelector('#form2 #exp').value = '${ccExpMonth}/${ccExpYear}'")
mainSession.evaluateJS("document.querySelector('#form2 #exp').focus()")
// Submit the form
mainSession.evaluateJS("document.querySelector('#form2').requestSubmit()")
sessionRule.waitForResult(saveHandled)
}
@Test @Test
fun creditCardSaveDismiss() { fun creditCardSaveDismiss() {
val ccName = "MyCard" val ccName = "MyCard"

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

@ -1151,4 +1151,4 @@ to allow adding gecko profiler markers.
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport(android.content.Context,android.os.Bundle,java.lang.String) [65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport(android.content.Context,android.os.Bundle,java.lang.String)
[65.25]: {{javadoc_uri}}/GeckoResult.html [65.25]: {{javadoc_uri}}/GeckoResult.html
[api-version]: 24b60ce96bd68c81a55110bd1a3c57442dd8c65f [api-version]: c9f91f7e909c6c71adca2ea333f92af6ff3af054

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

@ -258,8 +258,8 @@ class CreditCard {
version: aObj.version, version: aObj.version,
name: aObj["cc-name"], name: aObj["cc-name"],
number: aObj["cc-number"], number: aObj["cc-number"],
expMonth: aObj["cc-exp-month"], expMonth: aObj["cc-exp-month"]?.toString(),
expYear: aObj["cc-exp-year"], expYear: aObj["cc-exp-year"]?.toString(),
type: aObj["cc-type"], type: aObj["cc-type"],
guid: aObj.guid, guid: aObj.guid,
timeCreated: aObj.timeCreated, timeCreated: aObj.timeCreated,

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

@ -12798,12 +12798,13 @@ eu.meteorapp.com
co.pl co.pl
// Microsoft Corporation : http://microsoft.com // Microsoft Corporation : http://microsoft.com
// Submitted by Mitch Webster <miwebst@microsoft.com> // Submitted by Public Suffix List Admin <msftpsladmin@microsoft.com>
*.azurecontainer.io *.azurecontainer.io
azurewebsites.net azurewebsites.net
azure-mobile.net azure-mobile.net
cloudapp.net cloudapp.net
azurestaticapps.net azurestaticapps.net
1.azurestaticapps.net
centralus.azurestaticapps.net centralus.azurestaticapps.net
eastasia.azurestaticapps.net eastasia.azurestaticapps.net
eastus2.azurestaticapps.net eastus2.azurestaticapps.net

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

@ -0,0 +1 @@
pypi:boto3==1.4.4

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

@ -190,12 +190,6 @@ class NetworkObserver {
} }
_onRequest(channel, topic) { _onRequest(channel, topic) {
try {
channel.QueryInterface(Ci.nsIHttpChannel);
} catch (ex) {
return;
}
const httpChannel = channel.QueryInterface(Ci.nsIHttpChannel); const httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
const loadContext = getLoadContext(httpChannel); const loadContext = getLoadContext(httpChannel);
const browser = loadContext?.topFrameElement; const browser = loadContext?.topFrameElement;

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

@ -952,6 +952,7 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
{ "google.tn", true, false, false, -1, &kPinset_google_root_pems }, { "google.tn", true, false, false, -1, &kPinset_google_root_pems },
{ "google.to", true, false, false, -1, &kPinset_google_root_pems }, { "google.to", true, false, false, -1, &kPinset_google_root_pems },
{ "google.tt", true, false, false, -1, &kPinset_google_root_pems }, { "google.tt", true, false, false, -1, &kPinset_google_root_pems },
{ "google.ua", true, false, false, -1, &kPinset_google_root_pems },
{ "google.us", true, false, false, -1, &kPinset_google_root_pems }, { "google.us", true, false, false, -1, &kPinset_google_root_pems },
{ "google.uz", true, false, false, -1, &kPinset_google_root_pems }, { "google.uz", true, false, false, -1, &kPinset_google_root_pems },
{ "google.vg", true, false, false, -1, &kPinset_google_root_pems }, { "google.vg", true, false, false, -1, &kPinset_google_root_pems },
@ -1130,8 +1131,8 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
{ "zh.search.yahoo.com", false, true, false, -1, &kPinset_yahoo }, { "zh.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
}; };
// Pinning Preload List Length = 495; // Pinning Preload List Length = 496;
static const int32_t kUnknownId = -1; static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1658141463432000); static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1658401159656000);

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

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

@ -1,5 +1,36 @@
{ {
"data": [ "data": [
{
"stash": {
"blocked": [
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.8.2",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.8.1",
"{c4c9b8f3-3c9b-41c2-827e-569e556fcb8a}:1.0.0.7",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.9.0",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.8.3d",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.2d",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.1d",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.9.0d",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.3d",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.7f",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.5d",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.0d",
"{c4c9b8f3-3c9b-41c2-827e-569e556fcb8a}:1.0.0.0",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.8.0",
"{c4c9b8f3-3c9b-41c2-827e-569e556fcb8a}:1.0.0.5",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.4d",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.9.1",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.6d",
"{d619d6d4-d562-4ec3-a62b-9246e1553b42}:1.7d"
],
"unblocked": []
},
"schema": 1649691602593,
"key_format": "{guid}:{version}",
"stash_time": 1649788507913,
"id": "9f608cfe-480d-4ec7-b692-0b26cb3ac3c3",
"last_modified": 1649788697027
},
{ {
"stash": { "stash": {
"blocked": [ "blocked": [

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

@ -10620,114 +10620,6 @@
"id": "bf7893da-0baf-4aae-8bfc-282641a4dcff", "id": "bf7893da-0baf-4aae-8bfc-282641a4dcff",
"last_modified": 1640876333340 "last_modified": 1640876333340
}, },
{
"schema": 1640787170249,
"derHash": "yX42zr8VgKsb2tYcHVOwXHWBnoXZNyFL5oTIWbItReA=",
"subject": "CN=vTrus ECC DV SSL CA,O=iTrusChina Co.\\,Ltd.,C=CN",
"subjectDN": "MEkxCzAJBgNVBAYTAkNOMRwwGgYDVQQKExNpVHJ1c0NoaW5hIENvLixMdGQuMRwwGgYDVQQDExN2VHJ1cyBFQ0MgRFYgU1NMIENB",
"whitelist": false,
"attachment": {
"hash": "ef4575a1abe7f8492e2e0d89dbbf6e80b196e4b6dccd8bf4e48700ed4bcfec4a",
"size": 1183,
"filename": "gJ1It3GyfR5y0xbHIcRJPwjI6151kRqrGSR_W5v6jek=.pem",
"location": "security-state-staging/intermediates/3a24be71-e5b8-4645-ba9c-4fabca8847d3.pem",
"mimetype": "application/x-pem-file"
},
"pubKeyHash": "gJ1It3GyfR5y0xbHIcRJPwjI6151kRqrGSR/W5v6jek=",
"crlite_enrolled": false,
"id": "e296d20d-073e-4563-afc7-6e55d5946b3e",
"last_modified": 1640789973594
},
{
"schema": 1640787171474,
"derHash": "I1ge8ZId8vkpDboNTU9IqX+Yrq77XjNQs/cFgujNvng=",
"subject": "CN=vTrus ECC OV SSL CA,O=iTrusChina Co.\\,Ltd.,C=CN",
"subjectDN": "MEkxCzAJBgNVBAYTAkNOMRwwGgYDVQQKExNpVHJ1c0NoaW5hIENvLixMdGQuMRwwGgYDVQQDExN2VHJ1cyBFQ0MgT1YgU1NMIENB",
"whitelist": false,
"attachment": {
"hash": "f5e788b19092bef358268ca50c1012469e23bacaec6b8968235a7fde8315fae3",
"size": 1183,
"filename": "atwg6ejpADR_jBbKnuSFzeAuVeHiQKJdUl2HSR0gLmU=.pem",
"location": "security-state-staging/intermediates/c703ae6f-ec40-48dd-a708-54774a3fa005.pem",
"mimetype": "application/x-pem-file"
},
"pubKeyHash": "atwg6ejpADR/jBbKnuSFzeAuVeHiQKJdUl2HSR0gLmU=",
"crlite_enrolled": false,
"id": "2224e522-7889-4a09-b2de-d963d7e65cac",
"last_modified": 1640789973587
},
{
"schema": 1640787172648,
"derHash": "vTDA0eesuD78T19sYvjzpXm6snUnr65mbGlsOoZxdfE=",
"subject": "CN=vTrus ECC EV SSL CA,O=iTrusChina Co.\\,Ltd.,C=CN",
"subjectDN": "MEkxCzAJBgNVBAYTAkNOMRwwGgYDVQQKExNpVHJ1c0NoaW5hIENvLixMdGQuMRwwGgYDVQQDExN2VHJ1cyBFQ0MgRVYgU1NMIENB",
"whitelist": false,
"attachment": {
"hash": "5efe51a26c5280ef3910747587a1258ee032a5cd4592afff27a55faecd152eec",
"size": 1183,
"filename": "7k0rYa-qry4wDaWSSycBwDVQALkMXBvBWeWHCjNIjTA=.pem",
"location": "security-state-staging/intermediates/1999d48b-3e07-48cf-bf4a-7656a1b29a53.pem",
"mimetype": "application/x-pem-file"
},
"pubKeyHash": "7k0rYa+qry4wDaWSSycBwDVQALkMXBvBWeWHCjNIjTA=",
"crlite_enrolled": false,
"id": "72729739-8817-4cc4-a6d6-e50b179466d3",
"last_modified": 1640789973580
},
{
"schema": 1640787173887,
"derHash": "86ptcSoV9j+DUIBJedtUJBmmGysdIudWxBer/o10o8o=",
"subject": "CN=vTrus EV SSL CA,O=iTrusChina Co.\\,Ltd.,C=CN",
"subjectDN": "MEUxCzAJBgNVBAYTAkNOMRwwGgYDVQQKExNpVHJ1c0NoaW5hIENvLixMdGQuMRgwFgYDVQQDEw92VHJ1cyBFViBTU0wgQ0E=",
"whitelist": false,
"attachment": {
"hash": "01cb1f5c741d941d11e0575e8235a3df364dc571bdd452841c23bd28e35016d3",
"size": 2003,
"filename": "tHoUHCrraSrjkHaUbZGcxRVrjSHn8i6s8_iI6HHC6Ok=.pem",
"location": "security-state-staging/intermediates/bfdb2a93-b869-4473-9246-b6dae2c91caf.pem",
"mimetype": "application/x-pem-file"
},
"pubKeyHash": "tHoUHCrraSrjkHaUbZGcxRVrjSHn8i6s8/iI6HHC6Ok=",
"crlite_enrolled": false,
"id": "cd2c0c6f-fc8b-45b0-aa2b-15777338beb9",
"last_modified": 1640789973573
},
{
"schema": 1640787175080,
"derHash": "X36LSowRuvLL5kWbR/221QwChcSplPTu8v5RYKoKt4o=",
"subject": "CN=vTrus DV SSL CA,O=iTrusChina Co.\\,Ltd.,C=CN",
"subjectDN": "MEUxCzAJBgNVBAYTAkNOMRwwGgYDVQQKExNpVHJ1c0NoaW5hIENvLixMdGQuMRgwFgYDVQQDEw92VHJ1cyBEViBTU0wgQ0E=",
"whitelist": false,
"attachment": {
"hash": "02cc66488a37100af024e6807b42f3d0fcca6bac68c70036847c21859c2e0f9f",
"size": 2003,
"filename": "75pE_IZKhqgviWzR4qTd2zPqnbH6f4VSS4OvPeBjEjQ=.pem",
"location": "security-state-staging/intermediates/c817af85-7cff-40a6-960f-7cb18bce787c.pem",
"mimetype": "application/x-pem-file"
},
"pubKeyHash": "75pE/IZKhqgviWzR4qTd2zPqnbH6f4VSS4OvPeBjEjQ=",
"crlite_enrolled": false,
"id": "e3914740-82e4-4c6d-8237-d4b4be3ea8a3",
"last_modified": 1640789973567
},
{
"schema": 1640787176349,
"derHash": "pTtcm7WtknA9xPd/5k2ROiOf03IHOkjiegSBWApWN8Q=",
"subject": "CN=vTrus OV SSL CA,O=iTrusChina Co.\\,Ltd.,C=CN",
"subjectDN": "MEUxCzAJBgNVBAYTAkNOMRwwGgYDVQQKExNpVHJ1c0NoaW5hIENvLixMdGQuMRgwFgYDVQQDEw92VHJ1cyBPViBTU0wgQ0E=",
"whitelist": false,
"attachment": {
"hash": "4edc5bd03aede64fb9a23473cb654b555c969e2142043a263b82aeb3a59fe874",
"size": 2003,
"filename": "_AQe5lWT9xIwgAiIHcAT-pRj70-ckw8xE4qArEfIyd0=.pem",
"location": "security-state-staging/intermediates/0539c864-9413-4569-b1db-013de19c4878.pem",
"mimetype": "application/x-pem-file"
},
"pubKeyHash": "/AQe5lWT9xIwgAiIHcAT+pRj70+ckw8xE4qArEfIyd0=",
"crlite_enrolled": false,
"id": "a1713f8e-1fc7-4247-88b6-891789cca9d7",
"last_modified": 1640789973559
},
{ {
"schema": 1640574023025, "schema": 1640574023025,
"derHash": "vrUcj0UkJrK55nL33R7qSzPWw49MoqlpVs4kvQWww40=", "derHash": "vrUcj0UkJrK55nL33R7qSzPWw49MoqlpVs4kvQWww40=",

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

@ -418,7 +418,7 @@ dump-syms:
fetch: fetch:
type: git type: git
repo: https://github.com/mozilla/dump_syms/ repo: https://github.com/mozilla/dump_syms/
revision: bf7f6bd855eb6ecb233b52bfa7b2c975b7026540 revision: c558ad1824b247e147dcc45ec105588883e379fb
rust-minidump: rust-minidump:
description: rust-minidump 0.10.4-prerelease source code (for minidump-stackwalk) description: rust-minidump 0.10.4-prerelease source code (for minidump-stackwalk)

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

@ -32,7 +32,7 @@ job-template:
max-run-time: 600 max-run-time: 600
run: run:
using: mach using: mach
mach: {artifact-reference: "python build/upload_generated_sources.py <build/public/build/target.generated-files.tar.gz>"} mach: {artifact-reference: "python --virtualenv upload-generated-sources build/upload_generated_sources.py <build/public/build/target.generated-files.tar.gz>"}
sparse-profile: upload-generated-sources sparse-profile: upload-generated-sources
scopes: scopes:
- secrets:get:project/releng/gecko/build/level-{level}/gecko-generated-sources-upload - secrets:get:project/releng/gecko/build/level-{level}/gecko-generated-sources-upload

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

@ -161,7 +161,7 @@ class WebPlatformTestsRunnerSetup(MozbuildObject):
def kwargs_wptrun(self, kwargs): def kwargs_wptrun(self, kwargs):
"""Setup kwargs for wpt-run which is only used for non-gecko browser products""" """Setup kwargs for wpt-run which is only used for non-gecko browser products"""
from tools.wpt import run from tools.wpt import run, virtualenv
kwargs = self.kwargs_common(kwargs) kwargs = self.kwargs_common(kwargs)
@ -189,7 +189,7 @@ class WebPlatformTestsRunnerSetup(MozbuildObject):
path, require_hashes=False path, require_hashes=False
) )
venv = run.virtualenv.Virtualenv( venv = virtualenv.Virtualenv(
self.virtualenv_manager.virtualenv_root, skip_virtualenv_setup=True self.virtualenv_manager.virtualenv_root, skip_virtualenv_setup=True
) )
try: try:

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

@ -5,12 +5,16 @@ import pytest
async def new_tab(bidi_session, current_session): async def new_tab(bidi_session, current_session):
# Open and focus a new tab to run the test in a foreground tab. # Open and focus a new tab to run the test in a foreground tab.
context_id = current_session.new_window(type_hint="tab") context_id = current_session.new_window(type_hint="tab")
initial_window = current_session.window_handle
current_session.window_handle = context_id current_session.window_handle = context_id
# Retrieve the browsing context info for the new tab # Retrieve the browsing context info for the new tab
contexts = await bidi_session.browsing_context.get_tree(parent=context_id, max_depth=0) contexts = await bidi_session.browsing_context.get_tree(parent=context_id, max_depth=0)
yield contexts[0] yield contexts[0]
# Restore the focus and current window for the WebDriver session before
# closing the tab.
current_session.window_handle = initial_window
await bidi_session.browsing_context.close(context=contexts[0]["context"]) await bidi_session.browsing_context.close(context=contexts[0]["context"])

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

@ -66,6 +66,7 @@ XPCOMUtils.defineLazyPreferenceGetter(
); );
const TOGGLE_ENABLED_PREF = const TOGGLE_ENABLED_PREF =
"media.videocontrols.picture-in-picture.video-toggle.enabled"; "media.videocontrols.picture-in-picture.video-toggle.enabled";
const PIP_ENABLED_PREF = "media.videocontrols.picture-in-picture.enabled";
const TOGGLE_TESTING_PREF = const TOGGLE_TESTING_PREF =
"media.videocontrols.picture-in-picture.video-toggle.testing"; "media.videocontrols.picture-in-picture.video-toggle.testing";
const TOGGLE_VISIBILITY_THRESHOLD_PREF = const TOGGLE_VISIBILITY_THRESHOLD_PREF =
@ -79,9 +80,6 @@ const TOGGLE_HIDING_TIMEOUT_MS = 2000;
const SEEK_TIME_SECS = 5; const SEEK_TIME_SECS = 5;
const EMPTIED_TIMEOUT_MS = 1000; const EMPTIED_TIMEOUT_MS = 1000;
// If you change bottom position in texttracks.css, also change this
const TEXT_TRACKS_STYLE_BOTTOM_MULTIPLIER = 0.066;
// The ToggleChild does not want to capture events from the PiP // The ToggleChild does not want to capture events from the PiP
// windows themselves. This set contains all currently open PiP // windows themselves. This set contains all currently open PiP
// players' content windows // players' content windows
@ -249,7 +247,9 @@ class PictureInPictureToggleChild extends JSWindowActorChild {
// We keep the state stashed inside of this WeakMap, keyed on the document // We keep the state stashed inside of this WeakMap, keyed on the document
// itself. // itself.
this.weakDocStates = new WeakMap(); this.weakDocStates = new WeakMap();
this.toggleEnabled = Services.prefs.getBoolPref(TOGGLE_ENABLED_PREF); this.toggleEnabled =
Services.prefs.getBoolPref(TOGGLE_ENABLED_PREF) &&
Services.prefs.getBoolPref(PIP_ENABLED_PREF);
this.toggleTesting = Services.prefs.getBoolPref(TOGGLE_TESTING_PREF, false); this.toggleTesting = Services.prefs.getBoolPref(TOGGLE_TESTING_PREF, false);
// Bug 1570744 - JSWindowActorChild's cannot be used as nsIObserver's // Bug 1570744 - JSWindowActorChild's cannot be used as nsIObserver's
@ -259,12 +259,14 @@ class PictureInPictureToggleChild extends JSWindowActorChild {
this.observe(subject, topic, data); this.observe(subject, topic, data);
}; };
Services.prefs.addObserver(TOGGLE_ENABLED_PREF, this.observerFunction); Services.prefs.addObserver(TOGGLE_ENABLED_PREF, this.observerFunction);
Services.prefs.addObserver(PIP_ENABLED_PREF, this.observerFunction);
Services.cpmm.sharedData.addEventListener("change", this); Services.cpmm.sharedData.addEventListener("change", this);
} }
didDestroy() { didDestroy() {
this.stopTrackingMouseOverVideos(); this.stopTrackingMouseOverVideos();
Services.prefs.removeObserver(TOGGLE_ENABLED_PREF, this.observerFunction); Services.prefs.removeObserver(TOGGLE_ENABLED_PREF, this.observerFunction);
Services.prefs.removeObserver(PIP_ENABLED_PREF, this.observerFunction);
Services.cpmm.sharedData.removeEventListener("change", this); Services.cpmm.sharedData.removeEventListener("change", this);
// remove the observer on the <video> element // remove the observer on the <video> element
@ -286,7 +288,9 @@ class PictureInPictureToggleChild extends JSWindowActorChild {
return; return;
} }
this.toggleEnabled = Services.prefs.getBoolPref(TOGGLE_ENABLED_PREF); this.toggleEnabled =
Services.prefs.getBoolPref(TOGGLE_ENABLED_PREF) &&
Services.prefs.getBoolPref(PIP_ENABLED_PREF);
if (this.toggleEnabled) { if (this.toggleEnabled) {
// We have enabled the Picture-in-Picture toggle, so we need to make // We have enabled the Picture-in-Picture toggle, so we need to make
@ -1408,6 +1412,9 @@ class PictureInPictureChild extends JSWindowActorChild {
const isReducedMotionEnabled = originatingWindow.matchMedia( const isReducedMotionEnabled = originatingWindow.matchMedia(
"(prefers-reduced-motion: reduce)" "(prefers-reduced-motion: reduce)"
).matches; ).matches;
const textTracksFontScale = this.document
.querySelector(":root")
.style.getPropertyValue("--font-scale");
if (isFullscreen || isReducedMotionEnabled) { if (isFullscreen || isReducedMotionEnabled) {
textTracks.removeAttribute("overlap-video-controls"); textTracks.removeAttribute("overlap-video-controls");
@ -1417,8 +1424,7 @@ class PictureInPictureChild extends JSWindowActorChild {
if (isVideoControlsShowing) { if (isVideoControlsShowing) {
let playerVideoRect = textTracks.parentElement.getBoundingClientRect(); let playerVideoRect = textTracks.parentElement.getBoundingClientRect();
let isOverlap = let isOverlap =
playerVideoRect.bottom - playerVideoRect.bottom - textTracksFontScale * playerVideoRect.height >
TEXT_TRACKS_STYLE_BOTTOM_MULTIPLIER * playerVideoRect.height >
playerBottomControlsDOMRect.top; playerBottomControlsDOMRect.top;
if (isOverlap) { if (isOverlap) {

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

@ -88,6 +88,7 @@ class UAWidgetsChild extends JSWindowActorChild {
uri = "chrome://global/content/elements/videocontrols.js"; uri = "chrome://global/content/elements/videocontrols.js";
widgetName = "VideoControlsWidget"; widgetName = "VideoControlsWidget";
prefKeys = [ prefKeys = [
"media.videocontrols.picture-in-picture.enabled",
"media.videocontrols.picture-in-picture.video-toggle.enabled", "media.videocontrols.picture-in-picture.video-toggle.enabled",
"media.videocontrols.picture-in-picture.video-toggle.always-show", "media.videocontrols.picture-in-picture.video-toggle.always-show",
"media.videocontrols.picture-in-picture.video-toggle.min-video-secs", "media.videocontrols.picture-in-picture.video-toggle.min-video-secs",

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

@ -267,6 +267,7 @@ var State = {
threads: null, threads: null,
displayRank: Control._getDisplayGroupRank(cur, windows), displayRank: Control._getDisplayGroupRank(cur, windows),
windows, windows,
utilityActors: cur.utilityActors,
// If this process has an unambiguous title, store it here. // If this process has an unambiguous title, store it here.
title: null, title: null,
}; };
@ -528,6 +529,9 @@ var View = {
case "preallocated": case "preallocated":
fluentName = "about-processes-preallocated-process"; fluentName = "about-processes-preallocated-process";
break; break;
case "utility":
fluentName = "about-processes-utility-process";
break;
// The following are probably not going to show up for users // The following are probably not going to show up for users
// but let's handle the case anyway to avoid heisenoranges // but let's handle the case anyway to avoid heisenoranges
// during tests in case of a leftover process from a previous // during tests in case of a leftover process from a previous
@ -848,6 +852,34 @@ var View = {
} }
}, },
displayUtilityActorRow(data, parent) {
const cellCount = 2;
// The actor name is expected to be unique within a given utility process.
let rowId = "u:" + parent.pid + data.actorName;
let row = this._getOrCreateRow(rowId, cellCount);
row.actor = data;
row.className = "actor";
// Column: name
let nameCell = row.firstChild;
let fluentName;
let fluentArgs = {};
switch (data.actorName) {
case "audioDecoder":
fluentName = "about-processes-utility-actor-audio-decoder";
break;
default:
fluentName = "about-processes-utility-actor-unknown";
break;
}
this._fillCell(nameCell, {
fluentName,
fluentArgs,
classes: ["name", "indent", "favicon"],
});
},
/** /**
* Display a row showing a single thread. * Display a row showing a single thread.
* *
@ -1213,6 +1245,12 @@ var Control = {
} }
} }
if (process.type === "utility") {
for (let actor of process.utilityActors) {
View.displayUtilityActorRow(actor, process);
}
}
if (SHOW_THREADS) { if (SHOW_THREADS) {
if (View.displayThreadSummaryRow(process)) { if (View.displayThreadSummaryRow(process)) {
this._showThreads(processRow, this._maxSlopeCpu); this._showThreads(processRow, this._maxSlopeCpu);

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

@ -1,6 +1,9 @@
[default] [default]
head = head.js head = head.js
skip-if = asan || tsan # With sanitizers, we regularly hit internal timeouts. skip-if =
asan || tsan # With sanitizers, we regularly hit internal timeouts.
support-files =
small-shot.mp3
[browser_aboutprocesses_default_options.js] [browser_aboutprocesses_default_options.js]
https_first_disabled = true https_first_disabled = true

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

@ -12,7 +12,7 @@ const { AppConstants } = ChromeUtils.import(
// update these values. // update these values.
// Note that Test Verify can really stress the cpu durations. // Note that Test Verify can really stress the cpu durations.
const HARDCODED_ASSUMPTIONS_PROCESS = { const HARDCODED_ASSUMPTIONS_PROCESS = {
minimalNumberOfThreads: 10, minimalNumberOfThreads: 6,
maximalNumberOfThreads: 1000, maximalNumberOfThreads: 1000,
minimalCPUPercentage: 0, minimalCPUPercentage: 0,
maximalCPUPercentage: 1000, maximalCPUPercentage: 1000,
@ -382,6 +382,27 @@ async function setupTabWithOriginAndTitle(origin, title) {
return tab; return tab;
} }
async function setupAudioTab() {
let origin = "about:blank";
let title = "utility audio";
let tab = BrowserTestUtils.addTab(gBrowser, origin, { skipAnimation: true });
tab.testTitle = title;
tab.testOrigin = origin;
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
await SpecialPowers.spawn(tab.linkedBrowser, [title], async title => {
content.document.title = title;
const ROOT =
"https://example.com/browser/toolkit/components/aboutprocesses/tests/browser";
let audio = content.document.createElement("audio");
audio.setAttribute("controls", "true");
audio.setAttribute("loop", true);
audio.src = `${ROOT}/small-shot.mp3`;
content.document.body.appendChild(audio);
await audio.play();
});
return tab;
}
async function testAboutProcessesWithConfig({ showAllFrames, showThreads }) { async function testAboutProcessesWithConfig({ showAllFrames, showThreads }) {
const isFission = gFissionBrowser; const isFission = gFissionBrowser;
await SpecialPowers.pushPrefEnv({ await SpecialPowers.pushPrefEnv({
@ -391,6 +412,8 @@ async function testAboutProcessesWithConfig({ showAllFrames, showThreads }) {
// Force same-origin tabs to share a single process, to properly test // Force same-origin tabs to share a single process, to properly test
// functionality involving multiple tabs within a single process with Fission. // functionality involving multiple tabs within a single process with Fission.
["dom.ipc.processCount.webIsolated", 1], ["dom.ipc.processCount.webIsolated", 1],
// Ensure utility audio decoder is enabled
["media.utility-process.enabled", true],
], ],
}); });
@ -442,6 +465,8 @@ async function testAboutProcessesWithConfig({ showAllFrames, showThreads }) {
return tab; return tab;
})(); })();
let promiseAudioPlayback = setupAudioTab();
let promiseUserContextTab = (async function() { let promiseUserContextTab = (async function() {
let tab = BrowserTestUtils.addTab(gBrowser, "http://example.com", { let tab = BrowserTestUtils.addTab(gBrowser, "http://example.com", {
userContextId: 1, userContextId: 1,
@ -494,6 +519,7 @@ async function testAboutProcessesWithConfig({ showAllFrames, showThreads }) {
// Wait for initialization to finish. // Wait for initialization to finish.
let tabAboutProcesses = await promiseTabAboutProcesses; let tabAboutProcesses = await promiseTabAboutProcesses;
let tabHung = await promiseTabHung; let tabHung = await promiseTabHung;
let audioPlayback = await promiseAudioPlayback;
let tabUserContext = await promiseUserContextTab; let tabUserContext = await promiseUserContextTab;
let tabCloseSeparately1 = await promiseTabCloseSeparately1; let tabCloseSeparately1 = await promiseTabCloseSeparately1;
let tabCloseSeparately2 = await promiseTabCloseSeparately2; let tabCloseSeparately2 = await promiseTabCloseSeparately2;
@ -574,6 +600,17 @@ async function testAboutProcessesWithConfig({ showAllFrames, showThreads }) {
row.classList.contains("process") && row.classList.contains("process") &&
["web", "webIsolated"].includes(row.process.type), ["web", "webIsolated"].includes(row.process.type),
}, },
// A utility process with audio decoder.
{
name: "utility",
predicate: row =>
row.process &&
row.process.type == "utility" &&
row.classList.contains("process") &&
row.nextSibling &&
row.nextSibling.classList.contains("actor") &&
row.nextSibling.actor.actorName === "audioDecoder",
},
]; ];
for (let finder of processesToBeFound) { for (let finder of processesToBeFound) {
info(`Running sanity tests on ${finder.name}`); info(`Running sanity tests on ${finder.name}`);
@ -1024,6 +1061,7 @@ async function testAboutProcessesWithConfig({ showAllFrames, showThreads }) {
// We killed the process, but we don't want to leave zombie tabs lying around. // We killed the process, but we don't want to leave zombie tabs lying around.
BrowserTestUtils.removeTab(tabCloseProcess1); BrowserTestUtils.removeTab(tabCloseProcess1);
BrowserTestUtils.removeTab(tabCloseProcess2); BrowserTestUtils.removeTab(tabCloseProcess2);
BrowserTestUtils.removeTab(audioPlayback);
await SpecialPowers.popPrefEnv(); await SpecialPowers.popPrefEnv();

Двоичные данные
toolkit/components/aboutprocesses/tests/browser/small-shot.mp3 Normal file

Двоичный файл не отображается.

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