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")