forked from mirrors/gecko-dev
Merge autoland to mozilla-central. a=merge
This commit is contained in:
commit
e0488c86ff
695 changed files with 37927 additions and 13133 deletions
29
Cargo.lock
generated
29
Cargo.lock
generated
|
|
@ -351,6 +351,10 @@ dependencies = [
|
|||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.999"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.999"
|
||||
|
|
@ -1693,9 +1697,9 @@ checksum = "cda653ca797810c02f7ca4b804b40b8b95ae046eb989d356bce17919a8c25499"
|
|||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.25"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
|
||||
checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
|
|
@ -3485,9 +3489,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
|||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.6.2"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
|
@ -4026,9 +4030,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.30.3"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
|
||||
checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
|
@ -5096,9 +5100,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.7"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
|
||||
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
|
|
@ -5544,18 +5548,19 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.17.0"
|
||||
version = "1.29.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
|
||||
checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio 0.8.8",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"winapi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -132,6 +132,11 @@ base64 = { path = "build/rust/base64" }
|
|||
# Patch wasi 0.10 to 0.11
|
||||
wasi = { path = "build/rust/wasi" }
|
||||
|
||||
# tokio 0.29.0 includes an experimental "tracing" feature which requires
|
||||
# backtrace ^0.3.58 and the `tokio_unstable` flag. We don't use it, and nothing
|
||||
# else we do use requires backtrace, so dummy it out for now.
|
||||
backtrace = { path = "build/rust/backtrace" }
|
||||
|
||||
# Patch bindgen 0.63, 0.64 and 0.66 to 0.68
|
||||
bindgen_0_63 = { package = "bindgen", path = "build/rust/bindgen-0.63" }
|
||||
bindgen_0_64 = { package = "bindgen", path = "build/rust/bindgen-0.64" }
|
||||
|
|
|
|||
|
|
@ -2184,10 +2184,9 @@ pref("browser.migrate.opera-gx.enabled", true);
|
|||
pref("browser.migrate.safari.enabled", true);
|
||||
pref("browser.migrate.vivaldi.enabled", true);
|
||||
|
||||
pref("browser.migrate.content-modal.enabled", true);
|
||||
pref("browser.migrate.content-modal.import-all.enabled", true);
|
||||
|
||||
// Values can be: "default", "autoclose", "standalone", "legacy", "embedded".
|
||||
// Values can be: "default", "autoclose", "standalone", "embedded".
|
||||
pref("browser.migrate.content-modal.about-welcome-behavior", "embedded");
|
||||
|
||||
// The maximum age of history entries we'll import, in days.
|
||||
|
|
|
|||
|
|
@ -689,25 +689,23 @@
|
|||
</panelview>
|
||||
|
||||
<panelview id="reset-pbm-panel" class="PanelUI-subView">
|
||||
<hbox id="reset-pbm-panel-container">
|
||||
<hbox id="reset-pbm-panel-header">
|
||||
<description data-l10n-id="reset-pbm-panel-heading"/>
|
||||
</hbox>
|
||||
|
||||
<description id="reset-pbm-panel-description" data-l10n-id="reset-pbm-panel-description"/>
|
||||
<checkbox id="reset-pbm-panel-checkbox" data-l10n-id="reset-pbm-panel-always-ask-checkbox"/>
|
||||
|
||||
<html:moz-button-group id="reset-pbm-panel-footer" class="panel-footer">
|
||||
<button id="reset-pbm-panel-cancel-button"
|
||||
class="panel-footer-button"
|
||||
data-l10n-id="reset-pbm-panel-cancel-button"
|
||||
oncommand="ResetPBMPanel.onCancel(this)"></button>
|
||||
<button slot="primary"
|
||||
id="reset-pbm-panel-confirm-button"
|
||||
class="panel-footer-button"
|
||||
data-l10n-id="reset-pbm-panel-confirm-button"
|
||||
oncommand="ResetPBMPanel.onConfirm(this)"></button>
|
||||
</html:moz-button-group>
|
||||
<hbox id="reset-pbm-panel-header">
|
||||
<description data-l10n-id="reset-pbm-panel-heading"/>
|
||||
</hbox>
|
||||
|
||||
<description id="reset-pbm-panel-description" data-l10n-id="reset-pbm-panel-description"/>
|
||||
<checkbox id="reset-pbm-panel-checkbox" data-l10n-id="reset-pbm-panel-always-ask-checkbox"/>
|
||||
|
||||
<html:moz-button-group id="reset-pbm-panel-footer" class="panel-footer">
|
||||
<button id="reset-pbm-panel-cancel-button"
|
||||
class="panel-footer-button"
|
||||
data-l10n-id="reset-pbm-panel-cancel-button"
|
||||
oncommand="ResetPBMPanel.onCancel(this)"></button>
|
||||
<button slot="primary"
|
||||
id="reset-pbm-panel-confirm-button"
|
||||
class="panel-footer-button"
|
||||
data-l10n-id="reset-pbm-panel-confirm-button"
|
||||
oncommand="ResetPBMPanel.onConfirm(this)"></button>
|
||||
</html:moz-button-group>
|
||||
</panelview>
|
||||
</html:template>
|
||||
|
|
|
|||
|
|
@ -4,24 +4,20 @@
|
|||
"use strict";
|
||||
|
||||
add_setup(async () => {
|
||||
// Load the initial tab at example.com. This makes it so that if
|
||||
// we're using the new migration wizard, we'll load the about:preferences
|
||||
// page in a new tab rather than overtaking the initial one. This
|
||||
// makes it easier to be consistent with closing and opening
|
||||
// behaviours between the two kinds of migration wizards.
|
||||
// Load the initial tab at example.com. This makes it so that when the
|
||||
// about:preferences hosting the migration wizard opens, we'll load
|
||||
// the about:preferences page in a new tab rather than overtaking the
|
||||
// initial one. This makes it easier to be more explicit when cleaning
|
||||
// up because we can just remove the opened tab.
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
BrowserTestUtils.startLoadingURIString(browser, "https://example.com");
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
});
|
||||
|
||||
add_task(async function file_menu_import_wizard() {
|
||||
// We can't call this code directly or our JS execution will get blocked on Windows/Linux where
|
||||
// the dialog is modal.
|
||||
executeSoon(() =>
|
||||
document.getElementById("menu_importFromAnotherBrowser").doCommand()
|
||||
);
|
||||
|
||||
let wizard = await BrowserTestUtils.waitForMigrationWizard(window);
|
||||
ok(wizard, "Migrator window opened");
|
||||
await BrowserTestUtils.closeMigrationWizard(wizard);
|
||||
let wizardTabPromise = BrowserTestUtils.waitForMigrationWizard(window);
|
||||
document.getElementById("menu_importFromAnotherBrowser").doCommand();
|
||||
let wizardTab = await wizardTabPromise;
|
||||
ok(wizardTab, "Migration wizard tab opened");
|
||||
BrowserTestUtils.removeTab(wizardTab);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ skip-if = [
|
|||
["browser_permission_delegate_geo.js"]
|
||||
|
||||
["browser_permissions.js"]
|
||||
skip-if = ["a11y_checks"] # Bug 1858037 to investigate intermittent a11y_checks results (fails on Try, passes on Autoland)
|
||||
|
||||
["browser_permissions_delegate_vibrate.js"]
|
||||
support-files = ["empty.html"]
|
||||
|
|
@ -41,7 +40,6 @@ support-files = ["dummy.js"]
|
|||
["browser_reservedkey.js"]
|
||||
|
||||
["browser_site_scoped_permissions.js"]
|
||||
skip-if = ["a11y_checks"] # Bug 1858037 to investigate intermittent a11y_checks results (fails on Try, passes on Autoland)
|
||||
|
||||
["browser_temporary_permissions.js"]
|
||||
support-files = ["../webrtc/get_user_media.html"]
|
||||
|
|
|
|||
|
|
@ -60,7 +60,16 @@ add_task(async function testMainViewVisible() {
|
|||
|
||||
PermissionTestUtils.remove(gBrowser.currentURI, "camera");
|
||||
|
||||
// We intentionally turn off a11y_checks, because the following function
|
||||
// is expected to click a toolbar button that may be already hidden
|
||||
// with "display:none;". The permissions panel anchor is hidden because
|
||||
// the last permission was removed, however we force opening the panel
|
||||
// anyways in order to test that the list has been properly emptied:
|
||||
AccessibilityUtils.setEnv({
|
||||
mustHaveAccessibleRule: false,
|
||||
});
|
||||
await openPermissionPopup();
|
||||
AccessibilityUtils.resetEnv();
|
||||
|
||||
testPermListHasEntries(false);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,16 @@ add_task(async function testSiteScopedPermissionSubdomainAffectsBaseDomain() {
|
|||
|
||||
Services.perms.removeFromPrincipal(subdomainPrincipal, id);
|
||||
|
||||
// We intentionally turn off a11y_checks, because the following function
|
||||
// is expected to click a toolbar button that may be already hidden
|
||||
// with "display:none;". The permissions panel anchor is hidden because
|
||||
// the last permission was removed, however we force opening the panel
|
||||
// anyways in order to test that the list has been properly emptied:
|
||||
AccessibilityUtils.setEnv({
|
||||
mustHaveAccessibleRule: false,
|
||||
});
|
||||
await openPermissionPopup();
|
||||
AccessibilityUtils.resetEnv();
|
||||
|
||||
listEntryCount = permissionsList.querySelectorAll(
|
||||
".permission-popup-permission-item-3rdPartyStorage"
|
||||
|
|
|
|||
|
|
@ -73,6 +73,11 @@ var gExceptionPaths = [
|
|||
|
||||
// CSS files are referenced inside JS in an html template
|
||||
"chrome://browser/content/aboutlogins/components/",
|
||||
|
||||
// These files are for the old migration wizard which will be removed
|
||||
// shortly.
|
||||
"chrome://browser/content/migration/migration.xhtml",
|
||||
"chrome://browser/content/migration/migration.js",
|
||||
];
|
||||
|
||||
// These are not part of the omni.ja file, so we find them only when running
|
||||
|
|
|
|||
|
|
@ -108,9 +108,9 @@ add_task(async function test_no_logins_class() {
|
|||
// End the test now for Linux since the link is hidden.
|
||||
return;
|
||||
}
|
||||
let wizard = await wizardPromise;
|
||||
Assert.ok(wizard, "Migrator window opened");
|
||||
await BrowserTestUtils.closeMigrationWizard(wizard);
|
||||
let wizardTab = await wizardPromise;
|
||||
Assert.ok(wizardTab, "Migrator wizard tab opened");
|
||||
await BrowserTestUtils.removeTab(wizardTab);
|
||||
});
|
||||
|
||||
add_task(
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ add_setup(async function () {
|
|||
});
|
||||
|
||||
add_task(async function test_open_import() {
|
||||
let promiseImportWindow = BrowserTestUtils.waitForMigrationWizard(window);
|
||||
let promiseWizardTab = BrowserTestUtils.waitForMigrationWizard(window);
|
||||
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter("menu-button", {}, browser);
|
||||
|
|
@ -44,9 +44,9 @@ add_task(async function test_open_import() {
|
|||
}
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter(getImportItem, {}, browser);
|
||||
|
||||
info("waiting for Import to get opened");
|
||||
let importWindow = await promiseImportWindow;
|
||||
Assert.ok(true, "Import opened");
|
||||
info("waiting for migration wizard to open");
|
||||
let wizardTab = await promiseWizardTab;
|
||||
Assert.ok(wizardTab, "Migration wizard opened");
|
||||
|
||||
// First event is for opening about:logins
|
||||
await LoginTestUtils.telemetry.waitForEventCount(2);
|
||||
|
|
@ -56,5 +56,5 @@ add_task(async function test_open_import() {
|
|||
{ process: "content" }
|
||||
);
|
||||
|
||||
await BrowserTestUtils.closeMigrationWizard(importWindow);
|
||||
await BrowserTestUtils.removeTab(wizardTab);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -515,11 +515,15 @@ export class FxviewTabRow extends MozLitElement {
|
|||
backgroundImage: `url(${this.getImageUrl(this.favicon, this.url)})`,
|
||||
})}
|
||||
></span>
|
||||
<span class="fxview-tab-row-title" id="fxview-tab-row-title">
|
||||
<span
|
||||
class="fxview-tab-row-title text-truncated-ellipsis"
|
||||
id="fxview-tab-row-title"
|
||||
dir="auto"
|
||||
>
|
||||
${title}
|
||||
</span>
|
||||
<span
|
||||
class="fxview-tab-row-url"
|
||||
class="fxview-tab-row-url text-truncated-ellipsis"
|
||||
id="fxview-tab-row-url"
|
||||
?hidden=${this.compact}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -77,19 +77,14 @@
|
|||
}
|
||||
|
||||
.fxview-tab-row-title {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: match-parent;
|
||||
}
|
||||
|
||||
.fxview-tab-row-url {
|
||||
color: var(--text-color-deemphasized);
|
||||
word-break: break-word;
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
.fxview-tab-row-title,
|
||||
.fxview-tab-row-url {
|
||||
overflow: hidden;
|
||||
direction: ltr;
|
||||
text-align: match-parent;
|
||||
}
|
||||
|
||||
.fxview-tab-row-date,
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ var gMigrators = null;
|
|||
var gFileMigrators = null;
|
||||
var gProfileStartup = null;
|
||||
var gL10n = null;
|
||||
var gHasOpenedLegacyWizard = false;
|
||||
|
||||
let gForceExitSpinResolve = false;
|
||||
let gKeepUndoData = false;
|
||||
|
|
@ -552,8 +551,8 @@ class MigrationUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Show the migration wizard. On mac, this may just focus the wizard if it's
|
||||
* already running, in which case aOpener and aOptions are ignored.
|
||||
* Show the migration wizard in about:preferences, or if there is not an existing
|
||||
* browser window open, in a new top-level dialog window.
|
||||
*
|
||||
* NB: If you add new consumers, please add a migration entry point constant to
|
||||
* MIGRATION_ENTRYPOINTS and supply that entrypoint with the entrypoint property
|
||||
|
|
@ -577,10 +576,9 @@ class MigrationUtils {
|
|||
* @param {string} [aOptions.profileId]
|
||||
* An identifier for the profile to use when migrating.
|
||||
* @returns {Promise<undefined>}
|
||||
* If the new content-modal migration dialog is enabled and an
|
||||
* about:preferences tab can be opened, this will resolve when
|
||||
* If an about:preferences tab can be opened, this will resolve when
|
||||
* that tab has been switched to. Otherwise, this will resolve
|
||||
* just after opening the dialog window.
|
||||
* just after opening the top-level dialog window.
|
||||
*/
|
||||
showMigrationWizard(aOpener, aOptions) {
|
||||
// When migration is kicked off from about:welcome, there are
|
||||
|
|
@ -597,10 +595,6 @@ class MigrationUtils {
|
|||
// The migration wizard will open in a new top-level content
|
||||
// window.
|
||||
//
|
||||
// "legacy":
|
||||
// The legacy migration wizard will open, even if the new migration
|
||||
// wizard is enabled by default.
|
||||
//
|
||||
// "default" / other
|
||||
// The user will be directed to the migration wizard in
|
||||
// about:preferences. The tab will not close once the
|
||||
|
|
@ -610,92 +604,59 @@ class MigrationUtils {
|
|||
"default"
|
||||
);
|
||||
|
||||
let aboutWelcomeLegacyBehavior =
|
||||
aboutWelcomeBehavior == "legacy" &&
|
||||
aOptions.entrypoint == this.MIGRATION_ENTRYPOINTS.NEWTAB;
|
||||
let entrypoint = aOptions.entrypoint || this.MIGRATION_ENTRYPOINTS.UNKNOWN;
|
||||
Services.telemetry
|
||||
.getHistogramById("FX_MIGRATION_ENTRY_POINT_CATEGORICAL")
|
||||
.add(entrypoint);
|
||||
|
||||
if (
|
||||
Services.prefs.getBoolPref(
|
||||
"browser.migrate.content-modal.enabled",
|
||||
false
|
||||
) &&
|
||||
!aboutWelcomeLegacyBehavior
|
||||
) {
|
||||
let entrypoint =
|
||||
aOptions.entrypoint || this.MIGRATION_ENTRYPOINTS.UNKNOWN;
|
||||
Services.telemetry
|
||||
.getHistogramById("FX_MIGRATION_ENTRY_POINT_CATEGORICAL")
|
||||
.add(entrypoint);
|
||||
let openStandaloneWindow = blocking => {
|
||||
let features = "dialog,centerscreen,resizable=no";
|
||||
|
||||
let openStandaloneWindow = blocking => {
|
||||
let features = "dialog,centerscreen,resizable=no";
|
||||
if (blocking) {
|
||||
features += ",modal";
|
||||
}
|
||||
|
||||
if (blocking) {
|
||||
features += ",modal";
|
||||
Services.ww.openWindow(
|
||||
aOpener,
|
||||
"chrome://browser/content/migration/migration-dialog-window.html",
|
||||
"_blank",
|
||||
features,
|
||||
{
|
||||
options: aOptions,
|
||||
}
|
||||
);
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
Services.ww.openWindow(
|
||||
aOpener,
|
||||
"chrome://browser/content/migration/migration-dialog-window.html",
|
||||
"_blank",
|
||||
features,
|
||||
{
|
||||
options: aOptions,
|
||||
}
|
||||
if (aOptions.isStartupMigration) {
|
||||
// Record that the uninstaller requested a profile refresh
|
||||
if (Services.env.get("MOZ_UNINSTALLER_PROFILE_REFRESH")) {
|
||||
Services.env.set("MOZ_UNINSTALLER_PROFILE_REFRESH", "");
|
||||
Services.telemetry.scalarSet(
|
||||
"migration.uninstaller_profile_refresh",
|
||||
true
|
||||
);
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
if (aOptions.isStartupMigration) {
|
||||
// Record that the uninstaller requested a profile refresh
|
||||
if (Services.env.get("MOZ_UNINSTALLER_PROFILE_REFRESH")) {
|
||||
Services.env.set("MOZ_UNINSTALLER_PROFILE_REFRESH", "");
|
||||
Services.telemetry.scalarSet(
|
||||
"migration.uninstaller_profile_refresh",
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
openStandaloneWindow(true /* blocking */);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (aOpener?.openPreferences) {
|
||||
if (aOptions.entrypoint == this.MIGRATION_ENTRYPOINTS.NEWTAB) {
|
||||
if (aboutWelcomeBehavior == "autoclose") {
|
||||
return aOpener.openPreferences("general-migrate-autoclose");
|
||||
} else if (aboutWelcomeBehavior == "standalone") {
|
||||
openStandaloneWindow(false /* blocking */);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
return aOpener.openPreferences("general-migrate");
|
||||
}
|
||||
|
||||
// If somehow we failed to open about:preferences, fall back to opening
|
||||
// the top-level window.
|
||||
openStandaloneWindow(false /* blocking */);
|
||||
openStandaloneWindow(true /* blocking */);
|
||||
return Promise.resolve();
|
||||
}
|
||||
// Legacy migration dialog
|
||||
if (!gHasOpenedLegacyWizard) {
|
||||
gHasOpenedLegacyWizard = true;
|
||||
aOptions.openedTime = Cu.now();
|
||||
|
||||
if (aOpener?.openPreferences) {
|
||||
if (aOptions.entrypoint == this.MIGRATION_ENTRYPOINTS.NEWTAB) {
|
||||
if (aboutWelcomeBehavior == "autoclose") {
|
||||
return aOpener.openPreferences("general-migrate-autoclose");
|
||||
} else if (aboutWelcomeBehavior == "standalone") {
|
||||
openStandaloneWindow(false /* blocking */);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
return aOpener.openPreferences("general-migrate");
|
||||
}
|
||||
|
||||
const DIALOG_URL = "chrome://browser/content/migration/migration.xhtml";
|
||||
let features = "chrome,dialog,modal,centerscreen,titlebar,resizable=no";
|
||||
if (AppConstants.platform == "macosx" && !this.isStartupMigration) {
|
||||
let win = Services.wm.getMostRecentWindow("Browser:MigrationWizard");
|
||||
if (win) {
|
||||
win.focus();
|
||||
return Promise.resolve();
|
||||
}
|
||||
// On mac, the migration wiazrd should only be modal in the case of
|
||||
// startup-migration.
|
||||
features = "centerscreen,chrome,resizable=no";
|
||||
}
|
||||
Services.ww.openWindow(aOpener, DIALOG_URL, "_blank", features, aOptions);
|
||||
// If somehow we failed to open about:preferences, fall back to opening
|
||||
// the top-level window.
|
||||
openStandaloneWindow(false /* blocking */);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,6 @@ Migration Wizard Reference
|
|||
|
||||
The migration wizard is the piece of UI that allows users to migrate from other browsers to Firefox.
|
||||
|
||||
.. note::
|
||||
Firefox has had a legacy migration wizard for many years, and this has historically been a top-level XUL dialog window. **This documentation is not for the legacy migration wizard**, but is instead for an in-progress replacement migration wizard.
|
||||
|
||||
The new migration wizard can be enabled by setting ``browser.migrate.content-modal.enabled`` to ``true``.
|
||||
|
||||
The migration wizard can be embedded in the following contexts:
|
||||
|
||||
1. In a top level stand-alone dialog window
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
[DEFAULT]
|
||||
head = "head.js"
|
||||
prefs = [
|
||||
"browser.migrate.content-modal.enabled=true",
|
||||
"browser.migrate.internal-testing.enabled=true",
|
||||
"dom.window.sizeToContent.enabled=true",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,58 +3,27 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const CONTENT_MODAL_ENABLED_PREF = "browser.migrate.content-modal.enabled";
|
||||
const HISTOGRAM_ID = "FX_MIGRATION_ENTRY_POINT_CATEGORICAL";
|
||||
const LEGACY_HISTOGRAM_ID = "FX_MIGRATION_ENTRY_POINT";
|
||||
|
||||
async function showThenCloseMigrationWizardViaEntrypoint(entrypoint) {
|
||||
let openedPromise = BrowserTestUtils.waitForMigrationWizard(window);
|
||||
|
||||
// On some platforms, this call blocks, so in order to let the test proceed, we
|
||||
// run it on the next tick of the event loop.
|
||||
executeSoon(() => {
|
||||
MigrationUtils.showMigrationWizard(window, {
|
||||
entrypoint,
|
||||
});
|
||||
MigrationUtils.showMigrationWizard(window, {
|
||||
entrypoint,
|
||||
});
|
||||
|
||||
let wizard = await openedPromise;
|
||||
Assert.ok(wizard, "Migration wizard opened.");
|
||||
let wizardTab = await openedPromise;
|
||||
Assert.ok(wizardTab, "Migration wizard opened.");
|
||||
|
||||
if (!Services.prefs.getBoolPref(CONTENT_MODAL_ENABLED_PREF)) {
|
||||
// This scalar gets written to asynchronously. The old wizard will be going
|
||||
// away soon, so we'll just poll for it to be set rather than doing anything
|
||||
// fancier.
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
// We should make sure that the migration.time_to_produce_legacy_migrator_list
|
||||
// scalar was set, since we know that at least one legacy migration wizard has
|
||||
// been opened.
|
||||
let scalars = TelemetryTestUtils.getProcessScalars(
|
||||
"parent",
|
||||
false,
|
||||
false
|
||||
);
|
||||
if (!scalars["migration.time_to_produce_legacy_migrator_list"]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Assert.ok(
|
||||
scalars["migration.time_to_produce_legacy_migrator_list"] > 0,
|
||||
"Non-zero scalar value recorded for migration.time_to_produce_migrator_list"
|
||||
);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
await BrowserTestUtils.closeMigrationWizard(wizard);
|
||||
await BrowserTestUtils.removeTab(wizardTab);
|
||||
}
|
||||
|
||||
add_setup(async () => {
|
||||
// Load the initial tab at example.com. This makes it so that if
|
||||
// we're using the new migration wizard, we'll load the about:preferences
|
||||
// page in a new tab rather than overtaking the initial one. This
|
||||
// makes it easier to be consistent with closing and opening
|
||||
// behaviours between the two kinds of migration wizards.
|
||||
// when we load the wizard in about:preferences, we'll load the
|
||||
// about:preferences page in a new tab rather than overtaking the
|
||||
// initial one. This makes cleanup of the wizard more explicit, since
|
||||
// we can just close the tab.
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
BrowserTestUtils.startLoadingURIString(browser, "https://example.com");
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
|
|
@ -62,76 +31,42 @@ add_setup(async () => {
|
|||
|
||||
/**
|
||||
* Tests that the entrypoint passed to MigrationUtils.showMigrationWizard gets
|
||||
* written to both the FX_MIGRATION_ENTRY_POINT_CATEGORICAL histogram, as well
|
||||
* as the legacy FX_MIGRATION_ENTRY_POINT histogram (but only if using the old
|
||||
* wizard window).
|
||||
* written to both the FX_MIGRATION_ENTRY_POINT_CATEGORICAL histogram.
|
||||
*/
|
||||
add_task(async function test_legacy_wizard() {
|
||||
for (let contentModalEnabled of [true, false]) {
|
||||
info("Testing with content modal enabled: " + contentModalEnabled);
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [[CONTENT_MODAL_ENABLED_PREF, contentModalEnabled]],
|
||||
});
|
||||
add_task(async function test_entrypoints() {
|
||||
let histogram = TelemetryTestUtils.getAndClearHistogram(HISTOGRAM_ID);
|
||||
|
||||
let histogram = TelemetryTestUtils.getAndClearHistogram(HISTOGRAM_ID);
|
||||
let legacyHistogram =
|
||||
TelemetryTestUtils.getAndClearHistogram(LEGACY_HISTOGRAM_ID);
|
||||
|
||||
// Let's arbitrarily pick the "Bookmarks" entrypoint, and make sure this
|
||||
// is recorded.
|
||||
await showThenCloseMigrationWizardViaEntrypoint(
|
||||
MigrationUtils.MIGRATION_ENTRYPOINTS.BOOKMARKS
|
||||
);
|
||||
let entrypointId = MigrationUtils.getLegacyMigrationEntrypoint(
|
||||
MigrationUtils.MIGRATION_ENTRYPOINTS.BOOKMARKS
|
||||
);
|
||||
|
||||
TelemetryTestUtils.assertHistogram(histogram, entrypointId, 1);
|
||||
|
||||
if (!contentModalEnabled) {
|
||||
TelemetryTestUtils.assertHistogram(legacyHistogram, entrypointId, 1);
|
||||
}
|
||||
|
||||
histogram = TelemetryTestUtils.getAndClearHistogram(HISTOGRAM_ID);
|
||||
legacyHistogram =
|
||||
TelemetryTestUtils.getAndClearHistogram(LEGACY_HISTOGRAM_ID);
|
||||
|
||||
// Now let's pick the "Preferences" entrypoint, and make sure this
|
||||
// is recorded.
|
||||
await showThenCloseMigrationWizardViaEntrypoint(
|
||||
MigrationUtils.MIGRATION_ENTRYPOINTS.PREFERENCES
|
||||
);
|
||||
entrypointId = MigrationUtils.getLegacyMigrationEntrypoint(
|
||||
MigrationUtils.MIGRATION_ENTRYPOINTS.PREFERENCES
|
||||
);
|
||||
|
||||
TelemetryTestUtils.assertHistogram(histogram, entrypointId, 1);
|
||||
if (!contentModalEnabled) {
|
||||
TelemetryTestUtils.assertHistogram(legacyHistogram, entrypointId, 1);
|
||||
}
|
||||
|
||||
histogram = TelemetryTestUtils.getAndClearHistogram(HISTOGRAM_ID);
|
||||
legacyHistogram =
|
||||
TelemetryTestUtils.getAndClearHistogram(LEGACY_HISTOGRAM_ID);
|
||||
|
||||
// Finally, check the fallback by passing in something invalid as an entrypoint.
|
||||
await showThenCloseMigrationWizardViaEntrypoint(undefined);
|
||||
entrypointId = MigrationUtils.getLegacyMigrationEntrypoint(
|
||||
MigrationUtils.MIGRATION_ENTRYPOINTS.UNKNOWN
|
||||
);
|
||||
|
||||
TelemetryTestUtils.assertHistogram(histogram, entrypointId, 1);
|
||||
if (!contentModalEnabled) {
|
||||
TelemetryTestUtils.assertHistogram(legacyHistogram, entrypointId, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// We should make sure that the migration.time_to_produce_legacy_migrator_list
|
||||
// scalar was set, since we know that at least one legacy migration wizard has
|
||||
// been opened.
|
||||
let scalars = TelemetryTestUtils.getProcessScalars("parent", false, false);
|
||||
Assert.ok(
|
||||
scalars["migration.time_to_produce_legacy_migrator_list"] > 0,
|
||||
"Non-zero scalar value recorded for migration.time_to_produce_migrator_list"
|
||||
// Let's arbitrarily pick the "Bookmarks" entrypoint, and make sure this
|
||||
// is recorded.
|
||||
await showThenCloseMigrationWizardViaEntrypoint(
|
||||
MigrationUtils.MIGRATION_ENTRYPOINTS.BOOKMARKS
|
||||
);
|
||||
let entrypointId = MigrationUtils.getLegacyMigrationEntrypoint(
|
||||
MigrationUtils.MIGRATION_ENTRYPOINTS.BOOKMARKS
|
||||
);
|
||||
|
||||
TelemetryTestUtils.assertHistogram(histogram, entrypointId, 1);
|
||||
|
||||
histogram = TelemetryTestUtils.getAndClearHistogram(HISTOGRAM_ID);
|
||||
|
||||
// Now let's pick the "Preferences" entrypoint, and make sure this
|
||||
// is recorded.
|
||||
await showThenCloseMigrationWizardViaEntrypoint(
|
||||
MigrationUtils.MIGRATION_ENTRYPOINTS.PREFERENCES
|
||||
);
|
||||
entrypointId = MigrationUtils.getLegacyMigrationEntrypoint(
|
||||
MigrationUtils.MIGRATION_ENTRYPOINTS.PREFERENCES
|
||||
);
|
||||
|
||||
TelemetryTestUtils.assertHistogram(histogram, entrypointId, 1);
|
||||
|
||||
histogram = TelemetryTestUtils.getAndClearHistogram(HISTOGRAM_ID);
|
||||
|
||||
// Finally, check the fallback by passing in something invalid as an entrypoint.
|
||||
await showThenCloseMigrationWizardViaEntrypoint(undefined);
|
||||
entrypointId = MigrationUtils.getLegacyMigrationEntrypoint(
|
||||
MigrationUtils.MIGRATION_ENTRYPOINTS.UNKNOWN
|
||||
);
|
||||
|
||||
TelemetryTestUtils.assertHistogram(histogram, entrypointId, 1);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,12 +15,6 @@ const IMPORT_SCREEN = {
|
|||
},
|
||||
};
|
||||
|
||||
const FORCE_LEGACY =
|
||||
Services.prefs.getCharPref(
|
||||
"browser.migrate.content-modal.about-welcome-behavior",
|
||||
"default"
|
||||
) === "legacy";
|
||||
|
||||
add_task(async function test_wait_import_modal() {
|
||||
await setAboutWelcomeMultiStage(
|
||||
JSON.stringify([IMPORT_SCREEN, { id: "AW_NEXT", content: {} }])
|
||||
|
|
@ -38,10 +32,7 @@ add_task(async function test_wait_import_modal() {
|
|||
["main.AW_NEXT"]
|
||||
);
|
||||
|
||||
const wizardPromise = BrowserTestUtils.waitForMigrationWizard(
|
||||
window,
|
||||
FORCE_LEGACY
|
||||
);
|
||||
const wizardPromise = BrowserTestUtils.waitForMigrationWizard(window);
|
||||
const prefsTab = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
"about:preferences"
|
||||
|
|
@ -59,7 +50,7 @@ add_task(async function test_wait_import_modal() {
|
|||
["main.AW_NEXT"]
|
||||
);
|
||||
|
||||
await BrowserTestUtils.closeMigrationWizard(wizard, FORCE_LEGACY);
|
||||
await BrowserTestUtils.removeTab(wizard);
|
||||
|
||||
await test_screen_content(
|
||||
browser,
|
||||
|
|
@ -86,10 +77,7 @@ add_task(async function test_wait_import_spotlight() {
|
|||
});
|
||||
const [win] = await spotlightPromise;
|
||||
|
||||
const wizardPromise = BrowserTestUtils.waitForMigrationWizard(
|
||||
window,
|
||||
FORCE_LEGACY
|
||||
);
|
||||
const wizardPromise = BrowserTestUtils.waitForMigrationWizard(window);
|
||||
const prefsTab = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
"about:preferences"
|
||||
|
|
@ -99,7 +87,7 @@ add_task(async function test_wait_import_spotlight() {
|
|||
.click();
|
||||
const wizard = await wizardPromise;
|
||||
|
||||
await BrowserTestUtils.closeMigrationWizard(wizard, FORCE_LEGACY);
|
||||
await BrowserTestUtils.removeTab(wizard);
|
||||
|
||||
// cleanup
|
||||
BrowserTestUtils.removeTab(prefsTab);
|
||||
|
|
|
|||
|
|
@ -1049,7 +1049,7 @@ var gMainPane = {
|
|||
const supportedLanguages =
|
||||
await TranslationsParent.getSupportedLanguages();
|
||||
const languageList =
|
||||
TranslationsState.getLanguageList(supportedLanguages);
|
||||
TranslationsParent.getLanguageList(supportedLanguages);
|
||||
const downloadPhases = await TranslationsState.createDownloadPhases(
|
||||
languageList
|
||||
);
|
||||
|
|
@ -1067,38 +1067,6 @@ var gMainPane = {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a unique list of languages, sorted by the display name.
|
||||
*
|
||||
* @param {Object} supportedLanguages
|
||||
* @returns {Array<{ langTag: string, displayName: string}}
|
||||
*/
|
||||
static getLanguageList(supportedLanguages) {
|
||||
const displayNames = new Map();
|
||||
for (const languages of [
|
||||
supportedLanguages.fromLanguages,
|
||||
supportedLanguages.toLanguages,
|
||||
]) {
|
||||
for (const { langTag, displayName } of languages) {
|
||||
displayNames.set(langTag, displayName);
|
||||
}
|
||||
}
|
||||
|
||||
let appLangTag = new Intl.Locale(Services.locale.appLocaleAsBCP47)
|
||||
.language;
|
||||
|
||||
// Don't offer to download the app's language.
|
||||
displayNames.delete(appLangTag);
|
||||
|
||||
// Sort the list of languages by the display names.
|
||||
return [...displayNames.entries()]
|
||||
.map(([langTag, displayName]) => ({
|
||||
langTag,
|
||||
displayName,
|
||||
}))
|
||||
.sort((a, b) => a.displayName.localeCompare(b.displayName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the download phase of each language file.
|
||||
*
|
||||
|
|
@ -2164,22 +2132,14 @@ var gMainPane = {
|
|||
},
|
||||
|
||||
onMigrationButtonCommand(command) {
|
||||
// When browser.migrate.content-modal.enabled is enabled by default,
|
||||
// the event handler can just call showMigrationWizardDialog directly,
|
||||
// but for now, we delegate to MigrationUtils to open the native modal
|
||||
// in case that's the dialog we're still using.
|
||||
//
|
||||
// Enabling the pref by default will be part of bug 1822156.
|
||||
const browser = window.docShell.chromeEventHandler;
|
||||
const browserWindow = browser.ownerGlobal;
|
||||
// Even though we're going to be showing the migration wizard here in
|
||||
// about:preferences, we'll delegate the call to
|
||||
// `MigrationUtils.showMigrationWizard`, as this will allow us to
|
||||
// properly measure entering the dialog from the PREFERENCES entrypoint.
|
||||
const browserWindow = window.browsingContext.topChromeWindow;
|
||||
|
||||
// showMigrationWizard blocks on some platforms. We'll dispatch the request
|
||||
// to open to a runnable on the main thread so that we don't have to block
|
||||
// this function call.
|
||||
Services.tm.dispatchToMainThread(() => {
|
||||
MigrationUtils.showMigrationWizard(browserWindow, {
|
||||
entrypoint: MigrationUtils.MIGRATION_ENTRYPOINTS.PREFERENCES,
|
||||
});
|
||||
MigrationUtils.showMigrationWizard(browserWindow, {
|
||||
entrypoint: MigrationUtils.MIGRATION_ENTRYPOINTS.PREFERENCES,
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -15,33 +15,6 @@ add_task(async function test_open_migration_wizard() {
|
|||
async function (browser) {
|
||||
let button = browser.contentDocument.getElementById(BUTTON_ID);
|
||||
|
||||
// First, we'll test the legacy Migration Wizard.
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.migrate.content-modal.enabled", false]],
|
||||
});
|
||||
|
||||
let migrationWizardWindow = BrowserTestUtils.domWindowOpenedAndLoaded(
|
||||
null,
|
||||
win => {
|
||||
let type = win.document.documentElement.getAttribute("windowtype");
|
||||
if (type == "Browser:MigrationWizard") {
|
||||
Assert.ok(true, "Saw legacy Migration Wizard window open.");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
button.click();
|
||||
let win = await migrationWizardWindow;
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
|
||||
// Next, we'll test the new Migration Wizard.
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.migrate.content-modal.enabled", true]],
|
||||
});
|
||||
|
||||
let wizardReady = BrowserTestUtils.waitForEvent(
|
||||
browser.contentWindow,
|
||||
"MigrationWizard:Ready"
|
||||
|
|
|
|||
|
|
@ -51,24 +51,22 @@ add_task(async function test_cookie_banners_promo() {
|
|||
});
|
||||
await ASRouter.onPrefChange();
|
||||
|
||||
const { win, tab } = await openTabAndWaitForRender();
|
||||
|
||||
const sandbox = sinon.createSandbox();
|
||||
const expectedUrl = Services.urlFormatter.formatURL(
|
||||
"https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/cookie-banner-reduction"
|
||||
);
|
||||
let tabOpened = new Promise(resolve => {
|
||||
win.gBrowser.tabContainer.addEventListener(
|
||||
"TabOpen",
|
||||
event => {
|
||||
let newTab = event.target;
|
||||
let newBrowser = newTab.linkedBrowser;
|
||||
let result = newTab;
|
||||
BrowserTestUtils.waitForDocLoadAndStopIt(expectedUrl, newBrowser).then(
|
||||
() => resolve(result)
|
||||
);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
|
||||
const { win, tab } = await openTabAndWaitForRender();
|
||||
let triedToOpenTab = new Promise(resolve => {
|
||||
sandbox.stub(win, "openLinkIn").callsFake((url, where) => {
|
||||
is(url, expectedUrl, "The link should open the expected URL");
|
||||
is(
|
||||
where,
|
||||
"tabshifted",
|
||||
"The link should open the expected URL in a new foreground tab"
|
||||
);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
await SpecialPowers.spawn(tab, [promoImgSrc], async function (imgSrc) {
|
||||
|
|
@ -77,10 +75,11 @@ add_task(async function test_cookie_banners_promo() {
|
|||
);
|
||||
ok(promoImage?.src === imgSrc, "Cookie banner reduction promo is shown");
|
||||
let linkEl = content.document.getElementById("private-browsing-promo-link");
|
||||
EventUtils.synthesizeClick(linkEl);
|
||||
linkEl.click();
|
||||
});
|
||||
|
||||
await tabOpened;
|
||||
await triedToOpenTab;
|
||||
sandbox.restore();
|
||||
|
||||
ok(true, "The link was clicked and the new tab opened");
|
||||
|
||||
|
|
|
|||
|
|
@ -645,7 +645,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "a2ff61a05d98f6ac590af31e20b9584f3fc1ce59"
|
||||
"revision": "10247f877325c5d3e2e6421c9fc6f832aecb14c3"
|
||||
},
|
||||
"fur": {
|
||||
"pin": false,
|
||||
|
|
@ -663,7 +663,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "7c858ed3cdb39ba09620131778166de4c5e8c4af"
|
||||
"revision": "81fe64e956bf23f74da866bcdd4465407a6e91db"
|
||||
},
|
||||
"fy-NL": {
|
||||
"pin": false,
|
||||
|
|
@ -753,7 +753,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "0fa7f55ed6790d99b8af40e2dfafd02a4f422991"
|
||||
"revision": "ea5321945f68d7fb674802ad2793cd49deee54f7"
|
||||
},
|
||||
"gu-IN": {
|
||||
"pin": false,
|
||||
|
|
@ -789,7 +789,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "21494472c9e94f59dbdf3b64a3e860914784bd53"
|
||||
"revision": "d7ec09a12940e974bf6611377752f2985331adac"
|
||||
},
|
||||
"hi-IN": {
|
||||
"pin": false,
|
||||
|
|
@ -843,7 +843,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "41292dabca672049b111529a6e43d6d334e70b74"
|
||||
"revision": "2b9fc1dc146113f573fd6d6311de23b044c6d092"
|
||||
},
|
||||
"hu": {
|
||||
"pin": false,
|
||||
|
|
@ -861,7 +861,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "6e2b118c75b97b54a45d7e728393084a30c40394"
|
||||
"revision": "6a7128933727b0c11038544c74ce9f5d8ac8d0b3"
|
||||
},
|
||||
"hy-AM": {
|
||||
"pin": false,
|
||||
|
|
@ -915,7 +915,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "278ffacad10965be4e0b110b37339a6e90fa3d12"
|
||||
"revision": "c9aae1b862b4b239c56cb12fdbc885da88fa25b0"
|
||||
},
|
||||
"id": {
|
||||
"pin": false,
|
||||
|
|
@ -969,7 +969,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "382ca60beb3d4245a903913cd35945792af5a3ce"
|
||||
"revision": "9650cb3d6b2dcb127f9a7af9142306d37a5dc3c2"
|
||||
},
|
||||
"ja": {
|
||||
"pin": false,
|
||||
|
|
@ -1101,7 +1101,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "bc3e11d81961f39ed881baf680a246e6ae814baa"
|
||||
"revision": "962df49c492ee3a57137736546545a910267f95e"
|
||||
},
|
||||
"lij": {
|
||||
"pin": false,
|
||||
|
|
@ -1353,7 +1353,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "197abc4fac9566518e45a7c3ed42603ec82b9928"
|
||||
"revision": "b04979cfb0d8be4dc6be3bc8d9fb33aaefab7dab"
|
||||
},
|
||||
"oc": {
|
||||
"pin": false,
|
||||
|
|
@ -1425,7 +1425,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "e7fb94ac0808d5ba8ee356506798dc1f0aa763d6"
|
||||
"revision": "4ae9f56d370edd85133699018ac0ceec858175f3"
|
||||
},
|
||||
"pt-PT": {
|
||||
"pin": false,
|
||||
|
|
@ -1605,7 +1605,7 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "f84cd60575f1414124959f8edfdcbca42eda6e74"
|
||||
"revision": "fe258f24a71e6584396d3ffcd6a9b7501a78b95f"
|
||||
},
|
||||
"skr": {
|
||||
"pin": false,
|
||||
|
|
@ -2001,6 +2001,6 @@
|
|||
"win64-aarch64-devedition",
|
||||
"win64-devedition"
|
||||
],
|
||||
"revision": "01eac9796780092fdd37978e29a5cd1788aef160"
|
||||
"revision": "c3cbc202fb4b5ed2d6436dcab28f4c9aca2e1e87"
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ export const ThemeVariableMap = [
|
|||
},
|
||||
],
|
||||
[
|
||||
"--lwt-tab-text",
|
||||
"--tab-selected-textcolor",
|
||||
{
|
||||
lwtProperty: "tab_text",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -23,23 +23,6 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
/*
|
||||
This is a workaround for Bug 1482157
|
||||
-moz-default-appearance: toolbox; makes the macOS sheets attached to the
|
||||
element's bottom border. We cannot put this property on the toolbox itself as
|
||||
it cancels all backgrounds that are there, so we set it on the toolbox bottom
|
||||
border.
|
||||
*/
|
||||
#navigator-toolbox::after {
|
||||
content: "";
|
||||
display: flex;
|
||||
appearance: auto;
|
||||
-moz-default-appearance: toolbox;
|
||||
height: 1px;
|
||||
margin-top: -1px;
|
||||
opacity: 0.001;
|
||||
}
|
||||
|
||||
/** Begin titlebar **/
|
||||
|
||||
#titlebar {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
--input-border-color: light-dark(color-mix(in srgb, currentColor 41%, transparent), #8f8f9d);
|
||||
|
||||
--tab-selected-bgcolor: light-dark(rgb(255, 255, 255), rgb(66, 65, 77));
|
||||
--tab-selected-textcolor: light-dark(rgb(21, 20, 26), rgb(251, 251, 254));
|
||||
--tab-icon-overlay-stroke: light-dark(rgb(255, 255, 255), rgb(66, 65, 77));
|
||||
--tab-icon-overlay-fill: light-dark(rgb(91, 91, 102), rgb(251, 251, 254));
|
||||
--tab-attention-icon-color: light-dark(rgb(42, 195, 162), rgb(84, 255, 189));
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@
|
|||
|
||||
#navigator-toolbox {
|
||||
appearance: none;
|
||||
|
||||
/* Toolbar / content area border */
|
||||
border-bottom: 1px solid var(--chrome-content-separator-color);
|
||||
|
||||
|
|
|
|||
|
|
@ -434,12 +434,12 @@ panelview[id^=PanelUI-webext-] {
|
|||
width: 22.5em;
|
||||
}
|
||||
|
||||
#customizationui-widget-multiview panelview:not([extension]) {
|
||||
:where(#customizationui-widget-multiview) panelview:not([extension]) {
|
||||
min-width: var(--menu-panel-width);
|
||||
max-width: 35em;
|
||||
}
|
||||
|
||||
#customizationui-widget-multiview #appMenu-libraryView,
|
||||
#appMenu-libraryView,
|
||||
#pageActionPanel panelview,
|
||||
#widget-overflow panelview {
|
||||
min-width: var(--menu-panel-width-wide);
|
||||
|
|
@ -1987,12 +1987,7 @@ panelview:not([mainview]) #PanelUI-whatsNew-title {
|
|||
|
||||
#reset-pbm-panel {
|
||||
max-width: var(--menu-panel-width-wide);
|
||||
}
|
||||
|
||||
#reset-pbm-panel-container {
|
||||
padding: 16px 16px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -445,8 +445,9 @@
|
|||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.tabbrowser-tab:is([selected], [multiselected]):-moz-lwtheme {
|
||||
color: var(--lwt-tab-text, var(--toolbar-color));
|
||||
#TabsToolbar #firefox-view-button[open] > .toolbarbutton-icon,
|
||||
.tabbrowser-tab:is([selected], [multiselected]) {
|
||||
color: var(--tab-selected-textcolor, var(--toolbar-color));
|
||||
}
|
||||
|
||||
@media (prefers-contrast) {
|
||||
|
|
|
|||
|
|
@ -357,20 +357,26 @@
|
|||
|
||||
/* URL bar and page action buttons */
|
||||
|
||||
/* The background can be very dark and if the add-on uses a black-ish svg it
|
||||
will be barely visible. In the future we should have a standardized SVG
|
||||
solution we can apply to add-on icons, for now we can only try to make them
|
||||
visible through some filtering tricks */
|
||||
:root[lwt-toolbar-field-brighttext] #urlbar:not([focused="true"]) .urlbar-addon-page-action[style*=".svg"] > .urlbar-icon,
|
||||
:root[lwt-toolbar-field-focus-brighttext] #urlbar[focused="true"] .urlbar-addon-page-action[style*=".svg"] > .urlbar-icon {
|
||||
filter: grayscale(100%) brightness(20%) invert();
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
/* As above, but for the default theme in dark mode, which suffers from the same issue */
|
||||
:root:not(:-moz-lwtheme) .urlbar-addon-page-action[style*=".svg"] > .urlbar-icon {
|
||||
/*
|
||||
* The background can be very dark and if the add-on uses a black-ish svg it
|
||||
* will be barely visible. For now we try to make them more visible through
|
||||
* some filtering tricks.
|
||||
*
|
||||
* TODO(emilio): Evaluate removing this. SVGs can use prefers-color-scheme to
|
||||
* determine the right color-scheme to use, see bug 1779457.
|
||||
*/
|
||||
.urlbar-addon-page-action[style*=".svg"] > .urlbar-icon {
|
||||
:root[lwt-toolbar-field="dark"] #urlbar:not([focused="true"]) &,
|
||||
:root[lwt-toolbar-field-focus="dark"] #urlbar[focused="true"] & {
|
||||
filter: grayscale(100%) brightness(20%) invert();
|
||||
}
|
||||
|
||||
/* As above, but for the default theme in dark mode, which suffers from the same issue */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
&:not(:-moz-lwtheme) {
|
||||
filter: grayscale(100%) brightness(20%) invert();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#userContext-icons,
|
||||
|
|
|
|||
|
|
@ -30,21 +30,29 @@
|
|||
}
|
||||
}
|
||||
|
||||
@media not (prefers-contrast) {
|
||||
/* Use a different color in inactive windows. */
|
||||
#toolbar-menubar:not(:-moz-lwtheme):-moz-window-inactive {
|
||||
color: ThreeDShadow;
|
||||
}
|
||||
@media (-moz-windows-accent-color-in-titlebar) {
|
||||
:root[tabsintitlebar] {
|
||||
@media (-moz-windows-accent-color-in-tabs) {
|
||||
--toolbox-non-lwt-bgcolor: ActiveCaption;
|
||||
--toolbox-non-lwt-textcolor: CaptionText;
|
||||
--toolbox-non-lwt-bgcolor-inactive: InactiveCaption;
|
||||
--toolbox-non-lwt-textcolor-inactive: InactiveCaptionText;
|
||||
}
|
||||
|
||||
@media (-moz-windows-accent-color-in-titlebar) {
|
||||
:root[sizemode=normal][tabsintitlebar] #navigator-toolbox {
|
||||
&[sizemode="normal"] #navigator-toolbox {
|
||||
border-top: .5px solid ActiveBorder;
|
||||
|
||||
&:-moz-window-inactive {
|
||||
border-top-color: InactiveBorder;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media not (prefers-contrast) {
|
||||
/* Use a different color in inactive windows. */
|
||||
#toolbar-menubar:not(:-moz-lwtheme):-moz-window-inactive {
|
||||
color: ThreeDShadow;
|
||||
}
|
||||
|
||||
:root[tabsintitlebar] .tab-label-container:-moz-window-inactive {
|
||||
/* Calculated to match the opacity change of Windows Explorer
|
||||
|
|
|
|||
8
build/rust/backtrace/Cargo.toml
Normal file
8
build/rust/backtrace/Cargo.toml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "backtrace"
|
||||
version = "0.3.999"
|
||||
edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
0
build/rust/backtrace/lib.rs
Normal file
0
build/rust/backtrace/lib.rs
Normal file
|
|
@ -713,8 +713,8 @@ EventSourceImpl::OnStartRequest(nsIRequest* aRequest) {
|
|||
|
||||
if (NS_FAILED(status)) {
|
||||
// EventSource::OnStopRequest will evaluate if it shall either reestablish
|
||||
// or fail the connection
|
||||
return NS_ERROR_ABORT;
|
||||
// or fail the connection, based on the status.
|
||||
return status;
|
||||
}
|
||||
|
||||
uint32_t httpStatus;
|
||||
|
|
|
|||
|
|
@ -147,3 +147,5 @@ skip-if = ["verify"]
|
|||
["browser_user_input_handling_delay_reload_ticks.js"]
|
||||
|
||||
["browser_xml_toggle.js"]
|
||||
|
||||
["browser_event_source_reconnect_after_disconnect.js"]
|
||||
|
|
|
|||
108
dom/base/test/browser_event_source_reconnect_after_disconnect.js
Normal file
108
dom/base/test/browser_event_source_reconnect_after_disconnect.js
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
var { HttpServer } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/httpd.sys.mjs"
|
||||
);
|
||||
|
||||
function eventSourcePageHandler(metadata, response) {
|
||||
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
|
||||
// An HTML page that sets up the EventSource
|
||||
let pageContent = `
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
let es = new EventSource("/eventstream");
|
||||
es.onopen = function() {
|
||||
console.log("send es_open");
|
||||
window.dispatchEvent(new CustomEvent('es-open'));
|
||||
};
|
||||
es.onmessage = function(err) {
|
||||
console.log("send es_message");
|
||||
window.dispatchEvent(new CustomEvent('es-message'));
|
||||
};
|
||||
es.onerror = function(err) {
|
||||
console.log("send es_error");
|
||||
window.dispatchEvent(new CustomEvent('es-error'));
|
||||
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
response.write(pageContent);
|
||||
}
|
||||
|
||||
const server = new HttpServer();
|
||||
server.start(-1);
|
||||
const SERVER_PORT = server.identity.primaryPort;
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await server.stop();
|
||||
});
|
||||
|
||||
function eventStreamHandler(metadata, response) {
|
||||
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/event-stream", false);
|
||||
response.write("retry: 500\n");
|
||||
}
|
||||
|
||||
server.registerPathHandler("/page", eventSourcePageHandler);
|
||||
server.registerPathHandler("/eventstream", eventStreamHandler);
|
||||
|
||||
add_task(async function testReconnectAfterDisconnect() {
|
||||
info("Connect to the server to retrieve the EventSource doc");
|
||||
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
`http://localhost:${server.identity.primaryPort}/page`
|
||||
);
|
||||
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
// Define a function to handle events in the content process
|
||||
async function contentEventHandler() {
|
||||
return new Promise(resolve => {
|
||||
content.addEventListener(
|
||||
"es-open",
|
||||
function () {
|
||||
resolve("es-open");
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
|
||||
content.addEventListener(
|
||||
"es-error",
|
||||
function () {
|
||||
resolve("es-error");
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Execute the event handler in the content process
|
||||
let eventType = await SpecialPowers.spawn(browser, [], contentEventHandler);
|
||||
Assert.equal(eventType, "es-open", "EventSource opened successfully");
|
||||
|
||||
// Stop the server; we expect an error
|
||||
await server.stop();
|
||||
|
||||
eventType = await SpecialPowers.spawn(browser, [], contentEventHandler);
|
||||
Assert.equal(
|
||||
eventType,
|
||||
"es-error",
|
||||
"EventSource encountered an error after server close"
|
||||
);
|
||||
|
||||
// Restart the server; the eventSource should automatically reconnect
|
||||
server.start(SERVER_PORT);
|
||||
|
||||
eventType = await SpecialPowers.spawn(browser, [], contentEventHandler);
|
||||
Assert.equal(
|
||||
eventType,
|
||||
"es-open",
|
||||
"EventSource opened successfully after server restart"
|
||||
);
|
||||
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
|
@ -80,6 +80,18 @@ void ImageBitmapRenderingContext::TransferFromImageBitmap(
|
|||
return;
|
||||
}
|
||||
|
||||
// Note that this is reentrant and will call back into SetDimensions.
|
||||
if (mCanvasElement) {
|
||||
mCanvasElement->SetSize(mImage->GetSize(), aRv);
|
||||
} else if (mOffscreenCanvas) {
|
||||
mOffscreenCanvas->SetSize(mImage->GetSize(), aRv);
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
mImage = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (aImageBitmap->IsWriteOnly()) {
|
||||
if (mCanvasElement) {
|
||||
mCanvasElement->SetWriteOnly();
|
||||
|
|
@ -96,6 +108,16 @@ NS_IMETHODIMP
|
|||
ImageBitmapRenderingContext::SetDimensions(int32_t aWidth, int32_t aHeight) {
|
||||
mWidth = aWidth;
|
||||
mHeight = aHeight;
|
||||
|
||||
if (mOffscreenCanvas) {
|
||||
OffscreenCanvasDisplayData data;
|
||||
data.mSize = {mWidth, mHeight};
|
||||
data.mIsOpaque = GetIsOpaque();
|
||||
data.mIsAlphaPremult = true;
|
||||
data.mDoPaintCallbacks = false;
|
||||
mOffscreenCanvas->UpdateDisplayData(data);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,6 +147,23 @@ void OffscreenCanvas::SetHeight(uint32_t aHeight, ErrorResult& aRv) {
|
|||
CanvasAttrChanged();
|
||||
}
|
||||
|
||||
void OffscreenCanvas::SetSize(const nsIntSize& aSize, ErrorResult& aRv) {
|
||||
if (mNeutered) {
|
||||
aRv.ThrowInvalidStateError(
|
||||
"Cannot set dimensions of placeholder canvas transferred to worker.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(aSize.IsEmpty())) {
|
||||
aRv.ThrowRangeError("OffscreenCanvas size is empty, must be non-empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
mWidth = aSize.width;
|
||||
mHeight = aSize.height;
|
||||
CanvasAttrChanged();
|
||||
}
|
||||
|
||||
void OffscreenCanvas::GetContext(
|
||||
JSContext* aCx, const OffscreenRenderingContextId& aContextId,
|
||||
JS::Handle<JS::Value> aContextOptions,
|
||||
|
|
|
|||
|
|
@ -150,6 +150,8 @@ class OffscreenCanvas final : public DOMEventTargetHelper,
|
|||
|
||||
bool MayNeuter() const { return !mNeutered && !mCurrentContext; }
|
||||
|
||||
void SetSize(const nsIntSize& aSize, ErrorResult& aRv);
|
||||
|
||||
nsIPrincipal* GetExpandedReader() const { return mExpandedReader; }
|
||||
|
||||
void SetWriteOnly(RefPtr<nsIPrincipal>&& aExpandedReader);
|
||||
|
|
|
|||
|
|
@ -43,11 +43,11 @@ function runTest(canvasWidth, canvasHeight, nextTest) {
|
|||
ctx.fillStyle = "#00FF00";
|
||||
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
|
||||
|
||||
var canvasRef = createCanvas(90, 90);
|
||||
var canvasRef = createCanvas(canvasWidth, canvasHeight);
|
||||
var ctx = canvasRef.getContext("2d");
|
||||
// Clear with black transparent first
|
||||
ctx.fillStyle = "rgba(0, 0, 0, 0)";
|
||||
ctx.fillRect(0, 0, 90, 90);
|
||||
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
|
||||
|
||||
ctx.fillStyle = "#00FF00";
|
||||
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
|
||||
|
|
@ -89,52 +89,58 @@ function runTest(canvasWidth, canvasHeight, nextTest) {
|
|||
});
|
||||
}
|
||||
|
||||
function scaleTest() {
|
||||
var canvas1 = createCanvas(64, 64);
|
||||
var ctx = canvas1.getContext("2d");
|
||||
function createSolidGreenBitmap(width, height) {
|
||||
const canvas = createCanvas(width, height);
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.fillStyle = "#00FF00";
|
||||
ctx.fillRect(0, 0, 64, 64);
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
const bitmap = createImageBitmap(canvas);
|
||||
document.body.removeChild(canvas);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
var canvas2 = createCanvas(64, 64);
|
||||
var ctx2 = canvas2.getContext("2d");
|
||||
ctx2.fillStyle = "#00FF00";
|
||||
ctx2.fillRect(0, 0, 64, 64);
|
||||
async function scaleTestCase(name, refWidth, refHeight, testWidth, testHeight, canvasWidth, canvasHeight) {
|
||||
const refBitmap = await createSolidGreenBitmap(refWidth, refHeight);
|
||||
const refCanvas = createCanvas(refWidth, refHeight);
|
||||
const refCtx = refCanvas.getContext("bitmaprenderer");
|
||||
refCtx.transferFromImageBitmap(refBitmap);
|
||||
is(refCanvas.width, refWidth, name + ": refCanvas width " + refCanvas.width + " is ref " + refWidth);
|
||||
is(refCanvas.height, refHeight, name + ": refCanvas height " + refCanvas.height + " is ref " + refHeight);
|
||||
const refSnapshot = await snapshotWindow(window);
|
||||
document.body.removeChild(refCanvas);
|
||||
|
||||
var p1 = createImageBitmap(canvas1);
|
||||
var p2 = createImageBitmap(canvas2);
|
||||
Promise.all([p1, p2]).then(async function(bitmaps) {
|
||||
document.body.removeChild(canvas1);
|
||||
document.body.removeChild(canvas2);
|
||||
const bitmap = await createSolidGreenBitmap(testWidth, testHeight);
|
||||
const canvas = createCanvas(canvasWidth, canvasHeight);
|
||||
const ctx = canvas.getContext("bitmaprenderer");
|
||||
ctx.transferFromImageBitmap(bitmap);
|
||||
is(canvas.width, testWidth, name + ": canvas width " + canvas.width + " is bitmap " + testWidth);
|
||||
is(canvas.height, testHeight, name + ": canvas height " + canvas.height + " is bitmap " + testHeight);
|
||||
if (refWidth !== testWidth) {
|
||||
canvas.width = refWidth;
|
||||
is(canvas.width, refWidth, name + ": canvas width " + canvas.width + " is ref " + refWidth);
|
||||
}
|
||||
if (refHeight !== testHeight) {
|
||||
canvas.height = refHeight;
|
||||
is(canvas.height, refHeight, name + ": canvas height " + canvas.height + " is ref " + refHeight);
|
||||
}
|
||||
const snapshot = await snapshotWindow(window);
|
||||
document.body.removeChild(canvas);
|
||||
|
||||
// Create a large canvas then shrink.
|
||||
var canvas3 = createCanvas(128, 128);
|
||||
var ctx3 = canvas3.getContext("bitmaprenderer");
|
||||
ctx3.transferFromImageBitmap(bitmaps[0]);
|
||||
var snapshotLargeRef = await snapshotWindow(window);
|
||||
const results = compareSnapshots(snapshot, refSnapshot, true);
|
||||
ok(results[0], name + ": screenshots should be the same");
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
canvas3.width = 32;
|
||||
canvas3.height = 32;
|
||||
var snapshotSmall = await snapshotWindow(window);
|
||||
document.body.removeChild(canvas3);
|
||||
|
||||
// Create a small canvas then grow.
|
||||
var canvas4 = createCanvas(32, 32);
|
||||
var ctx4 = canvas4.getContext("bitmaprenderer");
|
||||
ctx4.transferFromImageBitmap(bitmaps[1]);
|
||||
var snapshotSmallRef = await snapshotWindow(window);
|
||||
|
||||
canvas4.width = 128;
|
||||
canvas4.height = 128;
|
||||
var snapshotLarge = await snapshotWindow(window);
|
||||
document.body.removeChild(canvas4);
|
||||
|
||||
var resultsLarge = compareSnapshots(snapshotLarge, snapshotLargeRef, true);
|
||||
ok(resultsLarge[0], "Screenshots should be the same");
|
||||
|
||||
var resultsSmall = compareSnapshots(snapshotSmall, snapshotSmallRef, true);
|
||||
ok(resultsSmall[0], "Screenshots should be the same");
|
||||
runTestOnWorker();
|
||||
});
|
||||
async function scaleTest() {
|
||||
await scaleTestCase("grow_unscaled", 64, 64, 64, 64, 32, 32); // Canvas grows, no scaling.
|
||||
await scaleTestCase("grow_downscaled", 64, 64, 128, 128, 32, 32); // Canvas grows, scales down.
|
||||
await scaleTestCase("grow_upscaled", 64, 64, 32, 32, 16, 16); // Canvas grows, scales up.
|
||||
await scaleTestCase("same_downscaled", 64, 64, 128, 128, 128, 128); // Canvas unchanged, scales down.
|
||||
await scaleTestCase("same_upscaled", 64, 64, 32, 32, 32, 32); // Canvas unchanged, scales up.
|
||||
await scaleTestCase("shrink_unscaled", 64, 64, 64, 64, 128, 128); // Canvas shrinks, no scaling.
|
||||
await scaleTestCase("shrink_downscaled", 64, 64, 128, 128, 256, 256); // Canvas shrinks, scales down.
|
||||
await scaleTestCase("shrink_upscaled", 64, 64, 32, 32, 256, 256); // Canvas shrinks, scales up.
|
||||
runTestOnWorker();
|
||||
}
|
||||
|
||||
function runTestOnWorker() {
|
||||
|
|
|
|||
|
|
@ -1104,6 +1104,26 @@ void HTMLCanvasElement::SetHeight(uint32_t aHeight, ErrorResult& aRv) {
|
|||
SetUnsignedIntAttr(nsGkAtoms::height, aHeight, DEFAULT_CANVAS_HEIGHT, aRv);
|
||||
}
|
||||
|
||||
void HTMLCanvasElement::SetSize(const nsIntSize& aSize, ErrorResult& aRv) {
|
||||
if (mOffscreenCanvas) {
|
||||
aRv.ThrowInvalidStateError(
|
||||
"Cannot set width of placeholder canvas transferred to "
|
||||
"OffscreenCanvas.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(aSize.IsEmpty())) {
|
||||
aRv.ThrowRangeError("Canvas size is empty, must be non-empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
SetUnsignedIntAttr(nsGkAtoms::width, aSize.width, DEFAULT_CANVAS_WIDTH, aRv);
|
||||
MOZ_ASSERT(!aRv.Failed());
|
||||
SetUnsignedIntAttr(nsGkAtoms::height, aSize.height, DEFAULT_CANVAS_HEIGHT,
|
||||
aRv);
|
||||
MOZ_ASSERT(!aRv.Failed());
|
||||
}
|
||||
|
||||
void HTMLCanvasElement::FlushOffscreenCanvas() {
|
||||
if (mOffscreenDisplay) {
|
||||
mOffscreenDisplay->FlushForDisplay();
|
||||
|
|
|
|||
|
|
@ -175,6 +175,11 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,
|
|||
*/
|
||||
nsIntSize GetSize();
|
||||
|
||||
/**
|
||||
* Set the size in pixels of this canvas element.
|
||||
*/
|
||||
void SetSize(const nsIntSize& aSize, ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Determine whether the canvas is write-only.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -486,6 +486,8 @@ class MediaTrack : public mozilla::LinkedListElement<MediaTrack> {
|
|||
*/
|
||||
virtual void DecrementSuspendCount();
|
||||
|
||||
class ControlMessageInterface;
|
||||
|
||||
protected:
|
||||
// Called on graph thread either during destroy handling or before handing
|
||||
// graph control to the main thread to release tracks.
|
||||
|
|
@ -1174,6 +1176,31 @@ class MediaTrackGraph {
|
|||
const TrackRate mSampleRate;
|
||||
};
|
||||
|
||||
/**
|
||||
* This represents a message run on the graph thread to modify track or graph
|
||||
* state. These are passed from main thread to graph thread through
|
||||
* AppendMessage(), or scheduled on the graph thread with
|
||||
* RunMessageAfterProcessing().
|
||||
*/
|
||||
class MediaTrack::ControlMessageInterface {
|
||||
public:
|
||||
MOZ_COUNTED_DEFAULT_CTOR(ControlMessageInterface)
|
||||
// All these run on the graph thread unless the graph has been forced to
|
||||
// shut down.
|
||||
MOZ_COUNTED_DTOR_VIRTUAL(ControlMessageInterface)
|
||||
// Do the action of this message on the MediaTrackGraph thread. Any actions
|
||||
// affecting graph processing should take effect at mProcessedTime.
|
||||
// All track data for times < mProcessedTime has already been
|
||||
// computed.
|
||||
virtual void Run() = 0;
|
||||
// RunDuringShutdown() is only relevant to messages generated on the main
|
||||
// thread (for AppendMessage()).
|
||||
// When we're shutting down the application, most messages are ignored but
|
||||
// some cleanup messages should still be processed (on the main thread).
|
||||
// This must not add new control messages to the graph.
|
||||
virtual void RunDuringShutdown() {}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* MOZILLA_MEDIATRACKGRAPH_H_ */
|
||||
|
|
|
|||
|
|
@ -75,31 +75,17 @@ struct TrackUpdate {
|
|||
* RunMessageAfterProcessing(). A ControlMessage
|
||||
* always has a weak reference to a particular affected track.
|
||||
*/
|
||||
class ControlMessage {
|
||||
class ControlMessage : public MediaTrack::ControlMessageInterface {
|
||||
public:
|
||||
explicit ControlMessage(MediaTrack* aTrack) : mTrack(aTrack) {
|
||||
MOZ_COUNT_CTOR(ControlMessage);
|
||||
}
|
||||
// All these run on the graph thread
|
||||
MOZ_COUNTED_DTOR_VIRTUAL(ControlMessage)
|
||||
// Do the action of this message on the MediaTrackGraph thread. Any actions
|
||||
// affecting graph processing should take effect at mProcessedTime.
|
||||
// All track data for times < mProcessedTime has already been
|
||||
// computed.
|
||||
virtual void Run() = 0;
|
||||
// RunDuringShutdown() is only relevant to messages generated on the main
|
||||
// thread (for AppendMessage()).
|
||||
// When we're shutting down the application, most messages are ignored but
|
||||
// some cleanup messages should still be processed (on the main thread).
|
||||
// This must not add new control messages to the graph.
|
||||
virtual void RunDuringShutdown() {}
|
||||
explicit ControlMessage(MediaTrack* aTrack) : mTrack(aTrack) {}
|
||||
|
||||
MediaTrack* GetTrack() { return mTrack; }
|
||||
|
||||
protected:
|
||||
// We do not hold a reference to mTrack. The graph will be holding a reference
|
||||
// to the track until the Destroy message is processed. The last message
|
||||
// referencing a track is the Destroy message for that track.
|
||||
MediaTrack* mTrack;
|
||||
MediaTrack* const mTrack;
|
||||
};
|
||||
|
||||
class MessageBlock {
|
||||
|
|
@ -123,6 +109,8 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
|
|||
public nsITimerCallback,
|
||||
public nsINamed {
|
||||
public:
|
||||
using ControlMessageInterface = MediaTrack::ControlMessageInterface;
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIMEMORYREPORTER
|
||||
NS_DECL_NSITHREADOBSERVER
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ static void UpdateCodecSpecificInfo(webrtc::CodecSpecificInfo& aInfo,
|
|||
vp9.temporal_idx = webrtc::kNoTemporalIdx;
|
||||
vp9.temporal_up_switch = false;
|
||||
vp9.num_spatial_layers = 1;
|
||||
vp9.end_of_picture = true;
|
||||
aInfo.end_of_picture = true;
|
||||
vp9.gof_idx = webrtc::kNoGofIdx;
|
||||
vp9.width[0] = aSize.width;
|
||||
vp9.height[0] = aSize.height;
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@ FilenameTypeAndDetails nsContentSecurityUtils::FilenameToFilenameType(
|
|||
return FilenameTypeAndDetails(kOther, Nothing());
|
||||
}
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
#if defined(EARLY_BETA_OR_EARLIER)
|
||||
// Crash String must be safe from a telemetry point of view.
|
||||
// This will be ensured when this function is used.
|
||||
void PossiblyCrash(const char* aPrefSuffix, const char* aUnsafeCrashString,
|
||||
|
|
@ -1541,7 +1541,7 @@ bool nsContentSecurityUtils::ValidateScriptFilename(JSContext* cx,
|
|||
: "(None)",
|
||||
"Blocking a script load %s from file %s");
|
||||
MOZ_CRASH_UNSAFE_PRINTF("%s", crashString.get());
|
||||
#elif defined(NIGHTLY_BUILD)
|
||||
#elif defined(EARLY_BETA_OR_EARLIER)
|
||||
// Cause a crash (if we've never crashed before and we can ensure we won't do
|
||||
// it again.)
|
||||
// The details in the second arg, passed to UNSAFE_PRINTF, are also included
|
||||
|
|
|
|||
|
|
@ -127,6 +127,8 @@ already_AddRefed<Buffer> Buffer::Create(Device* aDevice, RawId aDeviceId,
|
|||
buffer->SetMapped(0, aDesc.mSize, writable);
|
||||
}
|
||||
|
||||
aDevice->TrackBuffer(buffer.get());
|
||||
|
||||
return buffer.forget();
|
||||
}
|
||||
|
||||
|
|
@ -144,9 +146,12 @@ void Buffer::Drop() {
|
|||
}
|
||||
mMapped.reset();
|
||||
|
||||
if (mValid && !GetDevice().IsLost()) {
|
||||
if (mValid && GetDevice().IsBridgeAlive()) {
|
||||
GetDevice().GetBridge()->SendBufferDrop(mId);
|
||||
}
|
||||
|
||||
GetDevice().UntrackBuffer(this);
|
||||
|
||||
mValid = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,14 +69,6 @@ void Device::Cleanup() {
|
|||
if (mBridge) {
|
||||
mBridge->UnregisterDevice(mId);
|
||||
}
|
||||
|
||||
// Cycle collection may have disconnected the promise object.
|
||||
if (mLostPromise && mLostPromise->PromiseObj() != nullptr) {
|
||||
auto info = MakeRefPtr<DeviceLostInfo>(GetParentObject(),
|
||||
dom::GPUDeviceLostReason::Destroyed,
|
||||
u"Device destroyed"_ns);
|
||||
mLostPromise->MaybeResolve(info);
|
||||
}
|
||||
}
|
||||
|
||||
void Device::CleanupUnregisteredInParent() {
|
||||
|
|
@ -86,19 +78,29 @@ void Device::CleanupUnregisteredInParent() {
|
|||
mValid = false;
|
||||
}
|
||||
|
||||
bool Device::IsLost() const { return !mBridge || !mBridge->CanSend(); }
|
||||
bool Device::IsLost() const {
|
||||
return !mBridge || !mBridge->CanSend() ||
|
||||
(mLostPromise &&
|
||||
(mLostPromise->State() != dom::Promise::PromiseState::Pending));
|
||||
}
|
||||
|
||||
bool Device::IsBridgeAlive() const { return mBridge && mBridge->CanSend(); }
|
||||
|
||||
// Generate an error on the Device timeline for this device.
|
||||
//
|
||||
// aMessage is interpreted as UTF-8.
|
||||
void Device::GenerateValidationError(const nsCString& aMessage) {
|
||||
if (IsLost()) {
|
||||
if (!IsBridgeAlive()) {
|
||||
return; // Just drop it?
|
||||
}
|
||||
mBridge->SendGenerateError(Some(mId), dom::GPUErrorFilter::Validation,
|
||||
aMessage);
|
||||
}
|
||||
|
||||
void Device::TrackBuffer(Buffer* aBuffer) { mTrackedBuffers.Insert(aBuffer); }
|
||||
|
||||
void Device::UntrackBuffer(Buffer* aBuffer) { mTrackedBuffers.Remove(aBuffer); }
|
||||
|
||||
void Device::GetLabel(nsAString& aValue) const { aValue = mLabel; }
|
||||
void Device::SetLabel(const nsAString& aLabel) { mLabel = aLabel; }
|
||||
|
||||
|
|
@ -114,6 +116,32 @@ dom::Promise* Device::GetLost(ErrorResult& aRv) {
|
|||
return mLostPromise;
|
||||
}
|
||||
|
||||
void Device::ResolveLost(Maybe<dom::GPUDeviceLostReason> aReason,
|
||||
const nsAString& aMessage) {
|
||||
ErrorResult rv;
|
||||
dom::Promise* lostPromise = GetLost(rv);
|
||||
if (!lostPromise) {
|
||||
// Promise doesn't exist? Maybe out of memory.
|
||||
return;
|
||||
}
|
||||
if (lostPromise->State() != dom::Promise::PromiseState::Pending) {
|
||||
// lostPromise was already resolved or rejected.
|
||||
return;
|
||||
}
|
||||
if (!lostPromise->PromiseObj()) {
|
||||
// The underlying JS object is gone.
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<DeviceLostInfo> info;
|
||||
if (aReason.isSome()) {
|
||||
info = MakeRefPtr<DeviceLostInfo>(GetParentObject(), *aReason, aMessage);
|
||||
} else {
|
||||
info = MakeRefPtr<DeviceLostInfo>(GetParentObject(), aMessage);
|
||||
}
|
||||
lostPromise->MaybeResolve(info);
|
||||
}
|
||||
|
||||
already_AddRefed<Buffer> Device::CreateBuffer(
|
||||
const dom::GPUBufferDescriptor& aDesc, ErrorResult& aRv) {
|
||||
return Buffer::Create(this, mId, aDesc, aRv);
|
||||
|
|
@ -334,11 +362,25 @@ bool Device::CheckNewWarning(const nsACString& aMessage) {
|
|||
}
|
||||
|
||||
void Device::Destroy() {
|
||||
// TODO
|
||||
if (IsLost()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Unmap all buffers from this device, as specified by
|
||||
// https://gpuweb.github.io/gpuweb/#dom-gpudevice-destroy.
|
||||
dom::AutoJSAPI jsapi;
|
||||
if (jsapi.Init(GetOwnerGlobal())) {
|
||||
IgnoredErrorResult rv;
|
||||
for (const auto& buffer : mTrackedBuffers) {
|
||||
buffer->Unmap(jsapi.cx(), rv);
|
||||
}
|
||||
}
|
||||
|
||||
mBridge->SendDeviceDestroy(mId);
|
||||
}
|
||||
|
||||
void Device::PushErrorScope(const dom::GPUErrorFilter& aFilter) {
|
||||
if (IsLost()) {
|
||||
if (!IsBridgeAlive()) {
|
||||
return;
|
||||
}
|
||||
mBridge->SendDevicePushErrorScope(mId, aFilter);
|
||||
|
|
@ -357,7 +399,7 @@ already_AddRefed<dom::Promise> Device::PopErrorScope(ErrorResult& aRv) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (IsLost()) {
|
||||
if (!IsBridgeAlive()) {
|
||||
WebGPUChild::JsWarning(
|
||||
GetOwnerGlobal(),
|
||||
"popErrorScope resolving to null because device is already lost."_ns);
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class Promise;
|
|||
template <typename T>
|
||||
class Sequence;
|
||||
class GPUBufferOrGPUTexture;
|
||||
enum class GPUDeviceLostReason : uint8_t;
|
||||
enum class GPUErrorFilter : uint8_t;
|
||||
enum class GPUFeatureName : uint8_t;
|
||||
class GPULogCallback;
|
||||
|
|
@ -102,8 +103,11 @@ class Device final : public DOMEventTargetHelper, public SupportsWeakPtr {
|
|||
void CleanupUnregisteredInParent();
|
||||
|
||||
void GenerateValidationError(const nsCString& aMessage);
|
||||
void TrackBuffer(Buffer* aBuffer);
|
||||
void UntrackBuffer(Buffer* aBuffer);
|
||||
|
||||
bool IsLost() const;
|
||||
bool IsBridgeAlive() const;
|
||||
|
||||
private:
|
||||
~Device();
|
||||
|
|
@ -115,12 +119,14 @@ class Device final : public DOMEventTargetHelper, public SupportsWeakPtr {
|
|||
RefPtr<dom::Promise> mLostPromise;
|
||||
RefPtr<Queue> mQueue;
|
||||
nsTHashSet<nsCString> mKnownWarnings;
|
||||
nsTHashSet<Buffer*> mTrackedBuffers;
|
||||
|
||||
public:
|
||||
void GetLabel(nsAString& aValue) const;
|
||||
void SetLabel(const nsAString& aLabel);
|
||||
dom::Promise* GetLost(ErrorResult& aRv);
|
||||
dom::Promise* MaybeGetLost() const { return mLostPromise; }
|
||||
void ResolveLost(Maybe<dom::GPUDeviceLostReason> aReason,
|
||||
const nsAString& aMessage);
|
||||
|
||||
const RefPtr<SupportedFeatures>& Features() const { return mFeatures; }
|
||||
const RefPtr<SupportedLimits>& Limits() const { return mLimits; }
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/gfx/CanvasManagerChild.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
|
@ -25,6 +26,18 @@ static inline nsDependentCString ToCString(const std::string_view s) {
|
|||
return {s.data(), s.length()};
|
||||
}
|
||||
|
||||
/* static */ bool Instance::PrefEnabled(JSContext* aCx, JSObject* aObj) {
|
||||
if (!StaticPrefs::dom_webgpu_enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return StaticPrefs::dom_webgpu_workers_enabled();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
already_AddRefed<Instance> Instance::Create(nsIGlobalObject* aOwner) {
|
||||
RefPtr<Instance> result = new Instance(aOwner);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ class Instance final : public nsWrapperCache {
|
|||
|
||||
nsIGlobalObject* GetParentObject() const { return mOwner; }
|
||||
|
||||
static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
static already_AddRefed<Instance> Create(nsIGlobalObject* aOwner);
|
||||
|
||||
already_AddRefed<dom::Promise> RequestAdapter(
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ parent:
|
|||
async TextureViewDestroy(RawId selfId);
|
||||
async SamplerDestroy(RawId selfId);
|
||||
async DeviceDestroy(RawId selfId);
|
||||
async DeviceDrop(RawId selfId);
|
||||
|
||||
async CommandEncoderFinish(RawId selfId, RawId deviceId, GPUCommandBufferDescriptor desc);
|
||||
async CommandEncoderDestroy(RawId selfId);
|
||||
|
|
@ -89,6 +90,7 @@ parent:
|
|||
child:
|
||||
async UncapturedError(RawId? aDeviceId, nsCString message);
|
||||
async DropAction(ByteBuf buf);
|
||||
async DeviceLost(RawId aDeviceId, uint8_t? reason, nsCString message);
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1128,6 +1128,29 @@ ipc::IPCResult WebGPUChild::RecvDropAction(const ipc::ByteBuf& aByteBuf) {
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
ipc::IPCResult WebGPUChild::RecvDeviceLost(RawId aDeviceId,
|
||||
Maybe<uint8_t> aReason,
|
||||
const nsACString& aMessage) {
|
||||
RefPtr<Device> device;
|
||||
const auto itr = mDeviceMap.find(aDeviceId);
|
||||
if (itr != mDeviceMap.end()) {
|
||||
device = itr->second.get();
|
||||
MOZ_ASSERT(device);
|
||||
}
|
||||
|
||||
if (device) {
|
||||
auto message = NS_ConvertUTF8toUTF16(aMessage);
|
||||
if (aReason.isSome()) {
|
||||
dom::GPUDeviceLostReason reason =
|
||||
static_cast<dom::GPUDeviceLostReason>(*aReason);
|
||||
device->ResolveLost(Some(reason), message);
|
||||
} else {
|
||||
device->ResolveLost(Nothing(), message);
|
||||
}
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void WebGPUChild::DeviceCreateSwapChain(
|
||||
RawId aSelfId, const RGBDescriptor& aRgbDesc, size_t maxBufferCount,
|
||||
const layers::RemoteTextureOwnerId& aOwnerId,
|
||||
|
|
@ -1168,7 +1191,7 @@ void WebGPUChild::RegisterDevice(Device* const aDevice) {
|
|||
void WebGPUChild::UnregisterDevice(RawId aId) {
|
||||
mDeviceMap.erase(aId);
|
||||
if (IsOpen()) {
|
||||
SendDeviceDestroy(aId);
|
||||
SendDeviceDrop(aId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1192,17 +1215,7 @@ void WebGPUChild::ActorDestroy(ActorDestroyReason) {
|
|||
continue;
|
||||
}
|
||||
|
||||
RefPtr<dom::Promise> promise = device->MaybeGetLost();
|
||||
if (!promise) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto info = MakeRefPtr<DeviceLostInfo>(device->GetParentObject(),
|
||||
u"WebGPUChild destroyed"_ns);
|
||||
|
||||
// We have strong references to both the Device and the DeviceLostInfo and
|
||||
// the Promise objects on the stack which keeps them alive for long enough.
|
||||
promise->MaybeResolve(info);
|
||||
device->ResolveLost(Nothing(), u"WebGPUChild destroyed"_ns);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -144,6 +144,8 @@ class WebGPUChild final : public PWebGPUChild, public SupportsWeakPtr {
|
|||
ipc::IPCResult RecvUncapturedError(Maybe<RawId> aDeviceId,
|
||||
const nsACString& aMessage);
|
||||
ipc::IPCResult RecvDropAction(const ipc::ByteBuf& aByteBuf);
|
||||
ipc::IPCResult RecvDeviceLost(RawId aDeviceId, Maybe<uint8_t> aReason,
|
||||
const nsACString& aMessage);
|
||||
void ActorDestroy(ActorDestroyReason) override;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ class ErrorBuffer {
|
|||
ffi::WGPUErrorBufferType aType) {
|
||||
switch (aType) {
|
||||
case ffi::WGPUErrorBufferType_None:
|
||||
case ffi::WGPUErrorBufferType_DeviceLost:
|
||||
return {};
|
||||
case ffi::WGPUErrorBufferType_Internal:
|
||||
return Some(dom::GPUErrorFilter::Internal);
|
||||
|
|
@ -107,6 +108,7 @@ class ErrorBuffer {
|
|||
|
||||
struct Error {
|
||||
dom::GPUErrorFilter type;
|
||||
bool isDeviceLost;
|
||||
nsCString message;
|
||||
};
|
||||
|
||||
|
|
@ -118,11 +120,19 @@ class ErrorBuffer {
|
|||
// won't assert.
|
||||
Maybe<Error> GetError() {
|
||||
mAwaitingGetError = false;
|
||||
if (mType == ffi::WGPUErrorBufferType_DeviceLost) {
|
||||
// This error is for a lost device, so we return an Error struct
|
||||
// with the isDeviceLost bool set to true. It doesn't matter what
|
||||
// GPUErrorFilter type we use, so we just use Validation. The error
|
||||
// will not be reported.
|
||||
return Some(Error{dom::GPUErrorFilter::Validation, true,
|
||||
nsCString{mMessageUtf8}});
|
||||
}
|
||||
auto filterType = ErrorTypeToFilterType(mType);
|
||||
if (!filterType) {
|
||||
return {};
|
||||
}
|
||||
return Some(Error{*filterType, nsCString{mMessageUtf8}});
|
||||
return Some(Error{*filterType, false, nsCString{mMessageUtf8}});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -297,9 +307,35 @@ void WebGPUParent::MaintainDevices() {
|
|||
ffi::wgpu_server_poll_all_devices(mContext.get(), false);
|
||||
}
|
||||
|
||||
void WebGPUParent::LoseDevice(const RawId aDeviceId, Maybe<uint8_t> aReason,
|
||||
const nsACString& aMessage) {
|
||||
// Check to see if we've already sent a DeviceLost message to aDeviceId.
|
||||
if (mLostDeviceIds.Contains(aDeviceId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SendDeviceLost(aDeviceId, aReason, aMessage)) {
|
||||
NS_ERROR("SendDeviceLost failed");
|
||||
return;
|
||||
}
|
||||
|
||||
mLostDeviceIds.Insert(aDeviceId);
|
||||
}
|
||||
|
||||
bool WebGPUParent::ForwardError(const Maybe<RawId> aDeviceId,
|
||||
ErrorBuffer& aError) {
|
||||
if (auto error = aError.GetError()) {
|
||||
// If this is a error has isDeviceLost true, then instead of reporting
|
||||
// the error, we swallow it and call LoseDevice if we have an
|
||||
// aDeviceID. This is to comply with the spec declaration in
|
||||
// https://gpuweb.github.io/gpuweb/#lose-the-device
|
||||
// "No errors are generated after device loss."
|
||||
if (error->isDeviceLost) {
|
||||
if (aDeviceId.isSome()) {
|
||||
LoseDevice(*aDeviceId, Nothing(), error->message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
ReportError(aDeviceId, error->type, error->message);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -382,6 +418,10 @@ ipc::IPCResult WebGPUParent::RecvAdapterRequestDevice(
|
|||
ffi::wgpu_server_adapter_request_device(
|
||||
mContext.get(), aAdapterId, ToFFI(&aByteBuf), aDeviceId, error.ToFFI());
|
||||
if (ForwardError(0, error)) {
|
||||
uint8_t reasonDestroyed = 0; // GPUDeviceLostReason::Destroyed
|
||||
auto maybeError = error.GetError();
|
||||
MOZ_ASSERT(maybeError.isSome());
|
||||
LoseDevice(aDeviceId, Some(reasonDestroyed), maybeError->message);
|
||||
resolver(false);
|
||||
} else {
|
||||
mErrorScopeStackByDevice.insert({aDeviceId, {}});
|
||||
|
|
@ -396,8 +436,14 @@ ipc::IPCResult WebGPUParent::RecvAdapterDestroy(RawId aAdapterId) {
|
|||
}
|
||||
|
||||
ipc::IPCResult WebGPUParent::RecvDeviceDestroy(RawId aDeviceId) {
|
||||
ffi::wgpu_server_device_destroy(mContext.get(), aDeviceId);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
ipc::IPCResult WebGPUParent::RecvDeviceDrop(RawId aDeviceId) {
|
||||
ffi::wgpu_server_device_drop(mContext.get(), aDeviceId);
|
||||
mErrorScopeStackByDevice.erase(aDeviceId);
|
||||
mLostDeviceIds.Remove(aDeviceId);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
@ -435,7 +481,8 @@ ipc::IPCResult WebGPUParent::RecvCreateBuffer(
|
|||
size = aDesc.mSize;
|
||||
}
|
||||
|
||||
BufferMapData data = {std::move(shmem), hasMapFlags, offset, size};
|
||||
BufferMapData data = {std::move(shmem), hasMapFlags, offset, size,
|
||||
aDeviceId};
|
||||
mSharedMemoryMap.insert({aBufferId, std::move(data)});
|
||||
}
|
||||
}
|
||||
|
|
@ -488,9 +535,9 @@ static const char* MapStatusString(ffi::WGPUBufferMapAsyncStatus status) {
|
|||
MOZ_CRASH("Bad ffi::WGPUBufferMapAsyncStatus");
|
||||
}
|
||||
|
||||
static void MapCallback(ffi::WGPUBufferMapAsyncStatus status,
|
||||
uint8_t* userdata) {
|
||||
auto* req = reinterpret_cast<MapRequest*>(userdata);
|
||||
void WebGPUParent::MapCallback(ffi::WGPUBufferMapAsyncStatus aStatus,
|
||||
uint8_t* aUserData) {
|
||||
auto* req = reinterpret_cast<MapRequest*>(aUserData);
|
||||
|
||||
if (!req->mParent->CanSend()) {
|
||||
delete req;
|
||||
|
|
@ -503,9 +550,18 @@ static void MapCallback(ffi::WGPUBufferMapAsyncStatus status,
|
|||
auto* mapData = req->mParent->GetBufferMapData(bufferId);
|
||||
MOZ_RELEASE_ASSERT(mapData);
|
||||
|
||||
if (status != ffi::WGPUBufferMapAsyncStatus_Success) {
|
||||
if (aStatus != ffi::WGPUBufferMapAsyncStatus_Success) {
|
||||
// A buffer map operation that fails with a DeviceError gets
|
||||
// mapped to the ContextLost status. If we have this status, we
|
||||
// need to lose the device.
|
||||
if (aStatus == ffi::WGPUBufferMapAsyncStatus_ContextLost) {
|
||||
req->mParent->LoseDevice(
|
||||
mapData->mDeviceId, Nothing(),
|
||||
nsPrintfCString("Buffer %" PRIu64 " invalid", bufferId));
|
||||
}
|
||||
|
||||
result = BufferMapError(nsPrintfCString("Mapping WebGPU buffer failed: %s",
|
||||
MapStatusString(status)));
|
||||
MapStatusString(aStatus)));
|
||||
} else {
|
||||
auto size = req->mSize;
|
||||
auto offset = req->mOffset;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ class WebGPUParent final : public PWebGPUParent {
|
|||
AdapterRequestDeviceResolver&& resolver);
|
||||
ipc::IPCResult RecvAdapterDestroy(RawId aAdapterId);
|
||||
ipc::IPCResult RecvDeviceDestroy(RawId aDeviceId);
|
||||
ipc::IPCResult RecvDeviceDrop(RawId aDeviceId);
|
||||
ipc::IPCResult RecvCreateBuffer(RawId aDeviceId, RawId aBufferId,
|
||||
dom::GPUBufferDescriptor&& aDesc,
|
||||
ipc::UnsafeSharedMemoryHandle&& aShmem);
|
||||
|
|
@ -123,6 +124,7 @@ class WebGPUParent final : public PWebGPUParent {
|
|||
bool mHasMapFlags;
|
||||
uint64_t mMappedOffset;
|
||||
uint64_t mMappedSize;
|
||||
RawId mDeviceId;
|
||||
};
|
||||
|
||||
BufferMapData* GetBufferMapData(RawId aBufferId);
|
||||
|
|
@ -143,10 +145,14 @@ class WebGPUParent final : public PWebGPUParent {
|
|||
std::shared_ptr<ExternalTexture> GetExternalTexture(ffi::WGPUTextureId aId);
|
||||
|
||||
private:
|
||||
static void MapCallback(ffi::WGPUBufferMapAsyncStatus aStatus,
|
||||
uint8_t* aUserData);
|
||||
void DeallocBufferShmem(RawId aBufferId);
|
||||
|
||||
virtual ~WebGPUParent();
|
||||
void MaintainDevices();
|
||||
void LoseDevice(const RawId aDeviceId, Maybe<uint8_t> aReason,
|
||||
const nsACString& aMessage);
|
||||
|
||||
bool ForwardError(const RawId aDeviceId, ErrorBuffer& aError) {
|
||||
return ForwardError(Some(aDeviceId), aError);
|
||||
|
|
@ -176,6 +182,10 @@ class WebGPUParent final : public PWebGPUParent {
|
|||
|
||||
std::unordered_map<ffi::WGPUTextureId, std::shared_ptr<ExternalTexture>>
|
||||
mExternalTextures;
|
||||
|
||||
// Store a set of DeviceIds that have been SendDeviceLost. We use this to
|
||||
// limit each Device to one DeviceLost message.
|
||||
nsTHashSet<RawId> mLostDeviceIds;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ subsuite = webgpu
|
|||
run-if = !release_or_beta
|
||||
prefs =
|
||||
dom.webgpu.enabled=true
|
||||
dom.webgpu.workers.enabled=true
|
||||
gfx.offscreencanvas.enabled=true
|
||||
support-files =
|
||||
worker_wrapper.js
|
||||
|
|
@ -15,7 +16,6 @@ support-files =
|
|||
scheme = https
|
||||
|
||||
[test_basic_canvas.worker.html]
|
||||
skip-if = true # Bug 1818379 - no webgpu in worker scopes, see bug 1808820
|
||||
fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac')
|
||||
[test_buffer_mapping.html]
|
||||
fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac')
|
||||
|
|
@ -39,5 +39,4 @@ fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version
|
|||
[test_submit_render_empty.html]
|
||||
fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac')
|
||||
[test_submit_render_empty.worker.html]
|
||||
skip-if = true # Bug 1818379 - no webgpu in worker scopes, see bug 1808820
|
||||
fail-if = (os == 'linux' && os_version == '18.04') || (os == 'win' && os_version == '6.1') || (os == 'mac')
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ self.addEventListener("message", async function (event) {
|
|||
const offscreen = event.data.offscreen;
|
||||
const context = offscreen.getContext("webgpu");
|
||||
|
||||
const swapChainFormat = navigator.gpu.getPreferredCanvasFormat();
|
||||
const adapter = await navigator.gpu.requestAdapter();
|
||||
const device = await adapter.requestDevice();
|
||||
const swapChainFormat = context.getPreferredFormat(adapter);
|
||||
|
||||
context.configure({
|
||||
device,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,11 @@
|
|||
const buffer = device.createBuffer({ size: 0, usage: 0 });
|
||||
const error = await device.popErrorScope();
|
||||
|
||||
isnot(error, null);
|
||||
isnot(
|
||||
error,
|
||||
null,
|
||||
"Attempt to createBuffer with size 0 and usage 0 should generate an error."
|
||||
);
|
||||
|
||||
try {
|
||||
await device.popErrorScope();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ self.addEventListener("message", async function (event) {
|
|||
colorAttachments: [
|
||||
{
|
||||
view,
|
||||
loadValue: { r: 0, g: 0, b: 0, a: 0 },
|
||||
clearValue: { r: 0, g: 0, b: 0, a: 0 },
|
||||
loadOp: "clear",
|
||||
storeOp: "store",
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -27,15 +27,6 @@ interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
|
|||
|
||||
attribute EventHandler onmessage;
|
||||
attribute EventHandler onmessageerror;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#animation-frames
|
||||
// Ideally we would just include AnimationFrameProvider to add the interface,
|
||||
// but we cannot make an include conditional.
|
||||
[Throws]
|
||||
long requestAnimationFrame(FrameRequestCallback callback);
|
||||
|
||||
[Throws]
|
||||
undefined cancelAnimationFrame(long handle);
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-encoded-transform/#RTCEncodedAudioFrame-methods
|
||||
|
|
@ -43,3 +34,6 @@ partial interface DedicatedWorkerGlobalScope {
|
|||
[Pref="media.peerconnection.enabled",
|
||||
Pref="media.peerconnection.scripttransform.enabled"] attribute EventHandler onrtctransform;
|
||||
};
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#animation-frames
|
||||
DedicatedWorkerGlobalScope includes AnimationFrameProvider;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ dictionary GPUUncapturedErrorEventInit : EventInit {
|
|||
required GPUError error;
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker*/), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUUncapturedErrorEvent: Event {
|
||||
constructor(DOMString type, GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict);
|
||||
readonly attribute GPUError error;
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ dictionary GPUObjectDescriptorBase {
|
|||
USVString label = "";
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUSupportedLimits {
|
||||
readonly attribute unsigned long maxTextureDimension1D;
|
||||
readonly attribute unsigned long maxTextureDimension2D;
|
||||
|
|
@ -52,14 +52,14 @@ interface GPUSupportedLimits {
|
|||
readonly attribute unsigned long maxComputeWorkgroupsPerDimension;
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUSupportedFeatures {
|
||||
readonly setlike<DOMString>;
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUAdapterInfo {
|
||||
readonly attribute DOMString vendor;
|
||||
readonly attribute DOMString architecture;
|
||||
|
|
@ -77,7 +77,7 @@ interface GPUAdapterInfo {
|
|||
};
|
||||
|
||||
interface mixin NavigatorGPU {
|
||||
[SameObject, Pref="dom.webgpu.enabled", Exposed=(Window /* ,DedicatedWorker */), SecureContext] readonly attribute GPU gpu;
|
||||
[SameObject, Func="mozilla::webgpu::Instance::PrefEnabled", Exposed=(Window, DedicatedWorker), SecureContext] readonly attribute GPU gpu;
|
||||
};
|
||||
// NOTE: see `dom/webidl/Navigator.webidl`
|
||||
// Navigator includes NavigatorGPU;
|
||||
|
|
@ -85,8 +85,8 @@ interface mixin NavigatorGPU {
|
|||
// WorkerNavigator includes NavigatorGPU;
|
||||
|
||||
[
|
||||
Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext
|
||||
Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext
|
||||
]
|
||||
interface GPU {
|
||||
[Throws]
|
||||
|
|
@ -104,8 +104,8 @@ enum GPUPowerPreference {
|
|||
"high-performance",
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUAdapter {
|
||||
[SameObject] readonly attribute GPUSupportedFeatures features;
|
||||
[SameObject] readonly attribute GPUSupportedLimits limits;
|
||||
|
|
@ -138,8 +138,8 @@ enum GPUFeatureName {
|
|||
"float32-filterable",
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUDevice : EventTarget {
|
||||
[SameObject] readonly attribute GPUSupportedFeatures features;
|
||||
[SameObject] readonly attribute GPUSupportedLimits limits;
|
||||
|
|
@ -172,8 +172,8 @@ interface GPUDevice : EventTarget {
|
|||
};
|
||||
GPUDevice includes GPUObjectBase;
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUBuffer {
|
||||
readonly attribute GPUSize64Out size;
|
||||
readonly attribute GPUFlagsConstant usage;
|
||||
|
|
@ -206,8 +206,8 @@ dictionary GPUBufferDescriptor
|
|||
};
|
||||
|
||||
typedef [EnforceRange] unsigned long GPUBufferUsageFlags;
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUBufferUsage {
|
||||
const GPUFlagsConstant MAP_READ = 0x0001;
|
||||
const GPUFlagsConstant MAP_WRITE = 0x0002;
|
||||
|
|
@ -222,15 +222,15 @@ interface GPUBufferUsage {
|
|||
};
|
||||
|
||||
typedef [EnforceRange] unsigned long GPUMapModeFlags;
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUMapMode {
|
||||
const GPUFlagsConstant READ = 0x0001;
|
||||
const GPUFlagsConstant WRITE = 0x0002;
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUTexture {
|
||||
GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {});
|
||||
|
||||
|
|
@ -265,8 +265,8 @@ enum GPUTextureDimension {
|
|||
};
|
||||
|
||||
typedef [EnforceRange] unsigned long GPUTextureUsageFlags;
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUTextureUsage {
|
||||
const GPUFlagsConstant COPY_SRC = 0x01;
|
||||
const GPUFlagsConstant COPY_DST = 0x02;
|
||||
|
|
@ -275,8 +275,8 @@ interface GPUTextureUsage {
|
|||
const GPUFlagsConstant RENDER_ATTACHMENT = 0x10;
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUTextureView {
|
||||
};
|
||||
GPUTextureView includes GPUObjectBase;
|
||||
|
|
@ -383,8 +383,8 @@ enum GPUTextureFormat {
|
|||
"bc7-rgba-unorm-srgb",
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUSampler {
|
||||
};
|
||||
GPUSampler includes GPUObjectBase;
|
||||
|
|
@ -430,8 +430,8 @@ enum GPUCompareFunction {
|
|||
"always",
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUBindGroupLayout {
|
||||
};
|
||||
GPUBindGroupLayout includes GPUObjectBase;
|
||||
|
|
@ -452,8 +452,8 @@ dictionary GPUBindGroupLayoutEntry {
|
|||
};
|
||||
|
||||
typedef [EnforceRange] unsigned long GPUShaderStageFlags;
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUShaderStage {
|
||||
const GPUFlagsConstant VERTEX = 0x1;
|
||||
const GPUFlagsConstant FRAGMENT = 0x2;
|
||||
|
|
@ -506,8 +506,8 @@ dictionary GPUStorageTextureBindingLayout {
|
|||
GPUTextureViewDimension viewDimension = "2d";
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUBindGroup {
|
||||
};
|
||||
GPUBindGroup includes GPUObjectBase;
|
||||
|
|
@ -531,8 +531,8 @@ dictionary GPUBufferBinding {
|
|||
GPUSize64 size;
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUPipelineLayout {
|
||||
};
|
||||
GPUPipelineLayout includes GPUObjectBase;
|
||||
|
|
@ -542,8 +542,8 @@ dictionary GPUPipelineLayoutDescriptor
|
|||
required sequence<GPUBindGroupLayout> bindGroupLayouts;
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUShaderModule {
|
||||
[Throws]
|
||||
Promise<GPUCompilationInfo> compilationInfo(); // To be removed with <https://bugzilla.mozilla.org/show_bug.cgi?id=1846892>
|
||||
|
|
@ -565,8 +565,8 @@ enum GPUCompilationMessageType {
|
|||
"info",
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUCompilationMessage {
|
||||
readonly attribute DOMString message;
|
||||
readonly attribute GPUCompilationMessageType type;
|
||||
|
|
@ -576,8 +576,8 @@ interface GPUCompilationMessage {
|
|||
readonly attribute unsigned long long length;
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUCompilationInfo {
|
||||
[Cached, Frozen, Pure]
|
||||
readonly attribute sequence<GPUCompilationMessage> messages;
|
||||
|
|
@ -603,8 +603,8 @@ dictionary GPUProgrammableStage {
|
|||
|
||||
//TODO: Serializable
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1696219
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUComputePipeline {
|
||||
};
|
||||
GPUComputePipeline includes GPUObjectBase;
|
||||
|
|
@ -617,8 +617,8 @@ dictionary GPUComputePipelineDescriptor
|
|||
|
||||
//TODO: Serializable
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1696219
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPURenderPipeline {
|
||||
};
|
||||
GPURenderPipeline includes GPUObjectBase;
|
||||
|
|
@ -686,8 +686,8 @@ dictionary GPUBlendState {
|
|||
};
|
||||
|
||||
typedef [EnforceRange] unsigned long GPUColorWriteFlags;
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUColorWrite {
|
||||
const GPUFlagsConstant RED = 0x1;
|
||||
const GPUFlagsConstant GREEN = 0x2;
|
||||
|
|
@ -852,8 +852,8 @@ dictionary GPUImageCopyExternalImage {
|
|||
boolean flipY = false;
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUCommandBuffer {
|
||||
};
|
||||
GPUCommandBuffer includes GPUObjectBase;
|
||||
|
|
@ -865,8 +865,8 @@ dictionary GPUCommandBufferDescriptor
|
|||
interface mixin GPUCommandsMixin {
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUCommandEncoder {
|
||||
GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor);
|
||||
GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor = {});
|
||||
|
|
@ -914,8 +914,8 @@ interface mixin GPUDebugCommandsMixin {
|
|||
undefined insertDebugMarker(USVString markerLabel);
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUComputePassEncoder {
|
||||
undefined setPipeline(GPUComputePipeline pipeline);
|
||||
undefined dispatchWorkgroups(GPUSize32 workgroupCountX, optional GPUSize32 workgroupCountY = 1, optional GPUSize32 workgroupCountZ = 1);
|
||||
|
|
@ -934,8 +934,8 @@ dictionary GPUComputePassDescriptor
|
|||
: GPUObjectDescriptorBase {
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPURenderPassEncoder {
|
||||
undefined setViewport(float x, float y,
|
||||
float width, float height,
|
||||
|
|
@ -1026,8 +1026,8 @@ interface mixin GPURenderCommandsMixin {
|
|||
undefined drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPURenderBundle {
|
||||
};
|
||||
GPURenderBundle includes GPUObjectBase;
|
||||
|
|
@ -1036,8 +1036,8 @@ dictionary GPURenderBundleDescriptor
|
|||
: GPUObjectDescriptorBase {
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPURenderBundleEncoder {
|
||||
GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {});
|
||||
};
|
||||
|
|
@ -1061,8 +1061,8 @@ dictionary GPUQueueDescriptor
|
|||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1696216
|
||||
// https://github.com/heycam/webidl/issues/961
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUQueue {
|
||||
undefined submit(sequence<GPUCommandBuffer> buffers);
|
||||
|
||||
|
|
@ -1092,8 +1092,8 @@ interface GPUQueue {
|
|||
};
|
||||
GPUQueue includes GPUObjectBase;
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUQuerySet {
|
||||
undefined destroy();
|
||||
};
|
||||
|
|
@ -1120,8 +1120,8 @@ enum GPUQueryType {
|
|||
"timestamp",
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUCanvasContext {
|
||||
readonly attribute (HTMLCanvasElement or OffscreenCanvas) canvas;
|
||||
|
||||
|
|
@ -1150,8 +1150,8 @@ enum GPUDeviceLostReason {
|
|||
"destroyed",
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUDeviceLostInfo {
|
||||
readonly attribute any reason; // GPUDeviceLostReason or undefined
|
||||
readonly attribute DOMString message;
|
||||
|
|
@ -1162,30 +1162,30 @@ partial interface GPUDevice {
|
|||
readonly attribute Promise<GPUDeviceLostInfo> lost;
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUError {
|
||||
readonly attribute DOMString message;
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUValidationError
|
||||
: GPUError {
|
||||
[Throws]
|
||||
constructor(DOMString message);
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUOutOfMemoryError
|
||||
: GPUError {
|
||||
[Throws]
|
||||
constructor(DOMString message);
|
||||
};
|
||||
|
||||
[Pref="dom.webgpu.enabled",
|
||||
Exposed=(Window /* ,DedicatedWorker */), SecureContext]
|
||||
[Func="mozilla::webgpu::Instance::PrefEnabled",
|
||||
Exposed=(Window, DedicatedWorker), SecureContext]
|
||||
interface GPUInternalError
|
||||
: GPUError {
|
||||
[Throws]
|
||||
|
|
@ -1205,7 +1205,7 @@ partial interface GPUDevice {
|
|||
};
|
||||
|
||||
partial interface GPUDevice {
|
||||
[Exposed=(Window /* ,DedicatedWorker */)]
|
||||
[Exposed=(Window, DedicatedWorker)]
|
||||
attribute EventHandler onuncapturederror;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -94,9 +94,10 @@ impl ErrorBuffer {
|
|||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub(crate) enum ErrorBufferType {
|
||||
None = 0,
|
||||
Internal = 1,
|
||||
OutOfMemory = 2,
|
||||
Validation = 3,
|
||||
DeviceLost = 1,
|
||||
Internal = 2,
|
||||
OutOfMemory = 3,
|
||||
Validation = 4,
|
||||
}
|
||||
|
||||
/// A trait for querying the [`ErrorBufferType`] classification of an error. Used by
|
||||
|
|
@ -174,7 +175,7 @@ mod foreign {
|
|||
match self {
|
||||
RequestDeviceError::OutOfMemory => ErrorBufferType::OutOfMemory,
|
||||
|
||||
RequestDeviceError::DeviceLost => ErrorBufferType::None,
|
||||
RequestDeviceError::DeviceLost => ErrorBufferType::DeviceLost,
|
||||
|
||||
RequestDeviceError::Internal
|
||||
| RequestDeviceError::InvalidAdapter
|
||||
|
|
@ -437,7 +438,7 @@ mod foreign {
|
|||
fn error_type(&self) -> ErrorBufferType {
|
||||
match self {
|
||||
DeviceError::Invalid | DeviceError::WrongDevice => ErrorBufferType::Validation,
|
||||
DeviceError::Lost => ErrorBufferType::None,
|
||||
DeviceError::Lost => ErrorBufferType::DeviceLost,
|
||||
DeviceError::OutOfMemory => ErrorBufferType::OutOfMemory,
|
||||
DeviceError::ResourceCreationFailed => ErrorBufferType::Internal,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -226,6 +226,11 @@ pub extern "C" fn wgpu_server_adapter_drop(global: &Global, adapter_id: id::Adap
|
|||
gfx_select!(adapter_id => global.adapter_drop(adapter_id))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_server_device_destroy(global: &Global, self_id: id::DeviceId) {
|
||||
gfx_select!(self_id => global.device_destroy(self_id))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_server_device_drop(global: &Global, self_id: id::DeviceId) {
|
||||
gfx_select!(self_id => global.device_drop(self_id))
|
||||
|
|
|
|||
46
js/src/jit-test/tests/wasm/regress/bug1858982.js
Normal file
46
js/src/jit-test/tests/wasm/regress/bug1858982.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// |jit-test| --wasm-tail-calls; --wasm-gc; skip-if: !wasmGcEnabled() || !wasmTailCallsEnabled()
|
||||
|
||||
// Tests if instance registers were restored properly when call_ref is used
|
||||
// with tail calls.
|
||||
var t = wasmEvalText(`(module
|
||||
(type $t1 (func))
|
||||
(func $f0 (param funcref i32 i32 i32 i32 i32 i32 i32 i32 i32)
|
||||
local.get 0
|
||||
ref.cast (ref $t1)
|
||||
return_call_ref $t1
|
||||
)
|
||||
(func $f1 (param i32))
|
||||
(elem declare func $f)
|
||||
(func $f (param funcref)
|
||||
(local i32 i32 i32 i32)
|
||||
local.get 0
|
||||
i32.const 1
|
||||
i32.const 1
|
||||
i32.const 1
|
||||
i32.const 1
|
||||
i32.const 1
|
||||
i32.const 1
|
||||
i32.const 1
|
||||
i32.const 1
|
||||
i32.const 1
|
||||
return_call $f0
|
||||
)
|
||||
(func (export "f") (result funcref)
|
||||
ref.func $f
|
||||
)
|
||||
)`);
|
||||
|
||||
var t2 = wasmEvalText(`(module
|
||||
(import "" "f" (func $fi (result funcref)))
|
||||
(type $t1 (func (param funcref)))
|
||||
(elem declare func $f2)
|
||||
(func $f2)
|
||||
(func (export "test")
|
||||
ref.func $f2
|
||||
call $fi
|
||||
ref.cast (ref $t1)
|
||||
call_ref $t1
|
||||
)
|
||||
)`, {"": {f:t.exports.f},});
|
||||
|
||||
t2.exports.test();
|
||||
|
|
@ -5561,6 +5561,9 @@ void MacroAssembler::wasmCallRef(const wasm::CallSiteDesc& desc,
|
|||
loadPtr(Address(calleeFnObj, uncheckedEntrySlotOffset), calleeScratch);
|
||||
|
||||
*slowCallOffset = call(desc, calleeScratch);
|
||||
#ifdef ENABLE_WASM_TAIL_CALLS
|
||||
wasmMarkSlowCall();
|
||||
#endif
|
||||
|
||||
// Restore registers and realm and back to this caller's.
|
||||
loadPtr(Address(getStackPointer(), WasmCallerInstanceOffsetBeforeCall),
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ void GenericPrinter::vprintf(const char* fmt, va_list ap) {
|
|||
// Simple shortcut to avoid allocating strings.
|
||||
if (strchr(fmt, '%') == nullptr) {
|
||||
put(fmt);
|
||||
return;
|
||||
}
|
||||
|
||||
GenericPrinterPrintfTarget printer(*this);
|
||||
|
|
|
|||
|
|
@ -284,14 +284,14 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem {
|
|||
if (!surface || !surface->IsValid()) {
|
||||
return;
|
||||
}
|
||||
gfx::IntSize size = surface->GetSize();
|
||||
|
||||
transform = gfxUtils::SnapTransform(
|
||||
transform, gfxRect(0, 0, size.width, size.height), nullptr);
|
||||
transform, gfxRect(0, 0, canvasSizeInPx.width, canvasSizeInPx.height),
|
||||
nullptr);
|
||||
aCtx->Multiply(transform);
|
||||
|
||||
aCtx->GetDrawTarget()->FillRect(
|
||||
Rect(0, 0, size.width, size.height),
|
||||
Rect(0, 0, canvasSizeInPx.width, canvasSizeInPx.height),
|
||||
SurfacePattern(surface, ExtendMode::CLAMP, Matrix(),
|
||||
nsLayoutUtils::GetSamplingFilterForFrame(f)));
|
||||
return;
|
||||
|
|
|
|||
7
layout/reftests/css-visited/variables-visited-ref.html
Normal file
7
layout/reftests/css-visited/variables-visited-ref.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<!doctype html>
|
||||
<style>
|
||||
a {
|
||||
color: green;
|
||||
}
|
||||
</style>
|
||||
<a href="">Which color?</a>
|
||||
12
layout/reftests/css-visited/variables-visited.html
Normal file
12
layout/reftests/css-visited/variables-visited.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<!doctype html>
|
||||
<style>
|
||||
a {
|
||||
--foo: green;
|
||||
}
|
||||
|
||||
:visited {
|
||||
--foo: red;
|
||||
color: var(--foo);
|
||||
}
|
||||
</style>
|
||||
<a href="visited-page.html">Which color?</a>
|
||||
|
|
@ -112,6 +112,8 @@ TEST_HARNESS_FILES.testing.mochitest.tests.layout.style.test["css-visited"] += [
|
|||
"/layout/reftests/css-visited/svg-paint-currentcolor-visited.svg",
|
||||
"/layout/reftests/css-visited/transition-on-visited-ref.html",
|
||||
"/layout/reftests/css-visited/transition-on-visited.html",
|
||||
"/layout/reftests/css-visited/variables-visited-ref.html",
|
||||
"/layout/reftests/css-visited/variables-visited.html",
|
||||
"/layout/reftests/css-visited/visited-inherit-1-ref.html",
|
||||
"/layout/reftests/css-visited/visited-inherit-1.html",
|
||||
"/layout/reftests/css-visited/visited-page.html",
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ var gTests = [
|
|||
"== logical-box-border-color-visited-link-002.html logical-box-border-color-visited-link-ref.html",
|
||||
"== logical-box-border-color-visited-link-003.html logical-box-border-color-visited-link-ref.html",
|
||||
"== svg-paint-currentcolor-visited.svg svg-paint-currentcolor-visited-ref.svg",
|
||||
"== variables-visited.html variables-visited-ref.html",
|
||||
];
|
||||
|
||||
// We record the maximum number of times we had to look at a test before
|
||||
|
|
|
|||
|
|
@ -2506,6 +2506,7 @@ package org.mozilla.geckoview {
|
|||
public class WebExtension.MetaData {
|
||||
ctor protected MetaData();
|
||||
field public final boolean allowedInPrivateBrowsing;
|
||||
field @Nullable public final String amoListingUrl;
|
||||
field public final double averageRating;
|
||||
field @NonNull public final String baseUrl;
|
||||
field public final int blocklistState;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package org.mozilla.geckoview.test
|
|||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.MediumTest
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.hamcrest.Matchers.greaterThan
|
||||
import org.hamcrest.core.IsEqual.equalTo
|
||||
import org.hamcrest.core.StringEndsWith.endsWith
|
||||
import org.json.JSONObject
|
||||
|
|
@ -2258,6 +2259,8 @@ class WebExtensionTest : BaseSessionTest() {
|
|||
"xpinstall.signatures.required" to false,
|
||||
"extensions.install.requireBuiltInCerts" to false,
|
||||
"extensions.update.requireBuiltInCerts" to false,
|
||||
"extensions.getAddons.cache.enabled" to true,
|
||||
"extensions.getAddons.cache.lastUpdate" to 0,
|
||||
),
|
||||
)
|
||||
mainSession.loadUri("https://example.com")
|
||||
|
|
@ -2303,6 +2306,52 @@ class WebExtensionTest : BaseSessionTest() {
|
|||
|
||||
// Check that the WebExtension was not applied after being uninstalled
|
||||
assertBodyBorderEqualTo("")
|
||||
|
||||
// This pref should have been updated because we expect the cached
|
||||
// metadata to have been refreshed.
|
||||
val geckoPrefs = sessionRule.getPrefs(
|
||||
"extensions.getAddons.cache.lastUpdate",
|
||||
)
|
||||
assumeThat(geckoPrefs[0] as Int, greaterThan(0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateWithMetadataNotStale() {
|
||||
val now = (System.currentTimeMillis() / 1000).toInt()
|
||||
sessionRule.setPrefsUntilTestEnd(
|
||||
mapOf(
|
||||
"xpinstall.signatures.required" to false,
|
||||
"extensions.install.requireBuiltInCerts" to false,
|
||||
"extensions.update.requireBuiltInCerts" to false,
|
||||
"extensions.getAddons.cache.enabled" to true,
|
||||
"extensions.getAddons.cache.lastUpdate" to now,
|
||||
),
|
||||
)
|
||||
|
||||
sessionRule.delegateDuringNextWait(object : WebExtensionController.PromptDelegate {
|
||||
@AssertCalled
|
||||
override fun onInstallPrompt(extension: WebExtension): GeckoResult<AllowOrDeny> {
|
||||
assertEquals(extension.metaData.version, "1.0")
|
||||
|
||||
return GeckoResult.allow()
|
||||
}
|
||||
})
|
||||
|
||||
// 1. Install
|
||||
val update1 = sessionRule.waitForResult(
|
||||
controller.install("https://example.org/tests/junit/update-1.xpi"),
|
||||
)
|
||||
// 2. Update
|
||||
val update2 = sessionRule.waitForResult(controller.update(update1))
|
||||
// 3. Uninstall
|
||||
sessionRule.waitForResult(controller.uninstall(update2))
|
||||
|
||||
// This pref should not have been updated because the cache isn't stale
|
||||
// (we set the pref to the current time at the top of this test case).
|
||||
val geckoPrefs = sessionRule.getPrefs(
|
||||
"extensions.getAddons.cache.lastUpdate",
|
||||
)
|
||||
assumeThat(geckoPrefs[0] as Int, equalTo(now))
|
||||
}
|
||||
|
||||
// Test extension updating when the new extension has different permissions.
|
||||
|
|
|
|||
|
|
@ -1979,6 +1979,9 @@ public class WebExtension {
|
|||
*/
|
||||
public final boolean temporary;
|
||||
|
||||
/** The link to the AMO detail page for this extension. See `AddonWrapper.amoListingURL`. */
|
||||
public final @Nullable String amoListingUrl;
|
||||
|
||||
/** Override for testing. */
|
||||
protected MetaData() {
|
||||
icon = null;
|
||||
|
|
@ -2006,6 +2009,7 @@ public class WebExtension {
|
|||
reviewUrl = null;
|
||||
updateDate = null;
|
||||
downloadUrl = null;
|
||||
amoListingUrl = null;
|
||||
}
|
||||
|
||||
/* package */ MetaData(final GeckoBundle bundle) {
|
||||
|
|
@ -2032,6 +2036,7 @@ public class WebExtension {
|
|||
reviewUrl = bundle.getString("reviewURL");
|
||||
updateDate = bundle.getString("updateDate");
|
||||
downloadUrl = bundle.getString("downloadUrl");
|
||||
amoListingUrl = bundle.getString("amoListingURL");
|
||||
|
||||
final int signedState = bundle.getInt("signedState", SignedStateFlags.UNKNOWN);
|
||||
if (signedState <= SignedStateFlags.LAST) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ exclude: true
|
|||
- Added `DisabledFlags.SIGNATURE` for extensions disabled because they aren't correctly signed. ([bug 1847266]({{bugzilla}}1847266))
|
||||
- Added `Builder` pattern constructors for [`ReviewAnalysis`][120.2] and [`Recommendation`][120.3] (part of [bug 1846341]({{bugzilla}}1846341))
|
||||
- Added `DisabledFlags.APP_VERSION` for extensions disabled because they aren't compatible with the application version. ([bug 1847266]({{bugzilla}}1847266))
|
||||
- Added more metadata to the [WebExtension][120.4] class. ([bug 1850674]({{bugzilla}}1850674))
|
||||
- Added more metadata to the [WebExtension][120.4] class. ([bug 1850674]({{bugzilla}}1850674), [bug 1858925]({{bugzilla}}1858925))
|
||||
- Added session and translations controller. Includes [`TranslationsController`][120.5], [`TranslationsController.SessionTranslation`][120.6] (notably [translate][120.7]), and a [translations delegate][120.8].
|
||||
|
||||
[120.1]: {{javadoc_uri}}/WebExtensionController.html#disableExtensionProcessSpawning
|
||||
|
|
@ -1449,4 +1449,4 @@ to allow adding gecko profiler markers.
|
|||
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport(android.content.Context,android.os.Bundle,java.lang.String)
|
||||
[65.25]: {{javadoc_uri}}/GeckoResult.html
|
||||
|
||||
[api-version]: 0909ac573b825169118c688f1975adc1f30cc252
|
||||
[api-version]: 3615c62a176c6dd0815b7bf28e7b33c378849701
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ const lazy = {};
|
|||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
|
||||
AddonRepository: "resource://gre/modules/addons/AddonRepository.sys.mjs",
|
||||
AddonSettings: "resource://gre/modules/addons/AddonSettings.sys.mjs",
|
||||
EventDispatcher: "resource://gre/modules/Messaging.sys.mjs",
|
||||
Extension: "resource://gre/modules/Extension.sys.mjs",
|
||||
|
|
@ -297,6 +298,7 @@ async function exportExtension(aAddon, aPermissions, aSourceURI) {
|
|||
policy = await policy.readyPromise;
|
||||
}
|
||||
const {
|
||||
amoListingURL,
|
||||
averageRating,
|
||||
blocklistState,
|
||||
creator,
|
||||
|
|
@ -371,6 +373,7 @@ async function exportExtension(aAddon, aPermissions, aSourceURI) {
|
|||
isBuiltIn: isBuiltin,
|
||||
webExtensionFlags: exportFlags(policy),
|
||||
metaData: {
|
||||
amoListingURL,
|
||||
averageRating,
|
||||
baseURL,
|
||||
blocklistState,
|
||||
|
|
@ -1063,6 +1066,20 @@ export var GeckoViewWebExtension = {
|
|||
},
|
||||
|
||||
async updateWebExtension(aId) {
|
||||
// Refresh the cached metadata when necessary. This allows us to always
|
||||
// export relatively recent metadata to the embedder.
|
||||
if (lazy.AddonRepository.isMetadataStale()) {
|
||||
// We use a promise to avoid more than one call to `backgroundUpdateCheck()`
|
||||
// when `updateWebExtension()` is called for multiple add-ons in parallel.
|
||||
if (!this._promiseAddonRepositoryUpdate) {
|
||||
this._promiseAddonRepositoryUpdate =
|
||||
lazy.AddonRepository.backgroundUpdateCheck().finally(() => {
|
||||
this._promiseAddonRepositoryUpdate = null;
|
||||
});
|
||||
}
|
||||
await this._promiseAddonRepositoryUpdate;
|
||||
}
|
||||
|
||||
const extension = await this.extensionById(aId);
|
||||
|
||||
const install = await this.checkForUpdate(extension);
|
||||
|
|
|
|||
|
|
@ -1478,17 +1478,11 @@
|
|||
|
||||
# Communicates the toolbar color to platform (for e.g., prefers-color-scheme).
|
||||
#
|
||||
# Returns whether the toolbar is dark (0), light (1), or system (2).
|
||||
#
|
||||
# Default to "light" on macOS / Windows, and "system" elsewhere. The theming
|
||||
# code sets it appropriately.
|
||||
# Returns whether the toolbar is dark (0), light (1), or system (2). The
|
||||
# theming code overrides it if appropriate.
|
||||
- name: browser.theme.toolbar-theme
|
||||
type: RelaxedAtomicUint32
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
value: 1
|
||||
#else
|
||||
value: 2
|
||||
#endif
|
||||
mirror: always
|
||||
|
||||
# Communicates the preferred content theme color to platform (for e.g.,
|
||||
|
|
@ -1503,6 +1497,14 @@
|
|||
mirror: always
|
||||
rust: true
|
||||
|
||||
# Whether the firefox titlebar respects the
|
||||
# -moz-windows-accent-color-in-titlebar setting on the tab strip.
|
||||
- name: browser.theme.windows.accent-color-in-tabs.enabled
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
rust: true
|
||||
|
||||
# Blocked plugin content
|
||||
- name: browser.safebrowsing.blockedURIs.enabled
|
||||
type: bool
|
||||
|
|
@ -4480,6 +4482,12 @@
|
|||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
|
||||
# Is support for the Web GPU API enabled on DOM workers?
|
||||
- name: dom.webgpu.workers.enabled
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Are WebGPU indirect draws/dispatches enabled?
|
||||
- name: dom.webgpu.indirect-dispatch.enabled
|
||||
type: RelaxedAtomicBool
|
||||
|
|
@ -15495,13 +15503,6 @@
|
|||
value: false
|
||||
mirror: always
|
||||
|
||||
# Whether to use the accent color for the titlebar, if the relevant Windows
|
||||
# setting says so. See bug 1851155.
|
||||
- name: widget.windows.titlebar-accent.enabled
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: widget.windows.window_occlusion_tracking_display_state.enabled
|
||||
type: bool
|
||||
value: false
|
||||
|
|
|
|||
11
mots.yaml
11
mots.yaml
|
|
@ -8,7 +8,7 @@
|
|||
# documentation and how to modify this file.
|
||||
repo: mozilla-central
|
||||
created_at: '2021-10-14T12:50:40.073465'
|
||||
updated_at: '2023-10-12T17:34:35.401624'
|
||||
updated_at: '2023-10-16T17:08:49.465830'
|
||||
export:
|
||||
path: ./docs/mots/index.rst
|
||||
format: rst
|
||||
|
|
@ -408,6 +408,10 @@ people:
|
|||
bmo_id: 448747
|
||||
name: Gabriele Svelto
|
||||
nick: gsvelto
|
||||
- &gw
|
||||
bmo_id: 504871
|
||||
name: Glenn Watson
|
||||
nick: gw
|
||||
- &haik
|
||||
bmo_id: 558190
|
||||
name: Haik Aftandilian
|
||||
|
|
@ -1739,6 +1743,7 @@ modules:
|
|||
- *sotaro
|
||||
- *jnicol
|
||||
- *rhunt
|
||||
- *gw
|
||||
machine_name: core_graphics
|
||||
|
||||
- name: 'Core: HAL'
|
||||
|
|
@ -4200,5 +4205,5 @@ modules:
|
|||
- Ryan Tilder
|
||||
group: dev-platform
|
||||
hashes:
|
||||
config: b6048ef220609203d8a630974dfd73321761dcce
|
||||
export: dd5d7f2127edc8694c19f8f1a981e0687d8eb575
|
||||
config: d8c4484d39645eb0b2e175b1a3634d6b3cc47426
|
||||
export: a6e22c1edd65c7da848df1cb4c92c507e6803737
|
||||
|
|
|
|||
|
|
@ -403,14 +403,13 @@ void nsStandardURL::InvalidateCache(bool invalidateCachedFile) {
|
|||
// Return the number of "dots" in the string, or -1 if invalid. Note that the
|
||||
// number of relevant entries in the bases/starts/ends arrays is number of
|
||||
// dots + 1.
|
||||
// Since the trailing dot is allowed, we pass and adjust "length".
|
||||
//
|
||||
// length is assumed to be <= host.Length(); the callers is responsible for that
|
||||
// length is assumed to be <= host.Length(); the caller is responsible for that
|
||||
//
|
||||
// Note that the value returned is guaranteed to be in [-1, 3] range.
|
||||
inline int32_t ValidateIPv4Number(const nsACString& host, int32_t bases[4],
|
||||
int32_t dotIndex[3], bool& onlyBase10,
|
||||
int32_t& length) {
|
||||
int32_t length, bool trailingDot) {
|
||||
MOZ_ASSERT(length <= (int32_t)host.Length());
|
||||
if (length <= 0) {
|
||||
return -1;
|
||||
|
|
@ -426,16 +425,11 @@ inline int32_t ValidateIPv4Number(const nsACString& host, int32_t bases[4],
|
|||
// A dot should not follow a dot, or be first - it can follow an x though.
|
||||
if (!(lastWasNumber ||
|
||||
(i >= 2 && (host[i - 1] == 'X' || host[i - 1] == 'x') &&
|
||||
host[i - 2] == '0'))) {
|
||||
host[i - 2] == '0')) ||
|
||||
(i == (length - 1) && trailingDot)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dotCount > 0 &&
|
||||
i == (length - 1)) { // Trailing dot is OK; shorten and return
|
||||
length--;
|
||||
return dotCount;
|
||||
}
|
||||
|
||||
if (dotCount > 2) {
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -562,11 +556,20 @@ nsresult nsStandardURL::NormalizeIPv4(const nsACString& host,
|
|||
bool onlyBase10 = true; // Track this as a special case
|
||||
int32_t dotIndex[3]; // The positions of the dots in the string
|
||||
|
||||
// The length may be adjusted by ValidateIPv4Number (ignoring the trailing
|
||||
// period) so use "length", rather than host.Length() after that call.
|
||||
int32_t length = static_cast<int32_t>(host.Length());
|
||||
int32_t dotCount =
|
||||
ValidateIPv4Number(host, bases, dotIndex, onlyBase10, length);
|
||||
// Use "length" rather than host.Length() after call to
|
||||
// ValidateIPv4Number because of potential trailing period.
|
||||
nsDependentCSubstring filteredHost;
|
||||
bool trailingDot = false;
|
||||
if (host.Length() > 0 && host.Last() == '.') {
|
||||
trailingDot = true;
|
||||
filteredHost.Rebind(host.BeginReading(), host.Length() - 1);
|
||||
} else {
|
||||
filteredHost.Rebind(host.BeginReading(), host.Length());
|
||||
}
|
||||
|
||||
int32_t length = static_cast<int32_t>(filteredHost.Length());
|
||||
int32_t dotCount = ValidateIPv4Number(filteredHost, bases, dotIndex,
|
||||
onlyBase10, length, trailingDot);
|
||||
if (dotCount < 0 || length <= 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
@ -3995,7 +3998,7 @@ nsresult Test_ParseIPv4Number(const nsACString& input, int32_t base,
|
|||
|
||||
int32_t Test_ValidateIPv4Number(const nsACString& host, int32_t bases[4],
|
||||
int32_t dotIndex[3], bool& onlyBase10,
|
||||
int32_t& length) {
|
||||
int32_t length) {
|
||||
return mozilla::net::ValidateIPv4Number(host, bases, dotIndex, onlyBase10,
|
||||
length);
|
||||
length, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ TrackerUriBlocked=The resource at “%1$S” was blocked because content blockin
|
|||
UnsafeUriBlocked=The resource at “%1$S” was blocked by Safe Browsing.
|
||||
|
||||
# LOCALIZATION NOTE (StrictUrlProtocolSetter): %1$S is the URL that has attempted to be changed. %2$S is the invalid target protocol.
|
||||
StrictUrlProtocolSetter=Url “%1%S“ change to protocol “%2$S“ was blocked.
|
||||
StrictUrlProtocolSetter=Url “%1$S“ change to protocol “%2$S“ was blocked.
|
||||
|
||||
# LOCALIZATION NOTE (CORPBlocked): %1$S is the URL of the blocked resource. %2$S is the URL of the MDN page about CORP.
|
||||
CORPBlocked=The resource at “%1$S” was blocked due to its Cross-Origin-Resource-Policy header (or lack thereof). See %2$S
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@ inline bool nsHttpHeaderArray::IsSingletonHeader(const nsHttpAtom& header) {
|
|||
header == nsHttp::If_Modified_Since ||
|
||||
header == nsHttp::If_Unmodified_Since || header == nsHttp::From ||
|
||||
header == nsHttp::Location || header == nsHttp::Max_Forwards ||
|
||||
header == nsHttp::GlobalPrivacyControl ||
|
||||
// Ignore-multiple-headers are singletons in the sense that they
|
||||
// shouldn't be merged.
|
||||
IsIgnoreMultipleHeader(header);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ extern nsresult Test_ParseIPv4Number(const nsACString& input, int32_t base,
|
|||
uint32_t& number, uint32_t maxNumber);
|
||||
extern int32_t Test_ValidateIPv4Number(const nsACString& host, int32_t bases[4],
|
||||
int32_t dotIndex[3], bool& onlyBase10,
|
||||
int32_t& length);
|
||||
int32_t length);
|
||||
TEST(TestStandardURL, Simple)
|
||||
{
|
||||
nsCOMPtr<nsIURI> url;
|
||||
|
|
|
|||
|
|
@ -684,7 +684,7 @@ macro_rules! bool_pref_feature {
|
|||
/// to support new types in these entries and (2) ensuring that either
|
||||
/// nsPresContext::MediaFeatureValuesChanged is called when the value that
|
||||
/// would be returned by the evaluator function could change.
|
||||
pub static MEDIA_FEATURES: [QueryFeatureDescription; 62] = [
|
||||
pub static MEDIA_FEATURES: [QueryFeatureDescription; 63] = [
|
||||
feature!(
|
||||
atom!("width"),
|
||||
AllowsRanges::Yes,
|
||||
|
|
@ -1005,4 +1005,8 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 62] = [
|
|||
atom!("-moz-always-underline-links"),
|
||||
"layout.css.always_underline_links"
|
||||
),
|
||||
bool_pref_feature!(
|
||||
atom!("-moz-windows-accent-color-in-tabs"),
|
||||
"browser.theme.windows.accent-color-in-tabs.enabled"
|
||||
),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ where
|
|||
|
||||
/// Whether we're cascading for visited or unvisited styles.
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum CascadeMode<'a> {
|
||||
pub enum CascadeMode<'a, 'b> {
|
||||
/// We're cascading for unvisited styles.
|
||||
Unvisited {
|
||||
/// The visited rules that should match the visited style.
|
||||
|
|
@ -225,12 +225,28 @@ pub enum CascadeMode<'a> {
|
|||
},
|
||||
/// We're cascading for visited styles.
|
||||
Visited {
|
||||
/// The writing mode of our unvisited style, needed to correctly resolve
|
||||
/// logical properties..
|
||||
writing_mode: WritingMode,
|
||||
/// The cascade for our unvisited style.
|
||||
unvisited_context: &'a computed::Context<'b>,
|
||||
},
|
||||
}
|
||||
|
||||
fn iter_declarations<'builder, 'decls: 'builder>(
|
||||
iter: impl Iterator<Item = (&'decls PropertyDeclaration, CascadePriority)>,
|
||||
declarations: &mut Declarations<'decls>,
|
||||
mut custom_builder: Option<&mut CustomPropertiesBuilder<'builder>>,
|
||||
) {
|
||||
for (declaration, priority) in iter {
|
||||
if let PropertyDeclaration::Custom(ref declaration) = *declaration {
|
||||
if let Some(ref mut builder) = custom_builder {
|
||||
builder.cascade(declaration, priority);
|
||||
}
|
||||
} else {
|
||||
let id = declaration.id().as_longhand().unwrap();
|
||||
declarations.note_declaration(declaration, priority, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// NOTE: This function expects the declaration with more priority to appear
|
||||
/// first.
|
||||
pub fn apply_declarations<'a, E, I>(
|
||||
|
|
@ -285,34 +301,32 @@ where
|
|||
context.style().add_flags(cascade_input_flags);
|
||||
|
||||
let using_cached_reset_properties;
|
||||
let mut cascade = Cascade::new(&mut context, cascade_mode, first_line_reparenting);
|
||||
let mut data = CascadeData::default();
|
||||
|
||||
{
|
||||
let mut builder =
|
||||
CustomPropertiesBuilder::new(inherited_style.custom_properties(), stylist, is_root_element);
|
||||
for (declaration, priority) in iter {
|
||||
if let PropertyDeclaration::Custom(ref declaration) = *declaration {
|
||||
builder.cascade(declaration, priority);
|
||||
} else {
|
||||
let id = declaration.id().as_longhand().unwrap();
|
||||
data.note_declaration(declaration, priority, id);
|
||||
}
|
||||
}
|
||||
cascade.context.builder.custom_properties = builder.build();
|
||||
};
|
||||
|
||||
let properties_to_apply = match cascade.cascade_mode {
|
||||
CascadeMode::Visited { writing_mode } => {
|
||||
cascade.context.builder.writing_mode = writing_mode;
|
||||
let mut cascade = Cascade::new(&mut context, first_line_reparenting);
|
||||
let mut declarations = Default::default();
|
||||
let mut shorthand_cache = ShorthandsWithPropertyReferencesCache::default();
|
||||
let properties_to_apply = match cascade_mode {
|
||||
CascadeMode::Visited { unvisited_context } => {
|
||||
cascade.context.builder.custom_properties = unvisited_context.builder.custom_properties.clone();
|
||||
cascade.context.builder.writing_mode = unvisited_context.builder.writing_mode;
|
||||
// We never insert visited styles into the cache so we don't need to try looking it up.
|
||||
// It also wouldn't be super-profitable, only a handful :visited properties are
|
||||
// non-inherited.
|
||||
using_cached_reset_properties = false;
|
||||
// TODO(bug 1859385): If we match the same rules when visited and unvisited, we could
|
||||
// try to avoid gathering the declarations. That'd be:
|
||||
// unvisited_context.builder.rules.as_ref() == Some(rules)
|
||||
iter_declarations(iter, &mut declarations, None);
|
||||
LonghandIdSet::visited_dependent()
|
||||
},
|
||||
CascadeMode::Unvisited { visited_rules } => {
|
||||
cascade.apply_prioritary_properties(&mut data);
|
||||
cascade.context.builder.custom_properties = {
|
||||
let mut builder =
|
||||
CustomPropertiesBuilder::new(inherited_style.custom_properties(), stylist, is_root_element);
|
||||
iter_declarations(iter, &mut declarations, Some(&mut builder));
|
||||
builder.build()
|
||||
};
|
||||
|
||||
cascade.apply_prioritary_properties(&declarations, &mut shorthand_cache);
|
||||
|
||||
if let Some(visited_rules) = visited_rules {
|
||||
cascade.compute_visited_style_if_needed(
|
||||
|
|
@ -336,7 +350,7 @@ where
|
|||
},
|
||||
};
|
||||
|
||||
cascade.apply_non_prioritary_properties(&mut data, &properties_to_apply);
|
||||
cascade.apply_non_prioritary_properties(&declarations.longhand_declarations, &mut shorthand_cache, &properties_to_apply);
|
||||
|
||||
cascade.finished_applying_properties();
|
||||
|
||||
|
|
@ -536,22 +550,18 @@ struct Declaration<'a> {
|
|||
next_index: DeclarationIndex,
|
||||
}
|
||||
|
||||
/// A bit of a kitchen-sink struct for things that need to mutate in ways that otherwise rustc
|
||||
/// can't reason about if we put these in Cascade.
|
||||
/// The set of property declarations from our rules.
|
||||
#[derive(Default)]
|
||||
struct CascadeData<'a> {
|
||||
struct Declarations<'a> {
|
||||
/// Whether we have any prioritary property. This is just a minor optimization.
|
||||
has_prioritary_properties: bool,
|
||||
/// A cache for shorthands with property references, to avoid substituting the same value over
|
||||
/// and over for each of the longhands.
|
||||
shorthand_cache: ShorthandsWithPropertyReferencesCache,
|
||||
/// A list of all the applicable longhand declarations.
|
||||
longhand_declarations: SmallVec<[Declaration<'a>; 32]>,
|
||||
/// The prioritary property position data.
|
||||
prioritary_positions: [PrioritaryDeclarationPosition; PRIORITARY_PROPERTY_COUNT],
|
||||
}
|
||||
|
||||
impl<'a> CascadeData<'a> {
|
||||
impl<'a> Declarations<'a> {
|
||||
fn note_prioritary_property(&mut self, id: PrioritaryPropertyId) {
|
||||
let new_index = self.longhand_declarations.len();
|
||||
if new_index >= DeclarationIndex::MAX as usize {
|
||||
|
|
@ -593,7 +603,6 @@ impl<'a> CascadeData<'a> {
|
|||
|
||||
struct Cascade<'a, 'b: 'a> {
|
||||
context: &'a mut computed::Context<'b>,
|
||||
cascade_mode: CascadeMode<'a>,
|
||||
first_line_reparenting: FirstLineReparenting<'b>,
|
||||
ignore_colors: bool,
|
||||
seen: LonghandIdSet,
|
||||
|
|
@ -606,13 +615,11 @@ struct Cascade<'a, 'b: 'a> {
|
|||
impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
||||
fn new(
|
||||
context: &'a mut computed::Context<'b>,
|
||||
cascade_mode: CascadeMode<'a>,
|
||||
first_line_reparenting: FirstLineReparenting<'b>,
|
||||
) -> Self {
|
||||
let ignore_colors = !context.builder.device.use_document_colors();
|
||||
Self {
|
||||
context,
|
||||
cascade_mode,
|
||||
first_line_reparenting,
|
||||
ignore_colors,
|
||||
seen: LonghandIdSet::default(),
|
||||
|
|
@ -678,10 +685,11 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
|
||||
fn apply_one_prioritary_property(
|
||||
&mut self,
|
||||
data: &mut CascadeData,
|
||||
decls: &Declarations,
|
||||
cache: &mut ShorthandsWithPropertyReferencesCache,
|
||||
id: PrioritaryPropertyId,
|
||||
) -> bool {
|
||||
let mut index = data.prioritary_positions[id as usize].most_important;
|
||||
let mut index = decls.prioritary_positions[id as usize].most_important;
|
||||
if index == DeclarationIndex::MAX {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -692,13 +700,13 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
"That could require more book-keeping"
|
||||
);
|
||||
loop {
|
||||
let decl = data.longhand_declarations[index as usize];
|
||||
let decl = decls.longhand_declarations[index as usize];
|
||||
self.apply_one_longhand(
|
||||
longhand_id,
|
||||
longhand_id,
|
||||
decl.decl,
|
||||
decl.priority,
|
||||
&mut data.shorthand_cache,
|
||||
cache,
|
||||
);
|
||||
if self.seen.contains(longhand_id) {
|
||||
return true; // Common case, we're done.
|
||||
|
|
@ -721,27 +729,27 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
false
|
||||
}
|
||||
|
||||
fn apply_prioritary_properties(&mut self, data: &mut CascadeData) {
|
||||
if !data.has_prioritary_properties {
|
||||
fn apply_prioritary_properties(&mut self, decls: &Declarations, cache: &mut ShorthandsWithPropertyReferencesCache) {
|
||||
if !decls.has_prioritary_properties {
|
||||
return;
|
||||
}
|
||||
|
||||
let has_writing_mode = self
|
||||
.apply_one_prioritary_property(data, PrioritaryPropertyId::WritingMode) |
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::Direction) |
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::TextOrientation);
|
||||
.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::WritingMode) |
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::Direction) |
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::TextOrientation);
|
||||
if has_writing_mode {
|
||||
self.compute_writing_mode();
|
||||
}
|
||||
|
||||
if self.apply_one_prioritary_property(data, PrioritaryPropertyId::Zoom) {
|
||||
if self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::Zoom) {
|
||||
self.compute_zoom();
|
||||
}
|
||||
|
||||
// Compute font-family.
|
||||
let has_font_family =
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::FontFamily);
|
||||
let has_lang = self.apply_one_prioritary_property(data, PrioritaryPropertyId::XLang);
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::FontFamily);
|
||||
let has_lang = self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::XLang);
|
||||
if has_lang {
|
||||
self.recompute_initial_font_family_if_needed();
|
||||
}
|
||||
|
|
@ -750,15 +758,15 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
}
|
||||
|
||||
// Compute font-size.
|
||||
if self.apply_one_prioritary_property(data, PrioritaryPropertyId::XTextScale) {
|
||||
if self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::XTextScale) {
|
||||
self.unzoom_fonts_if_needed();
|
||||
}
|
||||
let has_font_size =
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::FontSize);
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::FontSize);
|
||||
let has_math_depth =
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::MathDepth);
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::MathDepth);
|
||||
let has_min_font_size_ratio =
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::MozMinFontSizeRatio);
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::MozMinFontSizeRatio);
|
||||
|
||||
if has_math_depth && has_font_size {
|
||||
self.recompute_math_font_size_if_needed();
|
||||
|
|
@ -771,26 +779,27 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
}
|
||||
|
||||
// Compute the rest of the first-available-font-affecting properties.
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::FontWeight);
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::FontStretch);
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::FontStyle);
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::FontSizeAdjust);
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::FontWeight);
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::FontStretch);
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::FontStyle);
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::FontSizeAdjust);
|
||||
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::ColorScheme);
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::ForcedColorAdjust);
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::ColorScheme);
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::ForcedColorAdjust);
|
||||
|
||||
// Compute the line height.
|
||||
self.apply_one_prioritary_property(data, PrioritaryPropertyId::LineHeight);
|
||||
self.apply_one_prioritary_property(decls, cache, PrioritaryPropertyId::LineHeight);
|
||||
}
|
||||
|
||||
fn apply_non_prioritary_properties(
|
||||
&mut self,
|
||||
data: &mut CascadeData,
|
||||
longhand_declarations: &[Declaration],
|
||||
shorthand_cache: &mut ShorthandsWithPropertyReferencesCache,
|
||||
properties_to_apply: &LonghandIdSet,
|
||||
) {
|
||||
debug_assert!(!properties_to_apply.contains_any(LonghandIdSet::prioritary_properties()));
|
||||
debug_assert!(self.declarations_to_apply_unless_overridden.is_empty());
|
||||
for declaration in &data.longhand_declarations {
|
||||
for declaration in &*longhand_declarations {
|
||||
let longhand_id = declaration.decl.id().as_longhand().unwrap();
|
||||
if !properties_to_apply.contains(longhand_id) {
|
||||
continue;
|
||||
|
|
@ -802,7 +811,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
physical_longhand_id,
|
||||
declaration.decl,
|
||||
declaration.priority,
|
||||
&mut data.shorthand_cache,
|
||||
shorthand_cache,
|
||||
);
|
||||
}
|
||||
if !self.declarations_to_apply_unless_overridden.is_empty() {
|
||||
|
|
@ -823,7 +832,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
physical_longhand_id: LonghandId,
|
||||
declaration: &PropertyDeclaration,
|
||||
priority: CascadePriority,
|
||||
shorthand_cache: &mut ShorthandsWithPropertyReferencesCache,
|
||||
cache: &mut ShorthandsWithPropertyReferencesCache,
|
||||
) {
|
||||
debug_assert!(!physical_longhand_id.is_logical());
|
||||
let origin = priority.cascade_level().origin();
|
||||
|
|
@ -841,7 +850,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut declaration = self.substitute_variables_if_needed(shorthand_cache, declaration);
|
||||
let mut declaration = self.substitute_variables_if_needed(cache, declaration);
|
||||
|
||||
// When document colors are disabled, do special handling of
|
||||
// properties that are marked as ignored in that mode.
|
||||
|
|
@ -896,7 +905,6 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
}
|
||||
|
||||
fn compute_zoom(&mut self) {
|
||||
debug_assert!(matches!(self.cascade_mode, CascadeMode::Unvisited { .. }));
|
||||
self.context.builder.effective_zoom = self
|
||||
.context
|
||||
.builder
|
||||
|
|
@ -905,7 +913,6 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
}
|
||||
|
||||
fn compute_writing_mode(&mut self) {
|
||||
debug_assert!(matches!(self.cascade_mode, CascadeMode::Unvisited { .. }));
|
||||
self.context.builder.writing_mode =
|
||||
WritingMode::new(self.context.builder.get_inherited_box())
|
||||
}
|
||||
|
|
@ -921,7 +928,6 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
) where
|
||||
E: TElement,
|
||||
{
|
||||
debug_assert!(matches!(self.cascade_mode, CascadeMode::Unvisited { .. }));
|
||||
let is_link = self.context.builder.pseudo.is_none() && element.unwrap().is_link();
|
||||
|
||||
macro_rules! visited_parent {
|
||||
|
|
@ -934,8 +940,6 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
};
|
||||
}
|
||||
|
||||
let writing_mode = self.context.builder.writing_mode;
|
||||
|
||||
// We could call apply_declarations directly, but that'd cause
|
||||
// another instantiation of this function which is not great.
|
||||
let style = cascade_rules(
|
||||
|
|
@ -947,7 +951,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
visited_parent!(parent_style),
|
||||
visited_parent!(layout_parent_style),
|
||||
self.first_line_reparenting,
|
||||
CascadeMode::Visited { writing_mode },
|
||||
CascadeMode::Visited { unvisited_context: &*self.context },
|
||||
// Cascade input flags don't matter for the visited style, they are
|
||||
// in the main (unvisited) style.
|
||||
Default::default(),
|
||||
|
|
|
|||
|
|
@ -239,6 +239,13 @@ user-id = 4333
|
|||
user-login = "joshtriplett"
|
||||
user-name = "Josh Triplett"
|
||||
|
||||
[[publisher.flate2]]
|
||||
version = "1.0.26"
|
||||
when = "2023-04-28"
|
||||
user-id = 4333
|
||||
user-login = "joshtriplett"
|
||||
user-name = "Josh Triplett"
|
||||
|
||||
[[publisher.freetype]]
|
||||
version = "0.7.0"
|
||||
when = "2020-07-14"
|
||||
|
|
@ -1044,12 +1051,38 @@ criteria = "safe-to-deploy"
|
|||
delta = "0.7.1 -> 0.8.0"
|
||||
notes = "This was a small update to the crate which has to do with Rust language features and compiler versions, no substantial changes."
|
||||
|
||||
[[audits.bytecode-alliance.audits.miniz_oxide]]
|
||||
who = "Alex Crichton <alex@alexcrichton.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "0.7.1"
|
||||
notes = """
|
||||
This crate is a Rust implementation of zlib compression/decompression and has
|
||||
been used by default by the Rust standard library for quite some time. It's also
|
||||
a default dependency of the popular `backtrace` crate for decompressing debug
|
||||
information. This crate forbids unsafe code and does not otherwise access system
|
||||
resources. It's originally a port of the `miniz.c` library as well, and given
|
||||
its own longevity should be relatively hardened against some of the more common
|
||||
compression-related issues.
|
||||
"""
|
||||
|
||||
[[audits.bytecode-alliance.audits.mio]]
|
||||
who = "Alex Crichton <alex@alexcrichton.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.8.6 -> 0.8.8"
|
||||
notes = "Mostly OS portability updates along with some minor bugfixes."
|
||||
|
||||
[[audits.bytecode-alliance.audits.object]]
|
||||
who = "Alex Crichton <alex@alexcrichton.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.30.3 -> 0.31.1"
|
||||
notes = "A large-ish update to the crate but nothing out of the ordering. Support for new formats like xcoff, new constants, minor refactorings, etc. Nothing out of the ordinary."
|
||||
|
||||
[[audits.bytecode-alliance.audits.object]]
|
||||
who = "Alex Crichton <alex@alexcrichton.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.31.1 -> 0.32.0"
|
||||
notes = "Various new features and refactorings as one would expect from an object parsing crate, all looks good."
|
||||
|
||||
[[audits.bytecode-alliance.audits.peeking_take_while]]
|
||||
who = "Nick Fitzgerald <fitzgen@gmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
|
@ -1095,6 +1128,12 @@ criteria = "safe-to-deploy"
|
|||
version = "0.4.6"
|
||||
notes = "provides a datastructure implemented using std's Vec. all uses of unsafe are just delegating to the underlying unsafe Vec methods."
|
||||
|
||||
[[audits.bytecode-alliance.audits.socket2]]
|
||||
who = "Alex Crichton <alex@alexcrichton.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.4.7 -> 0.4.9"
|
||||
notes = "Minor OS compat updates but otherwise nothing major here."
|
||||
|
||||
[[audits.bytecode-alliance.audits.tempfile]]
|
||||
who = "Pat Hickey <phickey@fastly.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
|
@ -1271,6 +1310,12 @@ criteria = "safe-to-run"
|
|||
version = "0.7.1"
|
||||
aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT"
|
||||
|
||||
[[audits.google.audits.tokio]]
|
||||
who = "Vovo Yang <vovoy@google.com>"
|
||||
criteria = "safe-to-run"
|
||||
version = "1.29.1"
|
||||
aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT"
|
||||
|
||||
[[audits.google.audits.tokio-stream]]
|
||||
who = "David Koloski <dkoloski@google.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
|
|
|||
|
|
@ -2831,29 +2831,16 @@ export var BrowserTestUtils = {
|
|||
|
||||
/**
|
||||
* A helper function for this test that returns a Promise that resolves
|
||||
* once either the legacy or new migration wizard appears.
|
||||
* once the migration wizard appears.
|
||||
*
|
||||
* @param {DOMWindow} window
|
||||
* The top-level window that the about:preferences tab is likely to open
|
||||
* in if the new migration wizard is enabled.
|
||||
* @param {boolean} forceLegacy
|
||||
* True if, despite the browser.migrate.content-modal.enabled pref value,
|
||||
* the legacy XUL migration wizard is expected.
|
||||
* @returns {Promise<Element>}
|
||||
* Resolves to the dialog window in the legacy case, and the
|
||||
* about:preferences tab otherwise.
|
||||
* Resolves to the opened about:preferences tab with the migration wizard
|
||||
* running and loaded in it.
|
||||
*/
|
||||
async waitForMigrationWizard(window, forceLegacy = false) {
|
||||
if (!this._usingNewMigrationWizard || forceLegacy) {
|
||||
return this.waitForCondition(() => {
|
||||
let win = Services.wm.getMostRecentWindow("Browser:MigrationWizard");
|
||||
if (win?.document?.readyState == "complete") {
|
||||
return win;
|
||||
}
|
||||
return false;
|
||||
}, "Wait for migration wizard to open");
|
||||
}
|
||||
|
||||
async waitForMigrationWizard(window) {
|
||||
let wizardReady = this.waitForEvent(window, "MigrationWizard:Ready");
|
||||
let wizardTab = await this.waitForNewTab(window.gBrowser, url => {
|
||||
return url.startsWith("about:preferences");
|
||||
|
|
@ -2862,27 +2849,6 @@ export var BrowserTestUtils = {
|
|||
|
||||
return wizardTab;
|
||||
},
|
||||
|
||||
/**
|
||||
* Closes the migration wizard.
|
||||
*
|
||||
* @param {Element} wizardWindowOrTab
|
||||
* The XUL dialog window for the migration wizard in the legacy case, and
|
||||
* the about:preferences tab otherwise. In general, it's probably best to
|
||||
* just pass whatever BrowserTestUtils.waitForMigrationWizard resolved to
|
||||
* into this in order to handle both the old and new migration wizard.
|
||||
* @param {boolean} forceLegacy
|
||||
* True if, despite the browser.migrate.content-modal.enabled pref value,
|
||||
* the legacy XUL migration wizard is expected.
|
||||
* @returns {Promise<undefined>}
|
||||
*/
|
||||
closeMigrationWizard(wizardWindowOrTab, forceLegacy = false) {
|
||||
if (!this._usingNewMigrationWizard || forceLegacy) {
|
||||
return BrowserTestUtils.closeWindow(wizardWindowOrTab);
|
||||
}
|
||||
|
||||
return BrowserTestUtils.removeTab(wizardWindowOrTab);
|
||||
},
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
|
|
@ -2892,11 +2858,4 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
|||
false
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
BrowserTestUtils,
|
||||
"_usingNewMigrationWizard",
|
||||
"browser.migrate.content-modal.enabled",
|
||||
false
|
||||
);
|
||||
|
||||
Services.obs.addObserver(BrowserTestUtils, "test-complete");
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium, safari
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 14000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -306,7 +306,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium, safari
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 2000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -567,7 +567,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium, safari
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 14000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: false
|
||||
|
|
@ -829,7 +829,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 14000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -1086,7 +1086,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium, safari
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 8000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: false
|
||||
|
|
@ -1343,6 +1343,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium, safari
|
||||
* **expected**: pass
|
||||
* **expose chrome trace**: true
|
||||
* **expose gecko profiler**: true
|
||||
* **gecko profile entries**: 8000000
|
||||
* **gecko profile interval**: 1
|
||||
|
|
@ -1600,7 +1601,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium, safari, custom-car
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 14000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: false
|
||||
|
|
@ -2281,7 +2282,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **browsertime args**: --browsertime.speedometer_iterations=5
|
||||
* **custom data**: true
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 14000000
|
||||
* **gecko profile interval**: 1
|
||||
* **host from parent**: false
|
||||
|
|
@ -2956,7 +2957,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium, safari
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 8000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: false
|
||||
|
|
@ -3215,7 +3216,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium, safari
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 8000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -3472,7 +3473,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 14000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -3992,7 +3993,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium, safari
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 8000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: false
|
||||
|
|
@ -4299,7 +4300,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium, safari
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 8000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -4557,7 +4558,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 8000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -4771,7 +4772,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 8000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -4985,7 +4986,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 4000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -5240,7 +5241,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 4000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -5456,7 +5457,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 4000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -5672,7 +5673,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, chrome, chromium, safari
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 4000000
|
||||
* **gecko profile interval**: 1
|
||||
* **lower is better**: true
|
||||
|
|
@ -5931,7 +5932,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, geckoview, fenix,refbrow, chrome
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
* **gecko profile threads**: MediaPlayback
|
||||
|
|
@ -5954,7 +5955,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, geckoview, fenix, refbrow, chrome
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
* **gecko profile threads**: MediaPlayback
|
||||
|
|
@ -5995,7 +5996,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gather cpuTime**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
|
|
@ -6197,7 +6198,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gather cpuTime**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
|
|
@ -6399,7 +6400,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gather cpuTime**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
|
|
@ -6601,7 +6602,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gather cpuTime**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
|
|
@ -6803,7 +6804,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, geckoview, fenix, refbrow, chrome
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
* **gecko profile threads**: MediaPlayback
|
||||
|
|
@ -7063,7 +7064,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, geckoview, fenix, refbrow, chrome
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
* **gecko profile threads**: MediaPlayback
|
||||
|
|
@ -7322,7 +7323,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gather cpuTime**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
|
|
@ -7524,7 +7525,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gather cpuTime**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
|
|
@ -7726,7 +7727,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gather cpuTime**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
|
|
@ -7928,7 +7929,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gather cpuTime**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
|
|
@ -8130,7 +8131,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, geckoview, fenix, refbrow, chrome
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
* **gecko profile threads**: MediaPlayback
|
||||
|
|
@ -8347,7 +8348,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, geckoview, fenix, refbrow, chrome
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
* **gecko profile threads**: MediaPlayback
|
||||
|
|
@ -8564,7 +8565,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, geckoview, fenix, refbrow, chrome
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
* **gecko profile threads**: MediaPlayback
|
||||
|
|
@ -8781,7 +8782,7 @@ Standard benchmarks are third-party tests (i.e. Speedometer) that we have integr
|
|||
* **alert threshold**: 2.0
|
||||
* **apps**: firefox, geckoview, fenix, refbrow, chrome
|
||||
* **expected**: pass
|
||||
* **expose gecko profiler**: true
|
||||
* **expose browser profiler**: true
|
||||
* **gecko profile entries**: 50000000
|
||||
* **gecko profile interval**: 1000
|
||||
* **gecko profile threads**: MediaPlayback
|
||||
|
|
|
|||
|
|
@ -30,7 +30,11 @@ module.exports = async function (context, commands) {
|
|||
context.log.info("Cycle %d, starting the measure", count);
|
||||
if (expose_profiler === "true") {
|
||||
context.log.info("Custom profiler start!");
|
||||
await commands.profiler.start();
|
||||
if (context.options.browser === "firefox") {
|
||||
await commands.profiler.start();
|
||||
} else if (context.options.browser === "chrome") {
|
||||
await commands.trace.start();
|
||||
}
|
||||
}
|
||||
await commands.measure.start(url);
|
||||
|
||||
|
|
@ -52,7 +56,11 @@ module.exports = async function (context, commands) {
|
|||
}
|
||||
if (expose_profiler === "true") {
|
||||
context.log.info("Custom profiler stop!");
|
||||
await commands.profiler.stop();
|
||||
if (context.options.browser === "firefox") {
|
||||
await commands.profiler.stop();
|
||||
} else if (context.options.browser === "chrome") {
|
||||
await commands.trace.stop();
|
||||
}
|
||||
}
|
||||
if (
|
||||
data == null &&
|
||||
|
|
|
|||
|
|
@ -29,7 +29,11 @@ module.exports = async function (context, commands) {
|
|||
context.log.info("Cycle %d, starting the measure", count);
|
||||
if (expose_profiler === "true") {
|
||||
context.log.info("Custom profiler start!");
|
||||
await commands.profiler.start();
|
||||
if (context.options.browser === "firefox") {
|
||||
await commands.profiler.start();
|
||||
} else if (context.options.browser === "chrome") {
|
||||
await commands.trace.start();
|
||||
}
|
||||
}
|
||||
await commands.measure.start(url);
|
||||
|
||||
|
|
@ -53,7 +57,11 @@ module.exports = async function (context, commands) {
|
|||
}
|
||||
if (expose_profiler === "true") {
|
||||
context.log.info("Custom profiler stop!");
|
||||
await commands.profiler.stop();
|
||||
if (context.options.browser === "firefox") {
|
||||
await commands.profiler.stop();
|
||||
} else if (context.options.browser === "chrome") {
|
||||
await commands.trace.stop();
|
||||
}
|
||||
}
|
||||
if (
|
||||
!data_exists &&
|
||||
|
|
|
|||
|
|
@ -236,16 +236,16 @@ class Browsertime(Perftest):
|
|||
def clean_up(self):
|
||||
super(Browsertime, self).clean_up()
|
||||
|
||||
def _expose_gecko_profiler(self, extra_profiler_run, test):
|
||||
def _expose_browser_profiler(self, extra_profiler_run, test):
|
||||
"""Use this method to check if we will use an exposed gecko profiler via browsertime.
|
||||
The exposed gecko profiler let's us control the start/stop during tests.
|
||||
At the moment we would only want this for the Firefox browser and for any test with the
|
||||
`expose_gecko_profiler` field set true (e.g. benchmark tests).
|
||||
The exposed browser profiler let's us control the start/stop during tests.
|
||||
At the moment we would only want this for the Firefox or Chrome* applications and for
|
||||
any test with the `expose_browser_profiler` field set true (e.g. benchmark tests).
|
||||
"""
|
||||
return (
|
||||
extra_profiler_run
|
||||
and test.get("expose_gecko_profiler")
|
||||
and self.config["app"] in GECKO_PROFILER_APPS
|
||||
and test.get("expose_browser_profiler")
|
||||
and self.config["app"] in GECKO_PROFILER_APPS + TRACE_APPS
|
||||
)
|
||||
|
||||
def _compose_cmd(self, test, timeout, extra_profiler_run=False):
|
||||
|
|
@ -380,7 +380,7 @@ class Browsertime(Perftest):
|
|||
os.environ.get("MOZ_FETCHES_DIR", "None"),
|
||||
"--browsertime.expose_profiler",
|
||||
"true"
|
||||
if (self._expose_gecko_profiler(extra_profiler_run, test))
|
||||
if self._expose_browser_profiler(extra_profiler_run, test)
|
||||
else "false",
|
||||
]
|
||||
|
||||
|
|
@ -582,7 +582,7 @@ class Browsertime(Perftest):
|
|||
LOG.info("Composing Gecko Profiler commands")
|
||||
self._init_gecko_profiling(test)
|
||||
priority1_options.append("--firefox.geckoProfiler")
|
||||
if self._expose_gecko_profiler(self.config.get("extra_profiler_run"), test):
|
||||
if self._expose_browser_profiler(self.config.get("extra_profiler_run"), test):
|
||||
priority1_options.extend(
|
||||
[
|
||||
"--firefox.geckoProfilerRecordingType",
|
||||
|
|
@ -629,7 +629,10 @@ class Browsertime(Perftest):
|
|||
|
||||
LOG.info("Composing Chrome Trace commands")
|
||||
self._init_chrome_trace(test)
|
||||
|
||||
priority1_options.extend(["--chrome.trace"])
|
||||
if self._expose_browser_profiler(self.config.get("extra_profiler_run"), test):
|
||||
priority1_options.extend(["--chrome.timelineRecordingType", "custom"])
|
||||
|
||||
# current categories to capture, we can modify this as needed in the future
|
||||
# reference:
|
||||
|
|
|
|||
|
|
@ -619,7 +619,7 @@ def get_raptor_test_list(args, oskey):
|
|||
"accept_zero_vismet",
|
||||
"interactive",
|
||||
"host_from_parent",
|
||||
"expose_gecko_profiler",
|
||||
"expose_browser_profiler",
|
||||
]
|
||||
for setting in bool_settings:
|
||||
if next_test.get(setting, None) is not None:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ alert_threshold = 2.0
|
|||
apps = firefox, chrome, chromium, safari
|
||||
gecko_profile_entries = 14000000
|
||||
gecko_profile_interval = 1
|
||||
expose_gecko_profiler = true
|
||||
expose_browser_profiler = true
|
||||
lower_is_better = true
|
||||
owner = :jandem and SpiderMonkey Team
|
||||
page_cycles = 4
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ alert_threshold = 2.0
|
|||
apps = firefox, chrome, chromium, safari
|
||||
gecko_profile_entries = 2000000
|
||||
gecko_profile_interval = 1
|
||||
expose_gecko_profiler = true
|
||||
expose_browser_profiler = true
|
||||
lower_is_better = true
|
||||
owner = PerfTest Team
|
||||
page_cycles = 1
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ alert_threshold = 2.0
|
|||
apps = firefox, chrome, chromium, safari
|
||||
gecko_profile_entries = 14000000
|
||||
gecko_profile_interval = 1
|
||||
expose_gecko_profiler = true
|
||||
expose_browser_profiler = true
|
||||
lower_is_better = false
|
||||
owner = :jandem and SpiderMonkey Team
|
||||
page_cycles = 4
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ alert_threshold = 2.0
|
|||
apps = firefox, chrome, chromium
|
||||
gecko_profile_entries = 14000000
|
||||
gecko_profile_interval = 1
|
||||
expose_gecko_profiler = true
|
||||
expose_browser_profiler = true
|
||||
lower_is_better = true
|
||||
owner = :jandem and SpiderMonkey Team
|
||||
page_cycles = 30
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ alert_threshold = 2.0
|
|||
apps = firefox, chrome, chromium, safari
|
||||
gecko_profile_entries = 8000000
|
||||
gecko_profile_interval = 1
|
||||
expose_gecko_profiler = true
|
||||
expose_browser_profiler = true
|
||||
lower_is_better = false
|
||||
page_cycles = 1
|
||||
page_timeout = 600000
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ apps = firefox, chrome, chromium, safari
|
|||
gecko_profile_entries = 8000000
|
||||
gecko_profile_interval = 1
|
||||
expose_gecko_profiler = true
|
||||
expose_chrome_trace = true
|
||||
lower_is_better = false
|
||||
owner = :jgilbert and Graphics(gfx) Team
|
||||
page_cycles = 5
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ alert_threshold = 2.0
|
|||
apps = firefox, chrome, chromium, safari, custom-car
|
||||
gecko_profile_entries = 14000000
|
||||
gecko_profile_interval = 1
|
||||
expose_gecko_profiler = true
|
||||
expose_browser_profiler = true
|
||||
lower_is_better = false
|
||||
owner = SpiderMonkey Team
|
||||
page_cycles = 5
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ alert_threshold = 2.0
|
|||
apps = firefox, chrome, chromium, safari
|
||||
gecko_profile_entries = 8000000
|
||||
gecko_profile_interval = 1
|
||||
expose_gecko_profiler = true
|
||||
expose_browser_profiler = true
|
||||
lower_is_better = false
|
||||
owner = :emelio and Layout Team
|
||||
page_cycles = 5
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue