diff --git a/Cargo.lock b/Cargo.lock index 751f6d162ff4a..18711e84c2948 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8337,9 +8337,11 @@ dependencies = [ [[package]] name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +version = "0.2.999" +dependencies = [ + "quote", + "syn", +] [[package]] name = "windows-numerics" @@ -8382,8 +8384,7 @@ dependencies = [ name = "windows-targets" version = "0.52.999" dependencies = [ - "quote", - "syn", + "windows-link", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 029ced130c1f6..5ade903144c78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -128,6 +128,10 @@ mozilla-central-workspace-hack = { path = "build/workspace-hack" } # crate, which we don't really need as we require MSVC anyways. windows-targets = { path = "build/rust/windows-targets" } +# windows-link replacement that doesn't use raw-dylibs, which have problems on +# the i686-pc-windows-gnu target. +windows-link = { path = "build/rust/windows-link" } + # Patch windows to use a non-vendored local copy of the crate. windows = { path = "build/rust/windows" } diff --git a/browser/components/aiwindow/models/Utils.sys.mjs b/browser/components/aiwindow/models/Utils.sys.mjs index ca27f26c6e809..3fdd260a14d59 100644 --- a/browser/components/aiwindow/models/Utils.sys.mjs +++ b/browser/components/aiwindow/models/Utils.sys.mjs @@ -14,7 +14,8 @@ import { createEngine } from "chrome://global/content/ml/EngineProcess.sys.mjs"; import { getFxAccountsSingleton } from "resource://gre/modules/FxAccounts.sys.mjs"; import { OAUTH_CLIENT_ID, - SCOPE_PROFILE, + SCOPE_PROFILE_UID, + SCOPE_SMART_WINDOW, } from "resource://gre/modules/FxAccountsCommon.sys.mjs"; import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; @@ -624,8 +625,7 @@ export class openAIEngine { try { const fxAccounts = getFxAccountsSingleton(); return await fxAccounts.getOAuthToken({ - // Scope needs to be updated in accordance with https://bugzilla.mozilla.org/show_bug.cgi?id=2005290 - scope: SCOPE_PROFILE, + scope: [SCOPE_SMART_WINDOW, SCOPE_PROFILE_UID], client_id: OAUTH_CLIENT_ID, }); } catch (error) { diff --git a/browser/components/aiwindow/models/tests/browser/browser.toml b/browser/components/aiwindow/models/tests/browser/browser.toml index 84ec727aac4aa..3a246599eaead 100644 --- a/browser/components/aiwindow/models/tests/browser/browser.toml +++ b/browser/components/aiwindow/models/tests/browser/browser.toml @@ -12,4 +12,5 @@ prefs = [ ["browser_getCurrentTabMetadata.js"] ["browser_get_page_content.js"] ["browser_title_generation.js"] +["browser_utils_fxAccount.js"] ["browser_utils_loadConfig.js"] diff --git a/browser/components/aiwindow/models/tests/browser/browser_utils_fxAccount.js b/browser/components/aiwindow/models/tests/browser/browser_utils_fxAccount.js new file mode 100644 index 0000000000000..d7f83852a8a53 --- /dev/null +++ b/browser/components/aiwindow/models/tests/browser/browser_utils_fxAccount.js @@ -0,0 +1,81 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { openAIEngine } = ChromeUtils.importESModule( + "moz-src:///browser/components/aiwindow/models/Utils.sys.mjs" +); + +const { OAUTH_CLIENT_ID, SCOPE_PROFILE_UID, SCOPE_SMART_WINDOW } = + ChromeUtils.importESModule("resource://gre/modules/FxAccountsCommon.sys.mjs"); + +const { getFxAccountsSingleton } = ChromeUtils.importESModule( + "resource://gre/modules/FxAccounts.sys.mjs" +); + +const { sinon } = ChromeUtils.importESModule( + "resource://testing-common/Sinon.sys.mjs" +); + +add_task(async function test_getFxAccountToken_passes_correct_scope() { + const fakeToken = "fake-oauth-token"; + const fxAccounts = getFxAccountsSingleton(); + + const getOAuthTokenStub = sinon + .stub(fxAccounts, "getOAuthToken") + .resolves(fakeToken); + + try { + const token = await openAIEngine.getFxAccountToken(); + + Assert.ok( + getOAuthTokenStub.calledOnce, + "getOAuthToken should be called once" + ); + + const callArgs = getOAuthTokenStub.getCall(0).args[0]; + Assert.ok(callArgs, "getOAuthToken should be called with arguments"); + Assert.deepEqual( + callArgs.scope, + [SCOPE_SMART_WINDOW, SCOPE_PROFILE_UID], + "getOAuthToken should be called with correct scope array" + ); + Assert.equal( + callArgs.client_id, + OAUTH_CLIENT_ID, + "getOAuthToken should be called with correct client_id" + ); + Assert.equal( + token, + fakeToken, + "getFxAccountToken should return the token from getOAuthToken" + ); + } finally { + getOAuthTokenStub.restore(); + } +}); + +add_task(async function test_getFxAccountToken_returns_null_on_error() { + const fxAccounts = getFxAccountsSingleton(); + + const getOAuthTokenStub = sinon + .stub(fxAccounts, "getOAuthToken") + .rejects(new Error("FxA authentication failed")); + + try { + const token = await openAIEngine.getFxAccountToken(); + + Assert.ok( + getOAuthTokenStub.calledOnce, + "getOAuthToken should be called once" + ); + Assert.equal( + token, + null, + "getFxAccountToken should return null when getOAuthToken throws an error" + ); + } finally { + getOAuthTokenStub.restore(); + } +}); diff --git a/browser/components/genai/GenAIChild.sys.mjs b/browser/components/genai/GenAIChild.sys.mjs index fbcd871e4aab6..38a49fd9bca6e 100644 --- a/browser/components/genai/GenAIChild.sys.mjs +++ b/browser/components/genai/GenAIChild.sys.mjs @@ -28,6 +28,11 @@ export class GenAIChild extends JSWindowActorChild { debounceDelay = 200; pendingHide = false; + /** + * A flag that gets set when this actor is destroyed. + */ + #isDestroyed = false; + registerHideEvents() { this.document.addEventListener("selectionchange", this); HIDE_EVENTS.forEach(ev => @@ -79,6 +84,10 @@ export class GenAIChild extends JSWindowActorChild { const { screenX, screenY } = event; this.mouseUpTimeout = this.contentWindow.setTimeout(() => { + if (this.#isDestroyed) { + return; + } + const selectionInfo = this.getSelectionInfo(); const delay = event.timeStamp - this.downTimeStamp; @@ -277,4 +286,8 @@ export class GenAIChild extends JSWindowActorChild { .replace(/(\s*\n\s*)|\s{2,}/g, (_, newline) => (newline ? "\n" : " ")), }; } + + didDestroy() { + this.#isDestroyed = true; + } } diff --git a/browser/components/search/test/browser/browser.toml b/browser/components/search/test/browser/browser.toml index 2ca22adb88282..4e6afa26d07a7 100644 --- a/browser/components/search/test/browser/browser.toml +++ b/browser/components/search/test/browser/browser.toml @@ -21,6 +21,10 @@ prefs = ["browser.search.widget.new=false"] ["browser_426329.js"] support-files = ["test.html", "discovery.html", "426329.xml"] +skip-if = [ + "os == 'win' && os_version == '11.26100' && arch == 'x86_64' && debug", # Bug 1920926 and being removed in bug 2012951 + "os == 'win' && os_version == '11.26100' && arch == 'x86_64' && asan", # Bug 1920926 and being removed in bug 2012951 +] ["browser_addSearchEngineFromForm.js"] support-files = ["test.html", "test_windows1252.html"] diff --git a/browser/components/search/test/browser/browser_426329.js b/browser/components/search/test/browser/browser_426329.js index fcd0b5e1fa5e9..49d752e2640a3 100644 --- a/browser/components/search/test/browser/browser_426329.js +++ b/browser/components/search/test/browser/browser_426329.js @@ -162,6 +162,10 @@ add_task(async function testShiftReturn() { }); add_task(async function testAltReturn() { + // Ensure the history has been updated so that it is complete when we + // get to the clear history test. + let historyUpdated = TestUtils.topicObserved("satchel-storage-changed"); + await prepareTest("testAltReturn"); await BrowserTestUtils.openNewForegroundTab(gBrowser, () => { EventUtils.synthesizeKey("KEY_Enter", { altKey: true }); @@ -173,6 +177,8 @@ add_task(async function testAltReturn() { expectedURL(searchBar.value), "testAltReturn opened correct search page" ); + + await historyUpdated; }); add_task(async function testAltReturnEmpty() { @@ -187,6 +193,10 @@ add_task(async function testAltReturnEmpty() { }); add_task(async function testAltGrReturn() { + // Ensure the history has been updated so that it is complete when we + // get to the clear history test. + let historyUpdated = TestUtils.topicObserved("satchel-storage-changed"); + await prepareTest("testAltGrReturn"); await BrowserTestUtils.openNewForegroundTab(gBrowser, () => { EventUtils.synthesizeKey("KEY_Enter", { altGraphKey: true }); @@ -198,6 +208,8 @@ add_task(async function testAltGrReturn() { expectedURL(searchBar.value), "testAltGrReturn opened correct search page" ); + + await historyUpdated; }); add_task(async function testAltGrReturnEmpty() { @@ -229,6 +241,10 @@ add_task(async function testShiftAltReturnEmpty() { }); add_task(async function testLeftClick() { + // Ensure the history has been updated so that it is complete when we + // get to the clear history test. + let historyUpdated = TestUtils.topicObserved("satchel-storage-changed"); + await prepareTest("testLeftClick"); simulateClick({ button: 0 }, searchButton); await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); @@ -238,9 +254,15 @@ add_task(async function testLeftClick() { expectedURL(searchBar.value), "testLeftClick opened correct search page" ); + + await historyUpdated; }); add_task(async function testMiddleClick() { + // Ensure the history has been updated so that it is complete when we + // get to the clear history test. + let historyUpdated = TestUtils.topicObserved("satchel-storage-changed"); + await prepareTest("testMiddleClick"); await BrowserTestUtils.openNewForegroundTab(gBrowser, () => { simulateClick({ button: 1 }, searchButton); @@ -251,9 +273,15 @@ add_task(async function testMiddleClick() { expectedURL(searchBar.value), "testMiddleClick opened correct search page" ); + + await historyUpdated; }); add_task(async function testShiftMiddleClick() { + // Ensure the history has been updated so that it is complete when we + // get to the clear history test. + let historyUpdated = TestUtils.topicObserved("satchel-storage-changed"); + await prepareTest("testShiftMiddleClick"); let url = expectedURL(searchBar.value); @@ -268,6 +296,8 @@ add_task(async function testShiftMiddleClick() { url, "testShiftMiddleClick opened correct search page" ); + + await historyUpdated; }); add_task(async function testRightClick() { @@ -291,7 +321,12 @@ add_task(async function testRightClick() { }); // The click in the searchbox focuses it, which opens the suggestion // panel. Clean up after ourselves. - searchBar.textbox.popup.hidePopup(); + let popupHiddenPromise = BrowserTestUtils.waitForPopupEvent( + searchBar.textbox.popup, + "hidden" + ); + searchBar.textbox.closePopup(); + await popupHiddenPromise; }); add_task(async function testSearchHistory() { @@ -311,30 +346,33 @@ add_task(async function testSearchHistory() { add_task(async function testAutocomplete() { let popup = searchBar.textbox.popup; - let popupShownPromise = BrowserTestUtils.waitForEvent(popup, "popupshown"); + let popupShownPromise = BrowserTestUtils.waitForPopupEvent(popup, "shown"); searchBar.textbox.showHistoryPopup(); await popupShownPromise; + checkMenuEntries(searchEntries); + + let popupHiddenPromise = BrowserTestUtils.waitForPopupEvent(popup, "hidden"); searchBar.textbox.closePopup(); + await popupHiddenPromise; }); add_task(async function testClearHistory() { - // Open the textbox context menu to trigger controller attachment. let textbox = searchBar.textbox; - let popupShownPromise = BrowserTestUtils.waitForEvent( - window, - "popupshown", - false, - event => event.target.classList.contains("textbox-contextmenu") + + // If the menu hasn't been built yet, then force it to be built. + if (!searchBar._menupopup) { + searchBar._buildContextMenu(); + } + let popupShownPromise = BrowserTestUtils.waitForPopupEvent( + searchBar._menupopup, + "shown" ); EventUtils.synthesizeMouseAtCenter(textbox, { type: "contextmenu", button: 2, }); await popupShownPromise; - // Close the context menu. - let contextMenu = document.querySelector(".textbox-contextmenu"); - contextMenu.hidePopup(); let menuitem = searchBar._menupopup.querySelector(".searchbar-clear-history"); ok(!menuitem.disabled, "Clear history menuitem enabled"); @@ -342,6 +380,15 @@ add_task(async function testClearHistory() { let historyCleared = promiseObserver("satchel-storage-changed"); searchBar._menupopup.activateItem(menuitem); await historyCleared; + + // Close the context menu. + let popupHiddenPromise = BrowserTestUtils.waitForPopupEvent( + searchBar._menupopup, + "hidden" + ); + searchBar._menupopup.hidePopup(); + await popupHiddenPromise; + let count = await FormHistoryTestUtils.count( textbox.getAttribute("autocompletesearchparam") ); diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js index 02a87bf8d8eea..545ee3629d88d 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -3471,7 +3471,7 @@ for (const tab of tabs) { this.tabpanels.setSplitViewPanelActive(isActive, tab.linkedPanel); } - this.tabpanels.isSplitViewActive = gBrowser.selectedTab.splitview; + this.tabpanels.setSplitViewActive(!!gBrowser.selectedTab.splitview); } /** @@ -9338,6 +9338,13 @@ PrivateBrowsingUtils.isWindowPrivate(window) ); this.mBrowser.registeredOpenURI = aLocation; + + // Record telemetry for URI loads in split view + if (this.mTab.splitview && aLocation.spec !== "about:opentabs") { + const index = this.mTab.splitview.tabs.indexOf(this.mTab); + const label = String(index + 1); // 0 -> "1" (LTR left), 1 -> "2" (LTR right) + Glean.splitview.uriCount[label].add(1); + } } if (this.mTab != gBrowser.selectedTab) { diff --git a/browser/components/tabbrowser/content/tabsplitview.js b/browser/components/tabbrowser/content/tabsplitview.js index 83810ef89df44..d84b129013964 100644 --- a/browser/components/tabbrowser/content/tabsplitview.js +++ b/browser/components/tabbrowser/content/tabsplitview.js @@ -304,6 +304,18 @@ this.#activate(); gBrowser.setIsSplitViewActive(this.hasActiveTab, this.#tabs); + + // Attempt to update uriCount metric using the resulting tabs collection, + // as tabs may not be added to the splitview if they are pinned etc. + for (let tab of this.tabs) { + let tabURI = tab.linkedBrowser.currentURI.spec; + if (!isBlankPageURL(tabURI) && tabURI !== "about:opentabs") { + // Add to the counter which tracks the number of URIs loaded into splitview tabs + const index = tabs.indexOf(tab); + const label = String(index + 1); // 0 -> "1" (LTR left), 1 -> "2" (LTR right) + Glean.splitview.uriCount[label].add(1); + } + } } /** diff --git a/browser/components/tabbrowser/metrics.yaml b/browser/components/tabbrowser/metrics.yaml index 0a0add6d301e8..74a7c396351c2 100644 --- a/browser/components/tabbrowser/metrics.yaml +++ b/browser/components/tabbrowser/metrics.yaml @@ -27,6 +27,8 @@ browser.engagement: - rtestard@mozilla.com expires: never telemetry_mirror: BROWSER_ENGAGEMENT_TAB_UNLOAD_COUNT + no_lint: + - COMMON_PREFIX tab_reload_count: type: counter @@ -43,6 +45,8 @@ browser.engagement: - rtestard@mozilla.com expires: never telemetry_mirror: BROWSER_ENGAGEMENT_TAB_RELOAD_COUNT + no_lint: + - COMMON_PREFIX tab_explicit_unload: type: event @@ -78,6 +82,8 @@ browser.engagement: description: Time to unload tabs (in ms) type: quantity expires: never + no_lint: + - COMMON_PREFIX tab_unload_to_reload: type: timing_distribution @@ -95,6 +101,8 @@ browser.engagement: - tkikuchi@mozilla.com expires: never telemetry_mirror: TAB_UNLOAD_TO_RELOAD + no_lint: + - COMMON_PREFIX browser.ui.interaction: all_tabs_panel_dragstart_tab_event_count: @@ -865,3 +873,21 @@ link.handling: type: boolean no_lint: - COMMON_PREFIX + +splitview: + uri_count: + type: labeled_counter + description: > + Records how many URIs were loaded on each side of the splitview. + bugs: + - https://bugzil.la/2013097 + data_reviews: + - https://bugzil.la/2013097 + data_sensitivity: + - interaction + notification_emails: + - sfoster@mozilla.com + expires: never + labels: + - "1" # left side + - "2" # right side diff --git a/browser/components/tabbrowser/test/browser/tabs/browser.toml b/browser/components/tabbrowser/test/browser/tabs/browser.toml index 853c98b6290cd..2b529525ac576 100644 --- a/browser/components/tabbrowser/test/browser/tabs/browser.toml +++ b/browser/components/tabbrowser/test/browser/tabs/browser.toml @@ -644,6 +644,10 @@ support-files = ["file_withicon.html"] ["browser_tab_splitview_keyboard_focus.js"] +["browser_tab_splitview_splitter_keyboard.js"] + +["browser_tab_splitview_telemetry.js"] + ["browser_tab_tooltips.js"] tags = "vertical-tabs" skip-if = [ diff --git a/browser/components/tabbrowser/test/browser/tabs/browser_tab_groups.js b/browser/components/tabbrowser/test/browser/tabs/browser_tab_groups.js index 8a5417b669ccc..fb63d57304bb5 100644 --- a/browser/components/tabbrowser/test/browser/tabs/browser_tab_groups.js +++ b/browser/components/tabbrowser/test/browser/tabs/browser_tab_groups.js @@ -1357,3 +1357,33 @@ add_task(async function test_bug1997096_autoUncollapseOnRightClick() { BrowserTestUtils.removeTab(newTab); BrowserTestUtils.removeTab(groupedTab); }); + +add_task(async function test_bug2007061_hideSplitViewWhenDraggingGroup() { + let tab1 = BrowserTestUtils.addTab(gBrowser, "about:blank"); + let tab2 = BrowserTestUtils.addTab(gBrowser, "about:blank"); + let splitview = gBrowser.addTabSplitView([tab1, tab2]); + let group = gBrowser.addTabGroup([splitview]); + + gBrowser.selectedTab = tab1; + Assert.ok(tab1.selected, "tab1 in split view is selected"); + + Assert.ok(splitview.hasActiveTab, "split view has active tab attribute"); + + group.collapsed = true; + Assert.ok(group.collapsed, "group is collapsed"); + + group.isBeingDragged = true; + Assert.ok( + group.hasAttribute("movingtabgroup"), + "group has movingtabgroup attribute when being dragged" + ); + + Assert.ok( + BrowserTestUtils.isHidden(splitview), + "split view wrapper is hidden while dragging collapsed group" + ); + + group.isBeingDragged = false; + + await removeTabGroup(group); +}); diff --git a/browser/components/tabbrowser/test/browser/tabs/browser_tab_splitview_splitter_keyboard.js b/browser/components/tabbrowser/test/browser/tabs/browser_tab_splitview_splitter_keyboard.js new file mode 100644 index 0000000000000..c16847b4f79e3 --- /dev/null +++ b/browser/components/tabbrowser/test/browser/tabs/browser_tab_splitview_splitter_keyboard.js @@ -0,0 +1,140 @@ +"use strict"; + +add_setup(() => + SpecialPowers.pushPrefEnv({ + set: [["test.wait300msAfterTabSwitch", true]], + }) +); + +async function expectFocusAfterKey(expectedActiveElement, keyName, keyOptions) { + let focused = BrowserTestUtils.waitForEvent(expectedActiveElement, "focus"); + EventUtils.synthesizeKey(keyName, keyOptions); + await focused; + Assert.equal( + document.activeElement, + expectedActiveElement, + `After ${keyName}, the expected element has focus` + ); +} + +/* Test that + * the splitter in a split view is focusable + * arrow keys correctly move the splitter and cause panels to resize + * when switching to a different splitview, the arrow keys move and affect the correct panels + */ + +add_task(async function test_SplitterKeyboardA11Y() { + const tab1 = BrowserTestUtils.addTab( + gBrowser, + "data:text/html,Tab 1" + ); + const tab2 = BrowserTestUtils.addTab( + gBrowser, + "data:text/html,Tab 2" + ); + const tab3 = BrowserTestUtils.addTab( + gBrowser, + "data:text/html,Tab 3" + ); + const tab4 = BrowserTestUtils.addTab( + gBrowser, + "data:text/html,Tab 4" + ); + + await BrowserTestUtils.switchTab(gBrowser, tab1); + const splitView = gBrowser.addTabSplitView([tab1, tab2], { + insertBefore: tab1, + }); + const splitter = gBrowser.tabpanels.splitViewSplitter; + let leftPanel = gBrowser.getPanel(tab1.linkedBrowser); + Assert.equal( + leftPanel, + document.getElementById(gBrowser.tabpanels.splitViewPanels[0]), + "Sanity check the left panel is the correct tab's panel" + ); + + Assert.ok(splitter, "The splitview splitter was created"); + Assert.equal( + splitter.getAttribute("role"), + "separator", + "The splitter has the separator role" + ); + Assert.equal( + splitter.getAttribute("aria-controls"), + leftPanel.id, + "The splitter's aria-controls attribute points to the left panel" + ); + + info("Move focus to the left-side browser"); + Services.focus.setFocus(gBrowser.selectedBrowser, Services.focus.FLAG_BYKEY); + + await expectFocusAfterKey(splitter, "KEY_Tab"); + await expectFocusAfterKey(tab2.linkedBrowser, "KEY_Tab"); + await expectFocusAfterKey(splitter, "KEY_Tab", { shiftKey: true }); + Assert.equal(document.activeElement, splitter, "Splitter has focus"); + + let beforeWidth = leftPanel.getBoundingClientRect().width; + let beforeValueNow = splitter.getAttribute("aria-valuenow"); + let cmdEventPromise = BrowserTestUtils.waitForEvent(splitter, "command"); + info( + `Before the arrow key, aria-valuenow value: ${beforeValueNow}, beforeWidth: ${beforeWidth}` + ); + + await EventUtils.synthesizeKey("KEY_ArrowLeft"); + await cmdEventPromise; + await BrowserTestUtils.waitForMutationCondition( + splitter, + { attributes: true, attributeFilter: ["aria-valuenow"] }, + () => splitter.getAttribute("aria-valuenow") != beforeValueNow + ); + info("New aria-valuenow value: " + splitter.getAttribute("aria-valuenow")); + + let afterWidth = leftPanel.getBoundingClientRect().width; + Assert.greater( + beforeWidth, + afterWidth, + "The left panel shrank when the splitter was moved" + ); + Assert.equal( + parseInt(splitter.ariaValueNow), + Math.floor(afterWidth), + "The aria-valuenow attribute reflects the new width of the left panel" + ); + Assert.ok( + splitter.ariaValueMin, + "The splitter has the aria-valuemin attribute" + ); + Assert.ok( + splitter.ariaValueMax, + "The splitter has the aria-valuemax attribute" + ); + + await BrowserTestUtils.switchTab(gBrowser, tab3); + const splitView2 = gBrowser.addTabSplitView([tab3, tab4], { + insertBefore: tab3, + }); + let controlledPanelId = splitter.getAttribute("aria-controls"); + Assert.equal( + controlledPanelId, + gBrowser.getPanel(tab3.linkedBrowser).id, + "The splitter's aria-controls attribute points to the new left panel" + ); + + splitView2.close(); + await BrowserTestUtils.waitForMutationCondition( + splitter, + { attributes: true, attributeFilter: ["aria-controls"] }, + () => splitter.getAttribute("aria-controls") != controlledPanelId + ); + // The initial split view should remain and the splitter now controls it + Assert.equal( + splitter.getAttribute("aria-controls"), + leftPanel.id, + "The splitter's aria-controls attribute points to the left panel" + ); + + splitView.close(); + Assert.ok(!splitter.ariaValueMin, "The aria-valuemin attribute was removed"); + Assert.ok(!splitter.ariaValueMax, "aria-valuemax attribute was removed"); + Assert.ok(!splitter.ariaValueNow, "aria-valuenow attribute was removed"); +}); diff --git a/browser/components/tabbrowser/test/browser/tabs/browser_tab_splitview_telemetry.js b/browser/components/tabbrowser/test/browser/tabs/browser_tab_splitview_telemetry.js new file mode 100644 index 0000000000000..d1375a4edb5e7 --- /dev/null +++ b/browser/components/tabbrowser/test/browser/tabs/browser_tab_splitview_telemetry.js @@ -0,0 +1,159 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +async function resetTelemetry() { + await Services.fog.testFlushAllChildren(); + Services.fog.testResetFOG(); +} + +async function tabIsInSplitView(tab) { + const panel = document.getElementById(tab.linkedPanel); + info("Waiting in tabIsInSplitView"); + await BrowserTestUtils.waitForMutationCondition( + panel, + { attributes: true }, + () => panel.classList.contains("split-view-panel") + ); +} + +function navigateTab(tab, url) { + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, url); + return BrowserTestUtils.browserLoaded(tab.linkedBrowser); +} + +add_setup(async () => { + await SpecialPowers.pushPrefEnv({ + set: [["browser.tabs.splitView.enabled", true]], + }); +}); + +registerCleanupFunction(async () => { + await resetTelemetry(); +}); + +add_task(async function test_splitview_uri_count_telemetry() { + await resetTelemetry(); + // Create 4 tabs with different URLs + const tabs = await Promise.all( + [ + "https://example.com/start1", + "https://example.com/start2", + "https://example.org/start3", + "about:blank", + ].map(async url => { + const tab = BrowserTestUtils.addTab(gBrowser, url); + if (url !== "about:blank") { + await BrowserTestUtils.browserLoaded(tab.linkedBrowser); + } + return tab; + }) + ); + await BrowserTestUtils.switchTab(gBrowser, tabs[0]); + await Services.fog.testFlushAllChildren(); + + // Verify telemetry starts undefined + Assert.equal( + Glean.splitview.uriCount["1"].testGetValue(), + undefined, + "URI count for left side (label '1') starts undefined" + ); + Assert.equal( + Glean.splitview.uriCount["2"].testGetValue(), + undefined, + "URI count for right side (label '2') starts undefined" + ); + + // Create split view (tab 0 is left/"1", tab 1 is right/"2") + const splitView1 = gBrowser.addTabSplitView([tabs[0], tabs[1]], { + id: "test-1", + }); + await tabIsInSplitView(tabs[0]); + await tabIsInSplitView(tabs[1]); + Assert.ok(splitView1.splitViewId, "Split view created successfully"); + Assert.equal(splitView1.tabs.length, 2, "Split view has 2 tabs"); + + await Services.fog.testFlushAllChildren(); + Assert.equal( + Glean.splitview.uriCount["1"].testGetValue(), + 1, + "URI count for left side (label '1') should be 1 after initial splitview creation" + ); + Assert.equal( + Glean.splitview.uriCount["2"].testGetValue(), + 1, + "URI count for right side (label '2') should be 1 after initial splitview creation" + ); + + // Navigate the first (left-side) tab + await navigateTab(tabs[0], "https://example.org/page1"); + await Services.fog.testFlushAllChildren(); + Assert.equal( + Glean.splitview.uriCount["1"].testGetValue(), + 2, + "URI count for left side (label '1') should increment to 2" + ); + Assert.equal( + Glean.splitview.uriCount["2"].testGetValue(), + 1, + "URI count for right side should still be 1" + ); + + // Navigate the right-side tab + await navigateTab(tabs[1], "https://example.com/page2"); + await Services.fog.testFlushAllChildren(); + Assert.equal( + Glean.splitview.uriCount["1"].testGetValue(), + 2, + "URI count for left side (label '1') should still be 2" + ); + Assert.equal( + Glean.splitview.uriCount["2"].testGetValue(), + 2, + "URI count for right side (label '2') should increment to 2" + ); + + // Create a split view from the other 2 tabs + info("Create a splitview from tabs 3 and 4"); + await BrowserTestUtils.switchTab(gBrowser, tabs[3]); + const splitView2 = gBrowser.addTabSplitView([tabs[2], tabs[3]], { + id: "test-2", + }); + await tabIsInSplitView(tabs[2]); + await tabIsInSplitView(tabs[3]); + await Services.fog.testFlushAllChildren(); + + Assert.equal( + Glean.splitview.uriCount["1"].testGetValue(), + 3, + "URI count for left side (label '1') should now be 3 after 2nd splitview creation" + ); + Assert.equal( + Glean.splitview.uriCount["2"].testGetValue(), + 2, + "URI count for right side (label '2') should remain at 2 as only about:blank was loaded" + ); + + // Navigate the right-side tab in 2nd splitview + await navigateTab(tabs[3], "https://example.com/page2"); + await Services.fog.testFlushAllChildren(); + Assert.equal( + Glean.splitview.uriCount["1"].testGetValue(), + 3, + "URI count for left side (label '1') should still be 3" + ); + Assert.equal( + Glean.splitview.uriCount["2"].testGetValue(), + 3, + "URI count for right side (label '2') should increment to 3" + ); + + // Cleanup + splitView1.close(); + splitView2.close(); + BrowserTestUtils.removeTab(tabs[0]); + BrowserTestUtils.removeTab(tabs[1]); + BrowserTestUtils.removeTab(tabs[2]); + BrowserTestUtils.removeTab(tabs[3]); +}); diff --git a/browser/components/urlbar/UrlbarView.sys.mjs b/browser/components/urlbar/UrlbarView.sys.mjs index 616c0d72b663e..4816b1e2f028e 100644 --- a/browser/components/urlbar/UrlbarView.sys.mjs +++ b/browser/components/urlbar/UrlbarView.sys.mjs @@ -2095,6 +2095,10 @@ export class UrlbarView { if (result.isNovaSuggestion) { item.toggleAttribute("nova", true); item.toggleAttribute("rich-suggestion", true); + item.setAttribute( + "type", + lazy.UrlbarUtils.searchEngagementTelemetryType(result) + ); this.#updateRowContentForNova(item, result); return; } diff --git a/browser/extensions/newtab/content-src/components/TopSites/TopSite.jsx b/browser/extensions/newtab/content-src/components/TopSites/TopSite.jsx index 0d4c5aada7e94..eccc6eb8947e1 100644 --- a/browser/extensions/newtab/content-src/components/TopSites/TopSite.jsx +++ b/browser/extensions/newtab/content-src/components/TopSites/TopSite.jsx @@ -47,11 +47,12 @@ export class TopSiteLink extends React.PureComponent { /* * Helper to determine whether the drop zone should allow a drop. We only allow * dropping top sites for now. We don't allow dropping on sponsored top sites - * as their position is fixed. + * or the add shortcut button as their position is fixed. */ _allowDrop(e) { return ( - (this.dragged || !isSponsored(this.props.link)) && + (this.dragged || + (!isSponsored(this.props.link) && !this.props.isAddButton)) && e.dataTransfer.types.includes("text/topsite-index") ); } @@ -853,15 +854,31 @@ export class _TopSiteList extends React.PureComponent { topSites.length = this.props.TopSitesRows * TOP_SITES_MAX_SITES_PER_ROW; // if topSites do not fill an entire row add 'Add shortcut' button to array of topSites // (there should only be one of these) - let firstPlaceholder = topSites.findIndex(Object.is.bind(null, undefined)); - // make sure placeholder exists and there already isnt a add button - if (firstPlaceholder && !topSites.includes(site => site.isAddButton)) { - topSites[firstPlaceholder] = { isAddButton: true }; - } else if (topSites.includes(site => site.isAddButton)) { - topSites.push( - topSites.splice(topSites.indexOf({ isAddButton: true }), 1)[0] - ); + const addButtonIndex = topSites.findIndex(site => site?.isAddButton); + + // Find the position right after the last regular shortcut + let targetPosition = topSites.length - 1; + for (let i = topSites.length - 1; i >= 0; i--) { + if (topSites[i] && !topSites[i].isAddButton) { + targetPosition = i + 1; + break; + } } + + if (addButtonIndex === -1) { + // No add button exists yet, insert it at target position if it's within bounds + if (targetPosition < topSites.length) { + topSites[targetPosition] = { isAddButton: true }; + } + } else if (addButtonIndex !== targetPosition) { + // Add button exists but not at the end, move it + const [button] = topSites.splice(addButtonIndex, 1); + // Adjust target if we removed something before it + const adjustedTarget = + addButtonIndex < targetPosition ? targetPosition - 1 : targetPosition; + topSites[adjustedTarget] = button; + } + return topSites; } @@ -873,10 +890,12 @@ export class _TopSiteList extends React.PureComponent { const topSites = this._getTopSites(); topSites[this.state.draggedIndex] = null; const preview = topSites.map(site => - site && (site.isPinned || isSponsored(site)) ? site : null + site && (site.isPinned || isSponsored(site) || site.isAddButton) + ? site + : null ); const unpinned = topSites.filter( - site => site && !site.isPinned && !isSponsored(site) + site => site && !site.isPinned && !isSponsored(site) && !site.isAddButton ); const siteToInsert = Object.assign({}, this.state.draggedSite, { isPinned: true, @@ -900,7 +919,10 @@ export class _TopSiteList extends React.PureComponent { index > this.state.draggedIndex ? holeIndex < index : holeIndex > index ) { let nextIndex = holeIndex + shiftingStep; - while (isSponsored(preview[nextIndex])) { + while ( + preview[nextIndex] && + (isSponsored(preview[nextIndex]) || preview[nextIndex].isAddButton) + ) { nextIndex += shiftingStep; } preview[holeIndex] = preview[nextIndex]; diff --git a/browser/extensions/newtab/data/content/activity-stream.bundle.js b/browser/extensions/newtab/data/content/activity-stream.bundle.js index 88d7f939a0032..695b4b1b6136d 100644 --- a/browser/extensions/newtab/data/content/activity-stream.bundle.js +++ b/browser/extensions/newtab/data/content/activity-stream.bundle.js @@ -8077,10 +8077,10 @@ class TopSiteLink extends (external_React_default()).PureComponent { /* * Helper to determine whether the drop zone should allow a drop. We only allow * dropping top sites for now. We don't allow dropping on sponsored top sites - * as their position is fixed. + * or the add shortcut button as their position is fixed. */ _allowDrop(e) { - return (this.dragged || !isSponsored(this.props.link)) && e.dataTransfer.types.includes("text/topsite-index"); + return (this.dragged || !isSponsored(this.props.link) && !this.props.isAddButton) && e.dataTransfer.types.includes("text/topsite-index"); } onDragEvent(event) { switch (event.type) { @@ -8786,16 +8786,29 @@ class _TopSiteList extends (external_React_default()).PureComponent { topSites.length = this.props.TopSitesRows * TOP_SITES_MAX_SITES_PER_ROW; // if topSites do not fill an entire row add 'Add shortcut' button to array of topSites // (there should only be one of these) - let firstPlaceholder = topSites.findIndex(Object.is.bind(null, undefined)); - // make sure placeholder exists and there already isnt a add button - if (firstPlaceholder && !topSites.includes(site => site.isAddButton)) { - topSites[firstPlaceholder] = { - isAddButton: true - }; - } else if (topSites.includes(site => site.isAddButton)) { - topSites.push(topSites.splice(topSites.indexOf({ - isAddButton: true - }), 1)[0]); + const addButtonIndex = topSites.findIndex(site => site?.isAddButton); + + // Find the position right after the last regular shortcut + let targetPosition = topSites.length - 1; + for (let i = topSites.length - 1; i >= 0; i--) { + if (topSites[i] && !topSites[i].isAddButton) { + targetPosition = i + 1; + break; + } + } + if (addButtonIndex === -1) { + // No add button exists yet, insert it at target position if it's within bounds + if (targetPosition < topSites.length) { + topSites[targetPosition] = { + isAddButton: true + }; + } + } else if (addButtonIndex !== targetPosition) { + // Add button exists but not at the end, move it + const [button] = topSites.splice(addButtonIndex, 1); + // Adjust target if we removed something before it + const adjustedTarget = addButtonIndex < targetPosition ? targetPosition - 1 : targetPosition; + topSites[adjustedTarget] = button; } return topSites; } @@ -8807,8 +8820,8 @@ class _TopSiteList extends (external_React_default()).PureComponent { _makeTopSitesPreview(index) { const topSites = this._getTopSites(); topSites[this.state.draggedIndex] = null; - const preview = topSites.map(site => site && (site.isPinned || isSponsored(site)) ? site : null); - const unpinned = topSites.filter(site => site && !site.isPinned && !isSponsored(site)); + const preview = topSites.map(site => site && (site.isPinned || isSponsored(site) || site.isAddButton) ? site : null); + const unpinned = topSites.filter(site => site && !site.isPinned && !isSponsored(site) && !site.isAddButton); const siteToInsert = Object.assign({}, this.state.draggedSite, { isPinned: true, isDragged: true @@ -8828,7 +8841,7 @@ class _TopSiteList extends (external_React_default()).PureComponent { const shiftingStep = index > this.state.draggedIndex ? 1 : -1; while (index > this.state.draggedIndex ? holeIndex < index : holeIndex > index) { let nextIndex = holeIndex + shiftingStep; - while (isSponsored(preview[nextIndex])) { + while (preview[nextIndex] && (isSponsored(preview[nextIndex]) || preview[nextIndex].isAddButton)) { nextIndex += shiftingStep; } preview[holeIndex] = preview[nextIndex]; diff --git a/browser/extensions/newtab/lib/TopSitesFeed.sys.mjs b/browser/extensions/newtab/lib/TopSitesFeed.sys.mjs index ab65876a63dac..547f7b5cf3a41 100644 --- a/browser/extensions/newtab/lib/TopSitesFeed.sys.mjs +++ b/browser/extensions/newtab/lib/TopSitesFeed.sys.mjs @@ -2234,6 +2234,10 @@ export class TopSitesFeed { */ _insertPin(site, originalIndex, draggedFromIndex) { let index = this._adjustPinIndexForSponsoredLinks(site, originalIndex); + let adjustedDraggedFromIndex = this._adjustPinIndexForSponsoredLinks( + site, + draggedFromIndex + ); // Don't insert any pins past the end of the visible top sites. Otherwise, // we can end up with a bunch of pinned sites that can never be unpinned again @@ -2249,11 +2253,11 @@ export class TopSitesFeed { if (!pinned[index]) { this._pinSiteAt(site, index); } else { - pinned[draggedFromIndex] = null; + pinned[adjustedDraggedFromIndex] = null; // Find the hole to shift the pinned site(s) towards. We shift towards the // hole left by the site being dragged. let holeIndex = index; - const indexStep = index > draggedFromIndex ? -1 : 1; + const indexStep = index > adjustedDraggedFromIndex ? -1 : 1; while (pinned[holeIndex]) { holeIndex += indexStep; } diff --git a/browser/extensions/newtab/test/unit/content-src/components/TopSites.test.jsx b/browser/extensions/newtab/test/unit/content-src/components/TopSites.test.jsx index 6423cf2f16083..9c928c0bddda7 100644 --- a/browser/extensions/newtab/test/unit/content-src/components/TopSites.test.jsx +++ b/browser/extensions/newtab/test/unit/content-src/components/TopSites.test.jsx @@ -1539,7 +1539,7 @@ describe("", () => { assert.lengthOf(wrapper.find(TopSitePlaceholder), 3, "placeholders"); }); it("should update state onDragStart and clear it onDragEnd", () => { - const wrapper = shallow(); + const wrapper = shallow(); const instance = wrapper.instance(); const index = 7; const link = { url: "https://foo.com" }; @@ -1661,16 +1661,6 @@ describe("", () => { null, null, ]); - assert.deepEqual(instance._makeTopSitesPreview(3), [ - site2, - site3, - addButton, - draggedSite, - null, - null, - null, - null, - ]); site2.isPinned = true; assert.deepEqual(instance._makeTopSitesPreview(1), [ site2, diff --git a/browser/locales/en-US/browser/tabbrowser.ftl b/browser/locales/en-US/browser/tabbrowser.ftl index eaf01feb7c2f4..defab647fbe0b 100644 --- a/browser/locales/en-US/browser/tabbrowser.ftl +++ b/browser/locales/en-US/browser/tabbrowser.ftl @@ -319,6 +319,9 @@ tab-context-move-split-view-to-group = ## +tab-splitview-splitter = + .aria-label = Resize split view tabs + tab-context-move-tab-to-group-saved-groups = .label = Closed Groups tab-group-editor-action-new-tab = diff --git a/browser/themes/shared/tabbrowser/content-area.css b/browser/themes/shared/tabbrowser/content-area.css index ccc062a4032ab..e84626aac294f 100644 --- a/browser/themes/shared/tabbrowser/content-area.css +++ b/browser/themes/shared/tabbrowser/content-area.css @@ -211,6 +211,11 @@ .split-view-splitter { order: 1; flex: none; + -moz-user-focus: normal; + + &:focus-visible { + outline: auto; + } } .split-view-panel[column="1"] { diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css index 121fb55c348ef..64b67f3b34228 100644 --- a/browser/themes/shared/tabbrowser/tabs.css +++ b/browser/themes/shared/tabbrowser/tabs.css @@ -1537,7 +1537,9 @@ tab-group { overflow-clip-margin: 0; } + #tabbrowser-tabs[orient="horizontal"] &[movingtabgroup][collapsed] > tab-split-view-wrapper[hasactivetab], #tabbrowser-tabs[orient="vertical"] &[movingtabgroup][collapsed] > .tabbrowser-tab[visuallyselected], + #tabbrowser-tabs[orient="vertical"] &[movingtabgroup][collapsed] > tab-split-view-wrapper[hasactivetab], #tabbrowser-tabs[orient="vertical"] &[collapsed] > .tabbrowser-tab:not([visuallyselected], [multiselected]), #tabbrowser-tabs[orient="vertical"] &[collapsed] > tab-split-view-wrapper:not([hasactivetab]) { display: none; diff --git a/browser/themes/shared/toolbarbutton-icons.css b/browser/themes/shared/toolbarbutton-icons.css index a291018d3b307..78e64eeaa6df8 100644 --- a/browser/themes/shared/toolbarbutton-icons.css +++ b/browser/themes/shared/toolbarbutton-icons.css @@ -320,6 +320,14 @@ &:is([overflowedItem="true"], [cui-areatype="panel"]) { list-style-image: url("chrome://browser/content/ipprotection/assets/states/ipprotection-off.svg"); + &::after { + -moz-context-properties: fill, fill-opacity; + content: url(chrome://global/skin/icons/arrow-right.svg); + fill: currentColor; + display: flex; + opacity: 0.6; + } + > .toolbarbutton-icon { width: var(--icon-size-small); height: var(--icon-size-small); diff --git a/browser/themes/shared/urlbarView.css b/browser/themes/shared/urlbarView.css index 95241d608797c..d266fba651424 100644 --- a/browser/themes/shared/urlbarView.css +++ b/browser/themes/shared/urlbarView.css @@ -910,12 +910,6 @@ flex-basis: 32px; } - &[icon-size="38"] { - width: 38px; - height: 38px; - flex-basis: 38px; - } - &[icon-size="52"] { width: 52px; height: 52px; @@ -1075,15 +1069,7 @@ } } -/* Sponsored Firefox Suggest rows */ - -.urlbarView-row[type$="_adm_sponsored"][icon-size="16"] > .urlbarView-row-inner { - /* Keep the status quo before these rows were rich suggestions, where the row - height is roughly the same as usual rows. */ - padding-block: 0; -} - -/* Other Firefox Suggest rows */ +/* Firefox Suggest rows */ .urlbarView-row[type$="_amo"][icon-size="24"] > .urlbarView-row-inner > .urlbarView-favicon { padding: calc((var(--urlbarView-top-pick-large-icon-box-size) - 24px) / 2); diff --git a/build/moz.configure/util.configure b/build/moz.configure/util.configure index b39010c6a947d..f0b6bd2c0b7b5 100644 --- a/build/moz.configure/util.configure +++ b/build/moz.configure/util.configure @@ -26,8 +26,12 @@ def configure_error(message): @imports("subprocess") @imports(_from="mozshellutil", _import="quote") @imports(_from="mozbuild.util", _import="system_encoding") +@imports(_from="mozbuild.util", _import="sanitize_shell_env") def get_cmd_output(*args, **kwargs): log.debug("Executing: `%s`", quote(*args)) + env = kwargs.get("env") or os.environ + if env: + kwargs["env"] = sanitize_shell_env(env) proc = subprocess.Popen( args, stdout=subprocess.PIPE, diff --git a/build/rust/windows-link/Cargo.toml b/build/rust/windows-link/Cargo.toml new file mode 100644 index 0000000000000..c94cfa449ea99 --- /dev/null +++ b/build/rust/windows-link/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "windows-link" +version = "0.2.999" +edition = "2018" +license = "MIT OR Apache-2.0" + +[lib] +proc-macro = true +path = "lib.rs" + +[dependencies] +syn = { version = "2", features = ["full"] } +quote = "1" diff --git a/build/rust/windows-link/lib.rs b/build/rust/windows-link/lib.rs new file mode 100644 index 0000000000000..439bc4694697e --- /dev/null +++ b/build/rust/windows-link/lib.rs @@ -0,0 +1,86 @@ +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use proc_macro::TokenStream; +use quote::quote; +use syn::parse::{Parse, ParseStream, Result}; +use syn::{parse_macro_input, Attribute, LitStr, Signature}; + +/* Proc macro equivalent to the following rust macro: + * ``` + * macro_rules! link { + * ($library:literal $abi:literal $($link_name:literal)? $(#[$($doc:tt)*])* fn $name:ident($($arg:ident: $argty:ty),*)->$ret:ty) => ( + * extern $abi { + * #[link(name = $library)] + * $(#[link_name=$link_name])? + * pub fn $name($($arg: $argty),*) -> $ret; + * } + * ) + * } + * ``` + * with the additional feature of removing ".dll" from the $library literal. + * + * The macro is derived from the equivalent macro in the real windows-targets crate, + * with the difference that it uses #[link] with the name of the library rather than + * a single "windows.$version" library, so as to avoid having to vendor all the fake + * "windows.$version" import libraries. We can do that because we also require MSVC + * to build, so we do have the real import libraries available. + * + * As the library name is there in the original for raw-dylib support, it contains + * a suffixed name, but plain #[link] expects a non-suffixed name, which is why we + * remove the suffix (and why this had to be a proc-macro). + * + * Once raw-dylib is more widely available and tested, we'll be able to use the + * raw-dylib variants directly. + */ + +struct LinkMacroInput { + library: LitStr, + abi: LitStr, + link_name: Option, + function: Signature, +} + +impl Parse for LinkMacroInput { + fn parse(input: ParseStream) -> Result { + let library: LitStr = input.parse()?; + let abi: LitStr = input.parse()?; + let link_name: Option = input.parse().ok(); + let _doc_comments = Attribute::parse_outer(input)?; + let function: Signature = input.parse()?; + Ok(LinkMacroInput { + library, + abi, + link_name, + function, + }) + } +} + +#[proc_macro] +pub fn link(input: TokenStream) -> TokenStream { + let LinkMacroInput { + library, + abi, + link_name, + function, + } = parse_macro_input!(input as LinkMacroInput); + + let link_name_attr = link_name.map(|lit| quote! { #[link_name = #lit] }); + + let library = library.value(); + let library = library.strip_suffix(".dll").unwrap_or(&library); + + let generated = quote! { + extern #abi { + #[link(name = #library)] + #link_name_attr + pub #function; + } + }; + + TokenStream::from(generated) +} diff --git a/build/rust/windows-targets/Cargo.toml b/build/rust/windows-targets/Cargo.toml index 5d3f665d7bc85..f2eb32ee77969 100644 --- a/build/rust/windows-targets/Cargo.toml +++ b/build/rust/windows-targets/Cargo.toml @@ -2,12 +2,10 @@ name = "windows-targets" version = "0.52.999" edition = "2018" -license = "MIT OR Apache-2.0" +license = "MPL-2.0" [lib] -proc-macro = true path = "lib.rs" [dependencies] -syn = { version = "2", features = ["full"] } -quote = "1" +windows-link = "0.2" diff --git a/build/rust/windows-targets/lib.rs b/build/rust/windows-targets/lib.rs index 439bc4694697e..5e89b0ba899ac 100644 --- a/build/rust/windows-targets/lib.rs +++ b/build/rust/windows-targets/lib.rs @@ -1,86 +1,8 @@ -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use proc_macro::TokenStream; -use quote::quote; -use syn::parse::{Parse, ParseStream, Result}; -use syn::{parse_macro_input, Attribute, LitStr, Signature}; +#![no_std] -/* Proc macro equivalent to the following rust macro: - * ``` - * macro_rules! link { - * ($library:literal $abi:literal $($link_name:literal)? $(#[$($doc:tt)*])* fn $name:ident($($arg:ident: $argty:ty),*)->$ret:ty) => ( - * extern $abi { - * #[link(name = $library)] - * $(#[link_name=$link_name])? - * pub fn $name($($arg: $argty),*) -> $ret; - * } - * ) - * } - * ``` - * with the additional feature of removing ".dll" from the $library literal. - * - * The macro is derived from the equivalent macro in the real windows-targets crate, - * with the difference that it uses #[link] with the name of the library rather than - * a single "windows.$version" library, so as to avoid having to vendor all the fake - * "windows.$version" import libraries. We can do that because we also require MSVC - * to build, so we do have the real import libraries available. - * - * As the library name is there in the original for raw-dylib support, it contains - * a suffixed name, but plain #[link] expects a non-suffixed name, which is why we - * remove the suffix (and why this had to be a proc-macro). - * - * Once raw-dylib is more widely available and tested, we'll be able to use the - * raw-dylib variants directly. - */ - -struct LinkMacroInput { - library: LitStr, - abi: LitStr, - link_name: Option, - function: Signature, -} - -impl Parse for LinkMacroInput { - fn parse(input: ParseStream) -> Result { - let library: LitStr = input.parse()?; - let abi: LitStr = input.parse()?; - let link_name: Option = input.parse().ok(); - let _doc_comments = Attribute::parse_outer(input)?; - let function: Signature = input.parse()?; - Ok(LinkMacroInput { - library, - abi, - link_name, - function, - }) - } -} - -#[proc_macro] -pub fn link(input: TokenStream) -> TokenStream { - let LinkMacroInput { - library, - abi, - link_name, - function, - } = parse_macro_input!(input as LinkMacroInput); - - let link_name_attr = link_name.map(|lit| quote! { #[link_name = #lit] }); - - let library = library.value(); - let library = library.strip_suffix(".dll").unwrap_or(&library); - - let generated = quote! { - extern #abi { - #[link(name = #library)] - #link_name_attr - pub #function; - } - }; - - TokenStream::from(generated) -} +#[doc(hidden)] +pub use windows_link::*; diff --git a/dom/canvas/TexUnpackBlob.cpp b/dom/canvas/TexUnpackBlob.cpp index 00826c13fc78a..104e4155bb378 100644 --- a/dom/canvas/TexUnpackBlob.cpp +++ b/dom/canvas/TexUnpackBlob.cpp @@ -1157,8 +1157,8 @@ bool TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec, surf = mDesc.sourceSurf->GetDataSurface(); } if (!surf) { - gfxCriticalError() << "TexUnpackSurface failed to create wrapping " - "DataSourceSurface for Shmem."; + gfxCriticalNote << "TexUnpackSurface failed to create wrapping " + "DataSourceSurface."; return false; } } else if (mDesc.sourceSurf) { diff --git a/dom/canvas/test/crossorigin/mochitest.toml b/dom/canvas/test/crossorigin/mochitest.toml index 86d469bf7aa81..d9a17d7727cca 100644 --- a/dom/canvas/test/crossorigin/mochitest.toml +++ b/dom/canvas/test/crossorigin/mochitest.toml @@ -10,6 +10,7 @@ support-files = [ # The video used in those tests crash the Android emulator's VP9 decoder. prefs = [ "media.android-media-codec.enabled=false", + "media.ffvpx-hw.enabled=false", ] ["test_canvas2d_crossorigin.html"] diff --git a/dom/canvas/test/mochitest.toml b/dom/canvas/test/mochitest.toml index d7b48a9cbe8f4..f484040ee0140 100644 --- a/dom/canvas/test/mochitest.toml +++ b/dom/canvas/test/mochitest.toml @@ -41,6 +41,7 @@ support-files = [ # The video used in those tests crash the Android emulator's VP9 decoder. prefs = [ "media.android-media-codec.enabled=false", + "media.ffvpx-hw.enabled=false", ] ["test_2d.clearRect.image.offscreen.html"] diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp index 9185b0e0c7f39..f92d7e786f938 100644 --- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -1150,6 +1150,10 @@ nsresult EventStateManager::PreHandleEvent(nsPresContext* aPresContext, // will be generated by GenerateMouseEnterExit mouseEvent->mMessage = eMouseMove; mouseEvent->mReason = WidgetMouseEvent::eSynthesized; + // We need to generate pointer boundary events here because there is no + // preceding pointer event dispatched for the eMouseExitFromWidget + // event. + GeneratePointerEnterExit(ePointerMove, mouseEvent); // then fall through... } else { MOZ_ASSERT_IF(XRE_IsParentProcess(), diff --git a/dom/events/test/pointerevents/mochitest.toml b/dom/events/test/pointerevents/mochitest.toml index 75c3cc8cb7cd1..859bddb42c4f9 100644 --- a/dom/events/test/pointerevents/mochitest.toml +++ b/dom/events/test/pointerevents/mochitest.toml @@ -101,6 +101,11 @@ support-files = ["!/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js ["test_multiple_touches.html"] +["test_pointer_boundary_events_iframe.html"] +skip-if = [ + "os == 'android'", # Bug 2014260 +] + ["test_pointercancel_target_at_dragstart.html"] ["test_pointercancel_target_at_dragstart_with_capture.html"] diff --git a/dom/events/test/pointerevents/test_pointer_boundary_events_iframe.html b/dom/events/test/pointerevents/test_pointer_boundary_events_iframe.html new file mode 100644 index 0000000000000..d1dba7f4c6fbb --- /dev/null +++ b/dom/events/test/pointerevents/test_pointer_boundary_events_iframe.html @@ -0,0 +1,120 @@ + + + +Test for pointer boundary events + + + + + + +
+

+
+ + +
+ + + diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index d931f7a23a3b1..5d4f72a1686c4 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -674,8 +674,9 @@ void MediaDecoder::DiscardOngoingSeekIfExists() { void MediaDecoder::CallSeek(const SeekTarget& aTarget) { MOZ_ASSERT(NS_IsMainThread()); if (mShouldDelaySeek) { - LOG("Delay seek to %f and store it to delayed seek target", - mDelayedSeekTarget->GetTime().ToSeconds()); + LOG("Delay seek to %f (was %f) and store it to delayed seek target", + aTarget.GetTime().ToSeconds(), + mDelayedSeekTarget ? mDelayedSeekTarget->GetTime().ToSeconds() : 0.0f); mDelayedSeekTarget = Some(aTarget); return; } diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp index 5ada6dad7cdf5..b91d26c729350 100644 --- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp @@ -646,6 +646,12 @@ void FFmpegVideoDecoder::InitHWDecoderIfAllowed() { return; } +# ifdef FFVPX_VERSION + if (!StaticPrefs::media_ffvpx_hw_enabled()) { + return; + } +# endif + # ifdef MOZ_ENABLE_VAAPI if (NS_SUCCEEDED(InitVAAPIDecoder())) { return; @@ -2517,6 +2523,12 @@ MediaResult FFmpegVideoDecoder::InitMediaCodecDecoder() { FFMPEG_LOG("Initialising MediaCodec FFmpeg decoder"); StaticMutexAutoLock mon(sMutex); + if (StaticPrefs::media_ffvpx_hw_minimal() && mCodecID != AV_CODEC_ID_H264 && + mCodecID != AV_CODEC_ID_HEVC) { + return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, + RESULT_DETAIL("codec not allowed when minimal")); + } + if (mInfo.mColorDepth > gfx::ColorDepth::COLOR_10) { return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, RESULT_DETAIL("not supported color depth")); diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoEncoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoEncoder.cpp index a55242aa44af8..71674d21a8edb 100644 --- a/dom/media/platforms/ffmpeg/FFmpegVideoEncoder.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegVideoEncoder.cpp @@ -329,6 +329,10 @@ bool FFmpegVideoEncoder::ShouldTryHardware() const { if (mCodecID == AV_CODEC_ID_H264 || mCodecID == AV_CODEC_ID_HEVC) { return StaticPrefs::media_ffvpx_hw_enabled(); } + + if (StaticPrefs::media_ffvpx_hw_minimal()) { + return false; + } #endif if (mConfig.mHardwarePreference == HardwarePreference::RequireSoftware) { diff --git a/dom/media/test/mochitest_stream.toml b/dom/media/test/mochitest_stream.toml index 9b393d275f008..7e8d34bd1721e 100644 --- a/dom/media/test/mochitest_stream.toml +++ b/dom/media/test/mochitest_stream.toml @@ -702,6 +702,7 @@ support-files = [ # painting a video to the canvas throws. bug 1372457, bug 1526207 prefs = [ "media.android-media-codec.preferred=false", + "media.ffvpx-hw.minimal=true", ] ["test_streams_capture_origin.html"] diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate.c b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate.c index 2146bded385bf..c95f593302a99 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate.c @@ -85,8 +85,8 @@ void nr_ice_candidate_compute_codeword(nr_ice_candidate *cand) nr_ice_compute_codeword(as_string,strlen(as_string),cand->codeword); } -char *nr_ice_candidate_type_names[]={0,"host","srflx","prflx","relay",0}; -char *nr_ice_candidate_tcp_type_names[]={0,"active","passive","so",0}; +const char *nr_ice_candidate_type_names[]={0,"host","srflx","prflx","relay",0}; +const char *nr_ice_candidate_tcp_type_names[]={0,"active","passive","so",0}; static const char *nr_ctype_name(nr_ice_candidate_type ctype) { assert(ctype0); @@ -121,7 +121,7 @@ int nr_ice_candidate_create(nr_ice_ctx *ctx,nr_ice_component *comp,nr_ice_socket int r,_status; char label[512]; - if(!(cand=RCALLOC(sizeof(nr_ice_candidate)))) + if(!(cand=R_NEW(nr_ice_candidate))) ABORT(R_NO_MEMORY); cand->state=NR_ICE_CAND_STATE_CREATED; cand->ctx=ctx; @@ -215,13 +215,13 @@ int nr_ice_candidate_create(nr_ice_ctx *ctx,nr_ice_component *comp,nr_ice_socket /* Create a peer reflexive candidate */ -int nr_ice_peer_peer_rflx_candidate_create(nr_ice_ctx *ctx,char *label, nr_ice_component *comp,nr_transport_addr *addr, nr_ice_candidate **candp) +int nr_ice_peer_peer_rflx_candidate_create(nr_ice_ctx *ctx, const char *label, nr_ice_component *comp,nr_transport_addr *addr, nr_ice_candidate **candp) { nr_ice_candidate *cand=0; nr_ice_candidate_type ctype=PEER_REFLEXIVE; int r,_status; - if(!(cand=RCALLOC(sizeof(nr_ice_candidate)))) + if(!(cand=R_NEW(nr_ice_candidate))) ABORT(R_NO_MEMORY); if(!(cand->label=r_strdup(label))) ABORT(R_NO_MEMORY); @@ -395,7 +395,7 @@ static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand) i++; } - if(!(foundation=RCALLOC(sizeof(nr_ice_foundation)))) + if(!(foundation=R_NEW(nr_ice_foundation))) ABORT(R_NO_MEMORY); nr_transport_addr_copy(&foundation->addr,&cand->base); foundation->type=cand->type; @@ -567,7 +567,7 @@ int nr_ice_candidate_compute_priority(nr_ice_candidate *cand) static void nr_ice_candidate_fire_ready_cb(NR_SOCKET s, int how, void *cb_arg) { - nr_ice_candidate *cand = cb_arg; + nr_ice_candidate *cand = (nr_ice_candidate*)cb_arg; cand->ready_cb_timer = 0; cand->ready_cb(0, 0, cand->ready_cb_arg); @@ -643,7 +643,7 @@ int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, vo #ifdef USE_TURN case RELAYED: protocol=NR_RESOLVE_PROTOCOL_TURN; - /* Fall through */ + [[fallthrough]]; #endif case SERVER_REFLEXIVE: if (nr_transport_addr_cmp(&cand->base, &cand->stun_server->addr, @@ -736,7 +736,7 @@ int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, vo static int nr_ice_candidate_resolved_cb(void *cb_arg, nr_transport_addr *addr) { - nr_ice_candidate *cand=cb_arg; + nr_ice_candidate *cand=(nr_ice_candidate*)cb_arg; int r,_status; cand->resolver_handle=0; @@ -810,7 +810,7 @@ static int nr_ice_candidate_initialize2(nr_ice_candidate *cand) static void nr_ice_srvrflx_start_stun_timer_cb(NR_SOCKET s, int how, void *cb_arg) { - nr_ice_candidate *cand=cb_arg; + nr_ice_candidate *cand=(nr_ice_candidate*)cb_arg; int r,_status; cand->delay_timer=0; @@ -863,7 +863,7 @@ static int nr_ice_srvrflx_start_stun(nr_ice_candidate *cand) #ifdef USE_TURN static void nr_ice_start_relay_turn_timer_cb(NR_SOCKET s, int how, void *cb_arg) { - nr_ice_candidate *cand=cb_arg; + nr_ice_candidate *cand=(nr_ice_candidate*)cb_arg; int r,_status; cand->delay_timer=0; @@ -910,7 +910,7 @@ static int nr_ice_start_relay_turn(nr_ice_candidate *cand) static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg) { int _status; - nr_ice_candidate *cand=cb_arg; + nr_ice_candidate *cand=(nr_ice_candidate*)cb_arg; r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/CAND(%s): %s",cand->ctx->label,cand->label,__FUNCTION__); @@ -950,7 +950,7 @@ static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_ar static void nr_ice_turn_allocated_cb(NR_SOCKET s, int how, void *cb_arg) { int r,_status; - nr_ice_candidate *cand=cb_arg; + nr_ice_candidate *cand=(nr_ice_candidate*)cb_arg; nr_turn_client_ctx *turn=cand->u.relayed.turn; char *label; nr_transport_addr relay_addr; diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate.h b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate.h index 89442c17ccc28..a191dbe367f4d 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate.h +++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate.h @@ -105,8 +105,8 @@ struct nr_ice_candidate_ { TAILQ_ENTRY(nr_ice_candidate_) entry_comp; }; -extern char *nr_ice_candidate_type_names[]; -extern char *nr_ice_candidate_tcp_type_names[]; +extern const char *nr_ice_candidate_type_names[]; +extern const char *nr_ice_candidate_tcp_type_names[]; int nr_ice_candidate_create(struct nr_ice_ctx_ *ctx,nr_ice_component *component, nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_socket_tcp_type tcp_type, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp); @@ -117,7 +117,7 @@ int nr_ice_candidate_destroy(nr_ice_candidate **candp); void nr_ice_candidate_stop_gathering(nr_ice_candidate *cand); int nr_ice_format_candidate_attribute(nr_ice_candidate *cand, char *attr, int maxlen, int obfuscate_srflx_addr); int nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *attr,nr_ice_media_stream *stream,nr_ice_candidate **candp); -int nr_ice_peer_peer_rflx_candidate_create(nr_ice_ctx *ctx,char *label, nr_ice_component *comp,nr_transport_addr *addr, nr_ice_candidate **candp); +int nr_ice_peer_peer_rflx_candidate_create(nr_ice_ctx *ctx, const char *label, nr_ice_component *comp,nr_transport_addr *addr, nr_ice_candidate **candp); int nr_ice_candidate_compute_priority(nr_ice_candidate *cand); #ifdef __cplusplus diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate_pair.c b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate_pair.c index becb917ea8d10..bb2724cf1868b 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate_pair.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate_pair.c @@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ice_codeword.h" #include "stun.h" -static char *nr_ice_cand_pair_states[]={"UNKNOWN","FROZEN","WAITING","IN_PROGRESS","FAILED","SUCCEEDED","CANCELLED"}; +static const char *nr_ice_cand_pair_states[]={"UNKNOWN","FROZEN","WAITING","IN_PROGRESS","FAILED","SUCCEEDED","CANCELLED"}; static void nr_ice_candidate_pair_restart_stun_role_change_cb(NR_SOCKET s, int how, void *cb_arg); static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair, @@ -70,8 +70,9 @@ int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand, UINT4 RTO; nr_ice_candidate tmpcand; UINT8 t_priority; + int flags = 0; - if(!(pair=RCALLOC(sizeof(nr_ice_cand_pair)))) + if(!(pair=R_NEW(nr_ice_cand_pair))) ABORT(R_NO_MEMORY); pair->pctx=pctx; @@ -129,7 +130,7 @@ int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand, ABORT(r); t_priority = tmpcand.priority; - int flags = NR_STUN_TRANSPORT_ADDR_CHECK_WILDCARD; + flags = NR_STUN_TRANSPORT_ADDR_CHECK_WILDCARD; if (!(pctx->ctx->flags & NR_ICE_CTX_FLAGS_ALLOW_LOOPBACK)) { flags |= NR_STUN_TRANSPORT_ADDR_CHECK_LOOPBACK; } @@ -208,7 +209,7 @@ int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg) { int r,_status; - nr_ice_cand_pair *pair=cb_arg; + nr_ice_cand_pair *pair=(nr_ice_cand_pair*)cb_arg; nr_ice_cand_pair *actual_pair=0; nr_ice_candidate *cand=0; nr_stun_message *sres; @@ -242,7 +243,7 @@ static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg) return; } - /* Fall through */ + [[fallthrough]]; case NR_STUN_CLIENT_STATE_TIMED_OUT: nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED); break; @@ -499,10 +500,10 @@ int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_ /* OK, there was a pair, it's just invalid: According to Section * 7.2.1.4, we need to resurrect it */ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): received STUN check on failed pair, resurrecting: %s",pctx->label,pair->codeword,pair->as_string); - /* fall through */ + [[fallthrough]]; case NR_ICE_PAIR_STATE_FROZEN: nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING); - /* fall through even further */ + [[fallthrough]]; case NR_ICE_PAIR_STATE_WAITING: /* Append it additionally to the trigger check queue */ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): Inserting pair to trigger check queue: %s",pctx->label,pair->codeword,pair->as_string); @@ -510,7 +511,7 @@ int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_ break; case NR_ICE_PAIR_STATE_CANCELLED: r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): received STUN check on cancelled pair, resurrecting: %s",pctx->label,pair->codeword,pair->as_string); - /* fall through */ + [[fallthrough]]; case NR_ICE_PAIR_STATE_IN_PROGRESS: /* Instead of trying to maintain two stun contexts on the same pair, * and handling heterogenous responses and error conditions, we instead @@ -626,7 +627,7 @@ void nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair * void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg) { - nr_ice_cand_pair *pair=cb_arg; + nr_ice_cand_pair *pair=(nr_ice_cand_pair*)cb_arg; int r,_status; pair->restart_nominated_cb_timer=0; @@ -654,7 +655,7 @@ void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void static void nr_ice_candidate_pair_restart_stun_role_change_cb(NR_SOCKET s, int how, void *cb_arg) { - nr_ice_cand_pair *pair=cb_arg; + nr_ice_cand_pair *pair=(nr_ice_cand_pair*)cb_arg; pair->restart_role_change_cb_timer=0; diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c index be86e1736114f..d13150ebe6e5a 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c @@ -64,7 +64,7 @@ static int nr_ice_pre_answer_request_create(nr_transport_addr *dst, nr_stun_serv nr_ice_pre_answer_request *par = 0; nr_stun_message_attribute *attr; - if (!(par = RCALLOC(sizeof(nr_ice_pre_answer_request)))) + if (!(par = R_NEW(nr_ice_pre_answer_request))) ABORT(R_NO_MEMORY); par->req = *req; /* Struct assignment */ @@ -113,7 +113,7 @@ int nr_ice_component_create(nr_ice_media_stream *stream, int component_id, nr_ic int _status; nr_ice_component *comp=0; - if(!(comp=RCALLOC(sizeof(nr_ice_component)))) + if(!(comp=R_NEW(nr_ice_component))) ABORT(R_NO_MEMORY); comp->state=NR_ICE_COMPONENT_UNPAIRED; @@ -247,7 +247,7 @@ static int nr_ice_component_initialize_udp(struct nr_ice_ctx_ *ctx,nr_ice_compon if (!(component->stream->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY)) { /* Create one host candidate */ - if(r=nr_ice_candidate_create(ctx,component,isock,sock,HOST,0,0, + if(r=nr_ice_candidate_create(ctx,component,isock,sock,HOST,TCP_TYPE_NONE,0, component->component_id,&cand)) ABORT(r); @@ -270,7 +270,7 @@ static int nr_ice_component_initialize_udp(struct nr_ice_ctx_ *ctx,nr_ice_compon /* Ensure id is set (nr_ice_ctx_set_stun_servers does not) */ component->stream->stun_servers[j].id = j; if(r=nr_ice_candidate_create(ctx,component, - isock,sock,SERVER_REFLEXIVE,0, + isock,sock,SERVER_REFLEXIVE,TCP_TYPE_NONE, &component->stream->stun_servers[j],component->component_id,&cand)) ABORT(r); TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp); @@ -310,7 +310,7 @@ static int nr_ice_component_initialize_udp(struct nr_ice_ctx_ *ctx,nr_ice_compon component->stream->turn_servers[j].turn_server.id = j + component->stream->stun_server_ct; /* srvrflx */ if(r=nr_ice_candidate_create(ctx,component, - isock,sock,SERVER_REFLEXIVE,0, + isock,sock,SERVER_REFLEXIVE,TCP_TYPE_NONE, &component->stream->turn_servers[j].turn_server,component->component_id,&cand)) ABORT(r); cand->state=NR_ICE_CAND_STATE_INITIALIZING; /* Don't start */ @@ -326,7 +326,7 @@ static int nr_ice_component_initialize_udp(struct nr_ice_ctx_ *ctx,nr_ice_compon if(r=nr_socket_turn_create(&turn_sock)) ABORT(r); if(r=nr_ice_candidate_create(ctx,component, - isock,turn_sock,RELAYED,0, + isock,turn_sock,RELAYED,TCP_TYPE_NONE, &component->stream->turn_servers[j].turn_server,component->component_id,&cand)) ABORT(r); if (srvflx_cand) { @@ -351,7 +351,7 @@ static int nr_ice_component_get_port_from_ephemeral_range(uint16_t *port) { int _status, r; void *buf = port; - if(r=nr_crypto_random_bytes(buf, 2)) + if(r=nr_crypto_random_bytes((UCHAR*)buf, 2)) ABORT(r); *port|=49152; /* make it fit into IANA ephemeral port range >= 49152 */ _status=0; @@ -999,7 +999,7 @@ static int nr_ice_component_process_incoming_check(nr_ice_component *comp, nr_tr static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun_ctx,nr_socket *sock, nr_stun_server_request *req, int *dont_free, int *error) { - nr_ice_component *pcomp=cb_arg; + nr_ice_component *pcomp=(nr_ice_component*)cb_arg; nr_transport_addr local_addr; int r,_status; @@ -1307,7 +1307,7 @@ static void nr_ice_component_consent_failed(nr_ice_component *comp) static void nr_ice_component_consent_timeout_cb(NR_SOCKET s, int how, void *cb_arg) { - nr_ice_component *comp=cb_arg; + nr_ice_component *comp=(nr_ice_component*)cb_arg; comp->consent_timeout = 0; @@ -1365,7 +1365,7 @@ static void nr_ice_component_consent_refreshed(nr_ice_component *comp) static void nr_ice_component_refresh_consent_cb(NR_SOCKET s, int how, void *cb_arg) { - nr_ice_cand_pair *pair=cb_arg; + nr_ice_cand_pair *pair=(nr_ice_cand_pair*)cb_arg; assert(pair && pair->remote && pair->remote->component); nr_ice_component *comp=pair->remote->component; @@ -1431,7 +1431,7 @@ void nr_ice_component_consent_calc_consent_timer(nr_ice_component *comp) static void nr_ice_component_consent_timer_cb(NR_SOCKET s, int how, void *cb_arg) { - nr_ice_component *comp=cb_arg; + nr_ice_component *comp=(nr_ice_component*)cb_arg; int r; if (!comp->consent_ctx) { @@ -1678,7 +1678,7 @@ int nr_ice_component_select_pair(nr_ice_peer_ctx *pctx, nr_ice_component *comp) } /* Make and fill the array */ - if(!(pairs=RCALLOC(sizeof(nr_ice_cand_pair *)*ct))) + if(!(pairs=R_NEW_CNT(nr_ice_cand_pair*, ct))) ABORT(R_NO_MEMORY); ct=0; diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c index 3cb787798968e..d574a92353335 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c @@ -82,7 +82,7 @@ int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out) UINT2 port; in_addr_t addr_int; - if(!(servers=RCALLOC(sizeof(nr_ice_stun_server)*ct))) + if(!(servers=R_NEW_CNT(nr_ice_stun_server, ct))) ABORT(R_NO_MEMORY); for(i=0;istun_servers_cfg=RCALLOC(sizeof(nr_ice_stun_server)*ct))) + if(!(ctx->stun_servers_cfg=R_NEW_CNT(nr_ice_stun_server, ct))) ABORT(R_NO_MEMORY); memcpy(ctx->stun_servers_cfg,servers,sizeof(nr_ice_stun_server)*ct); @@ -155,7 +155,7 @@ int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers,int } if(ct) { - if(!(ctx->turn_servers_cfg=RCALLOC(sizeof(nr_ice_turn_server)*ct))) + if(!(ctx->turn_servers_cfg=R_NEW_CNT(nr_ice_turn_server, ct))) ABORT(R_NO_MEMORY); memcpy(ctx->turn_servers_cfg,servers,sizeof(nr_ice_turn_server)*ct); @@ -178,7 +178,7 @@ static int nr_ice_ctx_set_local_addrs(nr_ice_ctx *ctx,nr_local_addr *addrs,int c } if (ct) { - if(!(ctx->local_addrs=RCALLOC(sizeof(nr_local_addr)*ct))) + if(!(ctx->local_addrs=R_NEW_CNT(nr_local_addr, ct))) ABORT(R_NO_MEMORY); for (i=0;idata = data.data; @@ -309,7 +309,7 @@ int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out) if(r=r_log_register("ice", &LOG_ICE)) ABORT(r); - if(!(ctx=RCALLOC(sizeof(nr_ice_ctx)))) + if(!(ctx=R_NEW(nr_ice_ctx))) ABORT(R_NO_MEMORY); ctx->flags=flags; @@ -468,7 +468,7 @@ int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out) void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg) { int r; - nr_ice_candidate *cand=cb_arg; + nr_ice_candidate *cand=(nr_ice_candidate*)cb_arg; nr_ice_ctx *ctx; nr_ice_media_stream *stream; int component_id; @@ -824,7 +824,7 @@ int nr_ice_set_target_for_default_local_address_lookup(nr_ice_ctx *ctx, const ch ctx->target_for_default_local_address_lookup=0; } - if (!(ctx->target_for_default_local_address_lookup=RCALLOC(sizeof(nr_transport_addr)))) + if (!(ctx->target_for_default_local_address_lookup=R_NEW(nr_transport_addr))) ABORT(R_NO_MEMORY); if ((r=nr_str_port_to_transport_addr(target_ip, target_port, IPPROTO_UDP, ctx->target_for_default_local_address_lookup))) { @@ -975,7 +975,7 @@ int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg) int _status; nr_ice_stun_id *xid; - xid = RCALLOC(sizeof(*xid)); + xid = R_NEW(nr_ice_stun_id); if (!xid) ABORT(R_NO_MEMORY); diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c index 8379cbdd8fd5c..844d79f1ad824 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c @@ -38,7 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ice_util.h" #include "ice_ctx.h" -static char *nr_ice_media_stream_states[]={"INVALID", +static const char *nr_ice_media_stream_states[]={"INVALID", "UNPAIRED","FROZEN","ACTIVE","CONNECTED","FAILED" }; @@ -51,7 +51,7 @@ int nr_ice_media_stream_create(nr_ice_ctx *ctx,const char *label,const char *ufr nr_ice_component *comp=0; int i; - if(!(stream=RCALLOC(sizeof(nr_ice_media_stream)))) + if(!(stream=R_NEW(nr_ice_media_stream))) ABORT(R_NO_MEMORY); if(!(stream->label=r_strdup(label))) @@ -85,7 +85,7 @@ int nr_ice_media_stream_create(nr_ice_ctx *ctx,const char *label,const char *ufr stream->l2r_user = 0; stream->flags = ctx->flags; if(ctx->stun_server_ct_cfg) { - if(!(stream->stun_servers=RCALLOC(sizeof(nr_ice_stun_server)*(ctx->stun_server_ct_cfg)))) + if(!(stream->stun_servers=R_NEW_CNT(nr_ice_stun_server, ctx->stun_server_ct_cfg))) ABORT(R_NO_MEMORY); memcpy(stream->stun_servers,ctx->stun_servers_cfg,sizeof(nr_ice_stun_server)*(ctx->stun_server_ct_cfg)); @@ -93,7 +93,7 @@ int nr_ice_media_stream_create(nr_ice_ctx *ctx,const char *label,const char *ufr } if(ctx->turn_server_ct_cfg) { - if(!(stream->turn_servers=RCALLOC(sizeof(nr_ice_turn_server)*(ctx->turn_server_ct_cfg)))) + if(!(stream->turn_servers=R_NEW_CNT(nr_ice_turn_server, ctx->turn_server_ct_cfg))) ABORT(R_NO_MEMORY); for(int i = 0; i < ctx->turn_server_ct_cfg; ++i) { @@ -225,10 +225,10 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr } /* Make the array we'll need */ - if(!(attrs=RCALLOC(sizeof(char *)*attrct))) + if(!(attrs=R_NEW_CNT(char *, attrct))) ABORT(R_NO_MEMORY); for(index=0;indexufrag); attrs[index++]=tmp; - if(!(tmp=RMALLOC(100))) + if(!(tmp=(char*)RMALLOC(100))) ABORT(R_NO_MEMORY); snprintf(tmp,100,"ice-pwd:%s",stream->pwd); attrs[index++]=tmp; @@ -376,7 +376,7 @@ int nr_ice_media_stream_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ic static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg) { int r,_status; - nr_ice_media_stream *stream=cb_arg; + nr_ice_media_stream *stream=(nr_ice_media_stream*)cb_arg; nr_ice_cand_pair *pair = 0; int timer_multiplier=stream->pctx->active_streams ? stream->pctx->active_streams : 1; int timer_val=stream->pctx->ctx->Ta*timer_multiplier; diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_parser.c b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_parser.c index 740ab3ad452f0..9de7ae9317909 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_parser.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_parser.c @@ -93,7 +93,7 @@ grab_token(char **str, char **out) len = c - *str; - tmp = RMALLOC(len + 1); + tmp = (char*)RMALLOC(len + 1); if (!tmp) ABORT(R_NO_MEMORY); @@ -121,7 +121,7 @@ nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_str char *rel_addr=0; unsigned char transport; - if(!(cand=RCALLOC(sizeof(nr_ice_candidate)))) + if(!(cand=R_NEW(nr_ice_candidate))) ABORT(R_NO_MEMORY); if(!(cand->label=r_strdup(orig))) @@ -240,7 +240,7 @@ nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_str for (i = 1; nr_ice_candidate_type_names[i]; ++i) { if(!strncasecmp(nr_ice_candidate_type_names[i], str, strlen(nr_ice_candidate_type_names[i]))) { - cand->type=i; + cand->type=(nr_ice_candidate_type)i; break; } } @@ -324,7 +324,7 @@ nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_str for (i = 1; nr_ice_candidate_tcp_type_names[i]; ++i) { if(!strncasecmp(nr_ice_candidate_tcp_type_names[i], str, strlen(nr_ice_candidate_tcp_type_names[i]))) { - cand->tcp_type=i; + cand->tcp_type=(nr_socket_tcp_type)i; fast_forward(&str, strlen(nr_ice_candidate_tcp_type_names[i])); break; } diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c index ca7368615699f..6fe6cb20add59 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c @@ -51,7 +51,7 @@ int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, int r,_status; nr_ice_peer_ctx *pctx=0; - if(!(pctx=RCALLOC(sizeof(nr_ice_peer_ctx)))) + if(!(pctx=R_NEW(nr_ice_peer_ctx))) ABORT(R_NO_MEMORY); pctx->state = NR_ICE_PEER_STATE_UNPAIRED; @@ -359,7 +359,7 @@ int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_ static void nr_ice_peer_ctx_trickle_wait_cb(NR_SOCKET s, int how, void *cb_arg) { - nr_ice_peer_ctx *pctx=cb_arg; + nr_ice_peer_ctx *pctx=(nr_ice_peer_ctx*)cb_arg; nr_ice_media_stream *stream; nr_ice_component *comp; @@ -692,7 +692,7 @@ void nr_ice_peer_ctx_connected(nr_ice_peer_ctx *pctx) static void nr_ice_peer_ctx_fire_connected(NR_SOCKET s, int how, void *cb_arg) { - nr_ice_peer_ctx *pctx=cb_arg; + nr_ice_peer_ctx *pctx=(nr_ice_peer_ctx*)cb_arg; pctx->connected_cb_timer=0; diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_socket.c b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_socket.c index a6c8513300b0c..b60b434be9fea 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_socket.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_socket.c @@ -42,7 +42,7 @@ static void nr_ice_socket_readable_cb(NR_SOCKET s, int how, void *cb_arg) { int r; nr_ice_stun_ctx *sc1,*sc2; - nr_ice_socket *sock=cb_arg; + nr_ice_socket *sock=(nr_ice_socket*)cb_arg; UCHAR buf[9216]; char string[256]; nr_transport_addr addr; @@ -201,7 +201,7 @@ int nr_ice_socket_create(nr_ice_ctx *ctx,nr_ice_component *comp, nr_socket *nsoc nr_transport_addr addr; int r,_status; - if(!(sock=RCALLOC(sizeof(nr_ice_socket)))) + if(!(sock=R_NEW(nr_ice_socket))) ABORT(R_NO_MEMORY); sock->sock=nsock; @@ -307,7 +307,7 @@ int nr_ice_socket_register_stun_client(nr_ice_socket *sock, nr_stun_client_ctx * nr_ice_stun_ctx *sc=0; int _status; - if(!(sc=RCALLOC(sizeof(nr_ice_stun_ctx)))) + if(!(sc=R_NEW(nr_ice_stun_ctx))) ABORT(R_NO_MEMORY); sc->type=NR_ICE_STUN_CLIENT; @@ -327,7 +327,7 @@ int nr_ice_socket_register_stun_server(nr_ice_socket *sock, nr_stun_server_ctx * nr_ice_stun_ctx *sc=0; int _status; - if(!(sc=RCALLOC(sizeof(nr_ice_stun_ctx)))) + if(!(sc=R_NEW(nr_ice_stun_ctx))) ABORT(R_NO_MEMORY); sc->type=NR_ICE_STUN_SERVER; @@ -348,7 +348,7 @@ int nr_ice_socket_register_turn_client(nr_ice_socket *sock, nr_turn_client_ctx * nr_ice_stun_ctx *sc=0; int _status; - if(!(sc=RCALLOC(sizeof(nr_ice_stun_ctx)))) + if(!(sc=R_NEW(nr_ice_stun_ctx))) ABORT(R_NO_MEMORY); sc->type=NR_ICE_TURN_CLIENT; @@ -368,7 +368,7 @@ int nr_ice_socket_register_turn_client(nr_ice_socket *sock, nr_turn_client_ctx * in the CB, which is where this is likely to be called */ int nr_ice_socket_deregister(nr_ice_socket *sock, void *handle) { - nr_ice_stun_ctx *sc=handle; + nr_ice_stun_ctx *sc=(nr_ice_stun_ctx*)handle; if(!sc) return(0); diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_interface_prioritizer.c b/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_interface_prioritizer.c index 75e5f9546780c..8e2c0dcb347b8 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_interface_prioritizer.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_interface_prioritizer.c @@ -43,7 +43,7 @@ int nr_interface_prioritizer_create_int(void *obj, int _status; nr_interface_prioritizer *ifp=0; - if(!(ifp=RCALLOC(sizeof(nr_interface_prioritizer)))) + if(!(ifp=R_NEW(nr_interface_prioritizer))) ABORT(R_NO_MEMORY); ifp->obj = obj; diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_resolver.c b/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_resolver.c index 4dbf1bbe913de..f5f47a464a53d 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_resolver.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_resolver.c @@ -41,7 +41,7 @@ int nr_resolver_create_int(void *obj, nr_resolver_vtbl *vtbl, nr_resolver **reso int _status; nr_resolver *resolver=0; - if (!(resolver=RCALLOC(sizeof(nr_resolver)))) + if (!(resolver=R_NEW(nr_resolver))) ABORT(R_NO_MEMORY); resolver->obj=obj; diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_socket.c b/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_socket.c index c9867610a6cc0..ff44731c30737 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_socket.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_socket.c @@ -41,7 +41,7 @@ int nr_socket_create_int(void *obj, nr_socket_vtbl *vtbl, nr_socket **sockp) int _status; nr_socket *sock=0; - if(!(sock=RCALLOC(sizeof(nr_socket)))) + if(!(sock=R_NEW(nr_socket))) ABORT(R_NO_MEMORY); assert(vtbl->version >= 1 && vtbl->version <= 2); @@ -153,7 +153,7 @@ int nr_socket_factory_create_int(void *obj, int _status; nr_socket_factory *factoryp=0; - if(!(factoryp=RCALLOC(sizeof(nr_socket_factory)))) + if(!(factoryp=R_NEW(nr_socket_factory))) ABORT(R_NO_MEMORY); factoryp->obj = obj; diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_socket_multi_tcp.c b/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_socket_multi_tcp.c index 9b2489b2142a0..8894324d6e339 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_socket_multi_tcp.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/net/nr_socket_multi_tcp.c @@ -79,7 +79,7 @@ static int nr_tcp_socket_ctx_create(nr_socket *nrsock, int is_framed, nr_tcp_socket_ctx *sock = 0; nr_socket *tcpsock; - if (!(sock = RCALLOC(sizeof(nr_tcp_socket_ctx)))) { + if (!(sock = R_NEW(nr_tcp_socket_ctx))) { nr_socket_destroy(&nrsock); ABORT(R_NO_MEMORY); } @@ -231,7 +231,7 @@ int nr_socket_multi_tcp_create(struct nr_ice_ctx_ *ctx, nr_tcp_socket_ctx *tcp_socket_ctx; nr_socket * nrsock; - if (!(sock = RCALLOC(sizeof(nr_socket_multi_tcp)))) + if (!(sock = R_NEW(nr_socket_multi_tcp))) ABORT(R_NO_MEMORY); TAILQ_INIT(&sock->sockets); diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c index 8d22e5979ea38..293061a5f8062 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c @@ -83,7 +83,7 @@ static int get_siocgifflags(nr_local_addr *addr) { } struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, addr->addr.ifname, IFNAMSIZ - 1); + (void)strlcpy(ifr.ifr_name, addr->addr.ifname, sizeof(ifr.ifr_name)); int rc = ioctl(fd, SIOCGIFFLAGS, &ifr); close(fd); if (rc == -1) { @@ -150,12 +150,12 @@ stun_convert_netlink(nr_local_addr *addr, struct ifaddrmsg *address_msg, struct int e; int s = socket(AF_INET, SOCK_DGRAM, 0); - strncpy(ifr.ifr_name, addr->addr.ifname, sizeof(ifr.ifr_name)); + (void)strlcpy(ifr.ifr_name, addr->addr.ifname, sizeof(ifr.ifr_name)); /* TODO (Bug 896851): interface property for Android */ /* Getting ethtool for ethernet information. */ ecmd.cmd = ETHTOOL_GSET; /* In/out param */ - ifr.ifr_data = (void*)&ecmd; + ifr.ifr_data = (char*)&ecmd; e = ioctl(s, SIOCETHTOOL, &ifr); if (e == 0) @@ -170,7 +170,7 @@ stun_convert_netlink(nr_local_addr *addr, struct ifaddrmsg *address_msg, struct #endif } - strncpy(wrq.ifr_name, addr->addr.ifname, sizeof(wrq.ifr_name)); + (void)strlcpy(wrq.ifr_name, addr->addr.ifname, sizeof(wrq.ifr_name)); e = ioctl(s, SIOCGIWRATE, &wrq); if (e == 0) { diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-win32.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-win32.c index a1b0cd9f0aba2..f7e79339bf4ce 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-win32.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-win32.c @@ -65,7 +65,7 @@ static int nr_win32_get_adapter_friendly_name(char *adapter_GUID, char **friendl #ifdef UNICODE newlen = wcslen(keyval_buf)+1; - my_fn = (char *) RCALLOC(newlen); + my_fn = (char *) RCALLOC_RAWSIZE(newlen); if (!my_fn) { ABORT(R_NO_MEMORY); } @@ -149,10 +149,10 @@ stun_getaddrs_filtered(nr_local_addr addrs[], int maxaddrs, int *count) if(r=nr_crypto_md5((UCHAR *)tmpAddress->FriendlyName, wcslen(tmpAddress->FriendlyName) * sizeof(wchar_t), - bin_hashed_ifname)) + (UCHAR *)bin_hashed_ifname)) ABORT(r); - if(r=nr_bin2hex(bin_hashed_ifname, sizeof(bin_hashed_ifname), - hex_hashed_ifname)) + if(r=nr_bin2hex((UCHAR*)bin_hashed_ifname, sizeof(bin_hashed_ifname), + (UCHAR*)hex_hashed_ifname)) ABORT(r); for (u = tmpAddress->FirstUnicastAddress; u != 0; u = u->Next) { diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c index c8a54566e24ec..4491b2b05100b 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c @@ -167,7 +167,7 @@ nr_stun_filter_addrs(nr_local_addr addrs[], int remove_loopback, int remove_link nr_local_addr *tmp = 0; int dest_index = 0; - tmp = RMALLOC(*count * sizeof(*tmp)); + tmp = (nr_local_addr*)RMALLOC(*count * sizeof(*tmp)); if (!tmp) ABORT(R_NO_MEMORY); diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c index ee734c887ef07..16e06f42d19fe 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c @@ -137,7 +137,7 @@ int nr_socket_buffered_stun_create(nr_socket *inner, int max_pending, nr_socket_buffered_stun *sock = 0; size_t frame_size; - if (!(sock = RCALLOC(sizeof(nr_socket_buffered_stun)))) + if (!(sock = R_NEW(nr_socket_buffered_stun))) ABORT(R_NO_MEMORY); sock->inner = inner; @@ -163,7 +163,7 @@ int nr_socket_buffered_stun_create(nr_socket *inner, int max_pending, } /* TODO(ekr@rtfm.com): Check this */ - if (!(sock->buffer = RMALLOC(sock->buffer_size))) + if (!(sock->buffer = (UCHAR*)RMALLOC(sock->buffer_size))) ABORT(R_NO_MEMORY); sock->read_state = NR_ICE_SOCKET_READ_NONE; @@ -239,7 +239,7 @@ static int nr_socket_buffered_stun_sendto(void *obj,const void *msg, size_t len, if (len > NR_MAX_FRAME_SIZE) ABORT(R_FAILED); - if (!(frame = RMALLOC(len + sizeof(nr_frame_header)))) + if (!(frame = (nr_frame_header*)RMALLOC(len + sizeof(nr_frame_header)))) ABORT(R_NO_MEMORY); frame->frame_length = htons(len); diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/nr_socket_turn.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/nr_socket_turn.c index 1a0162b13e1b3..52ff5c83f7099 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/nr_socket_turn.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/nr_socket_turn.c @@ -43,10 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "nr_socket_turn.h" -static char *nr_socket_turn_magic_cookie = "nr_socket_turn"; +static const char *nr_socket_turn_magic_cookie = "nr_socket_turn"; typedef struct nr_socket_turn_ { - char *magic_cookie; + const char *magic_cookie; nr_turn_client_ctx *turn; } nr_socket_turn; @@ -80,7 +80,7 @@ int nr_socket_turn_create(nr_socket **sockp) int r,_status; nr_socket_turn *sturn=0; - if(!(sturn=RCALLOC(sizeof(nr_socket_turn)))) + if(!(sturn=R_NEW(nr_socket_turn))) ABORT(R_NO_MEMORY); sturn->magic_cookie = nr_socket_turn_magic_cookie; @@ -104,7 +104,7 @@ static int nr_socket_turn_destroy(void **objp) if(!objp || !*objp) return(0); - sturn=*objp; + sturn=(nr_socket_turn*)*objp; *objp=0; assert(sturn->magic_cookie == nr_socket_turn_magic_cookie); @@ -121,12 +121,12 @@ static int nr_socket_turn_sendto(void *obj,const void *msg, size_t len, int flags, const nr_transport_addr *addr) { int r,_status; - nr_socket_turn *sturn=obj; + nr_socket_turn *sturn=(nr_socket_turn*)obj; assert(sturn->magic_cookie == nr_socket_turn_magic_cookie); assert(sturn->turn); - if ((r = nr_turn_client_send_indication(sturn->turn, msg, len, flags, + if ((r = nr_turn_client_send_indication(sturn->turn, (const UCHAR*)msg, len, flags, addr))) ABORT(r); @@ -155,7 +155,7 @@ static int nr_socket_turn_getfd(void *obj, NR_SOCKET *fd) static int nr_socket_turn_getaddr(void *obj, nr_transport_addr *addrp) { - nr_socket_turn *sturn=obj; + nr_socket_turn *sturn=(nr_socket_turn*)obj; int r, _status; assert(sturn->magic_cookie == nr_socket_turn_magic_cookie); @@ -174,7 +174,7 @@ static int nr_socket_turn_close(void *obj) { /* No-op */ #ifndef NDEBUG - nr_socket_turn *sturn=obj; + nr_socket_turn *sturn=(nr_socket_turn*)obj; assert(sturn->magic_cookie == nr_socket_turn_magic_cookie); #endif diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.c index 001b38e7c4de9..489dce7046767 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.c @@ -74,7 +74,7 @@ nr_stun_form_request_or_indication(int mode, int msg_type, nr_stun_message **msg default: if ((r=nr_stun_message_add_fingerprint_attribute(req))) ABORT(r); - /* fall through */ + [[fallthrough]]; case NR_STUN_MODE_STUN_NO_AUTH: req->header.magic_cookie = NR_STUN_MAGIC_COOKIE; break; @@ -566,9 +566,9 @@ nr_stun_form_success_response(nr_stun_message *req, nr_transport_addr *from, Dat /* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1.1 */ void -nr_stun_form_error_response(nr_stun_message *req, nr_stun_message* res, int number, char* msg) +nr_stun_form_error_response(nr_stun_message *req, nr_stun_message* res, int number, const char* msg) { - char *str; + const char *str; int request_method; char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */ diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.h b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.h index c3f91a87b08b0..dd53ef2fb17e8 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.h +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.h @@ -140,7 +140,7 @@ int nr_stun_build_data_indication(nr_stun_client_data_indication_params *params, #endif /* USE_TURN */ int nr_stun_form_success_response(nr_stun_message *req, nr_transport_addr *from, Data *password, nr_stun_message *res); -void nr_stun_form_error_response(nr_stun_message *request, nr_stun_message* response, int number, char* msg); +void nr_stun_form_error_response(nr_stun_message *request, nr_stun_message* response, int number, const char* msg); int nr_stun_compute_lt_message_integrity_password(const char *username, const char *realm, Data *password, Data *hmac_key); diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_client_ctx.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_client_ctx.c index 529ff74b3f822..1f23ff02cf3ee 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_client_ctx.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_client_ctx.c @@ -46,7 +46,7 @@ static int nr_stun_client_send_request(nr_stun_client_ctx *ctx); static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg); static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password); -int nr_stun_client_ctx_create(char* label, nr_socket* sock, +int nr_stun_client_ctx_create(const char* label, nr_socket* sock, nr_transport_addr* peer, UINT4 RTO, int flags, nr_stun_client_ctx** ctxp) { @@ -56,7 +56,7 @@ int nr_stun_client_ctx_create(char* label, nr_socket* sock, if ((r=nr_stun_startup())) ABORT(r); - if(!(ctx=RCALLOC(sizeof(nr_stun_client_ctx)))) + if(!(ctx=R_NEW(nr_stun_client_ctx))) ABORT(R_NO_MEMORY); ctx->state=NR_STUN_CLIENT_STATE_INITTED; @@ -122,13 +122,14 @@ static void nr_stun_client_fire_finished_cb(nr_stun_client_ctx *ctx) int nr_stun_client_start(nr_stun_client_ctx *ctx, int mode, NR_async_cb finished_cb, void *cb_arg) { int r,_status; + int flags = 0; if (ctx->state != NR_STUN_CLIENT_STATE_INITTED) ABORT(R_NOT_PERMITTED); /* We allow wildcard here if this is TCP, because we don't set the * destination address in many cases. */ - int flags = ctx->mapped_addr_check_mask; + flags = ctx->mapped_addr_check_mask; if (ctx->peer_addr.protocol == IPPROTO_TCP) { flags &= ~NR_STUN_TRANSPORT_ADDR_CHECK_WILDCARD; } @@ -188,7 +189,7 @@ nr_stun_client_reset(nr_stun_client_ctx *ctx) static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg) { int _status; - nr_stun_client_ctx *ctx=cb_arg; + nr_stun_client_ctx *ctx=(nr_stun_client_ctx*)cb_arg; struct timeval now; INT8 ms_waited; @@ -463,7 +464,7 @@ int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len * want to delay the completion of gathering. */ fail_on_error = 1; compute_lt_key = 1; - /* Fall through */ + [[fallthrough]]; case NR_STUN_CLIENT_MODE_BINDING_REQUEST_SHORT_TERM_AUTH: password = ctx->params.stun_binding_request.password; break; diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_client_ctx.h b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_client_ctx.h index 645b2fc3025c3..9342d3d6bc6c3 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_client_ctx.h +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_client_ctx.h @@ -190,7 +190,7 @@ struct nr_stun_client_ctx_ { #define NR_STUN_TRANSPORT_ADDR_CHECK_LOOPBACK 2 #define NR_STUN_TRANSPORT_ADDR_CHECK_LINK_LOCAL 4 -int nr_stun_client_ctx_create(char* label, nr_socket* sock, +int nr_stun_client_ctx_create(const char* label, nr_socket* sock, nr_transport_addr* peer, UINT4 RTO, int flags, nr_stun_client_ctx** ctxp); int nr_stun_client_start(nr_stun_client_ctx *ctx, int mode, NR_async_cb finished_cb, void *cb_arg); diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c index ae748a667b36c..ba54054cfce99 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c @@ -237,7 +237,7 @@ int nr_stun_attr_string_illegal(nr_stun_attr_info *attr_info, size_t len, void *data, size_t max_bytes, size_t max_chars) { int _status; - char *s = data; + char *s = (char*)data; size_t nchars; if (len > max_bytes) { @@ -260,7 +260,7 @@ int nr_stun_attr_error_code_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data) { int r,_status; - nr_stun_attr_error_code *ec = data; + nr_stun_attr_error_code *ec = (nr_stun_attr_error_code*)data; if (ec->number < 300 || ec->number > 699) ABORT(R_FAILED); @@ -298,7 +298,7 @@ nr_stun_attr_username_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void } static int -nr_stun_attr_codec_UCHAR_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_UCHAR_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %u", msg, attr_info->name, *(UCHAR*)data); return 0; @@ -347,7 +347,7 @@ nr_stun_attr_codec nr_stun_attr_codec_UCHAR = { }; static int -nr_stun_attr_codec_UINT4_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_UINT4_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %u", msg, attr_info->name, *(UINT4*)data); return 0; @@ -390,7 +390,7 @@ nr_stun_attr_codec nr_stun_attr_codec_UINT4 = { }; static int -nr_stun_attr_codec_UINT8_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_UINT8_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %llu", msg, attr_info->name, *(UINT8*)data); return 0; @@ -433,7 +433,7 @@ nr_stun_attr_codec nr_stun_attr_codec_UINT8 = { }; static int -nr_stun_attr_codec_addr_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_addr_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %s", msg, attr_info->name, ((nr_transport_addr*)data)->as_string); return 0; @@ -444,7 +444,7 @@ nr_stun_attr_codec_addr_encode(nr_stun_attr_info *attr_info, void *data, size_t { int r,_status; int start = offset; - nr_transport_addr *addr = data; + nr_transport_addr *addr = (nr_transport_addr*)data; UCHAR pad = '\0'; UCHAR family; @@ -494,7 +494,7 @@ nr_stun_attr_codec_addr_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCH UINT2 port; UINT4 addr4; struct in6_addr addr6; - nr_transport_addr *result = data; + nr_transport_addr *result = (nr_transport_addr*)data; if (nr_stun_decode(1, buf, buflen, &offset, &pad) || nr_stun_decode(1, buf, buflen, &offset, &family)) @@ -548,9 +548,9 @@ nr_stun_attr_codec nr_stun_attr_codec_addr = { }; static int -nr_stun_attr_codec_data_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_data_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { - nr_stun_attr_data *d = data; + nr_stun_attr_data *d = (nr_stun_attr_data*)data; r_dump(NR_LOG_STUN, LOG_DEBUG, attr_info->name, (char*)d->data, d->length); return 0; } @@ -558,7 +558,7 @@ nr_stun_attr_codec_data_print(nr_stun_attr_info *attr_info, char *msg, void *dat static int nr_stun_attr_codec_data_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) { - nr_stun_attr_data *d = data; + nr_stun_attr_data *d = (nr_stun_attr_data*)data; int start = offset; if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) @@ -575,7 +575,7 @@ static int nr_stun_attr_codec_data_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) { int _status; - nr_stun_attr_data *result = data; + nr_stun_attr_data *result = (nr_stun_attr_data*)data; /* -1 because it is going to be null terminated just to be safe */ if (attrlen >= (sizeof(result->data) - 1)) { @@ -602,9 +602,9 @@ nr_stun_attr_codec nr_stun_attr_codec_data = { }; static int -nr_stun_attr_codec_error_code_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_error_code_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { - nr_stun_attr_error_code *error_code = data; + nr_stun_attr_error_code *error_code = (nr_stun_attr_error_code*)data; r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %d %s", msg, attr_info->name, error_code->number, error_code->reason); @@ -614,18 +614,18 @@ nr_stun_attr_codec_error_code_print(nr_stun_attr_info *attr_info, char *msg, voi static int nr_stun_attr_codec_error_code_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) { - nr_stun_attr_error_code *error_code = data; + nr_stun_attr_error_code *error_code = (nr_stun_attr_error_code*)data; int start = offset; int length = strlen(error_code->reason); UCHAR pad[2] = { 0 }; - UCHAR class = error_code->number / 100; - UCHAR number = error_code->number % 100; + UCHAR err_class = error_code->number / 100; + UCHAR err_number = error_code->number % 100; if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) || nr_stun_encode_htons(4 + length , buflen, buf, &offset) || nr_stun_encode(pad, 2 , buflen, buf, &offset) - || nr_stun_encode(&class, 1 , buflen, buf, &offset) - || nr_stun_encode(&number, 1 , buflen, buf, &offset) + || nr_stun_encode(&err_class, 1 , buflen, buf, &offset) + || nr_stun_encode(&err_number, 1 , buflen, buf, &offset) || nr_stun_encode((UCHAR*)error_code->reason, length, buflen, buf, &offset)) return R_FAILED; @@ -638,18 +638,18 @@ static int nr_stun_attr_codec_error_code_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) { int _status; - nr_stun_attr_error_code *result = data; + nr_stun_attr_error_code *result = (nr_stun_attr_error_code*)data; UCHAR pad[2]; - UCHAR class; - UCHAR number; + UCHAR err_class; + UCHAR err_number; size_t size_reason; if (nr_stun_decode(2, buf, buflen, &offset, pad) - || nr_stun_decode(1, buf, buflen, &offset, &class) - || nr_stun_decode(1, buf, buflen, &offset, &number)) + || nr_stun_decode(1, buf, buflen, &offset, &err_class) + || nr_stun_decode(1, buf, buflen, &offset, &err_number)) ABORT(R_FAILED); - result->number = (class * 100) + number; + result->number = (err_class * 100) + err_number; size_reason = attrlen - 4; @@ -677,9 +677,9 @@ nr_stun_attr_codec nr_stun_attr_codec_error_code = { }; static int -nr_stun_attr_codec_fingerprint_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_fingerprint_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { - nr_stun_attr_fingerprint *fingerprint = data; + nr_stun_attr_fingerprint *fingerprint = (nr_stun_attr_fingerprint*)data; r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %08x", msg, attr_info->name, fingerprint->checksum); return 0; } @@ -688,7 +688,7 @@ static int nr_stun_attr_codec_fingerprint_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) { UINT4 checksum; - nr_stun_attr_fingerprint *fingerprint = data; + nr_stun_attr_fingerprint *fingerprint = (nr_stun_attr_fingerprint*)data; nr_stun_message_header *header = (nr_stun_message_header*)buf; /* the length must include the FINGERPRINT attribute when computing @@ -714,7 +714,7 @@ static int nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) { int r,_status; - nr_stun_attr_fingerprint *fingerprint = data; + nr_stun_attr_fingerprint *fingerprint = (nr_stun_attr_fingerprint*)data; nr_stun_message_header *header = (nr_stun_message_header*)buf; size_t length; UINT4 checksum; @@ -761,7 +761,7 @@ nr_stun_attr_codec nr_stun_attr_codec_fingerprint = { }; static int -nr_stun_attr_codec_flag_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_flag_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: on", msg, attr_info->name); return 0; @@ -800,9 +800,9 @@ nr_stun_attr_codec nr_stun_attr_codec_flag = { }; static int -nr_stun_attr_codec_message_integrity_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_message_integrity_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { - nr_stun_attr_message_integrity *integrity = data; + nr_stun_attr_message_integrity *integrity = (nr_stun_attr_message_integrity*)data; r_dump(NR_LOG_STUN, LOG_DEBUG, attr_info->name, (char*)integrity->hash, sizeof(integrity->hash)); return 0; } @@ -842,7 +842,7 @@ static int nr_stun_attr_codec_message_integrity_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) { int start = offset; - nr_stun_attr_message_integrity *integrity = data; + nr_stun_attr_message_integrity *integrity = (nr_stun_attr_message_integrity*)data; if (nr_stun_compute_message_integrity(buf, offset, integrity->password, integrity->passwordlen, integrity->hash)) return R_FAILED; @@ -862,7 +862,7 @@ nr_stun_attr_codec_message_integrity_decode(nr_stun_attr_info *attr_info, size_t { int _status; int start; - nr_stun_attr_message_integrity *result = data; + nr_stun_attr_message_integrity *result = (nr_stun_attr_message_integrity*)data; UCHAR computedHMAC[20]; result->valid = 0; @@ -917,7 +917,7 @@ nr_stun_attr_codec nr_stun_attr_codec_noop = { }; static int -nr_stun_attr_codec_quoted_string_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_quoted_string_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %s", msg, attr_info->name, (char*)data); @@ -948,7 +948,7 @@ nr_stun_attr_codec nr_stun_attr_codec_quoted_string = { }; static int -nr_stun_attr_codec_string_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_string_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %s", msg, attr_info->name, (char*)data); @@ -959,7 +959,7 @@ static int nr_stun_attr_codec_string_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) { int start = offset; - char *str = data; + char *str = (char*)data; int length = strlen(str); if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) @@ -976,7 +976,7 @@ static int nr_stun_attr_codec_string_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) { int _status; - char *result = data; + char *result = (char*)data; /* actual enforcement of the specific string size happens elsewhere */ if (attrlen >= NR_STUN_MAX_STRING_SIZE) { @@ -1010,9 +1010,9 @@ nr_stun_attr_codec nr_stun_attr_codec_string = { }; static int -nr_stun_attr_codec_unknown_attributes_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_unknown_attributes_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { - nr_stun_attr_unknown_attributes *unknown_attributes = data; + nr_stun_attr_unknown_attributes *unknown_attributes = (nr_stun_attr_unknown_attributes*)data; char type[9]; char str[64 + (NR_STUN_MAX_UNKNOWN_ATTRIBUTES * sizeof(type))]; int i; @@ -1032,7 +1032,7 @@ nr_stun_attr_codec_unknown_attributes_encode(nr_stun_attr_info *attr_info, void { int _status; int start = offset; - nr_stun_attr_unknown_attributes *unknown_attributes = data; + nr_stun_attr_unknown_attributes *unknown_attributes = (nr_stun_attr_unknown_attributes*)data; int length = (2 * unknown_attributes->num_attributes); int i; @@ -1061,7 +1061,7 @@ static int nr_stun_attr_codec_unknown_attributes_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) { int _status; - nr_stun_attr_unknown_attributes *unknown_attributes = data; + nr_stun_attr_unknown_attributes *unknown_attributes = (nr_stun_attr_unknown_attributes*)data; int i; UINT2 *a; @@ -1096,9 +1096,9 @@ nr_stun_attr_codec nr_stun_attr_codec_unknown_attributes = { }; static int -nr_stun_attr_codec_xor_mapped_address_print(nr_stun_attr_info *attr_info, char *msg, void *data) +nr_stun_attr_codec_xor_mapped_address_print(nr_stun_attr_info *attr_info, const char *msg, void *data) { - nr_stun_attr_xor_mapped_address *xor_mapped_address = data; + nr_stun_attr_xor_mapped_address *xor_mapped_address = (nr_stun_attr_xor_mapped_address*)data; r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %s (unmasked) %s (masked)", msg, attr_info->name, xor_mapped_address->unmasked.as_string, @@ -1109,7 +1109,7 @@ nr_stun_attr_codec_xor_mapped_address_print(nr_stun_attr_info *attr_info, char * static int nr_stun_attr_codec_xor_mapped_address_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) { - nr_stun_attr_xor_mapped_address *xor_mapped_address = data; + nr_stun_attr_xor_mapped_address *xor_mapped_address = (nr_stun_attr_xor_mapped_address*)data; nr_stun_message_header *header = (nr_stun_message_header*)buf; UINT4 magic_cookie; @@ -1135,7 +1135,7 @@ static int nr_stun_attr_codec_xor_mapped_address_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) { int r,_status; - nr_stun_attr_xor_mapped_address *xor_mapped_address = data; + nr_stun_attr_xor_mapped_address *xor_mapped_address = (nr_stun_attr_xor_mapped_address*)data; nr_stun_message_header *header = (nr_stun_message_header*)buf; UINT4 magic_cookie; @@ -1342,7 +1342,7 @@ nr_stun_encode_message(nr_stun_message *msg) if ((r=nr_stun_encode((UCHAR*)(&msg->header.id), sizeof(msg->header.id), sizeof(msg->buffer), msg->buffer, &msg->length))) ABORT(r); - r_dump(NR_LOG_STUN, LOG_DEBUG, "Encoded ID", (void*)&msg->header.id, sizeof(msg->header.id)); + r_dump(NR_LOG_STUN, LOG_DEBUG, "Encoded ID", (const char*)&msg->header.id, sizeof(msg->header.id)); TAILQ_FOREACH(attr, &msg->attributes, entry) { if ((r=nr_stun_find_attr_info(attr->type, &attr_info))) { @@ -1435,7 +1435,7 @@ nr_stun_decode_message(nr_stun_message *msg, int (*get_password)(void *arg, nr_s r_log(NR_LOG_STUN, LOG_DEBUG, "Parsed MsgType: 0x%03x", msg->header.type); r_log(NR_LOG_STUN, LOG_DEBUG, "Parsed Length: %d", msg->header.length); r_log(NR_LOG_STUN, LOG_DEBUG, "Parsed Cookie: %08x", msg->header.magic_cookie); - r_dump(NR_LOG_STUN, LOG_DEBUG, "Parsed ID", (void*)&msg->header.id, sizeof(msg->header.id)); + r_dump(NR_LOG_STUN, LOG_DEBUG, "Parsed ID", (const char*)&msg->header.id, sizeof(msg->header.id)); if (msg->header.length + sizeof(msg->header) != msg->length) { r_log(NR_LOG_STUN, LOG_WARNING, "Inconsistent message header length: %d/%d", diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.h b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.h index 4e4ff60e0c29c..b4b29a142e6bf 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.h +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.h @@ -40,15 +40,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. typedef struct nr_stun_attr_info_ nr_stun_attr_info; typedef struct nr_stun_attr_codec_ { - char *name; - int (*print)(nr_stun_attr_info *attr_info, char *msg, void *data); + const char *name; + int (*print)(nr_stun_attr_info *attr_info, const char *msg, void *data); int (*encode)(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen); int (*decode)(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data); } nr_stun_attr_codec; struct nr_stun_attr_info_ { UINT2 type; - char *name; + const char *name; nr_stun_attr_codec *codec; int (*illegal)(nr_stun_attr_info *attr_info, size_t attrlen, void *data); }; diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_msg.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_msg.c index 7e01686109cd3..03e0d996adf56 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_msg.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_msg.c @@ -52,7 +52,7 @@ nr_stun_message_create(nr_stun_message **msg) int _status; nr_stun_message *m = 0; - m = RCALLOC(sizeof(*m)); + m = R_NEW(nr_stun_message); if (!m) ABORT(R_NO_MEMORY); @@ -118,7 +118,7 @@ nr_stun_message_attribute_create(nr_stun_message *msg, nr_stun_message_attribute int _status; nr_stun_message_attribute *a = 0; - a = RCALLOC(sizeof(*a)); + a = R_NEW(nr_stun_message_attribute); if (!a) ABORT(R_NO_MEMORY); @@ -208,7 +208,7 @@ NR_STUN_MESSAGE_ADD_ATTRIBUTE( ) int -nr_stun_message_add_error_code_attribute(nr_stun_message *msg, UINT2 number, char *reason) +nr_stun_message_add_error_code_attribute(nr_stun_message *msg, UINT2 number, const char *reason) NR_STUN_MESSAGE_ADD_ATTRIBUTE( NR_STUN_ATTR_ERROR_CODE, { @@ -238,7 +238,7 @@ NR_STUN_MESSAGE_ADD_ATTRIBUTE( ) int -nr_stun_message_add_nonce_attribute(nr_stun_message *msg, char *nonce) +nr_stun_message_add_nonce_attribute(nr_stun_message *msg, const char *nonce) NR_STUN_MESSAGE_ADD_ATTRIBUTE( NR_STUN_ATTR_NONCE, { (void)strlcpy(attr->u.nonce, nonce, sizeof(attr->u.nonce)); } diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_msg.h b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_msg.h index ffd68d3eeed47..d5a283e485729 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_msg.h +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_msg.h @@ -138,8 +138,8 @@ typedef struct nr_stun_message_attribute_ { } u; nr_stun_encoded_attribute *encoding; size_t encoding_length; - char *name; - char *type_name; + const char *name; + const char *type_name; int invalid; TAILQ_ENTRY(nr_stun_message_attribute_) entry; } nr_stun_message_attribute; @@ -154,7 +154,7 @@ typedef struct nr_stun_message_header_ { } nr_stun_message_header; typedef struct nr_stun_message_ { - char *name; + const char *name; UCHAR buffer[NR_STUN_MAX_MESSAGE_SIZE]; size_t length; nr_stun_message_header header; @@ -175,10 +175,10 @@ int nr_stun_message_has_attribute(nr_stun_message *msg, UINT2 type, nr_stun_mess int nr_stun_message_get_attribute(nr_stun_message *msg, UINT2 type, UINT2 index, nr_stun_message_attribute **attribute); int nr_stun_message_add_alternate_server_attribute(nr_stun_message *msg, nr_transport_addr *alternate_server); -int nr_stun_message_add_error_code_attribute(nr_stun_message *msg, UINT2 number, char *reason); +int nr_stun_message_add_error_code_attribute(nr_stun_message *msg, UINT2 number, const char *reason); int nr_stun_message_add_fingerprint_attribute(nr_stun_message *msg); int nr_stun_message_add_message_integrity_attribute(nr_stun_message *msg, Data *password); -int nr_stun_message_add_nonce_attribute(nr_stun_message *msg, char *nonce); +int nr_stun_message_add_nonce_attribute(nr_stun_message *msg, const char *nonce); int nr_stun_message_add_realm_attribute(nr_stun_message *msg, char *realm); int nr_stun_message_add_server_attribute(nr_stun_message *msg, char *server_name); int nr_stun_message_add_unknown_attributes_attribute(nr_stun_message *msg, nr_stun_attr_unknown_attributes *unknown_attributes); diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_proc.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_proc.c index 13366e265d7fc..efc8f5a0d9fd0 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_proc.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_proc.c @@ -379,7 +379,7 @@ nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_ { int r,_status; char *realm = 0; - char *nonce; + const char *nonce; UINT2 size; if ((r=NR_reg_alloc_string(NR_STUN_REG_PREF_SERVER_REALM, &realm))) diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_server_ctx.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_server_ctx.c index c11ef18556414..e9c7d8dc27982 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_server_ctx.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_server_ctx.c @@ -49,7 +49,7 @@ int nr_stun_server_ctx_create(char *label, nr_stun_server_ctx **ctxp) if ((r=nr_stun_startup())) ABORT(r); - if(!(ctx=RCALLOC(sizeof(nr_stun_server_ctx)))) + if(!(ctx=R_NEW(nr_stun_server_ctx))) ABORT(R_NO_MEMORY); if(!(ctx->label=r_strdup(label))) @@ -86,12 +86,12 @@ int nr_stun_server_ctx_destroy(nr_stun_server_ctx **ctxp) return(0); } -static int nr_stun_server_client_create(nr_stun_server_ctx *ctx, char *client_label, char *user, Data *pass, nr_stun_server_cb cb, void *cb_arg, nr_stun_server_client **clntp) +static int nr_stun_server_client_create(nr_stun_server_ctx *ctx, const char *client_label, char *user, Data *pass, nr_stun_server_cb cb, void *cb_arg, nr_stun_server_client **clntp) { nr_stun_server_client *clnt=0; int r,_status; - if(!(clnt=RCALLOC(sizeof(nr_stun_server_client)))) + if(!(clnt=R_NEW(nr_stun_server_client))) ABORT(R_NO_MEMORY); if(!(clnt->label=r_strdup(client_label))) diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_util.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_util.c index 40641ca8d0dbf..7fc213d9f7725 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_util.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_util.c @@ -139,10 +139,10 @@ nr_stun_different_transaction(UCHAR *msg, size_t len, nr_stun_message *req) return _status; } -char* +const char* nr_stun_msg_type(int type) { - char *ret = 0; + const char *ret = 0; switch (type) { case NR_STUN_MSG_BINDING_REQUEST: @@ -205,7 +205,7 @@ nr_stun_msg_type(int type) int nr_random_alphanum(char *alphanum, int size) { - static char alphanums[256] = { + static const char alphanums[256] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_util.h b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_util.h index 89ddf0fe4d812..c9b0cd4692ea0 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_util.h +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_util.h @@ -46,7 +46,7 @@ int nr_stun_xor_mapped_address(UINT4 magicCookie, UINT12 transactionId, nr_trans int nr_stun_different_transaction(UCHAR *msg, size_t len, nr_stun_message *req); -char* nr_stun_msg_type(int type); +const char* nr_stun_msg_type(int type); int nr_random_alphanum(char *alphanum, int size); diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/turn_client_ctx.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/turn_client_ctx.c index 98da29c5b6286..66b1528cdc21a 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/turn_client_ctx.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/turn_client_ctx.c @@ -97,7 +97,7 @@ int nr_transport_addr_listnode_create(const nr_transport_addr *addr, nr_transpor nr_transport_addr_listnode *listnode = 0; int r,_status; - if (!(listnode=RCALLOC(sizeof(nr_transport_addr_listnode)))) { + if (!(listnode=R_NEW(nr_transport_addr_listnode))) { ABORT(R_NO_MEMORY); } @@ -129,11 +129,12 @@ static int nr_turn_stun_ctx_create(nr_turn_client_ctx *tctx, int mode, nr_turn_stun_ctx *sctx = 0; int r,_status; char label[256]; + int flags = 0; - if (!(sctx=RCALLOC(sizeof(nr_turn_stun_ctx)))) + if (!(sctx=R_NEW(nr_turn_stun_ctx))) ABORT(R_NO_MEMORY); - int flags = NR_STUN_TRANSPORT_ADDR_CHECK_WILDCARD; + flags = NR_STUN_TRANSPORT_ADDR_CHECK_WILDCARD; if (!(tctx->ctx->flags & NR_ICE_CTX_FLAGS_ALLOW_LOOPBACK)) { flags |= NR_STUN_TRANSPORT_ADDR_CHECK_LOOPBACK; } @@ -553,7 +554,7 @@ int nr_turn_client_ctx_create(const char* label, nr_socket* sock, if ((r=r_log_register("turn", &NR_LOG_TURN))) ABORT(r); - if(!(ctx=RCALLOC(sizeof(nr_turn_client_ctx)))) + if(!(ctx=R_NEW(nr_turn_client_ctx))) ABORT(R_NO_MEMORY); STAILQ_INIT(&ctx->stun_ctxs); @@ -1202,7 +1203,7 @@ static int nr_turn_permission_create(nr_turn_client_ctx *ctx, const nr_transport r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): Creating permission for %s", ctx->label, addr->as_string); - if (!(perm = RCALLOC(sizeof(nr_turn_permission)))) + if (!(perm = R_NEW(nr_turn_permission))) ABORT(R_NO_MEMORY); if ((r=nr_transport_addr_copy(&perm->addr, addr))) diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/util/ice_util.c b/dom/media/webrtc/transport/third_party/nICEr/src/util/ice_util.c index 249cfe350fb21..4ee94cdc23436 100644 --- a/dom/media/webrtc/transport/third_party/nICEr/src/util/ice_util.c +++ b/dom/media/webrtc/transport/third_party/nICEr/src/util/ice_util.c @@ -49,7 +49,7 @@ int nr_concat_strings(char **outp,...) va_end(ap); - if(!(out=RMALLOC(len+1))) + if(!(out=(char*)RMALLOC(len+1))) ABORT(R_NO_MEMORY); *outp=out; diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c b/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c index f1462f6ce4898..cbf974f744086 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c @@ -60,7 +60,7 @@ int NR_LOG_LOGGING = 0; -static char *log_level_strings[]={ +static const char *log_level_strings[]={ "EMERG", "ALERT", "CRIT", @@ -71,7 +71,7 @@ static char *log_level_strings[]={ "DEBUG" }; -static char *log_level_reg_strings[]={ +static const char *log_level_reg_strings[]={ "emergency", "alert", "critical", @@ -104,7 +104,7 @@ static int log_type_ct; typedef struct log_destination_ { - char *dest_name; + const char *dest_name; int enabled; int default_level; r_dest_vlog *dest_vlog; @@ -149,17 +149,17 @@ static int r_log_level_environment=0; static int r_log_initted=0; static int r_log_env_verbose=0; -static void r_log_facility_change_cb(void *cb_arg, char action, NR_registry name); -static void r_log_facility_delete_cb(void *cb_arg, char action, NR_registry name); -static void r_log_destination_change_cb(void *cb_arg, char action, NR_registry name); -static void r_log_default_level_change_cb(void *cb_arg, char action, NR_registry name); +static void r_log_facility_change_cb(void *cb_arg, char action, NR_registry_name name); +static void r_log_facility_delete_cb(void *cb_arg, char action, NR_registry_name name); +static void r_log_destination_change_cb(void *cb_arg, char action, NR_registry_name name); +static void r_log_default_level_change_cb(void *cb_arg, char action, NR_registry_name name); static int r_log_get_default_level(void); static int r_log_get_destinations(int usereg); static int r_logging_dest(int dest_index, int facility, int level); static int _r_log_init(int usereg); -static int r_log_get_reg_level(NR_registry name, int *level); +static int r_log_get_reg_level(NR_registry_name name, int *level); -int r_log_register(char *facility_name,int *log_facility) +int r_log_register(const char *facility_name,int *log_facility) { int i,j; int level; @@ -225,7 +225,7 @@ int r_log_register(char *facility_name,int *log_facility) return(_status); } -static int r_log_get_reg_level(NR_registry name, int *out) +static int r_log_get_reg_level(NR_registry_name name, int *out) { char level[32]; int r,_status; @@ -256,7 +256,7 @@ static int r_log_get_reg_level(NR_registry name, int *out) } /* Handle the case where a value changes */ -static void r_log_facility_change_cb(void *cb_arg, char action, NR_registry name) +static void r_log_facility_change_cb(void *cb_arg, char action, NR_registry_name name) { int *lt_level=(int *)cb_arg; int level; @@ -275,7 +275,7 @@ static void r_log_facility_change_cb(void *cb_arg, char action, NR_registry name } /* Handle the case where a value is deleted */ -static void r_log_facility_delete_cb(void *cb_arg, char action, NR_registry name) +static void r_log_facility_delete_cb(void *cb_arg, char action, NR_registry_name name) { int *lt_level=(int *)cb_arg; @@ -294,7 +294,7 @@ int r_log(int facility,int level,const char *format,...) return(0); } -int r_dump(int facility,int level,char *name,char *data,int len) +int r_dump(int facility,int level,const char *name,const char *data,int len) { char *hex = 0; size_t unused; @@ -302,11 +302,11 @@ int r_dump(int facility,int level,char *name,char *data,int len) if(!r_logging(facility,level)) return(0); - hex=RMALLOC((len*2)+1); + hex=(char*)RMALLOC((len*2)+1); if (!hex) return(R_FAILED); - if (nr_nbin2hex((UCHAR*)data, len, hex, len*2+1, &unused)) + if (nr_nbin2hex((const UCHAR*)data, len, hex, len*2+1, &unused)) strcpy(hex, "?"); if(name) @@ -330,9 +330,9 @@ int r_dump(int facility,int level,char *name,char *data,int len) int r_vlog(int facility,int level,const char *format,va_list ap) { char log_fmt_buf[MAX_ERROR_STRING_SIZE]; - char *level_str="unknown"; - char *facility_str="unknown"; - char *fmt_str=(char *)format; + const char *level_str="unknown"; + const char *facility_str="unknown"; + const char *fmt_str=format; int i; if(r_log_env_verbose){ @@ -517,12 +517,12 @@ static int r_log_get_destinations(int usereg) return(_status); } -static void r_log_destination_change_cb(void *cb_arg, char action, NR_registry name) +static void r_log_destination_change_cb(void *cb_arg, char action, NR_registry_name name) { r_log_get_destinations(1); } -static void r_log_default_level_change_cb(void *cb_arg, char action, NR_registry name) +static void r_log_default_level_change_cb(void *cb_arg, char action, NR_registry_name name) { r_log_get_destinations(1); } diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.h b/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.h index 973ae484d631f..c55210b0a216e 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.h +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.h @@ -53,9 +53,9 @@ int r_log(int facility,int level,const char *fmt,...) ; int r_vlog(int facility,int level,const char *fmt,va_list ap); -int r_dump(int facility,int level,char *name,char *data,int len); +int r_dump(int facility,int level,const char *name,const char *data,int len); -int r_log_register(char *tipename,int *facility); +int r_log_register(const char *tipename,int *facility); int r_logging(int facility, int level); int r_log_init(void); diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.c b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.c index 9eb5063de8ccd..dab318d32679c 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.c @@ -64,11 +64,11 @@ static int reg_initted = 0; /* must be in the order the types are numbered */ -static char *typenames[] = { "char", "UCHAR", "INT2", "UINT2", "INT4", "UINT4", "INT8", "UINT8", "double", "Data", "string", "registry" }; +static const char *typenames[] = { "char", "UCHAR", "INT2", "UINT2", "INT4", "UINT4", "INT8", "UINT8", "double", "Data", "string", "registry" }; int NR_LOG_REGISTRY=0; -NR_registry NR_TOP_LEVEL_REGISTRY = ""; +NR_registry_name NR_TOP_LEVEL_REGISTRY = ""; int NR_reg_init() @@ -112,7 +112,7 @@ NR_reg_initted(void) #define NRREGGET(func, TYPE, type) \ int \ -func(NR_registry name, type *out) \ +func(NR_registry_name name, type *out) \ { \ return nr_reg_get(name, TYPE, out); \ } @@ -126,13 +126,13 @@ NRREGGET(NR_reg_get_uint8, NR_REG_TYPE_UINT8, UINT8) NRREGGET(NR_reg_get_double, NR_REG_TYPE_DOUBLE, double) int -NR_reg_get_registry(NR_registry name, NR_registry out) +NR_reg_get_registry(NR_registry_name name, NR_registry out) { int r, _status; nr_scalar_registry_node *node = 0; int free_node = 0; - if ((r=nr_reg_fetch_node(name, NR_REG_TYPE_REGISTRY, (void*)&node, &free_node))) + if ((r=nr_reg_fetch_node(name, NR_REG_TYPE_REGISTRY, (nr_registry_node**)&node, &free_node))) ABORT(r); strncpy(out, name, sizeof(NR_registry)); @@ -145,26 +145,26 @@ NR_reg_get_registry(NR_registry name, NR_registry out) } int -NR_reg_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length) +NR_reg_get_bytes(NR_registry_name name, UCHAR *out, size_t size, size_t *length) { return nr_reg_get_array(name, NR_REG_TYPE_BYTES, out, size, length); } int -NR_reg_get_string(NR_registry name, char *out, size_t size) +NR_reg_get_string(NR_registry_name name, char *out, size_t size) { return nr_reg_get_array(name, NR_REG_TYPE_STRING, (UCHAR*)out, size, 0); } int -NR_reg_get_length(NR_registry name, size_t *length) +NR_reg_get_length(NR_registry_name name, size_t *length) { return nr_reg_local_get_length(name, length); } #define NRREGSET(func, TYPE, type) \ int \ -func(NR_registry name, type data) \ +func(NR_registry_name name, type data) \ { \ return nr_reg_set(name, TYPE, &data); \ } @@ -175,39 +175,39 @@ NRREGSET(NR_reg_set_int4, NR_REG_TYPE_INT4, INT4) NRREGSET(NR_reg_set_uint4, NR_REG_TYPE_UINT4, UINT4) int -NR_reg_set_string(NR_registry name, char *data) +NR_reg_set_string(NR_registry_name name, const char *data) { - return nr_reg_set_array(name, NR_REG_TYPE_STRING, (UCHAR*)data, strlen(data)+1); + return nr_reg_set_array(name, NR_REG_TYPE_STRING, (const UCHAR*)data, strlen(data)+1); } int -NR_reg_set_registry(NR_registry name) +NR_reg_set_registry(NR_registry_name name) { return nr_reg_set(name, NR_REG_TYPE_REGISTRY, 0); } int -NR_reg_set_bytes(NR_registry name, unsigned char *data, size_t length) +NR_reg_set_bytes(NR_registry_name name, const unsigned char *data, size_t length) { return nr_reg_set_array(name, NR_REG_TYPE_BYTES, data, length); } int -NR_reg_del(NR_registry name) +NR_reg_del(NR_registry_name name) { return nr_reg_local_del(name); } int -NR_reg_get_child_count(NR_registry parent, unsigned int *count) +NR_reg_get_child_count(NR_registry_name parent, unsigned int *count) { assert(sizeof(count) == sizeof(size_t)); return nr_reg_local_get_child_count(parent, (size_t*)count); } int -NR_reg_get_child_registry(NR_registry parent, unsigned int i, NR_registry child) +NR_reg_get_child_registry(NR_registry_name parent, unsigned int i, NR_registry child) { int r, _status; size_t count; @@ -220,7 +220,7 @@ NR_reg_get_child_registry(NR_registry parent, unsigned int i, NR_registry child) ABORT(R_NOT_FOUND); else { count++; - children = (NR_registry *)RCALLOC(count * sizeof(NR_registry)); + children = R_NEW_CNT(NR_registry, count); if (!children) ABORT(R_NO_MEMORY); @@ -241,7 +241,7 @@ NR_reg_get_child_registry(NR_registry parent, unsigned int i, NR_registry child) // convenience methods, call RFREE on the returned data int -NR_reg_alloc_data(NR_registry name, Data *data) +NR_reg_alloc_data(NR_registry_name name, Data *data) { int r, _status; size_t length; @@ -251,7 +251,7 @@ NR_reg_alloc_data(NR_registry name, Data *data) if ((r=NR_reg_get_length(name, &length))) ABORT(r); - if (!(tmp = (void*)RMALLOC(length))) + if (!(tmp = (UCHAR*)RMALLOC(length))) ABORT(R_NO_MEMORY); if ((r=NR_reg_get_bytes(name, tmp, length, &sanity_check))) @@ -271,7 +271,7 @@ NR_reg_alloc_data(NR_registry name, Data *data) } int -NR_reg_alloc_string(NR_registry name, char **data) +NR_reg_alloc_string(NR_registry_name name, char **data) { int r, _status; size_t length; @@ -280,7 +280,7 @@ NR_reg_alloc_string(NR_registry name, char **data) if ((r=NR_reg_get_length(name, &length))) ABORT(r); - if (!(tmp = (void*)RMALLOC(length+1))) + if (!(tmp = (char*)RMALLOC(length+1))) ABORT(R_NO_MEMORY); if ((r=NR_reg_get_string(name, tmp, length+1))) @@ -299,7 +299,7 @@ NR_reg_alloc_string(NR_registry name, char **data) } -char * +const char * nr_reg_type_name(int type) { if ((type < NR_REG_TYPE_CHAR) || (type > NR_REG_TYPE_REGISTRY)) @@ -308,46 +308,11 @@ nr_reg_type_name(int type) return(typenames[type]); } -int -nr_reg_compute_type(char *typename, int *type) -{ - int _status; - size_t i; - -#ifdef SANITY_CHECKS - assert(!strcasecmp(typenames[NR_REG_TYPE_CHAR], "char")); - assert(!strcasecmp(typenames[NR_REG_TYPE_UCHAR], "UCHAR")); - assert(!strcasecmp(typenames[NR_REG_TYPE_INT2], "INT2")); - assert(!strcasecmp(typenames[NR_REG_TYPE_UINT2], "UINT2")); - assert(!strcasecmp(typenames[NR_REG_TYPE_INT4], "INT4")); - assert(!strcasecmp(typenames[NR_REG_TYPE_UINT4], "UINT4")); - assert(!strcasecmp(typenames[NR_REG_TYPE_INT8], "INT8")); - assert(!strcasecmp(typenames[NR_REG_TYPE_UINT8], "UINT8")); - assert(!strcasecmp(typenames[NR_REG_TYPE_DOUBLE], "double")); - assert(!strcasecmp(typenames[NR_REG_TYPE_BYTES], "Data")); - assert(!strcasecmp(typenames[NR_REG_TYPE_STRING], "string")); - assert(!strcasecmp(typenames[NR_REG_TYPE_REGISTRY], "registry")); - assert(sizeof(typenames)/sizeof(*typenames) == (NR_REG_TYPE_REGISTRY+1)); -#endif - - for (i = 0; i < sizeof(typenames)/sizeof(*typenames); ++i) { - if (!strcasecmp(typenames[i], typename)) { - *type = i; - return 0; - } - } - ABORT(R_BAD_ARGS); - - _status=0; - abort: - return(_status); -} - /* More convenience functions: the same as their parents but they take a prefix and a suffix */ #define NRGET2(func, type, get) \ int \ -func(NR_registry parent, char *child, type *out) \ +func(NR_registry_name parent, const char *child, type *out) \ { \ int r, _status; \ NR_registry registry; \ @@ -374,7 +339,7 @@ NRGET2(NR_reg_alloc2_data, Data, NR_reg_alloc_data) take a prefix and a suffix */ #define NRSET2(func, type, set) \ int \ -func(NR_registry parent, char *child, type in) \ +func(NR_registry_name parent, const char *child, type in) \ { \ int r, _status; \ NR_registry registry; \ @@ -392,11 +357,11 @@ abort: \ } NRSET2(NR_reg_set2_uchar, UCHAR, NR_reg_set_uchar) -NRSET2(NR_reg_set2_string, char*, NR_reg_set_string) +NRSET2(NR_reg_set2_string, const char*, NR_reg_set_string) /* requires parent already in legal form */ int -NR_reg_make_registry(NR_registry parent, char *child, NR_registry out) +NR_reg_make_registry(NR_registry_name parent, const char *child, NR_registry out) { int r, _status; size_t plen; diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.h b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.h index 5ff60e270023a..d42892d235261 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.h +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry.h @@ -55,63 +55,64 @@ typedef char NR_registry[NR_REG_MAX_NR_REGISTRY_LEN]; typedef char NR_registry_type[NR_REG_MAX_TYPE_LEN]; +typedef const char * NR_registry_name; -extern NR_registry NR_TOP_LEVEL_REGISTRY; +extern NR_registry_name NR_TOP_LEVEL_REGISTRY; int NR_reg_init(void); int NR_reg_initted(void); -int NR_reg_get_char(NR_registry name, char *out); -int NR_reg_get_uchar(NR_registry name, UCHAR *out); -int NR_reg_get_uint2(NR_registry name, UINT2 *out); -int NR_reg_get_int4(NR_registry name, INT4 *out); -int NR_reg_get_uint4(NR_registry name, UINT4 *out); -int NR_reg_get_uint8(NR_registry name, UINT8 *out); -int NR_reg_get_double(NR_registry name, double *out); -int NR_reg_get_registry(NR_registry name, NR_registry out); +int NR_reg_get_char(NR_registry_name name, char *out); +int NR_reg_get_uchar(NR_registry_name name, UCHAR *out); +int NR_reg_get_uint2(NR_registry_name name, UINT2 *out); +int NR_reg_get_int4(NR_registry_name name, INT4 *out); +int NR_reg_get_uint4(NR_registry_name name, UINT4 *out); +int NR_reg_get_uint8(NR_registry_name name, UINT8 *out); +int NR_reg_get_double(NR_registry_name name, double *out); +int NR_reg_get_registry(NR_registry_name name, NR_registry out); -int NR_reg_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length); -int NR_reg_get_string(NR_registry name, char *out, size_t size); -int NR_reg_get_length(NR_registry name, size_t *length); +int NR_reg_get_bytes(NR_registry_name name, UCHAR *out, size_t size, size_t *length); +int NR_reg_get_string(NR_registry_name name, char *out, size_t size); +int NR_reg_get_length(NR_registry_name name, size_t *length); -int NR_reg_get2_char(NR_registry prefix, char *name, char *); -int NR_reg_get2_uchar(NR_registry prefix, char *name, UCHAR *); -int NR_reg_get2_uint2(NR_registry prefix, char *name, UINT2 *); +int NR_reg_get2_char(NR_registry_name prefix, const char *name, char *); +int NR_reg_get2_uchar(NR_registry_name prefix, const char *name, UCHAR *); +int NR_reg_get2_uint2(NR_registry_name prefix, const char *name, UINT2 *); -int NR_reg_alloc2_string(NR_registry prefix, char *name, char **); -int NR_reg_alloc2_data(NR_registry prefix, char *name, Data *); +int NR_reg_alloc2_string(NR_registry_name prefix, const char *name, char **); +int NR_reg_alloc2_data(NR_registry_name prefix, const char *name, Data *); -int NR_reg_set_char(NR_registry name, char data); -int NR_reg_set_uchar(NR_registry name, UCHAR data); -int NR_reg_set_int4(NR_registry name, INT4 data); -int NR_reg_set_uint4(NR_registry name, UINT4 data); +int NR_reg_set_char(NR_registry_name name, char data); +int NR_reg_set_uchar(NR_registry_name name, UCHAR data); +int NR_reg_set_int4(NR_registry_name name, INT4 data); +int NR_reg_set_uint4(NR_registry_name name, UINT4 data); -int NR_reg_set_registry(NR_registry name); +int NR_reg_set_registry(NR_registry_name name); -int NR_reg_set_bytes(NR_registry name, UCHAR *data, size_t length); -int NR_reg_set_string(NR_registry name, char *data); +int NR_reg_set_bytes(NR_registry_name name, const UCHAR *data, size_t length); +int NR_reg_set_string(NR_registry_name name, const char *data); -int NR_reg_set2_uchar(NR_registry prefix, char *name, UCHAR data); +int NR_reg_set2_uchar(NR_registry_name prefix, const char *name, UCHAR data); -int NR_reg_set2_string(NR_registry prefix, char *name, char *data); +int NR_reg_set2_string(NR_registry_name prefix, const char *name, const char *data); -int NR_reg_del(NR_registry name); +int NR_reg_del(NR_registry_name name); -int NR_reg_get_child_count(NR_registry parent, unsigned int *count); -int NR_reg_get_child_registry(NR_registry parent, unsigned int i, NR_registry child); +int NR_reg_get_child_count(NR_registry_name parent, unsigned int *count); +int NR_reg_get_child_registry(NR_registry_name parent, unsigned int i, NR_registry child); /* convenience methods, call RFREE on the returned data */ -int NR_reg_alloc_data(NR_registry name, Data *data); -int NR_reg_alloc_string(NR_registry name, char **data); +int NR_reg_alloc_data(NR_registry_name name, Data *data); +int NR_reg_alloc_string(NR_registry_name name, char **data); #define NR_REG_CB_ACTION_ADD (1<<0) #define NR_REG_CB_ACTION_CHANGE (1<<1) #define NR_REG_CB_ACTION_DELETE (1<<2) #define NR_REG_CB_ACTION_FINAL (1<<6) -int NR_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg); +int NR_reg_register_callback(NR_registry_name name, char action, void (*cb)(void *cb_arg, char action, NR_registry_name name), void *cb_arg); -int NR_reg_make_registry(NR_registry parent, char *child, NR_registry out); +int NR_reg_make_registry(NR_registry_name parent, const char *child, NR_registry out); #endif diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_int.h b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_int.h index d72992117e9bd..33fb36fb7ac57 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_int.h +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_int.h @@ -53,7 +53,7 @@ extern int NR_LOG_REGISTRY; -int nr_reg_is_valid(NR_registry name); +int nr_reg_is_valid(NR_registry_name name); #define NR_REG_TYPE_CHAR 0 #define NR_REG_TYPE_UCHAR 1 @@ -67,15 +67,13 @@ int nr_reg_is_valid(NR_registry name); #define NR_REG_TYPE_BYTES 9 #define NR_REG_TYPE_STRING 10 #define NR_REG_TYPE_REGISTRY 11 -char *nr_reg_type_name(int type); -int nr_reg_compute_type(char *type_name, int *type); - -char *nr_reg_action_name(int action); +const char *nr_reg_type_name(int type); +const char *nr_reg_action_name(int action); int nr_reg_cb_init(void); int nr_reg_client_cb_init(void); int nr_reg_register_for_callbacks(int fd, int connect_to_port); -int nr_reg_raise_event(NR_registry name, int action); +int nr_reg_raise_event(NR_registry_name name, int action); #ifndef NO_REG_RPC int nr_reg_get_client(CLIENT **client); #endif @@ -124,17 +122,17 @@ typedef struct nr_reg_find_children_arg_ { int nr_reg_local_init(void); -int nr_reg_get(char *name, int type, void *out); -int nr_reg_get_array(char *name, unsigned char type, UCHAR *out, size_t size, size_t *length); +int nr_reg_get(const char *name, int type, void *out); +int nr_reg_get_array(const char *name, unsigned char type, UCHAR *out, size_t size, size_t *length); -int nr_reg_set(char *name, int type, void *data); -int nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length); +int nr_reg_set(const char *name, int type, void *data); +int nr_reg_set_array(const char *name, unsigned char type, const UCHAR *data, size_t length); -int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node); +int nr_reg_fetch_node(const char *name, unsigned char type, nr_registry_node **node, int *free_node); -int nr_reg_local_get_length(NR_registry name, size_t *len); -int nr_reg_local_del(NR_registry name); -int nr_reg_local_get_child_count(NR_registry parent, size_t *count); -int nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length); +int nr_reg_local_get_length(NR_registry_name name, size_t *len); +int nr_reg_local_del(NR_registry_name name); +int nr_reg_local_get_child_count(NR_registry_name parent, size_t *count); +int nr_reg_local_get_children(NR_registry_name parent, NR_registry *data, size_t size, size_t *length); #endif diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_local.c b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_local.c index 96e1e46411e5b..2e92f7c70431c 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_local.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registry_local.c @@ -66,29 +66,29 @@ static int nr_reg_local_compare_string(const void *arg1, const void *arg2) { return strcasecmp(*(const char **)arg1, *(const char **)arg2); } -static int nr_reg_insert_node(char *name, void *node); -static int nr_reg_change_node(char *name, void *node, void *old); -static int nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out); -static int nr_reg_set_parent_registries(char *name); -char *nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit); +static int nr_reg_insert_node(const char *name, void *node); +static int nr_reg_change_node(const char *name, void *node, void *old); +static int nr_reg_get_data(NR_registry_name name, nr_scalar_registry_node *node, void *out); +static int nr_reg_set_parent_registries(const char *name); +char *nr_reg_alloc_node_data(const char *name, nr_registry_node *node, int *freeit); static int nr_reg_rfree(void *ptr); -static int nr_reg_compute_length(char *name, nr_registry_node *node, size_t *length); -char *nr_reg_action_name(int action); +static int nr_reg_compute_length(const char *name, nr_registry_node *node, size_t *length); +const char *nr_reg_action_name(int action); /* the registry, containing mappings like "foo.bar.baz" to registry * nodes, which are either of type nr_scalar_registry_node or * nr_array_registry_node */ static r_assoc *nr_registry = 0; -static int nr_reg_local_iter(NR_registry prefix, int (*action)(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node), void *ptr); -static int nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node); -static int nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node); -static int nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node); +static int nr_reg_local_iter(NR_registry_name prefix, int (*action)(void *ptr, r_assoc_iterator *iter, const char *prefix, const char *name, nr_registry_node *node), void *ptr); +static int nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, const char *prefix, const char *name, nr_registry_node *node); +static int nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, const char *prefix, const char *name, nr_registry_node *node); +static int nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, const char *prefix, const char *name, nr_registry_node *node); int -nr_reg_local_iter(NR_registry prefix, int (*action)(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node), void *ptr) +nr_reg_local_iter(NR_registry_name prefix, int (*action)(void *ptr, r_assoc_iterator *iter, const char *prefix, const char *name, nr_registry_node *node), void *ptr) { int r, _status; r_assoc_iterator iter; @@ -106,7 +106,7 @@ nr_reg_local_iter(NR_registry prefix, int (*action)(void *ptr, r_assoc_iterator prefixl = strlen(prefix); for (;;) { - if ((r=r_assoc_iter(&iter, (void*)&name, &namel, (void*)&node))) { + if ((r=r_assoc_iter(&iter, (void**)&name, &namel, (void**)&node))) { if (r == R_EOD) break; else @@ -143,7 +143,7 @@ nr_reg_local_iter(NR_registry prefix, int (*action)(void *ptr, r_assoc_iterator } int -nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node) +nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, const char *prefix, const char *name, nr_registry_node *node) { int r, _status; @@ -156,12 +156,12 @@ nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char * } int -nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node) +nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, const char *prefix, const char *name, nr_registry_node *node) { int _status; int prefixl = strlen(prefix); - char *dot = 0; - nr_reg_find_children_arg *arg = (void*)ptr; + const char *dot = 0; + nr_reg_find_children_arg *arg = (nr_reg_find_children_arg*)ptr; assert(sizeof(*(arg->children)) == sizeof(NR_registry)); @@ -186,10 +186,10 @@ nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char } int -nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node) +nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, const char *prefix, const char *name, nr_registry_node *node) { int prefixl = strlen(prefix); - char *dot = 0; + const char *dot = 0; /* only count children */ if (name[prefixl] == '.') { @@ -214,7 +214,7 @@ nr_reg_rfree(void *ptr) } int -nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node) +nr_reg_fetch_node(const char *name, unsigned char type, nr_registry_node **node, int *free_node) { int r, _status; @@ -224,7 +224,7 @@ nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int * if ((r=nr_reg_is_valid(name))) ABORT(r); - if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)node))) + if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void**)node))) ABORT(r); if ((*node)->type != type) @@ -248,7 +248,7 @@ nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int * } int -nr_reg_insert_node(char *name, void *node) +nr_reg_insert_node(const char *name, void *node) { int r, _status; @@ -272,7 +272,7 @@ nr_reg_insert_node(char *name, void *node) abort: if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) { int freeit; - char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit); + char *data = nr_reg_alloc_node_data(name, (nr_registry_node*)node, &freeit); r_log(NR_LOG_REGISTRY, LOG_INFO, "insert '%s' (%s) %s: %s", name, nr_reg_type_name(((nr_registry_node*)node)->type), @@ -284,7 +284,7 @@ nr_reg_insert_node(char *name, void *node) } int -nr_reg_change_node(char *name, void *node, void *old) +nr_reg_change_node(const char *name, void *node, void *old) { int r, _status; @@ -303,7 +303,7 @@ nr_reg_change_node(char *name, void *node, void *old) abort: if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) { int freeit; - char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit); + char *data = nr_reg_alloc_node_data(name, (nr_registry_node*)node, &freeit); r_log(NR_LOG_REGISTRY, LOG_INFO, "change '%s' (%s) %s: %s", name, nr_reg_type_name(((nr_registry_node*)node)->type), @@ -315,7 +315,7 @@ nr_reg_change_node(char *name, void *node, void *old) } char * -nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit) +nr_reg_alloc_node_data(const char *name, nr_registry_node *node, int *freeit) { char *s = 0; int len; @@ -340,7 +340,7 @@ nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit) } if (alloc > 0) { - s = (void*)RMALLOC(alloc); + s = (char*)RMALLOC(alloc); if (!s) return 0; @@ -406,13 +406,13 @@ nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit) } int -nr_reg_get(char *name, int type, void *out) +nr_reg_get(const char *name, int type, void *out) { int r, _status; nr_scalar_registry_node *node = 0; int free_node = 0; - if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node))) + if ((r=nr_reg_fetch_node(name, type, (nr_registry_node **)&node, &free_node))) ABORT(r); if ((r=nr_reg_get_data(name, node, out))) @@ -425,7 +425,7 @@ nr_reg_get(char *name, int type, void *out) } int -nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out) +nr_reg_get_data(NR_registry_name name /* mjf-unused */, nr_scalar_registry_node *node, void *out) { int _status; @@ -468,13 +468,13 @@ nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out) } int -nr_reg_get_array(char *name, unsigned char type, unsigned char *out, size_t size, size_t *length) +nr_reg_get_array(const char *name, unsigned char type, unsigned char *out, size_t size, size_t *length) { int r, _status; nr_array_registry_node *node = 0; int free_node = 0; - if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node))) + if ((r=nr_reg_fetch_node(name, type, (nr_registry_node **)&node, &free_node))) ABORT(r); if (size < node->array.length) @@ -492,7 +492,7 @@ nr_reg_get_array(char *name, unsigned char type, unsigned char *out, size_t size } int -nr_reg_set(char *name, int type, void *data) +nr_reg_set(const char *name, int type, void *data) { int r, _status; nr_scalar_registry_node *node = 0; @@ -500,7 +500,7 @@ nr_reg_set(char *name, int type, void *data) int changed = 0; int free_node = 0; - if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node))) + if ((r=nr_reg_fetch_node(name, type, (nr_registry_node **)&node, &free_node))) if (r == R_NOT_FOUND) { create_node = 1; free_node = 1; @@ -509,7 +509,7 @@ nr_reg_set(char *name, int type, void *data) ABORT(r); if (create_node) { - if (!(node=(void*)RCALLOC(sizeof(nr_scalar_registry_node)))) + if (!(node=R_NEW(nr_scalar_registry_node))) ABORT(R_NO_MEMORY); node->type = type; @@ -570,7 +570,7 @@ nr_reg_set(char *name, int type, void *data) } int -nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length) +nr_reg_set_array(const char *name, unsigned char type, const UCHAR *data, size_t length) { int r, _status; nr_array_registry_node *old = 0; @@ -579,7 +579,7 @@ nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length) int added = 0; int changed = 0; - if ((r=nr_reg_fetch_node(name, type, (void*)&old, &free_node))) { + if ((r=nr_reg_fetch_node(name, type, (nr_registry_node **)&old, &free_node))) { if (r != R_NOT_FOUND) ABORT(r); } @@ -596,7 +596,7 @@ nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length) changed = 1; if (old->array.length < length) { - if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length))) + if (!(node=(nr_array_registry_node*)RCALLOC_RAWSIZE(sizeof(nr_array_registry_node)+length))) ABORT(R_NO_MEMORY); } else { @@ -605,7 +605,7 @@ nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length) } } else { - if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length))) + if (!(node=(nr_array_registry_node*)RCALLOC_RAWSIZE(sizeof(nr_array_registry_node)+length))) ABORT(R_NO_MEMORY); added = 1; @@ -632,7 +632,7 @@ nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length) } int -nr_reg_set_parent_registries(char *name) +nr_reg_set_parent_registries(const char *name) { int r, _status; char *parent = 0; @@ -660,7 +660,7 @@ nr_reg_set_parent_registries(char *name) /* NON-STATIC METHODS */ int -nr_reg_is_valid(NR_registry name) +nr_reg_is_valid(NR_registry_name name) { int _status; unsigned int length; @@ -697,7 +697,7 @@ nr_reg_is_valid(NR_registry name) int -nr_reg_compute_length(char *name, nr_registry_node *in, size_t *length) +nr_reg_compute_length(const char *name, nr_registry_node *in, size_t *length) { int _status; nr_array_registry_node *node = (nr_array_registry_node*)in; @@ -767,7 +767,7 @@ nr_reg_local_init(void) } int -nr_reg_local_get_length(NR_registry name, size_t *length) +nr_reg_local_get_length(NR_registry_name name, size_t *length) { int r, _status; nr_registry_node *node = 0; @@ -775,7 +775,7 @@ nr_reg_local_get_length(NR_registry name, size_t *length) if ((r=nr_reg_is_valid(name))) ABORT(r); - if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)&node))) + if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void**)&node))) ABORT(r); if ((r=nr_reg_compute_length(name, node, length))) @@ -788,7 +788,7 @@ nr_reg_local_get_length(NR_registry name, size_t *length) int -nr_reg_local_del(NR_registry name) +nr_reg_local_del(NR_registry_name name) { int r, _status; @@ -818,7 +818,7 @@ nr_reg_local_del(NR_registry name) } int -nr_reg_local_get_child_count(NR_registry parent, size_t *count) +nr_reg_local_get_child_count(NR_registry_name parent, size_t *count) { int r, _status; nr_registry_node *ignore1 = 0; @@ -846,7 +846,7 @@ nr_reg_local_get_child_count(NR_registry parent, size_t *count) } int -nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length) +nr_reg_local_get_children(NR_registry_name parent, NR_registry *data, size_t size, size_t *length) { int r, _status; nr_reg_find_children_arg arg; diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c index e1f81056a85cc..c4ee4c21126fb 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c @@ -52,14 +52,14 @@ #include "r_log.h" #include "r_macros.h" -static char CB_ACTIONS[] = { NR_REG_CB_ACTION_ADD, - NR_REG_CB_ACTION_DELETE, - NR_REG_CB_ACTION_CHANGE, - NR_REG_CB_ACTION_FINAL }; +static const char CB_ACTIONS[] = { NR_REG_CB_ACTION_ADD, + NR_REG_CB_ACTION_DELETE, + NR_REG_CB_ACTION_CHANGE, + NR_REG_CB_ACTION_FINAL }; typedef struct nr_reg_cb_info_ { char action; - void (*cb)(void *cb_arg, char action, NR_registry name); + void (*cb)(void *cb_arg, char action, NR_registry_name name); void *cb_arg; NR_registry name; } nr_reg_cb_info; @@ -75,8 +75,8 @@ static int nr_reg_validate_action(char action); static int nr_reg_assoc_destroy(void *ptr); static int compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID]); static int nr_reg_info_free(void *ptr); -static int nr_reg_raise_event_recurse(char *name, char *tmp, int action); -static int nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg); +static int nr_reg_raise_event_recurse(const char *name, char *tmp, int action); +static int nr_reg_register_callback(NR_registry_name name, char action, void (*cb)(void *cb_arg, char action, NR_registry_name name), void *cb_arg); int nr_reg_cb_init() @@ -114,7 +114,7 @@ nr_reg_validate_action(char action) } int -nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg) +nr_reg_register_callback(NR_registry_name name, char action, void (*cb)(void *cb_arg, char action, NR_registry_name name), void *cb_arg) { int r, _status; r_assoc *assoc = 0; @@ -135,7 +135,7 @@ nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, if ((r=nr_reg_validate_action(action))) ABORT(r); - if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void*)&assoc))) { + if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void**)&assoc))) { if (r == R_NOT_FOUND) create_assoc = 1; else @@ -150,10 +150,10 @@ nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, ABORT(r); } - if ((r=compute_cb_id(cb, action, cb_id))) + if ((r=compute_cb_id((void*)cb, action, cb_id))) ABORT(r); - if ((r=r_assoc_fetch(assoc, (char*)cb_id, SIZEOF_CB_ID, (void*)&info))) { + if ((r=r_assoc_fetch(assoc, (char*)cb_id, SIZEOF_CB_ID, (void**)&info))) { if (r == R_NOT_FOUND) create_info = 1; else @@ -161,11 +161,11 @@ nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, } if (create_info) { - if (!(info=(void*)RCALLOC(sizeof(*info)))) + if (!(info=R_NEW(nr_reg_cb_info))) ABORT(R_NO_MEMORY); } - strncpy(info->name, name, sizeof(info->name)); + (void)strlcpy(info->name, name, sizeof(info->name)); info->action = action; info->cb = cb; info->cb_arg = cb_arg; @@ -200,10 +200,10 @@ compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID]) return 0; } -char * +const char * nr_reg_action_name(int action) { - char *name = "*Unknown*"; + const char *name = "*Unknown*"; switch (action) { case NR_REG_CB_ACTION_ADD: name = "add"; break; @@ -230,7 +230,7 @@ nr_reg_info_free(void *ptr) /* call with tmp=0 */ int -nr_reg_raise_event_recurse(char *name, char *tmp, int action) +nr_reg_raise_event_recurse(const char *name, char *tmp, int action) { int r, _status; r_assoc *assoc = 0; @@ -248,7 +248,7 @@ nr_reg_raise_event_recurse(char *name, char *tmp, int action) free_tmp = 1; } - if ((r=r_assoc_fetch(nr_registry_callbacks, tmp, strlen(tmp)+1, (void*)&assoc))) { + if ((r=r_assoc_fetch(nr_registry_callbacks, tmp, strlen(tmp)+1, (void**)&assoc))) { if (r != R_NOT_FOUND) ABORT(r); @@ -264,7 +264,7 @@ nr_reg_raise_event_recurse(char *name, char *tmp, int action) ABORT(r); for (;;) { - if ((r=r_assoc_iter(&iter, (void*)&key, &keyl, (void*)&info))) { + if ((r=r_assoc_iter(&iter, (void**)&key, &keyl, (void**)&info))) { if (r == R_EOD) break; else @@ -309,11 +309,11 @@ nr_reg_raise_event_recurse(char *name, char *tmp, int action) /* NON-STATIC METHODS */ int -nr_reg_raise_event(NR_registry name, int action) +nr_reg_raise_event(NR_registry_name name, int action) { int r, _status; int count; - char *event = nr_reg_action_name(action); + const char *event = nr_reg_action_name(action); r_log(NR_LOG_REGISTRY, LOG_DEBUG, "raising event '%s' on '%s'", event, name); @@ -344,7 +344,7 @@ nr_reg_raise_event(NR_registry name, int action) /* PUBLIC METHODS */ int -NR_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg) +NR_reg_register_callback(NR_registry_name name, char action, void (*cb)(void *cb_arg, char action, NR_registry_name name), void *cb_arg) { int r, _status; size_t i; diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/hex.c b/dom/media/webrtc/transport/third_party/nrappkit/src/util/hex.c index f5885f012abc5..e96495a3e70b2 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/hex.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/hex.c @@ -43,10 +43,10 @@ #include "hex.h" #include "r_log.h" -static char bin2hex_map[][3] = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" }; +static const char bin2hex_map[][3] = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" }; int -nr_nbin2hex(UCHAR *bin, size_t binlen, char hex[], size_t size, size_t *len) +nr_nbin2hex(const UCHAR *bin, size_t binlen, char hex[], size_t size, size_t *len) { int _status; size_t i; diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/hex.h b/dom/media/webrtc/transport/third_party/nrappkit/src/util/hex.h index cba757294f123..ac298ff650f7c 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/hex.h +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/hex.h @@ -40,7 +40,7 @@ #ifndef _hex_h #define _hex_h -int nr_nbin2hex(UCHAR *bin, size_t binlen, char hex[], size_t size, size_t *len); +int nr_nbin2hex(const UCHAR *bin, size_t binlen, char hex[], size_t size, size_t *len); #endif diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_assoc.c b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_assoc.c index 21e332409bebb..5eeb8683a9e6e 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_assoc.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_assoc.c @@ -107,7 +107,7 @@ typedef struct r_assoc_el_ { struct r_assoc_ { int size; int bits; - int (*hash_func)(char *key,int len,int size); + int (*hash_func)(const char *key,int len,int size); r_assoc_el **chains; UINT4 num_elements; }; @@ -116,25 +116,24 @@ struct r_assoc_ { static int destroy_assoc_chain(r_assoc_el *chain); static int r_assoc_fetch_bucket(r_assoc *assoc, - char *key,int len,r_assoc_el **bucketp); + const char *key,int len,r_assoc_el **bucketp); int r_assoc_create( r_assoc **assocp, - int (*hash_func)(char *key, int len, int size), + int (*hash_func)(const char *key, int len, int size), int bits ) { r_assoc *assoc=0; int _status; - if(!(assoc=(r_assoc *)RCALLOC(sizeof(r_assoc)))) + if(!(assoc=R_NEW(r_assoc))) ABORT(R_NO_MEMORY); assoc->size=(1<bits=bits; assoc->hash_func=hash_func; - if(!(assoc->chains=(r_assoc_el **)RCALLOC(sizeof(r_assoc_el *)* - assoc->size))) + if(!(assoc->chains=R_NEW_CNT(r_assoc_el *, assoc->size))) ABORT(R_NO_MEMORY); *assocp=assoc; @@ -186,7 +185,7 @@ static int destroy_assoc_chain(r_assoc_el *chain) static int r_assoc_fetch_bucket( r_assoc *assoc, - char *key, + const char *key, int len, r_assoc_el **bucketp ) @@ -206,7 +205,7 @@ static int r_assoc_fetch_bucket( return(R_NOT_FOUND); } -int r_assoc_fetch(r_assoc *assoc, char *key, int len, void **datap) +int r_assoc_fetch(r_assoc *assoc, const char *key, int len, void **datap) { r_assoc_el *bucket = 0; int r; @@ -223,7 +222,7 @@ int r_assoc_fetch(r_assoc *assoc, char *key, int len, void **datap) int r_assoc_insert( r_assoc *assoc, - char *key, + const char *key, int len, void *data, int (*copy)(void **knew, void *old), @@ -242,7 +241,7 @@ int r_assoc_insert( ABORT(r); hash_value=assoc->hash_func(key,len,assoc->bits); - if(!(new_bucket=(r_assoc_el *)RCALLOC(sizeof(r_assoc_el)))) + if(!(new_bucket=R_NEW(r_assoc_el))) ABORT(R_NO_MEMORY); if(!(new_bucket->key=(char *)RMALLOC(len))) ABORT(R_NO_MEMORY); @@ -370,9 +369,9 @@ int r_assoc_iter_delete(r_assoc_iterator *iter) } -int r_crc32(char *data,int len,UINT4 *crcval); +int r_crc32(const char *data,int len,UINT4 *crcval); -int r_assoc_crc32_hash_compute(char *data, int len, int bits) +int r_assoc_crc32_hash_compute(const char *data, int len, int bits) { UINT4 res; UINT4 mask; diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_assoc.h b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_assoc.h index a825daaa986f7..d0fd2836777df 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_assoc.h +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_assoc.h @@ -91,18 +91,18 @@ typedef struct r_assoc_ r_assoc; int r_assoc_create(r_assoc **assocp, - int (*hash_func)(char *,int,int), + int (*hash_func)(const char *,int,int), int bits); -int r_assoc_insert(r_assoc *assoc,char *key,int len, +int r_assoc_insert(r_assoc *assoc, const char *key, int len, void *value,int (*copy)(void **knew,void *old), int (*destroy)(void *ptr),int how); #define R_ASSOC_REPLACE 0x1 #define R_ASSOC_NEW 0x2 -int r_assoc_fetch(r_assoc *assoc,char *key, int len, void **value); +int r_assoc_fetch(r_assoc *assoc, const char *key, int len, void **value); int r_assoc_destroy(r_assoc **assocp); -int r_assoc_crc32_hash_compute(char *key, int len,int bits); +int r_assoc_crc32_hash_compute(const char *key, int len,int bits); /*We need iterators, but I haven't written them yet*/ typedef struct r_assoc_iterator_ { diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_crc32.c b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_crc32.c index 913ac3f0db92d..7ab16fd45ae93 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_crc32.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_crc32.c @@ -147,10 +147,10 @@ static const u_int32_t crctab[256] = { #include #include -int r_crc32(char *buf, int dlen, u_int32_t *cval) +int r_crc32(const char *buf, int dlen, u_int32_t *cval) { u_int32_t crc = ~0; - char *p = 0; + const char *p = 0; int i; u_int32_t crc32_total = 0 ; diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_crc32.h b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_crc32.h index c11be4e04daf3..bfa04dd760762 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_crc32.h +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_crc32.h @@ -9,6 +9,6 @@ #ifndef _r_crc32_ #define _r_crc32_ -int r_crc32 (char *buf,int dlen, UINT4 *cval); +int r_crc32 (const char *buf,int dlen, UINT4 *cval); #endif diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_data.c b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_data.c index 2c5bddd61602c..f08c5a9f5be7d 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_data.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_data.c @@ -89,7 +89,7 @@ int r_data_create(Data **dp, const UCHAR *d, size_t l) Data *d_=0; int _status; - if(!(d_=(Data *)RCALLOC(sizeof(Data)))) + if(!(d_=R_NEW(Data))) ABORT(R_NO_MEMORY); if(!(d_->data=(UCHAR *)RMALLOC(l))) ABORT(R_NO_MEMORY); @@ -114,9 +114,9 @@ int r_data_alloc(Data **dp, size_t l) Data *d_=0; int _status; - if(!(d_=(Data *)RCALLOC(sizeof(Data)))) + if(!(d_=R_NEW(Data))) ABORT(R_NO_MEMORY); - if(!(d_->data=(UCHAR *)RCALLOC(l))) + if(!(d_->data=(UCHAR*)RCALLOC_RAWSIZE(l))) ABORT(R_NO_MEMORY); d_->len=l; diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_errors.c b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_errors.c index 1fb93e1115549..e2885b00895c2 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_errors.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_errors.c @@ -88,15 +88,15 @@ static struct { int errnum; - char *str; + const char *str; } errors[] = NR_ERROR_MAPPING; -char * +const char * nr_strerror(int errnum) { static char unknown_error[256]; size_t i; - char *error = 0; + const char *error = 0; for (i = 0; i < sizeof(errors)/sizeof(*errors); ++i) { if (errnum == errors[i].errnum) { @@ -112,12 +112,3 @@ nr_strerror(int errnum) return error; } - -int -nr_strerror_r(int errnum, char *strerrbuf, size_t buflen) -{ - char *error = nr_strerror(errnum); - snprintf(strerrbuf, buflen, "%s", error); - return 0; -} - diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_errors.h b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_errors.h index 2ca0a7b2f12cb..55c8bcc8253a5 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_errors.h +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_errors.h @@ -118,8 +118,7 @@ { R_RETRY, "Retry may be possible" },\ } -char *nr_strerror(int errnum); -int nr_strerror_r(int errnum, char *strerrbuf, size_t buflen); +const char *nr_strerror(int errnum); #endif diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_memory.c b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_memory.c index f2d619ccdd286..6c5c0708bf855 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_memory.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_memory.c @@ -55,7 +55,7 @@ typedef struct r_malloc_chunk_ { #define CHUNK_MEMORY_OFFSET offsetof(struct r_malloc_chunk_, memory) #define GET_CHUNK_ADDR_FROM_MEM_ADDR(memp) \ - ((struct r_malloc_chunk *)(((unsigned char*)(memp))-CHUNK_MEMORY_OFFSET)) + ((r_malloc_chunk *)(((unsigned char*)(memp))-CHUNK_MEMORY_OFFSET)) #define CHUNK_SIZE(size) (size+sizeof(r_malloc_chunk)) #define HDR_FLAG 0x464c4147 @@ -70,7 +70,7 @@ void *r_malloc(int type, size_t size) total=size+sizeof(r_malloc_chunk); - if(!(chunk=malloc(total))) + if(!(chunk=(r_malloc_chunk*)malloc(total))) return(0); #ifdef SANITY_CHECKS @@ -129,7 +129,7 @@ char *r_strdup(const char *str) len=strlen(str)+1; - if(!(nstr=RMALLOC(len))) + if(!(nstr=(char*)RMALLOC(len))) return(0); memcpy(nstr,str,len); diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_memory.h b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_memory.h index 2f75b1787d862..b1d9cef6b120f 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_memory.h +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr/r_memory.h @@ -49,8 +49,16 @@ char *r_strdup(const char *str); #define RMALLOC(a) malloc(a) #endif -#ifndef RCALLOC -#define RCALLOC(a) calloc(1,a) +#ifndef RCALLOC_RAWSIZE +#define RCALLOC_RAWSIZE(a) calloc(1,a) +#endif + +#ifndef R_NEW +#define R_NEW(type) (type*)calloc(1,sizeof(type)) +#endif + +#ifndef R_NEW_CNT +#define R_NEW_CNT(type,cnt) (type*)calloc(cnt,sizeof(type)) #endif #ifndef RFREE @@ -73,8 +81,16 @@ void r_free (void *ptr); #define RMALLOC(a) r_malloc(R_MALLOC_TYPE,a) #endif -#ifndef RCALLOC -#define RCALLOC(a) r_calloc(R_MALLOC_TYPE,1,a) +#ifndef RCALLOC_RAWSIZE +#define RCALLOC_RAWSIZE(a) r_calloc(R_MALLOC_TYPE,1,a) +#endif + +#ifndef R_NEW +#define R_NEW(type) (type*)r_calloc(R_MALLOC_TYPE,1,sizeof(type)) +#endif + +#ifndef R_NEW_CNT +#define R_NEW_CNT(type,cnt) (type*)r_calloc(R_MALLOC_TYPE,cnt,sizeof(type)) #endif #ifndef RFREE diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/util/p_buf.c b/dom/media/webrtc/transport/third_party/nrappkit/src/util/p_buf.c index 5513e6fcbdf32..e272c70162b28 100644 --- a/dom/media/webrtc/transport/third_party/nrappkit/src/util/p_buf.c +++ b/dom/media/webrtc/transport/third_party/nrappkit/src/util/p_buf.c @@ -54,7 +54,7 @@ int nr_p_buf_ctx_create(int size, nr_p_buf_ctx **ctxp) int _status; nr_p_buf_ctx *ctx=0; - if(!(ctx=(nr_p_buf_ctx *)RCALLOC(sizeof(nr_p_buf_ctx)))) + if(!(ctx=R_NEW(nr_p_buf_ctx))) ABORT(R_NO_MEMORY); ctx->buf_size=size; @@ -97,7 +97,7 @@ int nr_p_buf_alloc(nr_p_buf_ctx *ctx, nr_p_buf **bufp) goto ok; } else { - if(!(buf=(nr_p_buf *)RCALLOC(sizeof(nr_p_buf)))) + if(!(buf=R_NEW(nr_p_buf))) ABORT(R_NO_MEMORY); if(!(buf->data=(UCHAR *)RMALLOC(ctx->buf_size))) ABORT(R_NO_MEMORY); diff --git a/dom/system/NetworkGeolocationProvider.sys.mjs b/dom/system/NetworkGeolocationProvider.sys.mjs index a3f9d5de24454..f89cf1b1a7fb8 100644 --- a/dom/system/NetworkGeolocationProvider.sys.mjs +++ b/dom/system/NetworkGeolocationProvider.sys.mjs @@ -402,7 +402,7 @@ NetworkGeolocationProvider.prototype = { let timeoutId = lazy.setTimeout( () => fetchController.abort(), - Services.prefs.getIntPref("geo.provider.network.timeout") + Services.prefs.getIntPref("geo.provider.network.timeout", 60000) ); let response = await fetch(url, fetchOpts); diff --git a/dom/webgpu/ObjectModel.h b/dom/webgpu/ObjectModel.h index 3dbc29588ad5a..f1563e6a95f34 100644 --- a/dom/webgpu/ObjectModel.h +++ b/dom/webgpu/ObjectModel.h @@ -68,6 +68,11 @@ class ObjectBase { JSObject* WrapObject(JSContext* cx, JS::Handle givenProto) \ override; +// Declare cycle collection support in a normal WebGPU DOM class. +// +// This macro is not appropriate for classes that have base classes with their +// own cycle collection machinery: those require an `_INHERITED` variant of the +// macro. See `mozilla::webgpu::Device` for an example. #define GPU_DECL_CYCLE_COLLECTION(T) \ NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(T) \ NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(T) @@ -77,6 +82,15 @@ class ObjectBase { return dom::GPU##T##_Binding::Wrap(cx, this, givenProto); \ } +// Implement cycle collection support for a normal WebGPU DOM class. +// +// This macro is not appropriate for classes that have base classes with their +// own cycle collection machinery: those require an `_INHERITED` variant of the +// macro. See `mozilla::webgpu::Device` for an example. +// +// This macro is not appropriate for classes that inherit from +// `SupportsWeakPtr`: those require a `_WEAK_PTR` variant of the macro. See +// `mozilla::webgpu::Device` for an example. #define GPU_IMPL_CYCLE_COLLECTION(T, ...) \ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(T, __VA_ARGS__) diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index ee1a2314229a3..64a58a0dd5ce2 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -1175,7 +1175,9 @@ void BarrieredMoveRangeImpl(gc::Cell* owner, void* dst, const T* src, template void BarrieredMoveRange(gc::Cell* owner, void* dst, const T* src, size_t count) { - MOZ_ASSERT(dst != src); + if (dst == src) { + return; + } if (owner->isTenured() || owner->shadowZone()->needsIncrementalBarrier()) { gc::BarrieredMoveRangeImpl(owner, dst, src, count); diff --git a/js/src/jit-test/tests/gc/pretenured-operations.js b/js/src/jit-test/tests/gc/pretenured-operations.js index 9fb1dbd522104..d5a62f09bb441 100644 --- a/js/src/jit-test/tests/gc/pretenured-operations.js +++ b/js/src/jit-test/tests/gc/pretenured-operations.js @@ -51,3 +51,12 @@ f(); // DOM Allocations let fdo = new FakeDOMObject(); check(() => { return fdo.doBar(); }) + +// Scripted constructors +class C {} +class D extends C {} +let boundC = C.bind({},1,2); + +check(() => { return new C() }); +check(() => { return new D() }); +check(() => { return new boundC() }); diff --git a/js/src/jit-test/tests/ion/bug2013543.js b/js/src/jit-test/tests/ion/bug2013543.js new file mode 100644 index 0000000000000..950f65945e164 --- /dev/null +++ b/js/src/jit-test/tests/ion/bug2013543.js @@ -0,0 +1,20 @@ +function foo(obj1, obj2) { + var keys1 = Object.keys(obj1); + var val = obj2[keys1[0]]; + var keys2 = Object.keys(obj2); + return val; +} + +var objs = []; +for (var i = 0; i < 30; i++) { + var o = {}; + for (var j = 0; j <= i; j++) { + o["p" + j] = j + 1; + } + objs.push(o); +} + +for (var i = 0; i < 5000; i++) { + var o = objs[i % objs.length]; + foo(o, o); +} diff --git a/js/src/jit-test/tests/wasm/gc/arrays.js b/js/src/jit-test/tests/wasm/gc/arrays.js index 5b183be74884b..c7d698053b508 100644 --- a/js/src/jit-test/tests/wasm/gc/arrays.js +++ b/js/src/jit-test/tests/wasm/gc/arrays.js @@ -1843,6 +1843,10 @@ for (let [elemTy, valueTy, src, exp1, exp2] of ARRAY_COPY_TESTS) { arrayCopy(srcTO, 2, srcTO, 0, 3); assertEq(eqArrays(srcTO, exp2), true); + // Also check that a useless copy is valid nonetheless. + arrayCopy(srcTO, 0, srcTO, 0, 6); + assertEq(eqArrays(srcTO, exp2), true); + // Check out-of-bounds conditions let exp1TO = arrayNew(exp1[0], exp1[1], exp1[2], exp1[3], exp1[4], exp1[5]); let exp2TO = arrayNew(exp2[0], exp2[1], exp2[2], exp2[3], exp2[4], exp2[5]); diff --git a/js/src/jit/BaselineCacheIRCompiler.cpp b/js/src/jit/BaselineCacheIRCompiler.cpp index 6ccd0024656e1..98b2bd292961b 100644 --- a/js/src/jit/BaselineCacheIRCompiler.cpp +++ b/js/src/jit/BaselineCacheIRCompiler.cpp @@ -3104,6 +3104,18 @@ bool BaselineCacheIRCompiler::emitCallClassHook(ObjOperandId calleeId, targetOffset_); } +// This op generates no code. It caches metadata for eventual use in createThis. +bool BaselineCacheIRCompiler::emitMetaCreateThis(uint32_t numFixedSlots, + uint32_t numDynamicSlots, + gc::AllocKind allocKind, + uint32_t thisShapeOffset, + uint32_t siteOffset) { + MOZ_ASSERT(createThisData_.isNothing()); + createThisData_.emplace(numFixedSlots, numDynamicSlots, allocKind, + thisShapeOffset, siteOffset); + return true; +} + // Helper function for loading call arguments from the stack. Loads // and unboxes an object from a specific slot. void BaselineCacheIRCompiler::loadStackObject(ArgumentKind kind, @@ -3127,9 +3139,8 @@ void BaselineCacheIRCompiler::loadStackObject(ArgumentKind kind, } } -template -void BaselineCacheIRCompiler::storeThis(const T& newThis, Register argcReg, - CallFlags flags) { +void BaselineCacheIRCompiler::storeThis(const ConstantOrRegister& newThis, + Register argcReg, CallFlags flags) { switch (flags.getArgFormat()) { case CallFlags::Standard: { BaseValueIndex thisAddress( @@ -3137,13 +3148,13 @@ void BaselineCacheIRCompiler::storeThis(const T& newThis, Register argcReg, argcReg, // Arguments 1 * sizeof(Value) + // NewTarget BaselineStubFrameLayout::Size()); // Stub frame - masm.storeValue(newThis, thisAddress); + masm.storeConstantOrRegister(newThis, thisAddress); } break; case CallFlags::Spread: { Address thisAddress(FramePointer, 2 * sizeof(Value) + // Arg array, NewTarget BaselineStubFrameLayout::Size()); // Stub frame - masm.storeValue(newThis, thisAddress); + masm.storeConstantOrRegister(newThis, thisAddress); } break; default: MOZ_CRASH("Invalid arg format for scripted constructor"); @@ -3162,7 +3173,8 @@ void BaselineCacheIRCompiler::storeThis(const T& newThis, Register argcReg, * overwrites the magic ThisV on the stack. */ void BaselineCacheIRCompiler::createThis(Register argcReg, Register calleeReg, - Register scratch, CallFlags flags, + Register scratch, Register scratch2, + Register scratch3, CallFlags flags, bool isBoundFunction) { MOZ_ASSERT(flags.isConstructing()); @@ -3171,12 +3183,54 @@ void BaselineCacheIRCompiler::createThis(Register argcReg, Register calleeReg, return; } + Label done; + bool hasCreateThisData = createThisData_.isSome(); + if (hasCreateThisData) { + Label fail; + Register result = scratch; + + Register shape = scratch2; + masm.loadPtr(stubAddress(createThisData_->thisShapeOffset), shape); + + Register site = scratch3; + masm.loadPtr(stubAddress(createThisData_->allocSiteOffset), site); + + // On x86-32, all of our registers are already spoken for, but we need one + // more. We already generate code to reload `calleeReg` in case it was + // clobbered by a GC, so we can use it here. + Register temp = calleeReg; + + masm.createPlainGCObject( + result, shape, temp, shape, createThisData_->numFixedSlots, + createThisData_->numDynamicSlots, createThisData_->allocKind, + gc::Heap::Default, &fail, AllocSiteInput(site)); + storeThis(TypedOrValueRegister(MIRType::Object, AnyRegister(result)), + argcReg, flags); + + // This rejoins the fallback path at the point where we will restore + // calleeReg. + masm.jump(&done); + + masm.bind(&fail); + if (isBoundFunction) { + // We clobbered calleeReg, but we still need it in the fallback path + // below. Restore it. + loadStackObject(ArgumentKind::Callee, flags, argcReg, calleeReg); + } + } + // Save live registers that don't have to be traced. LiveGeneralRegisterSet liveNonGCRegs; liveNonGCRegs.add(argcReg); masm.PushRegsInMask(liveNonGCRegs); - // CreateThis takes two arguments: callee, and newTarget. + // CreateThis takes two arguments: callee, and newTarget. We may also pass + // an alloc site. + + if (hasCreateThisData) { + masm.loadPtr(stubAddress(createThisData_->allocSiteOffset), scratch); + masm.push(scratch); + } if (isBoundFunction) { // Push the bound function's target as callee and newTarget. @@ -3194,10 +3248,16 @@ void BaselineCacheIRCompiler::createThis(Register argcReg, Register calleeReg, masm.push(scratch); } - // Call CreateThisFromIC. - using Fn = - bool (*)(JSContext*, HandleObject, HandleObject, MutableHandleValue); - callVM(masm); + if (hasCreateThisData) { + using Fn = bool (*)(JSContext*, HandleObject, HandleObject, gc::AllocSite*, + MutableHandleValue); + callVM(masm); + } else { + // Call CreateThisFromIC. + using Fn = + bool (*)(JSContext*, HandleObject, HandleObject, MutableHandleValue); + callVM(masm); + } #ifdef DEBUG Label createdThisOK; @@ -3218,7 +3278,9 @@ void BaselineCacheIRCompiler::createThis(Register argcReg, Register calleeReg, // Save |this| value back into pushed arguments on stack. MOZ_ASSERT(!liveNonGCRegs.aliases(JSReturnOperand)); - storeThis(JSReturnOperand, argcReg, flags); + storeThis(TypedOrValueRegister(JSReturnOperand), argcReg, flags); + + masm.bind(&done); // Restore calleeReg. CreateThisFromIC may trigger a GC, so we reload the // callee from the stub frame (which is traced) instead of spilling it to @@ -3258,8 +3320,9 @@ bool BaselineCacheIRCompiler::emitCallScriptedFunctionShared( ObjOperandId calleeId, Int32OperandId argcId, CallFlags flags, uint32_t argcFixed, Maybe icScriptOffset) { AutoOutputRegister output(*this); - AutoScratchRegisterMaybeOutput scratch(allocator, masm, output); - AutoScratchRegister scratch2(allocator, masm); + AutoScratchRegister scratch(allocator, masm); + AutoScratchRegisterMaybeOutput scratch2(allocator, masm, output); + AutoScratchRegisterMaybeOutputType scratch3(allocator, masm, output); Register calleeReg = allocator.useRegister(masm, calleeId); Register argcReg = allocator.useRegister(masm, argcId); @@ -3287,7 +3350,7 @@ bool BaselineCacheIRCompiler::emitCallScriptedFunctionShared( } if (isConstructing) { - createThis(argcReg, calleeReg, scratch, flags, + createThis(argcReg, calleeReg, scratch, scratch2, scratch3, flags, /* isBoundFunction = */ false); } @@ -3319,7 +3382,7 @@ bool BaselineCacheIRCompiler::emitCallScriptedFunctionShared( stubFrame.leave(masm); if (!isSameRealm) { - masm.switchToBaselineFrameRealm(scratch2); + masm.switchToBaselineFrameRealm(scratch); } return true; @@ -3476,8 +3539,9 @@ bool BaselineCacheIRCompiler::emitCallBoundScriptedFunction( JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); AutoOutputRegister output(*this); - AutoScratchRegisterMaybeOutput scratch(allocator, masm, output); - AutoScratchRegister scratch2(allocator, masm); + AutoScratchRegister scratch(allocator, masm); + AutoScratchRegisterMaybeOutput scratch2(allocator, masm, output); + AutoScratchRegisterMaybeOutputType scratch3(allocator, masm, output); Register calleeReg = allocator.useRegister(masm, calleeId); Register argcReg = allocator.useRegister(masm, argcId); @@ -3501,7 +3565,7 @@ bool BaselineCacheIRCompiler::emitCallBoundScriptedFunction( masm.unboxObject(boundTarget, scratch); masm.switchToObjectRealm(scratch, scratch); } - createThis(argcReg, calleeReg, scratch, flags, + createThis(argcReg, calleeReg, scratch, scratch2, scratch3, flags, /* isBoundFunction = */ true); } @@ -3537,7 +3601,7 @@ bool BaselineCacheIRCompiler::emitCallBoundScriptedFunction( stubFrame.leave(masm); if (!isSameRealm) { - masm.switchToBaselineFrameRealm(scratch2); + masm.switchToBaselineFrameRealm(scratch); } return true; diff --git a/js/src/jit/BaselineCacheIRCompiler.h b/js/src/jit/BaselineCacheIRCompiler.h index 88d981b19e33d..1fb4b001b6e5c 100644 --- a/js/src/jit/BaselineCacheIRCompiler.h +++ b/js/src/jit/BaselineCacheIRCompiler.h @@ -47,10 +47,20 @@ ICAttachResult AttachBaselineCacheIRStub(JSContext* cx, // BaselineCacheIRCompiler compiles CacheIR to BaselineIC native code. class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler { + struct CreateThisData { + uint32_t numFixedSlots; + uint32_t numDynamicSlots; + gc::AllocKind allocKind; + uint32_t thisShapeOffset; + uint32_t allocSiteOffset; + }; + bool makesGCCalls_; uint8_t localTracingSlots_ = 0; Register baselineFrameReg_ = FramePointer; + mozilla::Maybe createThisData_; + // This register points to the baseline frame of the caller. It should only // be used before we enter a stub frame. This is normally the frame pointer // register, but with --enable-ic-frame-pointers we have to allocate a @@ -95,9 +105,10 @@ class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler { CallFlags flags, uint32_t numBoundArgs, bool isJitCall); void createThis(Register argcReg, Register calleeReg, Register scratch, - CallFlags flags, bool isBoundFunction); - template - void storeThis(const T& newThis, Register argcReg, CallFlags flags); + Register scratch2, Register scratch3, CallFlags flags, + bool isBoundFunction); + void storeThis(const ConstantOrRegister& newThis, Register argcReg, + CallFlags flags); void updateReturnValue(); enum class NativeCallType { Native, ClassHook }; diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp index 46be83a4c3a43..3ae32cdc03c56 100644 --- a/js/src/jit/CacheIR.cpp +++ b/js/src/jit/CacheIR.cpp @@ -13608,7 +13608,7 @@ AttachDecision InlinableNativeIRGenerator::tryAttachStub() { // constructor, for later use during Ion compilation. ScriptedThisResult CallIRGenerator::getThisShapeForScripted( HandleFunction calleeFunc, Handle newTarget, - MutableHandle result) { + MutableHandle result) { // Some constructors allocate their own |this| object. if (calleeFunc->constructorNeedsUninitializedThis()) { return ScriptedThisResult::UninitializedThis; @@ -13622,7 +13622,7 @@ ScriptedThisResult CallIRGenerator::getThisShapeForScripted( } AutoRealm ar(cx_, calleeFunc); - Shape* thisShape = ThisShapeForFunction(cx_, calleeFunc, newTarget); + SharedShape* thisShape = ThisShapeForFunction(cx_, calleeFunc, newTarget); if (!thisShape) { cx_->clearPendingException(); return ScriptedThisResult::NoAction; @@ -13651,11 +13651,10 @@ static bool CanOptimizeScriptedCall(JSFunction* callee, bool isConstructing) { return true; } -void CallIRGenerator::emitCallScriptedGuards(ObjOperandId calleeObjId, - JSFunction* calleeFunc, - Int32OperandId argcId, - CallFlags flags, Shape* thisShape, - bool isBoundFunction) { +void CallIRGenerator::emitCallScriptedGuards( + ObjOperandId calleeObjId, JSFunction* calleeFunc, Int32OperandId argcId, + CallFlags flags, SharedShape* thisShape, gc::AllocSite* maybeAllocSite, + bool isBoundFunction) { bool isConstructing = flags.isConstructing(); if (mode_ == ICState::Mode::Specialized) { @@ -13700,9 +13699,14 @@ void CallIRGenerator::emitCallScriptedGuards(ObjOperandId calleeObjId, slot - newTarget->numFixedSlots()); } - // Call metaScriptedThisShape before emitting the call, so that Warp can - // use the shape to create the |this| object before transpiling the call. - writer.metaScriptedThisShape(thisShape); + // Call metaCreateThis before emitting the call, so that Warp can use the + // shape/site to create the |this| object before transpiling the call. + MOZ_ASSERT(maybeAllocSite); + uint32_t numFixedSlots = thisShape->numFixedSlots(); + uint32_t numDynamicSlots = NativeObject::calculateDynamicSlots(thisShape); + gc::AllocKind allocKind = gc::GetGCObjectKind(numFixedSlots); + writer.metaCreateThis(numFixedSlots, numDynamicSlots, allocKind, + thisShape, maybeAllocSite); } } else { // Guard that object is a scripted function @@ -13743,11 +13747,16 @@ AttachDecision CallIRGenerator::tryAttachCallScripted( return AttachDecision::NoAction; } - Rooted thisShape(cx_); + Rooted thisShape(cx_); + gc::AllocSite* maybeAllocSite = nullptr; if (isConstructing && isSpecialized) { Rooted newTarget(cx_, &newTarget_.toObject()); switch (getThisShapeForScripted(calleeFunc, newTarget, &thisShape)) { case ScriptedThisResult::PlainObjectShape: + maybeAllocSite = maybeCreateAllocSite(); + if (!maybeAllocSite) { + return AttachDecision::NoAction; + } break; case ScriptedThisResult::UninitializedThis: flags.setNeedsUninitializedThis(); @@ -13766,7 +13775,7 @@ AttachDecision CallIRGenerator::tryAttachCallScripted( ObjOperandId calleeObjId = writer.guardToObject(calleeValId); emitCallScriptedGuards(calleeObjId, calleeFunc, argcId, flags, thisShape, - /* isBoundFunction = */ false); + maybeAllocSite, /* isBoundFunction = */ false); writer.callScriptedFunction(calleeObjId, argcId, flags, ClampFixedArgc(argc_)); @@ -13975,7 +13984,8 @@ AttachDecision CallIRGenerator::tryAttachBoundFunction( } } - Rooted thisShape(cx_); + Rooted thisShape(cx_); + gc::AllocSite* maybeAllocSite = nullptr; if (isConstructing) { // Only optimize if newTarget == callee. This is the common case and ensures // we can always pass the bound function's target as newTarget. @@ -13987,6 +13997,10 @@ AttachDecision CallIRGenerator::tryAttachBoundFunction( Handle newTarget = target; switch (getThisShapeForScripted(target, newTarget, &thisShape)) { case ScriptedThisResult::PlainObjectShape: + maybeAllocSite = maybeCreateAllocSite(); + if (!maybeAllocSite) { + return AttachDecision::NoAction; + } break; case ScriptedThisResult::UninitializedThis: flags.setNeedsUninitializedThis(); @@ -14022,7 +14036,7 @@ AttachDecision CallIRGenerator::tryAttachBoundFunction( ObjOperandId targetId = writer.loadBoundFunctionTarget(calleeObjId); emitCallScriptedGuards(targetId, target, argcId, flags, thisShape, - /* isBoundFunction = */ true); + maybeAllocSite, /* isBoundFunction = */ true); writer.callBoundScriptedFunction(calleeObjId, targetId, argcId, flags, numBoundArgs); diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp index 174817173e07d..3a3825c4d9e93 100644 --- a/js/src/jit/CacheIRCompiler.cpp +++ b/js/src/jit/CacheIRCompiler.cpp @@ -10372,9 +10372,6 @@ bool CacheIRCompiler::emitCallIsSuspendedGeneratorResult(ValOperandId valId) { return true; } -// This op generates no code. It is consumed by the transpiler. -bool CacheIRCompiler::emitMetaScriptedThisShape(uint32_t) { return true; } - bool CacheIRCompiler::emitCallNativeGetElementResult(ObjOperandId objId, Int32OperandId indexId) { JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); diff --git a/js/src/jit/CacheIRGenerator.h b/js/src/jit/CacheIRGenerator.h index 08c3f2d369222..76e1276376470 100644 --- a/js/src/jit/CacheIRGenerator.h +++ b/js/src/jit/CacheIRGenerator.h @@ -604,9 +604,9 @@ class MOZ_RAII CallIRGenerator : public IRGenerator { friend class InlinableNativeIRGenerator; - ScriptedThisResult getThisShapeForScripted(HandleFunction calleeFunc, - Handle newTarget, - MutableHandle result); + ScriptedThisResult getThisShapeForScripted( + HandleFunction calleeFunc, Handle newTarget, + MutableHandle result); ObjOperandId emitFunCallOrApplyGuard(Int32OperandId argcId); ObjOperandId emitFunCallGuard(Int32OperandId argcId); @@ -616,7 +616,9 @@ class MOZ_RAII CallIRGenerator : public IRGenerator { void emitCallScriptedGuards(ObjOperandId calleeObjId, JSFunction* calleeFunc, Int32OperandId argcId, CallFlags flags, - Shape* thisShape, bool isBoundFunction); + SharedShape* thisShape, + gc::AllocSite* maybeAllocSite, + bool isBoundFunction); AttachDecision tryAttachFunCall(HandleFunction calleeFunc); AttachDecision tryAttachFunApply(HandleFunction calleeFunc); @@ -1138,7 +1140,7 @@ inline bool BytecodeGetOpCanHaveInlinableNative(JSOp op) { inline bool BytecodeOpCanHaveAllocSite(JSOp op) { return BytecodeCallOpCanHaveInlinableNative(op) || op == JSOp::NewArray || op == JSOp::NewObject || op == JSOp::NewInit || op == JSOp::CallIter || - op == JSOp::CallContentIter || op == JSOp::Lambda; + op == JSOp::CallContentIter || op == JSOp::Lambda || IsConstructOp(op); } class MOZ_RAII CloseIterIRGenerator : public IRGenerator { diff --git a/js/src/jit/CacheIROps.yaml b/js/src/jit/CacheIROps.yaml index b0d46164ea381..2c9ace661579b 100644 --- a/js/src/jit/CacheIROps.yaml +++ b/js/src/jit/CacheIROps.yaml @@ -2289,14 +2289,18 @@ nargsAndFlags: UInt32Imm #endif -# Meta ops generate no code, but contain data for the Warp Transpiler. -- name: MetaScriptedThisShape - shared: true +# This op generates no code itself, but contains data used by a subsequent +# Call(Scripted|Inlined|Bound)Function op. +- name: MetaCreateThis + shared: false transpile: true cost_estimate: 0 - custom_writer: true args: + numFixedSlots: UInt32Imm + numDynamicSlots: UInt32Imm + allocKind: AllocKindImm thisShape: ShapeField + site: AllocSiteField - name: BindFunctionResult shared: true diff --git a/js/src/jit/CacheIRWriter.h b/js/src/jit/CacheIRWriter.h index 849da4baee9c1..d0b9cc4c0645e 100644 --- a/js/src/jit/CacheIRWriter.h +++ b/js/src/jit/CacheIRWriter.h @@ -721,10 +721,6 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter { } #endif - void metaScriptedThisShape(Shape* thisShape) { - metaScriptedThisShape_(thisShape); - } - void guardMultipleShapes(ObjOperandId obj, ListObject* shapes) { MOZ_ASSERT(shapes->length() > 0); guardMultipleShapes_(obj, shapes); diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp index 8e4480d22a6d2..5d544d41f3215 100644 --- a/js/src/jit/IonAnalysis.cpp +++ b/js/src/jit/IonAnalysis.cpp @@ -3491,19 +3491,6 @@ static void AssertResumePointDominatedByOperands(MResumePoint* resume) { } #endif // DEBUG -static bool PrecedesInSameBlock(MInstruction* a, MInstruction* b) { - MOZ_ASSERT(a->block() == b->block()); - MBasicBlock* block = a->block(); - MInstructionIterator opIter = block->begin(a); - do { - ++opIter; - if (opIter == block->end()) { - return false; - } - } while (*opIter != b); - return true; -} - // Checks the basic GraphCoherency but also other conditions that // do not hold immediately (such as the fact that critical edges // are split, or conditions related to wasm semantics) @@ -3586,16 +3573,8 @@ void jit::AssertExtendedGraphCoherency(MIRGraph& graph, bool underValueNumberer, MInstruction* ins = *iter; for (size_t i = 0, e = ins->numOperands(); i < e; ++i) { MDefinition* op = ins->getOperand(i); - MBasicBlock* opBlock = op->block(); - MOZ_ASSERT(opBlock->dominates(*block), - "Instruction is not dominated by its operands"); - - // If the operand is an instruction in the same block, check - // that it comes first. - if (opBlock == *block && !op->isPhi()) { - MOZ_ASSERT(PrecedesInSameBlock(op->toInstruction(), ins), - "Operand in same block as instruction does not precede"); - } + MOZ_ASSERT(op->dominates(ins), + "instruction is not dominated by its operands"); } AssertIfResumableInstruction(ins); if (MResumePoint* resume = ins->resumePoint()) { @@ -4493,25 +4472,17 @@ static void TryOptimizeWasmCast(MDefinition* cast, MIRGraph& graph) { refUse->consumer() != cast) { MDefinition* otherCast = refUse->consumer()->toDefinition(); // And that ref.cast instruction dominates us... - if (otherCast->block()->dominates(cast->block())) { - // Like _really_ dominates us... - bool precedes = otherCast->block() == cast->block() - ? PrecedesInSameBlock(otherCast->toInstruction(), - cast->toInstruction()) - : true; - if (precedes) { - // And the type of the dominating ref.cast is <: the type of the - // current cast... - wasm::RefType dominatingDestType = - WasmRefTestOrCastDestType(otherCast); - wasm::RefType currentDestType = WasmRefTestOrCastDestType(cast); - if (wasm::RefType::isSubTypeOf(dominatingDestType, currentDestType)) { - // Then the cast is redundant because it is dominated by a tighter - // ref.cast. Discard the cast and fall back on the other. - cast->replaceAllUsesWith(otherCast); - cast->block()->discard(cast->toInstruction()); - return; - } + if (otherCast->dominates(cast)) { + // And the type of the dominating ref.cast is <: the type of the + // current cast... + wasm::RefType dominatingDestType = WasmRefTestOrCastDestType(otherCast); + wasm::RefType currentDestType = WasmRefTestOrCastDestType(cast); + if (wasm::RefType::isSubTypeOf(dominatingDestType, currentDestType)) { + // Then the cast is redundant because it is dominated by a tighter + // ref.cast. Discard the cast and fall back on the other. + cast->replaceAllUsesWith(otherCast); + cast->block()->discard(cast->toInstruction()); + return; } } } @@ -4581,27 +4552,19 @@ static void TryOptimizeWasmTest(MDefinition* refTest, MIRGraph& graph) { if (IsWasmRefCast(refUse->consumer()->toDefinition())) { MDefinition* refCast = refUse->consumer()->toDefinition(); // And that ref.cast instruction dominates us... - if (refCast->block()->dominates(refTest->block())) { - // Like _really_ dominates us... - bool precedes = refCast->block() == refTest->block() - ? PrecedesInSameBlock(refCast->toInstruction(), - refTest->toInstruction()) - : true; - if (precedes) { - // And the type of the dominating ref.cast is <: the type of the - // current ref.test... - wasm::RefType dominatingDestType = WasmRefTestOrCastDestType(refCast); - wasm::RefType currentDestType = WasmRefTestOrCastDestType(refTest); - if (wasm::RefType::isSubTypeOf(dominatingDestType, currentDestType)) { - // Then the ref.test is redundant because it is dominated by a - // tighter ref.cast. Replace with a constant 1. - auto* replacement = MConstant::NewInt32(graph.alloc(), 1); - refTest->block()->insertBefore(refTest->toInstruction(), - replacement); - refTest->replaceAllUsesWith(replacement); - refTest->block()->discard(refTest->toInstruction()); - return; - } + if (refCast->dominates(refTest)) { + // And the type of the dominating ref.cast is <: the type of the + // current ref.test... + wasm::RefType dominatingDestType = WasmRefTestOrCastDestType(refCast); + wasm::RefType currentDestType = WasmRefTestOrCastDestType(refTest); + if (wasm::RefType::isSubTypeOf(dominatingDestType, currentDestType)) { + // Then the ref.test is redundant because it is dominated by a + // tighter ref.cast. Replace with a constant 1. + auto* replacement = MConstant::NewInt32(graph.alloc(), 1); + refTest->block()->insertBefore(refTest->toInstruction(), replacement); + refTest->replaceAllUsesWith(replacement); + refTest->block()->discard(refTest->toInstruction()); + return; } } } @@ -5520,7 +5483,7 @@ bool jit::OptimizeIteratorIndices(const MIRGenerator* mir, MIRGraph& graph) { otherIter = FindObjectToIteratorUse(SkipIterObjectUnbox(receiver)); } - if (!otherIter || !otherIter->block()->dominates(ins->block())) { + if (!otherIter || !otherIter->dominates(ins)) { continue; } } diff --git a/js/src/jit/IonCacheIRCompiler.cpp b/js/src/jit/IonCacheIRCompiler.cpp index 97aa3b5780989..00b51dcfc57dd 100644 --- a/js/src/jit/IonCacheIRCompiler.cpp +++ b/js/src/jit/IonCacheIRCompiler.cpp @@ -2424,3 +2424,11 @@ bool IonCacheIRCompiler::emitRegExpHasCaptureGroupsResult( ObjOperandId regexpId, StringOperandId inputId) { MOZ_CRASH("Call ICs not used in ion"); } + +bool IonCacheIRCompiler::emitMetaCreateThis(uint32_t numFixedSlots, + uint32_t numDynamicSlots, + gc::AllocKind allocKind, + uint32_t thisShapeOffset, + uint32_t siteOffset) { + MOZ_CRASH("Call ICs not used in ion"); +} diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 9a912dfa1c0e8..84db6744b3cb8 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -618,6 +618,33 @@ bool MDefinition::congruentIfOperandsEqual(const MDefinition* ins) const { return true; } +bool MDefinition::dominates(const MDefinition* other) const { + if (block() != other->block()) { + return block()->dominates(other->block()); + } + + // Nothing in a block dominates a phi in that block. + if (other->isPhi()) { + return false; + } + + // Phis dominate all instructions in the block. + if (isPhi()) { + return true; + } + + // If both defs are instructions in the same block, check whether + // `this` precedes `other`. + MInstructionIterator opIter = block()->begin(toInstruction()); + do { + ++opIter; + if (opIter == block()->end()) { + return false; + } + } while (*opIter != other); + return true; +} + MDefinition* MDefinition::foldsTo(TempAllocator& alloc) { // In the default case, there are no constants to fold. return this; diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index e5210a7b4f8e1..731c2e265bdd4 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -960,6 +960,8 @@ class MDefinition : public MNode { return AliasType::MayAlias; } + bool dominates(const MDefinition* other) const; + virtual bool canRecoverOnBailout() const { return false; } }; diff --git a/js/src/jit/MIRGraph.h b/js/src/jit/MIRGraph.h index 32d591106c79e..d0dbf970ac8a9 100644 --- a/js/src/jit/MIRGraph.h +++ b/js/src/jit/MIRGraph.h @@ -448,7 +448,7 @@ class MBasicBlock : public TempObject, public InlineListNode { bool resumePointsEmpty() const { return resumePoints_.empty(); } #endif MInstructionIterator begin() { return instructions_.begin(); } - MInstructionIterator begin(MInstruction* at) { + MInstructionIterator begin(const MInstruction* at) { MOZ_ASSERT(at->block() == this); return instructions_.begin(at); } diff --git a/js/src/jit/VMFunctionList-inl.h b/js/src/jit/VMFunctionList-inl.h index ba546c38a6aa1..6109176f20e0b 100644 --- a/js/src/jit/VMFunctionList-inl.h +++ b/js/src/jit/VMFunctionList-inl.h @@ -140,6 +140,7 @@ namespace jit { IF_EXPLICIT_RESOURCE_MANAGEMENT( \ _(CreateSuppressedError, js::CreateSuppressedError)) \ _(CreateThisFromIC, js::jit::CreateThisFromIC) \ + _(CreateThisFromICWithAllocSite, js::jit::CreateThisFromICWithAllocSite) \ _(CreateThisFromIon, js::jit::CreateThisFromIon) \ _(DebugAfterYield, js::jit::DebugAfterYield) \ _(DebugEpilogueOnBaselineReturn, js::jit::DebugEpilogueOnBaselineReturn) \ diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index 4e0563f9c3fff..29425ebe5b3a9 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -919,6 +919,34 @@ bool CreateThisFromIC(JSContext* cx, HandleObject callee, return true; } +bool CreateThisFromICWithAllocSite(JSContext* cx, HandleObject callee, + HandleObject newTarget, gc::AllocSite* site, + MutableHandleValue rval) { + HandleFunction fun = callee.as(); + MOZ_ASSERT(fun->isInterpreted()); + MOZ_ASSERT(fun->isConstructor()); + MOZ_ASSERT(cx->realm() == fun->realm(), + "Realm switching happens before creating this"); + MOZ_ASSERT(!fun->constructorNeedsUninitializedThis()); + + Rooted shape(cx, ThisShapeForFunction(cx, fun, newTarget)); + if (!shape) { + return false; + } + + gc::AllocKind allocKind = gc::GetGCObjectKind(shape->numFixedSlots()); + gc::Heap initialHeap = site->initialHeap(); + PlainObject* obj = NativeObject::create( + cx, allocKind, initialHeap, shape, site); + if (!obj) { + return false; + } + + MOZ_ASSERT(fun->realm() == obj->nonCCWRealm()); + rval.setObject(*obj); + return true; +} + bool CreateThisFromIon(JSContext* cx, HandleObject callee, HandleObject newTarget, MutableHandleValue rval) { // Return JS_IS_CONSTRUCTING for cases not supported by the inline call path. diff --git a/js/src/jit/VMFunctions.h b/js/src/jit/VMFunctions.h index 68efa8a4608a5..4dc888fcda407 100644 --- a/js/src/jit/VMFunctions.h +++ b/js/src/jit/VMFunctions.h @@ -47,6 +47,7 @@ class MegamorphicCacheEntry; namespace gc { +class AllocSite; class Cell; } // namespace gc @@ -411,6 +412,11 @@ bool OperatorIn(JSContext* cx, HandleValue key, HandleObject obj, bool* out); [[nodiscard]] bool CreateThisFromIC(JSContext* cx, HandleObject callee, HandleObject newTarget, MutableHandleValue rval); +[[nodiscard]] bool CreateThisFromICWithAllocSite(JSContext* cx, + HandleObject callee, + HandleObject newTarget, + gc::AllocSite* site, + MutableHandleValue rval); [[nodiscard]] bool CreateThisFromIon(JSContext* cx, HandleObject callee, HandleObject newTarget, MutableHandleValue rval); diff --git a/js/src/jit/WarpCacheIRTranspiler.cpp b/js/src/jit/WarpCacheIRTranspiler.cpp index 199ca10cc1911..5630522426c56 100644 --- a/js/src/jit/WarpCacheIRTranspiler.cpp +++ b/js/src/jit/WarpCacheIRTranspiler.cpp @@ -6283,7 +6283,7 @@ bool WarpCacheIRTranspiler::maybeCreateThis(MDefinition* callee, MOZ_ASSERT(kind == CallKind::Scripted); if (thisArg->isNewPlainObject()) { - // We have already updated |this| based on MetaScriptedThisShape. We do + // We have already updated |this| based on MetaCreateThis. We do // not need to generate a check. return false; } @@ -7057,26 +7057,25 @@ bool WarpCacheIRTranspiler::emitCallNativeSetter(ObjOperandId receiverId, nargsAndFlagsOffset); } -bool WarpCacheIRTranspiler::emitMetaScriptedThisShape( - uint32_t thisShapeOffset) { +bool WarpCacheIRTranspiler::emitMetaCreateThis(uint32_t numFixedSlots, + uint32_t numDynamicSlots, + gc::AllocKind allocKind, + uint32_t thisShapeOffset, + uint32_t siteOffset) { SharedShape* shape = &shapeStubField(thisShapeOffset)->asShared(); MOZ_ASSERT(shape->getObjectClass() == &PlainObject::class_); MConstant* shapeConst = MConstant::NewShape(alloc(), shape); add(shapeConst); - // TODO: support pre-tenuring. - gc::Heap heap = gc::Heap::Default; + gc::Heap heap = allocSiteInitialHeapField(siteOffset); - uint32_t numFixedSlots = shape->numFixedSlots(); - uint32_t numDynamicSlots = NativeObject::calculateDynamicSlots(shape); - gc::AllocKind kind = gc::GetGCObjectKind(numFixedSlots); MOZ_ASSERT(gc::GetObjectFinalizeKind(&PlainObject::class_) == gc::FinalizeKind::None); - MOZ_ASSERT(!IsFinalizedKind(kind)); + MOZ_ASSERT(!IsFinalizedKind(allocKind)); auto* createThis = MNewPlainObject::New(alloc(), shapeConst, numFixedSlots, - numDynamicSlots, kind, heap); + numDynamicSlots, allocKind, heap); add(createThis); callInfo_->thisArg()->setImplicitlyUsedUnchecked(); diff --git a/js/src/vm/PortableBaselineInterpret.cpp b/js/src/vm/PortableBaselineInterpret.cpp index 8e881c1bc38f6..08367e2a753ee 100644 --- a/js/src/vm/PortableBaselineInterpret.cpp +++ b/js/src/vm/PortableBaselineInterpret.cpp @@ -666,7 +666,7 @@ uint64_t ICInterpretOps(uint64_t arg0, uint64_t arg1, ICStub* stub, DECLARE_CACHEOP_CASE(CallInt32ToString); DECLARE_CACHEOP_CASE(CallScriptedFunction); DECLARE_CACHEOP_CASE(CallNativeFunction); - DECLARE_CACHEOP_CASE(MetaScriptedThisShape); + DECLARE_CACHEOP_CASE(MetaCreateThis); DECLARE_CACHEOP_CASE(LoadFixedSlotResult); DECLARE_CACHEOP_CASE(LoadDynamicSlotResult); DECLARE_CACHEOP_CASE(LoadDenseElementResult); @@ -2611,10 +2611,10 @@ uint64_t ICInterpretOps(uint64_t arg0, uint64_t arg1, ICStub* stub, DISPATCH_CACHEOP(); } - CACHEOP_CASE(MetaScriptedThisShape) { + CACHEOP_CASE(MetaCreateThis) { // This op is only metadata for the Warp Transpiler and should be // ignored. - cacheIRReader.argsForMetaScriptedThisShape(); + cacheIRReader.argsForMetaCreateThis(); PREDICT_NEXT(CallScriptedFunction); DISPATCH_CACHEOP(); } diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index 829da83b0a1d1..b72d07ef415e6 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -6914,7 +6914,10 @@ void PresShell::RecordPointerLocation(WidgetGUIEvent* aEvent) { // session ends, we want to synthesize ePointerMove at the dropped point. // Therefore, we should update the last state of the pointer when we start // handling a drag event. - if (aEvent->mClass == eDragEventClass) { + // We also need to store the pointer location for eMouseEnterIntoWidget, + // so that the pointer boundary event can be generated earlier. + if (aEvent->mMessage == eMouseEnterIntoWidget || + aEvent->mClass == eDragEventClass) { StorePointerLocation(mouseEvent); } break; diff --git a/layout/xul/nsSplitterFrame.cpp b/layout/xul/nsSplitterFrame.cpp index 84c7d33a80f90..b034a8184e2f1 100644 --- a/layout/xul/nsSplitterFrame.cpp +++ b/layout/xul/nsSplitterFrame.cpp @@ -24,6 +24,8 @@ #include "mozilla/dom/Document.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/Event.h" +#include "mozilla/dom/KeyboardEvent.h" +#include "mozilla/dom/KeyboardEventBinding.h" #include "mozilla/dom/MouseEvent.h" #include "nsContainerFrame.h" #include "nsContentUtils.h" @@ -114,6 +116,7 @@ class nsSplitterFrameInner final : public nsIDOMEventListener { nsresult MouseDown(Event* aMouseEvent); nsresult MouseUp(Event* aMouseEvent); nsresult MouseMove(Event* aMouseEvent); + nsresult KeyDown(Event* aKeyEvent); void MouseDrag(nsPresContext* aPresContext, WidgetGUIEvent* aEvent); void MouseUp(nsPresContext* aPresContext, WidgetGUIEvent* aEvent); @@ -145,6 +148,10 @@ class nsSplitterFrameInner final : public nsIDOMEventListener { void EnsureOrient(); void SetPreferredSize(nsIFrame* aChildBox, bool aIsHorizontal, nscoord aSize); + // Collects child information for resizing. Returns false if the splitter + // is at a boundary or there are no valid children to resize. + bool CollectChildInfos(); + nsSplitterFrame* mOuter; bool mDidDrag = false; nscoord mDragStart = 0; @@ -463,6 +470,7 @@ void nsSplitterFrameInner::AddListener() { mOuter->GetContent()->AddEventListener(u"mousedown"_ns, this, false, false); mOuter->GetContent()->AddEventListener(u"mousemove"_ns, this, false, false); mOuter->GetContent()->AddEventListener(u"mouseout"_ns, this, false, false); + mOuter->GetContent()->AddEventListener(u"keydown"_ns, this, false, false); } void nsSplitterFrameInner::RemoveListener() { @@ -471,6 +479,7 @@ void nsSplitterFrameInner::RemoveListener() { mOuter->GetContent()->RemoveEventListener(u"mousedown"_ns, this, false); mOuter->GetContent()->RemoveEventListener(u"mousemove"_ns, this, false); mOuter->GetContent()->RemoveEventListener(u"mouseout"_ns, this, false); + mOuter->GetContent()->RemoveEventListener(u"keydown"_ns, this, false); } nsresult nsSplitterFrameInner::HandleEvent(dom::Event* aEvent) { @@ -486,6 +495,9 @@ nsresult nsSplitterFrameInner::HandleEvent(dom::Event* aEvent) { eventType.EqualsLiteral("mouseout")) { return MouseMove(aEvent); } + if (eventType.EqualsLiteral("keydown")) { + return KeyDown(aEvent); + } MOZ_ASSERT_UNREACHABLE("Unexpected eventType"); return NS_OK; @@ -526,31 +538,11 @@ static void ApplyMargin(nsSize& aSize, const nsMargin& aMargin) { } } -nsresult nsSplitterFrameInner::MouseDown(Event* aMouseEvent) { - NS_ENSURE_TRUE(mOuter, NS_OK); - dom::MouseEvent* mouseEvent = aMouseEvent->AsMouseEvent(); - if (!mouseEvent) { - return NS_OK; - } - - // only if left button - if (mouseEvent->Button() != 0) { - return NS_OK; - } - - if (SplitterElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, - nsGkAtoms::_true, eCaseMatters)) { - return NS_OK; - } - - mParentBox = GetValidParentBox(mOuter); +bool nsSplitterFrameInner::CollectChildInfos() { if (!mParentBox) { - return NS_OK; + return false; } - // get our index - mDidDrag = false; - EnsureOrient(); const bool isHorizontal = !mOuter->IsHorizontal(); @@ -576,11 +568,11 @@ nsresult nsSplitterFrameInner::MouseDown(Event* aMouseEvent) { foundOuter = true; if (!count) { // We're at the beginning, nothing to do. - return NS_OK; + return false; } if (count == childCount - 1 && resizeAfter != ResizeType::Grow) { // If it's the last index then we need to allow for resizeafter="grow" - return NS_OK; + return false; } } count++; @@ -674,11 +666,9 @@ nsresult nsSplitterFrameInner::MouseDown(Event* aMouseEvent) { } if (!foundOuter) { - return NS_OK; + return false; } - mPressed = true; - const bool reverseDirection = [&] { MOZ_ASSERT(mParentBox->IsFlexContainerFrame()); const FlexboxAxisInfo info(mParentBox); @@ -713,6 +703,41 @@ nsresult nsSplitterFrameInner::MouseDown(Event* aMouseEvent) { mChildInfosAfter.Reverse(); } + return true; +} + +nsresult nsSplitterFrameInner::MouseDown(Event* aMouseEvent) { + NS_ENSURE_TRUE(mOuter, NS_OK); + dom::MouseEvent* mouseEvent = aMouseEvent->AsMouseEvent(); + if (!mouseEvent) { + return NS_OK; + } + + // only if left button + if (mouseEvent->Button() != 0) { + return NS_OK; + } + + if (SplitterElement()->GetBoolAttr(nsGkAtoms::disabled)) { + return NS_OK; + } + + mParentBox = GetValidParentBox(mOuter); + if (!mParentBox) { + return NS_OK; + } + + // get our index + mDidDrag = false; + + // Collect child information for resizing + if (!CollectChildInfos()) { + return NS_OK; + } + + mPressed = true; + + const bool isHorizontal = !mOuter->IsHorizontal(); int32_t c; nsPoint pt = nsLayoutUtils::GetDOMEventCoordinatesRelativeTo(mouseEvent, mParentBox); @@ -754,6 +779,101 @@ nsresult nsSplitterFrameInner::MouseMove(Event* aMouseEvent) { return NS_OK; } +nsresult nsSplitterFrameInner::KeyDown(Event* aKeyEvent) { + NS_ENSURE_TRUE(mOuter, NS_OK); + + dom::KeyboardEvent* keyEvent = aKeyEvent->AsKeyboardEvent(); + if (!keyEvent) { + return NS_OK; + } + + // Check if splitter is disabled + if (SplitterElement()->GetBoolAttr(nsGkAtoms::disabled)) { + return NS_OK; + } + + mParentBox = GetValidParentBox(mOuter); + if (!mParentBox) { + return NS_OK; + } + + uint32_t keyCode = keyEvent->KeyCode(); + + // Determine orientation to map arrow keys correctly + EnsureOrient(); + const bool isHorizontal = !mOuter->IsHorizontal(); + + // Use 5px movement per keypress + const nscoord kKeyboardDelta = nsPresContext::CSSPixelsToAppUnits(5); + nscoord delta = 0; + + switch (keyCode) { + case dom::KeyboardEvent_Binding::DOM_VK_LEFT: + if (isHorizontal) { + delta = -kKeyboardDelta; + } + break; + + case dom::KeyboardEvent_Binding::DOM_VK_RIGHT: + if (isHorizontal) { + delta = kKeyboardDelta; + } + break; + + case dom::KeyboardEvent_Binding::DOM_VK_UP: + if (!isHorizontal) { + delta = -kKeyboardDelta; + } + break; + + case dom::KeyboardEvent_Binding::DOM_VK_DOWN: + if (!isHorizontal) { + delta = kKeyboardDelta; + } + break; + + default: + // Other keys - don't consume + return NS_OK; + } + + if (delta == 0) { + return NS_OK; + } + + keyEvent->PreventDefault(); + + // Collect child information for resizing + if (!CollectChildInfos()) { + return NS_OK; + } + + // Initialize changed values + for (auto& info : mChildInfosBefore) { + info.changed = info.current; + } + + for (auto& info : mChildInfosAfter) { + info.changed = info.current; + } + + // Apply the delta to resize children + ResizeChildTo(delta); + + AdjustChildren(mOuter->PresContext()); + + mChildInfosBefore.Clear(); + mChildInfosAfter.Clear(); + + // Fire command event to notify of change + RefPtr element = nsXULElement::FromNode(mOuter->GetContent()); + if (element) { + element->DoCommand(); + } + + return NS_OK; +} + bool nsSplitterFrameInner::SupportsCollapseDirection( nsSplitterFrameInner::CollapseDirection aDirection) { static Element::AttrValuesArray strings[] = { diff --git a/layout/xul/test/test_splitter.xhtml b/layout/xul/test/test_splitter.xhtml index 32c4118c8c19a..001c89aaaf7ca 100644 --- a/layout/xul/test/test_splitter.xhtml +++ b/layout/xul/test/test_splitter.xhtml @@ -39,6 +39,32 @@ XUL collapsing tests ); } + async function arrowKeyNudgeSplitter(direction) { + const splitterRect = splitter.getBoundingClientRect(); + const leftPanelRect = splitter.getBoundingClientRect(); + let keyToPress; + switch (direction) { + case "up": + keyToPress = "KEY_ArrowUp"; + break; + case "down": + keyToPress = "KEY_ArrowDown"; + break; + case "left": + keyToPress = "KEY_ArrowLeft"; + break; + case "right": + keyToPress = "KEY_ArrowRight"; + break; + } + Services.focus.setFocus(splitter, Services.focus.FLAG_BYKEY); + let promisedEvent = promiseCommandEvent(splitter); + info("sending key: " + keyToPress); + synthesizeKey(keyToPress); + info("Waiting for command event"); + await promisedEvent; + } + function shouldBeCollapsed(where) { is(splitter.getAttribute("state"), "collapsed", "The splitter should be collapsed"); is(splitter.getAttribute("substate"), where, "The splitter should be collapsed " + where); @@ -93,9 +119,63 @@ XUL collapsing tests await runPass(rtl, true, true); } + function promiseCommandEvent(target) { + return new Promise(res => { + target.addEventListener("command", res, { once: true }); + }); + } + + async function runHorizontalSplitterKeyboardTests(splitterId) { + info(`Running keyboard tests for ${splitterId}`); + splitter = document.getElementById(splitterId); + setActiveBox(splitter.parentNode); + + const leftPanel = splitter.previousElementSibling; + const rightPanel = splitter.nextElementSibling; + const leftRect = leftPanel.getBoundingClientRect(); + const rightRect = rightPanel.getBoundingClientRect(); + let splitterRect = splitter.getBoundingClientRect(); + + await arrowKeyNudgeSplitter("left"); + ok(splitter.getBoundingClientRect().x < splitterRect.x, "The splitter moved to the left"); + ok(leftPanel.getBoundingClientRect().width < leftRect.width, "The left panel got narrower"); + ok(rightPanel.getBoundingClientRect().width > rightRect.width, "The right panel got wider"); + + await arrowKeyNudgeSplitter("right"); + await arrowKeyNudgeSplitter("right"); + ok(splitter.getBoundingClientRect().x > splitterRect.x, "The splitter moved to the right"); + ok(leftPanel.getBoundingClientRect().width > leftRect.width, "The left panel got wider"); + ok(rightPanel.getBoundingClientRect().width < rightRect.width, "The right panel got narrower"); + } + + async function runVerticalSplitterKeyboardTests(splitterId) { + info(`Running keyboard tests for ${splitterId}`); + splitter = document.getElementById(splitterId); + setActiveBox(splitter.parentNode); + + const topPanel = splitter.previousElementSibling; + const bottomPanel = splitter.nextElementSibling; + const topRect = topPanel.getBoundingClientRect(); + const bottomRect = bottomPanel.getBoundingClientRect(); + let splitterRect = splitter.getBoundingClientRect(); + + await arrowKeyNudgeSplitter("down"); + ok(splitter.getBoundingClientRect().y > splitterRect.y, "The splitter moved down"); + ok(topPanel.getBoundingClientRect().height > topRect.height, "The top panel got taller"); + ok(bottomPanel.getBoundingClientRect().height < bottomRect.height, "The bottom panel got shorter"); + + await arrowKeyNudgeSplitter("up"); + await arrowKeyNudgeSplitter("up"); + ok(splitter.getBoundingClientRect().y < splitterRect.y, "The splitter moved up"); + ok(topPanel.getBoundingClientRect().height < topRect.height, "The top panel got shorter"); + ok(bottomPanel.getBoundingClientRect().height > bottomRect.height, "The bottom panel got taller"); + } + async function runAllTests() { await runTests(false, "ltr-splitter"); await runTests(true, "rtl-splitter"); + await runHorizontalSplitterKeyboardTests("focusable-splitter"); + await runVerticalSplitterKeyboardTests("focusable-splitter-vert"); SimpleTest.finish(); } @@ -103,7 +183,7 @@ XUL collapsing tests ]]> - + @@ -114,4 +194,16 @@ XUL collapsing tests + + + + + + + + + + + + diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-be/strings.xml index da8cb9caa1aa4..69bb7186e046a 100644 --- a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-be/strings.xml +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-be/strings.xml @@ -9,4 +9,6 @@ Прыняць і рэдагаваць прапанову + + Выдаліць прапанову diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-dsb/strings.xml index 30c7e474e509e..379d9bdd18f50 100644 --- a/mobile/android/android-components/components/feature/addons/src/main/res/values-dsb/strings.xml +++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-dsb/strings.xml @@ -265,7 +265,7 @@ Dopórucone - Hyšće njepódprěte + Hyšći njepódprěte Njejo hyšći k dispoziciji diff --git a/mobile/android/android-components/components/feature/prompts/src/main/res/values-km/strings.xml b/mobile/android/android-components/components/feature/prompts/src/main/res/values-km/strings.xml index 7fdf4e069f394..7ac505540cfdd 100644 --- a/mobile/android/android-components/components/feature/prompts/src/main/res/values-km/strings.xml +++ b/mobile/android/android-components/components/feature/prompts/src/main/res/values-km/strings.xml @@ -115,6 +115,12 @@ បោះបង់ បោះបង់ + + រូបភាព​គណនី បោះបង់ diff --git a/mobile/android/config/mozconfigs/android-aarch64/debug-searchfox b/mobile/android/config/mozconfigs/android-aarch64/debug-searchfox index 17164d71cb497..7b5349953caee 100644 --- a/mobile/android/config/mozconfigs/android-aarch64/debug-searchfox +++ b/mobile/android/config/mozconfigs/android-aarch64/debug-searchfox @@ -11,7 +11,6 @@ ac_add_options --with-branding=mobile/android/branding/nightly ac_add_options --enable-mozsearch-plugin ac_add_options --without-mozilla-api-keyfile -ac_add_options --without-google-location-service-api-keyfile ac_add_options --without-google-safebrowsing-api-keyfile . "$topsrcdir/mobile/android/config/mozconfigs/common.override" diff --git a/mobile/android/config/mozconfigs/android-arm-gradle-dependencies/base b/mobile/android/config/mozconfigs/android-arm-gradle-dependencies/base index 6b5de013e0dbc..65989988e64d2 100644 --- a/mobile/android/config/mozconfigs/android-arm-gradle-dependencies/base +++ b/mobile/android/config/mozconfigs/android-arm-gradle-dependencies/base @@ -41,7 +41,6 @@ export MOZILLA_OFFICIAL=1 # Disable Keyfile Loading (and checks) since dependency fetching doesn't need these keys. # This overrides the settings in the common android mozconfig ac_add_options --without-mozilla-api-keyfile -ac_add_options --without-google-location-service-api-keyfile ac_add_options --without-google-safebrowsing-api-keyfile . "$topsrcdir/mobile/android/config/mozconfigs/common.override" diff --git a/mobile/android/config/mozconfigs/android-arm/nightly-android-lints b/mobile/android/config/mozconfigs/android-arm/nightly-android-lints index 094ca33ebd856..54f7a4a0518b3 100644 --- a/mobile/android/config/mozconfigs/android-arm/nightly-android-lints +++ b/mobile/android/config/mozconfigs/android-arm/nightly-android-lints @@ -28,7 +28,6 @@ export MOZILLA_OFFICIAL=1 # Disable Keyfile Loading (and checks) since. # This overrides the settings in the common android mozconfig ac_add_options --without-mozilla-api-keyfile -ac_add_options --without-google-location-service-api-keyfile ac_add_options --without-google-safebrowsing-api-keyfile . "$topsrcdir/mobile/android/config/mozconfigs/common.override" diff --git a/mobile/android/config/mozconfigs/android-arm/nightly-android-lints-lite b/mobile/android/config/mozconfigs/android-arm/nightly-android-lints-lite index bb0410e07749c..9af56c3e83668 100644 --- a/mobile/android/config/mozconfigs/android-arm/nightly-android-lints-lite +++ b/mobile/android/config/mozconfigs/android-arm/nightly-android-lints-lite @@ -29,7 +29,6 @@ export MOZILLA_OFFICIAL=1 # Disable Keyfile Loading (and checks) since. # This overrides the settings in the common android mozconfig ac_add_options --without-mozilla-api-keyfile -ac_add_options --without-google-location-service-api-keyfile ac_add_options --without-google-safebrowsing-api-keyfile . "$topsrcdir/mobile/android/config/mozconfigs/common.override" diff --git a/mobile/android/config/mozconfigs/common b/mobile/android/config/mozconfigs/common index 6c54d45e485e9..c002fac42d0f3 100644 --- a/mobile/android/config/mozconfigs/common +++ b/mobile/android/config/mozconfigs/common @@ -23,7 +23,6 @@ fi ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --with-google-safebrowsing-api-keyfile=/builds/sb-gapi.data -ac_add_options --with-google-location-service-api-keyfile=/builds/gls-gapi.data ac_add_options --with-mozilla-api-keyfile=/builds/mozilla-fennec-geoloc-api.key # Package js shell. diff --git a/mobile/android/fenix/app/nimbus.fml.yaml b/mobile/android/fenix/app/nimbus.fml.yaml index 884472a239773..6ecdacec14b46 100644 --- a/mobile/android/fenix/app/nimbus.fml.yaml +++ b/mobile/android/fenix/app/nimbus.fml.yaml @@ -697,6 +697,14 @@ features: type: Boolean default: false + homepage-opening-screen-default: + description: Configure the default option for the homepage opening screen. + variables: + default-option: + description: The default option for the homepage opening screen. + type: OpeningScreenOption + default: homepage-four-hours + unified-trust-panel: description: Enables the unified trust panel. variables: @@ -1145,3 +1153,16 @@ types: Uses the following copy: - Title: "A note from Firefox" - Learn more: "You can learn more here." + + OpeningScreenOption: + description: The types of different experiment branches for the opening screen. + variants: + homepage: + description: + Uses the homepage as the opening screen. + last-tab: + description: + Uses the last tab as the opening screen. + homepage-four-hours: + description: + Uses the homepage after four hours of inactivity as the opening screen. diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/HomeSettingsFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/HomeSettingsFragment.kt index 579db37cf75a4..5112ef4aa802b 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/HomeSettingsFragment.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/HomeSettingsFragment.kt @@ -132,13 +132,6 @@ class HomeSettingsFragment : PreferenceFragmentCompat() { onPreferenceChangeListener = createMetricPreferenceChangeListener("recently_visited") } - val openingScreenRadioHomepage = - requirePreference(R.string.pref_key_start_on_home_always) - val openingScreenLastTab = - requirePreference(R.string.pref_key_start_on_home_never) - val openingScreenAfterFourHours = - requirePreference(R.string.pref_key_start_on_home_after_four_hours) - requirePreference(R.string.pref_key_wallpapers).apply { setOnPreferenceClickListener { view?.findNavController()?.navigateWithBreadcrumb( @@ -151,11 +144,7 @@ class HomeSettingsFragment : PreferenceFragmentCompat() { } } - addToRadioGroup( - openingScreenRadioHomepage, - openingScreenLastTab, - openingScreenAfterFourHours, - ) + setupOpeningScreenPreferences() } private fun createMetricPreferenceChangeListener(metricKey: String): Preference.OnPreferenceChangeListener { @@ -174,4 +163,25 @@ class HomeSettingsFragment : PreferenceFragmentCompat() { true } } + + private fun setupOpeningScreenPreferences() { + val openingScreenRadioHomepage = + requirePreference(R.string.pref_key_start_on_home_always).apply { + setDefaultValue(fenixSettings.alwaysOpenTheHomepageWhenOpeningTheApp) + } + val openingScreenLastTab = + requirePreference(R.string.pref_key_start_on_home_never).apply { + setDefaultValue(fenixSettings.alwaysOpenTheLastTabWhenOpeningTheApp) + } + val openingScreenAfterFourHours = + requirePreference(R.string.pref_key_start_on_home_after_four_hours).apply { + setDefaultValue(fenixSettings.openHomepageAfterFourHoursOfInactivity) + } + + addToRadioGroup( + openingScreenRadioHomepage, + openingScreenLastTab, + openingScreenAfterFourHours, + ) + } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/RadioButtonPreference.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/RadioButtonPreference.kt index 84f5b8ea94f41..dc08ed1fccb87 100644 --- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/RadioButtonPreference.kt +++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/RadioButtonPreference.kt @@ -60,6 +60,18 @@ open class RadioButtonPreference @JvmOverloads constructor( } } + /** + * Sets the default checked state used when no persisted value exists for this key. + * + * This only updates the fallback used by `preferences.getBoolean(key, defaultValue)`. + * It does not persist a value or notify listeners. + * + * @param defaultValue `true` to make the radio button checked by default, `false` otherwise. + */ + fun setDefaultValue(defaultValue: Boolean) { + this.defaultValue = defaultValue + } + override fun addToRadioGroup(radioButton: GroupableRadioButton) { radioGroups.add(radioButton) } 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 b820ed7126c3e..49297d0044a70 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 @@ -63,6 +63,7 @@ import org.mozilla.fenix.nimbus.CookieBannersSection import org.mozilla.fenix.nimbus.DefaultBrowserPrompt import org.mozilla.fenix.nimbus.FxNimbus import org.mozilla.fenix.nimbus.HomeScreenSection +import org.mozilla.fenix.nimbus.OpeningScreenOption import org.mozilla.fenix.settings.PhoneFeature import org.mozilla.fenix.settings.ShortcutType import org.mozilla.fenix.settings.deletebrowsingdata.DeleteBrowsingDataOnQuitType @@ -851,13 +852,16 @@ class Settings( default = 0L, ) + private val openingScreenDefault: OpeningScreenOption + get() = FxNimbus.features.homepageOpeningScreenDefault.value().defaultOption + /** * Indicates if the user has selected the option to start on the home screen after * four hours of inactivity. */ var openHomepageAfterFourHoursOfInactivity by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_start_on_home_after_four_hours), - default = true, + default = { openingScreenDefault == OpeningScreenOption.HOMEPAGE_FOUR_HOURS }, ) /** @@ -865,7 +869,7 @@ class Settings( */ var alwaysOpenTheHomepageWhenOpeningTheApp by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_start_on_home_always), - default = false, + default = { openingScreenDefault == OpeningScreenOption.HOMEPAGE }, ) /** @@ -874,7 +878,7 @@ class Settings( */ var alwaysOpenTheLastTabWhenOpeningTheApp by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_start_on_home_never), - default = false, + default = { openingScreenDefault == OpeningScreenOption.LAST_TAB }, ) /** diff --git a/mobile/android/fenix/app/src/main/res/values-be/strings.xml b/mobile/android/fenix/app/src/main/res/values-be/strings.xml index 867448b712dc1..e7150c3fe4cd1 100644 --- a/mobile/android/fenix/app/src/main/res/values-be/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-be/strings.xml @@ -547,6 +547,8 @@ Firefox клапоціцца аб вашай прыватнасці. Даведайцеся больш у нашых %1$s. Паведамленне аб прыватнасці + + Кіраваць наладамі Зрабіць прадвызначаным браўзерам @@ -1436,6 +1438,12 @@ Выдаліць Скасаваць + + Пераназваць файл + + Імя + Захаваць + Скасаваць У працэсе Аднавіць картку + + %s збіўся. Адправіць справаздачу? Аўтаматычна адпраўляць справаздачы аб збоях @@ -2047,6 +2057,14 @@ Строгая Мацнейшая ахова ад сачэння і лепшая хуткадзейнасць, але некаторыя сайты могуць не працаваць належным чынам. + + Падрабязней + + Вы ўпэўнены, што хочаце адключыць выпраўленні? Што блакуецца строгай аховай ад сачэння @@ -2949,6 +2967,10 @@ Сцягнуць і перакласці Скасаваць + + Ваша злучэнне не бяспечнае. + + Вы адключылі ахову Дазволы @@ -3053,6 +3075,8 @@ The title of the Addresses feature in the Debug Drawer. --> Адрасы + + Кіраваць адрасамі Выдаліць усе крэдытныя карты + + Інструменты адладкі Glean + + Пацягніце зверху і\u00a0выкарыстайце жэст \"Назад\", каб выйсці + + Пацягніце зверху і\u00a0націсніце \"Назад\", каб выйсці ٱووردن برنومه و بلگه ٱسلی - دسگایل Xiaomi گاشڌ موجوزا ازافی سی ٱووردن ر نهنگا و بلگه ٱسلی بخون. سامووا خوتووݩ ن واجۊری کۊنین. + دسگایل Xiaomi گاشڌ موجوزا ازافی سی ٱووردن ره نهنگا و بلگه ٱسلی بخون. سامووا خوتووݩ ن واجۊری کۊنین. هوم گوم کردن دووارته @@ -646,6 +646,8 @@ دؽوۉداری سامووا وا رڌجۊرا موزاهم خوڌافزی کۊنین + + گۊشیڌن پوی لینگا خوتووݩ وا هریم سیخومی منی ایما داده یل ایسا ن زفت اکۊنیم وو و جۊر خوتکار جلاو جاسۊسی شرکتا ز کلیک کردنا ایسا ن اگیریم. @@ -804,7 +806,7 @@ ٱر هیشتین، مجال گۊشیڌن چند تا برنومه، بلگه یل سیخومی ن ترین بنیرین - ٱووردن ر نهنگ گشت سیخومی + ٱووردن ره نهنگ گشت سیخومی هالت تینا-Https @@ -886,9 +888,9 @@ نشووݩ داڌن نوار بلگه - ر نهنگ نوار ٱوزار + ره نهنگ نوار ٱوزار - پسند ی ر نهنگ + پسند ی ره نهنگ اشاره یل @@ -924,7 +926,7 @@ پیتینیڌن نشووکا - نشووݩ داڌن ر نهنگا + نشووݩ داڌن ره نهنگا پیتینیڌن من بلگه یل هوم گوم وابیڌه @@ -1052,7 +1054,7 @@ کاقز دیواری یل - ر نهنگا هؽزگرووݩ + ره نهنگا هؽزگرووݩ گاشڌ برنومه بسته بۊ. سی گۊشیڌن دووارته %1$s، ری آیکون برقشت نۊ خوتووݩ بزنین. - آلشت آیکون، پوی وبگه یل وو ر نهنگایی ک من بلگه هووه ای خوت زفت کردی پاک اکونه.\n\nگاشڌ %1$s بسته بۊ. سی گۊشیڌن دووارته ری آیکون نۊ خوت بزݩ. + آلشت آیکون، پوی وبگه یل وو ره نهنگایی ک من بلگه هووه ای خوت زفت کردی پاک اکونه.\n\nگاشڌ %1$s بسته بۊ. سی گۊشیڌن دووارته ری آیکون نۊ خوت بزݩ. آلشت آیکون لقو - ورۊ رسۊوی آیکون برنومه مووفق نبی. ر نهنگایی ک هڌسووݩ ن پاک کۊنین وو ز نۊ امتهووݩ کۊنین. + ورۊ رسۊوی آیکون برنومه مووفق نبی. ره نهنگایی ک هڌسووݩ ن پاک کۊنین وو ز نۊ امتهووݩ کۊنین. نشووکا من «%s» زفت وابین - و ر نهنگا ٱوورده وابی! + و ره نهنگا ٱوورده وابی! بلگه سیخومی بسته وابی @@ -2736,7 +2738,7 @@ رئڌن وا پؽش و ای وبگه اینترنتی - نوم ر نهنگ + نوم ره نهنگ و آسۊوی ترین ای وبگه ن و بلگه هووه تیلیفووݩ خوتووݩ یارین تا هر سا دلتووݩ خاست وس دسرسی داشته بۊین وو کار وا ی برنومه گشت گر زیتری ن سیتووݩ داره. @@ -3092,9 +3094,9 @@ بؽ استسنا وبگه - ٱووردن و ر نهنگا + ٱووردن و ره نهنگا - وورداشتن ز ر نهنگا + وورداشتن ز ره نهنگا - ر نهنگا + ره نهنگا - نشووݩ داڌن پوی ر نهنگا + نشووݩ داڌن پوی ره نهنگا - و هندا موجاز ر نهنگ رسیڌین + و هندا موجاز ره نهنگ رسیڌین - سی ٱووردن ر نهنگی نۊ، یکی ن پاک کۊنین. بزنین ری وبگه، واڌارنین وو وورداشتن ن پسند کۊنین. + سی ٱووردن ره نهنگی نۊ، یکی ن پاک کۊنین. بزنین ری وبگه، واڌارنین وو وورداشتن ن پسند کۊنین. خا، فئمیم - ر نهنگا + ره نهنگا نوم - نوم ر نهنگ + نوم ره نهنگ - نشۊوی اینترنتی ر نهنگ + نشۊوی اینترنتی ره نهنگ لقو @@ -3202,7 +3204,7 @@ آلشت - آلشت ر نهنگ + آلشت ره نهنگ زفت diff --git a/mobile/android/fenix/app/src/main/res/values-cy/strings.xml b/mobile/android/fenix/app/src/main/res/values-cy/strings.xml index 358e4e431706e..d5e4cf2c2e9e3 100644 --- a/mobile/android/fenix/app/src/main/res/values-cy/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-cy/strings.xml @@ -647,7 +647,7 @@ Dweud ffarwel wrth dracwyr annymunol - Agorwch eich holl ddolenni gyda phreifatrwydd adeiledig + Agor eich holl ddolenni gyda phreifatrwydd mewnol Rydym yn diogelu eich data ac yn awtomatig yn rhwystro cwmnïau rhag ysbïo ar eich cliciau. 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 cc16bc5779de6..e07d0cf622912 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 @@ -543,60 +543,60 @@ Administrar - Lanza el navegador Android definitivo + Lanza el navegador Android definitivo - Carga sitios a la velocidad del rayo + Carga sitios a la velocidad del rayo - Protección contra el rastreo automática + Protección contra el rastreo automática - Miles de personalizaciones + Miles de personalizaciones - Al continuar, aceptas los %1$s. + Al continuar, aceptas los %1$s. - Términos de uso de Firefox + Términos de uso de Firefox - Firefox se preocupa de tu privacidad. Conoce más en nuestra %1$s. + Firefox se preocupa de tu privacidad. Conoce más en nuestra %1$s. - Aviso de privacidad + Aviso de privacidad - Para ayudar a mejorar el navegador, Firefox envía datos de diagnóstico e interacción a Mozilla. %1$s + Para ayudar a mejorar el navegador, Firefox envía datos de diagnóstico e interacción a Mozilla. %1$s - Administrar ajustes + Administrar ajustes - Continuar + Continuar - ¿Dónde quieres situar tu barra de direcciones? + ¿Dónde quieres situar tu barra de direcciones? - Continuar + Continuar - Ayúdanos a mejorar Firefox + Ayúdanos a mejorar Firefox - Comparte con los socios de marketing de Mozilla cómo descubriste Firefox y cómo lo usas. Estos datos nunca se venden. + Comparte con los socios de marketing de Mozilla cómo descubriste Firefox y cómo lo usas. Estos datos nunca se venden. - Cómo utilizamos los datos + Cómo utilizamos los datos - Confirmar + Confirmar - Obtén protección contra rastreo automática de forma predeterminada + Obtén protección contra rastreo automática de forma predeterminada - Un toque ayuda a evitar que las empresas espíen tus clics. + Un toque ayuda a evitar que las empresas espíen tus clics. - Sincroniza dondequiera que uses Firefox + Sincroniza dondequiera que uses Firefox - Accede a marcadores, pestañas y contraseñas en cualquier dispositivo. Todo protegido con cifrado. + Accede a marcadores, pestañas y contraseñas en cualquier dispositivo. Todo protegido con cifrado. - Empezar a sincronizar + Empezar a sincronizar - Ahora no + Ahora no Ayúdanos a mejorar Firefox @@ -616,46 +616,46 @@ - Continuar + Continuar - Ahora no + Ahora no - Prepárate para navegar libremente + Prepárate para navegar libremente - Rápido, seguro y no te traicionará.\nNavegar ahora es mucho mejor. + Rápido, seguro y no te traicionará.\nNavegar ahora es mucho mejor. - Al continuar, aceptas los %1$s. + Al continuar, aceptas los %1$s. - Términos de uso de Firefox + Términos de uso de Firefox - Firefox se preocupa de tu privacidad. Conoce más en nuestra %1$s. + Firefox se preocupa de tu privacidad. Conoce más en nuestra %1$s. - Aviso de privacidad + Aviso de privacidad - Para ayudar a mejorar el navegador, Firefox envía datos de diagnóstico e interacción a Mozilla. %1$s + Para ayudar a mejorar el navegador, Firefox envía datos de diagnóstico e interacción a Mozilla. %1$s - Administrar ajustes + Administrar ajustes Di adiós a los rastreadores intrusivos - Protegemos tus datos y bloqueamos automáticamente a las empresas que espían tus clics. + Protegemos tus datos y bloqueamos automáticamente a las empresas que espían tus clics. - Establecer como navegador predeterminado + Establecer como navegador predeterminado - Elige tu barra de direcciones + Elige tu barra de direcciones - Parte superior + Parte superior - Parte inferior + Parte inferior Elige tu tema @@ -665,32 +665,32 @@ Oscuro - Continúa al instante desde donde lo dejaste + Continúa al instante desde donde lo dejaste - Accede a marcadores, contraseñas y más en cualquier dispositivo al instante. Tus datos personales se mantienen seguros gracias al cifrado. + Accede a marcadores, contraseñas y más en cualquier dispositivo al instante. Tus datos personales se mantienen seguros gracias al cifrado. - Empezar a sincronizar + Empezar a sincronizar - Ayúdanos a construir un mejor Internet + Ayúdanos a construir un mejor Internet - Comparte con los socios de marketing de Mozilla cómo descubriste Firefox y cómo lo usas. Estos datos nunca se venden. %1$s + Comparte con los socios de marketing de Mozilla cómo descubriste Firefox y cómo lo usas. Estos datos nunca se venden. %1$s - Cómo utilizamos los datos + Cómo utilizamos los datos Las notificaciones te ayudan a estar más seguro con Firefox Descubre las últimas funcionalidades de privacidad en Firefox para estar siempre al día sobre cómo mantenerte protegido. - Activar notificaciones + Activar notificaciones - Haz que cada búsqueda sea más privada + Haz que cada búsqueda sea más privada - Comienza cada búsqueda desde la pantalla de inicio de tu teléfono sabiendo que las protecciones automáticas de Firefox te respaldan. + Comienza cada búsqueda desde la pantalla de inicio de tu teléfono sabiendo que las protecciones automáticas de Firefox te respaldan. - Añadir widget de Firefox + Añadir widget de Firefox @@ -3101,9 +3101,9 @@ --> Verificado por: %1$s - Eliminar + Eliminar - Editar + Editar ¿Estás seguro de que quieres eliminar esta contraseña? @@ -3111,15 +3111,15 @@ Cancelar - Opciones de contraseña + Opciones de contraseña - El campo de texto editable para la dirección del sitio web. + El campo de texto editable para la dirección del sitio web. - El campo de texto editable para el nombre de usuario. + El campo de texto editable para el nombre de usuario. - El campo de texto editable para la contraseña. + El campo de texto editable para la contraseña. - Guardar cambios. + Guardar cambios. Editar contraseña diff --git a/mobile/android/fenix/app/src/main/res/values-eu/strings.xml b/mobile/android/fenix/app/src/main/res/values-eu/strings.xml index f2b494198b9d2..d5963d5aaf4dd 100644 --- a/mobile/android/fenix/app/src/main/res/values-eu/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-eu/strings.xml @@ -646,6 +646,8 @@ Kudeatu ezarpenak Esan agur jarraipen-elementu beldurgarriei + + Ireki zure lotura guztiak integratutako pribatutasunarekin Zure datuak babestu eta enpresek zure klikak espiatzetik automatikoki blokeatzen ditugu. diff --git a/mobile/android/fenix/app/src/main/res/values-km/strings.xml b/mobile/android/fenix/app/src/main/res/values-km/strings.xml index 01d685dce3287..007731734fbd3 100644 --- a/mobile/android/fenix/app/src/main/res/values-km/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-km/strings.xml @@ -7,6 +7,8 @@ --> + + ឯកជន %s បើក​ដំណើរការក្នុង​ផ្ទាំង​ទាំងអស់ + + គណនី + + គណនី Mozilla + + ការកំណត់គណនី បាន​អនុញ្ញាត @@ -456,6 +464,12 @@ ផ្ទាំងរូបភាព បោះបង់ + + គ្រប់គ្រងគណនី បោះបង់ diff --git a/mobile/android/fenix/app/src/main/res/values-ko/strings.xml b/mobile/android/fenix/app/src/main/res/values-ko/strings.xml index a849e90920bd9..514bd5db398a2 100644 --- a/mobile/android/fenix/app/src/main/res/values-ko/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-ko/strings.xml @@ -2532,7 +2532,7 @@ 교차 사이트 쿠키 격리 - 웹 사이트에 내 데이터를 공유하거나 판매하지 말라고 요청 + 웹 사이트에 내 정보 판매 또는 공유 금지 요청 추적 콘텐츠 diff --git a/mobile/android/fenix/app/src/main/res/values-ru/strings.xml b/mobile/android/fenix/app/src/main/res/values-ru/strings.xml index 4db8f49488ee5..aebbb9a386461 100644 --- a/mobile/android/fenix/app/src/main/res/values-ru/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-ru/strings.xml @@ -646,6 +646,8 @@ Управление настройками Попрощайтесь с жуткими трекерами + + Открывайте все ссылки со встроенной приватностью Мы защищаем ваши данные и автоматически блокируем компании от отслеживания ваших кликов. diff --git a/mobile/android/fenix/app/src/main/res/values-tr/strings.xml b/mobile/android/fenix/app/src/main/res/values-tr/strings.xml index f30fb8302ece3..30cb718dd6d71 100644 --- a/mobile/android/fenix/app/src/main/res/values-tr/strings.xml +++ b/mobile/android/fenix/app/src/main/res/values-tr/strings.xml @@ -646,6 +646,8 @@ Ayarları yönet Ürpertici takip kodlarına veda edin + + Bağlantılarınızı açarken gizliliğinizi koruyun Verilerinizi koruyoruz ve şirketlerin tıklamalarınızı izlemesini otomatik olarak engelliyoruz. diff --git a/mobile/android/fenix/app/src/main/res/xml/home_preferences.xml b/mobile/android/fenix/app/src/main/res/xml/home_preferences.xml index 4fd1f8945ae24..e1afb71a53b22 100644 --- a/mobile/android/fenix/app/src/main/res/xml/home_preferences.xml +++ b/mobile/android/fenix/app/src/main/res/xml/home_preferences.xml @@ -48,17 +48,14 @@ app:iconSpaceReserved="false"> diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index 29b75a08200f2..a524b69436284 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -11784,6 +11784,15 @@ #endif mirror: always +# Provide minimal HW support for codecs that are otherwise unavailable on +# Android, e.g. H264 and HEVC. +#if defined(ANDROID) +- name: media.ffvpx-hw.minimal + type: RelaxedAtomicBool + value: false + mirror: always +#endif + # The codecs in the vendored ffmpeg copy are usually prefered to the other # codecs. This allows changing this policy for testing purposes. - name: media.prefer-non-ffvpx diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index e619ab86ede06..4c114d86f9c5a 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -3099,12 +3099,14 @@ pref("network.tcp.keepalive.idle_time", 600); // seconds; 10 mins // All the Geolocation preferences are here. // -pref("geo.provider.network.url", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_LOCATION_SERVICE_API_KEY%&solution_channel=%OS%"); +#ifndef ANDROID + pref("geo.provider.network.url", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_LOCATION_SERVICE_API_KEY%&solution_channel=%OS%"); -// Timeout to wait before sending the location request. -pref("geo.provider.network.timeToWaitBeforeSending", 5000); -// Timeout for outbound network geolocation provider. -pref("geo.provider.network.timeout", 60000); + // Timeout to wait before sending the location request. + pref("geo.provider.network.timeToWaitBeforeSending", 5000); + // Timeout for outbound network geolocation provider. + pref("geo.provider.network.timeout", 60000); +#endif #ifdef XP_MACOSX pref("geo.provider.use_corelocation", true); diff --git a/netwerk/test/http3server/src/main.rs b/netwerk/test/http3server/src/main.rs index 6d5ff01525454..313517b6c6489 100644 --- a/netwerk/test/http3server/src/main.rs +++ b/netwerk/test/http3server/src/main.rs @@ -1725,3 +1725,5 @@ extern "C" {} extern "C" {} #[cfg_attr(target_os = "windows", link(name = "iphlpapi"))] extern "C" {} +#[cfg_attr(target_os = "windows", link(name = "rpcrt4"))] +extern "C" {} diff --git a/python/mozbuild/mozbuild/mozconfig.py b/python/mozbuild/mozbuild/mozconfig.py index 3c9d1dd884a02..2dc9260e8cc24 100644 --- a/python/mozbuild/mozbuild/mozconfig.py +++ b/python/mozbuild/mozbuild/mozconfig.py @@ -13,6 +13,8 @@ from mozboot.mozconfig import find_mozconfig from mozpack import path as mozpath +from mozbuild.util import sanitize_shell_env + MOZCONFIG_BAD_EXIT_CODE = """ Evaluation of your mozconfig exited with an error. This could be triggered by a command inside your mozconfig failing. Please change your mozconfig @@ -131,7 +133,7 @@ def read_mozconfig(self, path=None): # actually leads to two shell executions on Windows. Avoid this by # directly calling sh mozconfig_loader. shell = "sh" - env = dict(os.environ) + env = sanitize_shell_env(os.environ) env["PYTHONIOENCODING"] = "utf-8" if "MOZILLABUILD" in os.environ: diff --git a/python/mozbuild/mozbuild/util.py b/python/mozbuild/mozbuild/util.py index 4ed3ef217f43d..9f46f13e29664 100644 --- a/python/mozbuild/mozbuild/util.py +++ b/python/mozbuild/mozbuild/util.py @@ -38,6 +38,17 @@ system_encoding = "utf-8" +def sanitize_shell_env(env): + """Return a copy of env with SHELLOPTS removed for bash subprocess calls. + + SHELLOPTS being exported can cause various problems in subprocess shell + execution, so we remove it entirely to prevent unexpected behavior. + """ + env = dict(env) + env.pop("SHELLOPTS", None) + return env + + LOG_TIMESTAMP_FORMAT = "%Y%m%d_%H%M%S" diff --git a/services/fxaccounts/FxAccountsCommon.sys.mjs b/services/fxaccounts/FxAccountsCommon.sys.mjs index bc1ce4e7a902f..f37d1580d8272 100644 --- a/services/fxaccounts/FxAccountsCommon.sys.mjs +++ b/services/fxaccounts/FxAccountsCommon.sys.mjs @@ -98,6 +98,9 @@ export let OAUTH_CLIENT_ID = CLIENT_IS_THUNDERBIRD : FX_OAUTH_CLIENT_ID; export let SCOPE_PROFILE = "profile"; export let SCOPE_PROFILE_WRITE = "profile:write"; +export let SCOPE_PROFILE_UID = "profile:uid"; +export let SCOPE_SMART_WINDOW = "https://identity.mozilla.com/apps/smartwindow"; + // Sync scope in Firefox. export let SCOPE_OLD_SYNC = "https://identity.mozilla.com/apps/oldsync"; // Sync scope in Thunderbird. diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index 79458f77029ad..38c3267e16c07 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -960,13 +960,6 @@ user-id = 64539 user-login = "kennykerr" user-name = "Kenny Kerr" -[[publisher.windows-link]] -version = "0.2.1" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - [[publisher.windows-numerics]] version = "0.3.1" when = "2025-10-06" diff --git a/taskcluster/scripts/builder/build-android.sh b/taskcluster/scripts/builder/build-android.sh index 55d0772456ed1..77e083f17f4b0 100755 --- a/taskcluster/scripts/builder/build-android.sh +++ b/taskcluster/scripts/builder/build-android.sh @@ -13,7 +13,6 @@ cat > $mozconfig < u32); - -unsafe { - SetLastError(1234); - assert_eq!(GetLastError(), 1234); -} -``` diff --git a/third_party/rust/windows-link/src/lib.rs b/third_party/rust/windows-link/src/lib.rs deleted file mode 100644 index dbecf9f3b5e4f..0000000000000 --- a/third_party/rust/windows-link/src/lib.rs +++ /dev/null @@ -1,39 +0,0 @@ -#![doc = include_str!("../readme.md")] -#![no_std] - -/// Defines an external function to import. -#[cfg(all(windows, target_arch = "x86"))] -#[macro_export] -macro_rules! link { - ($library:literal $abi:literal $($link_name:literal)? fn $($function:tt)*) => ( - #[link(name = $library, kind = "raw-dylib", modifiers = "+verbatim", import_name_type = "undecorated")] - extern $abi { - $(#[link_name=$link_name])? - pub fn $($function)*; - } - ) -} - -/// Defines an external function to import. -#[cfg(all(windows, not(target_arch = "x86")))] -#[macro_export] -macro_rules! link { - ($library:literal $abi:literal $($link_name:literal)? fn $($function:tt)*) => ( - #[link(name = $library, kind = "raw-dylib", modifiers = "+verbatim")] - extern $abi { - $(#[link_name=$link_name])? - pub fn $($function)*; - } - ) -} - -/// Defines an external function to import. -#[cfg(not(windows))] -#[macro_export] -macro_rules! link { - ($library:literal $abi:literal $($link_name:literal)? fn $($function:tt)*) => ( - extern $abi { - pub fn $($function)*; - } - ) -} diff --git a/toolkit/actors/UserCharacteristicsCanvasRenderingChild.sys.mjs b/toolkit/actors/UserCharacteristicsCanvasRenderingChild.sys.mjs index dc2e9731b56f8..3eb6ba3bcf1ab 100644 --- a/toolkit/actors/UserCharacteristicsCanvasRenderingChild.sys.mjs +++ b/toolkit/actors/UserCharacteristicsCanvasRenderingChild.sys.mjs @@ -75,9 +75,11 @@ export class UserCharacteristicsCanvasRenderingChild extends JSWindowActorChild }; } - return sha1Uint8Array( - ctx.getImageData(0, 0, canvas.width, canvas.height).data - ).catch(stringifyError); + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + const hash = await sha1Uint8Array(imageData.data).catch(stringifyError); + const raw = btoa(String.fromCharCode.apply(null, imageData.data)); + + return { hash, raw }; }; const errors = []; @@ -105,7 +107,8 @@ export class UserCharacteristicsCanvasRenderingChild extends JSWindowActorChild }); continue; } - renderings.set(name, result); + renderings.set(name, result.hash); + renderings.set(name + "Raw", result.raw); } // Run SW renderings @@ -114,13 +117,14 @@ export class UserCharacteristicsCanvasRenderingChild extends JSWindowActorChild const result = await runRecipe(false, recipe); if (result.error) { errors.push({ - name: name + "software", + name: name + "Software", error: result.error, originalError: result.originalError, }); continue; } - renderings.set(name + "software", result); + renderings.set(name + "Software", result.hash); + renderings.set(name + "SoftwareRaw", result.raw); } const data = new Map(); diff --git a/toolkit/components/ml/content/backends/ONNXPipeline.mjs b/toolkit/components/ml/content/backends/ONNXPipeline.mjs index 6c2efbbc9fd19..573769a193fb4 100644 --- a/toolkit/components/ml/content/backends/ONNXPipeline.mjs +++ b/toolkit/components/ml/content/backends/ONNXPipeline.mjs @@ -877,7 +877,7 @@ export class ONNXPipeline { }; const streamerOptions = { - perTokens: true, + perTokens: false, skipPrompt: true, returnTokens: false, ...request.streamerOptions, @@ -885,16 +885,36 @@ export class ONNXPipeline { let streamer; let chunkTokens = []; - // Removed unused chunkText declaration here + let chunkText = ""; + let nextTokensArePrompt = !streamerOptions.skipPrompt; + let restoreTokenizer = false; let firstTokenTimestamp = null; - if (tokenizer) { + if (tokenizer && inferenceProgressCallback) { + const flushPrompts = _tokens => { + streamer.token_cache = _tokens; + streamer.end(); + streamer.tokenizer = { + decode: () => { + streamer.token_cache = []; + return ""; + }, + }; + restoreTokenizer = true; + streamer.next_tokens_are_prompt = false; + }; + streamer = new transformers.TextStreamer(tokenizer, { skip_prompt: streamerOptions.skipPrompt, decode_kwargs: { skip_special_tokens: true, }, token_callback_function: tokens => { + if (restoreTokenizer) { + streamer.tokenizer = tokenizer; + restoreTokenizer = false; + } + // Record Time To First Token on the very first callback const now = ChromeUtils.now(); if (metrics.timeToFirstToken === null) { @@ -904,35 +924,37 @@ export class ONNXPipeline { metrics.outputTokens += tokens.length; - // Only proceed with buffering if we have a callback to call - if (!inferenceProgressCallback) { - return; - } - - if (streamerOptions.perTokens) { - // Logic handled in callback_function - } else { - // Append newly received tokens. - chunkTokens.push(tokens); - } - }, - // Per-word (or per-token if perTokens=true) callback function - callback_function: text => { - if (!inferenceProgressCallback) { - return; - } if (streamerOptions.perTokens) { + if (nextTokensArePrompt) { + flushPrompts(tokens); + } + inferenceProgressCallback({ ...progressInfo, metadata: { - text, - tokens: streamerOptions.returnTokens ? chunkTokens : null, + text: chunkText, + tokens: streamerOptions.returnTokens ? tokens : null, + isPrompt: nextTokensArePrompt, requestId, - isPrompt: false, // skipping prompt, so assumed false }, type: lazy.Progress.ProgressType.INFERENCE, statusText: lazy.Progress.ProgressStatusText.IN_PROGRESS, }); + + chunkText = ""; + } else { + chunkTokens.push(tokens); + + if (nextTokensArePrompt) { + flushPrompts(tokens); + } + } + nextTokensArePrompt = false; + }, + // Per-word callback function + callback_function: text => { + if (streamerOptions.perTokens) { + chunkText = text; } else { inferenceProgressCallback({ ...progressInfo, @@ -940,7 +962,7 @@ export class ONNXPipeline { text, tokens: streamerOptions.returnTokens ? chunkTokens : null, requestId, - isPrompt: false, + isPrompt: nextTokensArePrompt, }, type: lazy.Progress.ProgressType.INFERENCE, statusText: lazy.Progress.ProgressStatusText.IN_PROGRESS, @@ -952,11 +974,13 @@ export class ONNXPipeline { }); } - // Inject streamer into request options - const requestWithCallback = { - ...request, - options: { ...request.options, streamer }, - }; + // Override streamer in options + const requestWithCallback = inferenceProgressCallback + ? { + ...request, + options: { ...request.options, streamer }, + } + : request; let result; diff --git a/toolkit/components/places/tests/browser/browser.toml b/toolkit/components/places/tests/browser/browser.toml index db3c4da93d032..0f04a168679eb 100644 --- a/toolkit/components/places/tests/browser/browser.toml +++ b/toolkit/components/places/tests/browser/browser.toml @@ -30,6 +30,12 @@ skip-if = [ "verify-standalone", ] +["browser_bug680727_feltPrivacy.js"] +https_first_disabled = true +skip-if = [ + "verify-standalone", +] + ["browser_bug1601563.js"] https_first_disabled = true support-files = [ diff --git a/toolkit/components/places/tests/browser/browser_bug680727.js b/toolkit/components/places/tests/browser/browser_bug680727.js index abc73665dd0f4..15c168300606f 100644 --- a/toolkit/components/places/tests/browser/browser_bug680727.js +++ b/toolkit/components/places/tests/browser/browser_bug680727.js @@ -16,6 +16,10 @@ function test() { // reachable in offline mode. To avoid this, disable any proxy. proxyPrefValue = Services.prefs.getIntPref("network.proxy.type"); Services.prefs.setIntPref("network.proxy.type", 0); + // Once security.certerrors.felt-privacy-v1 is enabled by default this test + // can be removed because the felt privacy version is covered in + // browser_bug680727_feltPrivacy.js + Services.prefs.setBoolPref("security.certerrors.felt-privacy-v1", false); // Clear network cache. Services.cache2.clear(); @@ -83,18 +87,21 @@ function errorAsyncListener(aURI, aIsVisited) { ); SpecialPowers.spawn(ourTab.linkedBrowser, [], async function () { - const netErrorCard = await ContentTaskUtils.waitForCondition( - () => content.document.querySelector("net-error-card")?.wrappedJSObject + const button = content.document.querySelector( + "#netErrorButtonContainer > .try-again" ); - Assert.ok( - netErrorCard.tryAgainButton, - "The error page has got a .try-again element" + Assert.ok(button, "The error page has a .try-again element"); + + await ContentTaskUtils.waitForCondition( + () => ContentTaskUtils.isVisible(button), + "Wait for button to be visible" ); - EventUtils.synthesizeMouseAtCenter( - netErrorCard.tryAgainButton, - {}, - content + + Assert.ok( + ContentTaskUtils.isVisible(button), + ".try-again button is visible" ); + button.click(); }); } @@ -130,6 +137,7 @@ function reloadAsyncListener(aURI, aIsVisited) { registerCleanupFunction(async function () { Services.prefs.setIntPref("network.proxy.type", proxyPrefValue); + Services.prefs.setBoolPref("security.certerrors.felt-privacy-v1", true); Services.io.offline = false; BrowserTestUtils.removeTab(ourTab); }); diff --git a/toolkit/components/places/tests/browser/browser_bug680727_feltPrivacy.js b/toolkit/components/places/tests/browser/browser_bug680727_feltPrivacy.js new file mode 100644 index 0000000000000..620c6b75264e4 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_bug680727_feltPrivacy.js @@ -0,0 +1,138 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Ensure that clicking the button in the Offline mode neterror page updates + global history. See bug 680727. */ +/* TEST_PATH=toolkit/components/places/tests/browser/browser_bug680727_feltPrivacy.js make -C $(OBJDIR) mochitest-browser-chrome */ + +const kUniqueURI = Services.io.newURI( + "http://mochi.test:8888/#bug680727_feltPrivacy" +); +var proxyPrefValue; +var ourTab; + +function test() { + waitForExplicitFinish(); + + // Tests always connect to localhost, and per bug 87717, localhost is now + // reachable in offline mode. To avoid this, disable any proxy. + proxyPrefValue = Services.prefs.getIntPref("network.proxy.type"); + Services.prefs.setIntPref("network.proxy.type", 0); + Services.prefs.setBoolPref("security.certerrors.felt-privacy-v1", true); + + // Clear network cache. + Services.cache2.clear(); + + // Go offline, expecting the error page. + Services.io.offline = true; + + BrowserTestUtils.openNewForegroundTab(gBrowser).then(tab => { + ourTab = tab; + BrowserTestUtils.browserLoaded( + ourTab.linkedBrowser, + false, + null, + true + ).then(errorListener); + BrowserTestUtils.startLoadingURIString( + ourTab.linkedBrowser, + kUniqueURI.spec + ); + }); +} + +// ------------------------------------------------------------------------------ +// listen to loading the neterror page. (offline mode) +function errorListener() { + ok(Services.io.offline, "Services.io.offline is true."); + + // This is an error page. + SpecialPowers.spawn(ourTab.linkedBrowser, [kUniqueURI.spec], function (uri) { + Assert.equal( + content.document.documentURI.substring(0, 27), + "about:neterror?e=netOffline", + "Document URI is the error page." + ); + + // But location bar should show the original request. + Assert.equal( + content.location.href, + uri, + "Docshell URI is the original URI." + ); + }).then(() => { + // Global history does not record URI of a failed request. + PlacesTestUtils.promiseAsyncUpdates().then(() => { + PlacesUtils.history.hasVisits(kUniqueURI).then(isVisited => { + errorAsyncListener(kUniqueURI, isVisited); + }); + }); + }); +} + +function errorAsyncListener(aURI, aIsVisited) { + ok( + kUniqueURI.equals(aURI) && !aIsVisited, + "The neterror page is not listed in global history." + ); + + Services.prefs.setIntPref("network.proxy.type", proxyPrefValue); + + // Now press the "Try Again" button, with offline mode off. + Services.io.offline = false; + + BrowserTestUtils.browserLoaded(ourTab.linkedBrowser, false, null, true).then( + reloadListener + ); + + SpecialPowers.spawn(ourTab.linkedBrowser, [], async function () { + const netErrorCard = await ContentTaskUtils.waitForCondition( + () => content.document.querySelector("net-error-card")?.wrappedJSObject + ); + Assert.ok( + netErrorCard.tryAgainButton, + "The error page has got a .try-again element" + ); + EventUtils.synthesizeMouseAtCenter( + netErrorCard.tryAgainButton, + {}, + content + ); + }); +} + +// ------------------------------------------------------------------------------ +// listen to reload of neterror. +function reloadListener() { + // This listener catches "DOMContentLoaded" on being called + // nsIWPL::onLocationChange(...). That is right *AFTER* + // IHistory::VisitURI(...) is called. + ok(!Services.io.offline, "Services.io.offline is false."); + + SpecialPowers.spawn(ourTab.linkedBrowser, [kUniqueURI.spec], function (uri) { + // This is not an error page. + Assert.equal( + content.document.documentURI, + uri, + "Document URI is not the offline-error page, but the original URI." + ); + }).then(() => { + // Check if global history remembers the successfully-requested URI. + PlacesTestUtils.promiseAsyncUpdates().then(() => { + PlacesUtils.history.hasVisits(kUniqueURI).then(isVisited => { + reloadAsyncListener(kUniqueURI, isVisited); + }); + }); + }); +} + +function reloadAsyncListener(aURI, aIsVisited) { + ok(kUniqueURI.equals(aURI) && aIsVisited, "We have visited the URI."); + PlacesUtils.history.clear().then(finish); +} + +registerCleanupFunction(async function () { + Services.prefs.setIntPref("network.proxy.type", proxyPrefValue); + Services.io.offline = false; + BrowserTestUtils.removeTab(ourTab); +}); diff --git a/toolkit/components/resistfingerprinting/CanvasHashData.sys.mjs b/toolkit/components/resistfingerprinting/CanvasHashData.sys.mjs new file mode 100644 index 0000000000000..6424eb7095aed --- /dev/null +++ b/toolkit/components/resistfingerprinting/CanvasHashData.sys.mjs @@ -0,0 +1,1215 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// Canvas Hash Probability Lookup +// Generated from 10,677,564 total submissions +// Target: 50 samples per hash (calibrated for Release channel) +// Only includes hashes with frequency > 5,000 +// Hash trimming: 27 character(s) removed from end (108 bits) +// Effective bit length: 52 bits + +const BASE_CANVAS_HASH_PROBABILITIES = new Map([ + ["002177eb9dbf7", 0.007536931], + ["008c99e6ff9c1", 0.0022686025], + ["00d234b9572bf", 0.0026938204], + ["0109e891bde13", 0.0014334451], + ["01272f060b7fd", 0.0041729261], + ["0166a5c804c3c", 0.0066702241], + ["01864bf689f3a", 0.0084588056], + ["01cab43a07513", 0.000046968], + ["01d27f8536f35", 0.0034428148], + ["01ff75639bb51", 0.0080179602], + ["0225c3d139380", 0.0047560164], + ["02e074cbe2346", 0.0094625284], + ["03302a02e5462", 0.009948269], + ["035b6610be076", 0.0002747479], + ["03673370f9cb4", 0.0099127676], + ["03c7704b01f48", 0.0098425197], + ["03d1f7b2494f0", 0.0011163455], + ["0406580ce49d2", 0.0042881647], + ["041c213437aa9", 0.0077700078], + ["04657daef1aaf", 0.003875969], + ["047dd607443aa", 0.0006576784], + ["053b93e826c6c", 0.009596929], + ["0592916a26785", 0.0059227671], + ["05d727bf85403", 0.0009962938], + ["05d9e93f7befd", 0.0099820323], + ["061d9c3bb41ab", 0.0004564293], + ["06434d89715a4", 0.0003332556], + ["0657d0eb1ab00", 0.0079948833], + ["0659eb78c5c5a", 0.0023247164], + ["066daa27669e4", 0.0042119451], + ["0671a8470d024", 0.0028933511], + ["068d9cd054887", 0.005608525], + ["06c0a1aade824", 0.0006376412], + ["0742e982568bb", 0.0014356677], + ["074a77552a12b", 0.0035082795], + ["0776d2ee9c1ea", 0.0004429286], + ["07a961729e8cc", 0.0007733832], + ["07c306d78062c", 0.0009904913], + ["07ce0f263421e", 0.0000404563], + ["084958888da4f", 0.0032713949], + ["084e43a453c15", 0.0040134853], + ["0894b249d01f2", 0.0013062333], + ["08e102d4fd13e", 0.0002961734], + ["08ef99e6c9128", 0.0067944014], + ["091d751a2c7e4", 0.0038022814], + ["0939dc821b129", 0.0081433225], + ["097c0c3b726be", 0.0057683433], + ["09baf71eda5cf", 0.0051519835], + ["09bf234e9a373", 0.0010853285], + ["0a2cd5f4e5b3e", 0.0000345049], + ["0a694dbafe73e", 0.0015500992], + ["0aba80beca2e8", 0.0010947147], + ["0acd68034d5c1", 0.0021627233], + ["0addf88f68e69", 0.0022610111], + ["0afa7c765d084", 0.00847745], + ["0b326a6e0b1df", 0.0019654861], + ["0b8d520510fc7", 0.0059537985], + ["0b9a802ac6d94", 0.000594502], + ["0c1a210687dc0", 0.0008089044], + ["0c44642132767", 0.0054603036], + ["0c8665db51799", 0.0002215134], + ["0cb89b144b620", 0.0054975261], + ["0cc2e2f58dd2c", 0.0024003841], + ["0ce4ef52a3d47", 0.0013812536], + ["0dbe1c4c8dd0a", 0.0023986568], + ["0e40a1a464903", 0.0026299179], + ["0e45daa76671a", 0.0000469408], + ["0e52534adf9ff", 0.0028314174], + ["0eaab253f068d", 0.0040836328], + ["0ed7bbae8a9c8", 0.0006957103], + ["0eed3dfbebf9b", 0.0007575758], + ["0f38e9d86cd35", 0.0023185718], + ["0f3c45f589cc3", 0.0067585834], + ["0f3ff938187df", 0.0003877622], + ["0f4d08591c3f3", 0.0000182144], + ["0f5d18b85235a", 0.0022123894], + ["0f669a1f1a473", 0.0064259093], + ["0fa913472fa4b", 0.0015980568], + ["0fdc6e6b28d5e", 0.0072108451], + ["1077475fe2f84", 0.0036038633], + ["10a935de24c21", 0.0048323185], + ["10d0b12d3f313", 0.002235936], + ["11310e9d0e9c5", 0.0005624866], + ["11390fcc4d749", 0.0008994262], + ["114ab81389062", 0.0088794175], + ["116ac19f0331c", 0.0004411894], + ["11c5f521fd8d2", 0.0014381454], + ["11d803ba7cf51", 0.0004475514], + ["12e0c063dbf0d", 0.0039013733], + ["12fdd4305376d", 0.0033171897], + ["131a794315ee2", 0.0016900456], + ["1343a1beb4a67", 0.0004083333], + ["13a9d6916c9f0", 0.0083263947], + ["13ac289fe4e41", 0.0058302239], + ["142b4db0597c8", 0.0006256256], + ["14b1ae7cedee0", 0.0004973491], + ["14bfaa3121766", 0.001106366], + ["152fe39d551d2", 0.0043133195], + ["15421823dc35b", 0.0039071657], + ["157f4a8b9f28e", 0.0079339892], + ["162a142479c49", 0.0097408923], + ["1640e5741df34", 0.0009262347], + ["164ec490db57d", 0.0036067229], + ["1679f8d9ef629", 0.0045504186], + ["16991e60f8c0c", 0.0025625256], + ["16e7f5992b8b3", 0.0045224313], + ["1705285a31c76", 0.0000701678], + ["173034ffa22d0", 0.0015849368], + ["17565873ff40b", 0.0003219243], + ["175ca9b63db8e", 0.0089285714], + ["176f833a4dc31", 0.0001598184], + ["178ed5344cf50", 0.0083528233], + ["179638c72cb31", 0.0090269002], + ["17a06d00e2d20", 0.0061561192], + ["17abf71143386", 0.0081619327], + ["17f25f4994b41", 0.0022802937], + ["1810a83d924fe", 0.0017053788], + ["183435b2c23f1", 0.0046654847], + ["18d1f8ba62aa0", 0.0030365602], + ["193d581189532", 0.0080997894], + ["1a29726ed20ef", 0.0002812291], + ["1a2ca40dfa569", 0.0028162668], + ["1a54025dce6ef", 0.0087966221], + ["1a9c9f7ff7ffe", 0.0004324923], + ["1aaa6261c7ca2", 0.0040723245], + ["1ae891eebf6ae", 0.0081340491], + ["1b78ca0465fe6", 0.0035681153], + ["1b89e7bb258e2", 0.0003237964], + ["1b8df53fe44fa", 0.006559958], + ["1bf1b9d7b2073", 0.0029375477], + ["1c5000f286a9f", 0.0041753653], + ["1cb2129ef968e", 0.0031826862], + ["1cc5ed23f346e", 0.0009896091], + ["1cdc753a57014", 0.005881661], + ["1d2862a8e8775", 0.0016559033], + ["1d95847869635", 0.0052405408], + ["1db4a89982b87", 0.002617801], + ["1db58f0e27833", 0.0015280707], + ["1dc73bf9c8187", 0.0024557957], + ["1e53ca2ae452d", 0.0046142488], + ["1e684fa5d4b06", 0.0015703518], + ["1e7cd5911b817", 0.0087827156], + ["1eb01a8b9ab6a", 0.0038455622], + ["1ed4ce6b6652e", 0.0012125621], + ["1edaa2bde0423", 0.0015720799], + ["1ee4caccd7b77", 0.0002894423], + ["1f2f3663ff51b", 0.0015574383], + ["1f798c5a6b0c2", 0.000855271], + ["1fa10d94d4c9c", 0.001046945], + ["1faab224682be", 0.0075041273], + ["1fe55f2d05226", 0.0001214367], + ["200146d30bb63", 0.0055205918], + ["208ed230a9869", 0.0071952799], + ["20b8d86a04ffc", 0.0041753653], + ["20ff5a6d279e1", 0.0013864241], + ["210349ddf0730", 0.0005047089], + ["21631f247dc16", 0.0015536153], + ["21765b74e5b8f", 0.0090057637], + ["217a0d403831d", 0.0009183917], + ["218dc49948253", 0.0014325827], + ["21a7906dcbb39", 0.0044734723], + ["21bb876dfa1e2", 0.0018233535], + ["21f3b1aadfc1c", 0.0006917351], + ["21f7d08eb392e", 0.0059509641], + ["21f845fa0d6c2", 0.0024451073], + ["22335ebda28b1", 0.0019761284], + ["223b7178ff92d", 0.0015867978], + ["22ca0eccb578d", 0.0095730423], + ["232ae73b2657f", 0.0081994096], + ["23389e6cf5ab3", 0.0005079701], + ["2353f4e14bdff", 0.0007375175], + ["236f64ba5f30c", 0.0029751279], + ["23aa45bf7d599", 0.0000060365], + ["241d9eb08683c", 0.0065027962], + ["243745d42ab7f", 0.0027914247], + ["2453af6c1d255", 0.0026697992], + ["246ce6eb378ca", 0.0055512379], + ["24719021ba503", 0.0079327304], + ["24965483931a0", 0.0020204469], + ["25251acb39ef9", 0.0013094833], + ["2536ad1cc491f", 0.0040614085], + ["2552a0bf89f65", 0.0006805406], + ["256b42fac3b5a", 0.007513148], + ["257213ecfc25c", 0.0062924742], + ["25ecd7f29b666", 0.0055072145], + ["26b28649c03c5", 0.0026733679], + ["26db2d13e53a1", 0.0042753313], + ["26df52a44083d", 0.0026436842], + ["270b9d0de9058", 0.001111284], + ["275557c782042", 0.0054555374], + ["2792fdacb54e6", 0.0000697619], + ["2799be8b51f93", 0.0030075188], + ["27a33b4d4d685", 0.0000389001], + ["27fda03ea4cbe", 0.003288392], + ["284028a0c9266", 0.0009591406], + ["28bac1f5998a9", 0.0019650998], + ["28f85af732846", 0.000077778], + ["29023b0c8da64", 0.0033660967], + ["2992905d78c94", 0.0077942323], + ["29cab9e2a8a62", 0.0028307762], + ["2a6826efb5d71", 0.0094428706], + ["2aa6998ea927f", 0.0099880144], + ["2ab9254955fd6", 0.0041189554], + ["2ad9c05225ce6", 0.0076628352], + ["2afec7bd973f4", 0.0028464078], + ["2b2b7db924ea4", 0.0014253136], + ["2b60cee8f0a68", 0.0023181418], + ["2bc6e7135b3ff", 0.0014667488], + ["2bf8608d101be", 0.0065333856], + ["2c00237200715", 0.0003485171], + ["2c7f4613f3d80", 0.0026299179], + ["2cf1423b0df7b", 0.0012280185], + ["2d3bf7d06879e", 0.0028997274], + ["2d40a61d221ce", 0.0019086155], + ["2db6fcaa0e906", 0.0053344714], + ["2dc1a5f4c6b0b", 0.0074582339], + ["2dd2f41865a99", 0.0030107786], + ["2df266f27a42a", 0.004095675], + ["2e0450600fec0", 0.0085704491], + ["2e36430124037", 0.0030594138], + ["2e46af1e3cb1e", 0.0028192839], + ["2e673ea9f5bce", 0.0002838635], + ["2efe9b59c69b2", 0.0093703148], + ["2f68fc45c3177", 0.0025394891], + ["2fb88607aba21", 0.0000848943], + ["2fbc1409ea8b7", 0.0083263947], + ["2fddc7c67b0c6", 0.0081940347], + ["2ff602497aea9", 0.0002806687], + ["305a228f6c728", 0.001389159], + ["308a5ca8062e7", 0.0008499932], + ["30a7a145f6f99", 0.000040419], + ["3138e40babe62", 0.0039538194], + ["314052df931b9", 0.003031773], + ["316a82c0302df", 0.0048016902], + ["32a8656fb7c20", 0.0066551311], + ["32ab95aa794da", 0.0050643168], + ["32f31144c8b23", 0.0043357614], + ["3384899be91d0", 0.0009836517], + ["338d6267c6937", 0.003499685], + ["33918cba0991d", 0.0070293828], + ["3391cc8ac5069", 0.0091642229], + ["33a0b5214650b", 0.002042734], + ["33a94debfe3e9", 0.0016064773], + ["33da5c1f55645", 0.0065642641], + ["340b27ff751e1", 0.0000282528], + ["34eea34b99b97", 0.0003637422], + ["3503d9aac6df0", 0.0040306328], + ["3510d9e28fc5a", 0.0028449502], + ["3572a89672593", 0.0015893703], + ["35c022ad5b065", 0.0072579475], + ["35c19b7265525", 0.0062593891], + ["35d03a366eacc", 0.0092047128], + ["35d65291ef01b", 0.0004253835], + ["35f03080bdbdf", 0.0011454754], + ["36661de134145", 0.0005461198], + ["369b1963cd24c", 0.0079264426], + ["36d842ca63ba0", 0.006557377], + ["36e5e4e30964b", 0.0060990485], + ["36f476ed1ca78", 0.007003782], + ["37520bba0d274", 0.0003005061], + ["3757cc4217f97", 0.0014732748], + ["3830cb2aae491", 0.0080102531], + ["38624c54772af", 0.0040293335], + ["38bc446dd84f6", 0.007423905], + ["3906a6fc95beb", 0.0093040566], + ["390abc2200031", 0.0007512922], + ["39296319f2b9d", 0.0014096022], + ["3982c34f91ad5", 0.0045077533], + ["3a550d26787cb", 0.0007035911], + ["3a76a8e5abb4a", 0.0009144278], + ["3a93fe7e240a4", 0.007535795], + ["3acdb012eee07", 0.0038197097], + ["3ad6bbcbb421e", 0.0000214727], + ["3b1120325f102", 0.0049202913], + ["3b330a5afe81c", 0.0083963056], + ["3b57ccf743ee6", 0.0063816209], + ["3bd387484ea98", 0.0022421525], + ["3c02bb8d2349b", 0.0039382483], + ["3c252835eac74", 0.0030107786], + ["3c2cca8b53b54", 0.0002271695], + ["3c62ac9cd843d", 0.0001525753], + ["3c8530b714d4a", 0.0027773149], + ["3cda764b62d27", 0.0026126032], + ["3cf341635b79f", 0.009511128], + ["3d3d6c0f2bd4a", 0.0022021581], + ["3d5d4a5da8805", 0.0010958904], + ["3d979a1ca9334", 0.0026719393], + ["3e0b1122cd003", 0.0013200972], + ["3f0ce84ae344e", 0.0076138267], + ["3f1047f0a3d31", 0.0050900947], + ["3f2fed188d699", 0.0001110102], + ["3face2e9ceac6", 0.0022255853], + ["3fbf5e69e8fe4", 0.0038358266], + ["3fc467ca0b8c9", 0.005790388], + ["3fc9b3661acee", 0.00444247], + ["402fe25dff738", 0.0086385625], + ["405a37578657f", 0.0038690706], + ["4083185b442ef", 0.0040617384], + ["40c72b84ae3c0", 0.0025249975], + ["4118bf35dc247", 0.0027753108], + ["4151b8b0d2fd7", 0.0088012674], + ["41769e794d033", 0.0001192842], + ["418345d56125d", 0.0014316392], + ["41bf43db7de60", 0.0084860828], + ["42306a6a84119", 0.0002502477], + ["42a75ed555c51", 0.0007010361], + ["42b21a8764522", 0.0018287553], + ["42b549390a42b", 0.0098990299], + ["42c8a3d06610a", 0.0074063102], + ["42e22576e30f9", 0.0057883769], + ["42e9b136be10e", 0.0055834729], + ["42ec6f3eec5e3", 0.0088214538], + ["43120856ad58f", 0.0004596433], + ["431a1f362210e", 0.0012944649], + ["43481f5c558ea", 0.0011819772], + ["43b426a845a45", 0.0070008401], + ["43c996b66e1f8", 0.0006720159], + ["43e1acf1c1429", 0.0022144471], + ["446d890381336", 0.007082153], + ["446e4f5f3b944", 0.0025376846], + ["44713deed487c", 0.0001899674], + ["44ad2a2f87d1d", 0.0007622067], + ["450e561ff5cf6", 0.0044444444], + ["451b6c68c2c94", 0.0043817369], + ["456e141416511", 0.0035750036], + ["45bc03eb26fa7", 0.0046472721], + ["464e8b330f47f", 0.0067231411], + ["46530ea959cfa", 0.009786651], + ["468bcfbc2fab8", 0.0028635244], + ["46bf01d05948b", 0.0021011052], + ["46d8fe158fb1d", 0.0026248097], + ["46da7a01972c9", 0.0009518914], + ["4790aa14f6a00", 0.0047856049], + ["47cf5338b1ae3", 0.0012962435], + ["487255f17e374", 0.0091759956], + ["48936e830e451", 0.0040919879], + ["48aee75ed43b1", 0.0066462847], + ["490d1ecf59fbc", 0.0022648005], + ["4958fd56d6cc7", 0.0039154268], + ["49c0659672e4a", 0.0055991041], + ["49e9dbc6d25d9", 0.0072516316], + ["4a386a98a7248", 0.0010164048], + ["4acb4ff9a79c0", 0.0004319654], + ["4b307b01f14c1", 0.0004710626], + ["4b4f15c8443e2", 0.0027197563], + ["4b622808e271a", 0.000873515], + ["4b8ee80cfb802", 0.0096955594], + ["4bd915c1213d2", 0.0002105919], + ["4bfd9eaddbf73", 0.00314248], + ["4c62c2799e961", 0.0001433988], + ["4cbf1e712466b", 0.0000114589], + ["4cc833a305397", 0.0002162789], + ["4d21cbf21c024", 0.0010691299], + ["4d564506f339a", 0.0021614144], + ["4d708d6015967", 0.0063710499], + ["4da98d61a2104", 0.006595436], + ["4db98c3d4acba", 0.0090057637], + ["4dbfac108be4a", 0.0048571984], + ["4ddb26a618b86", 0.0060393767], + ["4e012ca2ad6c8", 0.0010041774], + ["4e07c896c5057", 0.0004454978], + ["4e1c32b105fff", 0.000213266], + ["4e913293180d4", 0.0003743047], + ["4e9bf769de26e", 0.0041673612], + ["4ef8157c1fe08", 0.0098522167], + ["4f2d0811599e7", 0.0091190954], + ["4f5b3910be913", 0.0019772224], + ["4fbe87a4d2aeb", 0.0052949275], + ["4fdfbc2c31dd9", 0.000932314], + ["4ffbefa97ce1b", 0.0007034426], + ["501e4702228e7", 0.0005392871], + ["5033e4e9f325b", 0.0084545147], + ["50392db412fa9", 0.0033249102], + ["5063d6beb463b", 0.0021077481], + ["50a086e92850d", 0.0054318305], + ["50a9c1837241b", 0.0063267114], + ["50c4db5a5fb9d", 0.0096618357], + ["50f6caa7e5b14", 0.0025255076], + ["510677ef4194a", 0.0031375502], + ["514c1aef54d4b", 0.0026891841], + ["5177051ec1f63", 0.0009221689], + ["51c52dd58920a", 0.0068287353], + ["51c8a7b704da3", 0.0087997184], + ["5252779c144f1", 0.0018106102], + ["52583bc8ffc13", 0.0073605182], + ["526adb8619f72", 0.0018758207], + ["528cc83dd9685", 0.0040407306], + ["528cf92cbc46c", 0.0017854592], + ["5304df83b2372", 0.0008746611], + ["5306022b121fc", 0.0036616624], + ["531729a6e1efa", 0.0011764983], + ["5336b42c72975", 0.0047344002], + ["5375dfda54f3c", 0.0022482014], + ["5392f692812a3", 0.0095093191], + ["53b8ee86f54b7", 0.0004916469], + ["53d2474e492df", 0.0064441294], + ["53e843c35eaeb", 0.0002834805], + ["53ecc5a71ef36", 0.0008439673], + ["53f8397c785b0", 0.0033660967], + ["5404232acc5b1", 0.0020824656], + ["5420931349e9f", 0.0057997912], + ["54655cddda2a9", 0.0016935948], + ["54817d5561bc3", 0.0022443666], + ["552bbf167d091", 0.0098911968], + ["556629d75792e", 0.002323636], + ["556b31bf9338c", 0.0095987714], + ["556c771d10076", 0.0057398691], + ["55825e3fefb26", 0.0010859178], + ["55b3c80bc6bab", 0.0061440157], + ["5655b2cec5b38", 0.0094002632], + ["5661872c745d5", 0.0005001951], + ["56e3d4bbd2d22", 0.0016142571], + ["578ef331c8f8e", 0.0019733986], + ["57ed9aecb79d1", 0.0000179763], + ["583fe0e968633", 0.0067285695], + ["586504b65cd72", 0.001553567], + ["59322021b109b", 0.0001528215], + ["59444b4fc3baf", 0.0002730584], + ["59594e3a9d6cd", 0.0058268267], + ["599cce5cef9de", 0.0085822176], + ["59a8a39752251", 0.0088292425], + ["59ccd13cebbb4", 0.0010617289], + ["5a567c83f5e30", 0.0023215861], + ["5aaa0fc1b4203", 0.001081385], + ["5b10da29a797c", 0.0087382034], + ["5b6a5ea5c1b01", 0.0094643195], + ["5bbf070547f14", 0.0024797897], + ["5c27ff345b9f4", 0.0040410571], + ["5c3314039f9f0", 0.0009386675], + ["5c754c190a250", 0.006352433], + ["5c763ccf33070", 0.0037072737], + ["5ca18d3224a29", 0.0044271294], + ["5ca2c27a2cb69", 0.0039013733], + ["5ca3e29045478", 0.002403615], + ["5ce31d4732032", 0.0039175742], + ["5cfa40e1efbc0", 0.0091625435], + ["5d067dd6cc57b", 0.0044334102], + ["5d11937514cf8", 0.0049632718], + ["5d4acf85fc93d", 0.004046617], + ["5d4ec99c9215a", 0.0022639801], + ["5d5d74cfbf471", 0.0004427874], + ["5d753856df2a0", 0.0053487377], + ["5d9689311f4e5", 0.0020508614], + ["5dd8a2cf47dde", 0.0061827625], + ["5e4ef0a615d7f", 0.0099068754], + ["5e82a8d1cf663", 0.0001290706], + ["5e99731f76094", 0.0001046174], + ["5ee11a104d5e7", 0.0021777952], + ["5f14d4fa24507", 0.0076126675], + ["5f3d56cc50095", 0.0010704346], + ["5fa6a8a188c30", 0.006027001], + ["5fe794f2db649", 0.0039354585], + ["5ffd4e023800b", 0.0017244352], + ["6035cc5c0a985", 0.0019805118], + ["605f87cc5ee83", 0.0021242247], + ["607560dc75d92", 0.0002195149], + ["610feabe6f200", 0.0059066745], + ["611cc3c3e26e2", 0.0089477452], + ["6126c21d4ff0b", 0.0053005407], + ["61974a5c8bd27", 0.0057703405], + ["61befb43c1a5d", 0.0004603458], + ["61c26ddd8d34d", 0.0089078924], + ["6274a49af234e", 0.0001902435], + ["62ef7195cafe6", 0.000507156], + ["644d26cfe7b19", 0.0041858518], + ["64723b4c2a4c2", 0.0039745628], + ["64ff03e3ac085", 0.0069213732], + ["6572720fb4042", 0.009809692], + ["6618117231a9b", 0.0011553214], + ["662cbd33fd716", 0.0039206461], + ["662e5b245cfd1", 0.0095675469], + ["666e85e692bb1", 0.0069204152], + ["669905d8c741a", 0.0065419338], + ["673ea1a6bff80", 0.0085309674], + ["67405477abadc", 0.0013219819], + ["676eeebd6789d", 0.0001903986], + ["67ba502123a98", 0.000669918], + ["67bb3173716a1", 0.0001127897], + ["67c9f353ae7fb", 0.000473449], + ["67d452b85f693", 0.0056173464], + ["67f403d1d9343", 0.0050505051], + ["67fddb22957e3", 0.002406623], + ["686451ea86b05", 0.0026150628], + ["68697c2764209", 0.0058927519], + ["68948b6b952d9", 0.0026397761], + ["693329de05b4c", 0.0047578266], + ["69375f02a40c1", 0.006424258], + ["694f4eb09d6fe", 0.0097770825], + ["6951976166cb0", 0.0037630767], + ["695c1f8682983", 0.0019496978], + ["69783d7323d52", 0.0008858181], + ["69b4968aa94ae", 0.0002271757], + ["69b9cc2abf57a", 0.000145408], + ["69cf5d4edfa60", 0.0091324201], + ["69d1e7d90bb93", 0.0022867597], + ["6a18500867f23", 0.0099206349], + ["6a239dfc364fa", 0.0013051763], + ["6a2cbafe8d661", 0.0089992801], + ["6a5964d77c99e", 0.0068465014], + ["6a8e6f1c1594f", 0.0002192877], + ["6a95c2cf08aaf", 0.0054818551], + ["6ade3d125a39c", 0.0050797521], + ["6b5540fff40b7", 0.0008434406], + ["6c8c98f26eedd", 0.0065522212], + ["6c9ab8e844961", 0.0002375398], + ["6c9c8a120186d", 0.0002286237], + ["6caac39501714", 0.0040617384], + ["6d368befc143f", 0.0090563304], + ["6d6cd5ff3d2a4", 0.0005924732], + ["6d74949c328be", 0.0005149065], + ["6d96e53bb70c1", 0.0090711176], + ["6e1b90f9671c4", 0.0002215939], + ["6e5343b7f2231", 0.0024390244], + ["6ea9b1538ae30", 0.0081566069], + ["6f18f073a68e3", 0.0042662116], + ["6f8aa27ab1538", 0.0006780672], + ["7053b9f748f6c", 0.0016693933], + ["705a61d235227", 0.0014435014], + ["70707b4cb654f", 0.0083668005], + ["71803bdef1cf7", 0.0015361455], + ["71844f4281f77", 0.0063808065], + ["718746ccdbf11", 0.0085120872], + ["71cbad815ecb9", 0.0090236419], + ["721f6bcc9b3b7", 0.0011349707], + ["73801dfeaf752", 0.005041339], + ["73888c4f005ee", 0.0045989698], + ["738e9b7a7cac5", 0.0042911088], + ["739979295016d", 0.008037293], + ["73c70e178847f", 0.0000575121], + ["7490bac6a8c0b", 0.0003866318], + ["74a43fc1b454f", 0.0011017341], + ["74deff74d535d", 0.0069290466], + ["74fe9f8cd0282", 0.002664535], + ["7545dbffda547", 0.0013230313], + ["7560656cdd26c", 0.0066383431], + ["75641873732c5", 0.0007080348], + ["75e0a49711319", 0.0002101026], + ["75e2721d6e79a", 0.0002709205], + ["76aecb5ceff30", 0.0093353249], + ["76afdd0373c90", 0.0071022727], + ["76f8991a43db4", 0.0006232704], + ["7714445d6c870", 0.0007502101], + ["771cda67954b5", 0.0000140844], + ["774a6375370dd", 0.0009616309], + ["7753f7db987db", 0.0000985109], + ["77652a33810a3", 0.0019412952], + ["77b662c4f129b", 0.0000179763], + ["77fcd1fedb335", 0.0057012543], + ["78572739db8e9", 0.0003774696], + ["78ad7769521d8", 0.0089031339], + ["7912041903ab3", 0.0003005584], + ["793765c5577ac", 0.0098814229], + ["79b175178ee74", 0.0007461016], + ["7a33444cce9c1", 0.0029606821], + ["7a4185191a572", 0.0003523881], + ["7a4d25eced811", 0.0014820963], + ["7a7c191b56aba", 0.0089365505], + ["7adc81b61b082", 0.006094588], + ["7b06a86d5cc94", 0.0079987202], + ["7b299e7c11298", 0.0080788496], + ["7b3d8f8d13015", 0.0090432266], + ["7b64dad0b0af1", 0.000371927], + ["7b6cc21e2f18c", 0.0074638006], + ["7b8c16d6f58e3", 0.0006671203], + ["7bed3689197cc", 0.0088999644], + ["7bed91f62f6b6", 0.0065876153], + ["7c2936364a553", 0.0011106915], + ["7c3f7a6e66f7b", 0.000004519], + ["7ca10a1beb155", 0.0006943866], + ["7cb0c1b56f001", 0.0008248375], + ["7cc6154c1a1ee", 0.0088794175], + ["7cecfb071a148", 0.0018452908], + ["7d391c6a0be37", 0.004657228], + ["7d39b088caa70", 0.0012894574], + ["7d99920421444", 0.0002200627], + ["7defd2bf86568", 0.0044670776], + ["7e07c1a1e8ad0", 0.0094250707], + ["7e9198853c6a4", 0.0097238429], + ["7f278f192837d", 0.0003264709], + ["7f3ba87fe7f72", 0.0045065345], + ["7f56b570745e8", 0.0000433754], + ["7fa86709e77a1", 0.0057123272], + ["800555aa96153", 0.0004996552], + ["801e81028787b", 0.0023337223], + ["8086edc0d7a36", 0.0039280383], + ["80b3281c29df8", 0.0017862884], + ["80be6d6053d1f", 0.0008727984], + ["812c4b9746e42", 0.000177261], + ["813ca17905a7a", 0.0012843895], + ["816a78900286a", 0.0024741452], + ["81794d8d04103", 0.0012724913], + ["81b77c794117d", 0.0039429067], + ["82045947605fa", 0.0050725373], + ["82193844f908e", 0.0085251492], + ["822997a96b9ea", 0.0007595091], + ["8242a96a8ce13", 0.0044642857], + ["8332adf14980e", 0.0048211359], + ["845bd569d3090", 0.0002983952], + ["84e062cd5e636", 0.0019046168], + ["8504adebe56d5", 0.0005924802], + ["852cf89643211", 0.0083208521], + ["853fcb5d15ba6", 0.0081619327], + ["855bd57ebcae7", 0.0074537865], + ["8564324fa7800", 0.0023184642], + ["858ba14988285", 0.0007094312], + ["85ac4bc9a4ba0", 0.0003872487], + ["85c7ed585d7b6", 0.0032314354], + ["85dd831ae1351", 0.0087397308], + ["85f36e2961ce9", 0.0007778953], + ["8672b236b6623", 0.0014389317], + ["86c6b7c955f6d", 0.002179124], + ["86cfe8eb31df0", 0.0010103664], + ["86d82964b5133", 0.0003866438], + ["86f4472b7d0c0", 0.0004129399], + ["8776eaa6a520b", 0.0081116158], + ["8796a17957e68", 0.0059017941], + ["87f40ec7e788e", 0.0056255626], + ["87f71e6ae033a", 0.0063227112], + ["880862343e93a", 0.0083710028], + ["881997e0b1454", 0.0005465257], + ["884fc862f1cb3", 0.0064061499], + ["887a29f07a835", 0.0032603026], + ["89057f7714832", 0.0023832221], + ["89e48a33b9078", 0.0009231224], + ["8a292e825b0e7", 0.0017208742], + ["8a2b775532a98", 0.0064918203], + ["8ac79be5c632f", 0.0023878886], + ["8ae7cbbbf2472", 0.0075976295], + ["8b017c838f807", 0.0007624043], + ["8b235fb6f0fd1", 0.0037285608], + ["8b68ec74a4a7c", 0.0000646731], + ["8b88993074f13", 0.001292023], + ["8bc0c2a0dd6f8", 0.0038916563], + ["8bfe447f1676c", 0.002708559], + ["8c10a4109d402", 0.0020812521], + ["8c26c759d3e2b", 0.0004344539], + ["8c277c5c4417c", 0.0038702686], + ["8c3534d12f797", 0.0001199144], + ["8c4421424bce3", 0.0049995], + ["8c52c803bc92a", 0.0036762003], + ["8c55b74ae5555", 0.0028307762], + ["8caadf88706b0", 0.000280932], + ["8cb23ce82b036", 0.0024488197], + ["8cc1c63c436a4", 0.000040765], + ["8cddded64f168", 0.001814421], + ["8d348af2901d8", 0.0091424392], + ["8d4eb42b94302", 0.0005895531], + ["8d60b53fd93af", 0.0009635954], + ["8d732f6785c22", 0.0059566357], + ["8d75c082eab29", 0.0016885047], + ["8ddfe483245bf", 0.0010058338], + ["8de2f3663ba7d", 0.000342454], + ["8def4e691f3e2", 0.0046455449], + ["8e98f36201aa1", 0.0001794823], + ["8ec55b10a5fd5", 0.0016554647], + ["8ed6a2f58e1e3", 0.0063954976], + ["8ef66b880b347", 0.0005130836], + ["8f2bed3ab2dd3", 0.0004710626], + ["8f37dc5b1f276", 0.0015933716], + ["8f719c307c82a", 0.0094732853], + ["8fb13cafcca4f", 0.0000353801], + ["9032200680020", 0.0050296751], + ["9054be6aa8abd", 0.0086820629], + ["905d466b87db5", 0.0001151965], + ["906737776b849", 0.002494761], + ["909441e3a0ee9", 0.0005757251], + ["9094ec94f050c", 0.0064892927], + ["90a2571364c93", 0.0083977158], + ["90bed08ee0772", 0.0053418803], + ["90d7468055a92", 0.0011993284], + ["91426d2ecaa9d", 0.0015046192], + ["914f4845b5b77", 0.0042488103], + ["919f261b25351", 0.0052443885], + ["91dec511bdcfd", 0.0052548607], + ["91e6e78fd1d96", 0.0006658056], + ["92224fff9a543", 0.0000122068], + ["92abc6c7759f5", 0.0010816658], + ["92f5807e8abb1", 0.0073637703], + ["9339c8374a0b7", 0.0036726899], + ["933dcff4f4675", 0.007583801], + ["936ada24694fb", 0.0000466081], + ["93c78da6885c6", 0.0077243936], + ["93e103b3339ed", 0.0000063254], + ["9421f10627a89", 0.0034539928], + ["94c2dc46f1a2a", 0.0041600799], + ["94c7f82d529e9", 0.0008760556], + ["950219e4df65d", 0.0047906487], + ["9560c477f8ddf", 0.0023519451], + ["95cf20cf0631f", 0.0046533271], + ["9628e9054849c", 0.0051036031], + ["9645fd673bacb", 0.0084430935], + ["967342b61b08e", 0.0023836766], + ["9675c6a386842", 0.0018671347], + ["967895c2828a7", 0.0030330604], + ["9685d79d28ed9", 0.0071367399], + ["96f053cdea8af", 0.0049860391], + ["970275a0faf4c", 0.0000100105], + ["971881711a83f", 0.003925263], + ["9768d6f7942c1", 0.0044891363], + ["97e9737b20468", 0.0074194984], + ["97f3f403ad1a2", 0.0036832413], + ["97f904a8d754f", 0.0066533599], + ["97f9ad181420d", 0.0005750762], + ["987a4ffb6e88b", 0.0001829163], + ["98b0a2d62e6e3", 0.0065419338], + ["98d9bfb6f425c", 0.0057863673], + ["99135da1be624", 0.0074526755], + ["99521294203b2", 0.0048309179], + ["99efb61b1cc7f", 0.0022846699], + ["9a6e5f79f0916", 0.0042098173], + ["9ad85737e1668", 0.0061561192], + ["9add0dfc52112", 0.0059080704], + ["9b532d1e9157c", 0.0076534517], + ["9bdec56db05a4", 0.0009910213], + ["9c5143ae06613", 0.0008917266], + ["9c8a624b2cf04", 0.0078406774], + ["9cbfa05e2fff9", 0.0005332253], + ["9cd461e2c00da", 0.0090432266], + ["9d7dd144ae9fe", 0.0048473097], + ["9d8d554da933f", 0.0024589358], + ["9da5d989bacff", 0.0036295006], + ["9db413e1c96eb", 0.0020346708], + ["9e0d9ad54f19b", 0.0084875233], + ["9e1326b8cbc42", 0.0021147908], + ["9e60e8f359ac6", 0.0009581848], + ["9fa35119914cc", 0.00847745], + ["9fe328ef95eac", 0.0099344327], + ["a00706088e85c", 0.0036161134], + ["a01ca25e856b1", 0.0006144167], + ["a042c3aa93157", 0.0001129721], + ["a05f2de462f56", 0.0090171326], + ["a0742511a79a9", 0.0052659294], + ["a07cfde4caec5", 0.0096024582], + ["a0cddef525f28", 0.0006607202], + ["a14bc26d32383", 0.0070086908], + ["a164c733bebbd", 0.0083822297], + ["a167a2d43ccbb", 0.0043308792], + ["a183bb037139f", 0.0023242841], + ["a1deb0ba00b5a", 0.0055187638], + ["a226560f75ff6", 0.0052854123], + ["a238f853a21e4", 0.000004519], + ["a277322b12253", 0.0004604772], + ["a3266c872fb18", 0.0089206066], + ["a335e13f72579", 0.0071408169], + ["a34ed3a13fa6d", 0.0011955716], + ["a385a999354e6", 0.0021808348], + ["a39e9619a83b3", 0.0015237399], + ["a3a7b3853969c", 0.0082521868], + ["a4014525e60db", 0.0061667489], + ["a42bc6793e651", 0.0049411997], + ["a469a6610b448", 0.0057346026], + ["a522f9961d3fb", 0.0050140393], + ["a53181c450ad9", 0.0023790265], + ["a549cb491625d", 0.0000146558], + ["a55972050bf25", 0.0091340884], + ["a58e2966cdc6b", 0.0036033439], + ["a5b2932769400", 0.0049212598], + ["a5ba98271a250", 0.0002066577], + ["a5c22793e23c7", 0.000767495], + ["a60b9d89fd1e3", 0.0000435776], + ["a62a415e5e888", 0.0018966694], + ["a6a1ac6f8bcbb", 0.0023697806], + ["a6cb75033cddf", 0.0041781566], + ["a6d294c59fd33", 0.0076769538], + ["a732504c087b0", 0.000433422], + ["a7903a395b075", 0.0000394423], + ["a7dc637171a03", 0.0076875769], + ["a80d44d532a2e", 0.0059937665], + ["a828d92492b43", 0.0056053812], + ["a8736c5afbfe2", 0.0000120819], + ["a885552ebd428", 0.0029696502], + ["a8e6680306431", 0.0066943366], + ["a8fd2f790225d", 0.0032560563], + ["a97ad4689560a", 0.0030053495], + ["a98030862e3db", 0.0079339892], + ["a9ada345b837d", 0.0054389209], + ["a9af0632c3c43", 0.001293728], + ["a9b8a7ba08cea", 0.0002298217], + ["a9f2bb24c1d79", 0.0017084088], + ["aa2260b52b714", 0.0034821366], + ["aa306286e380f", 0.0001952103], + ["aa3214921eff9", 0.0068371393], + ["aa476f4a73337", 0.0000402828], + ["ab37aa46ec7fd", 0.0092199889], + ["ab6580dfd4299", 0.0027041644], + ["abcd037e2d888", 0.000044679], + ["acc090216d67a", 0.0037147103], + ["ad0f6266a9cc6", 0.0008996365], + ["ad367a67f60b9", 0.006916586], + ["adb31f9d69ce9", 0.0019963268], + ["adb672f7070b4", 0.0006189574], + ["adc87198685a0", 0.004655927], + ["adffc397320cd", 0.0005948982], + ["ae028acf31df7", 0.0062057838], + ["ae2c2e1f7e594", 0.0087919817], + ["ae34d67851d20", 0.0017569135], + ["aed36fc806281", 0.004044653], + ["af00c24bfd776", 0.0090285302], + ["af3eed436d30b", 0.0084260195], + ["af4f8d67e37fe", 0.0089911886], + ["af71c7e7b54c7", 0.0076840326], + ["afbb7360615bb", 0.0016609088], + ["b06628217b62f", 0.0099720782], + ["b1239981324e0", 0.0064574454], + ["b12406cda376a", 0.0000156384], + ["b1b4412cb17a5", 0.0006818864], + ["b1d7dfc51343b", 0.001201952], + ["b1e46f1b1ccd1", 0.0029895366], + ["b25b29177f2e6", 0.0033595377], + ["b272aac12ed0a", 0.008214227], + ["b28d3732da329", 0.0098677719], + ["b2ae99392b0e1", 0.004623636], + ["b2ba83fb7165e", 0.0072674419], + ["b3283d7dc280b", 0.0005631392], + ["b332c3618b922", 0.0003880632], + ["b355cdaba34e3", 0.0044895394], + ["b3d59622f205d", 0.0011643883], + ["b4554171e1c8c", 0.0091945568], + ["b463d9de4ce2e", 0.0019412199], + ["b46fc97ee323a", 0.0040690104], + ["b566fa874d8e5", 0.0045150804], + ["b587abdeb6f3f", 0.0047723585], + ["b59331c15dc3b", 0.0047646274], + ["b64525b325691", 0.0058740602], + ["b6d5cc32562c4", 0.0032938076], + ["b6e3a42814af3", 0.001551109], + ["b6fd987a56602", 0.0040832993], + ["b734a3f6fa98b", 0.005304477], + ["b78988b290ca0", 0.0059844405], + ["b7b4cca7776b1", 0.009051412], + ["b82c7b98f17de", 0.0005636979], + ["b854bd22fd8fa", 0.0014590872], + ["b8613ea60a1bb", 0.0071664039], + ["b89b2f14cf9af", 0.0090481361], + ["b9abdbf26b2d6", 0.0002679715], + ["b9b0769526195", 0.003122853], + ["b9b42bb0bb0a4", 0.0080489375], + ["b9bc1a4d70bd4", 0.0061117223], + ["b9efab923b66a", 0.0007090992], + ["ba085aa03865d", 0.0007806401], + ["ba19e6a2dbfbf", 0.0021634719], + ["ba5ffd64ef164", 0.0018966694], + ["ba81954f48a3e", 0.0000773243], + ["ba9139bde5e85", 0.0003324954], + ["bab4c45cc6a07", 0.009699321], + ["babe19e662954", 0.0000060365], + ["bb58acb66e42f", 0.0008776395], + ["bb7e673d90115", 0.0049000392], + ["bba4f106033ad", 0.0053039143], + ["bbcfbdc73ce27", 0.001340914], + ["bbd86eb658155", 0.00527037], + ["bccab3484d607", 0.0066693344], + ["bd2098376171e", 0.0069979006], + ["bd2c93fb215ba", 0.0012295888], + ["bd419dd43b152", 0.0015734156], + ["bd753b30bdc01", 0.0014714971], + ["bd831c6bbc611", 0.0052394425], + ["bdbb96e65ae7b", 0.0029824038], + ["be01397e55271", 0.0016325464], + ["be1e02506b83e", 0.0004050452], + ["be5d275f5b43a", 0.0001762953], + ["bedbb222c83d0", 0.0005243344], + ["bedcc10755bf7", 0.000211039], + ["bee29f3326d57", 0.0073303035], + ["bf0e0b79a9903", 0.0002717066], + ["bf158990fcdab", 0.0059901761], + ["bf40ce210f029", 0.002543235], + ["bf450e7dee35e", 0.0063323202], + ["bf50e05eb2a00", 0.0017503938], + ["bfd8759b62d0e", 0.0089798851], + ["bfea82b4ce68b", 0.0018845168], + ["c01f23e194544", 0.0085851648], + ["c02198f15754b", 0.0027501238], + ["c03b78cef4718", 0.0030066146], + ["c0d4c3880da8e", 0.0025412961], + ["c0e9b3839b849", 0.0007619744], + ["c0f48b86f572a", 0.0003043825], + ["c10fb81700587", 0.0034134353], + ["c13643988f8b8", 0.0000196733], + ["c14dfc2b32f08", 0.0082617317], + ["c171510ed5007", 0.0013971554], + ["c1a4ae9979686", 0.0025107964], + ["c1c0b609a61c3", 0.0060731204], + ["c1ca4ede14e9e", 0.000240216], + ["c22add8590d27", 0.0076745971], + ["c2570797697ec", 0.0023745073], + ["c2db57e413fc2", 0.0040889761], + ["c2f8e5420c35c", 0.0015981078], + ["c302c5bc443c0", 0.0058713011], + ["c313096fb3d37", 0.0008165932], + ["c36407c88e00e", 0.0024565196], + ["c4075c846d9e3", 0.0061950192], + ["c421e8412d116", 0.0007506268], + ["c473d5fcefbfb", 0.0018202337], + ["c486b4755bc20", 0.0023001196], + ["c4c73c96c604a", 0.0036689169], + ["c50b3f79ae312", 0.0006020905], + ["c54a009d06308", 0.00558098], + ["c57954f91bfca", 0.0002145232], + ["c5a1d3a84efeb", 0.0014072219], + ["c5ba5e6f060e7", 0.0027028488], + ["c5bff758f50cd", 0.0053682628], + ["c61d8ba7ef4f0", 0.0025635767], + ["c71fc39c3ed72", 0.0035390713], + ["c7313e213eb6c", 0.0005931691], + ["c7543c413dbe2", 0.0055260831], + ["c7d818f7ada4d", 0.0011431707], + ["c802df45b9a65", 0.0000170846], + ["c810f16039078", 0.0070721358], + ["c836615f077aa", 0.0019378343], + ["c849ff3225efb", 0.0024352231], + ["c8887da37cfde", 0.0005598728], + ["c8934c62ca2f8", 0.0000249664], + ["c8a307b1f95d2", 0.0050709939], + ["c906532700d80", 0.0037724461], + ["ca02bb27db748", 0.0096432015], + ["ca5fe19caee6d", 0.0000401854], + ["cad60248552a2", 0.0016604676], + ["caed75c503e83", 0.003548616], + ["cb0d5a94003f2", 0.0010137875], + ["cbb8b79ec8693", 0.0036576445], + ["cc02ea1a9f1b4", 0.0028880032], + ["cc2b9eb7ed92e", 0.0057097179], + ["cc49a108c9f32", 0.0019671873], + ["cc73deb62bb0b", 0.0091257529], + ["cd64859b18118", 0.0002447345], + ["cd898e64fd733", 0.0006617345], + ["cddad0d3ec4c5", 0.0003735944], + ["cdef6e99fd350", 0.0022390399], + ["cdfe17b76a618", 0.0014711507], + ["ce22630dc95ba", 0.0049086982], + ["cec6b721b9f88", 0.0018809721], + ["cef80bfc222a7", 0.0026278446], + ["cefdfa9d0e8f2", 0.00005771], + ["cf1bf5144fc5a", 0.0025732078], + ["cf1e8928a97ce", 0.0050530571], + ["cf90a0f2e5c8c", 0.0029174933], + ["cfa2fc549e8b5", 0.0035218708], + ["cfc704ecfe367", 0.0063195147], + ["cfcb99186df1d", 0.0047492401], + ["d0332f35757c7", 0.0010961307], + ["d048b3291e5db", 0.0006509993], + ["d057a687bd1a5", 0.0058976174], + ["d05e5b2f4a834", 0.0016865682], + ["d0e9d5d502872", 0.0003817202], + ["d10359d23ddd2", 0.0000179775], + ["d10757cf4f77a", 0.0096061479], + ["d116b74a947f8", 0.0022491116], + ["d1259f6168012", 0.0066348195], + ["d14663ad59536", 0.0009526168], + ["d15b62cfdf6e4", 0.0084659668], + ["d185e9d590f1e", 0.0048044585], + ["d1ab1eea88245", 0.0029054564], + ["d1ae637871cb7", 0.0001085812], + ["d1d19ff16555b", 0.0011591246], + ["d218a8d861e1e", 0.0090057637], + ["d2581ea27b52b", 0.0060694343], + ["d27a53de53d8f", 0.0002271767], + ["d2e2096ec2058", 0.0003511236], + ["d30bbf14d9611", 0.0073920757], + ["d36ba9d1ab158", 0.0008941025], + ["d38b5324c3af5", 0.0029832936], + ["d3a28ece4266e", 0.004273139], + ["d3a374fd5c9b1", 0.0005981577], + ["d3b1bf2aebc72", 0.0012392188], + ["d3ec3cd93bd89", 0.0055972238], + ["d3f6005e1d513", 0.0044306602], + ["d43c2c9077e36", 0.0059502559], + ["d44b3f35cd2e2", 0.0084645336], + ["d44b4b9eb145f", 0.0014612192], + ["d4868a5364e97", 0.0027044569], + ["d497988b8899a", 0.0007804573], + ["d4d8b0765fa8d", 0.0008044146], + ["d5860817f5a1c", 0.0011364411], + ["d5bcc135fe2da", 0.0020259319], + ["d5f589be8e8c7", 0.000706544], + ["d626a4ba83a68", 0.0019425019], + ["d67e0f442c44e", 0.0064045088], + ["d690a8b37737c", 0.002825178], + ["d6a067eea088a", 0.0045384406], + ["d6d7a590dbcba", 0.0008895214], + ["d708fe90c4167", 0.0037506564], + ["d71039e84c36f", 0.00450045], + ["d7b3215753229", 0.0009531071], + ["d87b7d4c8a605", 0.0012482213], + ["d8d551f70cf82", 0.0078382192], + ["d8f35d6b6ae79", 0.005279831], + ["d92d91c93b077", 0.009046499], + ["d9378c995a388", 0.0058220773], + ["d95a05e6f8556", 0.0088542589], + ["d9613a756f4f5", 0.009809692], + ["d9f10ce068874", 0.0004808941], + ["da53ef5e8eb30", 0.0012236008], + ["da70a18085b04", 0.00210482], + ["daadeeda5ffff", 0.0073833432], + ["dacc85f47dfd6", 0.0020923128], + ["dad2c096ad6f3", 0.0006300244], + ["db1127e50290f", 0.0038340618], + ["db15472d77c4f", 0.0078752559], + ["db2569380fb8d", 0.000021791], + ["db2955d96380c", 0.0070801473], + ["db47d2a1529f4", 0.0000520616], + ["db908dd21e27c", 0.0003492766], + ["db9c972de0084", 0.0029207314], + ["dc06a7527865b", 0.002174764], + ["dc840e6e5d998", 0.0013199229], + ["dcebbce91a0fe", 0.0013576995], + ["dcfc3fcd20ddc", 0.0020989883], + ["dcfe1a1302221", 0.0034108739], + ["dda7e4b87f2e8", 0.0040633889], + ["de831b3f19acf", 0.0039827943], + ["decb289cb6562", 0.0071736011], + ["decb890526e67", 0.000043043], + ["dedc988cd0647", 0.0023912004], + ["deefce5d1e773", 0.0095474508], + ["df11f075e40ec", 0.008595496], + ["df24139fef2ce", 0.0033503082], + ["df69611e61a6a", 0.0006189498], + ["df7a03e94f40c", 0.0036041231], + ["df93f77369a6c", 0.0005792199], + ["df957c4d3c354", 0.0006904838], + ["dfc7335c8ec3b", 0.0034092459], + ["e0129f365ed68", 0.0057703405], + ["e03f8dc187200", 0.0008749059], + ["e05f1e3ac090c", 0.0057843591], + ["e0d22748c295d", 0.0005484982], + ["e0db69eab9e6e", 0.001261575], + ["e0e9a403104fc", 0.0007085766], + ["e0f74bcec6dd6", 0.0002734437], + ["e104dee8da524", 0.0078308536], + ["e1238f7b893f7", 0.0008258184], + ["e1464ae7dce37", 0.0040170322], + ["e18d1a2bd0ba7", 0.0093075205], + ["e19a835f4b6d6", 0.0000437795], + ["e1b9158dfbfdd", 0.0031539772], + ["e1c1dc23bb06c", 0.0037430753], + ["e1fcdf9325943", 0.0089589679], + ["e21589f1c172b", 0.0012628495], + ["e25cae737597f", 0.0071448985], + ["e2711009a5279", 0.0000239785], + ["e2f6a16eea14b", 0.0015465034], + ["e2f83fc48ab8e", 0.0010564571], + ["e2ffb10363213", 0.0060110604], + ["e31d0834a7555", 0.0022121936], + ["e320d65ecda3e", 0.0044738726], + ["e343a35539266", 0.0012018364], + ["e40c7beaa2a6e", 0.0049835543], + ["e44cf2e694180", 0.0080489375], + ["e44e2cd3a63e6", 0.0053118028], + ["e49c7ee82ad58", 0.0004736777], + ["e4d9a1057655a", 0.0005781951], + ["e4f298a792bbe", 0.0042662116], + ["e548243e9312a", 0.0001123611], + ["e5c629c9b9158", 0.0032016392], + ["e5d2f18919b2e", 0.0044980209], + ["e5d73004887c0", 0.0038381822], + ["e5eb5e01f35ad", 0.0000146556], + ["e5ffe236b6da0", 0.001898614], + ["e62cb1e679710", 0.0075987842], + ["e63c26af806ec", 0.0073238611], + ["e666ed7261d93", 0.0000239717], + ["e672efa495096", 0.0058180126], + ["e6ff04d985526", 0.0021053518], + ["e72fb1137640d", 0.0002490524], + ["e74db9592940a", 0.0067294751], + ["e75825b388368", 0.0015139587], + ["e772443005975", 0.0068643602], + ["e7ecacedfd3d3", 0.0088198977], + ["e82d4a32fcf0c", 0.0093214019], + ["e89bfdf5f5429", 0.001203833], + ["e8e28ee21e0e0", 0.0053356099], + ["e92627ca989e8", 0.0039007645], + ["e95d7f746a0e2", 0.000556254], + ["e99ea3d0ff7ad", 0.00975039], + ["e9fcddb94a1e7", 0.0078988942], + ["ea0c8b2ceb6f1", 0.0064366632], + ["ea567a9bf7d1a", 0.0010261251], + ["ea5b3a489fc3a", 0.0008151022], + ["ea60b07745134", 0.0003759964], + ["ea713362b606d", 0.0022253872], + ["ea823b441843d", 0.002971415], + ["ea8569470e211", 0.0010519893], + ["eabe3fb8cb5ff", 0.0029408305], + ["eb4fa232d56a2", 0.0002140668], + ["eb5aa8bec4f8f", 0.0008447373], + ["ebf5aa0c5ca68", 0.003037298], + ["ec0baec3ecd5e", 0.0018092998], + ["ec30e5838603f", 0.0001093917], + ["ed589cce7a900", 0.001771542], + ["ed6425c64721a", 0.0034234851], + ["ed66d19d43640", 0.0052290316], + ["edb5ae7480ae1", 0.0006951976], + ["edc3b8fcf3139", 0.0000060365], + ["edd314a51f359", 0.0063435676], + ["eeaee04553399", 0.0014908462], + ["eebed162f4c7b", 0.0086986778], + ["ef02b06774b12", 0.0020763257], + ["ef172e4298a17", 0.0048933255], + ["ef2eaf711c115", 0.0049005195], + ["ef3aae08eaac0", 0.0007271987], + ["ef8fb9c14723e", 0.0022760379], + ["efd35c98b877a", 0.0009930092], + ["eff0302104cdb", 0.0031611557], + ["f04d9fd7a2183", 0.0006102994], + ["f0f55355c774f", 0.0001182444], + ["f0fb0948d158d", 0.0075551526], + ["f1071e1df5456", 0.0014397604], + ["f120b0460192e", 0.0017488632], + ["f1255b18014b8", 0.001143406], + ["f13611d627602", 0.0014298379], + ["f17c57a740752", 0.0045812718], + ["f18375e76d2f4", 0.0098405826], + ["f1ee6541ef3c1", 0.0000596707], + ["f2c1b0e719962", 0.0005466811], + ["f32b51091b4d4", 0.0043971506], + ["f384673f456fa", 0.0041507554], + ["f3937b91343eb", 0.0075063804], + ["f3b57862d539c", 0.0048412084], + ["f404ac0b7239a", 0.0000063085], + ["f48b3870abf4f", 0.0006873986], + ["f4c998dee64c1", 0.0012639988], + ["f53031affbbba", 0.0002919128], + ["f533503216630", 0.003609066], + ["f5e5fd5d03887", 0.0030688026], + ["f600358540f94", 0.0055487737], + ["f62f5fd48573a", 0.000196687], + ["f6c790f28e47b", 0.0083208521], + ["f717d99d7a71e", 0.0004581985], + ["f724016de3087", 0.0080671184], + ["f7392211db3fa", 0.0010181226], + ["f75428a477fdc", 0.0009552558], + ["f7a61284f73a5", 0.005049485], + ["f7cd6cb934989", 0.0029255164], + ["f88c02b2a4825", 0.0020134498], + ["f9194386899ae", 0.0092438528], + ["f928c4579616b", 0.0000237057], + ["f95dfd0826fe1", 0.0013721186], + ["f96abdb399cdd", 0.0055997312], + ["f9b3405a4f1cf", 0.0049805758], + ["fa2eccb543353", 0.0026577367], + ["fa4742608f72e", 0.0076440911], + ["fad0dcdd64bf8", 0.0098814229], + ["fae8558ea0e03", 0.0089911886], + ["fb82d7509a2a9", 0.0049509852], + ["fbb0a3226810e", 0.0002074706], + ["fbdff42000a79", 0.0034814093], + ["fbe21707a3635", 0.0027516372], + ["fbe4fb31998e4", 0.0058261478], + ["fbec35818dd31", 0.0069979006], + ["fc78bd6c18a2f", 0.0059467174], + ["fc7e1b877d697", 0.0048309179], + ["fc97b4cf0978d", 0.0003413086], + ["fce999870e72d", 0.0059537985], + ["fd5af06c3495c", 0.0000223405], + ["fd6c5c62d4d64", 0.0001429425], + ["fd8cbc7c58702", 0.0019025151], + ["fded1f6505b0b", 0.006090134], + ["fe0d90f11aea0", 0.0014620311], + ["fe13a98b4e724", 0.0039178812], + ["fe144b291de20", 0.0095474508], + ["fe563d13bd338", 0.0008450085], + ["fe6ca72c22fd7", 0.002442241], + ["fe92fdb7711a0", 0.0034078517], + ["feaecc1641bc5", 0.0009393729], + ["fec5c7d5c6609", 0.0018399264], + ["ff04be83dd9db", 0.0006534923], + ["ff22af01bcb21", 0.0043702474], + ["ff387a807b325", 0.0081726054], + ["ff524d68000cf", 0.0038834951], + ["ff671cb178cf8", 0.0059460102], + ["ffb55e06514df", 0.0060052847], + ["ffe34b035b4a4", 0.0041511], + ["fff6cad2c4e19", 0.0053931615], +]); + +// Channel multipliers to maintain ~100 samples per hash across channels +const CHANNEL_MULTIPLIERS = { + release: 1, + beta: 100, + nightly: 100, + esr: 1, + default: 1, +}; + +export const CANVAS_HASH_LENGTH = 13; + +export function getHashProbability(hash) { + const base = BASE_CANVAS_HASH_PROBABILITIES.get(hash); + if (base === undefined) { + return undefined; + } + const channel = Services.appinfo.defaultUpdateChannel; + const multiplier = + CHANNEL_MULTIPLIERS[channel] ?? CHANNEL_MULTIPLIERS.default; + return Math.min(1.0, base * multiplier); +} + +export function isKnownHash(hash) { + return BASE_CANVAS_HASH_PROBABILITIES.has(hash); +} + +// Exported for testing - use isKnownHash/getHashProbability for production code +export { BASE_CANVAS_HASH_PROBABILITIES as CANVAS_HASH_PROBABILITIES }; diff --git a/toolkit/components/resistfingerprinting/UserCharacteristicsPageService.sys.mjs b/toolkit/components/resistfingerprinting/UserCharacteristicsPageService.sys.mjs index 90344766332fc..ee6645bad3f1b 100644 --- a/toolkit/components/resistfingerprinting/UserCharacteristicsPageService.sys.mjs +++ b/toolkit/components/resistfingerprinting/UserCharacteristicsPageService.sys.mjs @@ -3,6 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at https://mozilla.org/MPL/2.0/. */ +/* global CompressionStream */ + const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { @@ -71,6 +73,8 @@ export class UserCharacteristicsPageService { } this._initialized = true; this.handledErrors = []; + // Needed to collect canvas renderings from two different places for unified filtering + this.allCanvasData = new Map(); } shutdown() {} @@ -206,18 +210,53 @@ export class UserCharacteristicsPageService { } } + // After all populate functions complete, apply unified canvas filtering + // This is where ALL canvas data (Canvas 2D + WebGL) is filtered together + try { + await this.filterAndPopulateAllCanvasData(); + } catch (e) { + const error = `filterAndPopulateAllCanvasData: ${await stringifyError( + e + )}`; + errors.push(error); + lazy.console.debug(error); + } + errors.push(...this.handledErrors); Glean.characteristics.jsErrors.set(JSON.stringify(errors)); } + // Compress strings that are all the same repeated character + // e.g., "AAAAAAA" (length 7) becomes "[A * 7]" + compressRepeatedChars(value) { + if (typeof value !== "string" || value.length < 10) { + return value; + } + const firstChar = value[0]; + if (value.split("").every(c => c === firstChar)) { + return `[${firstChar} * ${value.length}]`; + } + return value; + } + async collectGleanMetricsFromMap( data, { prefix = "", suffix = "", operation = "set" } = {} ) { const entries = data instanceof Map ? data.entries() : Object.entries(data); for (const [key, value] of entries) { - Glean.characteristics[prefix + key + suffix][operation](value); + const metricName = prefix + key + suffix; + const processedValue = this.compressRepeatedChars(value); + try { + Glean.characteristics[metricName][operation](processedValue); + } catch (e) { + lazy.console.error( + `ERROR setting metric "${metricName}" (prefix: "${prefix}", key: "${key}", suffix: "${suffix}"):`, + e + ); + throw e; + } } } @@ -334,6 +373,325 @@ export class UserCharacteristicsPageService { await promise.then(data => this.collectGleanMetricsFromMap(data)); } + async filterAndPopulateAllCanvasData() { + // Apply unified filtering to all canvas data (Canvas 2D + WebGL) + // This sees ALL canvas data at once before populating any Glean metrics + lazy.console.debug( + `Applying unified filtering to all canvas data (${this.allCanvasData.size} entries)` + ); + + const filteredCanvasData = await this.filterAllCanvasRawData( + this.allCanvasData + ); + + // Populate all canvas metrics with filtered data + this.collectGleanMetricsFromMap(filteredCanvasData); + } + + // This function is different from above to allow us to return early in + // certain circumstances. After we return we still need to populate the Glean + // metrics, so we do this in a wrapper function + async filterAllCanvasRawData(allCanvasData) { + // Check if we should skip compression (test mode) + const skipCompression = lazy.Preferences.get( + "toolkit.telemetry.user_characteristics_ping.test_skip_compression", + false + ); + + // Compress all raw data and cache both sizes and compressed data + const compressedData = new Map(); // key -> { size, data (base64) } + + lazy.console.debug("Raw canvas data sizes:"); + for (const [key, value] of allCanvasData.entries()) { + if (key.endsWith("Raw")) { + const size = value ? value.length : 0; + + let compressedSize = 0; + let compressedBase64 = value; // Default to original if compression fails/skipped + if (value && !skipCompression) { + try { + const encoder = new TextEncoder(); + const bytes = encoder.encode(value); + const cs = new CompressionStream("gzip"); + const writer = cs.writable.getWriter(); + writer.write(bytes); + writer.close(); + + const reader = cs.readable.getReader(); + const chunks = []; + while (true) { + const { done, value: chunk } = await reader.read(); + if (done) { + break; + } + chunks.push(chunk); + } + + // Combine chunks into single Uint8Array + const totalLength = chunks.reduce((acc, c) => acc + c.length, 0); + const compressed = new Uint8Array(totalLength); + let offset = 0; + for (const chunk of chunks) { + compressed.set(chunk, offset); + offset += chunk.length; + } + + // Convert to base64 for storage in Glean + compressedBase64 = btoa(String.fromCharCode(...compressed)); + compressedSize = compressedBase64.length; + } catch (e) { + lazy.console.debug(` Error compressing ${key}: ${e}`); + compressedSize = size; // Fall back to uncompressed size + compressedBase64 = value; + } + } else if (skipCompression) { + compressedSize = size; + } + + // Cache the compressed size and data for later use + compressedData.set(key, { + size: compressedSize, + data: compressedBase64, + }); + + lazy.console.debug( + ` ${key}: ${size} bytes (compressed: ${compressedSize} bytes, ${((compressedSize / size) * 100).toFixed(1)}%)` + ); + } + } + + // ----------------------------------------------------------- + // First go through and decide what we want to keep based on the value + // and the collect probability. + + // Check if we should ignore probability filtering + const ignoreProbability = lazy.Preferences.get( + "toolkit.telemetry.user_characteristics_ping.ignore_canvas_probability", + false + ); + + // Import canvas hash lookup functions and length + const { isKnownHash, getHashProbability, CANVAS_HASH_LENGTH } = + ChromeUtils.importESModule( + "resource://gre/modules/CanvasHashData.sys.mjs" + ); + + // Iterate through all canvas metrics (1-13) for both HW and SW + // Use camelCase naming to match Glean conventions + const canvasMetrics = [ + "canvasdata1", + "canvasdata2", + "canvasdata3", + "canvasdata4", + "canvasdata5", + "canvasdata6", + "canvasdata7", + "canvasdata8", + "canvasdata9", + "canvasdata10", + "canvasdata11Webgl", + "canvasdata12Fingerprintjs1", + "canvasdata13Fingerprintjs2", + ]; + + const variants = [ + { key: "", suffix: "" }, // HW + { key: "Software", suffix: "Software" }, // SW + ]; + + for (const metric of canvasMetrics) { + for (const variant of variants) { + // Construct the key names (all camelCase) + // Examples: + // - canvasdata1, canvasdata1Software + // - canvasdata11Webgl, canvasdata11WebglSoftware + // - canvasdata12Fingerprintjs1, canvasdata12Fingerprintjs1Software + const hashKey = metric + variant.suffix; + const rawKey = hashKey + "Raw"; + + // Check if this raw data exists + if (!allCanvasData.has(rawKey)) { + continue; + } + + // Get the hash value + const hash = allCanvasData.get(hashKey); + if (!hash) { + // No hash, remove the raw data + allCanvasData.delete(rawKey); + continue; + } + + // Determine if we should keep this raw data based on probability + // Use substring of hash for comparison (trimmed hash) + const hashSubstring = + CANVAS_HASH_LENGTH > 0 && hash.length >= CANVAS_HASH_LENGTH + ? hash.substring(0, CANVAS_HASH_LENGTH) + : hash; + + const buf = new Uint32Array(1); + crypto.getRandomValues(buf); + const rand = buf[0] / 0x100000000; // [0,1) + + let shouldKeep; + if (isKnownHash(hashSubstring)) { + // Known hash - sample using cryptographically secure randomness + // getHashProbability applies channel-specific multiplier + const probability = getHashProbability(hashSubstring); + shouldKeep = rand < probability; + } else { + // Unknown hash - use 1/10 sampling rate + shouldKeep = rand < 1 / 10; + } + + if (ignoreProbability) { + if (!shouldKeep) { + lazy.console.debug( + `Canvas data ${hashKey} would have been excluded (probability filter), but keeping due to ignore_canvas_probability pref` + ); + } + shouldKeep = true; + } else if (!shouldKeep) { + lazy.console.debug( + `Canvas data ${hashKey} excluded by probability filter (hash: ${hashSubstring})` + ); + } + + if (!shouldKeep) { + allCanvasData.delete(rawKey); + } + } + } + + // ----------------------------------------------------------- + // Collect all raw data keys with their cached compressed sizes for budget filtering + const rawDataEntries = []; + for (const [key, value] of allCanvasData.entries()) { + if (key.endsWith("Raw")) { + if (!value) { + continue; + } + + // Use cached compressed data from earlier compression + const cached = compressedData.get(key); + const compressedSize = cached?.size || value.length; + + rawDataEntries.push({ + key, + size: compressedSize, + uncompressedSize: value.length, + }); + } + } + + if (rawDataEntries.length === 0) { + return allCanvasData; // No raw data to filter + } + + const totalUncompressed = rawDataEntries.reduce( + (sum, e) => sum + e.uncompressedSize, + 0 + ); + const totalCompressed = rawDataEntries.reduce((sum, e) => sum + e.size, 0); + lazy.console.debug( + `Found ${rawDataEntries.length} raw canvas entries (Canvas 2D + WebGL), ` + + `uncompressed: ~${Math.round(totalUncompressed / 1024)}KB, ` + + `compressed: ~${Math.round(totalCompressed / 1024)}KB ` + + `(${((totalCompressed / totalUncompressed) * 100).toFixed(1)}%)` + ); + + // ----------------------------------------------------------- + // Budget: ~170KB total for ALL raw canvas data (Canvas 2D + WebGL) + // TODO: Subject to change + const MAX_BUDGET_BYTES = 170 * 1024; + + // Priority algorithm: + // 1. canvasdata01 (if doesn't match, include it - prioritize software over hardware) + // 2. canvasdata02 (same logic) + // 3. canvasdata09 and canvasdata10 + // 4. Remaining images picked at random + + const getBaseName = key => { + // Extract base name: "canvasdata1Raw" -> "canvasdata1" + // "canvasdata1SoftwareRaw" -> "canvasdata1" + // "canvasdata11WebglRaw" -> "canvasdata11Webgl" + // "canvasdata11WebglSoftwareRaw" -> "canvasdata11Webgl" + return key.replace(/Raw$/, "").replace(/Software$/, ""); + }; + + const isSoftware = key => key.includes("Software"); + + // Map to store random priorities for non-priority canvases + const randomPriorities = new Map(); + + const getPriority = key => { + const baseName = getBaseName(key); + const soft = isSoftware(key); + + // Priority 0-1: canvasdata1 (software first, then hardware) + if (baseName === "canvasdata1") { + return soft ? 0 : 1; + } + // Priority 2-3: canvasdata2 (software first, then hardware) + if (baseName === "canvasdata2") { + return soft ? 2 : 3; + } + // Priority 4-5: canvasdata9 (software first, then hardware) + if (baseName === "canvasdata9") { + return soft ? 4 : 5; + } + // Priority 6-7: canvasdata10 (software first, then hardware) + if (baseName === "canvasdata10") { + return soft ? 6 : 7; + } + // Priority 8+: All others - use random value for shuffling + if (!randomPriorities.has(key)) { + randomPriorities.set(key, 8 + Math.random()); + } + return randomPriorities.get(key); + }; + + // Sort by priority + rawDataEntries.sort((a, b) => { + const priorityA = getPriority(a.key); + const priorityB = getPriority(b.key); + return priorityA - priorityB; + }); + + // Apply budget by removing lowest-priority items + // Use compressed sizes since we store compressed data in the ping + let totalSize = rawDataEntries.reduce((sum, e) => sum + e.size, 0); + const keysToRemove = []; + + while (totalSize > MAX_BUDGET_BYTES && rawDataEntries.length) { + const removed = rawDataEntries.pop(); // Remove lowest priority + keysToRemove.push(removed.key); + totalSize -= removed.size; + } + + // Build result map with compressed data replacing raw data + const result = new Map(allCanvasData); + + // Remove entries that exceeded budget + for (const key of keysToRemove) { + result.delete(key); + lazy.console.debug(`Budget exceeded, removing: ${key}`); + } + + // Replace remaining raw data with compressed versions + for (const [key, cached] of compressedData.entries()) { + if (result.has(key) && cached?.data) { + result.set(key, cached.data); + } + } + + lazy.console.debug( + `Budget filtering complete: kept ${rawDataEntries.length} entries, ` + + `removed ${keysToRemove.length}, total compressed size: ~${Math.round(totalSize / 1024)}KB` + ); + return result; + } + async populateCanvasData() { const actorName = "UserCharacteristicsCanvasRendering"; ChromeUtils.registerWindowActor(actorName, { @@ -469,15 +827,24 @@ export class UserCharacteristicsPageService { this.handledErrors.push(result.error); } - // We may have HW + SW, or only SW rendered canvases - populate the metrics with what we have - this.collectGleanMetricsFromMap(data.get("renderings") ?? {}); - Glean.characteristics.canvasDpr.set(data.get("dpr") ?? ""); + // Store Canvas 2D data for unified filtering later + // Don't populate Glean yet - wait for unified filtering + const renderings = data.get("renderings"); + if (renderings) { + for (const [key, value] of renderings.entries()) { + this.allCanvasData.set(key, value); + } + } + + // Store DPR for later population + this.allCanvasData.set("canvasDpr", data.get("dpr") ?? ""); ChromeUtils.unregisterWindowActor(actorName); // Record the errors - if (data.get("errors")?.length) { - this.handledErrors.push(...data.get("errors")); + const errors = data.get("errors"); + if (errors?.length) { + this.handledErrors.push(...errors); } } @@ -615,16 +982,29 @@ export class UserCharacteristicsPageService { } async populateMappableData(data) { - // We set data from usercharacteristics.js - // We could do Object.keys(data), but this - // is more explicit and provides better - // readability and control. + // Store WebGL canvas data for unified filtering later + // Don't populate WebGL metrics yet - wait for unified filtering + // Content script keys are already in camelCase format matching filtering logic + const webglKeys = [ + "canvasdata11Webgl", + "canvasdata11WebglSoftware", + "canvasdata11WebglRaw", + "canvasdata11WebglSoftwareRaw", + ]; + + for (const key of webglKeys) { + if (data.has(key)) { + this.allCanvasData.set(key, data.get(key)); + } + } + + // We set non-canvas data from usercharacteristics.js // Keys must match to data returned from // usercharacteristics.js and the metric defined + // Note: WebGL canvas data keys (hash and raw) are NOT included here - + // they go through filterAndPopulateAllCanvasData for unified filtering const metrics = { set: [ - "canvasdata11Webgl", - "canvasdata11Webglsoftware", "voicesCount", "voicesLocalCount", "voicesDefault", @@ -660,6 +1040,8 @@ export class UserCharacteristicsPageService { "mathml9", "mathml10", "monochrome", + "cssSystemColors", + "cssSystemFonts", "oscpu", "pdfViewer", "platform", @@ -1216,3 +1598,6 @@ function isValidRemoteType(sanitizedRemoteType) { lazy.ProcessType.kFallback ); } + +// Export constants for testing +export const MAX_CANVAS_RAW_DATA_BUDGET_BYTES = 170 * 1024; diff --git a/toolkit/components/resistfingerprinting/content/usercharacteristics.html b/toolkit/components/resistfingerprinting/content/usercharacteristics.html index ff98f377ed325..0b2b99eecdf51 100644 --- a/toolkit/components/resistfingerprinting/content/usercharacteristics.html +++ b/toolkit/components/resistfingerprinting/content/usercharacteristics.html @@ -52,7 +52,7 @@

WebGL Canvas

class="testcanvas" width="250" height="250" - id="glcanvassoftware" + id="glcanvasSoftware" > diff --git a/toolkit/components/resistfingerprinting/content/usercharacteristics.js b/toolkit/components/resistfingerprinting/content/usercharacteristics.js index 012538b91b497..68996d748b011 100644 --- a/toolkit/components/resistfingerprinting/content/usercharacteristics.js +++ b/toolkit/components/resistfingerprinting/content/usercharacteristics.js @@ -143,7 +143,7 @@ function populateWebGLCanvases(contextOptions = {}) { // with some minor modifications const data = {}; - const suffix = contextOptions.forceSoftwareRendering ? "software" : ""; + const suffix = contextOptions.forceSoftwareRendering ? "Software" : ""; // -------------------------------------------------------------------- // initBuffers @@ -453,6 +453,9 @@ function populateWebGLCanvases(contextOptions = {}) { pixels ); data["canvasdata11Webgl" + suffix] = sha1Uint8Array(pixels); + data["canvasdata11Webgl" + suffix + "Raw"] = btoa( + String.fromCharCode.apply(null, pixels) + ); return data; } @@ -771,6 +774,120 @@ async function populateCSSQueries() { }; } +async function populateCSSSystemColors() { + const systemColors = [ + "Canvas", + "CanvasText", + "LinkText", + "VisitedText", + "ActiveText", + "ButtonFace", + "ButtonText", + "ButtonBorder", + "Field", + "FieldText", + "Highlight", + "HighlightText", + "SelectedItem", + "SelectedItemText", + "AccentColor", + "AccentColorText", + "Mark", + "MarkText", + "GrayText", + "ActiveBorder", + "ActiveCaption", + "AppWorkspace", + "Background", + "ButtonShadow", + "InactiveBorder", + "InactiveCaption", + "InactiveCaptionText", + "InfoBackground", + "InfoText", + "Menu", + "MenuText", + "Scrollbar", + "ThreeDDarkShadow", + "ThreeDFace", + "ThreeDHighlight", + "ThreeDLightShadow", + "ThreeDShadow", + "Window", + "WindowFrame", + "WindowText", + ]; + + const rgbToHex = rgb => { + const match = rgb.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/); + if (!match) { + return rgb; + } + const [, r, g, b] = match; + return [r, g, b] + .map(x => parseInt(x, 10).toString(16).padStart(2, "0")) + .join("") + .toUpperCase(); + }; + + const div = document.createElement("div"); + document.body.appendChild(div); + + const results = []; + for (const colorName of systemColors) { + div.style.backgroundColor = colorName; + const computed = getComputedStyle(div).backgroundColor; + results.push({ [colorName]: rgbToHex(computed) }); + } + + document.body.removeChild(div); + + return { + cssSystemColors: JSON.stringify(results), + }; +} + +async function populateCSSSystemFonts() { + const systemFonts = [ + "caption", + "icon", + "menu", + "message-box", + "small-caption", + "status-bar", + "serif", + "sans-serif", + "monospace", + "cursive", + "fantasy", + "system-ui", + "Arial", + "Helvetica", + "Times New Roman", + "Courier New", + "Verdana", + "Georgia", + ]; + + const div = document.createElement("div"); + div.textContent = "Test"; + document.body.appendChild(div); + + const results = []; + for (const fontName of systemFonts) { + div.style.fontFamily = fontName; + const computed = getComputedStyle(div); + const value = computed.fontSize + " " + computed.fontFamily; + results.push({ [fontName]: value }); + } + + document.body.removeChild(div); + + return { + cssSystemFonts: JSON.stringify(results), + }; +} + async function populateNavigatorProperties() { return { oscpu: navigator.oscpu, @@ -863,7 +980,16 @@ async function populateICEFoundations() { }) .catch(reject); - return promise; + // Add timeout to prevent hanging indefinitely + const timeout = setTimeout(() => { + pc.close(); + resolve(result); + }, 5000); + + return promise.then(res => { + clearTimeout(timeout); + return res; + }); } // Run get candidates multiple times to see if foundation order changes @@ -982,18 +1108,35 @@ async function populateMathML() { async function populateAudioDeviceProperties() { const ctx = new AudioContext(); - await ctx.resume(); + + try { + // Add a timeout to prevent hanging indefinitely if the user has no audio hardware + await Promise.race([ + ctx.resume(), + new Promise((_, reject) => + setTimeout( + () => reject(new Error("AudioContext.resume() timeout")), + 5000 + ) + ), + ]); + } catch (e) { + throw new Error( + "AudioContext.resume error, probably a timeout, user may not have audio hardware" + ); + } // Give firefox some time to calculate latency await new Promise(resolve => setTimeout(resolve, 2000)); // All the other properties (min/max decibels, smoothingTimeConstant, // fftSize, frequencyBinCount, baseLatency) are hardcoded. - return { + const result = { audioFrames: ctx.outputLatency * ctx.sampleRate, audioRate: ctx.sampleRate, audioChannels: ctx.destination.maxChannelCount, }; + return result; } async function populateTimezoneWeb() { @@ -1077,6 +1220,8 @@ async function startPopulating() { populateSensorInfo, populateMathML, populateCSSQueries, + populateCSSSystemColors, + populateCSSSystemFonts, populateNavigatorProperties, populateAudioDeviceProperties, populateTimezoneWeb, diff --git a/toolkit/components/resistfingerprinting/metrics.yaml b/toolkit/components/resistfingerprinting/metrics.yaml index 75e2c2f1c4f98..d9e048020e6d4 100644 --- a/toolkit/components/resistfingerprinting/metrics.yaml +++ b/toolkit/components/resistfingerprinting/metrics.yaml @@ -1204,7 +1204,7 @@ characteristics: data_sensitivity: - technical - canvasdata1software: + canvasdata1_software: type: string description: > The sha1 hash of an image rendered on a canvas. The image is a simple organge box and used as a control image @@ -1222,7 +1222,7 @@ characteristics: data_sensitivity: - technical - canvasdata2software: + canvasdata2_software: type: string description: > The sha1 hash of an image rendered on a canvas. The image is a bordered triage, and used to test point interpolation @@ -1240,7 +1240,7 @@ characteristics: data_sensitivity: - technical - canvasdata3software: + canvasdata3_software: type: string description: > The sha1 hash of an image rendered on a canvas. The image is a stretched photographic image, used to test image operations. @@ -1258,7 +1258,7 @@ characteristics: data_sensitivity: - technical - canvasdata4software: + canvasdata4_software: type: string description: > The sha1 hash of an image rendered on a canvas. The image is two rotated, semi-transparenct overlapping squares, used to test transparency and point interpolation. @@ -1276,7 +1276,7 @@ characteristics: data_sensitivity: - technical - canvasdata5software: + canvasdata5_software: type: string description: > The sha1 hash of an image rendered on a canvas. The image is a local font rendered normally. @@ -1294,7 +1294,7 @@ characteristics: data_sensitivity: - technical - canvasdata6software: + canvasdata6_software: type: string description: > The sha1 hash of an image rendered on a canvas. The image is a local font rendered with italics, rotation, and shadow-blur. @@ -1312,7 +1312,7 @@ characteristics: data_sensitivity: - technical - canvasdata7software: + canvasdata7_software: type: string description: > The sha1 hash of an image rendered on a canvas. The image is a system-ui font rendered normally. @@ -1330,7 +1330,7 @@ characteristics: data_sensitivity: - technical - canvasdata8software: + canvasdata8_software: type: string description: > The sha1 hash of an image rendered on a canvas. The image is a system-ui font rendered with italics, rotation, and shadow-blur. @@ -1348,7 +1348,7 @@ characteristics: data_sensitivity: - technical - canvasdata9software: + canvasdata9_software: type: string description: > The sha1 hash of an image rendered on a canvas. The image is a font shipped with Firefox rendered normally. @@ -1366,7 +1366,7 @@ characteristics: data_sensitivity: - technical - canvasdata10software: + canvasdata10_software: type: string description: > The sha1 hash of an image rendered on a canvas. The image is a font shipped with Firefox rendered with italics, rotation, and shadow-blur. @@ -1384,7 +1384,7 @@ characteristics: data_sensitivity: - technical - canvasdata11_webglsoftware: + canvasdata11_webgl_software: type: string description: > The sha1 hash of an image rendered on a WebGL canvas (instead of Canvas2D). IT is a RGB gradient cube. @@ -1402,7 +1402,7 @@ characteristics: data_sensitivity: - technical - canvasdata12_fingerprintjs1software: + canvasdata12_fingerprintjs1_software: type: string description: > The sha1 hash of an image rendered on a canvas, it is a copy of fingerprintjs' text canvas @@ -1420,7 +1420,7 @@ characteristics: data_sensitivity: - technical - canvasdata13_fingerprintjs2software: + canvasdata13_fingerprintjs2_software: type: string description: > The sha1 hash of an image rendered on a canvas, it is a copy of fingerprintjs' geometry canvas @@ -1438,6 +1438,578 @@ characteristics: data_sensitivity: - technical + canvasdata1_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata1 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata1_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata1 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata2_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata2 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata2_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata2 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata3_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata3 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata3_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata3 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata4_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata4 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata4_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata4 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata5_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata5 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata5_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata5 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata6_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata6 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata6_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata6 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata7_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata7 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata7_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata7 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata8_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata8 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata8_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata8 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata9_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata9 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata9_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata9 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata10_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata10 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata10_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata10 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata11_webgl_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata11_webgl rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata11_webgl_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata11_webgl software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata12_fingerprintjs1_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata12_fingerprintjs1 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata12_fingerprintjs1_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata12_fingerprintjs1 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata13_fingerprintjs2_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata13_fingerprintjs2 rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + canvasdata13_fingerprintjs2_software_raw: + type: text + description: > + Gzip-compressed, base64-encoded raw pixel data from canvasdata13_fingerprintjs2 software rendering + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1894958 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1900693 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2005867 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + canvas_dpr: type: string description: > @@ -3987,6 +4559,55 @@ characteristics: data_sensitivity: - technical + css_system_colors: + type: text + description: > + JSON array containing CSS system color keywords and their computed values as + uppercase hex (without # prefix). System colors (like Canvas, ButtonFace, + LinkText, etc.) are CSS keywords that resolve to theme/OS-specific colors and + can be used for fingerprinting. This metric collects the computed backgroundColor + for each system color keyword. Data format: [{"Canvas": "FFFFFF"}, {"ButtonFace": "F0F0F0"}, ...]. + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2010671 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2010671 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + + css_system_fonts: + type: text + description: > + JSON array containing CSS system font keywords and their computed font properties. + System fonts (like caption, icon, menu, etc.) and common font families are tested + to determine their rendered fontSize and fontFamily values, which can vary by OS + and be used for fingerprinting. This metric collects computed fontSize + fontFamily + for each font keyword/name tested. + Data format: [{"caption": "11px system-ui"}, {"Arial": "16px Arial"}, ...]. + lifetime: application + send_in_pings: + - user-characteristics + notification_emails: + - tom@mozilla.com + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1879151 + - https://bugzilla.mozilla.org/show_bug.cgi?id=2010671 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=2010671 + expires: never + data_sensitivity: + # Text metrics are _required_ to be web_activity or highly_sensitive, so even though this + # is more like 'technical' (per the Data Review), I'm marking highly sensitive. + - highly_sensitive + firefox_binary_arch: type: string description: > diff --git a/toolkit/components/resistfingerprinting/moz.build b/toolkit/components/resistfingerprinting/moz.build index 8bf91b56409e6..a892bc7e9f8b3 100644 --- a/toolkit/components/resistfingerprinting/moz.build +++ b/toolkit/components/resistfingerprinting/moz.build @@ -52,6 +52,7 @@ EXPORTS.mozilla.gtest += ["nsUserCharacteristics.h"] EXTRA_JS_MODULES += [ "!RFPTargetConstants.sys.mjs", + "CanvasHashData.sys.mjs", "FingerprintingWebCompatService.sys.mjs", "RFPHelper.sys.mjs", "UserCharacteristicsPageService.sys.mjs", diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser.toml b/toolkit/components/resistfingerprinting/tests/browser/browser.toml index dd018dfefdcfd..db1736ee859b5 100644 --- a/toolkit/components/resistfingerprinting/tests/browser/browser.toml +++ b/toolkit/components/resistfingerprinting/tests/browser/browser.toml @@ -80,6 +80,13 @@ support-files = ["file_pdf.pdf"] ["browser_usercharacteristics.js"] +["browser_usercharacteristics_canvas_filtering.js"] +skip-if = [ + "os == 'win' && arch == 'x86'", # OOM on win32 due to memory constraints +] + +["browser_usercharacteristics_css.js"] + ["browser_usercharacteristics_gamepads.js"] ["browser_usercharacteristics_linux_distro.js"] diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_usercharacteristics_canvas_filtering.js b/toolkit/components/resistfingerprinting/tests/browser/browser_usercharacteristics_canvas_filtering.js new file mode 100644 index 0000000000000..20cb1103f8efd --- /dev/null +++ b/toolkit/components/resistfingerprinting/tests/browser/browser_usercharacteristics_canvas_filtering.js @@ -0,0 +1,646 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +"use strict"; + +const { UserCharacteristicsPageService, MAX_CANVAS_RAW_DATA_BUDGET_BYTES } = + ChromeUtils.importESModule( + "resource://gre/modules/UserCharacteristicsPageService.sys.mjs" + ); + +const { CANVAS_HASH_PROBABILITIES } = ChromeUtils.importESModule( + "resource://gre/modules/CanvasHashData.sys.mjs" +); + +// Get a known hash from the probabilities map for testing +const KNOWN_HASH = CANVAS_HASH_PROBABILITIES.keys().next().value; + +// Helper function to create less-compressible data +// Uses a pattern that won't compress as well as pure "AAA..." repetition +function createLargeData(size) { + let data = ""; + const chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + for (let i = 0; i < size; i++) { + // Use a pseudo-random but deterministic pattern + data += chars.charAt((i * 7 + (i % 13)) % chars.length); + } + return data; +} + +// Helper function to create test data with known hashes for all canvas types +function createAllKnownHashesData() { + const data = new Map(); + const canvasTypes = [ + "canvasdata1", + "canvasdata1Software", + "canvasdata2", + "canvasdata2Software", + "canvasdata3", + "canvasdata3Software", + "canvasdata4", + "canvasdata4Software", + "canvasdata5", + "canvasdata5Software", + "canvasdata6", + "canvasdata6Software", + "canvasdata7", + "canvasdata7Software", + "canvasdata8", + "canvasdata8Software", + "canvasdata9", + "canvasdata9Software", + "canvasdata10", + "canvasdata10Software", + "canvasdata11Webgl", + "canvasdata11WebglSoftware", + "canvasdata12Fingerprintjs1", + "canvasdata12Fingerprintjs1Software", + "canvasdata13Fingerprintjs2", + "canvasdata13Fingerprintjs2Software", + ]; + + for (const canvasType of canvasTypes) { + data.set(canvasType, KNOWN_HASH); + data.set(canvasType + "Raw", "A".repeat(100)); // Small raw data + } + + return data; +} + +// Test 1: All known hashes should be removed +add_task(async function test_all_known_hashes_removed() { + info("Test 1: Submit all known hashes and ensure they are all removed"); + + const service = new UserCharacteristicsPageService(); + const testData = createAllKnownHashesData(); + + const filtered = await service.filterAllCanvasRawData(testData); + + // Check that all raw data was removed (since all hashes are known and filtered by probability) + let rawCount = 0; + for (const key of filtered.keys()) { + if (key.endsWith("Raw")) { + rawCount++; + } + } + + info(`After filtering: ${rawCount} raw entries remain`); + // With known hashes, probabilistic sampling will remove most/all + // We expect very few (likely 0) to remain + Assert.lessOrEqual( + rawCount, + 3, + "Most or all known hash raw data should be filtered out" + ); +}); + +// Test 2: One unknown hash under budget should be present +add_task(async function test_one_unknown_hash_under_budget() { + info( + "Test 2: Submit all known hashes except one unknown hash with raw data under budget, ensure it is present" + ); + + const service = new UserCharacteristicsPageService(); + const testData = createAllKnownHashesData(); + + // Replace one hash with unknown hash + const unknownHash = "9999999999999999999999999999999999999999"; + testData.set("canvasdata5", unknownHash); + testData.set("canvasdata5Raw", "A".repeat(1000)); // Small, under budget + + // Run multiple times due to 1/10 sampling rate for unknown hashes + // With 100 iterations at 10% rate, probability of 0 successes is 0.9^100 ≈ 0.003% + let foundCount = 0; + const iterations = 100; + + for (let i = 0; i < iterations; i++) { + const filtered = await service.filterAllCanvasRawData(new Map(testData)); + + if (filtered.has("canvasdata5Raw")) { + foundCount++; + } + } + + info( + `Unknown hash raw data found ${foundCount}/${iterations} times (expected ~${iterations / 10})` + ); + + // With 1/10 sampling, we expect roughly 10% to be kept + // Allow for statistical variance + Assert.greater(foundCount, 0, "Unknown hash should be sampled sometimes"); + Assert.lessOrEqual( + foundCount, + iterations / 2, + "Unknown hash sampling rate should be reasonable" + ); +}); + +// Test 3: One unknown hash over budget should not be present +add_task(async function test_one_unknown_hash_over_budget() { + info( + "Test 3: Submit all known hashes except one unknown hash with raw data over budget, ensure it is not present" + ); + + // Disable compression so budget is calculated on uncompressed size + // (otherwise "AAA..." compresses to almost nothing) + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "toolkit.telemetry.user_characteristics_ping.test_skip_compression", + true, + ], + ], + }); + + const service = new UserCharacteristicsPageService(); + const testData = createAllKnownHashesData(); + + // Replace one hash with unknown hash and make it exceed the budget + const unknownHash = "8888888888888888888888888888888888888888"; + testData.set("canvasdata5", unknownHash); + testData.set( + "canvasdata5Raw", + "A".repeat(MAX_CANVAS_RAW_DATA_BUDGET_BYTES * 2) + ); // Way over budget + + const filtered = await service.filterAllCanvasRawData(testData); + + // Even if sampled, it should be removed due to budget + Assert.ok( + !filtered.has("canvasdata5Raw"), + "Over-budget raw data should be removed" + ); +}); + +// Test 4: Budget exceeded - 01 software preferred over hardware +add_task(async function test_01_software_preferred() { + info( + "Test 4: When 01 hardware and software combined exceed budget, confirm 01 software is included instead of hardware" + ); + + // Disable probability filtering and compression for budget tests + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "toolkit.telemetry.user_characteristics_ping.ignore_canvas_probability", + true, + ], + [ + "toolkit.telemetry.user_characteristics_ping.test_skip_compression", + true, + ], + ], + }); + + const service = new UserCharacteristicsPageService(); + const testData = new Map(); + + // Calculate size per entry: budget divided by 2 entries, plus 2 bytes to exceed budget + const numRawEntries = 2; + const sizePerEntry = + Math.floor(MAX_CANVAS_RAW_DATA_BUDGET_BYTES / numRawEntries) + 2; + + const unknownHash1 = "1111111111111111111111111111111111111111"; + const unknownHash2 = "2222222222222222222222222222222222222222"; + + testData.set("canvasdata1", unknownHash1); + testData.set("canvasdata1Raw", "A".repeat(sizePerEntry)); + testData.set("canvasdata1Software", unknownHash2); + testData.set("canvasdata1SoftwareRaw", "A".repeat(sizePerEntry)); + + const filtered = await service.filterAllCanvasRawData(testData); + + // Software should be included, hardware should not + Assert.ok( + filtered.has("canvasdata1SoftwareRaw"), + "01 software should be included (higher priority)" + ); + Assert.ok( + !filtered.has("canvasdata1Raw"), + "01 hardware should be removed due to budget" + ); +}); + +// Test 5: Budget exceeded - 01 HW and SW included, 02 SW omitted +add_task(async function test_01_included_02_sw_omitted() { + info( + "Test 5: When 01 HW, 01 SW, and 02 SW exceed budget, confirm 01 HW and 01 SW are included, 02 SW is omitted" + ); + + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "toolkit.telemetry.user_characteristics_ping.ignore_canvas_probability", + true, + ], + [ + "toolkit.telemetry.user_characteristics_ping.test_skip_compression", + true, + ], + ], + }); + + const service = new UserCharacteristicsPageService(); + const testData = new Map(); + + const numRawEntries = 3; + const sizePerEntry = + Math.floor(MAX_CANVAS_RAW_DATA_BUDGET_BYTES / numRawEntries) + 2; + + const unknownHash1 = "1111111111111111111111111111111111111111"; + const unknownHash2 = "2222222222222222222222222222222222222222"; + const unknownHash3 = "3333333333333333333333333333333333333333"; + + testData.set("canvasdata1", unknownHash1); + testData.set("canvasdata1Raw", "A".repeat(sizePerEntry)); + testData.set("canvasdata1Software", unknownHash2); + testData.set("canvasdata1SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set("canvasdata2Software", unknownHash3); + testData.set("canvasdata2SoftwareRaw", "A".repeat(sizePerEntry)); + + const filtered = await service.filterAllCanvasRawData(testData); + + Assert.ok( + filtered.has("canvasdata1SoftwareRaw"), + "01 software should be included" + ); + Assert.ok(filtered.has("canvasdata1Raw"), "01 hardware should be included"); + Assert.ok( + !filtered.has("canvasdata2SoftwareRaw"), + "02 software should be omitted due to budget" + ); +}); + +// Test 6: Budget exceeded - 02 HW omitted +add_task(async function test_01_and_02_sw_included_02_hw_omitted() { + info( + "Test 6: When 01 HW, 01 SW, 02 HW, and 02 SW exceed budget, confirm 02 HW is omitted" + ); + + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "toolkit.telemetry.user_characteristics_ping.ignore_canvas_probability", + true, + ], + [ + "toolkit.telemetry.user_characteristics_ping.test_skip_compression", + true, + ], + ], + }); + + const service = new UserCharacteristicsPageService(); + const testData = new Map(); + + const numRawEntries = 4; + const sizePerEntry = + Math.floor(MAX_CANVAS_RAW_DATA_BUDGET_BYTES / numRawEntries) + 2; + + const unknownHash1 = "1111111111111111111111111111111111111111"; + const unknownHash2 = "2222222222222222222222222222222222222222"; + const unknownHash3 = "3333333333333333333333333333333333333333"; + const unknownHash4 = "4444444444444444444444444444444444444444"; + + testData.set("canvasdata1", unknownHash1); + testData.set("canvasdata1Raw", "A".repeat(sizePerEntry)); + testData.set("canvasdata1Software", unknownHash2); + testData.set("canvasdata1SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set("canvasdata2Software", unknownHash3); + testData.set("canvasdata2SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set("canvasdata2", unknownHash4); + testData.set("canvasdata2Raw", "A".repeat(sizePerEntry)); + + const filtered = await service.filterAllCanvasRawData(testData); + + Assert.ok( + filtered.has("canvasdata1SoftwareRaw"), + "01 software should be included" + ); + Assert.ok(filtered.has("canvasdata1Raw"), "01 hardware should be included"); + Assert.ok( + filtered.has("canvasdata2SoftwareRaw"), + "02 software should be included" + ); + Assert.ok( + !filtered.has("canvasdata2Raw"), + "02 hardware should be omitted due to budget" + ); +}); + +// Test 7a: Budget exceeded - 09 omitted +add_task(async function test_01_02_included_09_omitted() { + info("Test 7a: When 01, 02, and 09 exceed budget, confirm 09 is omitted"); + + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "toolkit.telemetry.user_characteristics_ping.ignore_canvas_probability", + true, + ], + [ + "toolkit.telemetry.user_characteristics_ping.test_skip_compression", + true, + ], + ], + }); + + const service = new UserCharacteristicsPageService(); + const testData = new Map(); + + const numRawEntries = 5; + const sizePerEntry = + Math.floor(MAX_CANVAS_RAW_DATA_BUDGET_BYTES / numRawEntries) + 2; + + testData.set("canvasdata1", "1111111111111111111111111111111111111111"); + testData.set("canvasdata1Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata1Software", + "2222222222222222222222222222222222222222" + ); + testData.set("canvasdata1SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set("canvasdata2", "3333333333333333333333333333333333333333"); + testData.set("canvasdata2Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata2Software", + "4444444444444444444444444444444444444444" + ); + testData.set("canvasdata2SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata9Software", + "5555555555555555555555555555555555555555" + ); + testData.set("canvasdata9SoftwareRaw", "A".repeat(sizePerEntry)); + + const filtered = await service.filterAllCanvasRawData(testData); + + Assert.ok( + filtered.has("canvasdata1SoftwareRaw"), + "01 software should be included" + ); + Assert.ok(filtered.has("canvasdata1Raw"), "01 hardware should be included"); + Assert.ok( + filtered.has("canvasdata2SoftwareRaw"), + "02 software should be included" + ); + Assert.ok(filtered.has("canvasdata2Raw"), "02 hardware should be included"); + Assert.ok( + !filtered.has("canvasdata9SoftwareRaw"), + "09 software should be omitted due to budget" + ); +}); + +// Test 7b: Budget exceeded - 10 omitted +add_task(async function test_01_02_included_10_omitted() { + info("Test 7b: When 01, 02, and 10 exceed budget, confirm 10 is omitted"); + + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "toolkit.telemetry.user_characteristics_ping.ignore_canvas_probability", + true, + ], + [ + "toolkit.telemetry.user_characteristics_ping.test_skip_compression", + true, + ], + ], + }); + + const service = new UserCharacteristicsPageService(); + const testData = new Map(); + + const numRawEntries = 5; + const sizePerEntry = + Math.floor(MAX_CANVAS_RAW_DATA_BUDGET_BYTES / numRawEntries) + 2; + + testData.set("canvasdata1", "1111111111111111111111111111111111111111"); + testData.set("canvasdata1Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata1Software", + "2222222222222222222222222222222222222222" + ); + testData.set("canvasdata1SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set("canvasdata2", "3333333333333333333333333333333333333333"); + testData.set("canvasdata2Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata2Software", + "4444444444444444444444444444444444444444" + ); + testData.set("canvasdata2SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata10Software", + "5555555555555555555555555555555555555555" + ); + testData.set("canvasdata10SoftwareRaw", "A".repeat(sizePerEntry)); + + const filtered = await service.filterAllCanvasRawData(testData); + + Assert.ok( + filtered.has("canvasdata1SoftwareRaw"), + "01 software should be included" + ); + Assert.ok(filtered.has("canvasdata1Raw"), "01 hardware should be included"); + Assert.ok( + filtered.has("canvasdata2SoftwareRaw"), + "02 software should be included" + ); + Assert.ok(filtered.has("canvasdata2Raw"), "02 hardware should be included"); + Assert.ok( + !filtered.has("canvasdata10SoftwareRaw"), + "10 software should be omitted due to budget" + ); +}); + +// Test 7c: Budget exceeded - 13 omitted (random priority) +add_task(async function test_01_02_09_10_included_13_omitted() { + info( + "Test 7c: When 01, 02, 09, 10, and 13 exceed budget, confirm 13 is omitted (random priority)" + ); + + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "toolkit.telemetry.user_characteristics_ping.ignore_canvas_probability", + true, + ], + [ + "toolkit.telemetry.user_characteristics_ping.test_skip_compression", + true, + ], + ], + }); + + const service = new UserCharacteristicsPageService(); + const testData = new Map(); + + const numRawEntries = 9; + const sizePerEntry = + Math.floor(MAX_CANVAS_RAW_DATA_BUDGET_BYTES / numRawEntries) + 2; + + testData.set("canvasdata1", "1111111111111111111111111111111111111111"); + testData.set("canvasdata1Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata1Software", + "2222222222222222222222222222222222222222" + ); + testData.set("canvasdata1SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set("canvasdata2", "3333333333333333333333333333333333333333"); + testData.set("canvasdata2Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata2Software", + "4444444444444444444444444444444444444444" + ); + testData.set("canvasdata2SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set("canvasdata9", "5555555555555555555555555555555555555555"); + testData.set("canvasdata9Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata9Software", + "6666666666666666666666666666666666666666" + ); + testData.set("canvasdata9SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set("canvasdata10", "7777777777777777777777777777777777777777"); + testData.set("canvasdata10Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata10Software", + "8888888888888888888888888888888888888888" + ); + testData.set("canvasdata10SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata13Fingerprintjs2", + "9999999999999999999999999999999999999999" + ); + testData.set("canvasdata13Fingerprintjs2Raw", "A".repeat(sizePerEntry)); + + const filtered = await service.filterAllCanvasRawData(testData); + + // 01, 02, 09, 10 should all be included (they have fixed priority) + Assert.ok( + filtered.has("canvasdata1SoftwareRaw"), + "01 software should be included" + ); + Assert.ok(filtered.has("canvasdata1Raw"), "01 hardware should be included"); + Assert.ok( + filtered.has("canvasdata2SoftwareRaw"), + "02 software should be included" + ); + Assert.ok(filtered.has("canvasdata2Raw"), "02 hardware should be included"); + Assert.ok( + filtered.has("canvasdata9SoftwareRaw"), + "09 software should be included" + ); + Assert.ok(filtered.has("canvasdata9Raw"), "09 hardware should be included"); + Assert.ok( + filtered.has("canvasdata10SoftwareRaw"), + "10 software should be included" + ); + Assert.ok(filtered.has("canvasdata10Raw"), "10 hardware should be included"); + + // 13 has random priority and should be omitted due to budget + Assert.ok( + !filtered.has("canvasdata13Fingerprintjs2Raw"), + "13 should be omitted due to budget (random priority)" + ); +}); + +// Test 8: Budget exceeded - random canvas (14) omitted +add_task(async function test_01_02_09_10_13_included_14_omitted() { + info( + "Test 8: When 01, 02, 09, 10, 13, and 14 exceed budget, verify random priority selection" + ); + + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "toolkit.telemetry.user_characteristics_ping.ignore_canvas_probability", + true, + ], + [ + "toolkit.telemetry.user_characteristics_ping.test_skip_compression", + true, + ], + ], + }); + + const service = new UserCharacteristicsPageService(); + const testData = new Map(); + + const numRawEntries = 10; + const sizePerEntry = + Math.floor(MAX_CANVAS_RAW_DATA_BUDGET_BYTES / numRawEntries) + 2; + + testData.set("canvasdata1", "1111111111111111111111111111111111111111"); + testData.set("canvasdata1Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata1Software", + "2222222222222222222222222222222222222222" + ); + testData.set("canvasdata1SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set("canvasdata2", "3333333333333333333333333333333333333333"); + testData.set("canvasdata2Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata2Software", + "4444444444444444444444444444444444444444" + ); + testData.set("canvasdata2SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set("canvasdata9", "5555555555555555555555555555555555555555"); + testData.set("canvasdata9Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata9Software", + "6666666666666666666666666666666666666666" + ); + testData.set("canvasdata9SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set("canvasdata10", "7777777777777777777777777777777777777777"); + testData.set("canvasdata10Raw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata10Software", + "8888888888888888888888888888888888888888" + ); + testData.set("canvasdata10SoftwareRaw", "A".repeat(sizePerEntry)); + testData.set( + "canvasdata13Fingerprintjs2", + "9999999999999999999999999999999999999999" + ); + testData.set("canvasdata13Fingerprintjs2Raw", "A".repeat(sizePerEntry)); + testData.set("canvasdata3", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + testData.set("canvasdata3Raw", "A".repeat(sizePerEntry)); + + const filtered = await service.filterAllCanvasRawData(testData); + + // Fixed priority canvases (01, 02, 09, 10) should all be included + Assert.ok( + filtered.has("canvasdata1SoftwareRaw"), + "01 software should be included" + ); + Assert.ok(filtered.has("canvasdata1Raw"), "01 hardware should be included"); + Assert.ok( + filtered.has("canvasdata2SoftwareRaw"), + "02 software should be included" + ); + Assert.ok(filtered.has("canvasdata2Raw"), "02 hardware should be included"); + Assert.ok( + filtered.has("canvasdata9SoftwareRaw"), + "09 software should be included" + ); + Assert.ok(filtered.has("canvasdata9Raw"), "09 hardware should be included"); + Assert.ok( + filtered.has("canvasdata10SoftwareRaw"), + "10 software should be included" + ); + Assert.ok(filtered.has("canvasdata10Raw"), "10 hardware should be included"); + + // Random priority canvases (13, 03) - at least one should be omitted due to budget + const has13 = filtered.has("canvasdata13Fingerprintjs2Raw"); + const has03 = filtered.has("canvasdata3Raw"); + + info(`canvasdata13Fingerprintjs2Raw: ${has13 ? "included" : "omitted"}`); + info(`canvasdata3Raw: ${has03 ? "included" : "omitted"}`); + + // With budget constraints, at least one random-priority canvas should be omitted + Assert.ok( + !has13 || !has03, + "At least one random-priority canvas should be omitted due to budget" + ); +}); diff --git a/toolkit/components/resistfingerprinting/tests/browser/browser_usercharacteristics_css.js b/toolkit/components/resistfingerprinting/tests/browser/browser_usercharacteristics_css.js new file mode 100644 index 0000000000000..edf6b54412dff --- /dev/null +++ b/toolkit/components/resistfingerprinting/tests/browser/browser_usercharacteristics_css.js @@ -0,0 +1,118 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +const emptyPage = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "empty.html"; + +add_task(async function test_css_system_colors_and_fonts() { + info("Testing CSS system colors and fonts collection..."); + + await BrowserTestUtils.withNewTab({ gBrowser, url: emptyPage }, () => + GleanPings.userCharacteristics.testSubmission( + () => { + const colorsValue = + Glean.characteristics.cssSystemColors.testGetValue(); + Assert.notEqual( + colorsValue, + null, + "CSS system colors should be collected" + ); + Assert.notEqual( + colorsValue, + "", + "CSS system colors should not be empty" + ); + + const colorsParsed = JSON.parse(colorsValue); + Assert.ok( + Array.isArray(colorsParsed), + "CSS system colors should be an array" + ); + Assert.greater( + colorsParsed.length, + 0, + "CSS system colors should contain entries" + ); + + const firstColorEntry = colorsParsed[0]; + Assert.strictEqual( + typeof firstColorEntry, + "object", + "Each color entry should be an object" + ); + + const colorKeys = Object.keys(firstColorEntry); + Assert.equal( + colorKeys.length, + 1, + "Each color entry should have exactly one key" + ); + + const colorValue = firstColorEntry[colorKeys[0]]; + Assert.ok( + /^[0-9A-F]{6}$/.test(colorValue), + "Color value should be in uppercase HEX format (e.g., FFFFFF)" + ); + + info(`Collected ${colorsParsed.length} system colors`); + + const fontsValue = Glean.characteristics.cssSystemFonts.testGetValue(); + Assert.notEqual( + fontsValue, + null, + "CSS system fonts should be collected" + ); + Assert.notEqual(fontsValue, "", "CSS system fonts should not be empty"); + + const fontsParsed = JSON.parse(fontsValue); + Assert.ok( + Array.isArray(fontsParsed), + "CSS system fonts should be an array" + ); + Assert.greater( + fontsParsed.length, + 0, + "CSS system fonts should contain entries" + ); + + const firstFontEntry = fontsParsed[0]; + Assert.strictEqual( + typeof firstFontEntry, + "object", + "Each font entry should be an object" + ); + + const fontKeys = Object.keys(firstFontEntry); + Assert.equal( + fontKeys.length, + 1, + "Each font entry should have exactly one key" + ); + + const fontValue = firstFontEntry[fontKeys[0]]; + Assert.ok( + fontValue.includes("px"), + "Font value should include pixel size" + ); + + info(`Collected ${fontsParsed.length} system fonts`); + }, + async () => { + const populated = TestUtils.topicObserved( + "user-characteristics-populating-data-done", + () => true + ); + Services.obs.notifyObservers( + null, + "user-characteristics-testing-please-populate-data" + ); + await populated; + GleanPings.userCharacteristics.submit(); + } + ) + ); +}); diff --git a/toolkit/content/widgets/tabbox.js b/toolkit/content/widgets/tabbox.js index 949321aa7e474..bd1f5b5d52056 100644 --- a/toolkit/content/widgets/tabbox.js +++ b/toolkit/content/widgets/tabbox.js @@ -273,6 +273,13 @@ const splitterState = this.#splitViewSplitter.getAttribute("state"); if (splitterState === "dragging") { gBrowser.activeSplitView.resetRightPanelWidth(); + } else if (!this._splitterPendingUpdate) { + // wait for the layout flush before doing any measuring + this._splitterPendingUpdate = window + .promiseDocumentFlushed(() => {}) + .then(() => + this.updateSplitterAriaAttributes(!!this.#splitViewPanels.length) + ); } }); @@ -337,10 +344,23 @@ splitter.className = "split-view-splitter"; splitter.setAttribute("resizebefore", "sibling"); splitter.setAttribute("resizeafter", "none"); + splitter.setAttribute("tabindex", "0"); + splitter.setAttribute("role", "separator"); + splitter.setAttribute("data-l10n-id", "tab-splitview-splitter"); this.#splitViewSplitter = splitter; - splitter.addEventListener("command", () => - gBrowser.activeSplitView.resetRightPanelWidth() - ); + splitter.addEventListener("command", () => { + gBrowser.activeSplitView.resetRightPanelWidth(); + // wait for the layout flush before doing any measuring + if (!this._splitterPendingUpdate) { + this._splitterPendingUpdate = window + .promiseDocumentFlushed(() => {}) + .then(() => + this.updateSplitterAriaAttributes( + !!this.#splitViewPanels.length + ) + ); + } + }); this.#splitViewSplitterObserver.observe(splitter, { attributeFilter: ["state"], }); @@ -348,6 +368,49 @@ return this.#splitViewSplitter; } + updateSplitterAriaAttributes(isActive) { + delete this._splitterPendingUpdate; + + // avoid triggering the splitter's creation here if it doesnt already exist + const splitter = this.#splitViewSplitter; + if (!splitter) { + return; + } + // The splitter is actively controlling the size of the left/first panel + const controlledPanel = + isActive && + this.splitViewPanels.length && + document.getElementById(this.splitViewPanels[0]); + if (controlledPanel) { + splitter.setAttribute("aria-controls", controlledPanel.id); + + // gather the min, max and current widths to update the aria attributes + const { width: containerWidth } = + window.windowUtils.getBoundsWithoutFlushing(this); + const minWidth = parseFloat(getComputedStyle(controlledPanel).minWidth); + // We can reuse the controlled panel's minWidth to calculate maxWidth as it should be + // the same as the 2nd panel in the splitview + const maxWidth = containerWidth - minWidth; + // Sometimes dragging the splitter produces a panel width attribute which exceeds + // the max width, so lets get our own measurment. This may end up at the previous + // frames width + const currentWidth = + window.windowUtils.getBoundsWithoutFlushing(controlledPanel).width; + + splitter.setAttribute("aria-valuemin", String(minWidth)); + splitter.setAttribute("aria-valuemax", String(maxWidth)); + splitter.setAttribute( + "aria-valuenow", + String(Math.floor(currentWidth)) + ); + } else { + splitter.removeAttribute("aria-controls"); + splitter.removeAttribute("aria-valuenow"); + splitter.removeAttribute("aria-valuemin"); + splitter.removeAttribute("aria-valuemax"); + } + } + /** * nsIDOMXULRelatedElement */ @@ -405,7 +468,7 @@ browser?.addEventListener("focus", this); } this.#splitViewPanels = newPanels; - this.isSplitViewActive = !!newPanels.length; + this.setSplitViewActive(!!newPanels.length); } get splitViewPanels() { @@ -435,10 +498,10 @@ this.#splitViewPanels.splice(index, 1); } } - this.isSplitViewActive = !!this.#splitViewPanels.length; + this.setSplitViewActive(!!this.#splitViewPanels.length); } - set isSplitViewActive(isActive) { + setSplitViewActive(isActive) { this.toggleAttribute("splitview", isActive); this.splitViewSplitter.hidden = !isActive; const selectedPanel = this.selectedPanel; @@ -447,10 +510,11 @@ const firstPanel = document.getElementById(this.splitViewPanels[0]); firstPanel?.after(this.#splitViewSplitter); } - // Ensure that selected index stays up to date, in case the splitter // offsets it. this.selectedPanel = selectedPanel; + // Update aria attributes + this.updateSplitterAriaAttributes(isActive); } setSplitViewPanelActive(isActive, panel) { diff --git a/toolkit/crashreporter/client/app/src/main.rs b/toolkit/crashreporter/client/app/src/main.rs index 88ba7343d41bc..4718afc5213cb 100644 --- a/toolkit/crashreporter/client/app/src/main.rs +++ b/toolkit/crashreporter/client/app/src/main.rs @@ -347,3 +347,7 @@ mod fd_cleanup { #[cfg(all(target_os = "windows", target_env = "gnu"))] #[link(name = "bcryptprimitives")] extern "C" {} + +#[cfg(windows)] +#[link(name = "rpcrt4")] +extern "C" {} diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build index de16e73ab79ac..2853f66c45a21 100644 --- a/toolkit/library/moz.build +++ b/toolkit/library/moz.build @@ -260,6 +260,7 @@ if CONFIG["OS_ARCH"] == "FreeBSD": if CONFIG["OS_ARCH"] == "WINNT": OS_LIBS += [ "crypt32", + "d2d1", "gdi32", "shell32", "ntdll", diff --git a/toolkit/modules/AppConstants.sys.mjs b/toolkit/modules/AppConstants.sys.mjs index 45cac83b11cc7..7c57a768e679a 100644 --- a/toolkit/modules/AppConstants.sys.mjs +++ b/toolkit/modules/AppConstants.sys.mjs @@ -174,7 +174,9 @@ export var AppConstants = Object.freeze({ MOZ_BING_API_CLIENTID: "@MOZ_BING_API_CLIENTID@", MOZ_BING_API_KEY: "@MOZ_BING_API_KEY@", +#ifndef MOZ_WIDGET_ANDROID MOZ_GOOGLE_LOCATION_SERVICE_API_KEY: "@MOZ_GOOGLE_LOCATION_SERVICE_API_KEY@", +#endif MOZ_GOOGLE_SAFEBROWSING_API_KEY: "@MOZ_GOOGLE_SAFEBROWSING_API_KEY@", MOZ_MOZILLA_API_KEY: "@MOZ_MOZILLA_API_KEY@", diff --git a/toolkit/modules/moz.build b/toolkit/modules/moz.build index d72b63e2e6574..c7322c51ce2e0 100644 --- a/toolkit/modules/moz.build +++ b/toolkit/modules/moz.build @@ -263,6 +263,10 @@ if "Android" != CONFIG["OS_TARGET"]: "subprocess", ] + DEFINES["MOZ_GOOGLE_LOCATION_SERVICE_API_KEY"] = ( + CONFIG["MOZ_GOOGLE_LOCATION_SERVICE_API_KEY"] or "" + ) + if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows": EXTRA_JS_MODULES += [ "WindowsLaunchOnLogin.sys.mjs", @@ -277,7 +281,6 @@ for var in ( "MOZ_APP_VERSION_DISPLAY", "MOZ_BING_API_CLIENTID", "MOZ_BING_API_KEY", - "MOZ_GOOGLE_LOCATION_SERVICE_API_KEY", "MOZ_GOOGLE_SAFEBROWSING_API_KEY", "MOZ_MACBUNDLE_ID", "MOZ_MACBUNDLE_NAME", diff --git a/toolkit/moz.configure b/toolkit/moz.configure index be5bc11af6deb..64f527d9e8053 100644 --- a/toolkit/moz.configure +++ b/toolkit/moz.configure @@ -1061,9 +1061,9 @@ set_config("MOZ_PACKAGER_MINIFY", True, when=enable_minify.properties) set_config("MOZ_PACKAGER_MINIFY_JS", True, when=enable_minify.js) -@depends("--enable-debug") -def enable_minify_pdfjs_default(debug): - return not debug +@depends(target_is_android, "--enable-debug", milestone.is_nightly) +def enable_minify_pdfjs_default(is_android, debug, is_nightly): + return is_android and not debug and not is_nightly option( @@ -1183,7 +1183,8 @@ include("../build/moz.configure/keyfiles.configure") simple_keyfile("Mozilla API") -simple_keyfile("Google Location Service API") +with only_when(depends(target.os)(lambda os: os != "Android")): + simple_keyfile("Google Location Service API") simple_keyfile("Google Safebrowsing API")