diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp index b5de02bb3bce6..6c823eeaab81b 100644 --- a/accessible/generic/DocAccessible.cpp +++ b/accessible/generic/DocAccessible.cpp @@ -2429,20 +2429,10 @@ void DocAccessible::ContentRemoved(nsIContent* aContentNode) { } bool DocAccessible::RelocateARIAOwnedIfNeeded(nsIContent* aElement) { - if (!aElement->HasID()) return false; - - AttrRelProviders* list = GetRelProviders( - aElement->AsElement(), nsDependentAtomString(aElement->GetID())); - if (list) { - for (uint32_t idx = 0; idx < list->Length(); idx++) { - if (list->ElementAt(idx)->mRelAttr == nsGkAtoms::aria_owns) { - LocalAccessible* owner = GetAccessible(list->ElementAt(idx)->mContent); - if (owner) { - mNotificationController->ScheduleRelocation(owner); - return true; - } - } - } + RelatedAccIterator owners(mDoc, aElement, nsGkAtoms::aria_owns); + if (Accessible* owner = owners.Next()) { + mNotificationController->ScheduleRelocation(owner->AsLocal()); + return true; } return false; diff --git a/accessible/tests/browser/caching_granularity/browser_viewport_domain.js b/accessible/tests/browser/caching_granularity/browser_viewport_domain.js index d1ab65f6f9489..92290bf66ec15 100644 --- a/accessible/tests/browser/caching_granularity/browser_viewport_domain.js +++ b/accessible/tests/browser/caching_granularity/browser_viewport_domain.js @@ -8,8 +8,9 @@ addAccessibleTask( `
test
`, async function (browser, docAcc) { - // On Linux, the viewport cache is populated on the DocAccessible without - // explicitly requesting it and is present once the document has loaded. + // On Linux and macOS, inconsistently, the viewport cache is populated on + // the DocAccessible without explicitly requesting it and is present once + // the document has loaded. await testCachingPerPlatform(docAcc, "viewport", () => { docAcc.getState({}, {}); }); diff --git a/accessible/tests/browser/caching_granularity/head.js b/accessible/tests/browser/caching_granularity/head.js index 9bd55281da7e1..b4633b157d565 100644 --- a/accessible/tests/browser/caching_granularity/head.js +++ b/accessible/tests/browser/caching_granularity/head.js @@ -123,7 +123,8 @@ async function testCachingPerPlatform(accessible, attribute, queryCb) { attribute == "layout-guess" || attribute == "language" || attribute == "text" || - attribute == "style") + attribute == "style" || + attribute == "viewport") ) { // These attributes work on macOS, but aren't consistent. Events may happen // before document load complete that cause caching before the test starts. diff --git a/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js b/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js index 62ff3f5b83bf6..df1dcacfb2838 100644 --- a/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js +++ b/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js @@ -544,3 +544,65 @@ customElements.define("custom-listbox", await onReorder; } ); + +/** + * Test insertion of relocated by ID child after initial load + */ +addAccessibleTask( + `
`, + async function (browser, accDoc) { + const a = findAccessibleChildByID(accDoc, "a"); + is(a.children.length, 0, "'a' has no children"); + const waitFor = { + expected: [ + [EVENT_SHOW, "b"], + [EVENT_INNER_REORDER, a], + [EVENT_REORDER, accDoc], + ], + }; + await contentSpawnMutation(browser, waitFor, function () { + const b = content.document.createElement("div"); + b.id = "b"; + content.document.body.appendChild(b); + }); + is(getAccessibleDOMNodeID(a.firstChild), "b", "'a' owns relocated child"); + } +); + +/** + * Test insertion of relocated by child element reflection after initial load + */ +addAccessibleTask(`
`, async function (browser, accDoc) { + const a = findAccessibleChildByID(accDoc, "a"); + is(a.children.length, 0, "'a' has no children"); + + // Create div and add it to a's ariaOwnsElements. + // The refresh ticks called in contentSpawnMutation + // will cause a relocation to be scheduled and performed. + // Nothing will happen because 'b' is not parented yet. + let waitFor = { + unexpected: [ + [EVENT_SHOW, "b"], + [EVENT_INNER_REORDER, a], + [EVENT_REORDER, accDoc], + ], + }; + await contentSpawnMutation(browser, waitFor, function () { + content.b = content.document.createElement("div"); + content.b.id = "b"; + content.document.getElementById("a").ariaOwnsElements = [content.b]; + }); + + // Parent 'b'. It should relocate into 'a'. + waitFor = { + expected: [ + [EVENT_SHOW, "b"], + [EVENT_INNER_REORDER, a], + [EVENT_REORDER, accDoc], + ], + }; + await contentSpawnMutation(browser, waitFor, function () { + content.document.body.appendChild(content.b); + }); + is(getAccessibleDOMNodeID(a.firstChild), "b", "'a' owns relocated child"); +}); diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index f54a1538503b3..2fc549e65c98c 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -39,7 +39,6 @@ ChromeUtils.defineESModuleGetters(this, { E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs", ExtensionsUI: "resource:///modules/ExtensionsUI.sys.mjs", HomePage: "resource:///modules/HomePage.sys.mjs", - isProductURL: "chrome://global/content/shopping/ShoppingProduct.mjs", LightweightThemeConsumer: "resource://gre/modules/LightweightThemeConsumer.sys.mjs", LoginHelper: "resource://gre/modules/LoginHelper.sys.mjs", @@ -3600,14 +3599,8 @@ var XULBrowserWindow = { }, // Properties used to cache security state used to update the UI - _state: null, - _lastLocation: null, _event: null, _lastLocationForEvent: null, - // _isSecureContext can change without the state/location changing, due to security - // error pages that intercept certain loads. For example this happens sometimes - // with the the HTTPS-Only Mode error page (more details in bug 1656027) - _isSecureContext: null, // This is called in multiple ways: // 1. Due to the nsIWebProgressListener.onContentBlockingEvent notification. @@ -3654,41 +3647,23 @@ var XULBrowserWindow = { // 3. Called directly during this object's initializations. // aRequest will be null always in case 2 and 3, and sometimes in case 1. onSecurityChange(aWebProgress, aRequest, aState, _aIsSimulated) { - // Don't need to do anything if the data we use to update the UI hasn't - // changed - let uri = gBrowser.currentURI; - let spec = uri.spec; - let isSecureContext = gBrowser.securityUI.isSecureContext; - if ( - this._state == aState && - this._lastLocation == spec && - this._isSecureContext === isSecureContext - ) { - // Switching to a tab of the same URL doesn't change most security - // information, but tab specific permissions may be different. - gIdentityHandler.refreshIdentityBlock(); - return; - } - this._state = aState; - this._lastLocation = spec; - this._isSecureContext = isSecureContext; - // Make sure the "https" part of the URL is striked out or not, // depending on the current mixed active content blocking state. gURLBar.formatValue(); // Update the identity panel, making sure we use the precursorPrincipal's // URI where appropriate, for example about:blank windows. + let uri = gBrowser.currentURI; let uriOverride = this._securityURIOverride(gBrowser.selectedBrowser); if (uriOverride) { uri = uriOverride; - this._state |= Ci.nsIWebProgressListener.STATE_IDENTITY_ASSOCIATED; + aState |= Ci.nsIWebProgressListener.STATE_IDENTITY_ASSOCIATED; } try { uri = Services.io.createExposableURI(uri); } catch (e) {} - gIdentityHandler.updateIdentity(this._state, uri); + gIdentityHandler.updateIdentity(aState, uri); }, // simulate all change notifications after switching tabs diff --git a/browser/base/content/browser.js.globals b/browser/base/content/browser.js.globals index 746081f1d52a7..3c08424945429 100644 --- a/browser/base/content/browser.js.globals +++ b/browser/base/content/browser.js.globals @@ -128,7 +128,6 @@ "E10SUtils", "ExtensionsUI", "HomePage", - "isProductURL", "LightweightThemeConsumer", "LoginHelper", "LoginManagerParent", diff --git a/browser/base/content/test/performance/browser_preferences_usage.js b/browser/base/content/test/performance/browser_preferences_usage.js index 46d17a2f7bc6d..4ad2f8c1f5418 100644 --- a/browser/base/content/test/performance/browser_preferences_usage.js +++ b/browser/base/content/test/performance/browser_preferences_usage.js @@ -156,8 +156,7 @@ add_task(async function navigate_around() { // Disable bfcache so that we can measure more accurately the number of // pref accesses in the child processes. // If bfcache is enabled on Fission - // dom.ipc.keepProcessesAlive.webIsolated.perOrigin and - // security.sandbox.content.force-namespace are accessed only a couple of + // security.sandbox.content.force-namespace is accessed only a couple of // times. ["browser.sessionhistory.max_total_viewers", 0], ], @@ -183,12 +182,6 @@ add_task(async function navigate_around() { min: 50, max: 51, }; - // This pref is only accessed in automation to speed up tests. - knownProblematicPrefs["dom.ipc.keepProcessesAlive.webIsolated.perOrigin"] = - { - min: 50, - max: 51, - }; if (AppConstants.platform == "linux") { // The following sandbox pref is covered by // https://bugzilla.mozilla.org/show_bug.cgi?id=1600189 diff --git a/browser/base/content/test/static/browser.toml b/browser/base/content/test/static/browser.toml index 4e8a0ebe063c7..8798e6276ec63 100644 --- a/browser/base/content/test/static/browser.toml +++ b/browser/base/content/test/static/browser.toml @@ -24,6 +24,8 @@ skip-if = ["os == 'win' && msix"] # Permafail on MSIX packages due to it running ["browser_parsable_script.js"] skip-if = ["ccov && os == 'linux'"] # https://bugzilla.mozilla.org/show_bug.cgi?id=1608081 +["browser_glean_metrics_exist.js"] + ["browser_sentence_case_strings.js"] ["browser_title_case_menus.js"] diff --git a/browser/base/content/test/static/browser_glean_metrics_exist.js b/browser/base/content/test/static/browser_glean_metrics_exist.js new file mode 100644 index 0000000000000..755af762d736a --- /dev/null +++ b/browser/base/content/test/static/browser_glean_metrics_exist.js @@ -0,0 +1,259 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* This list allows pre-existing or 'unfixable' JS issues to remain, while we + * detect newly occurring issues in shipping JS. It is a list of regexes + * matching files which have errors: + */ + +requestLongerTimeout(2); + +const kAllowlist = new Set([ + /browser\/content\/browser\/places\/controller.js$/, +]); + +// Normally we would use reflect.sys.mjs to get Reflect.parse. However, if +// we do that, then all the AST data is allocated in reflect.sys.mjs's +// zone. That exposes a bug in our GC. The GC collects reflect.sys.mjs's +// zone but not the zone in which our test code lives (since no new +// data is being allocated in it). The cross-compartment wrappers in +// our zone that point to the AST data never get collected, and so the +// AST data itself is never collected. We need to GC both zones at +// once to fix the problem. +const init = Cc["@mozilla.org/jsreflect;1"].createInstance(); +init(); + +/** + * Check if an error should be ignored due to matching one of the allowlist + * objects. + * + * @param uri the uri to check against the allowlist + * @return true if the uri should be skipped, false otherwise. + */ +function uriIsAllowed(uri) { + for (let allowlistItem of kAllowlist) { + if (allowlistItem.test(uri.spec)) { + return true; + } + } + return false; +} + +function recursivelyCheckForGleanCalls(obj, parent = null) { + if (!obj) { + return; + } + + if (Array.isArray(obj)) { + for (let item of obj) { + recursivelyCheckForGleanCalls(item, { obj, parent }); + } + return; + } + + for (let key in obj) { + if (key == "loc") { + continue; + } + if (typeof obj[key] == "object") { + recursivelyCheckForGleanCalls(obj[key], { obj, parent }); + } + } + + if (obj.type != "Identifier" || obj.name != "Glean") { + return; + } + + function getMemberName(object, child) { + if ( + object.type == "MemberExpression" && + !object.computed && + object.object === child && + object.property.type == "Identifier" + ) { + return object.property.name; + } + return ""; + } + + let cat = getMemberName(parent.obj, obj); + if (cat) { + if (Glean.hasOwnProperty(cat)) { + ok(true, `The category ${cat} should exist in the global Glean object`); + } else { + record( + false, + `The category ${cat} should exist in the global Glean object`, + undefined, + `${obj.loc.source}:${obj.loc.start.line}` + ); + return; + } + + let name = getMemberName(parent.parent.obj, parent.obj); + if (name) { + if (Glean[cat].hasOwnProperty(name)) { + ok(true, `The metric ${name} should exist in the Glean.${cat} object`); + } else { + record( + false, + `The metric ${name} should exist in the Glean.${cat} object`, + undefined, + `${obj.loc.source}:${obj.loc.start.line}`, + // Object metrics are not supported yet in artifact builds (see bug 1883857), + // so we expect some failures. + Services.prefs.getBoolPref("telemetry.fog.artifact_build", false) + ? "fail" + : undefined + ); + return; + } + + let methodOrLabel = getMemberName( + parent.parent.parent.obj, + parent.parent.obj + ); + if (methodOrLabel) { + if (methodOrLabel in Glean[cat][name]) { + ok(true, `${methodOrLabel} should exist in Glean.${cat}.${name}`); + } else { + record( + false, + `${methodOrLabel} should exist in Glean.${cat}.${name}`, + undefined, + `${obj.loc.source}:${obj.loc.start.line}` + ); + return; + } + + let object = Glean[cat][name]; + let method = methodOrLabel; + if (typeof Glean[cat][name][methodOrLabel] == "object") { + method = getMemberName( + parent.parent.parent.parent.obj, + parent.parent.parent.obj + ); + if (!method) { + return; + } + object = Glean[cat][name][methodOrLabel]; + } + + if (method in object) { + ok(true, `${method} exists`); + is( + typeof object[method], + "function", + `${method} should be a function` + ); + } else { + record( + false, + `${method} should exist`, + undefined, + `${obj.loc.source}:${obj.loc.start.line}` + ); + } + } + } + } +} + +function parsePromise(uri, parseTarget) { + return new Promise(resolve => { + let xhr = new XMLHttpRequest(); + xhr.open("GET", uri, true); + xhr.onreadystatechange = function () { + if (this.readyState == this.DONE) { + let scriptText = this.responseText; + if (!scriptText.includes("Glean.")) { + resolve(); + return; + } + + try { + info(`Checking ${parseTarget} ${uri}`); + let parseOpts = { + source: uri, + target: parseTarget, + }; + recursivelyCheckForGleanCalls( + Reflect.parse(scriptText, parseOpts).body + ); + } catch (ex) { + let errorMsg = "Script error reading " + uri + ": " + ex; + ok(false, errorMsg); + } + resolve(); + } + }; + xhr.onerror = error => { + ok(false, "XHR error reading " + uri + ": " + error); + resolve(); + }; + xhr.overrideMimeType("application/javascript"); + xhr.send(null); + }); +} + +add_task(async function checkAllTheJS() { + // In debug builds, even on a fast machine, collecting the file list may take + // more than 30 seconds, and parsing all files may take four more minutes. + // For this reason, this test must be explictly requested in debug builds by + // using the "--setpref parse=" argument to mach. You can specify: + // - A case-sensitive substring of the file name to test (slow). + // - A single absolute URI printed out by a previous run (fast). + // - An empty string to run the test on all files (slowest). + let parseRequested = Services.prefs.prefHasUserValue("parse"); + let parseValue = parseRequested && Services.prefs.getCharPref("parse"); + if (SpecialPowers.isDebugBuild) { + if (!parseRequested) { + ok( + true, + "Test disabled on debug build. To run, execute: ./mach" + + " mochitest-browser --setpref parse=" + + " browser/base/content/test/general/browser_parsable_script.js" + ); + return; + } + // Request a 15 minutes timeout (30 seconds * 30) for debug builds. + requestLongerTimeout(30); + } + + let uris; + // If an absolute URI is specified on the command line, use it immediately. + if (parseValue && parseValue.includes(":")) { + uris = [NetUtil.newURI(parseValue)]; + } else { + let appDir = Services.dirsvc.get("GreD", Ci.nsIFile); + // This asynchronously produces a list of URLs (sadly, mostly sync on our + // test infrastructure because it runs against jarfiles there, and + // our zipreader APIs are all sync) + let startTimeMs = Date.now(); + info("Collecting URIs"); + uris = await generateURIsFromDirTree(appDir, [".js", ".jsm", ".mjs"]); + info("Collected URIs in " + (Date.now() - startTimeMs) + "ms"); + + // Apply the filter specified on the command line, if any. + if (parseValue) { + uris = uris.filter(uri => { + if (uri.spec.includes(parseValue)) { + return true; + } + info("Not checking filtered out " + uri.spec); + return false; + }); + } + } + + // We create an array of promises so we can parallelize all our parsing + // and file loading activity: + await PerfTestHelpers.throttledMapPromises(uris, uri => { + if (uriIsAllowed(uri)) { + info("Not checking allowlisted " + uri.spec); + return undefined; + } + return parsePromise(uri.spec, uriIsESModule(uri) ? "module" : "script"); + }); + ok(true, "All files parsed"); +}); diff --git a/browser/base/content/test/static/browser_parsable_script.js b/browser/base/content/test/static/browser_parsable_script.js index 71a2930ddc117..ef97d32ccde11 100644 --- a/browser/base/content/test/static/browser_parsable_script.js +++ b/browser/base/content/test/static/browser_parsable_script.js @@ -12,17 +12,6 @@ const kAllowlist = new Set([ /browser\/content\/browser\/places\/controller.js$/, ]); -const kESModuleList = new Set([ - /browser\/lockwise-card.js$/, - /browser\/monitor-card.js$/, - /browser\/proxy-card.js$/, - /browser\/vpn-card.js$/, - /toolkit\/content\/global\/certviewer\/components\/.*\.js$/, - /toolkit\/content\/global\/certviewer\/.*\.js$/, - /toolkit\/content\/global\/ml\/transformers.*\.js$/, - /chrome\/pdfjs\/content\/web\/.*\.js$/, -]); - // Normally we would use reflect.sys.mjs to get Reflect.parse. However, if // we do that, then all the AST data is allocated in reflect.sys.mjs's // zone. That exposes a bug in our GC. The GC collects reflect.sys.mjs's @@ -50,25 +39,6 @@ function uriIsAllowed(uri) { return false; } -/** - * Check if a URI should be parsed as an ES module. - * - * @param uri the uri to check against the ES module list - * @return true if the uri should be parsed as a module, otherwise parse it as a script. - */ -function uriIsESModule(uri) { - if (uri.filePath.endsWith(".mjs")) { - return true; - } - - for (let allowlistItem of kESModuleList) { - if (allowlistItem.test(uri.spec)) { - return true; - } - } - return false; -} - function parsePromise(uri, parseTarget) { let promise = new Promise(resolve => { let xhr = new XMLHttpRequest(); diff --git a/browser/base/content/test/static/head.js b/browser/base/content/test/static/head.js index 317ad430af164..b507eeaf5b3a2 100644 --- a/browser/base/content/test/static/head.js +++ b/browser/base/content/test/static/head.js @@ -21,6 +21,36 @@ var { PerfTestHelpers } = ChromeUtils.importESModule( "resource://testing-common/PerfTestHelpers.sys.mjs" ); +const kESModuleList = new Set([ + /browser\/lockwise-card.js$/, + /browser\/monitor-card.js$/, + /browser\/proxy-card.js$/, + /browser\/vpn-card.js$/, + /toolkit\/content\/global\/certviewer\/components\/.*\.js$/, + /toolkit\/content\/global\/certviewer\/.*\.js$/, + /toolkit\/content\/global\/ml\/transformers.*\.js$/, + /chrome\/pdfjs\/content\/web\/.*\.js$/, +]); + +/** + * Check if a URI should be parsed as an ES module. + * + * @param uri the uri to check against the ES module list + * @return true if the uri should be parsed as a module, otherwise parse it as a script. + */ +function uriIsESModule(uri) { + if (uri.filePath.endsWith(".mjs")) { + return true; + } + + for (let allowlistItem of kESModuleList) { + if (allowlistItem.test(uri.spec)) { + return true; + } + } + return false; +} + /** * Returns a promise that is resolved with a list of files that have one of the * extensions passed, represented by their nsIURI objects, which exist inside diff --git a/browser/components/backup/resources/BackupResource.sys.mjs b/browser/components/backup/resources/BackupResource.sys.mjs index d33af63f4e2eb..9d82d17a9828f 100644 --- a/browser/components/backup/resources/BackupResource.sys.mjs +++ b/browser/components/backup/resources/BackupResource.sys.mjs @@ -10,8 +10,22 @@ ChromeUtils.defineESModuleGetters(lazy, { Sqlite: "resource://gre/modules/Sqlite.sys.mjs", BackupError: "resource:///modules/backup/BackupError.mjs", ERRORS: "chrome://browser/content/backup/backup-constants.mjs", + PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs", }); +XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "isBrowsingHistoryEnabled", + "places.history.enabled", + true +); +XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "isSanitizeOnShutdownEnabled", + "privacy.sanitize.sanitizeOnShutdown", + false +); + // Convert from bytes to kilobytes (not kibibytes). export const BYTES_IN_KB = 1000; @@ -225,6 +239,20 @@ export class BackupResource { } } + /** + * Returns true if the browser is configured in such a way that backing up + * things related to browsing history is allowed. Otherwise, returns false. + * + * @returns {boolean} + */ + static canBackupHistory() { + return ( + !lazy.PrivateBrowsingUtils.permanentPrivateBrowsing && + !lazy.isSanitizeOnShutdownEnabled && + lazy.isBrowsingHistoryEnabled + ); + } + constructor() {} /** diff --git a/browser/components/backup/resources/CookiesBackupResource.sys.mjs b/browser/components/backup/resources/CookiesBackupResource.sys.mjs index fb7298d4a94f3..875d513746bfb 100644 --- a/browser/components/backup/resources/CookiesBackupResource.sys.mjs +++ b/browser/components/backup/resources/CookiesBackupResource.sys.mjs @@ -21,6 +21,10 @@ export class CookiesBackupResource extends BackupResource { profilePath = PathUtils.profileDir, _isEncrypting = false ) { + if (!BackupResource.canBackupHistory()) { + return null; + } + await BackupResource.copySqliteDatabases(profilePath, stagingPath, [ "cookies.sqlite", ]); diff --git a/browser/components/backup/resources/FormHistoryBackupResource.sys.mjs b/browser/components/backup/resources/FormHistoryBackupResource.sys.mjs index a5d6d7c1ea243..d179d92fc7011 100644 --- a/browser/components/backup/resources/FormHistoryBackupResource.sys.mjs +++ b/browser/components/backup/resources/FormHistoryBackupResource.sys.mjs @@ -21,6 +21,10 @@ export class FormHistoryBackupResource extends BackupResource { profilePath = PathUtils.profileDir, _isEncrypting = false ) { + if (!BackupResource.canBackupHistory()) { + return null; + } + await BackupResource.copySqliteDatabases(profilePath, stagingPath, [ "formhistory.sqlite", ]); diff --git a/browser/components/backup/resources/PlacesBackupResource.sys.mjs b/browser/components/backup/resources/PlacesBackupResource.sys.mjs index 23538c605a25f..b01b8d44cfa11 100644 --- a/browser/components/backup/resources/PlacesBackupResource.sys.mjs +++ b/browser/components/backup/resources/PlacesBackupResource.sys.mjs @@ -4,28 +4,13 @@ import { BackupResource } from "resource:///modules/backup/BackupResource.sys.mjs"; import { MeasurementUtils } from "resource:///modules/backup/MeasurementUtils.sys.mjs"; -import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { BookmarkJSONUtils: "resource://gre/modules/BookmarkJSONUtils.sys.mjs", - PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs", }); -XPCOMUtils.defineLazyPreferenceGetter( - lazy, - "isBrowsingHistoryEnabled", - "places.history.enabled", - true -); -XPCOMUtils.defineLazyPreferenceGetter( - lazy, - "isSanitizeOnShutdownEnabled", - "privacy.sanitize.sanitizeOnShutdown", - false -); - const BOOKMARKS_BACKUP_FILENAME = "bookmarks.jsonlz4"; /** @@ -49,16 +34,11 @@ export class PlacesBackupResource extends BackupResource { profilePath = PathUtils.profileDir, _isEncrypting = false ) { - let canBackupHistory = - !lazy.PrivateBrowsingUtils.permanentPrivateBrowsing && - !lazy.isSanitizeOnShutdownEnabled && - lazy.isBrowsingHistoryEnabled; - /** * Do not backup places.sqlite and favicons.sqlite if users have history disabled, want history cleared on shutdown or are using permanent private browsing mode. * Instead, export all existing bookmarks to a compressed JSON file that we can read when restoring the backup. */ - if (!canBackupHistory) { + if (!BackupResource.canBackupHistory()) { let bookmarksBackupFile = PathUtils.join( stagingPath, BOOKMARKS_BACKUP_FILENAME diff --git a/browser/components/backup/resources/PreferencesBackupResource.sys.mjs b/browser/components/backup/resources/PreferencesBackupResource.sys.mjs index 65aaa5a8c7997..728409e089140 100644 --- a/browser/components/backup/resources/PreferencesBackupResource.sys.mjs +++ b/browser/components/backup/resources/PreferencesBackupResource.sys.mjs @@ -39,12 +39,14 @@ export class PreferencesBackupResource extends BackupResource { ]; await BackupResource.copyFiles(profilePath, stagingPath, simpleCopyFiles); - const sqliteDatabases = ["permissions.sqlite", "content-prefs.sqlite"]; - await BackupResource.copySqliteDatabases( - profilePath, - stagingPath, - sqliteDatabases - ); + if (BackupResource.canBackupHistory()) { + const sqliteDatabases = ["permissions.sqlite", "content-prefs.sqlite"]; + await BackupResource.copySqliteDatabases( + profilePath, + stagingPath, + sqliteDatabases + ); + } // prefs.js is a special case - we have a helper function to flush the // current prefs state to disk off of the main thread. diff --git a/browser/components/backup/tests/xpcshell/head.js b/browser/components/backup/tests/xpcshell/head.js index 76af09cf2d4dd..0962927890a65 100644 --- a/browser/components/backup/tests/xpcshell/head.js +++ b/browser/components/backup/tests/xpcshell/head.js @@ -36,6 +36,13 @@ const { MockRegistrar } = ChromeUtils.importESModule( "resource://testing-common/MockRegistrar.sys.mjs" ); +const { PrivateBrowsingUtils } = ChromeUtils.importESModule( + "resource://gre/modules/PrivateBrowsingUtils.sys.mjs" +); + +const HISTORY_ENABLED_PREF = "places.history.enabled"; +const SANITIZE_ON_SHUTDOWN_PREF = "privacy.sanitize.sanitizeOnShutdown"; + let gFakeOSKeyStore; add_setup(async () => { diff --git a/browser/components/backup/tests/xpcshell/test_CookiesBackupResource.js b/browser/components/backup/tests/xpcshell/test_CookiesBackupResource.js index 1690580437fdd..26d924c3f2c11 100644 --- a/browser/components/backup/tests/xpcshell/test_CookiesBackupResource.js +++ b/browser/components/backup/tests/xpcshell/test_CookiesBackupResource.js @@ -104,6 +104,119 @@ add_task(async function test_backup() { sandbox.restore(); }); +/** + * Tests that the backup method does not copy the cookie database if the + * browser is configured to not save history - either while running, or to + * clear it at shutdown. + */ +add_task(async function test_backup_no_saved_history() { + let cookiesBackupResource = new CookiesBackupResource(); + let sourcePath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "CookiesBackupResource-source-test" + ); + let stagingPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "CookiesBackupResource-staging-test" + ); + + let sandbox = sinon.createSandbox(); + let fakeConnection = { + backup: sandbox.stub().resolves(true), + close: sandbox.stub().resolves(true), + }; + sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); + + // First, we'll try with browsing history in general being disabled. + Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, false); + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, false); + + let manifestEntry = await cookiesBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.deepEqual( + manifestEntry, + null, + "Should have gotten back a null ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.notCalled, + "No sqlite connections should have been made with remember history disabled" + ); + + // Now verify that the sanitize shutdown pref also prevents us from backing + // up cookies + Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, true); + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); + + fakeConnection.backup.resetHistory(); + manifestEntry = await cookiesBackupResource.backup(stagingPath, sourcePath); + Assert.deepEqual( + manifestEntry, + null, + "Should have gotten back a null ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.notCalled, + "No sqlite connections should have been made with sanitize shutdown enabled" + ); + + await maybeRemovePath(stagingPath); + await maybeRemovePath(sourcePath); + + sandbox.restore(); + Services.prefs.clearUserPref(HISTORY_ENABLED_PREF); + Services.prefs.clearUserPref(SANITIZE_ON_SHUTDOWN_PREF); +}); + +/** + * Tests that the backup method correctly skips backing up cookies when + * permanent private browsing mode is enabled. + */ +add_task(async function test_backup_private_browsing() { + let sandbox = sinon.createSandbox(); + + let cookiesBackupResource = new CookiesBackupResource(); + let sourcePath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "CookiesBackupResource-source-test" + ); + let stagingPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "CookiesBackupResource-staging-test" + ); + + let fakeConnection = { + backup: sandbox.stub().resolves(true), + close: sandbox.stub().resolves(true), + }; + sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); + sandbox.stub(PrivateBrowsingUtils, "permanentPrivateBrowsing").value(true); + + let manifestEntry = await cookiesBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.deepEqual( + manifestEntry, + null, + "Should have gotten back a null ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.notCalled, + "No sqlite connections should have been made with permanent private browsing enabled" + ); + + await maybeRemovePath(stagingPath); + await maybeRemovePath(sourcePath); + + sandbox.restore(); +}); + /** * Test that the recover method correctly copies items from the recovery * directory into the destination profile directory. diff --git a/browser/components/backup/tests/xpcshell/test_FormHistoryBackupResource.js b/browser/components/backup/tests/xpcshell/test_FormHistoryBackupResource.js index 93434daa9c728..124eb63f427ef 100644 --- a/browser/components/backup/tests/xpcshell/test_FormHistoryBackupResource.js +++ b/browser/components/backup/tests/xpcshell/test_FormHistoryBackupResource.js @@ -108,6 +108,122 @@ add_task(async function test_backup() { sandbox.restore(); }); +/** + * Tests that the backup method does not copy the form history database if the + * browser is configured to not save history - either while running, or to + * clear it at shutdown. + */ +add_task(async function test_backup_no_saved_history() { + let formHistoryBackupResource = new FormHistoryBackupResource(); + let sourcePath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "FormHistoryBackupResource-source-test" + ); + let stagingPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "FormHistoryBackupResource-staging-test" + ); + + let sandbox = sinon.createSandbox(); + let fakeConnection = { + backup: sandbox.stub().resolves(true), + close: sandbox.stub().resolves(true), + }; + sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); + + // First, we'll try with browsing history in general being disabled. + Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, false); + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, false); + + let manifestEntry = await formHistoryBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.deepEqual( + manifestEntry, + null, + "Should have gotten back a null ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.notCalled, + "No sqlite connections should have been made with remember history disabled" + ); + + // Now verify that the sanitize shutdown pref also prevents us from backing + // up form history + Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, true); + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); + + fakeConnection.backup.resetHistory(); + manifestEntry = await formHistoryBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.deepEqual( + manifestEntry, + null, + "Should have gotten back a null ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.notCalled, + "No sqlite connections should have been made with sanitize shutdown enabled" + ); + + await maybeRemovePath(stagingPath); + await maybeRemovePath(sourcePath); + + sandbox.restore(); + Services.prefs.clearUserPref(HISTORY_ENABLED_PREF); + Services.prefs.clearUserPref(SANITIZE_ON_SHUTDOWN_PREF); +}); + +/** + * Tests that the backup method correctly skips backing up form history when + * permanent private browsing mode is enabled. + */ +add_task(async function test_backup_private_browsing() { + let sandbox = sinon.createSandbox(); + + let formHistoryBackupResource = new FormHistoryBackupResource(); + let sourcePath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "FormHistoryBackupResource-source-test" + ); + let stagingPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "FormHistoryBackupResource-staging-test" + ); + + let fakeConnection = { + backup: sandbox.stub().resolves(true), + close: sandbox.stub().resolves(true), + }; + sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); + sandbox.stub(PrivateBrowsingUtils, "permanentPrivateBrowsing").value(true); + + let manifestEntry = await formHistoryBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.deepEqual( + manifestEntry, + null, + "Should have gotten back a null ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.notCalled, + "No sqlite connections should have been made with permanent private browsing enabled" + ); + + await maybeRemovePath(stagingPath); + await maybeRemovePath(sourcePath); + + sandbox.restore(); +}); + /** * Test that the recover method correctly copies items from the recovery * directory into the destination profile directory. diff --git a/browser/components/backup/tests/xpcshell/test_PlacesBackupResource.js b/browser/components/backup/tests/xpcshell/test_PlacesBackupResource.js index 0ffa91b36e8f5..b9ba78e32cb93 100644 --- a/browser/components/backup/tests/xpcshell/test_PlacesBackupResource.js +++ b/browser/components/backup/tests/xpcshell/test_PlacesBackupResource.js @@ -9,12 +9,6 @@ const { BookmarkJSONUtils } = ChromeUtils.importESModule( const { PlacesBackupResource } = ChromeUtils.importESModule( "resource:///modules/backup/PlacesBackupResource.sys.mjs" ); -const { PrivateBrowsingUtils } = ChromeUtils.importESModule( - "resource://gre/modules/PrivateBrowsingUtils.sys.mjs" -); - -const HISTORY_ENABLED_PREF = "places.history.enabled"; -const SANITIZE_ON_SHUTDOWN_PREF = "privacy.sanitize.sanitizeOnShutdown"; registerCleanupFunction(() => { /** diff --git a/browser/components/backup/tests/xpcshell/test_PreferencesBackupResource.js b/browser/components/backup/tests/xpcshell/test_PreferencesBackupResource.js index de8ca3a16fb7d..80bc20d53e4e5 100644 --- a/browser/components/backup/tests/xpcshell/test_PreferencesBackupResource.js +++ b/browser/components/backup/tests/xpcshell/test_PreferencesBackupResource.js @@ -151,6 +151,125 @@ add_task(async function test_backup() { sandbox.restore(); }); +/** + * Tests that the backup method does not copy the permissions or content prefs + * databases if the browser is configured to not save history - either while + * running, or to clear it at shutdown. + */ +add_task(async function test_backup_no_saved_history() { + let preferencesBackupResource = new PreferencesBackupResource(); + let sourcePath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "PreferencesBackupResource-source-test" + ); + let stagingPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "PreferencesBackupResource-staging-test" + ); + + let sandbox = sinon.createSandbox(); + let fakeConnection = { + backup: sandbox.stub().resolves(true), + close: sandbox.stub().resolves(true), + }; + sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); + + // First, we'll try with browsing history in general being disabled. + Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, false); + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, false); + + let manifestEntry = await preferencesBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.deepEqual( + manifestEntry, + { profilePath: sourcePath }, + "PreferencesBackupResource.backup should return the original profile path " + + "in its ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.notCalled, + "No sqlite connections should have been made with remember history disabled" + ); + + // Now verify that the sanitize shutdown pref also prevents us from backing + // up site permissions and preferences + Services.prefs.setBoolPref(HISTORY_ENABLED_PREF, true); + Services.prefs.setBoolPref(SANITIZE_ON_SHUTDOWN_PREF, true); + + fakeConnection.backup.resetHistory(); + manifestEntry = await preferencesBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.deepEqual( + manifestEntry, + { profilePath: sourcePath }, + "PreferencesBackupResource.backup should return the original profile path " + + "in its ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.notCalled, + "No sqlite connections should have been made with sanitize shutdown enabled" + ); + + await maybeRemovePath(stagingPath); + await maybeRemovePath(sourcePath); + + sandbox.restore(); + Services.prefs.clearUserPref(HISTORY_ENABLED_PREF); + Services.prefs.clearUserPref(SANITIZE_ON_SHUTDOWN_PREF); +}); + +/** + * Tests that the backup method correctly skips backing up the permissions and + * content prefs databases if permanent private browsing mode is enabled. + */ +add_task(async function test_backup_private_browsing() { + let sandbox = sinon.createSandbox(); + + let preferencesBackupResource = new PreferencesBackupResource(); + let sourcePath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "PreferencesBackupResource-source-test" + ); + let stagingPath = await IOUtils.createUniqueDirectory( + PathUtils.tempDir, + "PreferencesBackupResource-staging-test" + ); + + let fakeConnection = { + backup: sandbox.stub().resolves(true), + close: sandbox.stub().resolves(true), + }; + sandbox.stub(Sqlite, "openConnection").returns(fakeConnection); + sandbox.stub(PrivateBrowsingUtils, "permanentPrivateBrowsing").value(true); + + let manifestEntry = await preferencesBackupResource.backup( + stagingPath, + sourcePath + ); + Assert.deepEqual( + manifestEntry, + { profilePath: sourcePath }, + "PreferencesBackupResource.backup should return the original profile path " + + "in its ManifestEntry" + ); + + Assert.ok( + fakeConnection.backup.notCalled, + "No sqlite connections should have been made with permanent private browsing enabled" + ); + + await maybeRemovePath(stagingPath); + await maybeRemovePath(sourcePath); + + sandbox.restore(); +}); + /** * Test that the recover method correctly copies items from the recovery * directory into the destination profile directory. diff --git a/browser/components/extensions/test/browser/browser_ext_browserAction_area.js b/browser/components/extensions/test/browser/browser_ext_browserAction_area.js index 90ed744a78c54..bad9f9191c2ee 100644 --- a/browser/components/extensions/test/browser/browser_ext_browserAction_area.js +++ b/browser/components/extensions/test/browser/browser_ext_browserAction_area.js @@ -9,7 +9,7 @@ var browserAreas = { personaltoolbar: CustomizableUI.AREA_BOOKMARKS, }; -async function testInArea(area) { +async function testInArea(area, fallbackDefaultArea = null) { let manifest = { browser_action: { browser_style: true, @@ -24,17 +24,17 @@ async function testInArea(area) { await extension.startup(); let widget = getBrowserActionWidget(extension); let placement = CustomizableUI.getPlacementOfWidget(widget.id); - let fallbackDefaultArea = CustomizableUI.AREA_ADDONS; + let expectedArea = fallbackDefaultArea ?? browserAreas[area]; is( placement && placement.area, - browserAreas[area] || fallbackDefaultArea, + expectedArea, `widget located in correct area` ); await extension.unload(); } add_task(async function testBrowserActionDefaultArea() { - await testInArea(); + await testInArea(null, CustomizableUI.AREA_ADDONS); }); add_task(async function testBrowserActionInToolbar() { @@ -124,3 +124,41 @@ add_task(async function testPolicyOverridesBrowserActionToMenuPanel() { ); await extension.unload(); }); + +add_task(async function testBrowserActionWithVerticalTabs() { + await SpecialPowers.pushPrefEnv({ + set: [["sidebar.verticalTabs", true]], + }); + + await testInArea("tabstrip", CustomizableUI.AREA_ADDONS); + // Make sure other areas aren't affected. + await testInArea(null, CustomizableUI.AREA_ADDONS); + await testInArea("menupanel"); + await testInArea("navbar"); + await testInArea("personaltoolbar"); + + await SpecialPowers.popPrefEnv(); + + // Test action is still placed in tabstrip when sidebar.verticalTabs is not + // set to true anymore. + await testInArea("tabstrip"); +}); + +add_task(async function testBrowserActionWithPersonalToolbarNeverShown() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.toolbars.bookmarks.visibility", "never"]], + }); + + await testInArea("personaltoolbar", CustomizableUI.AREA_ADDONS); + // Make sure other areas aren't affected. + await testInArea(null, CustomizableUI.AREA_ADDONS); + await testInArea("menupanel"); + await testInArea("navbar"); + await testInArea("tabstrip"); + + await SpecialPowers.popPrefEnv(); + + // Test action is still placed in personaltoolbar if the bookmark.visibility + // pref is flipped back to its default value ('newtab'). + await testInArea("personaltoolbar"); +}); diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss index c9aef577fcedb..b7f3e9f77e6fe 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss @@ -31,6 +31,7 @@ $ds-card-image-gradient-solid: rgba(0, 0, 0, 100%); height: 100%; width: 100%; background: linear-gradient(90deg, rgba(255, 255, 255, 0%) 0%, var(--newtab-background-color-secondary) 50%, rgba(255, 255, 255, 0%) 100%); + z-index: 2; @media (prefers-reduced-motion: no-preference) { animation: loading 1.5s infinite; diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/ListFeed/ListFeed.jsx b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/ListFeed/ListFeed.jsx index 0e4edf2ad839b..008f2e2bd5a29 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/ListFeed/ListFeed.jsx +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/ListFeed/ListFeed.jsx @@ -20,40 +20,51 @@ function ListFeed({ type, firstVisibleTimestamp, recs }) { role="menu" aria-labelledby="list-feed-title" > - {recs.map(rec => ( - - ))} + {recs.map(rec => { + if (!rec || rec.placeholder) { + return ( + + ); + } + return ( + + ); + })} diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/ListFeed/_ListFeed.scss b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/ListFeed/_ListFeed.scss index 364081c204375..3316374c89d77 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/ListFeed/_ListFeed.scss +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/ListFeed/_ListFeed.scss @@ -20,9 +20,8 @@ .icon-trending { margin-inline-end: var(--space-small); - -moz-context-properties: stroke; - stroke: currentColor; transform: none; + fill: var(--newtab-text-primary-color); } } @@ -31,12 +30,36 @@ padding-inline-start: 0; margin: 0; } + + .ds-card.placeholder.list-card-placeholder { + box-shadow: unset; + padding-inline-end: var(--space-large); + padding-block: var(--space-large) var(--space-small); + + .placeholder-image { + height: 75px; + width: 75px; + position: absolute; + border-radius: var(--border-radius-medium); + inset-inline-end: var(--space-large); + } + + .placeholder-label { + margin-bottom: unset; + } + + .placeholder-header, .placeholder-description { + width: 60%; + height: 20px; + } + } } + .ds-card-grid .list-feed-content .ds-card.list-feed-card { // overrides when using the DSCard component background-color: var(--newtab-background-color-secondary); - border-block-start: 1px solid var(--color-gray-50); + border-block-start: 1px solid light-dark(var(--color-gray-70), var(--color-gray-50)); border-radius: 0; box-shadow: none; flex-direction: row-reverse; diff --git a/browser/components/newtab/css/activity-stream.css b/browser/components/newtab/css/activity-stream.css index 9a4f0dbdc8a43..f96a9027bbaa9 100644 --- a/browser/components/newtab/css/activity-stream.css +++ b/browser/components/newtab/css/activity-stream.css @@ -4814,6 +4814,7 @@ main section { height: 100%; width: 100%; background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, var(--newtab-background-color-secondary) 50%, rgba(255, 255, 255, 0) 100%); + z-index: 2; } @media (prefers-reduced-motion: no-preference) { .ds-card.placeholder-seen::before { @@ -6092,19 +6093,37 @@ main section { } .list-feed .list-feed-title .icon-trending { margin-inline-end: var(--space-small); - -moz-context-properties: stroke; - stroke: currentColor; transform: none; + fill: var(--newtab-text-primary-color); } .list-feed .list-feed-content { list-style: none; padding-inline-start: 0; margin: 0; } +.list-feed .ds-card.placeholder.list-card-placeholder { + box-shadow: unset; + padding-inline-end: var(--space-large); + padding-block: var(--space-large) var(--space-small); +} +.list-feed .ds-card.placeholder.list-card-placeholder .placeholder-image { + height: 75px; + width: 75px; + position: absolute; + border-radius: var(--border-radius-medium); + inset-inline-end: var(--space-large); +} +.list-feed .ds-card.placeholder.list-card-placeholder .placeholder-label { + margin-bottom: unset; +} +.list-feed .ds-card.placeholder.list-card-placeholder .placeholder-header, .list-feed .ds-card.placeholder.list-card-placeholder .placeholder-description { + width: 60%; + height: 20px; +} .ds-card-grid .list-feed-content .ds-card.list-feed-card { background-color: var(--newtab-background-color-secondary); - border-block-start: 1px solid var(--color-gray-50); + border-block-start: 1px solid light-dark(var(--color-gray-70), var(--color-gray-50)); border-radius: 0; box-shadow: none; flex-direction: row-reverse; diff --git a/browser/components/sidebar/browser-sidebar.js b/browser/components/sidebar/browser-sidebar.js index 372bc9eb79baf..ea2579705c7c2 100644 --- a/browser/components/sidebar/browser-sidebar.js +++ b/browser/components/sidebar/browser-sidebar.js @@ -1519,7 +1519,8 @@ var SidebarController = { toggleTabstrip() { let toVerticalTabs = CustomizableUI.verticalTabsEnabled; - let arrowScrollbox = gBrowser.tabContainer.arrowScrollbox; + let tabStrip = gBrowser.tabContainer; + let arrowScrollbox = tabStrip.arrowScrollbox; let currentScrollOrientation = arrowScrollbox.getAttribute("orient"); if ( @@ -1530,7 +1531,6 @@ var SidebarController = { return; } - let tabStrip = gBrowser.tabContainer; if (toVerticalTabs) { this.toggleExpanded(this._sidebarMain.expanded); arrowScrollbox.setAttribute("orient", "vertical"); @@ -1544,16 +1544,6 @@ var SidebarController = { let verticalToolbar = document.getElementById( CustomizableUI.AREA_VERTICAL_TABSTRIP ); - let indicatorTabs = gBrowser.visibleTabs.filter(tab => { - return ( - tab.hasAttribute("soundplaying") || - tab.hasAttribute("muted") || - tab.hasAttribute("activemedia-blocked") - ); - }); - for (const indicatorTab of indicatorTabs) { - tabStrip.updateTabIndicatorAttr(indicatorTab); - } verticalToolbar.toggleAttribute("visible", toVerticalTabs); }, }; diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js index 1f91d92efbe3d..2f6b9b16d3ce7 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -2751,7 +2751,8 @@ let animate = !skipAnimation && !pinned && - this.tabContainer.getAttribute("overflow") != "true" && + !this.tabContainer.verticalMode && + !this.tabContainer.overflowing && !gReduceMotion; let uriInfo = this._determineURIToLoad(uriString, createLazyBrowser); @@ -4160,6 +4161,7 @@ } let lockTabSizing = + !this.tabContainer.verticalMode && !aTab.pinned && !aTab.hidden && aTab._fullyOpen && @@ -4177,6 +4179,7 @@ isLastTab || aTab.pinned || aTab.hidden || + this.tabContainer.verticalMode || this._removingTabs.size > 3 /* don't want lots of concurrent animations */ || !aTab.hasAttribute( diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js index a00e4abd30784..6f8f017a07d14 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -115,14 +115,13 @@ "_tabMinWidthPref", "browser.tabs.tabMinWidth", null, - (pref, prevValue, newValue) => (this._tabMinWidth = newValue), + (pref, prevValue, newValue) => this.#updateTabMinWidth(newValue), newValue => { const LIMIT = 50; return Math.max(newValue, LIMIT); } ); - - this._tabMinWidth = this._tabMinWidthPref; + this.#updateTabMinWidth(this._tabMinWidthPref); CustomizableUI.addListener(this); this._updateNewTabVisibility(); @@ -158,6 +157,19 @@ } this._positionPinnedTabs(); + this.#updateTabMinWidth(); + + let indicatorTabs = gBrowser.visibleTabs.filter(tab => { + return ( + tab.hasAttribute("soundplaying") || + tab.hasAttribute("muted") || + tab.hasAttribute("activemedia-blocked") + ); + }); + for (const indicatorTab of indicatorTabs) { + this.updateTabIndicatorAttr(indicatorTab); + } + super.attributeChangedCallback(name, oldValue, newValue); } @@ -1326,8 +1338,16 @@ return node.before(tab); } - set _tabMinWidth(val) { - this.style.setProperty("--tab-min-width", val + "px"); + #updateTabMinWidth(val) { + const minWidthVariable = "--tab-min-width"; + if (this.verticalMode) { + this.style.removeProperty(minWidthVariable); + } else { + this.style.setProperty( + minWidthVariable, + (val ?? this._tabMinWidthPref) + "px" + ); + } } get _isCustomizing() { @@ -1474,6 +1494,10 @@ * Try to keep the active tab's close button under the mouse cursor */ _lockTabSizing(aTab, aTabWidth) { + if (this.verticalMode) { + return; + } + let tabs = this._getVisibleTabs(); if (!tabs.length) { return; diff --git a/browser/locales/l10n-changesets.json b/browser/locales/l10n-changesets.json index 19183daf49ef1..72a6f2b8c577f 100644 --- a/browser/locales/l10n-changesets.json +++ b/browser/locales/l10n-changesets.json @@ -16,7 +16,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "af": { "pin": false, @@ -35,7 +35,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "an": { "pin": false, @@ -54,7 +54,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ar": { "pin": false, @@ -73,7 +73,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ast": { "pin": false, @@ -92,7 +92,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "az": { "pin": false, @@ -111,7 +111,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "be": { "pin": false, @@ -130,7 +130,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "bg": { "pin": false, @@ -149,7 +149,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "bn": { "pin": false, @@ -168,7 +168,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "bo": { "pin": false, @@ -187,7 +187,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "br": { "pin": false, @@ -206,7 +206,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "brx": { "pin": false, @@ -225,7 +225,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "bs": { "pin": false, @@ -244,7 +244,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ca": { "pin": false, @@ -263,7 +263,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ca-valencia": { "pin": false, @@ -282,7 +282,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "cak": { "pin": false, @@ -301,7 +301,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ckb": { "pin": false, @@ -320,7 +320,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "cs": { "pin": false, @@ -339,7 +339,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "cy": { "pin": false, @@ -358,7 +358,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "da": { "pin": false, @@ -377,7 +377,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "de": { "pin": false, @@ -396,7 +396,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "dsb": { "pin": false, @@ -415,7 +415,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "el": { "pin": false, @@ -434,7 +434,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "en-CA": { "pin": false, @@ -453,7 +453,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "en-GB": { "pin": false, @@ -472,7 +472,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "eo": { "pin": false, @@ -491,7 +491,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "es-AR": { "pin": false, @@ -510,7 +510,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "es-CL": { "pin": false, @@ -529,7 +529,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "es-ES": { "pin": false, @@ -548,7 +548,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "es-MX": { "pin": false, @@ -567,7 +567,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "et": { "pin": false, @@ -586,7 +586,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "eu": { "pin": false, @@ -605,7 +605,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "fa": { "pin": false, @@ -624,7 +624,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ff": { "pin": false, @@ -643,7 +643,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "fi": { "pin": false, @@ -662,7 +662,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "fr": { "pin": false, @@ -681,7 +681,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "fur": { "pin": false, @@ -700,7 +700,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "fy-NL": { "pin": false, @@ -719,7 +719,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ga-IE": { "pin": false, @@ -738,7 +738,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "gd": { "pin": false, @@ -757,7 +757,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "gl": { "pin": false, @@ -776,7 +776,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "gn": { "pin": false, @@ -795,7 +795,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "gu-IN": { "pin": false, @@ -814,7 +814,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "he": { "pin": false, @@ -833,7 +833,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "hi-IN": { "pin": false, @@ -852,7 +852,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "hr": { "pin": false, @@ -871,7 +871,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "hsb": { "pin": false, @@ -890,7 +890,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "hu": { "pin": false, @@ -909,7 +909,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "hy-AM": { "pin": false, @@ -928,7 +928,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "hye": { "pin": false, @@ -947,7 +947,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ia": { "pin": false, @@ -966,7 +966,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "id": { "pin": false, @@ -985,7 +985,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "is": { "pin": false, @@ -1004,7 +1004,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "it": { "pin": false, @@ -1023,7 +1023,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ja": { "pin": false, @@ -1040,7 +1040,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ja-JP-mac": { "pin": false, @@ -1048,7 +1048,7 @@ "macosx64", "macosx64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ka": { "pin": false, @@ -1067,7 +1067,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "kab": { "pin": false, @@ -1086,7 +1086,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "kk": { "pin": false, @@ -1105,7 +1105,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "km": { "pin": false, @@ -1124,7 +1124,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "kn": { "pin": false, @@ -1143,7 +1143,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ko": { "pin": false, @@ -1162,7 +1162,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "lij": { "pin": false, @@ -1181,7 +1181,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "lo": { "pin": false, @@ -1200,7 +1200,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "lt": { "pin": false, @@ -1219,7 +1219,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ltg": { "pin": false, @@ -1238,7 +1238,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "lv": { "pin": false, @@ -1257,7 +1257,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "meh": { "pin": false, @@ -1276,7 +1276,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "mk": { "pin": false, @@ -1295,7 +1295,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "mr": { "pin": false, @@ -1314,7 +1314,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ms": { "pin": false, @@ -1333,7 +1333,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "my": { "pin": false, @@ -1352,7 +1352,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "nb-NO": { "pin": false, @@ -1371,7 +1371,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ne-NP": { "pin": false, @@ -1390,7 +1390,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "nl": { "pin": false, @@ -1409,7 +1409,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "nn-NO": { "pin": false, @@ -1428,7 +1428,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "oc": { "pin": false, @@ -1447,7 +1447,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "pa-IN": { "pin": false, @@ -1466,7 +1466,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "pl": { "pin": false, @@ -1485,7 +1485,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "pt-BR": { "pin": false, @@ -1504,7 +1504,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "pt-PT": { "pin": false, @@ -1523,7 +1523,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "rm": { "pin": false, @@ -1542,7 +1542,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ro": { "pin": false, @@ -1561,7 +1561,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ru": { "pin": false, @@ -1580,7 +1580,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sat": { "pin": false, @@ -1599,7 +1599,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sc": { "pin": false, @@ -1618,7 +1618,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "scn": { "pin": false, @@ -1637,7 +1637,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sco": { "pin": false, @@ -1656,7 +1656,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "si": { "pin": false, @@ -1675,7 +1675,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sk": { "pin": false, @@ -1694,7 +1694,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "skr": { "pin": false, @@ -1713,7 +1713,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sl": { "pin": false, @@ -1732,7 +1732,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "son": { "pin": false, @@ -1751,7 +1751,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sq": { "pin": false, @@ -1770,7 +1770,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sr": { "pin": false, @@ -1789,7 +1789,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sv-SE": { "pin": false, @@ -1808,7 +1808,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "szl": { "pin": false, @@ -1827,7 +1827,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ta": { "pin": false, @@ -1846,7 +1846,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "te": { "pin": false, @@ -1865,7 +1865,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "tg": { "pin": false, @@ -1884,7 +1884,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "th": { "pin": false, @@ -1903,7 +1903,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "tl": { "pin": false, @@ -1922,7 +1922,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "tr": { "pin": false, @@ -1941,7 +1941,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "trs": { "pin": false, @@ -1960,7 +1960,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "uk": { "pin": false, @@ -1979,7 +1979,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ur": { "pin": false, @@ -1998,7 +1998,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "uz": { "pin": false, @@ -2017,7 +2017,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "vi": { "pin": false, @@ -2036,7 +2036,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "wo": { "pin": false, @@ -2055,7 +2055,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "xh": { "pin": false, @@ -2074,7 +2074,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "zh-CN": { "pin": false, @@ -2093,7 +2093,7 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "zh-TW": { "pin": false, @@ -2112,6 +2112,6 @@ "win64-aarch64-devedition", "win64-devedition" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" } } \ No newline at end of file diff --git a/browser/themes/shared/browser-shared.css b/browser/themes/shared/browser-shared.css index e4b6f2821cf3a..a437ca50aa485 100644 --- a/browser/themes/shared/browser-shared.css +++ b/browser/themes/shared/browser-shared.css @@ -70,6 +70,7 @@ body { --urlbar-search-mode-picker-persisted-background-color: color-mix(in srgb, currentColor 14%, transparent); --urlbar-search-mode-picker-persisted-background-color-hover: color-mix(in srgb, currentColor 28%, transparent); --urlbar-search-mode-picker-persisted-background-color-active: color-mix(in srgb, currentColor 35%, transparent); + --urlbar-searchmodeswitcher-spacing: 6px; --pocket-icon-fill: #ef4056; diff --git a/browser/themes/shared/sidebar.css b/browser/themes/shared/sidebar.css index 126bbfc73f4c9..9b9ab3420444b 100644 --- a/browser/themes/shared/sidebar.css +++ b/browser/themes/shared/sidebar.css @@ -73,6 +73,9 @@ .sidebar-splitter { --splitter-width: 4px; + /* Ensure the splitter is painted on top of the sidebar box it overlaps. + Otherwise, the user may be unable to drag the splitter to resize the sidebar. */ + z-index: 1; /* stylelint-disable-next-line media-query-no-invalid */ @media (-moz-bool-pref: "sidebar.revamp") or (not (-moz-platform: linux)) { diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css index 2cde31d8cf2f3..b447bcf90f964 100644 --- a/browser/themes/shared/tabbrowser/tabs.css +++ b/browser/themes/shared/tabbrowser/tabs.css @@ -11,9 +11,10 @@ &[uidensity=touch] { --tab-min-height: 41px; } - --collapsed-tab-width: 40px; - --inline-tab-padding: var(--space-medium); + --tab-collapsed-width: 40px; + --tab-inline-padding: var(--space-medium); --tab-border-radius: 4px; + --tab-overflow-clip-margin: 2px; --tab-shadow-max-size: 6px; --tab-block-margin: 4px; --tab-icon-end-margin: 5.5px; @@ -50,24 +51,32 @@ } #tabbrowser-tabs { - --tab-min-width: 76px; - --tab-overflow-pinned-tabs-width: 0px; - padding-inline: var(--tab-overflow-pinned-tabs-width) 0; /* Use a bigger flex value than the searchbar to prevent it from * taking all the toolbar space. */ flex: 1000 1000; - &[orient="horizontal"][positionpinnedtabs] > #tabbrowser-arrowscrollbox::part(scrollbox) { - /* Add padding to match the shadow's blur radius so the - shadow doesn't get clipped when either the first or - last tab is selected */ - padding-inline: var(--tab-shadow-max-size); - } + &[orient="horizontal"] { + --tab-overflow-pinned-tabs-width: 0px; + padding-inline: var(--tab-overflow-pinned-tabs-width) 0; + + --tab-min-width: 76px; + :root[uidensity="touch"] & { + /* Touch mode needs additional space for the close button. */ + --tab-min-width: 86px; + } + + &[positionpinnedtabs] > #tabbrowser-arrowscrollbox::part(scrollbox) { + /* Add padding to match the shadow's blur radius so the + shadow doesn't get clipped when either the first or + last tab is selected */ + padding-inline: var(--tab-shadow-max-size); + } - /* Make it easier to drag tabs by expanding the drag area downwards. */ - &[movingtab] { - padding-bottom: 15px; - margin-bottom: -15px; + /* Make it easier to drag tabs by expanding the drag area downwards. */ + &[movingtab] { + padding-bottom: 15px; + margin-bottom: -15px; + } } } @@ -103,16 +112,15 @@ border-radius: 0; border-width: 0; margin: 0; - padding: 0 2px; + padding: 0 var(--tab-overflow-clip-margin); align-items: stretch; /* Needed so that overflowing content overflows towards the end rather than getting centered. That prevents tab opening animation from looking off at the start, see bug 1759221. */ justify-content: flex-start; overflow: clip; - /* Needed to avoid clipping the tab-background shadow, which has a 4px blur - * (we only have 2px padding in the inline direction) */ - overflow-clip-margin: 2px; + /* Needed to avoid clipping the tab-background shadow, which has a 4px blur. */ + overflow-clip-margin: var(--tab-overflow-clip-margin); &:not([pinned]) { flex: 100 100; @@ -120,11 +128,6 @@ min-width: var(--tab-min-width); transition: min-width 100ms ease-out, max-width 100ms ease-out; - - :root[uidensity=touch] & { - /* Touch mode needs additional space for the close button. */ - min-width: calc(var(--tab-min-width) + 10px); - } } &:not([pinned], [fadein]) { @@ -158,7 +161,7 @@ } .tab-content { - padding: 0 var(--inline-tab-padding); + padding: 0 var(--tab-inline-padding); &:not([pinned]) { min-width: 0; @@ -515,7 +518,7 @@ .tab-close-button { -moz-context-properties: fill, fill-opacity; - margin-inline-end: calc(var(--inline-tab-padding) / -2); + margin-inline-end: calc(var(--tab-inline-padding) / -2); width: 24px; height: 24px; padding: 6px; @@ -805,7 +808,8 @@ tab-group { font: message-box; /* match .tabbrowser-tab on macOS */ min-height: var(--tab-min-height); border-radius: var(--border-radius-medium); - padding: 0 var(--inline-tab-padding); + padding: 0 var(--tab-inline-padding); + margin-inline: var(--tab-overflow-clip-margin); #tabbrowser-tabs[orient="horizontal"] > &, #tabbrowser-tabs[orient="vertical"]:not([expanded]) > & > .toolbarbutton-text { @@ -826,7 +830,7 @@ tab-group { #vertical-tabs { overflow: hidden; display: none; - padding-inline: var(--space-medium); + padding-inline: calc(var(--space-medium) - var(--tab-overflow-clip-margin)); padding-block-start: var(--space-medium); &[visible] { @@ -836,7 +840,7 @@ tab-group { #vertical-pinned-tabs-container { display: grid; - grid-template-columns: repeat(auto-fit, minmax(var(--collapsed-tab-width), auto)); + grid-template-columns: repeat(auto-fit, minmax(var(--tab-collapsed-width), auto)); overflow-y: auto; overflow-x: hidden; scrollbar-width: thin; @@ -867,16 +871,23 @@ tab-group { } #tabbrowser-tabs[orient="vertical"] { - overflow: hidden; + --tab-min-width: unset; + + min-height: 0; display: flex; flex-direction: column; align-content: flex-start; grid-gap: var(--space-small); + padding: 0; /* override tabbox.css on macOS */ &[overflow] { border-bottom: var(--tabstrip-inner-border); } + .tabbrowser-tab { + flex: none; + } + .tab-close-button { display: none; } @@ -893,9 +904,7 @@ tab-group { &:not([expanded]) { .tabbrowser-tab { - min-width: inherit; - width: var(--collapsed-tab-width); - flex: none; + width: var(--tab-collapsed-width); } .tab-label-container { @@ -907,10 +916,7 @@ tab-group { --tab-icon-end-margin: 7.5px; .tabbrowser-tab { - min-width: calc(100% - var(--space-medium)); - flex: none; max-width: none; - padding: 0; &:is(:hover, [selected]):not([pinned]) .tab-close-button { display: flex; diff --git a/browser/themes/shared/urlbar-searchbar.css b/browser/themes/shared/urlbar-searchbar.css index 4b563e0f58f32..0e7f2b526879f 100644 --- a/browser/themes/shared/urlbar-searchbar.css +++ b/browser/themes/shared/urlbar-searchbar.css @@ -472,7 +472,8 @@ display: none; } -#urlbar-search-mode-indicator-close { +#urlbar-search-mode-indicator-close, +#searchmode-switcher-close { background: url(chrome://global/skin/icons/close.svg) no-repeat center; background-size: round(62.5%, 2px); width: round(max(16px, 1em), 2px); @@ -1116,11 +1117,17 @@ moz-input-box > menupopup .context-menu-add-engine > .menu-iconic-left::after { } #urlbar-searchmode-switcher { + appearance: none; display: none; - background-color: var(--toolbar-field-background-color); - border-radius: var(--toolbarbutton-border-radius); - margin-inline: 0 var(--urlbar-icon-padding); - padding-block: 0; + background-color: var(--urlbar-box-bgcolor); + border-radius: var(--urlbar-icon-border-radius); + margin: 0; + margin-inline-end: var(--urlbar-icon-padding); + padding-inline: var(--urlbar-searchmodeswitcher-spacing); + + #urlbar[focused] & { + background-color: var(--urlbar-box-focus-bgcolor); + } &:focus-visible { outline: var(--focus-outline); @@ -1151,19 +1158,19 @@ moz-input-box > menupopup .context-menu-add-engine > .menu-iconic-left::after { } #searchmode-switcher-icon { - width: calc(var(--urlbar-min-height) - 2px - 2 * var(--urlbar-container-padding)); - height: calc(var(--urlbar-min-height) - 2px - 2 * var(--urlbar-container-padding)); + width: 16px; + height: 16px; border-radius: var(--urlbar-icon-border-radius); - padding: var(--urlbar-icon-padding); -moz-context-properties: fill; fill: var(--text-color-deemphasized); } #searchmode-switcher-chicklet { - background-color: var(--toolbar-field-background-color); + background-color: var(--urlbar-box-bgcolor); border-start-end-radius: var(--toolbarbutton-border-radius); - border-end-end-radius: var(--toolbarbutton-border-radius); + border-end-end-radius: var(--urlbar-icon-border-radius); align-items: center; + height: 100%; margin-inline-end: var(--urlbar-icon-padding); display: none; @@ -1173,10 +1180,18 @@ moz-input-box > menupopup .context-menu-add-engine > .menu-iconic-left::after { display: inline-flex; } } + + #urlbar[focused] & { + background-color: var(--urlbar-box-focus-bgcolor); + } + + #urlbar[persistsearchterms] & { + background-color: var(--urlbar-search-mode-picker-persisted-background-color); + } } #searchmode-switcher-title { - margin-inline-start: 0; + margin: 0; align-items: center; &:empty { @@ -1185,10 +1200,9 @@ moz-input-box > menupopup .context-menu-add-engine > .menu-iconic-left::after { } #searchmode-switcher-close { - list-style-image: url("chrome://global/skin/icons/close-12.svg"); + appearance: none; pointer-events: all; - -moz-context-properties: fill; - fill: var(--text-color-deemphasized); + margin-inline: var(--urlbar-searchmodeswitcher-spacing); #urlbar[searchmode] & { display: inline-flex; @@ -1196,6 +1210,8 @@ moz-input-box > menupopup .context-menu-add-engine > .menu-iconic-left::after { } #searchmode-switcher-dropmarker { + margin-inline-start: var(--urlbar-searchmodeswitcher-spacing); + #urlbar[searchmode] & { display: none; } diff --git a/build.gradle b/build.gradle index 01592592613f9..a350a8ad187cd 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ buildscript { ksp_plugin = Versions.ksp_plugin // Used in mobile/android/fenix/app/build.gradle - protobuf_plugin = FenixVersions.protobuf_plugin + protobuf_plugin = Versions.protobuf_plugin } dependencies { diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure index 1c6a6a6b6f728..19ef32d97a41d 100644 --- a/build/moz.configure/toolchain.configure +++ b/build/moz.configure/toolchain.configure @@ -2865,6 +2865,13 @@ def security_hardening_cflags( if debug: flags.extend(trivial_auto_var_init) + if (c_compiler.type == "clang" and c_compiler.version >= "16") or ( + c_compiler.type == "gcc" and c_compiler.version >= "13" + ): + # Cannot use level 3 because we have many uses of the [0] GNU syntax. + # Cannot use level 2 because sqlite3 and icu use the [1] GNU syntax. + flags.append("-fstrict-flex-arrays=1") + # ASLR ------------------------------------------------ # ASLR (dynamicbase) is enabled by default in clang-cl; but the # mingw-clang build requires it to be explicitly enabled diff --git a/caps/nsScriptSecurityManager.h b/caps/nsScriptSecurityManager.h index f97170b145e97..5400c9f2254c1 100644 --- a/caps/nsScriptSecurityManager.h +++ b/caps/nsScriptSecurityManager.h @@ -81,8 +81,6 @@ class nsScriptSecurityManager final : public nsIScriptSecurityManager { bool aFromPrivateWindow, uint64_t aInnerWindowID = 0); - static uint32_t HashPrincipalByOrigin(nsIPrincipal* aPrincipal); - static bool GetStrictFileOriginPolicy() { return sStrictFileOriginPolicy; } void DeactivateDomainPolicy(); diff --git a/devtools/client/inspector/fonts/fonts.js b/devtools/client/inspector/fonts/fonts.js index cde47bc93823e..f134a8e632fb6 100644 --- a/devtools/client/inspector/fonts/fonts.js +++ b/devtools/client/inspector/fonts/fonts.js @@ -118,7 +118,6 @@ class FontInspector { this.update = this.update.bind(this); this.updateFontVariationSettings = this.updateFontVariationSettings.bind(this); - this.onResourceAvailable = this.onResourceAvailable.bind(this); this.init(); } @@ -185,11 +184,6 @@ class FontInspector { // @see ToolSidebar.onSidebarTabSelected() this.inspector.sidebar.on("fontinspector-selected", this.onNewNode); - this.inspector.toolbox.resourceCommand.watchResources( - [this.inspector.toolbox.resourceCommand.TYPES.DOCUMENT_EVENT], - { onAvailable: this.onResourceAvailable } - ); - // Listen for theme changes as the color of the previews depend on the theme gDevTools.on("theme-switched", this.onThemeChanged); } @@ -330,12 +324,6 @@ class FontInspector { this.ruleView.off("property-value-updated", this.onRulePropertyUpdated); gDevTools.off("theme-switched", this.onThemeChanged); - this.inspector.toolbox.resourceCommand.unwatchResources( - [this.inspector.toolbox.resourceCommand.TYPES.DOCUMENT_EVENT], - { onAvailable: this.onResourceAvailable } - ); - - this.fontsHighlighter = null; this.document = null; this.inspector = null; this.node = null; @@ -348,21 +336,6 @@ class FontInspector { this.writers = null; } - onResourceAvailable(resources) { - for (const resource of resources) { - if ( - resource.resourceType === - this.inspector.commands.resourceCommand.TYPES.DOCUMENT_EVENT && - resource.name === "will-navigate" && - resource.targetFront.isTopLevel - ) { - // Reset the fontsHighlighter so the next call to `onToggleFontHighlight` will - // re-create it from the inspector front tied to the new document. - this.fontsHighlighter = null; - } - } - } - /** * Get all expected CSS font properties and values from the node's matching rules and * fallback to computed style. Skip CSS Custom Properties, `calc()` and keyword values. @@ -896,32 +869,24 @@ class FontInspector { * just to the current element selection. */ async onToggleFontHighlight(font, show, isForCurrentElement = true) { - if (!this.fontsHighlighter) { - try { - this.fontsHighlighter = - await this.inspector.inspectorFront.getHighlighterByType( - HIGHLIGHTER_TYPES.FONTS - ); - } catch (e) { - // the FontsHighlighter won't be available when debugging a XUL document. - // Silently fail here and prevent any future calls to the function. - this.onToggleFontHighlight = () => {}; - return; - } - } - try { if (show) { const node = isForCurrentElement - ? this.node + ? this.inspector.selection.nodeFront : this.node.walkerFront.rootNode; - await this.fontsHighlighter.show(node, { - CSSFamilyName: font.CSSFamilyName, - name: font.name, - }); + await this.inspector.highlighters.showHighlighterTypeForNode( + HIGHLIGHTER_TYPES.FONTS, + node, + { + CSSFamilyName: font.CSSFamilyName, + name: font.name, + } + ); } else { - await this.fontsHighlighter.hide(); + await this.inspector.highlighters.hideHighlighterType( + HIGHLIGHTER_TYPES.FONTS + ); } } catch (e) { // Silently handle protocol errors here, because these might be called during diff --git a/devtools/client/inspector/fonts/test/browser_fontinspector_reveal-in-page.js b/devtools/client/inspector/fonts/test/browser_fontinspector_reveal-in-page.js index a4cfb4533afaf..e6a39795bf090 100644 --- a/devtools/client/inspector/fonts/test/browser_fontinspector_reveal-in-page.js +++ b/devtools/client/inspector/fonts/test/browser_fontinspector_reveal-in-page.js @@ -11,16 +11,20 @@ add_task(async function () { // events simulation will fail. await pushPref("devtools.toolbox.footer.height", 500); - const { view } = await openFontInspectorForURL(TEST_URI); - await testFontHighlighting(view); + const { inspector, view } = await openFontInspectorForURL(TEST_URI); + await testFontHighlighting(view, inspector); info("Check that highlighting still works after reloading the page"); await reloadBrowser(); - await testFontHighlighting(view); + await testFontHighlighting(view, inspector); + + info("Check that highlighting works for iframe nodes"); + await testFontHighlightingInIframe(view, inspector); }); -async function testFontHighlighting(view) { +async function testFontHighlighting(view, inspector) { + await selectNode("body", inspector); // The number of window selection change events we expect to get as we hover over each // font in the list. Waiting for those events is how we know that text-runs were // highlighted in the page. @@ -68,7 +72,10 @@ async function testFontHighlighting(view) { // Simulating a mouse over event on the font name and expecting a selectionchange. const nameEl = fontEls[i]; - let onEvents = waitForNSelectionEvents(expectedEvents); + let onEvents = waitForNSelectionEvents( + gBrowser.selectedBrowser, + expectedEvents + ); EventUtils.synthesizeMouse( nameEl, 2, @@ -82,7 +89,7 @@ async function testFontHighlighting(view) { // Simulating a mouse out event on the font name and expecting a selectionchange. const otherEl = viewDoc.querySelector("body"); - onEvents = waitForNSelectionEvents(1); + onEvents = waitForNSelectionEvents(gBrowser.selectedBrowser, 1); EventUtils.synthesizeMouse( otherEl, 2, @@ -96,24 +103,80 @@ async function testFontHighlighting(view) { } } -async function waitForNSelectionEvents(numberOfTimes) { - await SpecialPowers.spawn( - gBrowser.selectedBrowser, - [numberOfTimes], - async function (n) { - const win = content.wrappedJSObject; - - await new Promise(resolve => { - let received = 0; - win.document.addEventListener("selectionchange", function listen() { - received++; - - if (received === n) { - win.document.removeEventListener("selectionchange", listen); - resolve(); - } - }); - }); +async function testFontHighlightingInIframe(view, inspector) { + await selectNodeInFrames(["iframe", "div"], inspector); + + const viewDoc = view.document; + + // Wait for the view to have all the expected used fonts. + const fontEls = await waitFor(() => { + const els = getUsedFontsEls(viewDoc); + + if (!els.length) { + return false; } + + return [...els]; + }); + + is(fontEls.length, 1, "There's only one font used in the iframe document"); + ok( + // On Linux, Times New Roman does not exist. Liberation Serif is used instead. + ["Times New Roman", "Liberation Serif"].includes(fontEls[0].innerText), + "The expected font is displayed" ); + + const iframeBrowsingContext = await SpecialPowers.spawn( + gBrowser.selectedBrowser, + [], + () => content.document.querySelector("iframe").browsingContext + ); + + info(`Mousing over and out of the font in the list`); + + // Simulating a mouse over event on the font name and expecting a selectionchange. + const nameEl = fontEls[0]; + let onEvents = waitForNSelectionEvents(iframeBrowsingContext, 1); + EventUtils.synthesizeMouse( + nameEl, + 2, + 2, + { type: "mouseover" }, + viewDoc.defaultView + ); + await onEvents; + + ok(true, `A selectionchange events detected on mouseover`); + + // Simulating a mouse out event on the font name and expecting a selectionchange. + const otherEl = viewDoc.querySelector("body"); + onEvents = waitForNSelectionEvents(iframeBrowsingContext, 1); + EventUtils.synthesizeMouse( + otherEl, + 2, + 2, + { type: "mouseover" }, + viewDoc.defaultView + ); + await onEvents; + + ok(true, "1 selectionchange events detected on mouseout"); +} + +async function waitForNSelectionEvents(browser, numberOfTimes) { + await SpecialPowers.spawn(browser, [numberOfTimes], async function (n) { + const win = content.wrappedJSObject; + + await new Promise(resolve => { + let received = 0; + win.document.addEventListener("selectionchange", function listen() { + received++; + + if (received === n) { + win.document.removeEventListener("selectionchange", listen); + resolve(); + } + }); + }); + }); } diff --git a/devtools/client/inspector/fonts/test/doc_browser_fontinspector.html b/devtools/client/inspector/fonts/test/doc_browser_fontinspector.html index 27e24e2fd0513..b761bc43f73d9 100644 --- a/devtools/client/inspector/fonts/test/doc_browser_fontinspector.html +++ b/devtools/client/inspector/fonts/test/doc_browser_fontinspector.html @@ -57,7 +57,7 @@
DIV NESTED SPAN
- +
NORMAL DIV
BOLD DIV
800 DIV
diff --git a/devtools/client/netmonitor/test/browser.toml b/devtools/client/netmonitor/test/browser.toml index 957cbfec1c967..39537e79fb05c 100644 --- a/devtools/client/netmonitor/test/browser.toml +++ b/devtools/client/netmonitor/test/browser.toml @@ -512,6 +512,8 @@ fail-if = ["a11y_checks"] # Bug 1849028 clicked element may not be focusable and ["browser_net_throttle.js"] +["browser_net_throttling_cached.js"] + ["browser_net_throttling_profiles.js"] ["browser_net_timeline_ticks.js"] diff --git a/devtools/client/netmonitor/test/browser_net_throttling_cached.js b/devtools/client/netmonitor/test/browser_net_throttling_cached.js new file mode 100644 index 0000000000000..fb40a92c2e566 --- /dev/null +++ b/devtools/client/netmonitor/test/browser_net_throttling_cached.js @@ -0,0 +1,70 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { + profiles, + PROFILE_CONSTANTS, +} = require("resource://devtools/client/shared/components/throttling/profiles.js"); + +const offlineProfile = profiles.find( + profile => profile.id === PROFILE_CONSTANTS.OFFLINE +); + +const CACHED_URL = STATUS_CODES_SJS + "?sts=ok&cached&test_cached"; + +add_task(async function () { + const { monitor } = await initNetMonitor(SIMPLE_URL, { requestCount: 1 }); + const { connector } = monitor.panelWin; + const { updateNetworkThrottling } = connector; + + // Throttle the network before entering the content process + await pushPref("devtools.cache.disabled", false); + await updateNetworkThrottling(true, offlineProfile); + + // Clear the cache beforehand + Services.cache2.clear(); + + // The request is blocked since the profile is offline + await SpecialPowers.spawn( + gBrowser.selectedBrowser, + [CACHED_URL], + async url => { + try { + await content.fetch(url); + ok(false, "Should not load since profile is offline"); + } catch (err) { + is(err.name, "TypeError", "Should fail since profile is offline"); + } + } + ); + + // Disable throttling + await pushPref("devtools.cache.disabled", false); + await updateNetworkThrottling(false); + + // Fetch to prime the cache + await SpecialPowers.spawn( + gBrowser.selectedBrowser, + [CACHED_URL], + async url => { + await content.fetch(url); + } + ); + + // Set profile to offline again + await pushPref("devtools.cache.disabled", false); + await updateNetworkThrottling(true, offlineProfile); + + // Check that cached resource loaded + await SpecialPowers.spawn( + gBrowser.selectedBrowser, + [CACHED_URL], + async url => { + await content.fetch(url); + } + ); + + await teardown(monitor); +}); diff --git a/devtools/docs/user/index.rst b/devtools/docs/user/index.rst index 681c1c140a665..5893371b95f02 100644 --- a/devtools/docs/user/index.rst +++ b/devtools/docs/user/index.rst @@ -265,7 +265,7 @@ If you want to help improve the developer tools, these resources will get you st * - `Get Involved `_ - Our community website explains how to get involved. - * - `bugs.firefox-dev.tools `_ + * - `codetribute.mozilla.org `_ - A tool helping to find bugs to work on. * - :ref:`Read source docs ` diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp index dc65224fd9db8..cd4d788c654ae 100644 --- a/docshell/base/BrowsingContext.cpp +++ b/docshell/base/BrowsingContext.cpp @@ -109,6 +109,11 @@ struct ParamTraits : public mozilla::dom::WebIDLEnumSerializer< mozilla::dom::PrefersColorSchemeOverride> {}; +template <> +struct ParamTraits + : public mozilla::dom::WebIDLEnumSerializer< + mozilla::dom::ForcedColorsOverride> {}; + template <> struct ParamTraits : public ContiguousEnumSerializer< @@ -2851,6 +2856,15 @@ void BrowsingContext::DidSet(FieldIndex, PresContextAffectingFieldChanged(); } +void BrowsingContext::DidSet(FieldIndex, + dom::ForcedColorsOverride aOldValue) { + MOZ_ASSERT(IsTop()); + if (ForcedColorsOverride() == aOldValue) { + return; + } + PresContextAffectingFieldChanged(); +} + void BrowsingContext::DidSet(FieldIndex, nsString&& aOldValue) { MOZ_ASSERT(IsTop()); diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h index 3e869d779e6cd..e566841106c94 100644 --- a/docshell/base/BrowsingContext.h +++ b/docshell/base/BrowsingContext.h @@ -240,6 +240,8 @@ struct EmbedderColorSchemes { FIELD(MediumOverride, nsString) \ /* DevTools override for prefers-color-scheme */ \ FIELD(PrefersColorSchemeOverride, dom::PrefersColorSchemeOverride) \ + /* DevTools override for forced-colors */ \ + FIELD(ForcedColorsOverride, dom::ForcedColorsOverride) \ /* prefers-color-scheme override based on the color-scheme style of our \ * embedder element. */ \ FIELD(EmbedderColorSchemes, EmbedderColorSchemes) \ @@ -940,6 +942,10 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { return GetPrefersColorSchemeOverride(); } + dom::ForcedColorsOverride ForcedColorsOverride() const { + return GetForcedColorsOverride(); + } + bool IsInBFCache() const; bool AllowJavascript() const { return GetAllowJavascript(); } @@ -1099,6 +1105,11 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { return IsTop(); } + bool CanSet(FieldIndex, dom::ForcedColorsOverride, + ContentParent*) { + return IsTop(); + } + void DidSet(FieldIndex, bool aOldValue); void DidSet(FieldIndex, @@ -1107,6 +1118,9 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { void DidSet(FieldIndex, dom::PrefersColorSchemeOverride aOldValue); + void DidSet(FieldIndex, + dom::ForcedColorsOverride aOldValue); + template void WalkPresContexts(Callback&&); void PresContextAffectingFieldChanged(); diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 3a5787b6b8174..9eface9e97e6a 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -1329,7 +1329,20 @@ void nsDocShell::FirePageHideShowNonRecursive(bool aShow) { mEODForCurrentDocument = false; mIsRestoringDocument = true; mLoadGroup->AddRequest(channel, nullptr); - SetCurrentURI(doc->GetDocumentURI(), channel, + nsCOMPtr uri; + if (doc->FragmentDirective()) { + // If we have fragment directives, then we've mutated the document + // uri. Set the current URI from session history instead. + if (mozilla::SessionHistoryInParent()) { + uri = mActiveEntry ? mActiveEntry->GetURI() : nullptr; + } else if (mOSHE) { + uri = mOSHE->GetURI(); + } + } + if (!uri) { + uri = doc->GetDocumentURI(); + } + SetCurrentURI(uri, channel, /* aFireOnLocationChange */ true, /* aIsInitialAboutBlank */ false, /* aLocationFlags */ 0); diff --git a/docshell/test/browser/browser.toml b/docshell/test/browser/browser.toml index b604c16e5e54c..758397bf80d73 100644 --- a/docshell/test/browser/browser.toml +++ b/docshell/test/browser/browser.toml @@ -78,6 +78,8 @@ support-files = [ "file_backforward_restore_scroll.html^headers^", ] +["browser_backforward_text_fragment_restore_urlbar.js"] + ["browser_backforward_userinteraction.js"] support-files = ["dummy_iframe_page.html"] skip-if = ["os == 'linux' && bits == 64 && !debug"] # Bug 1607713 diff --git a/docshell/test/browser/browser_backforward_text_fragment_restore_urlbar.js b/docshell/test/browser/browser_backforward_text_fragment_restore_urlbar.js new file mode 100644 index 0000000000000..472a4c0b3bca5 --- /dev/null +++ b/docshell/test/browser/browser_backforward_text_fragment_restore_urlbar.js @@ -0,0 +1,33 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const ROOT = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://mochi.test:8888" +); + +const URL = `${ROOT}/dummy_page.html#:~:text=dummy`; + +function waitForPageShow(browser) { + return BrowserTestUtils.waitForContentEvent(browser, "pageshow", true); +} + +add_task(async function test_fragment_restore_urlbar() { + await BrowserTestUtils.withNewTab("https://example.com", async browser => { + let loaded = BrowserTestUtils.browserLoaded(browser, false); + BrowserTestUtils.startLoadingURIString(browser, URL); + await loaded; + + // Go back in history. + let change = waitForPageShow(browser); + browser.goBack(); + await change; + change = waitForPageShow(browser); + // Go forward in history. + browser.goForward(); + await change; + is(gURLBar.inputField.value, URL, "URL should have text directive"); + }); +}); diff --git a/dom/base/DirectionalityUtils.cpp b/dom/base/DirectionalityUtils.cpp index 65bc5987dd80c..3318268bff10b 100644 --- a/dom/base/DirectionalityUtils.cpp +++ b/dom/base/DirectionalityUtils.cpp @@ -214,10 +214,17 @@ static Directionality GetDirectionFromText(const Text* aTextNode, } /** - * Compute auto direction aRoot should have based on descendants - * https://html.spec.whatwg.org/#auto-directionality step 3 + * Compute auto direction for aRoot. If aCanExcludeRoot is true and aRoot + * establishes its own directionality, return early. + * https://html.spec.whatwg.org/#contained-text-auto-directionality */ -Directionality WalkDescendantsAndGetDirectionFromText(nsINode* aRoot) { +Directionality ContainedTextAutoDirectionality(nsINode* aRoot, + bool aCanExcludeRoot) { + MOZ_ASSERT_IF(aCanExcludeRoot, aRoot->IsElement()); + if (aCanExcludeRoot && EstablishesOwnDirection(aRoot->AsElement())) { + return Directionality::Unset; + } + nsIContent* child = aRoot->GetFirstChild(); while (child) { if (child->IsElement() && EstablishesOwnDirection(child->AsElement())) { @@ -225,7 +232,7 @@ Directionality WalkDescendantsAndGetDirectionFromText(nsINode* aRoot) { continue; } - // Step 3.2. If descendant is a slot element whose root is a shadow root, + // Step 1.2. If descendant is a slot element whose root is a shadow root, // then return the directionality of that shadow root's host. if (auto* slot = HTMLSlotElement::FromNode(child)) { if (const ShadowRoot* sr = slot->GetContainingShadow()) { @@ -235,8 +242,8 @@ Directionality WalkDescendantsAndGetDirectionFromText(nsINode* aRoot) { } } - // Step 3.3-5. If descendant is a Text node, return its - // text node directionality if it is not null + // Step 1.3-5. If descendant is a Text node, return its + // text node directionality. if (auto* text = Text::FromNode(child)) { Directionality textNodeDir = GetDirectionFromText(text); if (textNodeDir != Directionality::Unset) { @@ -276,22 +283,8 @@ Directionality ComputeAutoDirectionFromAssignedNodes( Element* assignedElement = Element::FromNode(assignedNode); MOZ_ASSERT(assignedElement); - // Step 2.1.3.2. Set childDirection to the auto directionality of child. - // Need to perform parts of the auto directionality algorithm here, as - // ComputeAutoDirectionality does not implement the whole algorithm. - if (Maybe maybe = - GetValueIfFormAssociatedElement(assignedElement)) { - const nsAutoString& value = maybe.value(); - childDirection = - GetDirectionFromText(value.BeginReading(), value.Length()); - if (childDirection == Directionality::Unset && !value.IsEmpty()) { - childDirection = Directionality::Ltr; - } - } - // Now recursively call into the remainder of auto directionality. - if (ParticipatesInAutoDirection(assignedElement)) { - childDirection = ComputeAutoDirectionality(assignedElement, aNotify); - } + // Step 2.1.3.2. + childDirection = ContainedTextAutoDirectionality(assignedElement, true); } // Step 2.1.4. If childDirection is not null, then return childDirection. @@ -329,7 +322,7 @@ static Directionality ComputeAutoDirectionality(Element* aElement, } // Step 3. find first text or slot that determines the direction - Directionality nodeDir = WalkDescendantsAndGetDirectionFromText(aElement); + Directionality nodeDir = ContainedTextAutoDirectionality(aElement, false); if (nodeDir != Directionality::Unset) { return nodeDir; } diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index d1b89b13258c9..ad128a0ac398b 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -8914,9 +8914,9 @@ void nsContentUtils::FirePageHideEventForFrameLoaderSwap( MOZ_DIAGNOSTIC_ASSERT(aItem); MOZ_DIAGNOSTIC_ASSERT(aChromeEventHandler); - RefPtr doc = aItem->GetDocument(); - NS_ASSERTION(doc, "What happened here?"); - doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup); + if (RefPtr doc = aItem->GetDocument()) { + doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup); + } int32_t childCount = 0; aItem->GetInProcessChildCount(&childCount); diff --git a/dom/base/test/useractivation/test_popup_blocker_mouse_event.html b/dom/base/test/useractivation/test_popup_blocker_mouse_event.html index fd94150f1ef7a..7a35d862a87a6 100644 --- a/dom/base/test/useractivation/test_popup_blocker_mouse_event.html +++ b/dom/base/test/useractivation/test_popup_blocker_mouse_event.html @@ -11,6 +11,8 @@
+ + diff --git a/dom/media/test/crashtests/crashtests.list b/dom/media/test/crashtests/crashtests.list index e7f700c5341b9..02213af604e80 100644 --- a/dom/media/test/crashtests/crashtests.list +++ b/dom/media/test/crashtests/crashtests.list @@ -183,3 +183,4 @@ load vp9cake_corrupt.webm load 1903669.html load 1905234.html load 1905231.webm +skip-if(Android) load audioworkletprocessor-recursion.html diff --git a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp index 594f890b80a35..72e09fd24d3aa 100644 --- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp +++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp @@ -216,7 +216,7 @@ nsresult MediaEngineRemoteVideoSource::Start() { LOG("%s", __PRETTY_FUNCTION__); AssertIsOnOwningThread(); - MOZ_ASSERT(mState == kAllocated || mState == kStopped); + MOZ_ASSERT(mState == kAllocated || mState == kStarted || mState == kStopped); MOZ_ASSERT(mTrack); { @@ -317,26 +317,13 @@ nsresult MediaEngineRemoteVideoSource::Reconfigure( return NS_OK; } - bool started = mState == kStarted; - if (started) { - nsresult rv = Stop(); - if (NS_WARN_IF(NS_FAILED(rv))) { - nsAutoCString name; - GetErrorName(rv, name); - LOG("Video source %p for video device %d Reconfigure() failed " - "unexpectedly in Stop(). rv=%s", - this, mCaptureId, name.Data()); - return NS_ERROR_UNEXPECTED; - } - } - { MutexAutoLock lock(mMutex); // Start() applies mCapability on the device. mCapability = newCapability; } - if (started) { + if (mState == kStarted) { nsresult rv = Start(); if (NS_WARN_IF(NS_FAILED(rv))) { nsAutoCString name; diff --git a/dom/media/webrtc/tests/mochitests/mochitest.toml b/dom/media/webrtc/tests/mochitests/mochitest.toml index cf6381c63c26f..7f7a68495f9ce 100644 --- a/dom/media/webrtc/tests/mochitests/mochitest.toml +++ b/dom/media/webrtc/tests/mochitests/mochitest.toml @@ -83,3 +83,6 @@ skip-if = ["os != 'linux'"] # the only platform with real devices ["test_setSinkId_preMutedElement.html"] ["test_unfocused_pref.html"] + +["test_ondevicechange_resistfingerprinting.html"] +run-sequentially = "sets prefs that may disrupt other tests" diff --git a/dom/media/webrtc/tests/mochitests/test_ondevicechange_resistfingerprinting.html b/dom/media/webrtc/tests/mochitests/test_ondevicechange_resistfingerprinting.html new file mode 100644 index 0000000000000..a9cec3b74a5e9 --- /dev/null +++ b/dom/media/webrtc/tests/mochitests/test_ondevicechange_resistfingerprinting.html @@ -0,0 +1,98 @@ + + + + + + + + + + diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp index 4e7d8846c2a32..3a3207cc4dd02 100644 --- a/dom/script/ScriptLoader.cpp +++ b/dom/script/ScriptLoader.cpp @@ -66,6 +66,7 @@ #include "nsIClassOfService.h" #include "nsICacheInfoChannel.h" #include "nsITimedChannel.h" +#include "nsITimer.h" #include "nsIScriptElement.h" #include "nsISupportsPriority.h" #include "nsIDocShell.h" @@ -268,6 +269,10 @@ ScriptLoader::~ScriptLoader() { } mModuleLoader = nullptr; + + if (mProcessPendingRequestsAsyncBypassParserBlocking) { + mProcessPendingRequestsAsyncBypassParserBlocking->Cancel(); + } } void ScriptLoader::SetGlobalObject(nsIGlobalObject* aGlobalObject) { @@ -2147,27 +2152,24 @@ nsresult ScriptLoader::ProcessOffThreadRequest(ScriptLoadRequest* aRequest) { aRequest->SetReady(); - if (aRequest == mParserBlockingRequest) { - if (!ReadyToExecuteParserBlockingScripts()) { - // If not ready to execute scripts, schedule an async call to - // ProcessPendingRequests to handle it. - ProcessPendingRequestsAsync(); - return NS_OK; - } - - // Same logic as in top of ProcessPendingRequests. - mParserBlockingRequest = nullptr; - UnblockParser(aRequest); - ProcessRequest(aRequest); - ContinueParserAsync(aRequest); - return NS_OK; - } - - // Async scripts and blocking scripts can be executed right away. - if ((aRequest->GetScriptLoadContext()->IsAsyncScript() || + // Move async scripts to mLoadedAsyncRequests and process them by calling + // ProcessPendingRequests. + if (aRequest != mParserBlockingRequest && + (aRequest->GetScriptLoadContext()->IsAsyncScript() || aRequest->GetScriptLoadContext()->IsBlockingScript()) && !aRequest->isInList()) { - return ProcessRequest(aRequest); + if (aRequest->GetScriptLoadContext()->IsAsyncScript()) { + // We're adding the request back to async list so that it can be executed + // later. + aRequest->GetScriptLoadContext()->mInAsyncList = false; + AddAsyncRequest(aRequest); + } else { + MOZ_ASSERT( + false, + "This should not run ever with the current default prefs. The " + "request should not run synchronously but added to some queue."); + return ProcessRequest(aRequest); + } } // Process other scripts in the proper order. @@ -3231,9 +3233,9 @@ bool ScriptLoader::HasPendingDynamicImports() const { void ScriptLoader::ProcessPendingRequestsAsync() { if (HasPendingRequests()) { - nsCOMPtr task = - NewRunnableMethod("dom::ScriptLoader::ProcessPendingRequests", this, - &ScriptLoader::ProcessPendingRequests); + nsCOMPtr task = NewRunnableMethod( + "dom::ScriptLoader::ProcessPendingRequests", this, + &ScriptLoader::ProcessPendingRequests, false); if (mDocument) { mDocument->Dispatch(task.forget()); } else { @@ -3242,15 +3244,48 @@ void ScriptLoader::ProcessPendingRequestsAsync() { } } -void ScriptLoader::ProcessPendingRequests() { +void ProcessPendingRequestsCallback(nsITimer* aTimer, void* aClosure) { + RefPtr sl = static_cast(aClosure); + sl->ProcessPendingRequests(true); +} + +void ScriptLoader::ProcessPendingRequestsAsyncBypassParserBlocking() { + MOZ_ASSERT(HasPendingRequests()); + + if (!mProcessPendingRequestsAsyncBypassParserBlocking) { + mProcessPendingRequestsAsyncBypassParserBlocking = NS_NewTimer(); + } + + // test_bug503481b.html tests the unlikely edge case where loading parser + // blocking script depends on async script to be executed. So don't block + // async scripts forever. + mProcessPendingRequestsAsyncBypassParserBlocking->InitWithNamedFuncCallback( + ProcessPendingRequestsCallback, this, 2500, nsITimer::TYPE_ONE_SHOT, + "ProcessPendingRequestsAsyncBypassParserBlocking"); +} + +void ScriptLoader::ProcessPendingRequests(bool aAllowBypassingParserBlocking) { RefPtr request; - if (mParserBlockingRequest && mParserBlockingRequest->IsFinished() && - ReadyToExecuteParserBlockingScripts()) { - request.swap(mParserBlockingRequest); - UnblockParser(request); - ProcessRequest(request); - ContinueParserAsync(request); + if (mProcessPendingRequestsAsyncBypassParserBlocking) { + mProcessPendingRequestsAsyncBypassParserBlocking->Cancel(); + } + + if (mParserBlockingRequest) { + if (mParserBlockingRequest->IsFinished() && + ReadyToExecuteParserBlockingScripts()) { + request.swap(mParserBlockingRequest); + UnblockParser(request); + ProcessRequest(request); + ContinueParserAsync(request); + ProcessPendingRequestsAsync(); + return; + } + + if (!aAllowBypassingParserBlocking) { + ProcessPendingRequestsAsyncBypassParserBlocking(); + return; + } } while (ReadyToExecuteParserBlockingScripts() && !mXSLTRequests.isEmpty() && diff --git a/dom/script/ScriptLoader.h b/dom/script/ScriptLoader.h index 9bfa4c75ccbac..f86e71ba8298c 100644 --- a/dom/script/ScriptLoader.h +++ b/dom/script/ScriptLoader.h @@ -38,6 +38,7 @@ class nsIContent; class nsIIncrementalStreamLoader; class nsIPrincipal; class nsIScriptGlobalObject; +class nsITimer; class nsIURI; namespace JS { @@ -361,7 +362,7 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface { /** * Processes any pending requests that are ready for processing. */ - void ProcessPendingRequests(); + void ProcessPendingRequests(bool aAllowBypassingParserBlocking = false); /** * Starts deferring deferred scripts and puts them in the mDeferredRequests @@ -572,6 +573,8 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface { */ virtual void ProcessPendingRequestsAsync(); + void ProcessPendingRequestsAsyncBypassParserBlocking(); + /** * If true, the loader is ready to execute parser-blocking scripts, and so are * all its ancestors. If the loader itself is ready but some ancestor is not, @@ -813,6 +816,8 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface { RefPtr mCache; + nsCOMPtr mProcessPendingRequestsAsyncBypassParserBlocking; + // Logging public: static LazyLogModule gCspPRLog; diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index 9181de826575f..c1a3f92e1a67b 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -27,6 +27,7 @@ #include "nsNetUtil.h" #include "nsReadableUtils.h" #include "nsSandboxFlags.h" +#include "nsScriptSecurityManager.h" #include "nsIXPConnect.h" #include "mozilla/BasePrincipal.h" @@ -1427,6 +1428,9 @@ nsresult nsContentSecurityManager::doContentSecurityCheck( rv = CheckAllowLoadByTriggeringRemoteType(aChannel); NS_ENSURE_SUCCESS(rv, rv); + rv = CheckForIncoherentResultPrincipal(aChannel); + NS_ENSURE_SUCCESS(rv, rv); + // if dealing with a redirected channel then we have already installed // streamlistener and redirect proxies and so we are done. if (loadInfo->GetInitialSecurityCheckDone()) { @@ -1709,3 +1713,66 @@ nsContentSecurityManager::PerformSecurityCheck( inAndOutListener.forget(outStreamListener); return NS_OK; } + +nsresult nsContentSecurityManager::CheckForIncoherentResultPrincipal( + nsIChannel* aChannel) { + nsCOMPtr loadInfo = aChannel->LoadInfo(); + ExtContentPolicyType contentPolicyType = + loadInfo->GetExternalContentPolicyType(); + if (contentPolicyType != ExtContentPolicyType::TYPE_DOCUMENT && + contentPolicyType != ExtContentPolicyType::TYPE_SUBDOCUMENT && + contentPolicyType != ExtContentPolicyType::TYPE_OBJECT) { + return NS_OK; + } + + nsCOMPtr resultOrPrecursor; + nsresult rv = nsScriptSecurityManager::GetScriptSecurityManager() + ->GetChannelResultPrincipalIfNotSandboxed( + aChannel, getter_AddRefs(resultOrPrecursor)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_STATE(resultOrPrecursor); + + if (nsCOMPtr precursor = + resultOrPrecursor->GetPrecursorPrincipal()) { + resultOrPrecursor = precursor; + } + + if (!resultOrPrecursor->GetIsContentPrincipal()) { + return NS_OK; + } + + nsAutoCString resultSiteOriginNoSuffix; + rv = resultOrPrecursor->GetSiteOriginNoSuffix(resultSiteOriginNoSuffix); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr resultSiteOriginURI; + NS_NewURI(getter_AddRefs(resultSiteOriginURI), resultSiteOriginNoSuffix); + NS_ENSURE_STATE(resultSiteOriginURI); + + nsCOMPtr channelURI; + aChannel->GetURI(getter_AddRefs(channelURI)); + NS_ENSURE_STATE(channelURI); + + nsCOMPtr channelUriPrincipal = + BasePrincipal::CreateContentPrincipal(channelURI, {}); + NS_ENSURE_STATE(channelUriPrincipal); + + nsAutoCString channelUriSiteOrigin; + rv = channelUriPrincipal->GetSiteOriginNoSuffix(channelUriSiteOrigin); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr channelSiteOriginURI; + NS_NewURI(getter_AddRefs(channelSiteOriginURI), channelUriSiteOrigin); + NS_ENSURE_STATE(channelSiteOriginURI); + + if (nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin( + resultSiteOriginURI, channelSiteOriginURI) || + (!net::SchemeIsHTTP(resultSiteOriginURI) && + !net::SchemeIsHTTPS(resultSiteOriginURI) && + (net::SchemeIsHTTP(channelSiteOriginURI) || + net::SchemeIsHTTPS(channelSiteOriginURI)))) { + return NS_ERROR_CONTENT_BLOCKED; + } + + return NS_OK; +} diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h index 17d42e9676f0b..45757a973c15b 100644 --- a/dom/security/nsContentSecurityManager.h +++ b/dom/security/nsContentSecurityManager.h @@ -87,6 +87,7 @@ class nsContentSecurityManager : public nsIContentSecurityManager, static nsresult CheckAllowLoadInPrivilegedAboutContext(nsIChannel* aChannel); static nsresult CheckChannelHasProtocolSecurityFlag(nsIChannel* aChannel); static bool CrossOriginEmbedderPolicyAllowsCredentials(nsIChannel* aChannel); + static nsresult CheckForIncoherentResultPrincipal(nsIChannel* aChannel); virtual ~nsContentSecurityManager() = default; }; diff --git a/dom/worklet/WorkletThread.cpp b/dom/worklet/WorkletThread.cpp index fd42c7a91182c..65e05fa47bc2e 100644 --- a/dom/worklet/WorkletThread.cpp +++ b/dom/worklet/WorkletThread.cpp @@ -423,6 +423,8 @@ void WorkletThread::Terminate() { DispatchRunnable(runnable.forget()); } +uint32_t WorkletThread::StackSize() { return kWorkletStackSize; } + void WorkletThread::TerminateInternal() { MOZ_ASSERT(!CycleCollectedJSContext::Get() || IsOnWorkletThread()); diff --git a/dom/worklet/WorkletThread.h b/dom/worklet/WorkletThread.h index e6d0e414dced1..10ec4b7174732 100644 --- a/dom/worklet/WorkletThread.h +++ b/dom/worklet/WorkletThread.h @@ -45,6 +45,10 @@ class WorkletThread final : public nsThread, public nsIObserver { void Terminate(); + // Recommended native stack size to use, greater than the stack size + // internally used by SpiderMonkey. + static uint32_t StackSize(); + private: explicit WorkletThread(WorkletImpl* aWorkletImpl); ~WorkletThread(); diff --git a/dom/xhr/tests/browser_xhr_onchange_leak.js b/dom/xhr/tests/browser_xhr_onchange_leak.js index 4d13e33ee4712..6c4dbcaf7f2e8 100644 --- a/dom/xhr/tests/browser_xhr_onchange_leak.js +++ b/dom/xhr/tests/browser_xhr_onchange_leak.js @@ -8,16 +8,11 @@ // turned off once it is closed. add_task(async function test() { - // We need to reuse the content process when we navigate so the entire process - // with the possible-leaking window doesn't get torn down. - await SpecialPowers.pushPrefEnv({ - set: [["dom.ipc.keepProcessesAlive.webIsolated.perOrigin", 1]], - }); - const url = "http://mochi.test:8888/browser/dom/xhr/tests/browser_xhr_onchange_leak.html"; let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url); let browser = gBrowser.selectedBrowser; + let origContentProcessId = browser.frameLoader.remoteTab.contentProcessId; let pageShowPromise = BrowserTestUtils.waitForContentEvent( browser, "pageshow", @@ -26,6 +21,13 @@ add_task(async function test() { BrowserTestUtils.startLoadingURIString(browser, "http://mochi.test:8888/"); await pageShowPromise; - ok(pageShowPromise, "need to check something"); + is( + browser.frameLoader.remoteTab.contentProcessId, + origContentProcessId, + "we must still be in the same process after we navigate " + + "so the entire process with the possibly-leaking window " + + "doesn't get torn down" + ); + BrowserTestUtils.removeTab(newTab); }); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index c659d3c5036d8..55e463ead6064 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -4046,14 +4046,6 @@ void AsyncPanZoomController::HandleFlingOverscroll( } } -void AsyncPanZoomController::HandleSmoothScrollOverscroll( - const ParentLayerPoint& aVelocity, SideBits aOverscrollSideBits) { - // We must call BuildOverscrollHandoffChain from this deferred callback - // function in order to avoid a deadlock when acquiring the tree lock. - HandleFlingOverscroll(aVelocity, aOverscrollSideBits, - BuildOverscrollHandoffChain(), nullptr); -} - ParentLayerPoint AsyncPanZoomController::ConvertDestinationToDelta( CSSPoint& aDestination) const { ParentLayerPoint startPoint, endPoint; diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 10f19453b6bac..675013aded81a 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -1627,9 +1627,6 @@ class AsyncPanZoomController { const RefPtr& aOverscrollHandoffChain, const RefPtr& aScrolledApzc); - void HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity, - SideBits aOverscrollSideBits); - // Start an overscroll animation with the given initial velocity. void StartOverscrollAnimation(const ParentLayerPoint& aVelocity, SideBits aOverscrollSideBits); diff --git a/gfx/layers/apz/src/SmoothMsdScrollAnimation.cpp b/gfx/layers/apz/src/SmoothMsdScrollAnimation.cpp index 8342dc157f413..41412d352a818 100644 --- a/gfx/layers/apz/src/SmoothMsdScrollAnimation.cpp +++ b/gfx/layers/apz/src/SmoothMsdScrollAnimation.cpp @@ -76,45 +76,11 @@ bool SmoothMsdScrollAnimation::DoSample(FrameMetrics& aFrameMetrics, mApzc.mX.AdjustDisplacement(displacement.x, adjustedOffset.x, overscroll.x); mApzc.mY.AdjustDisplacement(displacement.y, adjustedOffset.y, overscroll.y); mApzc.ScrollBy(adjustedOffset / zoom); - // The smooth scroll may have caused us to reach the end of our scroll - // range. This can happen if either the - // layout.css.scroll-behavior.damping-ratio preference is set to less than 1 - // (underdamped) or if a smooth scroll inherits velocity from a fling - // gesture. - if (!IsZero(overscroll / zoom)) { - // Hand off a fling with the remaining momentum to the next APZC in the - // overscroll handoff chain. - // We may have reached the end of the scroll range along one axis but - // not the other. In such a case we only want to hand off the relevant - // component of the fling. - if (mApzc.IsZero(overscroll.x)) { - velocity.x = 0; - } else if (mApzc.IsZero(overscroll.y)) { - velocity.y = 0; - } - - // To hand off the fling, we attempt to find a target APZC and start a new - // fling with the same velocity on that APZC. For simplicity, the actual - // overscroll of the current sample is discarded rather than being handed - // off. The compositor should sample animations sufficiently frequently - // that this is not noticeable. The target APZC is chosen by seeing if - // there is an APZC further in the handoff chain which is pannable; if - // there isn't, we take the new fling ourselves, entering an overscrolled - // state. - // Note: APZC is holding mRecursiveMutex, so directly calling - // HandleSmoothScrollOverscroll() (which acquires the tree lock) would - // violate the lock ordering. Instead we schedule - // HandleSmoothScrollOverscroll() to be called after mRecursiveMutex is - // released. - mDeferredTasks.AppendElement(NewRunnableMethod( - "layers::AsyncPanZoomController::HandleSmoothScrollOverscroll", &mApzc, - &AsyncPanZoomController::HandleSmoothScrollOverscroll, velocity, - apz::GetOverscrollSideBits(overscroll))); - return false; - } - - return true; + bool reachedEndOfScrollRange = !IsZero(overscroll / zoom); + // Do not hand off a smooth scroll animation to an ancestor APZC, + // nor allow it to cause overscroll. + return !reachedEndOfScrollRange; } void SmoothMsdScrollAnimation::SetDestination( diff --git a/gfx/layers/apz/test/gtest/APZCBasicTester.h b/gfx/layers/apz/test/gtest/APZCBasicTester.h index a79e51b72a635..d39aa99db96dd 100644 --- a/gfx/layers/apz/test/gtest/APZCBasicTester.h +++ b/gfx/layers/apz/test/gtest/APZCBasicTester.h @@ -83,22 +83,22 @@ class APZCBasicTester : public APZCTesterBase { /** * Sample animations once, 1 ms later than the last sample. */ - void SampleAnimationOnce() { + bool SampleAnimationOnce() { const TimeDuration increment = TimeDuration::FromMilliseconds(1); ParentLayerPoint pointOut; AsyncTransform viewTransformOut; mcc->AdvanceBy(increment); - apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); + return apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); } /** * Sample animations one frame, 17 ms later than the last sample. */ - void SampleAnimationOneFrame() { + bool SampleAnimationOneFrame() { const TimeDuration increment = TimeDuration::FromMilliseconds(17); ParentLayerPoint pointOut; AsyncTransform viewTransformOut; mcc->AdvanceBy(increment); - apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); + return apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); } AsyncPanZoomController::GestureBehavior mGestureBehavior; diff --git a/gfx/layers/apz/test/gtest/TestOverscroll.cpp b/gfx/layers/apz/test/gtest/TestOverscroll.cpp index da5bfec1706ce..247c7deec3edd 100644 --- a/gfx/layers/apz/test/gtest/TestOverscroll.cpp +++ b/gfx/layers/apz/test/gtest/TestOverscroll.cpp @@ -7,6 +7,7 @@ #include "APZCBasicTester.h" #include "APZCTreeManagerTester.h" #include "APZTestCommon.h" +#include "mozilla/ScrollPositionUpdate.h" #include "mozilla/layers/ScrollableLayerGuid.h" #include "mozilla/layers/WebRenderScrollDataWrapper.h" @@ -2159,7 +2160,7 @@ TEST_F(APZCOverscrollTester, FillOutGutterWhilePanning) { } // Similar to FillOutGutterWhilePanning but expanding the content while an -// overscroll animation is runnig. +// overscroll animation is running. TEST_F(APZCOverscrollTester, FillOutGutterWhileAnimating) { SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true); @@ -2213,3 +2214,30 @@ TEST_F(APZCOverscrollTester, FillOutGutterWhileAnimating) { EXPECT_FALSE(apzc->IsOverscrolled()); } #endif + +// Test that a programmatic scroll animation does NOT trigger overscroll. +TEST_F(APZCOverscrollTester, ProgrammaticScroll) { + SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true); + + // Send a SmoothMsd scroll update to a destination far outside of the + // scroll range (here, y=100000). This probably shouldn't happen in the + // first place, but even if it does for whatever reason, the smooth scroll + // should not trigger overscroll. + ScrollMetadata metadata = apzc->GetScrollMetadata(); + nsTArray scrollUpdates; + scrollUpdates.AppendElement(ScrollPositionUpdate::NewSmoothScroll( + ScrollMode::SmoothMsd, ScrollOrigin::Other, + CSSPoint::ToAppUnits(CSSPoint(0, 100000)), ScrollTriggeredByScript::Yes, + nullptr)); + metadata.SetScrollUpdates(scrollUpdates); + metadata.GetMetrics().SetScrollGeneration( + scrollUpdates.LastElement().GetGeneration()); + apzc->NotifyLayersUpdated(metadata, /*aIsFirstPaint=*/false, + /*aThisLayerTreeUpdated=*/true); + + apzc->AssertStateIsSmoothMsdScroll(); + + while (SampleAnimationOneFrame()) { + EXPECT_FALSE(apzc->IsOverscrolled()); + } +} diff --git a/gfx/src/nsITheme.h b/gfx/src/nsITheme.h index 48f563751fc7e..60074e0ecce62 100644 --- a/gfx/src/nsITheme.h +++ b/gfx/src/nsITheme.h @@ -171,22 +171,15 @@ class nsITheme : public nsISupports { enum Transparency { eOpaque = 0, eTransparent, eUnknownTransparency }; - /** - * Returns what we know about the transparency of the widget. - */ + /** Returns what we know about the transparency of the widget. */ virtual Transparency GetWidgetTransparency(nsIFrame* aFrame, StyleAppearance aWidgetType) { return eUnknownTransparency; } - /** - * Sets |*aShouldRepaint| to indicate whether an attribute or content state - * change should trigger a repaint. Call with null |aAttribute| (and - * null |aOldValue|) for content state changes. - */ - NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, StyleAppearance aWidgetType, - nsAtom* aAttribute, bool* aShouldRepaint, - const nsAttrValue* aOldValue) = 0; + /** Returns whether an attribute change should trigger a repaint. */ + virtual bool WidgetAttributeChangeRequiresRepaint(StyleAppearance, + nsAtom* aAttribute) = 0; NS_IMETHOD ThemeChanged() = 0; diff --git a/js/loader/ModuleLoaderBase.cpp b/js/loader/ModuleLoaderBase.cpp index 9cc9288e65ca5..c331a7af2f346 100644 --- a/js/loader/ModuleLoaderBase.cpp +++ b/js/loader/ModuleLoaderBase.cpp @@ -839,7 +839,15 @@ nsresult ModuleLoaderBase::ResolveRequestedModules( for (uint32_t i = 0; i < length; i++) { JS::Rooted str( cx, JS::GetRequestedModuleSpecifier(cx, moduleRecord, i)); - MOZ_ASSERT(str); + if (!str) { + JS::Rooted pendingException(cx); + if (!JS_GetPendingException(cx, &pendingException)) { + return NS_ERROR_FAILURE; + } + ms->SetParseError(pendingException); + JS_ClearPendingException(cx); + return NS_ERROR_FAILURE; + } nsAutoJSString specifier; if (!specifier.init(cx, str)) { diff --git a/js/src/builtin/Promise.cpp b/js/src/builtin/Promise.cpp index 9e0d9da9c8c2a..2c228cd8aea64 100644 --- a/js/src/builtin/Promise.cpp +++ b/js/src/builtin/Promise.cpp @@ -2220,7 +2220,18 @@ static bool PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp) { // Step 1.d.ii.2. Let handlerResult be ThrowCompletion(argument). resolutionMode = RejectMode; handlerResult = argument; - } else { + } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + else if (handlerNum == PromiseHandler::AsyncIteratorDisposeAwaitFulfilled) { + // Explicit Resource Management Proposal + // 27.1.3.1 %AsyncIteratorPrototype% [ @@asyncDispose ] ( ) + // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25asynciteratorprototype%25-%40%40asyncdispose + // + // Step 6.e.i. Return undefined. + handlerResult = JS::UndefinedValue(); + } +#endif + else { // Special case for Async-from-Sync Iterator. MOZ_ASSERT(handlerNum == @@ -5606,6 +5617,25 @@ template return PerformPromiseThenWithReaction(cx, unwrappedPromise, reaction); } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +// Explicit Resource Management Proposal +// 27.1.3.1 %AsyncIteratorPrototype% [ @@asyncDispose ] ( ) +// Steps 6.c-g +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25asynciteratorprototype%25-%40%40asyncdispose +// The steps mentioned above are almost identical to the steps 3-7 of +// https://tc39.es/ecma262/#await we have a utility function InternalAwait which +// covers these steps thus this following function wraps around the utility +// and implements the steps of %AsyncIteratorPrototype% [ @@asyncDispose ] ( ). +[[nodiscard]] bool js::InternalAsyncIteratorDisposeAwait( + JSContext* cx, JS::Handle value, + JS::Handle resultPromise) { + auto extra = [](JS::Handle reaction) {}; + return InternalAwait(cx, value, resultPromise, + PromiseHandler::AsyncIteratorDisposeAwaitFulfilled, + PromiseHandler::Thrower, extra); +} +#endif + [[nodiscard]] bool js::InternalAsyncGeneratorAwait( JSContext* cx, JS::Handle generator, JS::Handle value, PromiseHandler onFulfilled, diff --git a/js/src/builtin/Promise.h b/js/src/builtin/Promise.h index 4feb928b89b0f..0d0ec89f69d7e 100644 --- a/js/src/builtin/Promise.h +++ b/js/src/builtin/Promise.h @@ -73,6 +73,15 @@ enum class PromiseHandler : uint32_t { AsyncFromSyncIteratorValueUnwrapDone, AsyncFromSyncIteratorValueUnwrapNotDone, +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + // Explicit Resource Management Proposal + // 27.1.3.1 %AsyncIteratorPrototype% [ @@asyncDispose ] ( ) + // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25asynciteratorprototype%25-%40%40asyncdispose + // + // Step 6.e. unwrap Abstract Closure + AsyncIteratorDisposeAwaitFulfilled, +#endif + // One past the maximum allowed PromiseHandler value. Limit }; @@ -268,6 +277,12 @@ bool IsPromiseConstructor(const JSObject* obj); bool AbruptRejectPromise(JSContext* cx, JS::CallArgs& args, JS::Handle promiseObj, JS::Handle reject); + +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +[[nodiscard]] bool InternalAsyncIteratorDisposeAwait( + JSContext* cx, JS::Handle value, + JS::Handle resultPromise); +#endif } // namespace js #endif // builtin_Promise_h diff --git a/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-calls.js b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-calls.js new file mode 100644 index 0000000000000..f76ae4456514d --- /dev/null +++ b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-calls.js @@ -0,0 +1,133 @@ +// |jit-test| skip-if: !getBuildConfiguration("explicit-resource-management") + +load(libdir + "asserts.js"); + +{ + async function* gen() { + yield 1; + yield 2; + yield 3; + } + + const returned = []; + const iter = gen(); + iter.return = async function () { + returned.push('return'); + return { done: true }; + } + async function testCallsToIterReturnWithAwaitUsingSyntax() { + { + returned.push((await iter.next()).value); + await using it = iter; + } + } + testCallsToIterReturnWithAwaitUsingSyntax(); + drainJobQueue(); + assertArrayEq(returned, [1, 'return']); +} + +{ + async function* gen() { + yield 1; + yield 2; + yield 3; + } + + const returned = []; + const iter = gen(); + iter.return = async function () { + returned.push('return'); + return { done: true }; + } + async function testCallsToIterReturnWithMultipleReturnCalls() { + { + returned.push((await iter.next()).value); + await using it = iter; + it.return(); + } + } + testCallsToIterReturnWithMultipleReturnCalls(); + drainJobQueue(); + assertArrayEq(returned, [1, 'return', 'return']); +} + +{ + const returned = []; + function getCustomIter() { + async function* generator() {} + const AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(generator.prototype)); + return { + values: [1, 2, 3], + [Symbol.asyncIterator]() { + return this; + }, + async next() { + return { value: this.values.shift(), done: !this.values.length }; + }, + async return() { + returned.push('return'); + return { done: true }; + }, + __proto__: AsyncIteratorPrototype + } + } + async function testCallsToIterReturnWithCustomIterator() { + { + await using it = getCustomIter()[Symbol.asyncIterator](); + returned.push((await it.next()).value); + returned.push((await it.next()).value); + } + } + testCallsToIterReturnWithCustomIterator(); + drainJobQueue(); + + assertArrayEq(returned, [1, 2, 'return']); +} + +{ + async function* gen() {} + + const iter = gen(); + iter.return = null; + async function testCallsToIterReturnWithNullReturnFn() { + { + await using it = iter; + } + } + + // Test that a null return function for the iterator doesn't cause a throw. + testCallsToIterReturnWithNullReturnFn(); + drainJobQueue(); +} + +{ + async function* gen() {} + + const iter = gen(); + iter.return = undefined; + async function testCallsToIterReturnWithUndefinedReturnFn() { + { + await using it = iter; + } + } + + // Test that a undefined return function for the iteratordoesn't cause a throw. + testCallsToIterReturnWithUndefinedReturnFn(); + drainJobQueue(); +} + +{ + async function* gen() {} + + const iter = gen(); + iter.return = 1; + async function testIterReturnNotCallable() { + { + await using it = iter; + } + } + + // Test that a non-callable, non-undefined, non-null return function for the + // iterator return causes a TypeError. + assertThrowsInstanceOfAsync(testIterReturnNotCallable, TypeError); +} diff --git a/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-exception-handling.js b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-exception-handling.js new file mode 100644 index 0000000000000..33b9c903135a4 --- /dev/null +++ b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-exception-handling.js @@ -0,0 +1,48 @@ +// |jit-test| skip-if: !getBuildConfiguration("explicit-resource-management") + +load(libdir + "asserts.js"); + +class CustomError extends Error {} + +{ + async function* gen() { + yield 1; + yield 2; + yield 3; + } + + const returned = []; + const iter = gen(); + iter.return = function () { + returned.push('return'); + throw new CustomError(); + } + + assertThrowsInstanceOfAsync(() => { return iter[Symbol.asyncDispose]() }, CustomError); + assertArrayEq(returned, ['return']); +} + +{ + async function* gen() { + yield 1; + yield 2; + yield 3; + } + + const returned = []; + const iter = gen(); + iter.return = function () { + returned.push('return'); + throw new CustomError(); + } + + async function testThrowInIteratorReturnRejectsWithAwaitUsingSyntax() { + { + returned.push((await iter.next()).value); + await using it = iter; + } + } + + assertThrowsInstanceOfAsync(testThrowInIteratorReturnRejectsWithAwaitUsingSyntax, CustomError); + assertArrayEq(returned, [1, 'return']); +} diff --git a/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-properties.js b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-properties.js new file mode 100644 index 0000000000000..d6cd58ce840a2 --- /dev/null +++ b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-properties.js @@ -0,0 +1,27 @@ +// |jit-test| skip-if: !getBuildConfiguration("explicit-resource-management") + +load(libdir + "asserts.js"); + +async function* generator() {} +const AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(generator.prototype)); + +assertEq(typeof AsyncIteratorPrototype[Symbol.asyncDispose], 'function'); +assertDeepEq(Object.getOwnPropertyDescriptor(AsyncIteratorPrototype[Symbol.asyncDispose], 'length'), { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); +assertDeepEq(Object.getOwnPropertyDescriptor(AsyncIteratorPrototype[Symbol.asyncDispose], 'name'), { + value: '[Symbol.asyncDispose]', + writable: false, + enumerable: false, + configurable: true, +}); +assertDeepEq(Object.getOwnPropertyDescriptor(AsyncIteratorPrototype, Symbol.asyncDispose), { + value: AsyncIteratorPrototype[Symbol.asyncDispose], + writable: true, + enumerable: false, + configurable: true, +}); +assertEq(AsyncIteratorPrototype[Symbol.asyncDispose]() instanceof Promise, true); diff --git a/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-then-call-counts.js b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-then-call-counts.js new file mode 100644 index 0000000000000..b0a1371f06657 --- /dev/null +++ b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-return-then-call-counts.js @@ -0,0 +1,25 @@ +// |jit-test| skip-if: !getBuildConfiguration("explicit-resource-management") + +let thenGetterCalls = 0; +const thenVal = Promise.prototype.then; +Object.defineProperty(Promise.prototype, "then", { + get() { + thenGetterCalls++; + return thenVal; + } +}); + +async function* generator() {} +const AsyncIteratorPrototype = Object.getPrototypeOf( + Object.getPrototypeOf(generator.prototype) +); +const asyncDispose = AsyncIteratorPrototype[Symbol.asyncDispose]; + +asyncDispose + .call({ + return() { + return 10; + }, + }); +drainJobQueue(); +assertEq(thenGetterCalls, 0); diff --git a/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-returns-passes-arguments.js b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-returns-passes-arguments.js new file mode 100644 index 0000000000000..36116a9d32078 --- /dev/null +++ b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-returns-passes-arguments.js @@ -0,0 +1,28 @@ +// |jit-test| skip-if: !getBuildConfiguration("explicit-resource-management") + +async function* generator() {} +const AsyncIteratorPrototype = Object.getPrototypeOf( + Object.getPrototypeOf(generator.prototype) +); +const asyncDispose = AsyncIteratorPrototype[Symbol.asyncDispose]; + +let len = null; +let arg0 = null; +asyncDispose.call({ + return() { + len = arguments.length; + arg0 = arguments[0]; + return; + }, +}); +drainJobQueue(); + +// The spec mentions that calls to the return method should pass one\ +// undefined argument. +// +// Explicit Resource Management Proposal +// 27.1.3.1 %AsyncIteratorPrototype% [ @@asyncDispose ] ( ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25asynciteratorprototype%25-%40%40asyncdispose +// Step 6.a. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »). +assertEq(len, 1); +assertEq(arg0, undefined); diff --git a/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-returns-undefined.js b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-returns-undefined.js new file mode 100644 index 0000000000000..b67c554414139 --- /dev/null +++ b/js/src/jit-test/tests/explicit-resource-management/alias-to-async-iterator-returns-undefined.js @@ -0,0 +1,30 @@ +// |jit-test| skip-if: !getBuildConfiguration("explicit-resource-management") + +async function* generator() {} +const AsyncIteratorPrototype = Object.getPrototypeOf( + Object.getPrototypeOf(generator.prototype) +); +const asyncDispose = AsyncIteratorPrototype[Symbol.asyncDispose]; + +let value = null; +asyncDispose + .call({ + return() { + return 10; + }, + }) + .then(v => { + value = v; + }); + +drainJobQueue(); + +// The spec mentions that closure wrapper called on reaction to the Promise +// returned by the return method should return undefined. +// +// Explicit Resource Management Proposal +// 27.1.3.1 %AsyncIteratorPrototype% [ @@asyncDispose ] ( ) +// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25asynciteratorprototype%25-%40%40asyncdispose +// Step 6.e. Let unwrap be a new Abstract Closure that performs the following steps when called: +// Step 6.e.i. Return undefined. +assertEq(value, undefined); diff --git a/js/src/vm/AsyncIteration.cpp b/js/src/vm/AsyncIteration.cpp index 79dd51815735b..4b5a79edb57c5 100644 --- a/js/src/vm/AsyncIteration.cpp +++ b/js/src/vm/AsyncIteration.cpp @@ -986,6 +986,71 @@ bool js::AsyncGeneratorThrow(JSContext* cx, unsigned argc, Value* vp) { return AsyncGeneratorReturned(cx, generator, thisOrRval); } +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT +/** + * Explicit Resource Management Proposal + * 27.1.3.1 %AsyncIteratorPrototype% [ @@asyncDispose ] ( ) + * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25asynciteratorprototype%25-%40%40asyncdispose + */ +static bool AsyncIteratorDispose(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + + // Step 1. Let O be the this value. + JS::Rooted O(cx, args.thisv()); + + // Step 2. Let promiseCapability be ! NewPromiseCapability(%Promise%). + JS::Rooted promise(cx, + PromiseObject::createSkippingExecutor(cx)); + if (!promise) { + return false; + } + + // Step 3. Let return be Completion(GetMethod(O, "return")). + JS::Rooted returnMethod(cx); + if (!GetProperty(cx, O, cx->names().return_, &returnMethod)) { + // Step 4. IfAbruptRejectPromise(return, promiseCapability). + return AbruptRejectPromise(cx, args, promise, nullptr); + } + + // Step 5. If return is undefined, then + // As per the spec GetMethod returns undefined if the property is either null + // or undefined thus here we check for both. + if (returnMethod.isNullOrUndefined()) { + // Step 5.a. Perform ! Call(promiseCapability.[[Resolve]], undefined, « + // undefined »). + if (!PromiseObject::resolve(cx, promise, JS::UndefinedHandleValue)) { + return false; + } + args.rval().setObject(*promise); + return true; + } + + // GetMethod also throws a TypeError exception if the function is not callable + // thus we perform that check here. + if (!IsCallable(returnMethod)) { + ReportIsNotFunction(cx, returnMethod); + return AbruptRejectPromise(cx, args, promise, nullptr); + } + + // Step 6. Else, + // Step 6.a. Let result be Completion(Call(return, O, « undefined »)). + JS::Rooted rval(cx); + if (!Call(cx, returnMethod, O, JS::UndefinedHandleValue, &rval)) { + // Step 6.b. IfAbruptRejectPromise(result, promiseCapability). + return AbruptRejectPromise(cx, args, promise, nullptr); + } + + // Step 6.c-g. + if (!InternalAsyncIteratorDisposeAwait(cx, rval, promise)) { + return AbruptRejectPromise(cx, args, promise, nullptr); + } + + // Step 7. Return promiseCapability.[[Promise]]. + args.rval().setObject(*promise); + return true; +} +#endif + static const JSFunctionSpec async_generator_methods[] = { JS_FN("next", js::AsyncGeneratorNext, 1, 0), JS_FN("throw", js::AsyncGeneratorThrow, 1, 0), @@ -1254,6 +1319,9 @@ bool GlobalObject::initAsyncFromSyncIteratorProto( static const JSFunctionSpec async_iterator_proto_methods[] = { JS_SELF_HOSTED_SYM_FN(asyncIterator, "AsyncIteratorIdentity", 0, 0), +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + JS_SYM_FN(asyncDispose, AsyncIteratorDispose, 0, 0), +#endif JS_FS_END, }; @@ -1271,6 +1339,9 @@ static const JSFunctionSpec async_iterator_proto_methods_with_helpers[] = { JS_SELF_HOSTED_FN("every", "AsyncIteratorEvery", 1, 0), JS_SELF_HOSTED_FN("find", "AsyncIteratorFind", 1, 0), JS_SELF_HOSTED_SYM_FN(asyncIterator, "AsyncIteratorIdentity", 0, 0), +#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT + JS_SYM_FN(asyncDispose, AsyncIteratorDispose, 0, 0), +#endif JS_FS_END, }; diff --git a/js/src/vm/Modules.cpp b/js/src/vm/Modules.cpp index c1b60694d290a..16fbc9c00802b 100644 --- a/js/src/vm/Modules.cpp +++ b/js/src/vm/Modules.cpp @@ -271,8 +271,26 @@ JS_PUBLIC_API JSString* JS::GetRequestedModuleSpecifier( CHECK_THREAD(cx); cx->check(moduleRecord); - auto& module = moduleRecord->as(); - return module.requestedModules()[index].moduleRequest()->specifier(); + auto* moduleRequest = moduleRecord->as() + .requestedModules()[index] + .moduleRequest(); + + // This implements step 7.1.1 in HostLoadImportedModule. + // https://html.spec.whatwg.org/multipage/webappapis.html#hostloadimportedmodule + // + // If moduleRequest.[[Attributes]] contains a Record entry such that + // entry.[[Key]] is not "type", + if (moduleRequest->hasFirstUnsupportedAttributeKey()) { + UniqueChars printableKey = AtomToPrintableString( + cx, moduleRequest->getFirstUnsupportedAttributeKey()); + JS_ReportErrorNumberASCII( + cx, GetErrorMessage, nullptr, + JSMSG_IMPORT_ATTRIBUTES_STATIC_IMPORT_UNSUPPORTED_ATTRIBUTE, + printableKey ? printableKey.get() : ""); + return nullptr; + } + + return moduleRequest->specifier(); } JS_PUBLIC_API void JS::GetRequestedModuleSourcePos( diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index 78d84d9272e59..b4700300f02a6 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -596,9 +596,16 @@ static bool StateChangeMayAffectFrame(const Element& aElement, static bool RepaintForAppearance(nsIFrame& aFrame, const Element& aElement, ElementState aStateMask) { - if (aStateMask.HasAtLeastOneOfStates(ElementState::HOVER | - ElementState::ACTIVE) && - aElement.IsAnyOfXULElements(nsGkAtoms::checkbox, nsGkAtoms::radio)) { + constexpr auto kThemingStates = + ElementState::HOVER | ElementState::ACTIVE | ElementState::FOCUSRING | + ElementState::DISABLED | ElementState::CHECKED | + ElementState::INDETERMINATE | ElementState::READONLY | + ElementState::FOCUS; + if (!aStateMask.HasAtLeastOneOfStates(kThemingStates)) { + return false; + } + + if (aElement.IsAnyOfXULElements(nsGkAtoms::checkbox, nsGkAtoms::radio)) { // The checkbox inside these elements inherit hover state and so on, see // nsNativeTheme::GetContentState. // FIXME(emilio): Would be nice to not have these hard-coded. @@ -609,13 +616,7 @@ static bool RepaintForAppearance(nsIFrame& aFrame, const Element& aElement, return false; } nsPresContext* pc = aFrame.PresContext(); - nsITheme* theme = pc->Theme(); - if (!theme->ThemeSupportsWidget(pc, &aFrame, appearance)) { - return false; - } - bool repaint = false; - theme->WidgetStateChanged(&aFrame, appearance, nullptr, &repaint, nullptr); - return repaint; + return pc->Theme()->ThemeSupportsWidget(pc, &aFrame, appearance); } /** @@ -3654,13 +3655,9 @@ void RestyleManager::AttributeChanged(Element* aElement, int32_t aNameSpaceID, primaryFrame->StyleDisplay()->EffectiveAppearance(); if (appearance != StyleAppearance::None) { nsITheme* theme = PresContext()->Theme(); - if (theme->ThemeSupportsWidget(PresContext(), primaryFrame, appearance)) { - bool repaint = false; - theme->WidgetStateChanged(primaryFrame, appearance, aAttribute, - &repaint, aOldValue); - if (repaint) { - changeHint |= nsChangeHint_RepaintFrame; - } + if (theme->ThemeSupportsWidget(PresContext(), primaryFrame, appearance) && + theme->WidgetAttributeChangeRequiresRepaint(appearance, aAttribute)) { + changeHint |= nsChangeHint_RepaintFrame; } } diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 98e9dbb81d22a..b2ba0fa91c35c 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -297,7 +297,8 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType) #ifdef DEBUG mInitialized(false), #endif - mOverriddenOrEmbedderColorScheme(dom::PrefersColorSchemeOverride::None) { + mOverriddenOrEmbedderColorScheme(dom::PrefersColorSchemeOverride::None), + mForcedColors(StyleForcedColors::None) { #ifdef DEBUG PodZero(&mLayoutPhaseCount); #endif @@ -328,6 +329,7 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType) } UpdateFontVisibility(); + UpdateForcedColors(/* aNotify = */ false); } static const char* gExactCallbackPrefs[] = { @@ -617,6 +619,7 @@ void nsPresContext::PreferenceChanged(const char* aPrefName) { if (PreferenceSheet::AffectedByPref(prefName)) { restyleHint |= RestyleHint::RestyleSubtree(); PreferenceSheet::Refresh(); + UpdateForcedColors(); } // Same, this just frees a bunch of memory. @@ -736,6 +739,51 @@ nsresult nsPresContext::Init(nsDeviceContext* aDeviceContext) { return NS_OK; } +void nsPresContext::UpdateForcedColors(bool aNotify) { + auto old = mForcedColors; + mForcedColors = [&] { + if (Document()->IsBeingUsedAsImage()) { + return StyleForcedColors::None; + } + + // Handle BrowsingContext override. + if (auto* bc = mDocument->GetBrowsingContext(); + bc && + bc->Top()->ForcedColorsOverride() == ForcedColorsOverride::Active) { + return StyleForcedColors::Active; + } + + const auto& prefs = PrefSheetPrefs(); + if (!prefs.mUseDocumentColors) { + return StyleForcedColors::Active; + } + // On Windows, having a high contrast theme also means that the OS is + // requesting the colors to be forced. This is mostly convenience for the + // front-end, which wants to reuse the forced-colors styles for chrome in + // this case as well, and it's a lot more convenient to use + // `(forced-colors)` than `(forced-colors) or ((-moz-platform: windows) and + // (prefers-contrast))`. + // + // TODO(emilio): We might want to factor in here the lwtheme attribute in + // the root element and so on. +#ifdef XP_WINDOWS + if (prefs.mUseAccessibilityTheme && prefs.mIsChrome) { + return StyleForcedColors::Requested; + } +#endif + return StyleForcedColors::None; + }(); + if (aNotify && mForcedColors != old) { + MediaFeatureValuesChanged( + MediaFeatureChange::ForPreferredColorSchemeOrForcedColorsChange(), + MediaFeatureChangePropagation::JustThisDocument); + } +} + +bool nsPresContext::ForcingColors() const { + return mForcedColors == StyleForcedColors::Active; +} + bool nsPresContext::UpdateFontVisibility() { FontVisibility oldValue = mFontVisibility; @@ -924,7 +972,7 @@ void nsPresContext::SetColorSchemeOverride( if (mDocument->PreferredColorScheme() != oldScheme) { MediaFeatureValuesChanged( - MediaFeatureChange::ForPreferredColorSchemeChange(), + MediaFeatureChange::ForPreferredColorSchemeOrForcedColorsChange(), MediaFeatureChangePropagation::JustThisDocument); } } @@ -963,6 +1011,8 @@ void nsPresContext::RecomputeBrowsingContextDependentData() { return browsingContext->GetEmbedderColorSchemes().mPreferred; }()); + UpdateForcedColors(); + SetInRDMPane(top->GetInRDMPane()); if (doc == mDocument) { @@ -1845,6 +1895,7 @@ void nsPresContext::ThemeChangedInternal() { LookAndFeel::HandleGlobalThemeChange(); // Full zoom might have changed as a result of the text scale factor. + // Forced colors might also have changed. RecomputeBrowsingContextDependentData(); // Changes to system metrics and other look and feel values can change media @@ -1949,7 +2000,7 @@ void nsPresContext::EmulateMedium(nsAtom* aMediaType) { MediaFeatureChange change(MediaFeatureChangeReason::MediumChange); if (oldScheme != mDocument->PreferredColorScheme()) { - change |= MediaFeatureChange::ForPreferredColorSchemeChange(); + change |= MediaFeatureChange::ForPreferredColorSchemeOrForcedColorsChange(); } MediaFeatureValuesChanged(change, MediaFeatureChangePropagation::JustThisDocument); diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 0d1da270f8363..f82f9aad87897 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -85,6 +85,7 @@ class TimelineManager; struct MediaFeatureChange; enum class MediaFeatureChangePropagation : uint8_t; enum class ColorScheme : uint8_t; +enum class StyleForcedColors : uint8_t; namespace layers { class ContainerLayer; class LayerManager; @@ -377,10 +378,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr { return mozilla::PreferenceSheet::PrefsFor(*mDocument); } - bool ForcingColors() const { - return mozilla::PreferenceSheet::MayForceColors() && - !PrefSheetPrefs().mUseDocumentColors; - } + bool ForcingColors() const; mozilla::ColorScheme DefaultBackgroundColorScheme() const; nscolor DefaultBackgroundColor() const; @@ -560,6 +558,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr { void SetOverrideDPPX(float); void SetInRDMPane(bool aInRDMPane); void UpdateTopInnerSizeForRFP(); + void UpdateForcedColors(bool aNotify = true); public: float GetFullZoom() { return mFullZoom; } @@ -1402,6 +1401,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr { // that breaks bindgen in win32. FontVisibility mFontVisibility = FontVisibility::Unknown; mozilla::dom::PrefersColorSchemeOverride mOverriddenOrEmbedderColorScheme; + mozilla::StyleForcedColors mForcedColors; protected: virtual ~nsPresContext(); diff --git a/layout/base/tests/mochitest.toml b/layout/base/tests/mochitest.toml index 3a1dc7c271db0..f6b5788808252 100644 --- a/layout/base/tests/mochitest.toml +++ b/layout/base/tests/mochitest.toml @@ -249,6 +249,8 @@ support-files = ["file_dynamic_toolbar_max_height.html"] ["test_emulate_color_scheme.html"] +["test_emulate_forced_colors.html"] + ["test_event_target_radius.html"] support-files = ["helper_bug1733509.html"] skip-if = ["xorigin"] # JavaScript error: resource://specialpowers/SpecialPowersChild.sys.mjs, line 73: SecurityError: Permission denied to access property "windowUtils" on cross-origin object diff --git a/layout/base/tests/test_emulate_forced_colors.html b/layout/base/tests/test_emulate_forced_colors.html new file mode 100644 index 0000000000000..cb4d44a7b730a --- /dev/null +++ b/layout/base/tests/test_emulate_forced_colors.html @@ -0,0 +1,47 @@ + + +Emulation of forced-colors (bug 1916589) + + + +
+ diff --git a/layout/generic/ScrollContainerFrame.cpp b/layout/generic/ScrollContainerFrame.cpp index bc5ad7dd06bce..a3f21ab670644 100644 --- a/layout/generic/ScrollContainerFrame.cpp +++ b/layout/generic/ScrollContainerFrame.cpp @@ -3409,7 +3409,8 @@ static void AppendToTop(nsDisplayListBuilder* aBuilder, struct HoveredStateComparator { static bool Hovered(const nsIFrame* aFrame) { return aFrame->GetContent()->IsElement() && - aFrame->GetContent()->AsElement()->HasAttr(nsGkAtoms::hover); + aFrame->GetContent()->AsElement()->State().HasState( + ElementState::HOVER); } bool Equals(nsIFrame* A, nsIFrame* B) const { diff --git a/layout/generic/ScrollbarActivity.cpp b/layout/generic/ScrollbarActivity.cpp index bc55b1d6a2f58..abebd90ea7829 100644 --- a/layout/generic/ScrollbarActivity.cpp +++ b/layout/generic/ScrollbarActivity.cpp @@ -42,14 +42,17 @@ void ScrollbarActivity::ActivityOccurred() { ActivityStopped(); } -static void SetBooleanAttribute(Element* aElement, nsAtom* aAttribute, - bool aValue) { - if (aElement) { - if (aValue) { - aElement->SetAttr(kNameSpaceID_None, aAttribute, u"true"_ns, true); - } else { - aElement->UnsetAttr(kNameSpaceID_None, aAttribute, true); +static void SetScrollbarActive(Element* aScrollbar, bool aIsActive) { + if (!aScrollbar) { + return; + } + if (aIsActive) { + if (nsScrollbarFrame* sf = do_QueryFrame(aScrollbar->GetPrimaryFrame())) { + sf->WillBecomeActive(); } + aScrollbar->SetAttr(kNameSpaceID_None, nsGkAtoms::active, u""_ns, true); + } else { + aScrollbar->UnsetAttr(kNameSpaceID_None, nsGkAtoms::active, true); } } @@ -60,10 +63,13 @@ void ScrollbarActivity::ActivityStarted() { return; } CancelFadeTimer(); + if (mScrollbarEffectivelyVisible) { + return; + } StartListeningForScrollbarEvents(); StartListeningForScrollAreaEvents(); - SetBooleanAttribute(GetHorizontalScrollbar(), nsGkAtoms::active, true); - SetBooleanAttribute(GetVerticalScrollbar(), nsGkAtoms::active, true); + SetScrollbarActive(GetHorizontalScrollbar(), true); + SetScrollbarActive(GetVerticalScrollbar(), true); mScrollbarEffectivelyVisible = true; } @@ -78,8 +84,6 @@ void ScrollbarActivity::ActivityStopped() { if (IsActive()) { return; } - // Clear sticky scrollbar hover status. - HoveredScrollbar(nullptr); StartFadeTimer(); } @@ -145,11 +149,8 @@ void ScrollbarActivity::HandleEventForScrollbar(const nsAString& aType, bool newHoveredState = aType.EqualsLiteral("mouseover"); if (newHoveredState && !*aStoredHoverState) { ActivityStarted(); - HoveredScrollbar(aScrollbar); } else if (*aStoredHoverState && !newHoveredState) { ActivityStopped(); - // Don't call HoveredScrollbar(nullptr) here because we want the hover - // attribute to stick until the scrollbars are hidden. } *aStoredHoverState = newHoveredState; } @@ -245,32 +246,8 @@ void ScrollbarActivity::StartFadeTimer() { void ScrollbarActivity::BeginFade() { MOZ_ASSERT(!IsActive()); mScrollbarEffectivelyVisible = false; - SetBooleanAttribute(GetHorizontalScrollbar(), nsGkAtoms::active, false); - SetBooleanAttribute(GetVerticalScrollbar(), nsGkAtoms::active, false); -} - -static void MaybeInvalidateScrollbarForHover( - Element* aScrollbarToInvalidate, Element* aScrollbarAboutToGetHover) { - if (aScrollbarToInvalidate) { - bool hasHover = aScrollbarToInvalidate->HasAttr(nsGkAtoms::hover); - bool willHaveHover = aScrollbarAboutToGetHover == aScrollbarToInvalidate; - if (hasHover != willHaveHover) { - if (nsIFrame* f = aScrollbarToInvalidate->GetPrimaryFrame()) { - f->SchedulePaint(); - } - } - } -} - -void ScrollbarActivity::HoveredScrollbar(Element* aScrollbar) { - Element* vertScrollbar = GetVerticalScrollbar(); - Element* horzScrollbar = GetHorizontalScrollbar(); - MaybeInvalidateScrollbarForHover(vertScrollbar, aScrollbar); - MaybeInvalidateScrollbarForHover(horzScrollbar, aScrollbar); - - SetBooleanAttribute(horzScrollbar, nsGkAtoms::hover, false); - SetBooleanAttribute(vertScrollbar, nsGkAtoms::hover, false); - SetBooleanAttribute(aScrollbar, nsGkAtoms::hover, true); + SetScrollbarActive(GetHorizontalScrollbar(), false); + SetScrollbarActive(GetVerticalScrollbar(), false); } Element* ScrollbarActivity::GetScrollbarContent(bool aVertical) { diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 9cf4899f13e5b..b716b96215e5e 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -2478,8 +2478,16 @@ bool FlexItem::CanMainSizeInfluenceCrossSize() const { if (IsInlineAxisCrossAxis()) { // If we get here, this function is really asking: "can changes to this - // item's block size have an influence on its inline size"? For blocks and - // tables, the answer is "no". + // item's block size have an influence on its inline size"? + + // If a flex item's intrinsic inline size or its descendants' inline size + // contributions depend on the item's block size, the answer is "yes". + if (mFrame->HasAnyStateBits( + NS_FRAME_DESCENDANT_INTRINSIC_ISIZE_DEPENDS_ON_BSIZE)) { + return true; + } + // For blocks and tables, the answer is "no" (aside from the above special + // case). if (mFrame->IsBlockFrame() || mFrame->IsTableWrapperFrame()) { // XXXdholbert (Maybe use an IsFrameOfType query or something more // general to test this across all frame types? For now, I'm just @@ -5296,6 +5304,8 @@ nsFlexContainerFrame::FlexLayoutResult nsFlexContainerFrame::DoFlexLayout( sizeOverrides.mStyleISize.emplace(item.StyleMainSize()); } else { sizeOverrides.mStyleBSize.emplace(item.StyleMainSize()); + nsLayoutUtils::MarkIntrinsicISizesDirtyIfDependentOnBSize( + item.Frame()); } FLEX_ITEM_LOG(item.Frame(), "Sizing item in cross axis"); FLEX_LOGV("Main size override: %d", item.MainSize()); diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp index 2bbcbc7e349bd..867c79edfc1d6 100644 --- a/layout/generic/nsIFrame.cpp +++ b/layout/generic/nsIFrame.cpp @@ -6700,11 +6700,12 @@ nscoord nsIFrame::ComputeBSizeValueAsPercentageBasis( const StyleSize& aStyleBSize, const StyleSize& aStyleMinBSize, const StyleMaxSize& aStyleMaxBSize, nscoord aCBBSize, nscoord aContentEdgeToBoxSizingBSize) { - const nscoord bSize = nsLayoutUtils::IsAutoBSize(aStyleBSize, aCBBSize) - ? NS_UNCONSTRAINEDSIZE - : nsLayoutUtils::ComputeBSizeValue( - aCBBSize, aContentEdgeToBoxSizingBSize, - aStyleBSize.AsLengthPercentage()); + if (nsLayoutUtils::IsAutoBSize(aStyleBSize, aCBBSize)) { + return NS_UNCONSTRAINEDSIZE; + } + + const nscoord bSize = nsLayoutUtils::ComputeBSizeValue( + aCBBSize, aContentEdgeToBoxSizingBSize, aStyleBSize.AsLengthPercentage()); const nscoord minBSize = nsLayoutUtils::IsAutoBSize(aStyleMinBSize, aCBBSize) ? 0 diff --git a/layout/reftests/bugs/1117304-1-ref.html b/layout/reftests/bugs/1117304-1-ref.html new file mode 100644 index 0000000000000..703de547b71f7 --- /dev/null +++ b/layout/reftests/bugs/1117304-1-ref.html @@ -0,0 +1,18 @@ + + + +Bug 1117304 - Different surface formats for different input tiles in feTile filter + +
+ + + + + + + + diff --git a/layout/reftests/bugs/1117304-1.html b/layout/reftests/bugs/1117304-1.html new file mode 100644 index 0000000000000..a7366ef5b2459 --- /dev/null +++ b/layout/reftests/bugs/1117304-1.html @@ -0,0 +1,20 @@ + + + +Bug 1117304 - Different surface formats for different input tiles in feTile filter + +
+ + + + + + + + + + diff --git a/layout/reftests/bugs/1117304-2-ref.html b/layout/reftests/bugs/1117304-2-ref.html new file mode 100644 index 0000000000000..dba8c8a54b936 --- /dev/null +++ b/layout/reftests/bugs/1117304-2-ref.html @@ -0,0 +1,18 @@ + + + +Bug 1117304 - Different surface formats for different input tiles in feTile filter + +
+ + + + + + + + diff --git a/layout/reftests/bugs/1117304-2.html b/layout/reftests/bugs/1117304-2.html new file mode 100644 index 0000000000000..2cb1671e79d2c --- /dev/null +++ b/layout/reftests/bugs/1117304-2.html @@ -0,0 +1,20 @@ + + + +Bug 1117304 - Different surface formats for different input tiles in feTile filter + +
+ + + + + + + + + + diff --git a/layout/reftests/bugs/1117304-3-ref.html b/layout/reftests/bugs/1117304-3-ref.html new file mode 100644 index 0000000000000..1cb8712720331 --- /dev/null +++ b/layout/reftests/bugs/1117304-3-ref.html @@ -0,0 +1,18 @@ + + + +Bug 1117304 - Different surface formats for different input tiles in feTile filter + +
+ + + + + + + + diff --git a/layout/reftests/bugs/1117304-3.html b/layout/reftests/bugs/1117304-3.html new file mode 100644 index 0000000000000..d660bc31dee39 --- /dev/null +++ b/layout/reftests/bugs/1117304-3.html @@ -0,0 +1,20 @@ + + + +Bug 1117304 - Different surface formats for different input tiles in feTile filter + +
+ + + + + + + + + + diff --git a/layout/reftests/bugs/1117304-4-ref.html b/layout/reftests/bugs/1117304-4-ref.html new file mode 100644 index 0000000000000..e389b66022d21 --- /dev/null +++ b/layout/reftests/bugs/1117304-4-ref.html @@ -0,0 +1,18 @@ + + + +Bug 1117304 - Different surface formats for different input tiles in feTile filter + +
+ + + + + + + + diff --git a/layout/reftests/bugs/1117304-4.html b/layout/reftests/bugs/1117304-4.html new file mode 100644 index 0000000000000..15568178a90e5 --- /dev/null +++ b/layout/reftests/bugs/1117304-4.html @@ -0,0 +1,20 @@ + + + +Bug 1117304 - Different surface formats for different input tiles in feTile filter + +
+ + + + + + + + + + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index e306dea8f6d8c..90b6e44888016 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1887,6 +1887,10 @@ fuzzy(0-128,0-22) == 1155828-1.html 1155828-1-ref.html # bug 1646527 for WR fuzz fuzzy(0-7,0-84) == 1156129-1.html 1156129-1-ref.html pref(dom.use_xbl_scopes_for_remote_xul,true) HTTP(..) == 1157127-1.html 1157127-1-ref.html fuzzy-if(Android,0-6,0-6) fuzzy-if(appleSilicon,0-1,0-7) == 1169331-1.html 1169331-1-ref.html +== 1117304-1.html 1117304-1-ref.html +== 1117304-2.html 1117304-2-ref.html +== 1117304-3.html 1117304-3-ref.html +== 1117304-4.html 1117304-4-ref.html fuzzy(0-3,0-110) fails == 1174332-1.html 1174332-1-ref.html # bug 1312658, expected to fail w/ non-native theme because of bug 1699937 == 1179078-1.html 1179078-1-ref.html == 1179288-1.html 1179288-1-ref.html diff --git a/layout/style/MediaFeatureChange.h b/layout/style/MediaFeatureChange.h index a766406219cb0..40118ca99232f 100644 --- a/layout/style/MediaFeatureChange.h +++ b/layout/style/MediaFeatureChange.h @@ -77,7 +77,7 @@ struct MediaFeatureChange { return *this; } - static MediaFeatureChange ForPreferredColorSchemeChange() { + static MediaFeatureChange ForPreferredColorSchemeOrForcedColorsChange() { // We need to restyle because not only media queries have changed, system // colors may as well via the prefers-color-scheme meta tag / effective // color-scheme property value. diff --git a/layout/style/ServoBindings.toml b/layout/style/ServoBindings.toml index 0cd4846aad46f..0d42a79f79c22 100644 --- a/layout/style/ServoBindings.toml +++ b/layout/style/ServoBindings.toml @@ -595,6 +595,7 @@ cbindgen-types = [ { gecko = "StyleImageRendering", servo = "crate::values::computed::ImageRendering" }, { gecko = "StylePrintColorAdjust", servo = "crate::values::computed::PrintColorAdjust" }, { gecko = "StyleForcedColorAdjust", servo = "crate::values::computed::ForcedColorAdjust" }, + { gecko = "StyleForcedColors", servo = "crate::gecko::media_features::ForcedColors" }, { gecko = "StyleScrollbarGutter", servo = "crate::values::computed::ScrollbarGutter" }, { gecko = "StyleHyphenateCharacter", servo = "crate::values::computed::HyphenateCharacter" }, { gecko = "StyleColumnCount", servo = "crate::values::computed::ColumnCount" }, diff --git a/layout/xul/nsScrollbarFrame.cpp b/layout/xul/nsScrollbarFrame.cpp index d726fb9f56a5b..af7c13ed38819 100644 --- a/layout/xul/nsScrollbarFrame.cpp +++ b/layout/xul/nsScrollbarFrame.cpp @@ -58,6 +58,45 @@ void nsScrollbarFrame::Init(nsIContent* aContent, nsContainerFrame* aParent, AddStateBits(NS_FRAME_REFLOW_ROOT); } +nsScrollbarFrame* nsScrollbarFrame::GetOppositeScrollbar() const { + ScrollContainerFrame* sc = do_QueryFrame(GetParent()); + if (!sc) { + return nullptr; + } + auto* vScrollbar = sc->GetScrollbarBox(/* aVertical= */ true); + if (vScrollbar == this) { + return sc->GetScrollbarBox(/* aVertical= */ false); + } + MOZ_ASSERT(sc->GetScrollbarBox(/* aVertical= */ false) == this, + "Which scrollbar are we?"); + return vScrollbar; +} + +void nsScrollbarFrame::ElementStateChanged(dom::ElementState aStates) { + if (!aStates.HasState(dom::ElementState::HOVER)) { + return; + } + // Hover state on the scrollbar changes both the scrollbar and potentially + // descendants too, so invalidate when it changes. + InvalidateFrameSubtree(); + if (!mContent->AsElement()->State().HasState(dom::ElementState::HOVER)) { + return; + } + mHasBeenHovered = true; + // When hovering over one scrollbar, remove the sticky hover effect from the + // opposite scrollbar, if needed. + if (auto* opposite = GetOppositeScrollbar(); + opposite && opposite->mHasBeenHovered) { + opposite->mHasBeenHovered = false; + opposite->InvalidateFrameSubtree(); + } +} + +void nsScrollbarFrame::WillBecomeActive() { + // Reset our sticky hover state before becoming active. + mHasBeenHovered = false; +} + void nsScrollbarFrame::Destroy(DestroyContext& aContext) { aContext.AddAnonymousContent(mUpTopButton.forget()); aContext.AddAnonymousContent(mDownTopButton.forget()); diff --git a/layout/xul/nsScrollbarFrame.h b/layout/xul/nsScrollbarFrame.h index 4b48295f027e5..bb2d8ec9be06b 100644 --- a/layout/xul/nsScrollbarFrame.h +++ b/layout/xul/nsScrollbarFrame.h @@ -34,18 +34,7 @@ class nsScrollbarFrame final : public nsContainerFrame, public: explicit nsScrollbarFrame(ComputedStyle* aStyle, nsPresContext* aPresContext) - : nsContainerFrame(aStyle, aPresContext, kClassID), - mSmoothScroll(false), - mScrollUnit(mozilla::ScrollUnit::DEVICE_PIXELS), - mDirection(0), - mIncrement(0), - mScrollbarMediator(nullptr), - mUpTopButton(nullptr), - mDownTopButton(nullptr), - mSlider(nullptr), - mThumb(nullptr), - mUpBottomButton(nullptr), - mDownBottomButton(nullptr) {} + : nsContainerFrame(aStyle, aPresContext, kClassID) {} NS_DECL_QUERYFRAME NS_DECL_FRAMEARENA_HELPERS(nsScrollbarFrame) @@ -94,7 +83,7 @@ class nsScrollbarFrame final : public nsContainerFrame, void SetScrollbarMediatorContent(nsIContent* aMediator); nsIScrollbarMediator* GetScrollbarMediator(); - + void WillBecomeActive(); /** * The following three methods set the value of mIncrement when a * scrollbar button is pressed. @@ -116,7 +105,7 @@ class nsScrollbarFrame final : public nsContainerFrame, */ enum class ImplementsScrollByUnit { Yes, No }; int32_t MoveToNewPosition(ImplementsScrollByUnit aImplementsScrollByUnit); - int32_t GetIncrement() { return mIncrement; } + int32_t GetIncrement() const { return mIncrement; } // nsIAnonymousContentCreator nsresult CreateAnonymousContent(nsTArray& aElements) override; @@ -124,17 +113,24 @@ class nsScrollbarFrame final : public nsContainerFrame, uint32_t aFilter) override; void UpdateChildrenAttributeValue(nsAtom* aAttribute, bool aNotify); + void ElementStateChanged(mozilla::dom::ElementState) override; + bool HasBeenHovered() const { return mHasBeenHovered; } + + // If we're an horizontal scrollbar, get the vertical one, or viceversa. + nsScrollbarFrame* GetOppositeScrollbar() const; protected: - bool mSmoothScroll; - mozilla::ScrollUnit mScrollUnit; // Direction and multiple to scroll - int32_t mDirection; - + int32_t mDirection = 0; // Amount to scroll, in CSSPixels // Ignored in favour of mScrollUnit/mDirection for regular scroll frames. // Trees use this though. - int32_t mIncrement; + int32_t mIncrement = 0; + mozilla::ScrollUnit mScrollUnit = mozilla::ScrollUnit::DEVICE_PIXELS; + bool mSmoothScroll = false; + // On macOS, overlay scrollbar hover state should be sticky (remain hovered + // while we've been hovered at least once). + bool mHasBeenHovered = false; private: nsCOMPtr mScrollbarMediator; diff --git a/media/libcubeb/0002-disable-crash-reporter-death-test.patch b/media/libcubeb/0002-disable-crash-reporter-death-test.patch index a9ea4c8491af5..b463cf64af7ee 100644 --- a/media/libcubeb/0002-disable-crash-reporter-death-test.patch +++ b/media/libcubeb/0002-disable-crash-reporter-death-test.patch @@ -1,5 +1,5 @@ -diff --git a/test/test_duplex.cpp b/test/test_duplex.cpp ---- a/test/test_duplex.cpp +diff -U8 b/test/test_duplex.cpp b/test/test_duplex.cpp +--- b/test/test_duplex.cpp +++ b/test/test_duplex.cpp @@ -13,16 +13,18 @@ #endif @@ -20,22 +20,46 @@ diff --git a/test/test_duplex.cpp b/test/test_duplex.cpp #define STREAM_FORMAT CUBEB_SAMPLE_FLOAT32LE #define INPUT_CHANNELS 1 #define INPUT_LAYOUT CUBEB_LAYOUT_MONO -@@ -202,16 +204,18 @@ TEST(cubeb, duplex_collection_change) +@@ -199,16 +201,21 @@ + + duplex_collection_change_impl(ctx); + r = cubeb_register_device_collection_changed( + ctx, static_cast(CUBEB_DEVICE_TYPE_INPUT), nullptr, + nullptr); + ASSERT_EQ(r, CUBEB_OK); } ++void CauseDeath(cubeb * p) { ++ mozilla::gtest::DisableCrashReporter(); ++ cubeb_destroy(p); ++} ++ #ifdef GTEST_HAS_DEATH_TEST TEST(cubeb, duplex_collection_change_no_unregister) { cubeb * ctx; int r; -+ mozilla::gtest::DisableCrashReporter(); -+ r = common_init(&ctx, "Cubeb duplex example with collection change"); ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library"; - +@@ -216,17 +223,19 @@ /* This test needs an available input device, skip it if this host does not * have one. */ if (!can_run_audio_input_test(ctx)) { cubeb_destroy(ctx); return; + } + + std::unique_ptr cleanup_cubeb_at_exit( +- ctx, [](cubeb * p) noexcept { EXPECT_DEATH(cubeb_destroy(p), ""); }); ++ ctx, [](cubeb* p) noexcept { ++ EXPECT_DEATH(CauseDeath(p), ""); ++ }); + + duplex_collection_change_impl(ctx); + } + #endif + + long + data_cb_input(cubeb_stream * stream, void * user, const void * inputbuffer, + void * outputbuffer, long nframes) diff --git a/media/libcubeb/test/test_duplex.cpp b/media/libcubeb/test/test_duplex.cpp index 614c83242b4a5..9dfce253a61da 100644 --- a/media/libcubeb/test/test_duplex.cpp +++ b/media/libcubeb/test/test_duplex.cpp @@ -206,6 +206,11 @@ TEST(cubeb, duplex_collection_change) ASSERT_EQ(r, CUBEB_OK); } +void CauseDeath(cubeb * p) { + mozilla::gtest::DisableCrashReporter(); + cubeb_destroy(p); +} + #ifdef GTEST_HAS_DEATH_TEST TEST(cubeb, duplex_collection_change_no_unregister) { @@ -225,7 +230,9 @@ TEST(cubeb, duplex_collection_change_no_unregister) } std::unique_ptr cleanup_cubeb_at_exit( - ctx, [](cubeb * p) noexcept { EXPECT_DEATH(cubeb_destroy(p), ""); }); + ctx, [](cubeb* p) noexcept { + EXPECT_DEATH(CauseDeath(p), ""); + }); duplex_collection_change_impl(ctx); } diff --git a/media/libjxl/moz.build b/media/libjxl/moz.build index 886c2319ad60d..b493386d4113d 100644 --- a/media/libjxl/moz.build +++ b/media/libjxl/moz.build @@ -15,7 +15,6 @@ SOURCES += [ "/third_party/jpeg-xl/lib/jxl/alpha.cc", "/third_party/jpeg-xl/lib/jxl/ans_common.cc", "/third_party/jpeg-xl/lib/jxl/blending.cc", - "/third_party/jpeg-xl/lib/jxl/cache_aligned.cc", "/third_party/jpeg-xl/lib/jxl/chroma_from_luma.cc", "/third_party/jpeg-xl/lib/jxl/coeff_order.cc", "/third_party/jpeg-xl/lib/jxl/color_encoding_internal.cc", @@ -85,6 +84,7 @@ SOURCES += [ "/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_ycbcr.cc", "/third_party/jpeg-xl/lib/jxl/simd_util.cc", "/third_party/jpeg-xl/lib/jxl/splines.cc", + "/third_party/jpeg-xl/lib/jxl/test_memory_manager.cc", "/third_party/jpeg-xl/lib/jxl/toc.cc", ] diff --git a/media/libjxl/moz.yaml b/media/libjxl/moz.yaml index 6798daeeda1a0..c70a47e8f60bf 100644 --- a/media/libjxl/moz.yaml +++ b/media/libjxl/moz.yaml @@ -10,9 +10,9 @@ origin: url: https://github.com/libjxl/libjxl - release: v0.10.3 (2024-06-27T14:10:08+02:00). + release: v0.11.0 (2024-09-13T07:31:05+02:00). - revision: v0.10.3 + revision: v0.11.0 license: Apache-2.0 diff --git a/memory/build/mozjemalloc.cpp b/memory/build/mozjemalloc.cpp index 02b0d89aca192..873d5ce2285e3 100644 --- a/memory/build/mozjemalloc.cpp +++ b/memory/build/mozjemalloc.cpp @@ -426,7 +426,7 @@ struct arena_chunk_t { size_t ndirty; // Map of pages within chunk that keeps track of free/large/small. - arena_chunk_map_t map[1]; // Dynamically sized. + arena_chunk_map_t map[]; // Dynamically sized. }; // *************************************************************************** @@ -577,8 +577,8 @@ DEFINE_GLOBAL(size_t) gChunkNumPages = kChunkSize >> gPageSize2Pow; // Number of pages necessary for a chunk header plus a guard page. DEFINE_GLOBAL(size_t) gChunkHeaderNumPages = - 1 + (((sizeof(arena_chunk_t) + - sizeof(arena_chunk_map_t) * (gChunkNumPages - 1) + gPageSizeMask) & + 1 + (((sizeof(arena_chunk_t) + sizeof(arena_chunk_map_t) * gChunkNumPages + + gPageSizeMask) & ~gPageSizeMask) >> gPageSize2Pow); @@ -1020,7 +1020,7 @@ struct arena_run_t { #endif // Bitmask of in-use regions (0: in use, 1: free). - unsigned mRegionsMask[1]; // Dynamically sized. + unsigned mRegionsMask[]; // Dynamically sized. }; struct arena_bin_t { @@ -1199,7 +1199,7 @@ struct arena_t { // | 46 | 3584 | // | 47 | 3840 | // +----------+------+ - arena_bin_t mBins[1]; // Dynamically sized. + arena_bin_t mBins[]; // Dynamically sized. explicit arena_t(arena_params_t* aParams, bool aIsPrivate); ~arena_t(); @@ -1910,7 +1910,7 @@ arena_t* TypedBaseAlloc::sFirstFree = nullptr; template <> size_t TypedBaseAlloc::size_of() { // Allocate enough space for trailing bins. - return sizeof(arena_t) + (sizeof(arena_bin_t) * (NUM_SMALL_CLASSES - 1)); + return sizeof(arena_t) + (sizeof(arena_bin_t) * NUM_SMALL_CLASSES); } template diff --git a/mobile/android/android-components/components/feature/customtabs/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/feature/customtabs/src/main/res/values-es/strings.xml index 0c5343da93690..131a47f09ab89 100644 --- a/mobile/android/android-components/components/feature/customtabs/src/main/res/values-es/strings.xml +++ b/mobile/android/android-components/components/feature/customtabs/src/main/res/values-es/strings.xml @@ -4,4 +4,6 @@ Compartir enlace Refrescar + + Más opciones diff --git a/mobile/android/android-components/components/feature/customtabs/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/feature/customtabs/src/main/res/values-kab/strings.xml index 0aafaf21f94c2..59ce3621bc131 100644 --- a/mobile/android/android-components/components/feature/customtabs/src/main/res/values-kab/strings.xml +++ b/mobile/android/android-components/components/feature/customtabs/src/main/res/values-kab/strings.xml @@ -4,4 +4,6 @@ Bḍu aseɣwen Smiren + + Ugar n iγewwaṛen diff --git a/mobile/android/android-components/components/feature/prompts/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/feature/prompts/src/main/res/values-es/strings.xml index f74d6b8570435..74084967b5362 100644 --- a/mobile/android/android-components/components/feature/prompts/src/main/res/values-es/strings.xml +++ b/mobile/android/android-components/components/feature/prompts/src/main/res/values-es/strings.xml @@ -49,7 +49,9 @@ ¿Actualizar contraseña? - ¿Añadir nombre de usuario a la contraseña guardada? + ¿Añadir nombre de usuario a la contraseña guardada? + + ¿Actualizar nombre de usuario? Etiqueta para ingresar un campo de entrada de texto @@ -116,8 +118,6 @@ Sugerir contraseña segura - - Sugerir contraseña segura Usar contraseña segura @@ -126,7 +126,10 @@ ¿Usar contraseña segura? - Protege tus cuentas utilizando una contraseña segura generada aleatoriamente. Obtén acceso rápido a tus contraseñas guardándolas en tu cuenta. + Protege tus cuentas utilizando una contraseña segura generada aleatoriamente. Obtén acceso rápido a tus contraseñas guardándolas en tu cuenta. + + Protege tus cuentas utilizando una contraseña segura generada aleatoriamente. Se guardará en tu cuenta para uso futuro. + Usar contraseña @@ -137,6 +140,9 @@ Contraseña actualizada + + Nombre de usuario actualizado + ¿Reenviar los datos a este sitio? Actualizar esta página podría duplicar acciones recientes, como hacer un pago o publicar un comentario dos veces. @@ -196,7 +202,7 @@ Usar %1$s como proveedor de inicio de sesión - Política de privacidad y a los Términos de servicio]]> + Política de privacidad y a los Términos de servicio]]> Continuar diff --git a/mobile/android/android-components/components/feature/prompts/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/feature/prompts/src/main/res/values-skr/strings.xml index ab59b61e527e4..009e628204905 100644 --- a/mobile/android/android-components/components/feature/prompts/src/main/res/values-skr/strings.xml +++ b/mobile/android/android-components/components/feature/prompts/src/main/res/values-skr/strings.xml @@ -128,6 +128,11 @@ تَکڑا پاس ورڈ وَرتو؟ + + ہک مضبوط، بے ترتیبا تیار تھیا پاس ورڈ ورت تے آپݨے اکاؤنٹس دی حفاظت کرو۔ آپݨے اکاؤنٹ وچ محفوظ کرتے آپݨے پاس ورڈز تائیں فوری رسائی گھنو۔ + + ہک مضبوط، بے ترتیبا تیار تھیا پاس ورڈ ورت تے آپݨے اکاؤنٹس دی حفاظت کرو۔ ایہ مستقبل وچ ورتݨ کیتے تہاݙے کھاتے وچ محفوظ تھی ویسی۔ + پاس ورڈ ورتو @@ -200,7 +205,7 @@ %1$s کوں لاگ ان مہیاکار دے طور تے ورتو - رازداری پالیسی اَتے خدمت دیاں شرطاںدے تابع ہِے۔]]> + رازداری پالیسی اَتے خدمت دیاں شرطاںدے تابع ہِے۔]]> جاری diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/qwant.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/qwant.xml index e5b9dfb328973..316192c04c189 100644 --- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/qwant.xml +++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/qwant.xml @@ -5,7 +5,7 @@ Qwant UTF-8 -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAABGdBTUEAALGPC/xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAYKADAAQAAAABAAAAYAAAAACK+310AAAMKUlEQVR4Ae1dC1BU1xn+7/JaBBdEUVgUHygqCr6ijYqv+JgEX4kdbfNobKZaptNxJmYybWKnCdWoTWxtOpk2D51JbEI6OrW+U19RSXxgSEYFg4RIFOWloMAuwvLc/v+VJYvs5Zxd7rm74P1nYO895z//+c/333ue/zlXAk5K22UPLKiCOfYWWIJJEiQAs90OZrwO5RTRU9lqJAlK7AAlWMBcyQD748LhZNoKqYGnwIhj5/TLD+1RLTZ4rQXgWeQ0dc6tx7YiYDEApBuMsP6jF6SyzlBRNMCaz+xBlYXwB7TuS/ikh3QmRI9zjQBidw+x29pnMGx8J0Wqd8Xl0gD01DfZYA8meNRVIj3MbQQy/Y3wlKu3oYMBnt9mT2pphkNgh4FuZ6MnUEZAgiJ/CVI+SpVynJnaGUB+8ushSwffGSIVr8kIQTDZ+U3AtuI+UZ0vVzv6k++ARP1fxJYwJqwdwtsMQA0uBup1vgMZcb+PtmIt5yBXQVT1NNfDVb23Iw51Z8nUO/ILguFUFclvAPXzdfCdIRJ7TVgT5pSLRCPcq3egHK/1QZZY3B+UbhneFyINNL2gg/8gNprcmwh7Q+vcjiY56pm0R4CwpzYgoX2wfqchAgkG7AbRjKZOXkCAsDdgi6wbwAvgU5aEvT/++vR8vr2lCe4UZkH51dNguZWHf/lgqy6BRpsVmuprwIBj+wBjbwjs1QdCI4dD7/7xEDFoIvSPnwXG3v29BC13tqFkAJ8jAr3k8mdwPetTKL1yFJob7inq2NxYC/Rns96SDeTMGG4eC7GTfgaDH3kGevXxzblF6bl38UXwESLgC85sh28Pb5IBVU0tXKaKnfBTSFy0HkL7DVNNrBqCfMYANy/shuyDr0FN+VU1yuVShmQIgOHJv4Yxj6+DoNB+Lnm0DvS6AapKvoWsT1Ph7o0szcoeYDTJRhj52FrN8lTKqG02VIlBZHhx9n74/G8zNQWfytNos8DFva/A2Q+fwfajTmQRmbK9ZoDco3+G09tXyD0ZppaCGKjaO/H2HKitKhaUA1us5gZoaW6Eczt+ATkHX0ftvN/+3715AY79ZRq+hV+z0RLAobkBvt75W7jxzS51ioK9GzXIZimDjHeXQE3FNTXEuSVD03HAdyf/Dtcyd7iloIO5d+QIiElaApFxyWAMM0OvsGh5oNXUUAt1ODCrs5SCtSwPinIOwu38k9DSzOUX5RAPDffuwOlty2DeS1+Cf5B2Y1PNekFlOKDKeG8p1jro4sVJBr9AiMNuY9z0VRAWNZozFcjtSlH2Acg9vBGs5d9zpyNG89iFMGP1blwpwZkaDUgTA1ixb39syzTsfVRzFknCEexySFxIA6ehnGk6stnRv6bg7Ha4/L83oN56uyODQsjo+b+HpMXrFWLVDVanEmXodHHP77jB9wsMgemrdsLUlR93CXxSSTL44cArFZ5YdxGrrhkMLX+Mzvv8r/Kc048h4q6EG6C84DTO6xziKkFIxGCYtzYDBiZhVaUiBYX0hTlrDkPctF9xSaUpkZwDf+Ti7SqTcANc3Psql47B2LDOXXsKwmMSufjdZZIM/vDIz/8J8bPWcCUtyt4Ld66f5+LtCpNQA9y8+F+4W/gVUz8DOk4mr/4PkBFE0/hlb0HUqPlc2fA+PFzCFJiEGiD3yCaFbNsHT376PYiIndQ+UNCdhGOHaS+ky2sHrCwqfjgDt7/PYLF1KV6YAaqKc4D+WNR/xGwYMvlpFpuq8QHBYTD+yTe5ZF7/6hMuPk+ZhBngelY6h04SArGZg099lpjERdBv2HSmYKpGW5pcuvYz0/IwCDNAWd5RZv6Dxi+DPrh86C0at3QjM2ta9iz/4SyTz1MGIQaot5ZDNc7zs2jIFNr15D3qN3QqjjXimArczj/F5PGUQYgBKji6bzTgiho1z1O9VUsXk7iYKaviWiaTx1MGIQaw3v6OqU/06AWyRwOTUTADTfCxyHqLXR6WDKV4QQbIV8qvLTwi1nt1f5sSeMGjB820UlsggoQYwGatYOpqNEUzebRg8AsIhoDgcGZWNmzXRJAQAzSh0xSLgnE+31eIR5du9QbQIgmLAkN8wy2E9KTJOhaR85cIEvIG+AUGM3VtrL3D5NGKoeHeXWZWBn92mZhCXDAIMQD5arKotqqUxaJZfC0uabIowChmmVKIAXi8zmzYs/AFam60QWNdFVOVoNBIJo8nDEIMYEIPZRZVojuIL1BlEVsPoylK9sAWoa8QA5CLOItKrxzBSS73PBdYMj2JL8bFexbxlIclQyleiAH6DvmJUn5t4dStu5V/ou3eWxfkHsmifkPF7V8XYgCjaQCYONxICtH/35tE3nA8biv9R8wSpqYQA5C2PMt+heghV1mULaxwLMGX9tHpDJ0TTRpGxrHXDTqXohwrzAC0K4VNdsjev47NJoCjNPcILjeeYkoeNG4p0HSFKBJmgIjYCRAWzd4BW5Z3DMhLWUui9od8lXhoyJTneNg85hFmANJo9IJXuRQ7n76aa/2YSxiLCXdknduxssN+MlfJqDMxYORcV1GqhQk1wOBJK7iWHGkT3pcfLEP3QTEzjs5oXUKHq5LLB52DFK/HLd2kGKdWhFADkJK8haitvAHH354NFvRwFkF2dAq+sPtlyDu+hUu8eUyK7InNxdwFJuEGGBA/B6Jw9YuHaIPe8a0zgBpINamxrhq+QP///Ix3+MSi71Di4jf4eLvIJdwApN+Ep7Zw+9zT/q0v3n8Ssv6dKvv9d6l8WN9fO/8xHN48Eaix56WRc16EcPMYXvYu8Wnink4aFuccwA0Qy/GKf1sSdf/iZ6+R9weQ4y4vkR8PbfS+fHgDl3eGs1wav8z8zX7cHqDJswmaGYAKmXv0TdwbJh8U5VxmruvwmCSIScQdMsOTZR9S8iOlaW/yZK6z3AKaXa0uzZMbWNbueqUMaRfO/JfP4BJlmBKL6uGaGoC0z9zxPBR+s1OVgtAbQtPJ7rxVShnT3mHanmSKGqXEIiRcm/fMSfUpz27DvV7q+P/f3+PLX6U5qdHukub6qdrRGnxSQnMD0Okmyat2QcKCV9qB4K0bGq1TtUNect4gzQ3gKGTioj/hNqRPhM6zOPJS+o1OeEKudtxp4JVkeRruNQOQwrQRb+6LJ4TtilEChWY4ExemwczUPdzdYyVZXQ3XvBF2qTD21+lsoJxDaUAjYlEkSX4wbOpKGJPyOgTjMqMvkG8YoBUJ6r/nZ/wDrhx7CxpqK1XFJzrhcRi3ZDOEmdkztKpmzBDmUwZw6Epdy6JL+/CtSPdo17tDDvXrB01cDkNxSjk0ku2G7kin5a9PGsAZAOpqVuAGifKCM/JEHXle11ajsyy6P94/jkBqOzMuBE/DCotKwDYlCaeRH4OQiFhnUT557fMG6Aw1OsCP5nloQ7ZoSsbN41SNqU2aHtahtvKmAfH4xI+EqpLLaovuIK/o0l4hBvBqN7RDKT0IUGtUzcq6mHb7CzjfsNsbwIwTdFoQHfZRce2c6ll1ewNEDBqPZ4Jq09gWcThxuWuhbm8AKjDPPi93gXHFz+NF5ypdZ2E9wgADOTbadQYCb1xNRQE2+Oztt7zyiK9HGICOMQvsFeFOuT3mLc7e53FaVwl7hAFoHGAem+KqfKqHleSwnXndybRHGIAKrPYhT0og0jGXtZU3laLdDu8xBogaPV+ztQU1G2OaiqA9pWI2QLn9PDxcCfBgRqsB/5U8XMX2qdKWGnBJWzeAl2xC2FMbkOul/PVsEXsDOoCp26/SYeVGgLA30AfoMYWFO5XOqBYCFsLekLZCasB6iOeAN7Uy1uUgAoR5K/Z4Y4T12Bu6pyOjDQKENWFOuVEjDPRdW1xr2ErXOolHgLB2fNZcNgBl2Wcw0BGC4g5HE1+u7pJDZivWsr7tDsmnL2uja04WuvD75lfPugvESnpKUISusZMdTz+xtb0BdCN/YtsPFgIy0r1OKiJA4EuQ4gw+SW9nAAr412opm6yEl3p1RICoQ5nyk58q5TworoMBiIGshPXUbLzcoPeOCBHPqBW7DYTlg0++Q2K7NsAR6PxL7QJ9gL4FgI65NTnH6deKCFjwyU6nrqYS8I6UTAM4GNN22QPpG+itn0BPwIRm7E6ZMf5hn8quwSe9pHVSM5emF2iES4MsB3ad/f4fDbO11HHkpjkAAAAASUVORK5CYII= +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAuzSURBVHgB7Z0JUBRXGsf/3TMQEOUUBIIcMgomilcUYY1nEo3mMNl4rO5uEg+SzSabpOLWesVNVdxoLKPRqKgxalKJFaNxXddzRcVE8UDxQhQEnSCHXDIil8hM73udYMQw3T3SxyD9q5qa6e6PKXhf93vf+WAggdDQUB8XF4/hHGN7kgPiGCCE4zgPgGGhQ+EYBpWcDfkMwxwEi70s5/5DdvapErEfZIQuRkZGduRgfJNjMBkc/KDjCMVEKZuNLPfPrKysUntCBnsXOnXq8gbHGLaQj0PJqw10HIXMEOhr45g/+vj637aUlx5vSug3T0B4+GA31li4guPwKnRkg8zVa6zWoLfM5uTau883egLCw3t6M8byb8h0Mx46skLWzt4MWxnl7dX9vxaLub7hfKNFlGFrPiOSz0FHKcawbOEnd5+48wREREZPIxPSNOgoC4O+Pn4B+ZbrpWk/HxKioqKC66w4R+5+X+ioQYX1dk14bm5uOT8F1d3GLH3wVcXTxdWNn20Yk8nkb+PYdA5MAHRUg/gI+fV1Nd2NVhiGkGN98FWGmPkPsy5uw1niOg+FjiYwYIewRBWDoKMJDDgTS+b+jtDRBoZ5lD4BepynCXrExEBpSETZn5qhDHQa0dlkwrq1q8kNqvjQsHo8vwmio7vA29sbvXr2gNLoCmiC+Ph4/v2xvn2gNLoCmmDI4IH8+zMjR0JpdAXcg5+fHwICfvZLo7tG46GHHoKS6Aq4h0EDB975bDQY8Fif3lASXQF34ePjgxdfeL7RueHDnyLnvaEUTERkFIdWipubG3r2iEHv3r3Qr19f9CHvHh4ev5GzWG4g5cgRZGRcwIkTJ5F26jTq6+shB61SARMmjMewoUPJdDOAGOKOTwKVlZVEEWnYsnUrtm/fiebQKqegK5evoKSkGJcuZTt8J9fV1aGoqBgXMy+irLQMzaVVT0GUzp1NGPC7eHTr9ij6x/ZDUFBQo+skXIDcq3lISUnBmTNncfTYcVwlx/S8HLR6BdzLooUfY/ToXxfiRYuXYtnyFVCKFjkFsQpGUHbs2t3o+MdDP0JJjHBSaCAsPDwMvXv1RCQJjgUHBZJXENr7+8PVxQir1YabN2+ioKCAvApxraiInyJOnEzD7du3cb+kpp6485l+T0bGRSiJ0ykgIMAfY8e+hDEv/R4dQ0JE5R95pGuj48rKKqSeSMXKlZ+T95NwlIqKm/wc37FjCNLT05ulTCk4jQIiIzvh7bfexJNPDmuW+9+2rQeJ5QzmX3QgFy76FDt27ITNZpP8HdTmH9dxDLZu2w6l0VwBrq6umDTpFUx+9WU+DmMPanVcys7h78rqqiq+Mp7epTRU0JTzRKHXlyxeiJFPD8f8+QvwU+5VSOHIkeMYN3YMThGHS2k0tYK8vLyQuHwp+vePtStDBz4xcRW+2/w9cpsYQBcXF2JGxuHv094jcfwou99TbrFg+vTZ2JuUBDE6kGDctv98j9i4x6E0Bh/f9h9AA0JCHsa6L1ajF1lk7XE1Lw9TE/6CzVv+jRs3KpqUoVOL2fwTNm3eglu3ahEfF9eknDsJO4x8egRu1d7CybQ0CFFTU4OkpP0kBGGB0miiAIOBxbcbvkZXEu61B42/jB03ERcvZkIKVquVWDAnYTAa0K9v3yZlWJZBXFx/3gPOzsmx+130qVNj8PnfCRqQuGIZoqK6CMpMnpJAFlFpc/bdLCaO07btO+xep8qfP28uv+g7A6or4NlnRuKJYcK1YBs2fItTp8/gfqB374IFnxBzssKujKdnO8z/aC6MRu2NQFUV4OnpiXfffUdQhga71qxdj+ZAnbO9SfsEZfoQ62nEiKegNaoq4AWS7AgPCxWUoQNnNpvRXJYtX8krU4hZM6ajXbt20BJVFfDa1MmiMnv27IUc5BMLKjvnsqBMhw4BeOIJbUtjVVMAtdEDAwMFZWhs/nhqKuSgnlhFBw4ki8o9M+ppaIlqChg35iVRmXPn0lFcLNrbLJn09POiMrH9+vHOnFaopgCadxUjh2Sq5OQcCVuI0aZNG14JWqGKAmh5h5DT1UC6hAFzhJKSUklBOC19AlUUEEhi+VJs7sLCa5ATGkqmeQIxYrp3g1aoooCw0DBJctXVVZCbQpKsESNMxDRWElUU4NdeWgNmTW0d5Ka6ukZUxtdXuwZRVRTg7uYuSa62RnywHMXGia8Bbm7K1n8KoYoCpAwCRYlkOythSyNOw7oQVRRQVVkpSY6ahHJjdDGIylRVyb/2SEUVBRRItG7atm0LufHx9hGVKSgUX6iVQh0F5BdIkmvnKb8CaF5YjCtX5HUAHUEVBZSWlRFrpFpUTkoZiiN4eXnaTdjfjRrJd3uoswgTb/RQSoqoXKdOEZCTrtHi3jclM/MStEK1WFDK4SOiMr0FEvT3g5T4E/W+M7OyoBWqKWDX7j2iMqGhoYKlJY4iVO7SgJQyFSVRTQE0MHb06DFROdqpIgdBQR34tKMYO3buhpaomhFb88V6UZnnnh0lS4f6MJL4p7VAQiTt29+oGFcLVFVA8sGDSBJJlvfq2RPx8XFoDh4ebfB6wlRBGWoYKFn3LxVVFUD/6HkfLxRMltO7f877M5v1FLz85z8hODhYUGbtuvU4e1be/MP9oHplHK04KyN+wbChQ+zK+JHoJI0fHT/ueH6YljrO+9eHgmnG8+czMH36LNyqkz/66iialCbSXK27u7vgIhlHLJjiomKknxfP6zYQFhaGNatXCoaXacn6pCkJKCkthTOgWXHusV/u7lgBq2fQoMd5T5ZWyYk1SowfPxarEpcJDj4tT3/51cm8EpwFzZv0Jk4Yj3fefkuwN6C8vBzfbNjI92vREvWamlq4kBRnO09Pvtf3xRdGo7tIWpHa+7Pf/4A3h50Jp+iSNJlMmDF9Gt/VIgatHaLl43SRlhI9LS0tw5Kly7Dxu02ydbfLiVO1qdKy8lmz/oHu3ZqfJKcL/caNm5C4ajWJ94sHArXCKfuEg4ODMPr553h/gIYmfH3EY/q1tbV8XOfw4RQcSD5IpqvDonc83SuCtjjR5mutng6nb9Smg9Tt0Uf42p2JE/7Ad7Q3QAdt/Zdf8RtonM+4wLerSu1g72yKJE/bDAx8fAD270/GlITXoQVO2yfcAL2zae8vfdE7+2jKr43TtNZo4oQJCOwQiDyS9MkXSfzQnHN3osCEhCkYMfypO85efkE+tKLFbVXwCvFy58yZ1eQ1qqw0YrJmXszk+31pzxhteaV9CfQJ6tEjBl7k87289vpfRfsJlKJF7hXx2ZLFGCVjVfOoZ0fjwgVlO+Lt0SL3ipg5ew5ZbMUTPFKgPoVWg09pkQqge0TQcMIhYuk0lzNn7q8XTS5a7IZNNDTxyqSpWLf+KzSHDA3vfkqL3jGLhrc/nPsRxo6fiOLiYtwPeXnaWUCUB2LLMuoHxA8YTOz6OTh95qzkn6N+w5494rlqJXngdsyitn1MTDf0j41FREQ4eUWQQJ8vDAYjH9TLI5HQvPx8vlOe5qgLCrSriuN/X33LMm1plbsmOhO6AjRGV4DGUAVI38tLR26sLIkH3oSOVhSwHANpxfs68sMghz4B8kS1dByHY7JYzopd0NEEhsP/WKvVdR95CpyrVqN1UFzNuv/A5uaeK+fArYaOqpDc9eJr2adKeD/AwLglkhhKBXTUosDViDX0A99Ee/16UYW3ry8xRxnl/2+TDmwMN+PypayD9POdLmbL9bJUX5/2YcQ0Em+s0mkG3OfmnKw5DUeNQhE22603ODBfQkcR6FrLWYP/dve5Rn38Foul3tsrJJkx1D9MDpX/R4qtCQYrYA1+12xOrm182g4RkdHvkaszyXKt3V4uDwDUuOGstveuXMla09R1uztZWMpLj3Tw9/vaxjHUR6D/XFe85VznDiQxl0cG/1Nbfe04sznHbpe6pEYsk6mXvxXVQ4jrPIwcdmHAdSZpNLoHpfhWJK0DGlEuYsBc4Fhkk1ljr7WuZl9ubm652A/+H9NAGCizUk1MAAAAAElFTkSuQmCC diff --git a/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt b/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt index 0288f20df9c78..42272cf36cd32 100644 --- a/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt +++ b/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // These lines are generated by android-components/automation/application-services-nightly-bump.py -val VERSION = "132.20240914050334" +val VERSION = "132.20240917050325" val CHANNEL = ApplicationServicesChannel.NIGHTLY object ApplicationServicesConfig { diff --git a/mobile/android/android-components/plugins/dependencies/src/main/java/DependenciesPlugin.kt b/mobile/android/android-components/plugins/dependencies/src/main/java/DependenciesPlugin.kt index 58052d60fb333..a9e417337232a 100644 --- a/mobile/android/android-components/plugins/dependencies/src/main/java/DependenciesPlugin.kt +++ b/mobile/android/android-components/plugins/dependencies/src/main/java/DependenciesPlugin.kt @@ -89,6 +89,8 @@ object Versions { const val work = "2.9.1" } + // Gradle can't deal with this being nested below. + const val protobuf_plugin = "0.9.4" object Google { const val accompanist = "0.36.0" const val firebase_messaging = "24.0.1" @@ -98,6 +100,7 @@ object Versions { const val play_services_ads_id = "16.0.0" const val play_services_base = "18.5.0" const val play_services_fido = "21.1.0" + const val protobuf = "3.21.10" // Keep Protobuf in sync with the version used by AppServices. } object Testing { @@ -265,4 +268,6 @@ object ComponentsDependencies { const val play_services_ads_id = "com.google.android.gms:play-services-ads-identifier:${Versions.Google.play_services_ads_id}" const val play_services_base = "com.google.android.gms:play-services-base:${Versions.Google.play_services_base}" const val play_services_fido = "com.google.android.gms:play-services-fido:${Versions.Google.play_services_fido}" + const val protobuf_compiler = "com.google.protobuf:protoc:${Versions.Google.protobuf}" + const val protobuf_javalite = "com.google.protobuf:protobuf-javalite:${Versions.Google.protobuf}" } diff --git a/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml b/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml index 029217cf87913..cdad12b3b7d37 100644 --- a/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml +++ b/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml @@ -31,11 +31,11 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: b028222e898b235c09cabd7f7aa1550e2bffe01c (2024-09-14T05:03:34). + release: 8be45cd32354c1ed808271cb0f2212b7bffce317 (2024-09-17T05:03:25). # Revision to pull in # Must be a long or short commit SHA (long preferred) - revision: b028222e898b235c09cabd7f7aa1550e2bffe01c + revision: 8be45cd32354c1ed808271cb0f2212b7bffce317 # The package's license, where possible using the mnemonic from # https://spdx.org/licenses/ diff --git a/mobile/android/fenix/app/.experimenter.yaml b/mobile/android/fenix/app/.experimenter.yaml index b8cdf14cfecb7..d78513f57c11f 100644 --- a/mobile/android/fenix/app/.experimenter.yaml +++ b/mobile/android/fenix/app/.experimenter.yaml @@ -224,14 +224,6 @@ splash-screen: maximum_duration_ms: type: int description: The maximum amount of time in milliseconds the splashscreen will be visible while waiting for initialization calls to complete. -toolbar: - description: The searchbar/awesomebar that user uses to search. - hasExposure: true - exposureDescription: "" - variables: - toolbar-position-top: - type: boolean - description: "If true, toolbar appears at top of the screen." unified-search: description: A feature allowing user to easily search for specified results directly in the search bar. hasExposure: true diff --git a/mobile/android/fenix/app/build.gradle b/mobile/android/fenix/app/build.gradle index 65c58826b6de7..17a65b308af86 100644 --- a/mobile/android/fenix/app/build.gradle +++ b/mobile/android/fenix/app/build.gradle @@ -697,7 +697,7 @@ dependencies { implementation ComponentsDependencies.androidx_viewpager2 implementation ComponentsDependencies.androidx_work_runtime - implementation FenixDependencies.protobuf_javalite + implementation ComponentsDependencies.protobuf_javalite implementation ComponentsDependencies.google_material implementation FenixDependencies.adjust @@ -761,7 +761,7 @@ dependencies { protobuf { protoc { - artifact = FenixDependencies.protobuf_compiler + artifact = ComponentsDependencies.protobuf_compiler } // Generates the java Protobuf-lite code for the Protobufs in this project. See diff --git a/mobile/android/fenix/app/messaging-fenix.fml.yaml b/mobile/android/fenix/app/messaging-fenix.fml.yaml index 67089da0ab30b..892aa187d9c3c 100644 --- a/mobile/android/fenix/app/messaging-fenix.fml.yaml +++ b/mobile/android/fenix/app/messaging-fenix.fml.yaml @@ -50,6 +50,7 @@ import: SECOND_HOMEPAGE_VIEW: "'home_screen_displayed'|eventSum('Years', 4, 0) >= 2" PERFORMED_A_SEARCH_AGAIN_RECENTLY: "'performed_search'|eventSum('Years', 4, 0) >= 2 && 'performed_search'|eventLastSeen('Minutes') < 1" FXA_CURRENTLY_SIGNED_IN: "is_fxa_signed_in == true" + FXA_MORE_THAN_1_DEVICE: "fxa_connected_devices > 1" # Has the user signed in the last 4 years FXA_SIGNED_IN: "'sync_auth.sign_in'|eventLastSeen('Years', 0) <= 4" diff --git a/mobile/android/fenix/app/nimbus.fml.yaml b/mobile/android/fenix/app/nimbus.fml.yaml index 44ea89b03edf4..34c3182b0d5b7 100644 --- a/mobile/android/fenix/app/nimbus.fml.yaml +++ b/mobile/android/fenix/app/nimbus.fml.yaml @@ -35,13 +35,6 @@ import: } features: - toolbar: - description: The searchbar/awesomebar that user uses to search. - variables: - toolbar-position-top: - description: If true, toolbar appears at top of the screen. - type: Boolean - default: false homescreen: description: The homescreen that the user goes to when they press home or new tab. variables: diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelper.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelper.kt index 34bb7a0d44a42..706bb0dd8b225 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelper.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelper.kt @@ -104,6 +104,11 @@ interface FeatureSettingsHelper { */ var isSetAsDefaultBrowserPromptEnabled: Boolean + /** + * Enable or disable bottom toolbar position. + */ + var shouldUseBottomToolbar: Boolean + fun applyFlagUpdates() fun resetAllFeatureFlags() diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelperDelegate.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelperDelegate.kt index df63b34081d7c..8b515ee2bc1b4 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelperDelegate.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/FeatureSettingsHelperDelegate.kt @@ -47,6 +47,7 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper { isNavigationToolbarEnabled = settings.navigationToolbarEnabled, isMicrosurveyEnabled = settings.microsurveyFeatureEnabled, isSetAsDefaultBrowserPromptEnabled = settings.setAsDefaultBrowserPromptForExistingUsersEnabled, + shouldUseBottomToolbar = settings.shouldUseBottomToolbar, ) /** @@ -80,6 +81,7 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper { override var isNavigationToolbarEnabled: Boolean by updatedFeatureFlags::isNavigationToolbarEnabled override var isMicrosurveyEnabled: Boolean by updatedFeatureFlags::isMicrosurveyEnabled override var isSetAsDefaultBrowserPromptEnabled: Boolean by updatedFeatureFlags::isSetAsDefaultBrowserPromptEnabled + override var shouldUseBottomToolbar: Boolean by updatedFeatureFlags::shouldUseBottomToolbar override fun applyFlagUpdates() { Log.i(TAG, "applyFlagUpdates: Trying to apply the updated feature flags: $updatedFeatureFlags") @@ -112,6 +114,7 @@ class FeatureSettingsHelperDelegate() : FeatureSettingsHelper { settings.navigationToolbarEnabled = featureFlags.isNavigationToolbarEnabled settings.microsurveyFeatureEnabled = featureFlags.isMicrosurveyEnabled settings.setAsDefaultBrowserPromptForExistingUsersEnabled = featureFlags.isSetAsDefaultBrowserPromptEnabled + settings.shouldUseBottomToolbar = featureFlags.shouldUseBottomToolbar setETPPolicy(featureFlags.etpPolicy) setPermissions(PhoneFeature.LOCATION, featureFlags.isLocationPermissionEnabled) } @@ -136,6 +139,7 @@ private data class FeatureFlags( var isNavigationToolbarEnabled: Boolean, var isMicrosurveyEnabled: Boolean, var isSetAsDefaultBrowserPromptEnabled: Boolean, + var shouldUseBottomToolbar: Boolean, ) internal fun getETPPolicy(settings: Settings): ETPPolicy { diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt index e6e391cd4836b..c23afba008f60 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt @@ -64,6 +64,7 @@ class HomeActivityTestRule( isNavigationToolbarEnabled: Boolean = false, isMicrosurveyEnabled: Boolean = settings.microsurveyFeatureEnabled, isSetAsDefaultBrowserPromptEnabled: Boolean = settings.setAsDefaultBrowserPromptForExistingUsersEnabled, + shouldUseBottomToolbar: Boolean = settings.shouldUseBottomToolbar, ) : this(initialTouchMode, launchActivity, skipOnboarding) { this.isHomeOnboardingDialogEnabled = isHomeOnboardingDialogEnabled this.isPocketEnabled = isPocketEnabled @@ -82,6 +83,7 @@ class HomeActivityTestRule( this.isNavigationToolbarEnabled = isNavigationToolbarEnabled this.isMicrosurveyEnabled = isMicrosurveyEnabled this.isSetAsDefaultBrowserPromptEnabled = isSetAsDefaultBrowserPromptEnabled + this.shouldUseBottomToolbar = shouldUseBottomToolbar } /** @@ -144,6 +146,9 @@ class HomeActivityTestRule( composeTopSitesEnabled = composeTopSitesEnabled, isMicrosurveyEnabled = false, isSetAsDefaultBrowserPromptEnabled = false, + // workaround for toolbar at top position by default + // remove with https://bugzilla.mozilla.org/show_bug.cgi?id=1917640 + shouldUseBottomToolbar = true, ) } } @@ -187,6 +192,7 @@ class HomeActivityIntentTestRule internal constructor( isNavigationToolbarEnabled: Boolean = false, isMicrosurveyEnabled: Boolean = settings.microsurveyFeatureEnabled, isSetAsDefaultBrowserPromptEnabled: Boolean = settings.setAsDefaultBrowserPromptForExistingUsersEnabled, + shouldUseBottomToolbar: Boolean = settings.shouldUseBottomToolbar, ) : this(initialTouchMode, launchActivity, skipOnboarding) { this.isHomeOnboardingDialogEnabled = isHomeOnboardingDialogEnabled this.isPocketEnabled = isPocketEnabled @@ -205,6 +211,7 @@ class HomeActivityIntentTestRule internal constructor( this.isNavigationToolbarEnabled = isNavigationToolbarEnabled this.isMicrosurveyEnabled = isMicrosurveyEnabled this.isSetAsDefaultBrowserPromptEnabled = isSetAsDefaultBrowserPromptEnabled + this.shouldUseBottomToolbar = shouldUseBottomToolbar } private val longTapUserPreference = getLongPressTimeout() @@ -278,6 +285,7 @@ class HomeActivityIntentTestRule internal constructor( isNavigationToolbarEnabled = settings.navigationToolbarEnabled isMicrosurveyEnabled = settings.microsurveyFeatureEnabled isSetAsDefaultBrowserPromptEnabled = settings.setAsDefaultBrowserPromptForExistingUsersEnabled + shouldUseBottomToolbar = settings.shouldUseBottomToolbar } companion object { @@ -308,6 +316,9 @@ class HomeActivityIntentTestRule internal constructor( composeTopSitesEnabled = composeTopSitesEnabled, isMicrosurveyEnabled = false, isSetAsDefaultBrowserPromptEnabled = false, + // workaround for toolbar at top position by default + // remove with https://bugzilla.mozilla.org/show_bug.cgi?id=1917640 + shouldUseBottomToolbar = true, ) } } diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/BrowsingErrorPagesTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/BrowsingErrorPagesTest.kt index f21dd40efb990..7de41dc838fa5 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/BrowsingErrorPagesTest.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/BrowsingErrorPagesTest.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.ui import androidx.core.net.toUri +import androidx.test.filters.SdkSuppress import org.junit.Rule import org.junit.Test import org.mozilla.fenix.R @@ -121,6 +122,7 @@ class BrowsingErrorPagesTest : TestSetup() { } // TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2140588 + @SdkSuppress(minSdkVersion = 34) @Test fun verifyNoInternetConnectionErrorMessageTest() { val url = "www.example.com" diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt index 5818b2a7b2abd..4b9b940e7261f 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt @@ -42,6 +42,9 @@ class CollectionTest : TestSetup() { isPocketEnabled = false, isWallpaperOnboardingEnabled = false, isTCPCFREnabled = false, + // workaround for toolbar at top position by default + // remove with https://bugzilla.mozilla.org/show_bug.cgi?id=1917640 + shouldUseBottomToolbar = true, ), ) { it.activity } diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/ContextMenusTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/ContextMenusTest.kt index 38ed4b464f388..3fae6460adfb6 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/ContextMenusTest.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/ContextMenusTest.kt @@ -47,6 +47,9 @@ class ContextMenusTest : TestSetup() { AndroidComposeTestRule( HomeActivityIntentTestRule( isJumpBackInCFREnabled = false, + // workaround for toolbar at top position by default + // remove with https://bugzilla.mozilla.org/show_bug.cgi?id=1917640 + shouldUseBottomToolbar = true, ), ) { it.activity } diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/DownloadTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/DownloadTest.kt index f66eaea11a71b..3fd3878458c80 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/DownloadTest.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/DownloadTest.kt @@ -8,6 +8,7 @@ import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.core.net.toUri import androidx.test.espresso.intent.rule.IntentsRule import androidx.test.filters.SdkSuppress +import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.mozilla.fenix.customannotations.SmokeTest @@ -343,6 +344,7 @@ class DownloadTest : TestSetup() { } // TestRail link: https://mozilla.testrail.io/index.php?/cases/view/244125 + @Ignore("Failing to restart the network connection, to be re-enabled when it's ready for API 34") @SdkSuppress(maxSdkVersion = 30) @Test fun restartDownloadFromAppNotificationAfterConnectionIsInterruptedTest() { diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt index 436763ccd7cee..c8cb6c445f62b 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt @@ -36,6 +36,9 @@ class HistoryTest : TestSetup() { AndroidComposeTestRule( HomeActivityIntentTestRule( isJumpBackInCFREnabled = false, + // workaround for toolbar at top position by default + // remove with https://bugzilla.mozilla.org/show_bug.cgi?id=1917640 + shouldUseBottomToolbar = true, ), ) { it.activity } diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt index e53563509cf90..137393fbeba1e 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt @@ -5,7 +5,6 @@ package org.mozilla.fenix.ui import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.test.filters.SdkSuppress import mozilla.components.concept.engine.mediasession.MediaSession import org.junit.Rule import org.junit.Test @@ -41,7 +40,6 @@ class MediaNotificationTest : TestSetup() { val retryTestRule = RetryTestRule(3) // TestRail link: https://mozilla.testrail.io/index.php?/cases/view/1347033 - @SdkSuppress(maxSdkVersion = 30) @SmokeTest @Test fun verifyVideoPlaybackSystemNotificationTest() { @@ -77,7 +75,6 @@ class MediaNotificationTest : TestSetup() { } // TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2316010 - @SdkSuppress(maxSdkVersion = 30) @SmokeTest @Test fun verifyAudioPlaybackSystemNotificationTest() { diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/NoNetworkAccessStartupTests.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/NoNetworkAccessStartupTests.kt index 273e6ced20e71..724ffd6de4391 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/NoNetworkAccessStartupTests.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/NoNetworkAccessStartupTests.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.ui import androidx.core.net.toUri +import androidx.test.filters.SdkSuppress import org.junit.Rule import org.junit.Test import org.mozilla.fenix.customannotations.SmokeTest @@ -29,6 +30,7 @@ class NoNetworkAccessStartupTests : TestSetup() { // caution when making changes to it, so they don't block the builds // Based on STR from https://github.com/mozilla-mobile/fenix/issues/16886 // TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2240542 + @SdkSuppress(minSdkVersion = 34) @Test fun noNetworkConnectionStartupTest() { setNetworkEnabled(false) @@ -42,6 +44,7 @@ class NoNetworkAccessStartupTests : TestSetup() { // Based on STR from https://github.com/mozilla-mobile/fenix/issues/16886 // TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2240722 + @SdkSuppress(minSdkVersion = 34) @Test fun networkInterruptedFromBrowserToHomeTest() { val url = "example.com" @@ -60,6 +63,7 @@ class NoNetworkAccessStartupTests : TestSetup() { } // TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2240723 + @SdkSuppress(minSdkVersion = 34) @Test fun testPageReloadAfterNetworkInterrupted() { val url = "example.com" @@ -77,6 +81,7 @@ class NoNetworkAccessStartupTests : TestSetup() { } // TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2240721 + @SdkSuppress(minSdkVersion = 34) @SmokeTest @Test fun testSignInPageWithNoNetworkConnection() { diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt index 7f33fb2903e07..7b1b155c05348 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt @@ -74,6 +74,9 @@ class SearchTest : TestSetup() { isTCPCFREnabled = false, isWallpaperOnboardingEnabled = false, isLocationPermissionEnabled = SitePermissionsRules.Action.BLOCKED, + // workaround for toolbar at top position by default + // remove with https://bugzilla.mozilla.org/show_bug.cgi?id=1917640 + shouldUseBottomToolbar = true, ), ) { it.activity } diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt index c7a060ded7c34..6aa2531c790c8 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt @@ -623,7 +623,7 @@ class BrowserRobot { clearTextFieldItem(itemWithResId("username")) clickSuggestedLoginsButton() verifySuggestedUserName(composeTestRule, userName) - clickPageObject(itemWithResIdAndText("$packageName:id/username", userName)) + clickSuggestedLogin(composeTestRule, userName) clickPageObject(itemWithResId("togglePassword")) } } diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt index bba12abaa0fae..40ee4098d3e2d 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt @@ -12,6 +12,7 @@ import androidx.test.uiautomator.UiSelector import org.mozilla.fenix.helpers.Constants.RETRY_COUNT import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists +import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectIsGone import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText import org.mozilla.fenix.helpers.MatcherHelper.itemWithDescription import org.mozilla.fenix.helpers.MatcherHelper.itemWithText @@ -68,10 +69,8 @@ class NotificationRobot { } fun verifySystemNotificationDoesNotExist(notificationMessage: String) { - Log.i(TAG, "verifySystemNotificationDoesNotExist: Waiting for $waitingTime ms for notification: $notificationMessage to be gone") - mDevice.findObject(UiSelector().textContains(notificationMessage)).waitUntilGone(waitingTime) - Log.i(TAG, "verifySystemNotificationDoesNotExist: Waited for $waitingTime ms for notification: $notificationMessage to be gone") - assertUIObjectExists(itemContainingText(notificationMessage), exists = false) + mDevice.waitForWindowUpdate(packageName, waitingTime) + assertUIObjectIsGone(itemContainingText(notificationMessage), waitingTime = waitingTime) } fun verifyPrivateTabsNotification() { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 313b6db567e00..bcbad58918a07 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -1349,11 +1349,11 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { } @VisibleForTesting + @SuppressLint("NewApi") // The Android Q check is done in the systemGesturesInsets property getter internal fun collectOSNavigationTelemetry() { binding.root.doOnAttach { val systemGestureInsets = binding.root.systemGesturesInsets - @SuppressLint("NewApi") // The Android Q check is done in the systemGesturesInsets property getter val isUsingGesturesNavigation = (systemGestureInsets?.left ?: 0) > 0 && (systemGestureInsets?.right ?: 0) > 0 NavigationBar.osNavigationUsesGestures.set(isUsingGesturesNavigation) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 0237fd51a9e8f..6c0b9f28a24fa 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -1541,6 +1541,8 @@ abstract class BaseBrowserFragment : }, ) } + } else { + restoreBrowserToolbarAfterMicrosurveyPrompt(browserToolbar) } if (isToolbarAtBottom) { @@ -1744,6 +1746,7 @@ abstract class BaseBrowserFragment : } } + @Suppress("LongMethod") private fun initializeMicrosurveyPrompt() { val context = requireContext() val view = requireView() @@ -1799,6 +1802,8 @@ abstract class BaseBrowserFragment : }, ) } + } else { + restoreBrowserToolbarAfterMicrosurveyPrompt(browserToolbar) } if (isToolbarAtBottom) { @@ -1844,6 +1849,15 @@ abstract class BaseBrowserFragment : browserToolbar.elevation = 0.0f } + private fun restoreBrowserToolbarAfterMicrosurveyPrompt(browserToolbar: BrowserToolbar) { + val defaultBackground = ResourcesCompat.getDrawable( + resources, + R.drawable.toolbar_background, + context?.theme, + ) + browserToolbar.background = defaultBackground + } + private var currentMicrosurvey: MicrosurveyUIData? = null /** diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/MenuDialogFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/MenuDialogFragment.kt index 905ba3887021d..75426648cb748 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/MenuDialogFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/MenuDialogFragment.kt @@ -81,7 +81,7 @@ import org.mozilla.fenix.utils.exitSubmenu // three states instead of the expected two states required by design. private const val PEEK_HEIGHT = 460 private const val EXPANDED_MIN_RATIO = 0.0001f -private const val TOP_EXPANDED_OFFSET = 80 +private const val EXPANDED_OFFSET = 80 private const val HIDING_FRICTION = 0.9f /** @@ -111,7 +111,7 @@ class MenuDialogFragment : BottomSheetDialogFragment() { isFitToContents = true peekHeight = PEEK_HEIGHT.dpToPx(resources.displayMetrics) halfExpandedRatio = EXPANDED_MIN_RATIO - expandedOffset = TOP_EXPANDED_OFFSET + maxHeight = resources.displayMetrics.heightPixels - EXPANDED_OFFSET.dpToPx(resources.displayMetrics) state = BottomSheetBehavior.STATE_COLLAPSED hideFriction = HIDING_FRICTION } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/SaveSubmenu.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/SaveSubmenu.kt index b60d8454dd745..80191fb875136 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/SaveSubmenu.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/SaveSubmenu.kt @@ -37,6 +37,9 @@ internal fun SaveSubmenu( header = { SubmenuHeader( header = stringResource(id = R.string.browser_menu_save), + backButtonContentDescription = stringResource( + id = R.string.browser_menu_back_button_content_description, + ), onClick = onBackButtonClick, ) }, diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/header/SubmenuHeader.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/header/SubmenuHeader.kt index 87fa9ae3fd30c..271e026594d20 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/header/SubmenuHeader.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/menu/compose/header/SubmenuHeader.kt @@ -43,9 +43,7 @@ internal fun SubmenuHeader( IconButton( onClick = { onClick() }, modifier = Modifier.semantics { - if (backButtonContentDescription != null) { - this.contentDescription = backButtonContentDescription - } + backButtonContentDescription?.also { this.contentDescription = it } }, ) { Icon( diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/compose/BottomSheetHandle.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/compose/BottomSheetHandle.kt index 8e509354e1128..b8cad648b019d 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/compose/BottomSheetHandle.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/compose/BottomSheetHandle.kt @@ -15,8 +15,10 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.onClick +import androidx.compose.ui.semantics.role import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp import org.mozilla.fenix.R @@ -42,6 +44,7 @@ fun BottomSheetHandle( modifier = modifier .height(dimensionResource(id = R.dimen.bottom_sheet_handle_height)) .semantics(mergeDescendants = true) { + role = Role.Button this.contentDescription = contentDescription onClick { onRequestDismiss() diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 3f33eecd804a3..39226bcd1cfd6 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -631,10 +631,8 @@ class HomeFragment : Fragment() { if (!activity.isMicrosurveyPromptDismissed.value && !context.settings().shouldShowNavigationBarCFR ) { - currentMicrosurvey.let { - if (it == null) { - binding.bottomBarShadow.visibility = View.VISIBLE - } else { + currentMicrosurvey + ?.let { if (isToolbarAtBottom) { updateToolbarViewUIForMicrosurveyPrompt() } @@ -665,7 +663,8 @@ class HomeFragment : Fragment() { }, ) } - } + } else { + binding.bottomBarShadow.visibility = View.VISIBLE } if (isToolbarAtBottom) { @@ -835,10 +834,8 @@ class HomeFragment : Fragment() { context.shouldAddNavigationBar() && context.settings().shouldShowNavigationBarCFR if (!activity.isMicrosurveyPromptDismissed.value && !shouldShowNavBarCFR) { - currentMicrosurvey.let { - if (it == null) { - binding.bottomBarShadow.visibility = View.VISIBLE - } else { + currentMicrosurvey + ?.let { if (isToolbarAtTheBottom) { updateToolbarViewUIForMicrosurveyPrompt() } @@ -867,7 +864,8 @@ class HomeFragment : Fragment() { }, ) } - } + } else { + binding.bottomBarShadow.visibility = View.VISIBLE } if (isToolbarAtTheBottom) { diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/messaging/CustomAttributeProvider.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/messaging/CustomAttributeProvider.kt index 0c4eed4f32adc..5797311d40792 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/messaging/CustomAttributeProvider.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/messaging/CustomAttributeProvider.kt @@ -16,6 +16,7 @@ import org.mozilla.fenix.components.metrics.UTMParams.Companion.UTM_CONTENT import org.mozilla.fenix.components.metrics.UTMParams.Companion.UTM_MEDIUM import org.mozilla.fenix.components.metrics.UTMParams.Companion.UTM_SOURCE import org.mozilla.fenix.components.metrics.UTMParams.Companion.UTM_TERM +import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import java.text.SimpleDateFormat import java.util.Calendar @@ -92,6 +93,11 @@ object CustomAttributeProvider : JexlAttributeProvider { "android_version" to android.os.Build.VERSION.SDK_INT, "is_fxa_signed_in" to settings.signedInFxaAccount, + + "fxa_connected_devices" to ( + context.components.backgroundServices.syncStore.state + .constellationState?.otherDevices?.size ?: 0 + ), ), ) } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index 4816c3c908f2f..c14f571d94103 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -949,10 +949,9 @@ class Settings(private val appContext: Context) : PreferencesHolder { default = true, ) - var shouldUseBottomToolbar by lazyFeatureFlagPreference( + var shouldUseBottomToolbar by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_toolbar_bottom), - featureFlag = true, - default = { shouldDefaultToBottomToolbar() }, + default = false, ) val toolbarPosition: ToolbarPosition @@ -996,18 +995,6 @@ class Settings(private val appContext: Context) : PreferencesHolder { return touchExplorationIsEnabled || switchServiceIsEnabled } - val toolbarPositionTop: Boolean - get() = FxNimbus.features.toolbar.value().toolbarPositionTop - - /** - * Checks if we should default to bottom toolbar. - */ - fun shouldDefaultToBottomToolbar(): Boolean { - // Default accessibility users to top toolbar - return (!touchExplorationIsEnabled && !switchServiceIsEnabled) && - !toolbarPositionTop - } - fun getDeleteDataOnQuit(type: DeleteBrowsingDataOnQuitType): Boolean = preferences.getBoolean(type.getPreferenceKey(appContext), false) diff --git a/mobile/android/fenix/app/src/main/res/values-es/strings.xml b/mobile/android/fenix/app/src/main/res/values-es/strings.xml index 6e0ac60295d4f..d771643055c72 100644 --- a/mobile/android/fenix/app/src/main/res/values-es/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-es/strings.xml @@ -49,15 +49,6 @@ Seleccionada - - - Guardado recientemente - - Mostrar todos los marcadores guardados - - - Eliminar - Marcadores @@ -120,7 +111,18 @@ Navega más rápido con la nueva navegación - Esta barra se oculta a medida que te desplazas hacia abajo para tener más espacio de navegación. + Esta barra se oculta a medida que te desplazas hacia abajo para tener más espacio de navegación. + + + En un sitio web, esta barra se oculta a medida que te desplazas hacia abajo para tener más espacio de navegación. + + Mantén pulsadas las flechas para saltar entre las páginas del historial de esta pestaña. + + + + Nuevo: flechas hacia atrás y hacia adelante con un solo toque + + Disfruta de una navegación más rápida y siempre al alcance de la mano. Se necesita acceso a la cámara. Ve a la configuración de Android, pulsa Permisos y luego Permitir. @@ -204,10 +206,20 @@ Detener Extensiones + + Haz %s tuyo + + Las extensiones mejoran tu navegación, desde cambiar la apariencia y el rendimiento de %s hasta mejorar la privacidad y la seguridad. + + Saber más Gestionar extensiones Descubrir más extensiones + + Desactivado temporalmente Información de la cuenta @@ -226,6 +238,8 @@ Agregar a la pantalla de Inicio Añadir a la pantalla de inicio… + + Es posible que los dispositivos Xiaomi requieran de permisos adicionales para añadir accesos directos a la pantalla de inicio. Por favor, verifica tus ajustes. Resincronizar @@ -262,6 +276,8 @@ Personalizar vista de lectura + + Personalizar vista de lectura Añadir @@ -290,12 +306,22 @@ Cambiar al sitio de escritorio + + Cambiar al sitio móvil Herramientas + + Volver al menú principal + + Vista de lectura, traducir, imprimir, compartir, abrir aplicación + + Vista de lectura, imprimir, compartir, abrir aplicación Guardar + + Añadir marcador, acceso directo, inicio, colección, PDF Añadir esta página a marcadores @@ -314,6 +340,16 @@ Imprimir… + + Salir de %1$s + + + + Nuevo: menú simplificado + + Encuentra lo que necesitas más rápido, desde navegación privada hasta acciones para guardar contenido. + No hay extensiones aquí @@ -410,12 +446,12 @@ - Aviso de privacidad de Firefox + Aviso de privacidad de Firefox Nos encanta mantenerte a salvo - Descubre por qué millones aman Firefox + Descubre por qué millones aman Firefox Navegación segura con más opciones @@ -437,17 +473,20 @@ Mantén todo cifrado cuando pases de un dispositivo a otro - Tras iniciar sesión y sincronizar, estás más seguro. Firefox cifra tus contraseñas, marcadores y más. + Tras iniciar sesión y sincronizar, estás más seguro. Firefox cifra tus contraseñas, marcadores y más. + + Firefox cifra tus contraseñas, marcadores y más cuando estás sincronizado. Iniciar sesión Ahora no - Las notificaciones te ayudan a estar más seguro con Firefox + Las notificaciones te ayudan a estar más seguro con Firefox - Envía pestañas de forma segura entre tus dispositivos y descubre otras funciones de privacidad en Firefox. + Envía pestañas de forma segura entre tus dispositivos y descubre otras funciones de privacidad en Firefox. Activar notificaciones @@ -455,13 +494,13 @@ - Prueba el widget de búsqueda de Firefox + Prueba el widget de búsqueda de Firefox - Con Firefox en tu pantalla de inicio, tendrás fácil acceso al navegador que prioriza la privacidad y bloquea los rastreadores entre sitios. + Con Firefox en tu pantalla de inicio, tendrás fácil acceso al navegador que prioriza la privacidad y bloquea los rastreadores entre sitios. - Añadir widget de Firefox + Añadir widget de Firefox Ahora no @@ -504,9 +543,9 @@ Preferencias de la barra de direcciones - Barra de direcciones - Sugerencias de Firefox + Barra de direcciones - Sugerencias de Firefox - Saber más sobre Firefox Suggest + Saber más sobre Firefox Suggest Calificar en Google Play Cuenta - - Barra de herramientas Ubicación de la barra de direcciones @@ -621,8 +658,6 @@ Reconectar para reanudar la sincronización Idioma - - Traducción Traducciones @@ -720,8 +755,6 @@ Volver a esta pestaña - - Marcadores recientes Marcadores Nuevas extensiones disponibles ahora - Descubre más de 100 nuevas extensiones que te permiten personalizar Firefox. + Descubre más de 100 nuevas extensiones que te permiten personalizar Firefox. Explorar extensiones @@ -840,7 +873,7 @@ Pestañas recibidas - Notificaciones para pestañas recibidas de otros dispositivos Firefox. + Notificaciones para pestañas recibidas de otros dispositivos Firefox. Pestaña recibida @@ -914,8 +947,6 @@ Arrastrar para actualizar Desplazar para ocultar la barra de herramientas - - Deslizar la barra hacia los lados para cambiar de pestaña Deslizar la barra de herramientas hacia arriba para abrir pestañas @@ -1109,7 +1140,7 @@ Nombre de la colección - Renombrar + Renombrar Eliminar @@ -1184,6 +1215,8 @@ Agregar carpeta ¡Marcador guardado! + + Guardado en “%s” EDITAR @@ -1218,8 +1251,12 @@ URL CARPETA + + Guardar en NOMBRE + + Nombre Agregar carpeta @@ -1243,6 +1280,17 @@ Introducir términos de búsqueda + + Ir a la página anterior + + Añadir una carpeta nueva + + Cerrar marcadores + + Buscar en marcadores + + Menú de elementos para %s + Ir a Ajustes @@ -1427,7 +1475,7 @@ Conectar otro dispositivo - Para enviar una pestaña, inicia sesión en Firefox al menos en otro dispositivo. + Para enviar una pestaña, inicia sesión en Firefox al menos en otro dispositivo. Entendido @@ -1468,10 +1516,10 @@ - Firefox es rápido y privado + Firefox es rápido y privado - Convertir Firefox en tu navegador predeterminado + Convertir Firefox en tu navegador predeterminado Prueba la navegación privada - Ayúdanos a mejorar Firefox respondiendo a una pequeña encuesta. + Ayúdanos a mejorar Firefox respondiendo a una pequeña encuesta. Realizar encuesta @@ -1541,7 +1589,7 @@ Eliminar - Accediendo a pantalla completa + Accediendo a pantalla completa URL copiada @@ -1644,7 +1692,7 @@ Escanear el código - https://firefox.com/pair]]> + https://firefox.com/pair]]> Listo para escanear @@ -1652,7 +1700,7 @@ Usa el correo electrónico - Crea una para sincronizar Firefox entre dispositivos.]]> + Crea una para sincronizar Firefox entre dispositivos.]]> %s dejará de sincronizarse con tu cuenta, pero no se borrarán los datos de navegación de este dispositivo. @@ -1716,7 +1764,9 @@ Criptomineros - Detectores de huellas digitales + Detectores de huellas digitales + + Detectores de huellas digitales conocidos Detalles @@ -1740,9 +1790,11 @@ Impide que los scripts maliciosos obtengan acceso a tu dispositivo para extraer moneda digital. - Detectores de huellas digitales + Detectores de huellas digitales + + Impide que se recopilen datos que identifiquen de manera única a tu dispositivo y que pueden usarse para fines de rastreo. - Impide que se recopilen datos que identifiquen de manera única a tu dispositivo y que pueden usarse para fines de rastreo. + Impide que se recopilen datos identificables acerca de tu dispositivo que puedan usarse para fines de rastreo. Contenido de rastreo @@ -1768,6 +1820,12 @@ Borra las cookies establecidas por redirecciones a sitios web de rastreo conocidos. + + Detectores de huellas digitales sospechosos + + Activa la protección de huellas digitales para evitar rastreadores sospechosos. + + Detectores de huellas digitales conocidos Algunos rastreadores marcados debajo han sido parcialmente desbloqueados en esta página porque ha interactuado con ellos*. @@ -2179,7 +2237,7 @@ Por favor, activa la sincronización de pestañas. - No tienes ninguna pestaña abierta en Firefox en tus otros dispositivos. + No tienes ninguna pestaña abierta en Firefox en tus otros dispositivos. Ver una lista de pestañas de tus otros dispositivos. @@ -2207,8 +2265,10 @@ Nombre Nombre de acceso directo + + URL de acceso directo - Aceptar + Aceptar Cancelar @@ -2219,6 +2279,17 @@ Patrocinado + + Editar + + Editar acceso directo + + Guardar + + Introduce una URL válida + + URL + Pestañas inactivas @@ -2234,7 +2305,7 @@ ¿Cerrar automáticamente después de un mes? - Firefox puede cerrar pestañas que no has visto durante el último mes. + Firefox puede cerrar pestañas que no has visto durante el último mes. ACTIVAR EL CIERRE AUTOMÁTICO @@ -2243,7 +2314,7 @@ - Firefox Suggest + Firefox Suggest Búsqueda de Google @@ -2254,7 +2325,7 @@ Cambia tu navegador predeterminado - Configura enlaces de sitios web, correos electrónicos y mensajes para que se abran automáticamente en Firefox. + Configura enlaces de sitios web, correos electrónicos y mensajes para que se abran automáticamente en Firefox. Eliminar @@ -2278,7 +2349,7 @@ Impulsado por %s. - Parte de la familia Firefox. %s + Parte de la familia Firefox. %s Saber más @@ -2424,7 +2495,7 @@ Abrir el verificador de reseñas - Beta + Beta Abrir el verificador de reseñas @@ -2615,7 +2686,9 @@ - Descargar idiomas + Descargar idiomas + + Descargar idiomas Descarga idiomas completos para traducciones más rápidas y para traducir sin conexión. %1$s @@ -2636,12 +2709,14 @@ Eliminar todos los idiomas Eliminar - - En curso + + En curso + + Detener la descarga de %1$s (%2$s) Descargar - - Seleccionado No se han podido cargar los idiomas. Inténtalo de nuevo más tarde. @@ -2669,6 +2744,14 @@ Cancelar + + ¿Cancelar la descarga de %1$s? + + + + No + Descargamos idiomas parcialmente a la caché para mantener las traducciones privadas. - - Descargamos idiomas parcialmente para mantener las traducciones privadas. Descargar siempre en modo de ahorro de datos @@ -2702,8 +2783,6 @@ Número de pestañas - Activa - Activo Inactiva @@ -2737,22 +2816,16 @@ - Ayúdanos a mejorar Firefox. Solo te llevará un minuto. + Ayúdanos a mejorar Firefox. Solo te llevará un minuto. Continuar - Completa esta encuesta - Por favor, completa la encuesta - Aviso de privacidad - Aviso de privacidad Enviar - - Cerrar Encuesta completada @@ -2770,15 +2843,21 @@ No lo uso + + No uso la búsqueda en Firefox - ¿Estás satisfecho con la página de inicio de Firefox? + ¿Estás satisfecho con la página de inicio de Firefox? - Ayuda a mejorar la impresión en Firefox. Solo te llevará un segundo - - ¿Cómo estás de satisfecho con la impresión en Firefox? + Ayuda a mejorar la impresión en Firefox. Solo te llevará un segundo + + ¿Cómo estás de satisfecho con la impresión en Firefox? + + ¿Cómo de satisfecho estás con tu página de inicio de Firefox? + + ¿Cómo estás de satisfecho con la experiencia de búsqueda en Firefox? - Logo de Firefox + Logo de Firefox Icono de la función de encuesta @@ -2797,4 +2876,27 @@ Añade una conexión falsa para este dominio Eliminar inicio de sesión con nombre de usuario %s + + + + Herramientas CFR + + Restablecer CFRs + + + + Para salir de pantalla completa, arrastra desde arriba y usa el gesto hacia atrás + + Para salir de la pantalla completa, arrastra desde arriba y pulsa atrás + + + + Arrastra desde la parte superior y usa el gesto hacia atrás para salir + + + Arrastra desde la parte superior y presiona atrás para salir + + + + BETA diff --git a/mobile/android/fenix/app/src/main/res/values-fy-rNL/strings.xml b/mobile/android/fenix/app/src/main/res/values-fy-rNL/strings.xml index 8bf4cc3454c67..8be43a334df83 100644 --- a/mobile/android/fenix/app/src/main/res/values-fy-rNL/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-fy-rNL/strings.xml @@ -238,6 +238,8 @@ Tafoegje oan startskerm Tafoegje oan startskerm… + + Xiaomi-apparaten hawwe mooglik ekstra tastimmingen nedich om fluchkeppelingen oan it startskerm ta te foegjen. Kontrolearje jo ynstellingen. Opnij syngronisearje @@ -577,13 +579,9 @@ Annulearje - Oanfraach ferstjoere - - Freegje om website ta te foegjen + Oanfraach ferstjoere - Stipe oanfreegje foar dizze side? - - %1$s freegje om cookies automatysk te wegerjen + Stipe oanfreegje foar dizze side? Oanfraach ferstjoerd @@ -591,18 +589,14 @@ Stipe-oanfraach ferstjoerd - Website wurdt op dit stuit net stipe - - Website net stipe + Website wurdt op dit stuit net stipe Blokkearring fan cookiebanners ynskeakelje foar %1$s? Blokkearring fan cookiebanners útskeakelje foar %1$s? - %1$s kin cookiefersiken op dizze website net automatysk wegerje. Jo kinne in oanfraach stjoere om dizze website yn de takomst te stypjen. + %1$s kin cookiefersiken op dizze website net automatysk wegerje. Jo kinne in oanfraach stjoere om dizze website yn de takomst te stypjen. - - Wy kinne cookie-pop-ups op dizze website op dit stuit net automatysk wegerje. Skeakelje dit út en %1$s sil cookies wiskje en dizze website opnij lade. Dit kin jo ôfmelde of winkelweintsjes leegje. @@ -1244,8 +1238,12 @@ URL MAP + + Besparje yn NAMME + + Namme Map tafoegje @@ -2812,14 +2810,18 @@ Dizze analyze sil jo allinnich helpe om de beoardielingskwaliteit te beoardielen Ik brûk it net + + Ik brûk de sykfunksje op Firefox net Hoe tefreden binne jo mei jo ûnderfining fan de Firefox-Startside? Help it ôfdrukken yn Firefox better te meitsjen. It duorret mar in amerijke - + Hoe tefreden binne jo mei it ôfdrukken yn Firefox? - + Hoe tefreden binne jo mei jo ûnderfining fan de Firefox-Startside? + + Hoe tefreden binne jo mei de sykûnderfining yn Firefox? Firefox-logo @@ -2850,9 +2852,16 @@ Dizze analyze sil jo allinnich helpe om de beoardielingskwaliteit te beoardielen - Sleep fan de boppekant ôf en brûk it tebek-gebear om it folslein skerm ôf te sluten + Sleep fan de boppekant ôf en brûk it tebek-gebear om it folslein skerm ôf te sluten - Sleep fan de boppekant ôf en druk op tebek om it folslein skerm ôf te sluten + Sleep fan de boppekant ôf en druk op tebek om it folslein skerm ôf te sluten + + + + Sleep fan de boppekant & brûk it gebear werom om ôf te sluten + + + Sleep fan de boppekant & druk it gebear werom om ôf te sluten diff --git a/mobile/android/fenix/app/src/main/res/values-kab/strings.xml b/mobile/android/fenix/app/src/main/res/values-kab/strings.xml index fc4bfdcc08e81..197ab57eca709 100644 --- a/mobile/android/fenix/app/src/main/res/values-kab/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-kab/strings.xml @@ -294,6 +294,8 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Uɣal ɣer usmel aziraz Ifecka + + Uɣal ɣer wumuɣ agejdan Askar n tɣuri, suqel, siggez, bḍu, ldi deg usnas @@ -326,6 +328,10 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara The first parameter is the name of the app defined in app_name (for example: Fenix). --> Ffeɣ si %1$s + + + Amaynut: Umuɣ afessas + Ulac isiɣzaf dagi @@ -423,12 +429,12 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara - Tasertit tabaḍnit n Firefox + Tasertit tabaḍnit n Firefox Nḥemmel ad teqqimeḍ d aɣellsan - Wali ayɣer aṭas i iḥemmlen Firefox + Wali ayɣer aṭas i iḥemmlen Firefox Tunigin tusligt s wugar n yifranen @@ -450,20 +456,20 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Mmesten iman-ik s ttawil n uwgelhen mi ara tɛeddiḍ seg yibenk ɣer wayeḍ - Mi ara teqqneḍ rnu ad tremdeḍ amtawi, taɣellist tettwaseǧhed. Firefox yettwgelhin awalen-ik uffiren, ticraḍ n yisebtar, akked wayen niḍen. + Mi ara teqqneḍ rnu ad tremdeḍ amtawi, taɣellist tettwaseǧhed. Firefox yettwgelhin awalen-ik uffiren, ticraḍ n yisebtar, akked wayen niḍen. - Firefox ittewgelhin awalen uffiren, ticraḍ n yisebtar, d wugar mi ara tremdeḍ amtawi. + Firefox ittewgelhin awalen uffiren, ticraḍ n yisebtar, d wugar mi ara tremdeḍ amtawi. Kcem Mačči tura - Ilɣa ad ak-ɛawnen ad teqqimeḍ d aɣellsan s Firefox + Ilɣa ad ak-ɛawnen ad teqqimeḍ d aɣellsan s Firefox - Azen s wudem aɣellsan accaren seg yibenk ɣer wayeḍ, tesnirmeḍ timahilin timaynutin n ummesten n tudert tabaḍnit deg Firefox. + Azen s wudem aɣellsan accaren seg yibenk ɣer wayeḍ, tesnirmeḍ timahilin timaynutin n ummesten n tudert tabaḍnit deg Firefox. Rmed ilɣa @@ -471,13 +477,13 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara - Ɛreḍ iwiǧit n unadi n Firefox + Ɛreḍ iwiǧit n unadi n Firefox - Er Firefox ɣef ugdil agejdan i unekcum uzrib ɣer yiminig yebnan ɣef uqader n tudert tabaḍnit, iyessewḥalen ineḍfaren ger yismal. + Er Firefox ɣef ugdil agejdan i unekcum uzrib ɣer yiminig yebnan ɣef uqader n tudert tabaḍnit, iyessewḥalen ineḍfaren ger yismal. - Rnu awiǧit n Firefox + Rnu awiǧit n Firefox Mačči tura @@ -518,9 +524,9 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ismenyifen i ufeggag n tansiwin - Afeggag n tansiwin - Firefox isumer + Afeggag n tansiwin - Firefox isumer - Issin ugar ɣef Firefox Suggest + Issin ugar ɣef Firefox Suggest Mudd tazmilt deg Google Play Amiḍan - - Afeggag n yifecka Adig n ufeggag n tansa @@ -790,7 +794,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Llan akka tura isiɣzaf imaynuten - Snirem ugar n 100 yisiɣzaf imaynuten ara ak·akem-yeǧǧen ad tsagneḍ Firefox. + Snirem ugar n 100 yisiɣzaf imaynuten ara ak·akem-yeǧǧen ad tsagneḍ Firefox. Snirem isiɣzaf @@ -857,7 +861,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Accaren yettwaremsen - Ilɣa n yiccaren yettwaremsen seg Firefox ɣef yibenlan-nniḍen. + Ilɣa n yiccaren yettwaremsen seg Firefox ɣef yibenlan-nniḍen. Iccaren yettwarmesen @@ -930,8 +934,6 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Drurem i wakken ad teffreḍ agalis n yifecka - - Err agalis n yifecka deg tama i ubeddel n waccaren Err agalis n yifecka deg usawen i twaledyawt n waccaren @@ -1202,6 +1204,8 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Rnu akaram Tacreṭ n usebter tettwasekles! + + Yettwasekles deg “%s” ẒREG @@ -1236,8 +1240,12 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara URL AKARAM + + Sekles deg ISEM + + Isem Rnu akaram @@ -1446,7 +1454,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Qqen ibenk-nniḍen - Akken ad tazneḍ iccer, qqen ɣer Firefox xarsum ɣef yiwen n yibenk. + Akken ad tazneḍ iccer, qqen ɣer Firefox xarsum ɣef yiwen n yibenk. Awi-t @@ -1487,10 +1495,10 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara - Firefox d arurad, d uslig + Firefox d arurad, d uslig - Err Firefox d iminig-ik amezwer + Err Firefox d iminig-ik amezwer Ɛreḍ tunigin tusligt @@ -1513,7 +1521,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara - Ttxil-k ɛawen Firefox ad igerrez ugar s uɛemmer n uḥedqus-a. + Ttxil-k ɛawen Firefox ad igerrez ugar s uɛemmer n uḥedqus-a. Eg aḥedqis @@ -1659,7 +1667,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Semḍen tangalt - https://firefox.com/pair]]> + https://firefox.com/pair]]> Ihegga i uḍummu @@ -1667,7 +1675,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Seqdec tansa n yimayl deg umḍiq-is - Rnu yiwen i umtaw n Firefox gar yibenkan.]]> + Rnu yiwen i umtaw n Firefox gar yibenkan.]]> %s ad iseḥbes amtawi d umiḍan-inek, acukan ur ittekkes ara isefka-inek n tunigin seg uselkim-a. @@ -2202,7 +2210,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ma ulac aɣilif, rmed amtawi n waccaren. - Ulac ɣur-k accarren yeldin deg Firefox deg yibenkan-inek-nniḍen. + Ulac ɣur-k accarren yeldin deg Firefox deg yibenkan-inek-nniḍen. Wali tabdart n waccaren seg yibenkan-ik-nniḍen. @@ -2272,7 +2280,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Amdal awurman seld yiwen wayyur? - Firefox izmer ad imdel accaren i twalaḍ aggur iɛeddan. + Firefox izmer ad imdel accaren i twalaḍ aggur iɛeddan. RMED AMDAL AWURMAN @@ -2281,7 +2289,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara - Firefox Suggest + Firefox Suggest Anadi deg Google @@ -2292,7 +2300,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Beddel iminig-ik·im amezwer - Sbadu iseɣwan seg yismal web, seg yimaylen d yiznan i twaledyawt s wudem awurman deg Firefox. + Sbadu iseɣwan seg yismal web, seg yimaylen d yiznan i twaledyawt s wudem awurman deg Firefox. Kkes @@ -2316,7 +2324,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ddaw leɛnaya n %s. - D aḥric seg twacult Firefox. %s + D aḥric seg twacult Firefox. %s Issin ugar @@ -2682,8 +2690,6 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Kkes akk tutlayin Kkes - - Iteddu Iteddu Nessadar-d tutlayin s wudem abruyan deg tkatut tuffirt i wakken ad qqiment tsuqilin d tusligin. - - Nessadar-d tutlayin s wudem abruyan i wakken ad qqiment tsuqilin d tusligin. Sader yal tikkelt deg uskar n usekles n yisefka @@ -2793,17 +2797,13 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara - Ԑawen-aɣ ad nesnerni Firefox ugar. Aya ad yeṭṭef cwiṭ n wakud. + Ԑawen-aɣ ad nesnerni Firefox ugar. Aya ad yeṭṭef cwiṭ n wakud. Kemmel - Smed aḥedqis-a - Ttxil-k smed aḥedqis - Tasertit n tbaḍnit - Tasertit n tbaḍnit Azen @@ -2825,17 +2825,19 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ur t-sseqdaceɣ ara + + Ur sseqdaceɣ ara anadi ɣef Firefox - Tumreḍ s usebtar-ik agejdan n Firefox? + Tumreḍ s usebtar-ik agejdan n Firefox? - Ɛawen-aɣ ad nesnerni asiggez deg Firefox. Aya ad yeṭṭef cwiṭ kan n wakud - - Tumreḍ s usiggez deg Firefox? - - Tumreḍ s usebtar-ik agejdan n Firefox? + Ɛawen-aɣ ad nesnerni asiggez deg Firefox. Aya ad yeṭṭef cwiṭ kan n wakud + + Tumreḍ s usiggez deg Firefox? + + Tumreḍ s usebtar-ik agejdan n Firefox? - Alugu Firefox + Alugu Firefox Tignit n tmahilt n uḥedqis @@ -2863,9 +2865,9 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara - i wakken ad teffɣeḍ seg ugdil aččura, zuɣer seg usawen syen seqdec asilif n tuɣalin + i wakken ad teffɣeḍ seg ugdil aččura, zuɣer seg usawen syen seqdec asilif n tuɣalin - i wakken ad teffɣeḍ seg ugdil aččura, zuɣer seg usawen syen sit ɣef uɣal + i wakken ad teffɣeḍ seg ugdil aččura, zuɣer seg usawen syen sit ɣef uɣal diff --git a/mobile/android/fenix/app/src/main/res/values-skr/strings.xml b/mobile/android/fenix/app/src/main/res/values-skr/strings.xml index 6d26264610b5e..9c115a6468ef0 100644 --- a/mobile/android/fenix/app/src/main/res/values-skr/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-skr/strings.xml @@ -112,6 +112,9 @@ نویں نیویگیشݨ نال تکھیرا براؤز کرو + + + نواں: ہک ٹیپ پچھوں تے اڳوں تیر تکھیری نیویگیشن توں لطف اندوز تھیوو جہڑی ہمیشہ تہاݙے ݙوݙیاں تے ہوندی ہے۔ diff --git a/mobile/android/fenix/app/src/main/res/values-th/strings.xml b/mobile/android/fenix/app/src/main/res/values-th/strings.xml index 8e176f597a3ee..8f0d5c257d157 100644 --- a/mobile/android/fenix/app/src/main/res/values-th/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-th/strings.xml @@ -303,9 +303,15 @@ เครื่องมือ กลับสู่เมนูหลัก + + มุมมองผู้อ่าน, แปล, พิมพ์, แบ่งปัน, เปิดแอป + + มุมมองผู้อ่าน, พิมพ์, แบ่งปัน, เปิดแอป บันทึก + + เพิ่มที่คั่นหน้า, ทางลัด, หน้าแรก, คอลเลกชัน, PDF เพิ่มที่คั่นหน้าสำหรับหน้านี้ @@ -567,13 +573,9 @@ ยกเลิก - ส่งคำขอ - - ขอให้เพิ่มเว็บไซต์ + ส่งคำขอ - ขอการรองรับไซต์นี้ไหม? - - ขอให้ %1$s ปฏิเสธคุกกี้โดยอัตโนมัติ + ขอการรองรับไซต์นี้ไหม? ส่งคำขอแล้ว @@ -582,18 +584,14 @@ ส่งคำขอรองรับแล้ว - ไม่รองรับไซต์ในขณะนี้ - - ไม่รองรับเว็บไซต์นี้ + ไม่รองรับไซต์ในขณะนี้ ต้องการเปิดตัวปิดกั้นแบนเนอร์คุกกี้สำหรับ %1$s หรือไม่? ต้องการปิดตัวปิดกั้นแบนเนอร์คุกกี้สำหรับ %1$s หรือไม่? - %1$s ไม่สามารถปฏิเสธคำขอคุกกี้โดยอัตโนมัติบนไซต์นี้ คุณสามารถส่งคำขอให้รองรับไซต์นี้ในอนาคตได้ + %1$s ไม่สามารถปฏิเสธคำขอคุกกี้โดยอัตโนมัติบนไซต์นี้ คุณสามารถส่งคำขอให้รองรับไซต์นี้ในอนาคตได้ - - เราไม่สามารถปฏิเสธป๊อปอัปคุกกี้โดยอัตโนมัติบนเว็บไซต์นี้ได้ในขณะนี้ หลังจากปิดแล้ว %1$s จะล้างคุกกี้และโหลดไซต์นี้ใหม่ การกระทำนี้อาจนำคุณลงชื่อออกหรือล้างรถเข็นช็อปปิ้ง @@ -1239,8 +1237,12 @@ URL โฟลเดอร์ + + บันทึกใน ชื่อ + + ชื่อ เพิ่มโฟลเดอร์ @@ -2811,9 +2813,9 @@ คุณพึงพอใจกับหน้าแรกของ Firefox มากน้อยเพียงใด? ช่วยเราทำให้ระบบการพิมพ์ใน Firefox ดีขึ้น โดยสละเวลาเพียงนาทีเดียว - + คุณพึงพอใจกับระบบการพิมพ์ใน Firefox มากน้อยเพียงใด? - + คุณพึงพอใจกับหน้าแรกของ Firefox มากน้อยเพียงใด? @@ -2845,9 +2847,9 @@ - หากต้องการออกจากการแสดงเต็มจอ ให้ลากจากด้านบนแล้วใช้ท่าทางย้อนกลับ + หากต้องการออกจากการแสดงเต็มจอ ให้ลากจากด้านบนแล้วใช้ท่าทางย้อนกลับ - หากต้องการออกจากการแสดงเต็มจอ ให้ลากจากด้านบนแล้วกดย้อนกลับ + หากต้องการออกจากการแสดงเต็มจอ ให้ลากจากด้านบนแล้วกดย้อนกลับ diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt index ff857fcdff9ae..e983189817a27 100644 --- a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt +++ b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt @@ -863,15 +863,6 @@ class SettingsTest { assertTrue(actual) } - @Test - fun `GIVEN toolbarPositionTop is false, touchExplorationIsEnabled is true THEN shouldDefaultToBottomToolbar returns false`() { - val settings = spyk(settings) - every { settings.toolbarPositionTop } returns true - every { settings.touchExplorationIsEnabled } returns true - - assertEquals(false, settings.shouldDefaultToBottomToolbar()) - } - @Test fun `GIVEN Https-only mode is disabled THEN the engine mode is HttpsOnlyMode#DISABLED`() { settings.shouldUseHttpsOnly = false diff --git a/mobile/android/fenix/build.gradle b/mobile/android/fenix/build.gradle index ce41a3bb0ade2..b714cf70e7e2d 100644 --- a/mobile/android/fenix/build.gradle +++ b/mobile/android/fenix/build.gradle @@ -38,7 +38,7 @@ buildscript { ext { detekt_plugin = Versions.detekt ksp_plugin = Versions.ksp_plugin - protobuf_plugin = FenixVersions.protobuf_plugin + protobuf_plugin = Versions.protobuf_plugin python_envs_plugin = Versions.python_envs_plugin } } diff --git a/mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt b/mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt index 5f19d34b9fd24..b7f722aa1fdeb 100644 --- a/mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt +++ b/mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt @@ -20,17 +20,10 @@ object FenixVersions { const val installreferrer = "2.2" const val mockk = "1.13.12" - - // keep in sync with the versions used in AS. - const val protobuf = "3.21.10" - const val protobuf_plugin = "0.9.4" } @Suppress("unused") object FenixDependencies { - const val protobuf_javalite = "com.google.protobuf:protobuf-javalite:${FenixVersions.protobuf}" - const val protobuf_compiler = "com.google.protobuf:protoc:${FenixVersions.protobuf}" - const val adjust = "com.adjust.sdk:adjust-android:${FenixVersions.adjust}" const val installreferrer = "com.android.installreferrer:installreferrer:${FenixVersions.installreferrer}" diff --git a/mobile/android/focus-android/app/src/main/res/values-co/strings.xml b/mobile/android/focus-android/app/src/main/res/values-co/strings.xml index bfeb0f57a5db0..c991b1008d00c 100644 --- a/mobile/android/focus-android/app/src/main/res/values-co/strings.xml +++ b/mobile/android/focus-android/app/src/main/res/values-co/strings.xml @@ -123,23 +123,23 @@ - Circà in Focus + Circà in Focus - Circà in Klar + Circà in Klar - Circà in Focus Beta + Circà in Focus Beta - Circà in Focus Nightly + Circà in Focus Nightly - %1$s vi aiuta à stà à e cumande.

+ %1$s vi aiuta à stà à e cumande.

Impiegatelu cum’è un navigatore privatu :

  • Fate ricerche è navigate cù l’appiecazione
  • @@ -609,9 +609,12 @@ Squassà a cronolugia di navigazione + + Chjode l’altre unghjette + - Scaricà Firefox + Scaricà Firefox @@ -623,23 +626,23 @@ - Mozilla Public License è d’altre licenze di tipu fonte aperta.]]> + Mozilla Public License è d’altre licenze di tipu fonte aperta.]]> - quì.]]> + quì.]]> - licenze libere è fonte aperta.]]> + licenze libere è fonte aperta.]]> - GNU General Public License v3, è dispunibule quì.]]> + GNU General Public License v3, è dispunibule quì.]]> Nome d’utilizatore @@ -830,7 +833,7 @@ Studii - Firefox pò installà è lancià studii di quandu in quandu. + Firefox pò installà è lancià studii di quandu in quandu. Per sapene di più @@ -1039,7 +1042,7 @@ - Per sapene di più

    Cambiate sta definizione in Preferenze > Vita privata è sicurità > Sicurità.]]>
    diff --git a/mobile/android/focus-android/app/src/main/res/values-cy/strings.xml b/mobile/android/focus-android/app/src/main/res/values-cy/strings.xml index 49124c5af49be..b501686010e46 100644 --- a/mobile/android/focus-android/app/src/main/res/values-cy/strings.xml +++ b/mobile/android/focus-android/app/src/main/res/values-cy/strings.xml @@ -123,24 +123,24 @@ - Chwilio o fewn Focus + Chwilio o fewn Focus - Chwilio o fewn Klar + Chwilio o fewn Klar - Chwilio o fewn Focus Beta + Chwilio o fewn Focus Beta - Chwilio o fewn Focus Nightly + Chwilio o fewn Focus Nightly - Gyda %1$s chi sy’n rheoli.

    + Gyda %1$s chi sy’n rheoli.

    Defnyddiwch ef fel porwr preifat:

    • Chwilio a phori o fewn yr ap
    • @@ -611,9 +611,12 @@ Dileu hanes pori + + Cau tabiau eraill + - Llwytho Firefox i Lawr + Llwytho Firefox i Lawr @@ -625,23 +628,23 @@ - Trwydded Gyhoeddus Mozilla a thrwyddedau cod agored eraill.]]> + Trwydded Gyhoeddus Mozilla a thrwyddedau cod agored eraill.]]> - yma.]]> + yma.]]> - drwyddedau rhydd a chod agored.]]> + drwyddedau rhydd a chod agored.]]> - Trwydded Gyhoeddus Gyffredinol GNU v3, ac sydd ar gael yma.]]> + Trwydded Gyhoeddus Gyffredinol GNU v3, ac sydd ar gael yma.]]> Enw Defnyddiwr @@ -833,7 +836,7 @@ Astudiaethau - Efallai y bydd Firefox yn gosod a rhedeg astudiaethau o bryd i’w gilydd. + Efallai y bydd Firefox yn gosod a rhedeg astudiaethau o bryd i’w gilydd. Darllen rhagor @@ -1037,7 +1040,7 @@ - Dysgu rhagor

      Newidiwch y gosodiad hwn yn Gosodiadau > Preifatrwydd a Diogelwch > Diogelwch.]]>
      diff --git a/mobile/android/focus-android/app/src/main/res/values-fr/strings.xml b/mobile/android/focus-android/app/src/main/res/values-fr/strings.xml index 02da1f7949d67..66a9d8c976fbb 100644 --- a/mobile/android/focus-android/app/src/main/res/values-fr/strings.xml +++ b/mobile/android/focus-android/app/src/main/res/values-fr/strings.xml @@ -124,23 +124,23 @@ - Rechercher dans Focus + Rechercher dans Focus - Rechercher dans Klar + Rechercher dans Klar - Rechercher dans Focus Beta + Rechercher dans Focus Beta - Rechercher dans Focus Nightly + Rechercher dans Focus Nightly - %1$s vous aide à rester aux commandes.

      + %1$s vous aide à rester aux commandes.

      Utilisez-le comme un navigateur privé :

      • Effectuez des recherches et naviguez depuis l’application
      • @@ -611,9 +611,12 @@ Effacer l’historique de navigation + + Fermer les autres onglets + - Télécharger Firefox + Télécharger Firefox @@ -625,23 +628,23 @@ - Mozilla Public License et d’autres licences open source.]]> + Mozilla Public License et d’autres licences open source.]]> - ici.]]> + ici.]]> - licences libres et open source.]]> + licences libres et open source.]]> - GNU General Public License v3 et qui sont disponibles ici.]]> + GNU General Public License v3 et qui sont disponibles ici.]]> Nom d’utilisateur @@ -833,7 +836,7 @@ Études - Firefox peut installer et lancer des études de temps en temps. + Firefox peut installer et lancer des études de temps en temps. En savoir plus @@ -1037,7 +1040,7 @@ - En savoir plus

        Modifiez ce paramètre dans Paramètres > Vie privée et sécurité > Sécurité.]]>
        diff --git a/mobile/android/focus-android/app/src/main/res/values-fy-rNL/strings.xml b/mobile/android/focus-android/app/src/main/res/values-fy-rNL/strings.xml index d69d3cd9f2b81..c452248c7c078 100644 --- a/mobile/android/focus-android/app/src/main/res/values-fy-rNL/strings.xml +++ b/mobile/android/focus-android/app/src/main/res/values-fy-rNL/strings.xml @@ -123,23 +123,23 @@ - Sykje yn Focus + Sykje yn Focus - Sykje yn Klar + Sykje yn Klar - Sykje yn Focus Beta + Sykje yn Focus Beta - Sykje yn Focus Nightly + Sykje yn Focus Nightly - %1$s jout jo de kontrôle.

        + %1$s jout jo de kontrôle.

        Gebrûk as in priveebrowser:

        • Streekrjocht fan de app út sykje en navigearje
        • @@ -610,9 +610,12 @@ Navigaasjeskiednis wiskje + + Oare ljepblêden slute + - Firefox downloade + Firefox downloade @@ -624,23 +627,23 @@ - Mozilla Public License en oare opensourcelisinsjes.]]> + Mozilla Public License en oare opensourcelisinsjes.]]> - hjir te finen.]]> + hjir te finen.]]> - lisinsjes.]]> + lisinsjes.]]> - GNU General Public License v3 en dy hjir beskikber binne.]]> + GNU General Public License v3 en dy hjir beskikber binne.]]> Brûkersnamme @@ -832,7 +835,7 @@ Undersiken - Firefox kin sa no en dan ûndersiken ynstallearje en útfiere. + Firefox kin sa no en dan ûndersiken ynstallearje en útfiere. Mear ynfo @@ -1036,7 +1039,7 @@ - Mear ynfo

          Wizigje dizze ynstelling yn Ynstellingen > Privacy en befeiliging > Befeiliging.]]>
          diff --git a/mobile/android/focus-android/app/src/main/res/values-gl/strings.xml b/mobile/android/focus-android/app/src/main/res/values-gl/strings.xml index 92d37243047dc..0429246e8bbb7 100644 --- a/mobile/android/focus-android/app/src/main/res/values-gl/strings.xml +++ b/mobile/android/focus-android/app/src/main/res/values-gl/strings.xml @@ -607,6 +607,9 @@ Borrar o historial de navegación + + Pechar as outras lapelas + Descargar o Firefox diff --git a/mobile/android/focus-android/app/src/main/res/values-is/strings.xml b/mobile/android/focus-android/app/src/main/res/values-is/strings.xml index fca6d8286e790..1a1e370c11d38 100644 --- a/mobile/android/focus-android/app/src/main/res/values-is/strings.xml +++ b/mobile/android/focus-android/app/src/main/res/values-is/strings.xml @@ -127,23 +127,23 @@ - Leita í Focus + Leita í Focus - Leita í Klar + Leita í Klar - Leita í Focus Beta + Leita í Focus Beta - Leita í Focus næturútgáfunni + Leita í Focus næturútgáfunni - %1$s setur þig við stjórnvölinn.

          + %1$s setur þig við stjórnvölinn.

          Notaðu það sem huliðsvafra:

          • Leitaðu og flettu beint í forritinu
          • @@ -588,9 +588,12 @@ Eyða vafurferli + + Loka öðrum flipum + - Sækja Firefox + Sækja Firefox @@ -599,23 +602,23 @@ - Mozilla Public License og annarra notkunarleyfa opins hugbúnaðar.]]> + Mozilla Public License og annarra notkunarleyfa opins hugbúnaðar.]]> - hér.]]> + hér.]]> - hugbúnaðarleyfum.]]> + hugbúnaðarleyfum.]]> - almenna GNU General Public notkunarleyfinu útg.3 og er tiltækt hér.]]> + almenna GNU General Public notkunarleyfinu útg.3 og er tiltækt hér.]]> Notandanafn @@ -805,7 +808,7 @@ Rannsóknir - Firefox kann að setja upp og keyra rannsóknir af og til. + Firefox kann að setja upp og keyra rannsóknir af og til. Fræðast meira @@ -1009,7 +1012,7 @@ - Frekari upplýsingar

            Breyttu þessari stillingu í Stillingar > Persónuvernd og öryggi > Öryggi.]]>
            diff --git a/mobile/android/focus-android/app/src/main/res/values-kab/strings.xml b/mobile/android/focus-android/app/src/main/res/values-kab/strings.xml index 6e8567058a755..6b97b110647ac 100644 --- a/mobile/android/focus-android/app/src/main/res/values-kab/strings.xml +++ b/mobile/android/focus-android/app/src/main/res/values-kab/strings.xml @@ -125,23 +125,23 @@ - Nadi deg Focus + Nadi deg Focus - Nadi deg Klar + Nadi deg Klar - Nadi deg Focus Beta + Nadi deg Focus Beta - Nadi deg Focus Nightly + Nadi deg Focus Nightly - %1$s ad k-d-yefk afus ad teqqimeḍ d aqeṛṛu.

            + %1$s ad k-d-yefk afus ad teqqimeḍ d aqeṛṛu.

            Seqdec-it d iminig uslig:

            • Nadi sakin snirem akken iwata deg usnas
            • @@ -613,9 +613,12 @@ Sfeḍ amazray n tunigin + + Mdel accaren niḍen + - Sader Firefox + Sader Firefox @@ -627,23 +630,23 @@ - Turagt tazayazt n Mozillaakked turagin-nniḍen n uɣbalu yeldin.]]> + Turagt tazayazt n Mozillaakked turagin-nniḍen n uɣbalu yeldin.]]> - dagi.]]> + dagi.]]> - turagin tiyaḍ yemgaraden d tilelliyin yerna n uɣbalu yeldin.]]> + turagin tiyaḍ yemgaraden d tilelliyin yerna n uɣbalu yeldin.]]> - Turagt tazayazt tamatut GNU v3, yernza tella dagi.]]> + Turagt tazayazt tamatut GNU v3, yernza tella dagi.]]> Isem n useqdac @@ -835,7 +838,7 @@ Leqraya - Firefox yezmer ad isebded yerna ad iseddu leqraya seg wakud ɣer wayeḍ. + Firefox yezmer ad isebded yerna ad iseddu leqraya seg wakud ɣer wayeḍ. Issin ugar @@ -1039,7 +1042,7 @@ - Issin ugar

              Beddel aɣewwaṛ-a deg Iɣewwaṛen > Tabaḍnit & Taɣellist.]]>
              diff --git a/mobile/android/focus-android/app/src/main/res/values-nl/strings.xml b/mobile/android/focus-android/app/src/main/res/values-nl/strings.xml index a01c3c1fd1022..78e2a269993da 100644 --- a/mobile/android/focus-android/app/src/main/res/values-nl/strings.xml +++ b/mobile/android/focus-android/app/src/main/res/values-nl/strings.xml @@ -124,23 +124,23 @@ - Zoeken in Focus + Zoeken in Focus - Zoeken in Klar + Zoeken in Klar - Zoeken in Focus Beta + Zoeken in Focus Beta - Zoeken in Focus Nightly + Zoeken in Focus Nightly - %1$s geeft u de controle.

              + %1$s geeft u de controle.

              Gebruik als een privébrowser:

              • Rechtstreeks vanuit de app zoeken en navigeren
              • @@ -610,9 +610,12 @@ Navigatiegeschiedenis wissen + + Overige tabbladen sluiten + - Firefox downloaden + Firefox downloaden @@ -624,23 +627,23 @@ - Mozilla Public License en andere opensourcelicenties.]]> + Mozilla Public License en andere opensourcelicenties.]]> - hier te vinden.]]> + hier te vinden.]]> - licenties.]]> + licenties.]]> - GNU General Public License v3 en die hier beschikbaar zijn.]]> + GNU General Public License v3 en die hier beschikbaar zijn.]]> Gebruikersnaam @@ -832,7 +835,7 @@ Onderzoeken - Firefox kan af en toe onderzoeken installeren en uitvoeren. + Firefox kan af en toe onderzoeken installeren en uitvoeren. Meer info @@ -1036,7 +1039,7 @@ - Meer info

                Wijzig deze instelling in Instellingen > Privacy en beveiliging > Beveiliging.]]>
                diff --git a/mobile/android/focus-android/app/src/main/res/values-pt-rBR/strings.xml b/mobile/android/focus-android/app/src/main/res/values-pt-rBR/strings.xml index fe18ade672c83..3395145c8c8b1 100644 --- a/mobile/android/focus-android/app/src/main/res/values-pt-rBR/strings.xml +++ b/mobile/android/focus-android/app/src/main/res/values-pt-rBR/strings.xml @@ -609,6 +609,9 @@ Limpar o histórico de navegação + + Fechar as outras abas + Baixar o Firefox diff --git a/mobile/locales/l10n-changesets.json b/mobile/locales/l10n-changesets.json index b1b1666f544a4..b93cc04739dfa 100644 --- a/mobile/locales/l10n-changesets.json +++ b/mobile/locales/l10n-changesets.json @@ -6,7 +6,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "an": { "pin": false, @@ -15,7 +15,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ar": { "pin": false, @@ -24,7 +24,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ast": { "pin": false, @@ -33,7 +33,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "az": { "pin": false, @@ -42,7 +42,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "be": { "pin": false, @@ -51,7 +51,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "bg": { "pin": false, @@ -60,7 +60,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "bn": { "pin": false, @@ -69,7 +69,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "br": { "pin": false, @@ -78,7 +78,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "bs": { "pin": false, @@ -87,7 +87,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ca": { "pin": false, @@ -96,7 +96,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "cak": { "pin": false, @@ -105,7 +105,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "cs": { "pin": false, @@ -114,7 +114,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "cy": { "pin": false, @@ -123,7 +123,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "da": { "pin": false, @@ -132,7 +132,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "de": { "pin": false, @@ -141,7 +141,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "dsb": { "pin": false, @@ -150,7 +150,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "el": { "pin": false, @@ -159,7 +159,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "en-CA": { "pin": false, @@ -168,7 +168,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "en-GB": { "pin": false, @@ -177,7 +177,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "eo": { "pin": false, @@ -186,7 +186,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "es-AR": { "pin": false, @@ -195,7 +195,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "es-CL": { "pin": false, @@ -204,7 +204,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "es-ES": { "pin": false, @@ -213,7 +213,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "es-MX": { "pin": false, @@ -222,7 +222,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "et": { "pin": false, @@ -231,7 +231,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "eu": { "pin": false, @@ -240,7 +240,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "fa": { "pin": false, @@ -249,7 +249,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ff": { "pin": false, @@ -258,7 +258,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "fi": { "pin": false, @@ -267,7 +267,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "fr": { "pin": false, @@ -276,7 +276,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "fy-NL": { "pin": false, @@ -285,7 +285,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ga-IE": { "pin": false, @@ -294,7 +294,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "gd": { "pin": false, @@ -303,7 +303,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "gl": { "pin": false, @@ -312,7 +312,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "gn": { "pin": false, @@ -321,7 +321,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "gu-IN": { "pin": false, @@ -330,7 +330,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "he": { "pin": false, @@ -339,7 +339,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "hi-IN": { "pin": false, @@ -348,7 +348,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "hr": { "pin": false, @@ -357,7 +357,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "hsb": { "pin": false, @@ -366,7 +366,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "hu": { "pin": false, @@ -375,7 +375,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "hy-AM": { "pin": false, @@ -384,7 +384,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ia": { "pin": false, @@ -393,7 +393,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "id": { "pin": false, @@ -402,7 +402,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "is": { "pin": false, @@ -411,7 +411,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "it": { "pin": false, @@ -420,7 +420,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ja": { "pin": false, @@ -429,7 +429,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ka": { "pin": false, @@ -438,7 +438,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "kab": { "pin": false, @@ -447,7 +447,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "kk": { "pin": false, @@ -456,7 +456,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "km": { "pin": false, @@ -465,7 +465,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "kn": { "pin": false, @@ -474,7 +474,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ko": { "pin": false, @@ -483,7 +483,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "lij": { "pin": false, @@ -492,7 +492,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "lo": { "pin": false, @@ -501,7 +501,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "lt": { "pin": false, @@ -510,7 +510,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ltg": { "pin": false, @@ -519,7 +519,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "lv": { "pin": false, @@ -528,7 +528,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "meh": { "pin": false, @@ -537,7 +537,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "mix": { "pin": false, @@ -546,7 +546,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ml": { "pin": false, @@ -555,7 +555,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "mr": { "pin": false, @@ -564,7 +564,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ms": { "pin": false, @@ -573,7 +573,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "my": { "pin": false, @@ -582,7 +582,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "nb-NO": { "pin": false, @@ -591,7 +591,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ne-NP": { "pin": false, @@ -600,7 +600,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "nl": { "pin": false, @@ -609,7 +609,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "nn-NO": { "pin": false, @@ -618,7 +618,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "oc": { "pin": false, @@ -627,7 +627,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "pa-IN": { "pin": false, @@ -636,7 +636,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "pl": { "pin": false, @@ -645,7 +645,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "pt-BR": { "pin": false, @@ -654,7 +654,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "pt-PT": { "pin": false, @@ -663,7 +663,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "rm": { "pin": false, @@ -672,7 +672,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ro": { "pin": false, @@ -681,7 +681,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ru": { "pin": false, @@ -690,7 +690,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sk": { "pin": false, @@ -699,7 +699,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sl": { "pin": false, @@ -708,7 +708,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "son": { "pin": false, @@ -717,7 +717,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sq": { "pin": false, @@ -726,7 +726,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sr": { "pin": false, @@ -735,7 +735,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "sv-SE": { "pin": false, @@ -744,7 +744,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ta": { "pin": false, @@ -753,7 +753,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "te": { "pin": false, @@ -762,7 +762,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "th": { "pin": false, @@ -771,7 +771,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "tl": { "pin": false, @@ -780,7 +780,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "tr": { "pin": false, @@ -789,7 +789,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "trs": { "pin": false, @@ -798,7 +798,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "uk": { "pin": false, @@ -807,7 +807,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "ur": { "pin": false, @@ -816,7 +816,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "uz": { "pin": false, @@ -825,7 +825,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "vi": { "pin": false, @@ -834,7 +834,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "wo": { "pin": false, @@ -843,7 +843,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "xh": { "pin": false, @@ -852,7 +852,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "zam": { "pin": false, @@ -861,7 +861,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "zh-CN": { "pin": false, @@ -870,7 +870,7 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" }, "zh-TW": { "pin": false, @@ -879,6 +879,6 @@ "android-arm", "android-multilocale" ], - "revision": "d1fe24b183ee549d27146a0d7481b3517ddda6f2" + "revision": "370cbff9cfa983022555ca3939fb09f722772498" } } \ No newline at end of file diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index 2b07a0bb74d42..6633a5762a6ea 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -3010,6 +3010,13 @@ value: false mirror: always +# If non-zero, a grace delay (in milliseconds) during which unused content +# processes are kept available for re-use to avoid unnecessary process churn. +- name: dom.ipc.processReuse.unusedGraceMs + type: uint32_t + value: 0 + mirror: always + # Process launch delay (in milliseconds). - name: dom.ipc.processPrelaunch.delayMs type: uint32_t @@ -14018,12 +14025,6 @@ value: 5 mirror: always - # If true, requests will be canceled if any of the response headers values has a NUL character -- name: network.http.reject_NULs_in_response_header_values - type: RelaxedAtomicBool - value: true - mirror: always - # If true, will be more strict with status code parsing - name: network.http.strict_response_status_line_parsing type: RelaxedAtomicBool @@ -15587,7 +15588,7 @@ - name: security.tls.enable_kyber type: RelaxedAtomicBool - value: false + value: @IS_NOT_ANDROID@ mirror: always rust: true diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 13d05e33de884..f672005352529 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -667,7 +667,10 @@ nsresult nsHttpChannel::OnBeforeConnect() { RefPtr bc; mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)); - if (bc && bc->Top()->GetForceOffline()) { + // If bypassing the cache and we're forced offline + // we can just return the error here. + if (bc && bc->Top()->GetForceOffline() && + BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())) { return NS_ERROR_OFFLINE; } @@ -773,7 +776,12 @@ nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade, return aStatus; } - if (mURI->SchemeIs("https") || aShouldUpgrade || !LoadUseHTTPSSVC()) { + RefPtr bc; + mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)); + bool forceOffline = bc && bc->Top()->GetForceOffline(); + + if (mURI->SchemeIs("https") || aShouldUpgrade || !LoadUseHTTPSSVC() || + forceOffline) { return ContinueOnBeforeConnect(aShouldUpgrade, aStatus); } @@ -1190,10 +1198,19 @@ nsresult nsHttpChannel::ContinueConnect() { "CORS preflight must have been finished by the time we " "do the rest of ContinueConnect"); + RefPtr bc; + mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)); + // we may or may not have a cache entry at this point if (mCacheEntry) { // read straight from the cache if possible... if (mCachedContentIsValid) { + // If we're forced offline, and set to bypass the cache, return offline. + if (bc && bc->Top()->GetForceOffline() && + BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())) { + return NS_ERROR_OFFLINE; + } + nsRunnableMethod* event = nullptr; nsresult rv; if (!LoadCachedContentIsPartial()) { @@ -1230,6 +1247,11 @@ nsresult nsHttpChannel::ContinueConnect() { return NS_ERROR_DOCUMENT_NOT_CACHED; } + // We're about to hit the network. Don't if we're forced offline. + if (bc && bc->Top()->GetForceOffline()) { + return NS_ERROR_OFFLINE; + } + // hit the net... nsresult rv = DoConnect(mTransactionSticky); mTransactionSticky = nullptr; @@ -4138,10 +4160,10 @@ nsresult nsHttpChannel::OpenCacheEntryInternal(bool isHttps) { return NS_OK; } - if (offline || (mLoadFlags & INHIBIT_CACHING) || - (bc && bc->Top()->GetForceOffline())) { + bool forceOffline = bc && bc->Top()->GetForceOffline(); + if (offline || (mLoadFlags & INHIBIT_CACHING) || forceOffline) { if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass()) && - !offline) { + !offline && !forceOffline) { return NS_OK; } cacheEntryOpenFlags = nsICacheStorage::OPEN_READONLY; diff --git a/netwerk/protocol/http/nsHttpResponseHead.cpp b/netwerk/protocol/http/nsHttpResponseHead.cpp index 18f7beed3a584..80944d89a8e11 100644 --- a/netwerk/protocol/http/nsHttpResponseHead.cpp +++ b/netwerk/protocol/http/nsHttpResponseHead.cpp @@ -445,8 +445,7 @@ nsresult nsHttpResponseHead::ParseHeaderLine_locked( // reject the header if there are 0x00 bytes in the value. // (see https://github.com/httpwg/http-core/issues/215 for details). - if (StaticPrefs::network_http_reject_NULs_in_response_header_values() && - val.FindChar('\0') >= 0) { + if (val.FindChar('\0') >= 0) { return NS_ERROR_DOM_INVALID_HEADER_VALUE; } diff --git a/python/mozboot/mozboot/bootstrap.py b/python/mozboot/mozboot/bootstrap.py index f55ea13349bf7..df3f39f5483f7 100644 --- a/python/mozboot/mozboot/bootstrap.py +++ b/python/mozboot/mozboot/bootstrap.py @@ -680,7 +680,9 @@ def update_vct(hg: Path, root_state_dir: Path): return vct_dir -def configure_mercurial(hg: Optional[Path], root_state_dir: Path): +def configure_mercurial( + hg: Optional[Path], root_state_dir: Path, update_only: bool = False +): """Run the Mercurial configuration wizard.""" vct_dir = update_vct(hg, root_state_dir) @@ -693,6 +695,8 @@ def configure_mercurial(hg: Optional[Path], root_state_dir: Path): f"extensions.configwizard={vct_dir}/hgext/configwizard", "configwizard", ] + if update_only: + args += ["--config", "configwizard.steps="] subprocess.call(args) diff --git a/python/mozboot/mozboot/mach_commands.py b/python/mozboot/mozboot/mach_commands.py index 02cc69f54bc60..538747687228e 100644 --- a/python/mozboot/mozboot/mach_commands.py +++ b/python/mozboot/mozboot/mach_commands.py @@ -104,7 +104,9 @@ def vcs_setup(command_context, update_only=False): Path(command_context._mach_context.state_dir), ) else: - bootstrap.update_vct(vcs, Path(command_context._mach_context.state_dir)) + bootstrap.configure_mercurial( + vcs, Path(command_context._mach_context.state_dir), update_only=True + ) else: if repo.name == "git": bootstrap.configure_git( diff --git a/remote/webdriver-bidi/modules/root/browsingContext.sys.mjs b/remote/webdriver-bidi/modules/root/browsingContext.sys.mjs index 34f0b48ca2ea3..8f3138143039f 100644 --- a/remote/webdriver-bidi/modules/root/browsingContext.sys.mjs +++ b/remote/webdriver-bidi/modules/root/browsingContext.sys.mjs @@ -1471,6 +1471,7 @@ class BrowsingContextModule extends RootBiDiModule { height: targetHeight, width: targetWidth, }, + retryOnAbort: true, }); } } diff --git a/servo/components/style/gecko/media_queries.rs b/servo/components/style/gecko/media_queries.rs index fb092ff89878d..6867786cb27be 100644 --- a/servo/components/style/gecko/media_queries.rs +++ b/servo/components/style/gecko/media_queries.rs @@ -500,26 +500,7 @@ impl Device { /// Returns whether document colors are enabled. #[inline] pub fn forced_colors(&self) -> ForcedColors { - if self.document().mIsBeingUsedAsImage() { - // SVG images never force colors. - return ForcedColors::None; - } - let prefs = self.pref_sheet_prefs(); - if !prefs.mUseDocumentColors { - return ForcedColors::Active; - } - // On Windows, having a high contrast theme also means that the OS is requesting the - // colors to be forced. This is mostly convenience for the front-end, which wants to - // reuse the forced-colors styles for chrome in this case as well, and it's a lot - // more convenient to use `(forced-colors)` than - // `(forced-colors) or ((-moz-platform: windows) and (prefers-contrast))`. - // - // TODO(emilio): We might want to factor in here the lwtheme attribute in the root element - // and so on. - if cfg!(target_os = "windows") && prefs.mUseAccessibilityTheme && prefs.mIsChrome { - return ForcedColors::Requested; - } - ForcedColors::None + self.pres_context().map_or(ForcedColors::None, |pc| pc.mForcedColors) } /// Computes a system color and returns it as an nscolor. diff --git a/servo/ports/geckolib/cbindgen.toml b/servo/ports/geckolib/cbindgen.toml index c95d090795dd5..3cf38a5e4477e 100644 --- a/servo/ports/geckolib/cbindgen.toml +++ b/servo/ports/geckolib/cbindgen.toml @@ -305,6 +305,7 @@ include = [ "ImageRendering", "PrintColorAdjust", "ForcedColorAdjust", + "ForcedColors", "ScrollbarGutter", "ScrollDirection", "HyphenateCharacter", diff --git a/testing/mozharness/mozharness/mozilla/building/buildbase.py b/testing/mozharness/mozharness/mozilla/building/buildbase.py index 65d6dc1d79045..5b50d63ead158 100755 --- a/testing/mozharness/mozharness/mozilla/building/buildbase.py +++ b/testing/mozharness/mozharness/mozilla/building/buildbase.py @@ -7,7 +7,6 @@ """ buildbase.py. provides a base class for fx desktop builds -author: Jordan Lund """ import copy diff --git a/testing/mozharness/scripts/desktop_unittest.py b/testing/mozharness/scripts/desktop_unittest.py index 0c72a28f2778e..f44c9b8f3b18e 100755 --- a/testing/mozharness/scripts/desktop_unittest.py +++ b/testing/mozharness/scripts/desktop_unittest.py @@ -5,10 +5,6 @@ # You can obtain one at http://mozilla.org/MPL/2.0/. # ***** END LICENSE BLOCK ***** -"""desktop_unittest.py - -author: Jordan Lund -""" import copy import glob @@ -1221,6 +1217,24 @@ def do_gnome_video_recording(suite_name, upload_dir, ev): ev.wait() + def do_macos_video_recording(suite_name, upload_dir, ev): + import os + import subprocess + + target_file = os.path.join( + upload_dir, + "video_{}.mov".format(suite_name), + ) + self.info("Recording suite {} to {}".format(suite_name, target_file)) + + process = subprocess.Popen( + ["/usr/sbin/screencapture", "-v", "-k", target_file], + stdin=subprocess.PIPE, + ) + ev.wait() + process.stdin.write(b"p") + process.wait() + if suites: self.info("#### Running %s suites" % suite_category) for suite in suites: @@ -1372,8 +1386,16 @@ def do_gnome_video_recording(suite_name, upload_dir, ev): finish_video = threading.Event() do_video_recording = os.getenv("MOZ_RECORD_TEST") if do_video_recording: + if sys.platform == "linux": + target = do_gnome_video_recording + elif sys.platform == "darwin": + target = do_macos_video_recording + else: + raise NotImplementedError( + "Screen recording not implemented for this platform" + ) thread = threading.Thread( - target=do_gnome_video_recording, + target=target, args=( suite, env["MOZ_UPLOAD_DIR"], diff --git a/testing/mozharness/scripts/fx_desktop_build.py b/testing/mozharness/scripts/fx_desktop_build.py index c8295d2f7b774..8a7965345203f 100755 --- a/testing/mozharness/scripts/fx_desktop_build.py +++ b/testing/mozharness/scripts/fx_desktop_build.py @@ -8,9 +8,6 @@ script harness to build nightly firefox within Mozilla's build environment and developer machines alike - -author: Jordan Lund - """ import os diff --git a/testing/web-platform/meta/content-security-policy/script-src/scripthash-changed-1.html.ini b/testing/web-platform/meta/content-security-policy/script-src/scripthash-changed-1.html.ini index 237ba4c6b3f2f..2cdddb9c8a2e0 100644 --- a/testing/web-platform/meta/content-security-policy/script-src/scripthash-changed-1.html.ini +++ b/testing/web-platform/meta/content-security-policy/script-src/scripthash-changed-1.html.ini @@ -2,4 +2,4 @@ expected: if (os == "android") and fission: [OK, TIMEOUT] [scr1.innerText before modification should not be blocked] - expected: FAIL + expected: [PASS, FAIL] diff --git a/testing/web-platform/meta/css/css-overscroll-behavior/overscroll-behavior.html.ini b/testing/web-platform/meta/css/css-overscroll-behavior/overscroll-behavior.html.ini index 167b353ab747f..0d944d830f0e1 100644 --- a/testing/web-platform/meta/css/css-overscroll-behavior/overscroll-behavior.html.ini +++ b/testing/web-platform/meta/css/css-overscroll-behavior/overscroll-behavior.html.ini @@ -1,10 +1,2 @@ [overscroll-behavior.html] - prefs: [test.events.async.enabled:true] - [overscroll-behavior prevents scroll-propagation in the area and direction as specified] - expected: - if (os == "linux") and not debug and (processor == "x86_64") and not asan and not tsan: [FAIL, PASS] - if (os == "linux") and debug and not fission: PASS - if (os == "win") and debug: PASS - if (os == "mac") and debug: PASS - if os == "android": FAIL - [PASS, FAIL] + prefs: [test.events.async.enabled:true, dom.event.wheel-event-groups.enabled:true, mousewheel.transaction.timeout:0] diff --git a/testing/web-platform/meta/css/css-view-transitions/unset-and-initial-view-transition-name.html.ini b/testing/web-platform/meta/css/css-view-transitions/unset-and-initial-view-transition-name.html.ini index 9bc8844da3e68..2a6b231d2f8d8 100644 --- a/testing/web-platform/meta/css/css-view-transitions/unset-and-initial-view-transition-name.html.ini +++ b/testing/web-platform/meta/css/css-view-transitions/unset-and-initial-view-transition-name.html.ini @@ -1,4 +1,4 @@ [unset-and-initial-view-transition-name.html] - expected: TIMEOUT + expected: [TIMEOUT, ERROR] [validates that view-transition-name: unset or initial are ignored] expected: TIMEOUT diff --git a/testing/web-platform/meta/html/canvas/__dir__.ini b/testing/web-platform/meta/html/canvas/__dir__.ini index c8f88e829bccb..41856314e55a1 100644 --- a/testing/web-platform/meta/html/canvas/__dir__.ini +++ b/testing/web-platform/meta/html/canvas/__dir__.ini @@ -1,3 +1,2 @@ -prefs: - if not fission: [dom.ipc.keepProcessesAlive.web: 1] +prefs: [dom.ipc.processReuse.unusedGraceMs: 1000] tags: [canvas] diff --git a/testing/web-platform/meta/html/dom/elements/global-attributes/dir-auto-dynamic-changes.window.js.ini b/testing/web-platform/meta/html/dom/elements/global-attributes/dir-auto-dynamic-changes.window.js.ini deleted file mode 100644 index e0f89db5af719..0000000000000 --- a/testing/web-platform/meta/html/dom/elements/global-attributes/dir-auto-dynamic-changes.window.js.ini +++ /dev/null @@ -1,3 +0,0 @@ -[dir-auto-dynamic-changes.window.html] - [dir=auto slot is not affected by text in value of input element children] - expected: FAIL diff --git a/testing/web-platform/meta/html/dom/elements/global-attributes/dir-slots-directionality.html.ini b/testing/web-platform/meta/html/dom/elements/global-attributes/dir-slots-directionality.html.ini deleted file mode 100644 index 0797af1e0fb81..0000000000000 --- a/testing/web-platform/meta/html/dom/elements/global-attributes/dir-slots-directionality.html.ini +++ /dev/null @@ -1,12 +0,0 @@ -[dir-slots-directionality.html] - [dir=auto slot ignores assigned nodes with dir attribute] - expected: FAIL - - [dir=auto slot ignores text in bdi assigned nodes] - expected: FAIL - - [dir=auto slot ignores text in value of input element children] - expected: FAIL - - [dir=auto slot is not affected by value of auto-directionality form associated elements] - expected: FAIL diff --git a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/import-attributes/__dir__.ini b/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/import-attributes/__dir__.ini new file mode 100644 index 0000000000000..4f9d5407273ed --- /dev/null +++ b/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/import-attributes/__dir__.ini @@ -0,0 +1,2 @@ +prefs: + if not release_or_beta: [javascript.options.experimental.import_attributes:true] diff --git a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/import-attributes/dynamic-import-with-attributes-argument.any.js.ini b/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/import-attributes/dynamic-import-with-attributes-argument.any.js.ini index e840d52bb7f3e..2efa493ec3cda 100644 --- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/import-attributes/dynamic-import-with-attributes-argument.any.js.ini +++ b/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/import-attributes/dynamic-import-with-attributes-argument.any.js.ini @@ -1,10 +1,11 @@ [dynamic-import-with-attributes-argument.any.sharedworker.html] expected: - if tsan: CRASH - ERROR + if release_or_beta: ERROR [dynamic-import-with-attributes-argument.any.worker.html] - expected: ERROR + expected: + if release_or_beta: ERROR [dynamic-import-with-attributes-argument.any.html] - expected: ERROR + expected: + if release_or_beta: ERROR diff --git a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/import-attributes/empty-attributes-clause.html.ini b/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/import-attributes/empty-attributes-clause.html.ini index 6da5c5c6b92e5..1d6a1a2fa73e3 100644 --- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/import-attributes/empty-attributes-clause.html.ini +++ b/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/import-attributes/empty-attributes-clause.html.ini @@ -1,4 +1,6 @@ [empty-attributes-clause.html] - expected: ERROR + expected: + if release_or_beta: ERROR [Test that no error occurs when an empty import attributes clause is provided.] - expected: FAIL + expected: + if release_or_beta: FAIL diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/viewport.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/viewport.py index ef48ad2926a5d..17f2dc585eea8 100644 --- a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/viewport.py +++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/set_viewport/viewport.py @@ -1,4 +1,7 @@ +import asyncio + import pytest +from tests.bidi import get_viewport_dimensions pytestmark = pytest.mark.asyncio @@ -16,3 +19,31 @@ async def test_params_viewport_max_value(bidi_session, new_tab, viewport): await bidi_session.browsing_context.set_viewport( context=new_tab["context"], viewport=viewport ) + + +@pytest.mark.parametrize("type_hint", ["tab", "window"]) +async def test_when_context_created( + bidi_session, wait_for_event, wait_for_future_safe, type_hint +): + test_viewport = {"width": 499, "height": 599} + + await bidi_session.session.subscribe(events=["browsingContext.contextCreated"]) + on_context_created = wait_for_event("browsingContext.contextCreated") + + # Save the task to await for it later. + task = asyncio.create_task( + bidi_session.browsing_context.create(type_hint=type_hint) + ) + + context_info = await wait_for_future_safe(on_context_created) + + # Bug 1918287 - Don't fail the command when the initial about:blank page is loaded + await bidi_session.browsing_context.set_viewport( + context=context_info["context"], viewport=test_viewport + ) + + new_tab = await task + + assert await get_viewport_dimensions(bidi_session, new_tab) == test_viewport + + await bidi_session.browsing_context.close(context=new_tab["context"]) diff --git a/testing/web-platform/tests/css/css-sizing/aspect-ratio/block-aspect-ratio-058.html b/testing/web-platform/tests/css/css-sizing/aspect-ratio/block-aspect-ratio-058.html new file mode 100644 index 0000000000000..b6d923f12bc42 --- /dev/null +++ b/testing/web-platform/tests/css/css-sizing/aspect-ratio/block-aspect-ratio-058.html @@ -0,0 +1,33 @@ + + + + + + + + + + + +

                Test passes if there is a filled green square and no red.

                +
                +
                +
                +
                diff --git a/testing/web-platform/tests/css/css-sizing/intrinsic-percent-replaced-017.html b/testing/web-platform/tests/css/css-sizing/intrinsic-percent-replaced-017.html index 190b2f8fe4435..d7e5d70e43af7 100644 --- a/testing/web-platform/tests/css/css-sizing/intrinsic-percent-replaced-017.html +++ b/testing/web-platform/tests/css/css-sizing/intrinsic-percent-replaced-017.html @@ -5,7 +5,7 @@ - +