Update On 202108010529
This commit is contained in:
parent
fc43d50a0c
commit
f57cabae8c
396 changed files with 8813 additions and 4420 deletions
34
Cargo.lock
generated
34
Cargo.lock
generated
|
@ -1472,6 +1472,7 @@ dependencies = [
|
|||
name = "fluent-ffi"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cstr",
|
||||
"fluent",
|
||||
"fluent-fallback",
|
||||
"fluent-pseudo",
|
||||
|
@ -1481,6 +1482,7 @@ dependencies = [
|
|||
"nsstring",
|
||||
"thin-vec",
|
||||
"unic-langid",
|
||||
"xpcom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1744,6 +1746,12 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "gecko-profiler"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"lazy_static",
|
||||
"profiler-macros",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gecko_logger"
|
||||
|
@ -1788,6 +1796,7 @@ dependencies = [
|
|||
"bincode",
|
||||
"cssparser",
|
||||
"cstr",
|
||||
"gecko-profiler",
|
||||
"libc",
|
||||
"log",
|
||||
"malloc_size_of",
|
||||
|
@ -2018,7 +2027,6 @@ dependencies = [
|
|||
"processtools",
|
||||
"profiler_helper",
|
||||
"qcms",
|
||||
"remote",
|
||||
"rlbox_lucet_sandbox",
|
||||
"rsdparsa_capi",
|
||||
"rusqlite",
|
||||
|
@ -2659,6 +2667,9 @@ dependencies = [
|
|||
"async-trait",
|
||||
"cstr",
|
||||
"fluent",
|
||||
"fluent-fallback",
|
||||
"fluent-ffi",
|
||||
"futures 0.3.15",
|
||||
"futures-channel",
|
||||
"l10nregistry",
|
||||
"libc",
|
||||
|
@ -3937,6 +3948,14 @@ dependencies = [
|
|||
"xpcom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "profiler-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "profiler_helper"
|
||||
version = "0.1.0"
|
||||
|
@ -4175,19 +4194,6 @@ version = "0.6.25"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "remote"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"http",
|
||||
"libc",
|
||||
"log",
|
||||
"nserror",
|
||||
"nsstring",
|
||||
"thiserror",
|
||||
"xpcom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
|
|
|
@ -1818,8 +1818,16 @@ LayoutDeviceIntRect HyperTextAccessible::GetCaretRect(nsIWidget** aWidget) {
|
|||
// the character. This is important for font size transitions, and is
|
||||
// necessary because the Gecko caret uses the previous character's size as
|
||||
// the user moves forward in the text by character.
|
||||
int32_t caretOffset = CaretOffset();
|
||||
if (NS_WARN_IF(caretOffset == -1)) {
|
||||
// The caret offset will be -1 if this Accessible isn't focused. Note that
|
||||
// the DOM node contaning the caret might be focused, but the Accessible
|
||||
// might not be; e.g. due to an autocomplete popup suggestion having a11y
|
||||
// focus.
|
||||
return LayoutDeviceIntRect();
|
||||
}
|
||||
nsIntRect charRect = CharBounds(
|
||||
CaretOffset(), nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE);
|
||||
caretOffset, nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE);
|
||||
if (!charRect.IsEmpty()) {
|
||||
caretRect.SetTopEdge(charRect.Y());
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ support-files =
|
|||
[test_flush.html]
|
||||
[test_focusable_statechange.html]
|
||||
[test_focus_aria_activedescendant.html]
|
||||
[test_focus_autocomplete.html]
|
||||
[test_focus_autocomplete.xhtml]
|
||||
# Disabled on Linux and Windows due to frequent failures - bug 695019, bug 890795
|
||||
skip-if = os == 'win' || os == 'linux'
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
<!doctype html>
|
||||
|
||||
<head>
|
||||
<title>Form Autocomplete Tests</title>
|
||||
|
||||
<link rel="stylesheet"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script src="../common.js"></script>
|
||||
<script src="../promisified-events.js"></script>
|
||||
<script src="../role.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
const { TestUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/TestUtils.jsm");
|
||||
|
||||
async function waitForFocusOnOptionWithname(name) {
|
||||
let event = await waitForEvent(
|
||||
EVENT_FOCUS,
|
||||
evt => evt.accessible.role == ROLE_COMBOBOX_OPTION
|
||||
);
|
||||
if (!event.accessible.name) {
|
||||
// Sometimes, the name is null for a very short time after the focus
|
||||
// event.
|
||||
await waitForEvent(EVENT_NAME_CHANGE, event.accessible);
|
||||
}
|
||||
is(event.accessible.name, name, "Got focus on option with name " + name);
|
||||
}
|
||||
|
||||
async function doTests() {
|
||||
const input = getNode("input");
|
||||
info("Focusing the input");
|
||||
let focused = waitForEvent(EVENT_FOCUS, input);
|
||||
input.focus();
|
||||
await focused;
|
||||
|
||||
let shown = waitForEvent(EVENT_SHOW, event =>
|
||||
event.accessible.role == ROLE_GROUPING &&
|
||||
event.accessible.firstChild.role == ROLE_COMBOBOX_LIST);
|
||||
info("Pressing ArrowDown to open the popup");
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
await shown;
|
||||
// The popup still doesn't seem to be ready even once it's fired an a11y
|
||||
// show event!
|
||||
const controller = Cc["@mozilla.org/autocomplete/controller;1"].
|
||||
getService(Ci.nsIAutoCompleteController);
|
||||
info("Waiting for popup to be fully open and ready");
|
||||
await TestUtils.waitForCondition(() => controller.input.popupOpen);
|
||||
|
||||
focused = waitForFocusOnOptionWithname("a");
|
||||
info("Pressing ArrowDown to focus first item");
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
await focused;
|
||||
|
||||
focused = waitForFocusOnOptionWithname("b");
|
||||
info("Pressing ArrowDown to focus the second item");
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
await focused;
|
||||
|
||||
focused = waitForEvent(EVENT_FOCUS, input);
|
||||
info("Pressing enter to select the second item");
|
||||
synthesizeKey("KEY_Enter");
|
||||
await focused;
|
||||
is(input.value, "b", "input value filled with second item");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTests);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<input id="input" list="list">
|
||||
<datalist id="list">
|
||||
<option id="a" value="a">
|
||||
<option id="b" value="b">
|
||||
</datalist>
|
||||
</body>
|
||||
</html>
|
|
@ -67,10 +67,10 @@ bool XULColumnItemAccessible::DoAction(uint8_t aIndex) const {
|
|||
XULListboxAccessible::XULListboxAccessible(nsIContent* aContent,
|
||||
DocAccessible* aDoc)
|
||||
: XULSelectControlAccessible(aContent, aDoc) {
|
||||
nsIContent* parentContent = mContent->GetFlattenedTreeParent();
|
||||
if (parentContent) {
|
||||
dom::Element* parentEl = mContent->GetParentElement();
|
||||
if (parentEl) {
|
||||
nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
|
||||
parentContent->AsElement()->AsAutoCompletePopup();
|
||||
parentEl->AsAutoCompletePopup();
|
||||
if (autoCompletePopupElm) mGenericTypes |= eAutoCompletePopup;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ pref("extensions.strictCompatibility", false);
|
|||
// extensions.checkCompatibility=false has been set.
|
||||
pref("extensions.checkCompatibility.temporaryThemeOverride_minAppVersion", "29.0a1");
|
||||
|
||||
pref("extensions.webextPermissionPrompts", true);
|
||||
pref("extensions.webextOptionalPermissionPrompts", true);
|
||||
// If enabled, install origin permission verification happens after addons are downloaded.
|
||||
pref("extensions.postDownloadThirdPartyPrompt", true);
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
oncommand="gBrowser.selectAllTabs();"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="context_closeTab"
|
||||
data-lazy-l10n-id="tab-context-close-tabs"
|
||||
data-lazy-l10n-id="tab-context-close-n-tabs"
|
||||
data-l10n-args='{"tabCount": 1}'
|
||||
oncommand="TabContextMenu.closeContextTabs();"/>
|
||||
<menu id="context_closeTabOptions"
|
||||
|
|
|
@ -270,6 +270,8 @@ var whitelist = [
|
|||
},
|
||||
{ file: "chrome://browser/content/screenshots/menu-fullpage.svg" },
|
||||
{ file: "chrome://browser/content/screenshots/menu-visible.svg" },
|
||||
|
||||
{ file: "resource://app/modules/SnapshotSelector.jsm" },
|
||||
];
|
||||
|
||||
if (AppConstants.NIGHTLY_BUILD && AppConstants.platform != "win") {
|
||||
|
|
|
@ -11,7 +11,6 @@ skip-if =
|
|||
[browser_aboutRestartRequired_buildid.js]
|
||||
skip-if =
|
||||
!debug
|
||||
(os == 'win')
|
||||
[browser_autoSubmitRequest.js]
|
||||
skip-if =
|
||||
apple_silicon # crash bug 1707182
|
||||
|
|
|
@ -657,6 +657,9 @@ var DownloadsCommon = {
|
|||
case Downloads.Error.BLOCK_VERDICT_POTENTIALLY_UNWANTED:
|
||||
message = s.unblockTypePotentiallyUnwanted2;
|
||||
break;
|
||||
case Downloads.Error.BLOCK_VERDICT_INSECURE:
|
||||
message = s.unblockInsecure;
|
||||
break;
|
||||
default:
|
||||
// Assume Downloads.Error.BLOCK_VERDICT_MALWARE
|
||||
message = s.unblockTypeMalware;
|
||||
|
|
|
@ -24,6 +24,7 @@ add_task(async function test_unblock_dialog_unblock() {
|
|||
for (let verdict of [
|
||||
Downloads.Error.BLOCK_VERDICT_MALWARE,
|
||||
Downloads.Error.BLOCK_VERDICT_POTENTIALLY_UNWANTED,
|
||||
Downloads.Error.BLOCK_VERDICT_INSECURE,
|
||||
Downloads.Error.BLOCK_VERDICT_UNCOMMON,
|
||||
]) {
|
||||
let args = { verdict, window, dialogType: "unblock" };
|
||||
|
@ -46,54 +47,64 @@ add_task(async function test_unblock_dialog_unblock() {
|
|||
* Tests the "chooseUnblock" dialog for potentially unwanted downloads.
|
||||
*/
|
||||
add_task(async function test_chooseUnblock_dialog() {
|
||||
let args = {
|
||||
verdict: Downloads.Error.BLOCK_VERDICT_POTENTIALLY_UNWANTED,
|
||||
window,
|
||||
dialogType: "chooseUnblock",
|
||||
};
|
||||
for (let verdict of [
|
||||
Downloads.Error.BLOCK_VERDICT_POTENTIALLY_UNWANTED,
|
||||
Downloads.Error.BLOCK_VERDICT_INSECURE,
|
||||
]) {
|
||||
let args = {
|
||||
verdict,
|
||||
window,
|
||||
dialogType: "chooseUnblock",
|
||||
};
|
||||
|
||||
// Test each of the three buttons.
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "accept",
|
||||
expectedResult: "unblock",
|
||||
});
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "cancel",
|
||||
expectedResult: "cancel",
|
||||
});
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "extra1",
|
||||
expectedResult: "confirmBlock",
|
||||
});
|
||||
// Test each of the three buttons.
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "accept",
|
||||
expectedResult: "unblock",
|
||||
});
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "cancel",
|
||||
expectedResult: "cancel",
|
||||
});
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "extra1",
|
||||
expectedResult: "confirmBlock",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests the "chooseOpen" dialog for uncommon downloads.
|
||||
*/
|
||||
add_task(async function test_chooseOpen_dialog() {
|
||||
let args = {
|
||||
verdict: Downloads.Error.BLOCK_VERDICT_UNCOMMON,
|
||||
window,
|
||||
dialogType: "chooseOpen",
|
||||
};
|
||||
for (let verdict of [
|
||||
Downloads.Error.BLOCK_VERDICT_UNCOMMON,
|
||||
Downloads.Error.BLOCK_VERDICT_INSECURE,
|
||||
]) {
|
||||
let args = {
|
||||
verdict,
|
||||
window,
|
||||
dialogType: "chooseOpen",
|
||||
};
|
||||
|
||||
// Test each of the three buttons.
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "accept",
|
||||
expectedResult: "open",
|
||||
});
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "cancel",
|
||||
expectedResult: "cancel",
|
||||
});
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "extra1",
|
||||
expectedResult: "confirmBlock",
|
||||
});
|
||||
// Test each of the three buttons.
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "accept",
|
||||
expectedResult: "open",
|
||||
});
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "cancel",
|
||||
expectedResult: "cancel",
|
||||
});
|
||||
await assertDialogResult({
|
||||
args,
|
||||
buttonToClick: "extra1",
|
||||
expectedResult: "confirmBlock",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -22,6 +22,7 @@ async function testManifest(manifest, expectedError) {
|
|||
}`
|
||||
);
|
||||
}
|
||||
return normalized.errors;
|
||||
}
|
||||
|
||||
const all_actions = [
|
||||
|
@ -75,16 +76,7 @@ add_task(async function test_manifest() {
|
|||
|
||||
add_task(async function test_action_version() {
|
||||
// The above test validates these work with the correct version,
|
||||
// here we verify they fail with the incorrect version.
|
||||
testManifest(
|
||||
{
|
||||
manifest_version: 2,
|
||||
action: {
|
||||
default_panel: "foo.html",
|
||||
},
|
||||
},
|
||||
/Property "action" is unsupported in Manifest Version 2/
|
||||
);
|
||||
// here we verify they fail with the incorrect version for MV3.
|
||||
testManifest(
|
||||
{
|
||||
manifest_version: 3,
|
||||
|
@ -94,4 +86,29 @@ add_task(async function test_action_version() {
|
|||
},
|
||||
/Property "browser_action" is unsupported in Manifest Version 3/
|
||||
);
|
||||
|
||||
// But we still allow previously ignored keys in MV2, just warn about them.
|
||||
ExtensionTestUtils.failOnSchemaWarnings(false);
|
||||
|
||||
let warnings = await testManifest({
|
||||
manifest_version: 2,
|
||||
action: {
|
||||
default_icon: "",
|
||||
default_panel: "foo.html",
|
||||
},
|
||||
});
|
||||
|
||||
equal(warnings.length, 2, "Got exactly two warnings");
|
||||
equal(
|
||||
warnings[0],
|
||||
`Property "action" is unsupported in Manifest Version 2`,
|
||||
`Manifest v2 with "action" key first warning is clear.`
|
||||
);
|
||||
equal(
|
||||
warnings[1],
|
||||
"Warning processing action: An unexpected property was found in the WebExtension manifest.",
|
||||
`Manifest v2 with "action" key second warning has more details.`
|
||||
);
|
||||
|
||||
ExtensionTestUtils.failOnSchemaWarnings(true);
|
||||
});
|
||||
|
|
|
@ -50,6 +50,8 @@ Please note that some targeting attributes require stricter controls on the tele
|
|||
* [activeNotifications](#activenotifications)
|
||||
* [isMajorUpgrade](#ismajorupgrade)
|
||||
* [hasActiveEnterprisePolicies](#hasactiveenterprisepolicies)
|
||||
* [mainPingSubmissions](#mainpingsubmissions)
|
||||
* [userMonthlyActivity](#usermonthlyactivity)
|
||||
|
||||
## Detailed usage
|
||||
|
||||
|
@ -816,3 +818,23 @@ A boolean. `true` if the browser just updated to a new major version.
|
|||
### `hasActiveEnterprisePolicies`
|
||||
|
||||
A boolean. `true` if any Enterprise Policies are active.
|
||||
|
||||
### `mainPingSubmissions`
|
||||
|
||||
Filter through the local telemetry pings archive submitted and select the `main`
|
||||
pings sent at least 24 hours apart. Result is sorted in ascending order.
|
||||
|
||||
```javascript
|
||||
interface MainTelemetryPing {
|
||||
id: string,
|
||||
type: "main",
|
||||
timestampCreated: number,
|
||||
}
|
||||
|
||||
declare const mainPingSubmissions: Promise<MainTelemetryPing[]>
|
||||
```
|
||||
|
||||
### `userMonthlyActivity`
|
||||
|
||||
Returns an array of entries in the form `[int, unixTimestamp]` for each day of
|
||||
user activity where the first entry is the total urls visited for that day.
|
||||
|
|
|
@ -28,6 +28,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
HomePage: "resource:///modules/HomePage.jsm",
|
||||
AboutNewTab: "resource:///modules/AboutNewTab.jsm",
|
||||
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
|
||||
TelemetryArchive: "resource://gre/modules/TelemetryArchive.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
|
@ -243,6 +244,7 @@ const QueryCache = {
|
|||
CheckBrowserNeedsUpdate: new CheckBrowserNeedsUpdate(),
|
||||
RecentBookmarks: new CachedTargetingGetter("getRecentBookmarks"),
|
||||
ListAttachedOAuthClients: new CacheListAttachedOAuthClients(),
|
||||
UserMonthlyActivity: new CachedTargetingGetter("getUserMonthlyActivity"),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -634,6 +636,38 @@ const TargetingGetters = {
|
|||
get hasActiveEnterprisePolicies() {
|
||||
return Services.policies.status === Services.policies.ACTIVE;
|
||||
},
|
||||
|
||||
get mainPingSubmissions() {
|
||||
return (
|
||||
TelemetryArchive.promiseArchivedPingList()
|
||||
// Filter out non-main pings. Do it before so we compare timestamps
|
||||
// between pings of same type.
|
||||
.then(pings => pings.filter(p => p.type === "main"))
|
||||
.then(pings => {
|
||||
if (pings.length <= 1) {
|
||||
return pings;
|
||||
}
|
||||
// Pings are returned in ascending order.
|
||||
return pings.reduce(
|
||||
(acc, ping) => {
|
||||
if (
|
||||
// Keep only main pings sent a day (or more) apart
|
||||
new Date(ping.timestampCreated).toDateString() !==
|
||||
new Date(acc[acc.length - 1].timestampCreated).toDateString()
|
||||
) {
|
||||
acc.push(ping);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
[pings[0]]
|
||||
);
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
get userMonthlyActivity() {
|
||||
return QueryCache.queries.UserMonthlyActivity.get();
|
||||
},
|
||||
};
|
||||
|
||||
this.ASRouterTargeting = {
|
||||
|
|
|
@ -16,7 +16,6 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
L10nRegistry: "resource://gre/modules/L10nRegistry.jsm",
|
||||
OS: "resource://gre/modules/osfile.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
||||
|
@ -200,7 +199,7 @@ class _RemoteL10n {
|
|||
// In the case that the Fluent file has not been downloaded from Remote Settings,
|
||||
// `fetchFile` will return `false` and fall back to the packaged Fluent file.
|
||||
const resource = await fs.fetchFile(appLocale, "asrouter.ftl");
|
||||
for await (let bundle of L10nRegistry.generateBundles(
|
||||
for await (let bundle of L10nRegistry.getInstance().generateBundles(
|
||||
appLocales.slice(0, 1),
|
||||
resourceIds
|
||||
)) {
|
||||
|
|
|
@ -1103,3 +1103,10 @@ add_task(async function check_is_major_upgrade() {
|
|||
"Should select the message"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function check_userMonthlyActivity() {
|
||||
ok(
|
||||
Array.isArray(await ASRouterTargeting.Environment.userMonthlyActivity),
|
||||
"value is an array"
|
||||
);
|
||||
});
|
||||
|
|
|
@ -273,6 +273,103 @@ describe("#CacheListAttachedOAuthClients", () => {
|
|||
assert.calledOnce(fxAccounts.listAttachedOAuthClients);
|
||||
});
|
||||
});
|
||||
describe("#mainPingSubmissions", () => {
|
||||
let promiseArchivedPingList;
|
||||
let globals;
|
||||
let sandbox;
|
||||
beforeEach(() => {
|
||||
sandbox = sinon.createSandbox();
|
||||
globals = new GlobalOverrider();
|
||||
});
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
globals.restore();
|
||||
});
|
||||
it("should return an empty list", async () => {
|
||||
promiseArchivedPingList = sandbox.stub().resolves([]);
|
||||
globals.set("TelemetryArchive", { promiseArchivedPingList });
|
||||
assert.typeOf(
|
||||
await ASRouterTargeting.Environment.mainPingSubmissions,
|
||||
"array",
|
||||
"we get back an array"
|
||||
);
|
||||
assert.lengthOf(
|
||||
await ASRouterTargeting.Environment.mainPingSubmissions,
|
||||
0,
|
||||
"no pings available"
|
||||
);
|
||||
});
|
||||
it("should filter out bhr pings", async () => {
|
||||
promiseArchivedPingList = sandbox.stub().resolves([
|
||||
{
|
||||
id: "5c8c786b-eca5-734b-a755-7ec0f022aaaf",
|
||||
timestampCreated: 1622525975674,
|
||||
type: "bhr",
|
||||
},
|
||||
]);
|
||||
globals.set("TelemetryArchive", { promiseArchivedPingList });
|
||||
assert.lengthOf(
|
||||
await ASRouterTargeting.Environment.mainPingSubmissions,
|
||||
0,
|
||||
"no `main` pings available"
|
||||
);
|
||||
});
|
||||
it("should filter out pings less than 24hrs apart", async () => {
|
||||
let startTime = 0;
|
||||
promiseArchivedPingList = sandbox.stub().resolves([
|
||||
{
|
||||
id: "5c8c786b-eca5-734b-a755-7ec0f022aaaf",
|
||||
timestampCreated: 1622525975674,
|
||||
type: "bhr",
|
||||
},
|
||||
{
|
||||
id: "5c8c786b-eca5-734b-a755-7ec0f022aaaa",
|
||||
timestampCreated: startTime,
|
||||
type: "main",
|
||||
},
|
||||
{
|
||||
id: "5c8c786b-eca5-734b-a755-7ec0f022aaaa",
|
||||
timestampCreated: startTime + 1000,
|
||||
type: "main",
|
||||
},
|
||||
{
|
||||
id: "5c8c786b-eca5-734b-a755-7ec0f022aaac",
|
||||
timestampCreated: startTime + 86400001,
|
||||
type: "main",
|
||||
},
|
||||
]);
|
||||
globals.set("TelemetryArchive", { promiseArchivedPingList });
|
||||
assert.lengthOf(
|
||||
await ASRouterTargeting.Environment.mainPingSubmissions,
|
||||
2,
|
||||
"1 main ping is removed"
|
||||
);
|
||||
});
|
||||
it("should allow for pings < 24hrs apart but on different days", async () => {
|
||||
let startTime = new Date("2020-02-20").getTime();
|
||||
let oneDay = 86400000;
|
||||
promiseArchivedPingList = sandbox.stub().resolves([
|
||||
{
|
||||
id: "5c8c786b-eca5-734b-a755-7ec0f022aaaa",
|
||||
// Using oneDay / 2 because timezone of browser running the test
|
||||
// affects the calculation
|
||||
timestampCreated: startTime - oneDay / 2,
|
||||
type: "main",
|
||||
},
|
||||
{
|
||||
id: "5c8c786b-eca5-734b-a755-7ec0f022aaac",
|
||||
timestampCreated: startTime + 1000,
|
||||
type: "main",
|
||||
},
|
||||
]);
|
||||
globals.set("TelemetryArchive", { promiseArchivedPingList });
|
||||
assert.lengthOf(
|
||||
await ASRouterTargeting.Environment.mainPingSubmissions,
|
||||
2,
|
||||
"pings are less day oneDay apart but fall on different days"
|
||||
);
|
||||
});
|
||||
});
|
||||
describe("ASRouterTargeting", () => {
|
||||
let evalStub;
|
||||
let sandbox;
|
||||
|
|
|
@ -235,7 +235,7 @@ class _Interactions {
|
|||
* Used by tests.
|
||||
*/
|
||||
async reset() {
|
||||
logConsole.debug("Reset");
|
||||
logConsole.debug("Database reset");
|
||||
this.#interactions = new WeakMap();
|
||||
this.#userIsIdle = false;
|
||||
this._pageViewStartTime = Cu.now();
|
||||
|
@ -270,11 +270,11 @@ class _Interactions {
|
|||
}
|
||||
|
||||
if (InteractionsBlocklist.isUrlBlocklisted(docInfo.url)) {
|
||||
logConsole.debug("URL is blocklisted", docInfo);
|
||||
logConsole.debug("Ignoring a page as the URL is blocklisted", docInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
logConsole.debug("New interaction", docInfo);
|
||||
logConsole.debug("Tracking a new interaction", docInfo);
|
||||
let now = monotonicNow();
|
||||
interaction = {
|
||||
url: docInfo.url,
|
||||
|
@ -312,7 +312,7 @@ class _Interactions {
|
|||
if (!browser) {
|
||||
return;
|
||||
}
|
||||
logConsole.debug("End of interaction");
|
||||
logConsole.debug("Saw the end of an interaction");
|
||||
|
||||
this.#updateInteraction(browser);
|
||||
this.#interactions.delete(browser);
|
||||
|
@ -331,7 +331,7 @@ class _Interactions {
|
|||
!this.#activeWindow ||
|
||||
(browser && browser.ownerGlobal != this.#activeWindow)
|
||||
) {
|
||||
logConsole.debug("No update due to no active window");
|
||||
logConsole.debug("Not updating interaction as there is no active window");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -340,7 +340,7 @@ class _Interactions {
|
|||
// Sometimes an interaction may be signalled before idle is cleared, however
|
||||
// worst case we'd only loose approx 2 seconds of interaction detail.
|
||||
if (this.#userIsIdle) {
|
||||
logConsole.debug("No update due to user is idle");
|
||||
logConsole.debug("Not updating interaction as the user is idle");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -362,7 +362,6 @@ class _Interactions {
|
|||
interaction.keypresses += typingInteraction.keypresses;
|
||||
interaction.updated_at = monotonicNow();
|
||||
|
||||
logConsole.debug("Add to store: ", interaction);
|
||||
this.store.add(interaction);
|
||||
}
|
||||
|
||||
|
@ -372,7 +371,7 @@ class _Interactions {
|
|||
* @param {DOMWindow} win
|
||||
*/
|
||||
#onActivateWindow(win) {
|
||||
logConsole.debug("Activate window");
|
||||
logConsole.debug("Window activated");
|
||||
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(win)) {
|
||||
return;
|
||||
|
@ -388,7 +387,7 @@ class _Interactions {
|
|||
* @param {DOMWindow} win
|
||||
*/
|
||||
#onDeactivateWindow(win) {
|
||||
logConsole.debug("Deactivate window");
|
||||
logConsole.debug("Window deactivate");
|
||||
|
||||
this.#updateInteraction();
|
||||
this.#activeWindow = undefined;
|
||||
|
@ -403,7 +402,7 @@ class _Interactions {
|
|||
* The instance of the browser that the user switched away from.
|
||||
*/
|
||||
#onTabSelect(previousBrowser) {
|
||||
logConsole.debug("Tab switch notified");
|
||||
logConsole.debug("Tab switched");
|
||||
|
||||
this.#updateInteraction(previousBrowser);
|
||||
this._pageViewStartTime = Cu.now();
|
||||
|
@ -444,14 +443,14 @@ class _Interactions {
|
|||
this.#onWindowOpen(subject);
|
||||
break;
|
||||
case "idle":
|
||||
logConsole.debug("idle");
|
||||
logConsole.debug("User went idle");
|
||||
// We save the state of the current interaction when we are notified
|
||||
// that the user is idle.
|
||||
this.#updateInteraction();
|
||||
this.#userIsIdle = true;
|
||||
break;
|
||||
case "active":
|
||||
logConsole.debug("active");
|
||||
logConsole.debug("User became active");
|
||||
this.#userIsIdle = false;
|
||||
this._pageViewStartTime = Cu.now();
|
||||
break;
|
||||
|
@ -620,6 +619,8 @@ class InteractionsStore {
|
|||
* The document information to write.
|
||||
*/
|
||||
add(interaction) {
|
||||
logConsole.debug("Preparing interaction for storage", interaction);
|
||||
|
||||
let interactionsForUrl = this.#interactions.get(interaction.url);
|
||||
if (!interactionsForUrl) {
|
||||
interactionsForUrl = new Map();
|
||||
|
@ -631,7 +632,6 @@ class InteractionsStore {
|
|||
let promise = new Promise(resolve => {
|
||||
this.#timerResolve = resolve;
|
||||
this.#timer = setTimeout(() => {
|
||||
logConsole.debug("Save Timer");
|
||||
this.#updateDatabase()
|
||||
.catch(Cu.reportError)
|
||||
.then(resolve);
|
||||
|
@ -704,7 +704,9 @@ class InteractionsStore {
|
|||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
logConsole.debug(`Storing ${i} entries in the database`);
|
||||
|
||||
this.progress.pendingUpdates = i;
|
||||
await PlacesUtils.withConnectionWrapper(
|
||||
"Interactions.jsm::updateDatabase",
|
||||
|
@ -724,6 +726,8 @@ class InteractionsStore {
|
|||
);
|
||||
this.progress.pendingUpdates = 0;
|
||||
|
||||
Services.obs.notifyObservers(null, "places-metadata-updated");
|
||||
|
||||
if (this.#userIsIdle) {
|
||||
this.updateSnapshots();
|
||||
}
|
||||
|
|
186
browser/components/places/SnapshotSelector.jsm
Normal file
186
browser/components/places/SnapshotSelector.jsm
Normal file
|
@ -0,0 +1,186 @@
|
|||
/* 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/. */
|
||||
const EXPORTED_SYMBOLS = ["SnapshotSelector"];
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
EventEmitter: "resource://gre/modules/EventEmitter.jsm",
|
||||
DeferredTask: "resource://gre/modules/DeferredTask.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
Snapshots: "resource:///modules/Snapshots.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "logConsole", function() {
|
||||
return console.createInstance({
|
||||
prefix: "SnapshotSelector",
|
||||
maxLogLevel: Services.prefs.getBoolPref(
|
||||
"browser.places.interactions.log",
|
||||
false
|
||||
)
|
||||
? "Debug"
|
||||
: "Warn",
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* A snapshot selector is responsible for generating a list of snapshots based
|
||||
* on the current context. The context initially is just the url of the page
|
||||
* being viewed but will evolve to include things like the search terms that
|
||||
* brought the user to that page etc.
|
||||
*
|
||||
* Individual snapshots can be told to rebuild their set of snapshots and a
|
||||
* global function is provided that triggers all current selectors to rebuild.
|
||||
*
|
||||
* The selector is an event emitter that will emit a "snapshots-updated" event
|
||||
* when a new list is generated.
|
||||
*
|
||||
* This component is intentionally decoupled from where the context comes from
|
||||
* so it can be unit tested.
|
||||
*/
|
||||
class SnapshotSelector extends EventEmitter {
|
||||
/**
|
||||
* All of the active selectors.
|
||||
*/
|
||||
static #selectors = new Set();
|
||||
|
||||
/**
|
||||
* Triggers a rebuild of all selectors.
|
||||
*/
|
||||
static rebuildAll() {
|
||||
for (let selector of SnapshotSelector.#selectors) {
|
||||
selector.rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The context should be thought of as the current state for this specific
|
||||
* selector. Global state that impacts all selectors should not be kept here.
|
||||
*/
|
||||
#context = {
|
||||
/**
|
||||
* The number of snapshots desired.
|
||||
* @type {number}
|
||||
*/
|
||||
count: undefined,
|
||||
/**
|
||||
* The page the snapshots are for.
|
||||
* @type {string | undefined}
|
||||
*/
|
||||
url: undefined,
|
||||
/**
|
||||
* The type of snapshots desired.
|
||||
* @type {PageDataCollector.DATA_TYPE | undefined}
|
||||
*/
|
||||
type: undefined,
|
||||
};
|
||||
|
||||
/**
|
||||
* A DeferredTask that runs the task to generate snapshots.
|
||||
*/
|
||||
#task = null;
|
||||
|
||||
/**
|
||||
* @param {number} count
|
||||
* The maximum number of snapshots we ever need to generate. This should not
|
||||
* affect the actual snapshots generated and their order but may speed up
|
||||
* calculations.
|
||||
*/
|
||||
constructor(count = 5) {
|
||||
super();
|
||||
this.#task = new DeferredTask(() => this.#buildSnapshots(), 500);
|
||||
this.#context.count = count;
|
||||
SnapshotSelector.#selectors.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call to destroy the selector.
|
||||
*/
|
||||
destroy() {
|
||||
this.#task.disarm();
|
||||
this.#task.finalize();
|
||||
this.#task = null;
|
||||
SnapshotSelector.#selectors.delete(this);
|
||||
}
|
||||
|
||||
rebuild() {
|
||||
this.#task.arm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called internally when the set of snapshots has been generated.
|
||||
*
|
||||
* @param {Snapshot[]} snapshots
|
||||
*/
|
||||
#snapshotsGenerated(snapshots) {
|
||||
logConsole.debug(
|
||||
"Generated snapshots",
|
||||
snapshots.map(s => s.url)
|
||||
);
|
||||
this.emit("snapshots-updated", snapshots);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the process of building snapshots.
|
||||
*/
|
||||
async #buildSnapshots() {
|
||||
// Task a copy of the context to avoid it changing while we are generating
|
||||
// the list.
|
||||
let context = { ...this.#context };
|
||||
logConsole.debug("Building snapshots", context);
|
||||
|
||||
// Query for one more than we need in case the current url is returned.
|
||||
let snapshots = await Snapshots.query({
|
||||
limit: context.count + 1,
|
||||
type: context.type,
|
||||
});
|
||||
|
||||
snapshots = snapshots
|
||||
.filter(snapshot => snapshot.url != context.url)
|
||||
.slice(0, context.count);
|
||||
|
||||
this.#snapshotsGenerated(snapshots);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current context's url for this selector.
|
||||
*
|
||||
* @param {string} url
|
||||
*/
|
||||
setUrl(url) {
|
||||
if (this.#context.url == url) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#context.url = url;
|
||||
this.rebuild();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of snapshots for this selector.
|
||||
*
|
||||
* @param {PageDataCollector.DATA_TYPE | undefined} type
|
||||
*/
|
||||
async setType(type) {
|
||||
if (this.#context.type === type) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#context.type = type;
|
||||
this.rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
// Listen for global events that may affect the snapshots generated.
|
||||
Services.obs.addObserver(SnapshotSelector.rebuildAll, "places-snapshots-added");
|
||||
Services.obs.addObserver(
|
||||
SnapshotSelector.rebuildAll,
|
||||
"places-snapshots-deleted"
|
||||
);
|
||||
Services.obs.addObserver(
|
||||
SnapshotSelector.rebuildAll,
|
||||
"places-metadata-updated"
|
||||
);
|
|
@ -467,7 +467,7 @@ const Snapshots = new (class Snapshots {
|
|||
}
|
||||
|
||||
logConsole.debug(
|
||||
`Updating ${urls ? urls.length : "all"} potential snapshots`
|
||||
`Testing ${urls ? urls.length : "all"} potential snapshots`
|
||||
);
|
||||
|
||||
let model;
|
||||
|
@ -475,7 +475,9 @@ const Snapshots = new (class Snapshots {
|
|||
model = JSON.parse(snapshotCriteria);
|
||||
|
||||
if (!model.length) {
|
||||
logConsole.debug(`No model provided, falling back to default`);
|
||||
logConsole.debug(
|
||||
`No snapshot criteria provided, falling back to default`
|
||||
);
|
||||
model = DEFAULT_CRITERIA;
|
||||
}
|
||||
} catch (e) {
|
||||
|
@ -576,7 +578,7 @@ const Snapshots = new (class Snapshots {
|
|||
);
|
||||
|
||||
if (insertedUrls.length) {
|
||||
logConsole.debug(`Inserted ${insertedUrls.length} snapshots.`);
|
||||
logConsole.debug(`${insertedUrls.length} snapshots created`);
|
||||
await this.#addPageData(insertedUrls);
|
||||
this.#notify(
|
||||
"places-snapshots-added",
|
||||
|
|
|
@ -21,6 +21,7 @@ EXTRA_JS_MODULES += [
|
|||
"InteractionsBlocklist.jsm",
|
||||
"PlacesUIUtils.jsm",
|
||||
"Snapshots.jsm",
|
||||
"SnapshotSelector.jsm",
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES.actors += [
|
||||
|
|
|
@ -206,6 +206,26 @@ function assertSnapshot(actual, expected) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the list of snapshots match the expected values.
|
||||
*
|
||||
* @param {Snapshot[]} received
|
||||
* The received snapshots.
|
||||
* @param {Snapshot[]} expected
|
||||
* The expected snapshots.
|
||||
*/
|
||||
async function assertSnapshotList(received, expected) {
|
||||
info(`Found ${received.length} snapshots:\n ${JSON.stringify(received)}`);
|
||||
Assert.equal(
|
||||
received.length,
|
||||
expected.length,
|
||||
"Should have the expected number of snapshots"
|
||||
);
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
assertSnapshot(received[i], expected[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the snapshots in the database match the expected values.
|
||||
*
|
||||
|
@ -217,15 +237,7 @@ function assertSnapshot(actual, expected) {
|
|||
async function assertSnapshots(expected, options) {
|
||||
let snapshots = await Snapshots.query(options);
|
||||
|
||||
info(`Found ${snapshots.length} snapshots:\n ${JSON.stringify(snapshots)}`);
|
||||
Assert.equal(
|
||||
snapshots.length,
|
||||
expected.length,
|
||||
"Should have the expected number of snapshots"
|
||||
);
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
assertSnapshot(snapshots[i], expected[i]);
|
||||
}
|
||||
await assertSnapshotList(snapshots, expected);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that we select the most recent set of snapshots excluding the current
|
||||
* url.
|
||||
*/
|
||||
|
||||
const TEST_URL1 = "https://example.com/";
|
||||
const TEST_URL2 = "https://example.com/12345";
|
||||
const TEST_URL3 = "https://example.com/14235";
|
||||
const TEST_URL4 = "https://example.com/14345";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
SnapshotSelector: "resource:///modules/SnapshotSelector.jsm",
|
||||
});
|
||||
|
||||
add_task(async function setup() {
|
||||
let now = Date.now();
|
||||
await addInteractions([
|
||||
{ url: TEST_URL1, created_at: now - 2000 },
|
||||
{ url: TEST_URL2, created_at: now - 1000 },
|
||||
{ url: TEST_URL3, created_at: now - 3000 },
|
||||
]);
|
||||
|
||||
let selector = new SnapshotSelector(2);
|
||||
|
||||
let snapshotPromise = selector.once("snapshots-updated");
|
||||
selector.rebuild();
|
||||
let snapshots = await snapshotPromise;
|
||||
|
||||
await assertSnapshotList(snapshots, []);
|
||||
|
||||
snapshotPromise = selector.once("snapshots-updated");
|
||||
await Snapshots.add({ url: TEST_URL1 });
|
||||
snapshots = await snapshotPromise;
|
||||
|
||||
await assertSnapshotList(snapshots, [{ url: TEST_URL1 }]);
|
||||
|
||||
// Changing the url should generate new snapshots and should exclude the
|
||||
// current url.
|
||||
snapshotPromise = selector.once("snapshots-updated");
|
||||
selector.setUrl(TEST_URL1);
|
||||
snapshots = await snapshotPromise;
|
||||
|
||||
await assertSnapshotList(snapshots, []);
|
||||
|
||||
snapshotPromise = selector.once("snapshots-updated");
|
||||
selector.setUrl(TEST_URL2);
|
||||
snapshots = await snapshotPromise;
|
||||
|
||||
await assertSnapshotList(snapshots, [{ url: TEST_URL1 }]);
|
||||
|
||||
snapshotPromise = selector.once("snapshots-updated");
|
||||
await Snapshots.add({ url: TEST_URL2 });
|
||||
snapshots = await snapshotPromise;
|
||||
|
||||
await assertSnapshotList(snapshots, [{ url: TEST_URL1 }]);
|
||||
|
||||
snapshotPromise = selector.once("snapshots-updated");
|
||||
await Snapshots.add({ url: TEST_URL3 });
|
||||
snapshots = await snapshotPromise;
|
||||
|
||||
await assertSnapshotList(snapshots, [{ url: TEST_URL1 }, { url: TEST_URL3 }]);
|
||||
|
||||
snapshotPromise = selector.once("snapshots-updated");
|
||||
selector.setUrl(TEST_URL3);
|
||||
snapshots = await snapshotPromise;
|
||||
|
||||
await assertSnapshotList(snapshots, [{ url: TEST_URL2 }, { url: TEST_URL1 }]);
|
||||
|
||||
snapshotPromise = selector.once("snapshots-updated");
|
||||
selector.setUrl(TEST_URL4);
|
||||
snapshots = await snapshotPromise;
|
||||
|
||||
// The snapshot count is limited to 2.
|
||||
await assertSnapshotList(snapshots, [{ url: TEST_URL2 }, { url: TEST_URL1 }]);
|
||||
|
||||
await reset();
|
||||
});
|
|
@ -0,0 +1,73 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that we select the most recent set of snapshots excluding the current
|
||||
* url.
|
||||
*/
|
||||
|
||||
const TEST_URL1 = "https://example.com/";
|
||||
const TEST_URL2 = "https://example.com/12345";
|
||||
const TEST_URL3 = "https://example.com/14235";
|
||||
const TEST_URL4 = "https://example.com/14345";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
SnapshotSelector: "resource:///modules/SnapshotSelector.jsm",
|
||||
PageDataService: "resource:///modules/pagedata/PageDataService.jsm",
|
||||
PageDataCollector: "resource:///modules/pagedata/PageDataCollector.jsm",
|
||||
});
|
||||
|
||||
add_task(async () => {
|
||||
let now = Date.now();
|
||||
await addInteractions([
|
||||
{ url: TEST_URL1, created_at: now - 2000 },
|
||||
{ url: TEST_URL2, created_at: now - 1000 },
|
||||
{ url: TEST_URL3, created_at: now - 3000 },
|
||||
]);
|
||||
|
||||
PageDataService.pageDataDiscovered(TEST_URL1, [
|
||||
{
|
||||
type: PageDataCollector.DATA_TYPE.PRODUCT,
|
||||
data: {
|
||||
price: 276,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
await Snapshots.add({ url: TEST_URL1 });
|
||||
await Snapshots.add({ url: TEST_URL2 });
|
||||
await Snapshots.add({ url: TEST_URL3 });
|
||||
|
||||
let selector = new SnapshotSelector(5);
|
||||
|
||||
let snapshotPromise = selector.once("snapshots-updated");
|
||||
selector.setUrl(TEST_URL4);
|
||||
let snapshots = await snapshotPromise;
|
||||
|
||||
// Finds any snapshot.
|
||||
await assertSnapshotList(snapshots, [
|
||||
{ url: TEST_URL2 },
|
||||
{ url: TEST_URL1 },
|
||||
{ url: TEST_URL3 },
|
||||
]);
|
||||
|
||||
snapshotPromise = selector.once("snapshots-updated");
|
||||
selector.setType(PageDataCollector.DATA_TYPE.PRODUCT);
|
||||
snapshots = await snapshotPromise;
|
||||
|
||||
// Only finds the product snapshot.
|
||||
await assertSnapshotList(snapshots, [{ url: TEST_URL1 }]);
|
||||
|
||||
snapshotPromise = selector.once("snapshots-updated");
|
||||
selector.setType(undefined);
|
||||
snapshots = await snapshotPromise;
|
||||
|
||||
// Back to any.
|
||||
await assertSnapshotList(snapshots, [
|
||||
{ url: TEST_URL2 },
|
||||
{ url: TEST_URL1 },
|
||||
{ url: TEST_URL3 },
|
||||
]);
|
||||
|
||||
await reset();
|
||||
});
|
|
@ -2,6 +2,7 @@
|
|||
prefs =
|
||||
browser.places.interactions.enabled=true
|
||||
browser.places.interactions.log=true
|
||||
browser.pagedata.enabled=true
|
||||
browser.pagedata.log=true
|
||||
head = head_interactions.js
|
||||
firefox-appdir = browser
|
||||
|
@ -12,3 +13,5 @@ skip-if = toolkit == 'android'
|
|||
[test_snapshots_create_criteria.js]
|
||||
[test_snapshots_pagedata.js]
|
||||
[test_snapshots_queries.js]
|
||||
[test_snapshotselection_recent.js]
|
||||
[test_snapshotselection_typed.js]
|
||||
|
|
|
@ -17,9 +17,6 @@ var { TransientPrefs } = ChromeUtils.import(
|
|||
var { AppConstants } = ChromeUtils.import(
|
||||
"resource://gre/modules/AppConstants.jsm"
|
||||
);
|
||||
var { L10nRegistry } = ChromeUtils.import(
|
||||
"resource://gre/modules/L10nRegistry.jsm"
|
||||
);
|
||||
var { HomePage } = ChromeUtils.import("resource:///modules/HomePage.jsm");
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
|
@ -263,7 +260,7 @@ function getBundleForLocales(newLocales) {
|
|||
])
|
||||
);
|
||||
function generateBundles(resourceIds) {
|
||||
return L10nRegistry.generateBundles(locales, resourceIds);
|
||||
return L10nRegistry.getInstance().generateBundles(locales, resourceIds);
|
||||
}
|
||||
return new Localization(
|
||||
["browser/preferences/preferences.ftl", "branding/brand.ftl"],
|
||||
|
|
|
@ -17,7 +17,9 @@ support-files =
|
|||
[browser_cross_origin_isolated_reduce_time_precision.js]
|
||||
[browser_dynamical_window_rounding.js]
|
||||
https_first_disabled = true
|
||||
skip-if = (os == "mac") #Bug 1570812
|
||||
skip-if =
|
||||
(os == "mac") #Bug 1570812
|
||||
os == 'linux' && bits == 64 && !debug # Bug 1570812
|
||||
[browser_navigator.js]
|
||||
https_first_disabled = true
|
||||
skip-if =
|
||||
|
|
|
@ -63,10 +63,6 @@ ChromeUtils.defineModuleGetter(
|
|||
// with region names based on en-US. This is
|
||||
// necessary for tests that expect to match
|
||||
// on region code display names.
|
||||
const { L10nRegistry } = ChromeUtils.import(
|
||||
"resource://gre/modules/L10nRegistry.jsm"
|
||||
);
|
||||
|
||||
const fs = [
|
||||
{
|
||||
path: "toolkit/intl/regionNames.ftl",
|
||||
|
@ -87,7 +83,7 @@ region-name-tw = Taiwan
|
|||
"resource://mock_path",
|
||||
fs
|
||||
);
|
||||
L10nRegistry.registerSources([mockSource]);
|
||||
L10nRegistry.getInstance().registerSources([mockSource]);
|
||||
}
|
||||
|
||||
do_get_profile();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
"name": "Web Compatibility Interventions",
|
||||
"description": "Urgent post-release fixes for web compatibility.",
|
||||
"version": "24.13.0",
|
||||
"version": "24.14.0",
|
||||
|
||||
"applications": {
|
||||
"gecko": {
|
||||
|
@ -97,6 +97,7 @@
|
|||
"shims/bmauth.js",
|
||||
"shims/chartbeat.js",
|
||||
"shims/criteo.js",
|
||||
"shims/cxense.js",
|
||||
"shims/eluminate.js",
|
||||
"shims/empty-script.js",
|
||||
"shims/empty-shim.txt",
|
||||
|
|
|
@ -86,6 +86,7 @@ FINAL_TARGET_FILES.features["webcompat@mozilla.org"]["shims"] += [
|
|||
"shims/bmauth.js",
|
||||
"shims/chartbeat.js",
|
||||
"shims/criteo.js",
|
||||
"shims/cxense.js",
|
||||
"shims/eluminate.js",
|
||||
"shims/empty-script.js",
|
||||
"shims/empty-shim.txt",
|
||||
|
|
593
browser/extensions/webcompat/shims/cxense.js
Normal file
593
browser/extensions/webcompat/shims/cxense.js
Normal file
|
@ -0,0 +1,593 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Bug 1713721 - Shim Cxense
|
||||
*
|
||||
* Sites relying on window.cX can experience breakage if it is blocked.
|
||||
* Stubbing out the API in a shim can mitigate this breakage. There are
|
||||
* two versions of the API, one including window.cX.CCE, but both appear
|
||||
* to be very similar so we use one shim for both.
|
||||
*/
|
||||
|
||||
if (window.cX?.getUserSegmentIds === undefined) {
|
||||
const callQueue = window.cX?.callQueue || [];
|
||||
const callQueueCCE = window.cX?.CCE?.callQueue || [];
|
||||
|
||||
function getRandomString(l = 16) {
|
||||
const v = crypto.getRandomValues(new Uint8Array(l));
|
||||
const s = Array.from(v, c => c.toString(16)).join("");
|
||||
return s.slice(0, l);
|
||||
}
|
||||
|
||||
const call = (cb, ...args) => {
|
||||
if (typeof cb !== "function") {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
cb(...args);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
const invokeOn = lib => {
|
||||
return (fn, ...args) => {
|
||||
try {
|
||||
lib[fn](...args);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const userId = getRandomString();
|
||||
const cxUserId = `cx:${getRandomString(25)}:${getRandomString(12)}`;
|
||||
const topLeft = { left: 0, top: 0 };
|
||||
const margins = { left: 0, top: 0, right: 0, bottom: 0 };
|
||||
const ccePushUrl =
|
||||
"https://comcluster.cxense.com/cce/push?callback={{callback}}";
|
||||
const displayWidget = (divId, a, ctx, callback) => call(callback, ctx, divId);
|
||||
const getUserSegmentIds = a => call(a?.callback, a?.defaultValue || []);
|
||||
const init = (a, b, c, d, callback) => call(callback);
|
||||
const render = (a, data, ctx, callback) => call(callback, data, ctx);
|
||||
const run = (params, ctx, callback) => call(callback, params, ctx);
|
||||
const runCtrlVersion = (a, b, callback) => call(callback);
|
||||
const runCxVersion = (a, data, b, ctx, callback) => call(callback, data, ctx);
|
||||
const runTest = (a, divId, b, c, ctx, callback) => call(callback, divId, ctx);
|
||||
const sendConversionEvent = (a, options) => call(options?.callback, {});
|
||||
const sendEvent = (a, b, args) => call(args?.callback, {});
|
||||
|
||||
const getDivId = className => {
|
||||
const e = document.querySelector(`.${className}`);
|
||||
if (e) {
|
||||
return `${className}-01`;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const getDocumentSize = () => {
|
||||
const width = document.body.clientWidth;
|
||||
const height = document.body.clientHeight;
|
||||
return { width, height };
|
||||
};
|
||||
|
||||
const getNowSeconds = () => {
|
||||
return Math.round(new Date().getTime() / 1000);
|
||||
};
|
||||
|
||||
const getPageContext = () => {
|
||||
return {
|
||||
location: location.href,
|
||||
pageViewRandom: "",
|
||||
userId,
|
||||
};
|
||||
};
|
||||
|
||||
const getWindowSize = () => {
|
||||
const width = window.innerWidth;
|
||||
const height = window.innerHeight;
|
||||
return { width, height };
|
||||
};
|
||||
|
||||
const isObject = i => {
|
||||
return typeof i === "object" && i !== null && !Array.isArray(i);
|
||||
};
|
||||
|
||||
const runMulti = widgets => {
|
||||
widgets?.forEach(({ widgetParams, widgetContext, widgetCallback }) => {
|
||||
call(widgetCallback, widgetParams, widgetContext);
|
||||
});
|
||||
};
|
||||
|
||||
let testGroup = -1;
|
||||
let snapPoints = [];
|
||||
const startTime = new Date();
|
||||
|
||||
const library = {
|
||||
addCustomerScript() {},
|
||||
addEventListener() {},
|
||||
addExternalId() {},
|
||||
afterInitializePage() {},
|
||||
allUserConsents() {},
|
||||
backends: {
|
||||
production: {
|
||||
baseAdDeliveryUrl: "http://adserver.cxad.cxense.com/adserver/search",
|
||||
secureBaseAdDeliveryUrl:
|
||||
"https://s-adserver.cxad.cxense.com/adserver/search",
|
||||
},
|
||||
sandbox: {
|
||||
baseAdDeliveryUrl:
|
||||
"http://adserver.sandbox.cxad.cxense.com/adserver/search",
|
||||
secureBaseAdDeliveryUrl:
|
||||
"https://s-adserver.sandbox.cxad.cxense.com/adserver/search",
|
||||
},
|
||||
},
|
||||
calculateAdSpaceSize(adCount, adUnitSize, marginA, marginB) {
|
||||
return adCount * (adUnitSize + marginA + marginB);
|
||||
},
|
||||
cdn: {
|
||||
template: {
|
||||
direct: {
|
||||
http: "http://cdn.cxpublic.com/",
|
||||
https: "https://cdn.cxpublic.com/",
|
||||
},
|
||||
mapped: {
|
||||
http: "http://cdn-templates.cxpublic.com/",
|
||||
https: "https://cdn-templates.cxpublic.com/",
|
||||
},
|
||||
},
|
||||
},
|
||||
cint() {},
|
||||
cleanUpGlobalIds: [],
|
||||
clearBaseUrl: "https://scdn.cxense.com/sclear.html",
|
||||
clearCustomParameters() {},
|
||||
clearIdUrl: "https://scomcluster.cxense.com/public/clearid",
|
||||
clearIds() {},
|
||||
clickTracker: (a, b, callback) => call(callback),
|
||||
clientStorageUrl: "https://clientstorage.cxense.com",
|
||||
combineArgs: () => Object.create(),
|
||||
combineKeywordsIntoArray: () => [],
|
||||
consentClasses: ["pv", "segment", "ad", "recs"],
|
||||
consentClassesV2: ["geo", "device"],
|
||||
cookieSyncRUrl: "csyn-r.cxense.com",
|
||||
createDelegate() {},
|
||||
csdUrls: {
|
||||
domainScriptUrl: "//csd.cxpublic.com/d/",
|
||||
customerScriptUrl: "//csd.cxpublic.com/t/",
|
||||
},
|
||||
cxenseGlobalIdIframeUrl: "https://scdn.cxense.com/sglobal.html",
|
||||
cxenseUserIdUrl: "https://id.cxense.com/public/user/id",
|
||||
decodeUrlEncodedNameValuePairs: () => Object.create(),
|
||||
defaultAdRenderer: () => "",
|
||||
deleteCookie() {},
|
||||
denyWithoutConsent: {
|
||||
addExternalId: "pv",
|
||||
getUserSegmentIds: "segment",
|
||||
insertAdSpace: "ad",
|
||||
insertMultipleAdSpaces: "ad",
|
||||
sendEvent: "pv",
|
||||
sendPageViewEvent: "pv",
|
||||
sync: "ad",
|
||||
},
|
||||
dmpPushUrl: "https://comcluster.cxense.com/dmp/push?callback={{callback}}",
|
||||
emptyWidgetUrl: "https://scdn.cxense.com/empty.html",
|
||||
eventReceiverBaseUrl: "https://scomcluster.cxense.com/Repo/rep.html",
|
||||
eventReceiverBaseUrlGif: "https://scomcluster.cxense.com/Repo/rep.gif",
|
||||
getAllText: () => "",
|
||||
getClientStorageVariable() {},
|
||||
getCookie: () => null,
|
||||
getCxenseUserId: () => cxUserId,
|
||||
getDocumentSize,
|
||||
getElementPosition: () => topLeft,
|
||||
getHashFragment: () => location.hash.substr(1),
|
||||
getLocalStats: () => Object.create(),
|
||||
getNodeValue: n => n.nodeValue,
|
||||
getNowSeconds,
|
||||
getPageContext,
|
||||
getRandomString,
|
||||
getScrollPos: () => topLeft,
|
||||
getSessionId: () => "",
|
||||
getSiteId: () => "",
|
||||
getTimezoneOffset: () => new Date().getTimezoneOffset(),
|
||||
getTopLevelDomain: () => location.hostname,
|
||||
getUserId: () => userId,
|
||||
getUserSegmentIds,
|
||||
getWindowSize,
|
||||
hasConsent: () => true,
|
||||
hasHistory: () => true,
|
||||
hasLocalStorage: () => true,
|
||||
hasPassiveEventListeners: () => true,
|
||||
hasPostMessage: () => true,
|
||||
hasSessionStorage() {},
|
||||
initializePage() {},
|
||||
insertAdSpace() {},
|
||||
insertMultipleAdSpaces() {},
|
||||
insertWidget() {},
|
||||
invoke: invokeOn(library),
|
||||
isAmpIFrame() {},
|
||||
isArray() {},
|
||||
isCompatModeActive() {},
|
||||
isConsentRequired() {},
|
||||
isEdge: () => false,
|
||||
isFirefox: () => true,
|
||||
isIE6Or7: () => false,
|
||||
isObject,
|
||||
isRecsDestination: () => false,
|
||||
isSafari: () => false,
|
||||
isTextNode: n => n?.nodeType === 3,
|
||||
isTopWindow: () => window === top,
|
||||
jsonpRequest: () => false,
|
||||
loadScript() {},
|
||||
m_accountId: "0",
|
||||
m_activityEvents: false,
|
||||
m_activityState: {
|
||||
activeTime: startTime,
|
||||
currScrollLeft: 0,
|
||||
currScrollTop: 0,
|
||||
exitLink: "",
|
||||
hadHIDActivity: false,
|
||||
maxViewLeft: 1,
|
||||
maxViewTop: 1,
|
||||
parentMetrics: undefined,
|
||||
prevActivityTime: startTime + 2,
|
||||
prevScreenX: 0,
|
||||
prevScreenY: 0,
|
||||
prevScrollLeft: 0,
|
||||
prevScrollTop: 0,
|
||||
prevTime: startTime + 1,
|
||||
prevWindowHeight: 1,
|
||||
prevWindowWidth: 1,
|
||||
scrollDepthPercentage: 0,
|
||||
scrollDepthPixels: 0,
|
||||
},
|
||||
m_atfr: null,
|
||||
m_c1xTpWait: 0,
|
||||
m_clientStorage: {
|
||||
iframeEl: null,
|
||||
iframeIsLoaded: false,
|
||||
iframeOrigin: "https://clientstorage.cxense.com",
|
||||
iframePath: "/clientstorage_v2.html",
|
||||
messageContexts: {},
|
||||
messageQueue: [],
|
||||
},
|
||||
m_compatMode: {},
|
||||
m_compatModeActive: false,
|
||||
m_compatPvSent: false,
|
||||
m_consentVersion: 1,
|
||||
m_customParameters: [],
|
||||
m_documentSizeRequestedFromChild: false,
|
||||
m_externalUserIds: [],
|
||||
m_globalIdLoading: {
|
||||
globalIdIFrameEl: null,
|
||||
globalIdIFrameElLoaded: false,
|
||||
},
|
||||
m_isSpaRecsDestination: false,
|
||||
m_knownMessageSources: [],
|
||||
m_p1Complete: false,
|
||||
m_prevLocationHash: "",
|
||||
m_previousPageViewReport: null,
|
||||
m_rawCustomParameters: {},
|
||||
m_rnd: getRandomString(),
|
||||
m_scriptStartTime: startTime,
|
||||
m_siteId: "0",
|
||||
m_spaRecsClickUrl: null,
|
||||
m_thirdPartyIds: true,
|
||||
m_usesConsent: false,
|
||||
m_usesIabConsent: false,
|
||||
m_usesSecureCookies: true,
|
||||
m_usesTcf20Consent: false,
|
||||
m_widgetSpecs: {},
|
||||
Object,
|
||||
onClearIds() {},
|
||||
onFFP1() {},
|
||||
onP1() {},
|
||||
p1BaseUrl: "https://scdn.cxense.com/sp1.html",
|
||||
p1JsUrl: "https://p1cluster.cxense.com/p1.js",
|
||||
parseHashArgs: () => Object.create(),
|
||||
parseMargins: () => margins,
|
||||
parseUrlArgs: () => Object.create(),
|
||||
postMessageToParent() {},
|
||||
publicWidgetDataUrl: "https://api.cxense.com/public/widget/data",
|
||||
removeClientStorageVariable() {},
|
||||
removeEventListener() {},
|
||||
renderContainedImage: () => "<div/>",
|
||||
renderTemplate: () => "<div/>",
|
||||
reportActivity() {},
|
||||
requireActivityEvents() {},
|
||||
requireConsent() {},
|
||||
requireOnlyFirstPartyIds() {},
|
||||
requireSecureCookies() {},
|
||||
requireTcf20() {},
|
||||
sendEvent,
|
||||
sendSpaRecsClick: (a, callback) => call(callback),
|
||||
setAccountId() {},
|
||||
setAllConsentsTo() {},
|
||||
setClientStorageVariable() {},
|
||||
setCompatMode() {},
|
||||
setConsent() {},
|
||||
setCookie() {},
|
||||
setCustomParameters() {},
|
||||
setEventAttributes() {},
|
||||
setGeoPosition() {},
|
||||
setNodeValue() {},
|
||||
setRandomId() {},
|
||||
setRestrictionsToConsentClasses() {},
|
||||
setRetargetingParameters() {},
|
||||
setSiteId() {},
|
||||
setUserProfileParameters() {},
|
||||
setupIabCmp() {},
|
||||
setupTcfApi() {},
|
||||
shouldPollActivity() {},
|
||||
startLocalStats() {},
|
||||
startSessionAnnotation() {},
|
||||
stopAllSessionAnnotations() {},
|
||||
stopSessionAnnotation() {},
|
||||
sync() {},
|
||||
trackAmpIFrame() {},
|
||||
trackElement() {},
|
||||
trim: s => s.trim(),
|
||||
tsridUrl: "https://tsrid.cxense.com/lookup?callback={{callback}}",
|
||||
userSegmentUrl:
|
||||
"https://api.cxense.com/profile/user/segment?callback={{callback}}",
|
||||
};
|
||||
|
||||
const libraryCCE = {
|
||||
"__cx-toolkit__": {
|
||||
isShown: true,
|
||||
data: [],
|
||||
},
|
||||
activeSnapPoint: null,
|
||||
activeWidgets: [],
|
||||
ccePushUrl,
|
||||
clickTracker: () => "",
|
||||
displayResult() {},
|
||||
displayWidget,
|
||||
getDivId,
|
||||
getTestGroup: () => testGroup,
|
||||
init,
|
||||
insertMaster() {},
|
||||
instrumentClickLinks() {},
|
||||
invoke: invokeOn(libraryCCE),
|
||||
noCache: false,
|
||||
offerProductId: null,
|
||||
persistedQueryId: null,
|
||||
prefix: null,
|
||||
previewCampaign: null,
|
||||
previewDiv: null,
|
||||
previewId: null,
|
||||
previewTestId: null,
|
||||
processCxResult() {},
|
||||
render,
|
||||
reportTestImpression() {},
|
||||
run,
|
||||
runCtrlVersion,
|
||||
runCxVersion,
|
||||
runMulti,
|
||||
runTest,
|
||||
sendConversionEvent,
|
||||
sendPageViewEvent: (a, b, c, callback) => call(callback),
|
||||
setSnapPoints(x) {
|
||||
snapPoints = x;
|
||||
},
|
||||
setTestGroup(x) {
|
||||
testGroup = x;
|
||||
},
|
||||
setVisibilityField() {},
|
||||
get snapPoints() {
|
||||
return snapPoints;
|
||||
},
|
||||
startTime,
|
||||
get testGroup() {
|
||||
return testGroup;
|
||||
},
|
||||
testVariant: null,
|
||||
trackTime: 0.5,
|
||||
trackVisibility() {},
|
||||
updateRecsClickUrls() {},
|
||||
utmParams: [],
|
||||
version: "2.42",
|
||||
visibilityField: "timeHalf",
|
||||
};
|
||||
|
||||
const CCE = {
|
||||
activeSnapPoint: null,
|
||||
activeWidgets: [],
|
||||
callQueue: callQueueCCE,
|
||||
ccePushUrl,
|
||||
clickTracker: () => "",
|
||||
displayResult() {},
|
||||
displayWidget,
|
||||
getDivId,
|
||||
getTestGroup: () => testGroup,
|
||||
init,
|
||||
insertMaster() {},
|
||||
instrumentClickLinks() {},
|
||||
invoke: invokeOn(libraryCCE),
|
||||
library: libraryCCE,
|
||||
noCache: false,
|
||||
offerProductId: null,
|
||||
persistedQueryId: null,
|
||||
prefix: null,
|
||||
previewCampaign: null,
|
||||
previewDiv: null,
|
||||
previewId: null,
|
||||
previewTestId: null,
|
||||
processCxResult() {},
|
||||
render,
|
||||
reportTestImpression() {},
|
||||
run,
|
||||
runCtrlVersion,
|
||||
runCxVersion,
|
||||
runMulti,
|
||||
runTest,
|
||||
sendConversionEvent,
|
||||
sendPageViewEvent: (a, b, c, callback) => call(callback),
|
||||
setSnapPoints(x) {
|
||||
snapPoints = x;
|
||||
},
|
||||
setTestGroup(x) {
|
||||
testGroup = x;
|
||||
},
|
||||
setVisibilityField() {},
|
||||
get snapPoints() {
|
||||
return snapPoints;
|
||||
},
|
||||
startTime,
|
||||
get testGroup() {
|
||||
return testGroup;
|
||||
},
|
||||
testVariant: null,
|
||||
trackTime: 0.5,
|
||||
trackVisibility() {},
|
||||
updateRecsClickUrls() {},
|
||||
utmParams: [],
|
||||
version: "2.42",
|
||||
visibilityField: "timeHalf",
|
||||
};
|
||||
|
||||
window.cX = {
|
||||
addCustomerScript() {},
|
||||
addEventListener() {},
|
||||
addExternalId() {},
|
||||
afterInitializePage() {},
|
||||
allUserConsents: () => undefined,
|
||||
Array,
|
||||
calculateAdSpaceSize: () => 0,
|
||||
callQueue,
|
||||
CCE,
|
||||
cint: () => undefined,
|
||||
clearCustomParameters() {},
|
||||
clearIds() {},
|
||||
clickTracker: () => "",
|
||||
combineArgs: () => Object.create(),
|
||||
combineKeywordsIntoArray: () => [],
|
||||
createDelegate() {},
|
||||
decodeUrlEncodedNameValuePairs: () => Object.create(),
|
||||
defaultAdRenderer: () => "",
|
||||
deleteCookie() {},
|
||||
getAllText: () => "",
|
||||
getClientStorageVariable() {},
|
||||
getCookie: () => null,
|
||||
getCxenseUserId: () => cxUserId,
|
||||
getDocumentSize,
|
||||
getElementPosition: () => topLeft,
|
||||
getHashFragment: () => location.hash.substr(1),
|
||||
getLocalStats: () => Object.create(),
|
||||
getNodeValue: n => n.nodeValue,
|
||||
getNowSeconds,
|
||||
getPageContext,
|
||||
getRandomString,
|
||||
getScrollPos: () => topLeft,
|
||||
getSessionId: () => "",
|
||||
getSiteId: () => "",
|
||||
getTimezoneOffset: () => new Date().getTimezoneOffset(),
|
||||
getTopLevelDomain: () => location.hostname,
|
||||
getUserId: () => userId,
|
||||
getUserSegmentIds,
|
||||
getWindowSize,
|
||||
hasConsent: () => true,
|
||||
hasHistory: () => true,
|
||||
hasLocalStorage: () => true,
|
||||
hasPassiveEventListeners: () => true,
|
||||
hasPostMessage: () => true,
|
||||
hasSessionStorage() {},
|
||||
initializePage() {},
|
||||
insertAdSpace() {},
|
||||
insertMultipleAdSpaces() {},
|
||||
insertWidget() {},
|
||||
invoke: invokeOn(library),
|
||||
isAmpIFrame() {},
|
||||
isArray() {},
|
||||
isCompatModeActive() {},
|
||||
isConsentRequired() {},
|
||||
isEdge: () => false,
|
||||
isFirefox: () => true,
|
||||
isIE6Or7: () => false,
|
||||
isObject,
|
||||
isRecsDestination: () => false,
|
||||
isSafari: () => false,
|
||||
isTextNode: n => n?.nodeType === 3,
|
||||
isTopWindow: () => window === top,
|
||||
JSON,
|
||||
jsonpRequest: () => false,
|
||||
library,
|
||||
loadScript() {},
|
||||
Object,
|
||||
onClearIds() {},
|
||||
onFFP1() {},
|
||||
onP1() {},
|
||||
parseHashArgs: () => Object.create(),
|
||||
parseMargins: () => margins,
|
||||
parseUrlArgs: () => Object.create(),
|
||||
postMessageToParent() {},
|
||||
removeClientStorageVariable() {},
|
||||
removeEventListener() {},
|
||||
renderContainedImage: () => "<div/>",
|
||||
renderTemplate: () => "<div/>",
|
||||
reportActivity() {},
|
||||
requireActivityEvents() {},
|
||||
requireConsent() {},
|
||||
requireOnlyFirstPartyIds() {},
|
||||
requireSecureCookies() {},
|
||||
requireTcf20() {},
|
||||
sendEvent,
|
||||
sendPageViewEvent: (a, callback) => call(callback, {}),
|
||||
sendSpaRecsClick() {},
|
||||
setAccountId() {},
|
||||
setAllConsentsTo() {},
|
||||
setClientStorageVariable() {},
|
||||
setCompatMode() {},
|
||||
setConsent() {},
|
||||
setCookie() {},
|
||||
setCustomParameters() {},
|
||||
setEventAttributes() {},
|
||||
setGeoPosition() {},
|
||||
setNodeValue() {},
|
||||
setRandomId() {},
|
||||
setRestrictionsToConsentClasses() {},
|
||||
setRetargetingParameters() {},
|
||||
setSiteId() {},
|
||||
setUserProfileParameters() {},
|
||||
setupIabCmp() {},
|
||||
setupTcfApi() {},
|
||||
shouldPollActivity() {},
|
||||
startLocalStats() {},
|
||||
startSessionAnnotation() {},
|
||||
stopAllSessionAnnotations() {},
|
||||
stopSessionAnnotation() {},
|
||||
sync() {},
|
||||
trackAmpIFrame() {},
|
||||
trackElement() {},
|
||||
trim: s => s.trim(),
|
||||
};
|
||||
|
||||
window.cxTest = window.cX;
|
||||
|
||||
window.cx_pollActiveTime = () => undefined;
|
||||
window.cx_pollActivity = () => undefined;
|
||||
window.cx_pollFragmentMessage = () => undefined;
|
||||
|
||||
const execQueue = (lib, queue) => {
|
||||
return () => {
|
||||
const invoke = invokeOn(lib);
|
||||
setTimeout(() => {
|
||||
queue.push = cmd => {
|
||||
setTimeout(() => invoke(...cmd), 1);
|
||||
};
|
||||
for (const cmd of queue) {
|
||||
invoke(...cmd);
|
||||
}
|
||||
}, 25);
|
||||
};
|
||||
};
|
||||
|
||||
window.cx_callQueueExecute = execQueue(library, callQueue);
|
||||
window.cxCCE_callQueueExecute = execQueue(libraryCCE, callQueueCCE);
|
||||
|
||||
window.cx_callQueueExecute();
|
||||
window.cxCCE_callQueueExecute();
|
||||
}
|
|
@ -197,8 +197,6 @@
|
|||
|
||||
; WebDriver (Marionette, Remote Agent) remote protocols
|
||||
#ifdef ENABLE_WEBDRIVER
|
||||
@RESPATH@/components/marionette.manifest
|
||||
@RESPATH@/components/marionette.js
|
||||
@RESPATH@/chrome/remote@JAREXT@
|
||||
@RESPATH@/chrome/remote.manifest
|
||||
#endif
|
||||
|
|
|
@ -80,11 +80,11 @@ tab-context-reopen-closed-tabs =
|
|||
*[other] Reopen Closed Tabs
|
||||
}
|
||||
.accesskey = o
|
||||
tab-context-close-tabs =
|
||||
tab-context-close-n-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[1] Close Tab
|
||||
*[other] Close Tabs
|
||||
*[other] Close { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = C
|
||||
tab-context-move-tabs =
|
||||
|
|
|
@ -67,6 +67,7 @@ const TOTAL_URI_COUNT_NORMAL_AND_PRIVATE_MODE_SCALAR_NAME =
|
|||
"browser.engagement.total_uri_count_normal_and_private_mode";
|
||||
|
||||
const CONTENT_PROCESS_COUNT = "CONTENT_PROCESS_COUNT";
|
||||
const CONTENT_PROCESS_PRECISE_COUNT = "CONTENT_PROCESS_PRECISE_COUNT";
|
||||
|
||||
const MINIMUM_TAB_COUNT_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes, in ms
|
||||
const CONTENT_PROCESS_COUNT_INTERVAL_MS = 5 * 60 * 1000;
|
||||
|
@ -433,7 +434,8 @@ let BrowserUsageTelemetry = {
|
|||
Services.prefs.addObserver("browser.tabs.drawInTitlebar", this);
|
||||
|
||||
this._recordUITelemetry();
|
||||
this._contentProcessCountInterval = setInterval(
|
||||
|
||||
this._recordContentProcessCountInterval = setInterval(
|
||||
() => this._recordContentProcessCount(),
|
||||
CONTENT_PROCESS_COUNT_INTERVAL_MS
|
||||
);
|
||||
|
@ -480,7 +482,6 @@ let BrowserUsageTelemetry = {
|
|||
Services.obs.removeObserver(this, TELEMETRY_SUBSESSIONSPLIT_TOPIC);
|
||||
|
||||
clearInterval(this._recordContentProcessCountInterval);
|
||||
this._recordContentProcessCountDelayed = null;
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
|
@ -1276,6 +1277,9 @@ let BrowserUsageTelemetry = {
|
|||
const count = ChromeUtils.getAllDOMProcesses().length - 1;
|
||||
|
||||
Services.telemetry.getHistogramById(CONTENT_PROCESS_COUNT).add(count);
|
||||
Services.telemetry
|
||||
.getHistogramById(CONTENT_PROCESS_PRECISE_COUNT)
|
||||
.add(count);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -22,13 +22,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"WEBEXT_PERMISSION_PROMPTS",
|
||||
"extensions.webextPermissionPrompts",
|
||||
false
|
||||
);
|
||||
|
||||
const DEFAULT_EXTENSION_ICON =
|
||||
"chrome://mozapps/skin/extensions/extensionGeneric.svg";
|
||||
|
||||
|
@ -84,31 +77,29 @@ var ExtensionsUI = {
|
|||
// happening in a specific order.
|
||||
sideloaded.sort((a, b) => a.id.localeCompare(b.id));
|
||||
|
||||
if (WEBEXT_PERMISSION_PROMPTS) {
|
||||
if (!this.sideloadListener) {
|
||||
this.sideloadListener = {
|
||||
onEnabled: addon => {
|
||||
if (!this.sideloaded.has(addon)) {
|
||||
return;
|
||||
}
|
||||
if (!this.sideloadListener) {
|
||||
this.sideloadListener = {
|
||||
onEnabled: addon => {
|
||||
if (!this.sideloaded.has(addon)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.sideloaded.delete(addon);
|
||||
this._updateNotifications();
|
||||
this.sideloaded.delete(addon);
|
||||
this._updateNotifications();
|
||||
|
||||
if (this.sideloaded.size == 0) {
|
||||
AddonManager.removeAddonListener(this.sideloadListener);
|
||||
this.sideloadListener = null;
|
||||
}
|
||||
},
|
||||
};
|
||||
AddonManager.addAddonListener(this.sideloadListener);
|
||||
}
|
||||
|
||||
for (let addon of sideloaded) {
|
||||
this.sideloaded.add(addon);
|
||||
}
|
||||
this._updateNotifications();
|
||||
if (this.sideloaded.size == 0) {
|
||||
AddonManager.removeAddonListener(this.sideloadListener);
|
||||
this.sideloadListener = null;
|
||||
}
|
||||
},
|
||||
};
|
||||
AddonManager.addAddonListener(this.sideloadListener);
|
||||
}
|
||||
|
||||
for (let addon of sideloaded) {
|
||||
this.sideloaded.add(addon);
|
||||
}
|
||||
this._updateNotifications();
|
||||
},
|
||||
|
||||
_updateNotifications() {
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "mozilla/ContentBlocking.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIURIMutator.h"
|
||||
#include "mozilla/PermissionManager.h"
|
||||
|
||||
#include "json/json.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
|
@ -391,8 +392,36 @@ BasePrincipal::EqualsForPermission(nsIPrincipal* aOther, bool aExactHost,
|
|||
NS_ENSURE_ARG_POINTER(aOther);
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
// If the principals are equal, then they match.
|
||||
if (FastEquals(aOther)) {
|
||||
auto* other = Cast(aOther);
|
||||
if (Kind() != other->Kind()) {
|
||||
// Principals of different kinds can't be equal.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (Kind() == eSystemPrincipal) {
|
||||
*aResult = this == other;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (Kind() == eNullPrincipal) {
|
||||
// We don't store permissions for NullPrincipals.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(Kind() == eExpandedPrincipal || Kind() == eContentPrincipal);
|
||||
|
||||
// Certain origin attributes should not be used to isolate permissions.
|
||||
// Create a stripped copy of both OA sets to compare.
|
||||
mozilla::OriginAttributes ourAttrs = mOriginAttributes;
|
||||
PermissionManager::MaybeStripOriginAttributes(false, ourAttrs);
|
||||
mozilla::OriginAttributes theirAttrs = aOther->OriginAttributesRef();
|
||||
PermissionManager::MaybeStripOriginAttributes(false, theirAttrs);
|
||||
|
||||
if (ourAttrs != theirAttrs) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mOriginNoSuffix == other->mOriginNoSuffix) {
|
||||
*aResult = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -403,22 +432,18 @@ BasePrincipal::EqualsForPermission(nsIPrincipal* aOther, bool aExactHost,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Compare their OriginAttributes
|
||||
const mozilla::OriginAttributes& theirAttrs = aOther->OriginAttributesRef();
|
||||
const mozilla::OriginAttributes& ourAttrs = OriginAttributesRef();
|
||||
|
||||
if (theirAttrs != ourAttrs) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> ourURI;
|
||||
nsresult rv = GetURI(getter_AddRefs(ourURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
auto* basePrin = BasePrincipal::Cast(aOther);
|
||||
// Some principal types may indicate success, but still return nullptr for
|
||||
// URI.
|
||||
NS_ENSURE_TRUE(ourURI, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIURI> otherURI;
|
||||
rv = basePrin->GetURI(getter_AddRefs(otherURI));
|
||||
rv = other->GetURI(getter_AddRefs(otherURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(otherURI, NS_ERROR_FAILURE);
|
||||
|
||||
// Compare schemes
|
||||
nsAutoCString otherScheme;
|
||||
rv = otherURI->GetScheme(otherScheme);
|
||||
|
|
|
@ -9,8 +9,8 @@ origin:
|
|||
description: rlbox integration for the wasm2c sandboxed code
|
||||
url: https://github.com/PLSysSec/rlbox_wasm2c_sandbox
|
||||
|
||||
release: commit 3ed74da56a45bc6e556eea60d83995ee2ab962f8 (2021-07-11T21:18:27Z).
|
||||
revision: 3ed74da56a45bc6e556eea60d83995ee2ab962f8
|
||||
release: commit 1cd3e4165d30d3ecc30974744e6fd52caa2a3f1d (2021-07-23T02:53:22Z).
|
||||
revision: 1cd3e4165d30d3ecc30974744e6fd52caa2a3f1d
|
||||
|
||||
license: MIT
|
||||
license-file: LICENSE
|
||||
|
|
|
@ -9,8 +9,8 @@ origin:
|
|||
description: wasm2c fork used for rlbox sandboxing
|
||||
url: https://github.com/PLSysSec/wasm2c_sandbox_compiler
|
||||
|
||||
release: commit 498f15980a553dd41bc6ff97fb22b5ee1c52f701 (2021-07-11T23:33:38Z).
|
||||
revision: 498f15980a553dd41bc6ff97fb22b5ee1c52f701
|
||||
release: commit df7630a80686c1e3bc775a6cb261841e99484b54 (2021-07-28T00:22:29Z).
|
||||
revision: df7630a80686c1e3bc775a6cb261841e99484b54
|
||||
|
||||
license: Apache-2.0
|
||||
license-file: LICENSE
|
||||
|
|
|
@ -503,7 +503,7 @@ $(LIBRARY): $(OBJS) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
|
|||
$(WASM_ARCHIVE): $(CWASMOBJS) $(CPPWASMOBJS) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
|
||||
$(REPORT_BUILD_VERBOSE)
|
||||
$(RM) $(WASM_ARCHIVE)
|
||||
$(WASM_CXX) $(OUTOPTION)$@ -Wl,--export-all $(if $(LUCETC),,-Wl,--no-entry -Wl,--growable-table) $(CWASMOBJS) $(CPPWASMOBJS)
|
||||
$(WASM_CXX) $(OUTOPTION)$@ -Wl,--export-all -Wl,--stack-first -Wl,-z,stack-size=$(if $(MOZ_OPTIMIZE),262144,1048576) $(if $(LUCETC),,-Wl,--no-entry -Wl,--growable-table) $(CWASMOBJS) $(CPPWASMOBJS)
|
||||
|
||||
ifdef LUCETC
|
||||
lucet_options := \
|
||||
|
|
|
@ -589,7 +589,6 @@ system_headers = [
|
|||
'Palettes.h',
|
||||
'PALM_CMN.H',
|
||||
'pango/pango-break.h',
|
||||
'pango/pangocairo.h',
|
||||
'pango/pangofc-decoder.h',
|
||||
'pango/pangofc-font.h',
|
||||
'pango/pangofc-fontmap.h',
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"use strict";
|
||||
|
||||
const Services = require("Services");
|
||||
const { L10nRegistry } = require("resource://gre/modules/L10nRegistry.jsm");
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
|
@ -146,7 +145,7 @@ AccessibilityPanel.prototype = {
|
|||
*/
|
||||
async createFluentBundles() {
|
||||
const locales = Services.locale.appLocalesAsBCP47;
|
||||
const generator = L10nRegistry.generateBundles(locales, [
|
||||
const generator = L10nRegistry.getInstance().generateBundles(locales, [
|
||||
"devtools/client/accessibility.ftl",
|
||||
]);
|
||||
|
||||
|
|
|
@ -4,22 +4,26 @@
|
|||
|
||||
PromiseTestUtils.allowMatchingRejectionsGlobally(/Connection closed/);
|
||||
|
||||
// Test that sources appear in the debugger when navigating using the BFCache.
|
||||
// Test the debugger when navigating using the BFCache.
|
||||
|
||||
add_task(async function() {
|
||||
info("Run test with bfcacheInParent DISABLED");
|
||||
await pushPref("fission.bfcacheInParent", false);
|
||||
await testCase();
|
||||
await testSourcesOnNavigation();
|
||||
await testDebuggerPauseStateOnNavigation();
|
||||
|
||||
// bfcacheInParent only works if sessionHistoryInParent is enable
|
||||
// so only test it if both settings are enabled.
|
||||
if (Services.appinfo.sessionHistoryInParent) {
|
||||
info("Run test with bfcacheInParent ENABLED");
|
||||
await pushPref("fission.bfcacheInParent", true);
|
||||
await testCase();
|
||||
await testSourcesOnNavigation();
|
||||
await testDebuggerPauseStateOnNavigation();
|
||||
}
|
||||
});
|
||||
|
||||
async function testCase() {
|
||||
async function testSourcesOnNavigation() {
|
||||
info("Test that sources appear in the debugger when navigating using the BFCache")
|
||||
const dbg = await initDebugger("doc-bfcache1.html");
|
||||
|
||||
await navigate(dbg, "doc-bfcache2.html", "doc-bfcache2.html");
|
||||
|
@ -33,3 +37,54 @@ async function testCase() {
|
|||
|
||||
await dbg.toolbox.closeToolbox();
|
||||
}
|
||||
|
||||
async function testDebuggerPauseStateOnNavigation() {
|
||||
info("Test the debugger pause state when navigating using the BFCache");
|
||||
|
||||
if (Services.appinfo.sessionHistoryInParent) {
|
||||
enableTargetSwitching();
|
||||
}
|
||||
const dbg = await initDebugger("doc-bfcache1.html");
|
||||
|
||||
await addBreakpoint(dbg, "doc-bfcache1.html", 4);
|
||||
|
||||
await navigate(dbg, "doc-bfcache2.html");
|
||||
await waitForSources(dbg, "doc-bfcache2.html");
|
||||
|
||||
await goBack(EXAMPLE_URL + "doc-bfcache1.html");
|
||||
await waitForSources(dbg, "doc-bfcache1.html");
|
||||
|
||||
await reload(dbg);
|
||||
await waitForPaused(dbg);
|
||||
|
||||
ok(dbg.toolbox.isHighlighted("jsdebugger"), "Debugger is highlighted");
|
||||
|
||||
await goForward(EXAMPLE_URL + "doc-bfcache2.html");
|
||||
|
||||
// This check should be removed when Bug 1722305 is fixed, which would cause will-navigate
|
||||
// to start firing properly with fission.
|
||||
if (!Services.appinfo.sessionHistoryInParent) {
|
||||
await waitUntil(() => !dbg.toolbox.isHighlighted("jsdebugger"));
|
||||
ok(true, "Debugger is not highlighted");
|
||||
}
|
||||
|
||||
dbg.toolbox.closeToolbox();
|
||||
}
|
||||
|
||||
async function goBack(expectedUrl) {
|
||||
const onLocationChange = BrowserTestUtils.waitForLocationChange(
|
||||
gBrowser,
|
||||
expectedUrl
|
||||
);
|
||||
gBrowser.goBack();
|
||||
await onLocationChange;
|
||||
}
|
||||
|
||||
async function goForward(expectedUrl) {
|
||||
const onLocationChange = BrowserTestUtils.waitForLocationChange(
|
||||
gBrowser,
|
||||
expectedUrl
|
||||
);
|
||||
gBrowser.goForward();
|
||||
await onLocationChange;
|
||||
}
|
||||
|
|
|
@ -145,20 +145,3 @@ add_task(async function() {
|
|||
|
||||
|
||||
});
|
||||
|
||||
async function assertDebuggerIsHighlightedAndPaused(toolbox) {
|
||||
info("Wait for the debugger to be automatically selected on pause");
|
||||
await waitUntil(() => toolbox.currentToolId == "jsdebugger");
|
||||
ok(true, "Debugger selected");
|
||||
|
||||
// Wait for the debugger to finish loading.
|
||||
await toolbox.getPanelWhenReady("jsdebugger");
|
||||
|
||||
// And to be fully paused
|
||||
const dbg = createDebuggerContext(toolbox);
|
||||
await waitForPaused(dbg);
|
||||
|
||||
ok(toolbox.isHighlighted("jsdebugger"), "Debugger is highlighted");
|
||||
|
||||
return dbg;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<body>
|
||||
First Page!
|
||||
<script>
|
||||
console.log("First Page!");
|
||||
function goForward() { history.go(1); }
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -1940,6 +1940,29 @@ async function assertNodeIsFocused(dbg, index) {
|
|||
ok(node.classList.contains("focused"), `node ${index} is focused`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the debugger is paused and the debugger tab is
|
||||
* highlighted.
|
||||
* @param {*} toolbox
|
||||
* @returns
|
||||
*/
|
||||
async function assertDebuggerIsHighlightedAndPaused(toolbox) {
|
||||
info("Wait for the debugger to be automatically selected on pause");
|
||||
await waitUntil(() => toolbox.currentToolId == "jsdebugger");
|
||||
ok(true, "Debugger selected");
|
||||
|
||||
// Wait for the debugger to finish loading.
|
||||
await toolbox.getPanelWhenReady("jsdebugger");
|
||||
|
||||
// And to be fully paused
|
||||
const dbg = createDebuggerContext(toolbox);
|
||||
await waitForPaused(dbg);
|
||||
|
||||
ok(toolbox.isHighlighted("jsdebugger"), "Debugger is highlighted");
|
||||
|
||||
return dbg;
|
||||
}
|
||||
|
||||
async function addExpression(dbg, input) {
|
||||
info("Adding an expression");
|
||||
|
||||
|
|
|
@ -3013,6 +3013,18 @@ Toolbox.prototype = {
|
|||
* Fired when user just started navigating away to another web page.
|
||||
*/
|
||||
async _onWillNavigate() {
|
||||
// On navigate, the server will resume all paused threads, but due to an
|
||||
// issue which can cause loosing outgoing messages/RDP packets, the THREAD_STATE
|
||||
// resources for the resumed state might not get received. So let assume it happens
|
||||
// make use the UI is the appropriate state.
|
||||
if (this._pausedTargets > 0) {
|
||||
this.emit("toolbox-resumed");
|
||||
this._pausedTargets = 0;
|
||||
if (this.isHighlighted("jsdebugger")) {
|
||||
this.unhighlightTool("jsdebugger");
|
||||
}
|
||||
}
|
||||
|
||||
// Clearing the error count as soon as we navigate
|
||||
this.setErrorCount(0);
|
||||
this.updateToolboxButtons();
|
||||
|
|
13
devtools/client/performance-new/@types/perf.d.ts
vendored
13
devtools/client/performance-new/@types/perf.d.ts
vendored
|
@ -544,3 +544,16 @@ export type SymbolicationWorkerReplyData<R> =
|
|||
| {
|
||||
error: SymbolicationWorkerError;
|
||||
};
|
||||
|
||||
// This type is used in the symbolication worker for the return type of the
|
||||
// FileAndPathHelper's readFile method.
|
||||
// FIXME: Or rather, this type *would* be used if the worker code was checked
|
||||
// by TypeScript.
|
||||
export interface FileHandle {
|
||||
// Return the length of the file in bytes.
|
||||
getLength: () => number;
|
||||
// Synchronously read the bytes at offset `offset` into the array `dest`.
|
||||
readBytesInto: (dest: Uint8Array, offset: number) => void;
|
||||
// Called when the file is no longer needed, to allow closing the file.
|
||||
drop: () => void;
|
||||
}
|
||||
|
|
|
@ -6,213 +6,32 @@
|
|||
// THIS FILE IS AUTOGENERATED by wasm-bindgen.
|
||||
//
|
||||
// Generated from:
|
||||
// https://github.com/mstange/profiler-get-symbols/commit/90ee39f1d18d2727f07dc57bd93cff6bc73ce8a0
|
||||
// https://github.com/mstange/profiler-get-symbols/commit/c1dca28a2a506df40f0a6f32c12ba51ec54b02be
|
||||
// by following the instructions in that repository's Readme.md
|
||||
//
|
||||
|
||||
let wasm_bindgen;
|
||||
(function() {
|
||||
const __exports = {};
|
||||
let wasm;
|
||||
|
||||
let cachegetInt32Memory = null;
|
||||
function getInt32Memory() {
|
||||
if (cachegetInt32Memory === null || cachegetInt32Memory.buffer !== wasm.memory.buffer) {
|
||||
cachegetInt32Memory = new Int32Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachegetInt32Memory;
|
||||
}
|
||||
|
||||
let cachegetUint32Memory = null;
|
||||
function getUint32Memory() {
|
||||
if (cachegetUint32Memory === null || cachegetUint32Memory.buffer !== wasm.memory.buffer) {
|
||||
cachegetUint32Memory = new Uint32Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachegetUint32Memory;
|
||||
}
|
||||
|
||||
function getArrayU32FromWasm(ptr, len) {
|
||||
return getUint32Memory().subarray(ptr / 4, ptr / 4 + len);
|
||||
}
|
||||
|
||||
let cachegetUint8Memory = null;
|
||||
function getUint8Memory() {
|
||||
if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== wasm.memory.buffer) {
|
||||
cachegetUint8Memory = new Uint8Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachegetUint8Memory;
|
||||
}
|
||||
|
||||
function getArrayU8FromWasm(ptr, len) {
|
||||
return getUint8Memory().subarray(ptr / 1, ptr / 1 + len);
|
||||
}
|
||||
|
||||
const heap = new Array(32);
|
||||
|
||||
heap.fill(undefined);
|
||||
const heap = new Array(32).fill(undefined);
|
||||
|
||||
heap.push(undefined, null, true, false);
|
||||
|
||||
let stack_pointer = 32;
|
||||
|
||||
function addBorrowedObject(obj) {
|
||||
if (stack_pointer == 1) throw new Error('out of js stack');
|
||||
heap[--stack_pointer] = obj;
|
||||
return stack_pointer;
|
||||
}
|
||||
|
||||
function _assertClass(instance, klass) {
|
||||
if (!(instance instanceof klass)) {
|
||||
throw new Error(`expected instance of ${klass.name}`);
|
||||
}
|
||||
return instance.ptr;
|
||||
}
|
||||
|
||||
let WASM_VECTOR_LEN = 0;
|
||||
|
||||
let cachedTextEncoder = new TextEncoder('utf-8');
|
||||
|
||||
let passStringToWasm;
|
||||
if (typeof cachedTextEncoder.encodeInto === 'function') {
|
||||
passStringToWasm = function(arg) {
|
||||
|
||||
|
||||
let size = arg.length;
|
||||
let ptr = wasm.__wbindgen_malloc(size);
|
||||
let offset = 0;
|
||||
{
|
||||
const mem = getUint8Memory();
|
||||
for (; offset < arg.length; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset !== arg.length) {
|
||||
arg = arg.slice(offset);
|
||||
ptr = wasm.__wbindgen_realloc(ptr, size, size = offset + arg.length * 3);
|
||||
const view = getUint8Memory().subarray(ptr + offset, ptr + size);
|
||||
const ret = cachedTextEncoder.encodeInto(arg, view);
|
||||
|
||||
offset += ret.written;
|
||||
}
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
};
|
||||
} else {
|
||||
passStringToWasm = function(arg) {
|
||||
|
||||
|
||||
let size = arg.length;
|
||||
let ptr = wasm.__wbindgen_malloc(size);
|
||||
let offset = 0;
|
||||
{
|
||||
const mem = getUint8Memory();
|
||||
for (; offset < arg.length; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset !== arg.length) {
|
||||
const buf = cachedTextEncoder.encode(arg.slice(offset));
|
||||
ptr = wasm.__wbindgen_realloc(ptr, size, size = offset + buf.length);
|
||||
getUint8Memory().set(buf, ptr + offset);
|
||||
offset += buf.length;
|
||||
}
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @param {WasmMemBuffer} binary_data
|
||||
* @param {WasmMemBuffer} debug_data
|
||||
* @param {string} breakpad_id
|
||||
* @returns {CompactSymbolTable}
|
||||
*/
|
||||
__exports.get_compact_symbol_table = function(binary_data, debug_data, breakpad_id) {
|
||||
_assertClass(binary_data, WasmMemBuffer);
|
||||
_assertClass(debug_data, WasmMemBuffer);
|
||||
const ret = wasm.get_compact_symbol_table(binary_data.ptr, debug_data.ptr, passStringToWasm(breakpad_id), WASM_VECTOR_LEN);
|
||||
return CompactSymbolTable.__wrap(ret);
|
||||
};
|
||||
|
||||
function getObject(idx) { return heap[idx]; }
|
||||
|
||||
function debugString(val) {
|
||||
// primitive types
|
||||
const type = typeof val;
|
||||
if (type == 'number' || type == 'boolean' || val == null) {
|
||||
return `${val}`;
|
||||
}
|
||||
if (type == 'string') {
|
||||
return `"${val}"`;
|
||||
}
|
||||
if (type == 'symbol') {
|
||||
const description = val.description;
|
||||
if (description == null) {
|
||||
return 'Symbol';
|
||||
} else {
|
||||
return `Symbol(${description})`;
|
||||
}
|
||||
}
|
||||
if (type == 'function') {
|
||||
const name = val.name;
|
||||
if (typeof name == 'string' && name.length > 0) {
|
||||
return `Function(${name})`;
|
||||
} else {
|
||||
return 'Function';
|
||||
}
|
||||
}
|
||||
// objects
|
||||
if (Array.isArray(val)) {
|
||||
const length = val.length;
|
||||
let debug = '[';
|
||||
if (length > 0) {
|
||||
debug += debugString(val[0]);
|
||||
}
|
||||
for(let i = 1; i < length; i++) {
|
||||
debug += ', ' + debugString(val[i]);
|
||||
}
|
||||
debug += ']';
|
||||
return debug;
|
||||
}
|
||||
// Test for built-in
|
||||
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
|
||||
let className;
|
||||
if (builtInMatches.length > 1) {
|
||||
className = builtInMatches[1];
|
||||
} else {
|
||||
// Failed to match the standard '[object ClassName]'
|
||||
return toString.call(val);
|
||||
}
|
||||
if (className == 'Object') {
|
||||
// we're a user defined class or Object
|
||||
// JSON.stringify avoids problems with cycles, and is generally much
|
||||
// easier than looping through ownProperties of `val`.
|
||||
try {
|
||||
return 'Object(' + JSON.stringify(val) + ')';
|
||||
} catch (_) {
|
||||
return 'Object';
|
||||
}
|
||||
}
|
||||
// errors
|
||||
if (val instanceof Error) {
|
||||
return `${val.name}: ${val.message}\n${val.stack}`;
|
||||
}
|
||||
// TODO we could test for more things here, like `Set`s and `Map`s.
|
||||
return className;
|
||||
}
|
||||
|
||||
let cachedTextDecoder = new TextDecoder('utf-8');
|
||||
|
||||
function getStringFromWasm(ptr, len) {
|
||||
return cachedTextDecoder.decode(getUint8Memory().subarray(ptr, ptr + len));
|
||||
}
|
||||
|
||||
let heap_next = heap.length;
|
||||
|
||||
function addHeapObject(obj) {
|
||||
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||
const idx = heap_next;
|
||||
heap_next = heap[idx];
|
||||
|
||||
heap[idx] = obj;
|
||||
return idx;
|
||||
}
|
||||
|
||||
function dropObject(idx) {
|
||||
if (idx < 36) return;
|
||||
heap[idx] = heap_next;
|
||||
|
@ -225,202 +44,413 @@ function takeObject(idx) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
function addHeapObject(obj) {
|
||||
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||
const idx = heap_next;
|
||||
heap_next = heap[idx];
|
||||
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
||||
|
||||
heap[idx] = obj;
|
||||
return idx;
|
||||
cachedTextDecoder.decode();
|
||||
|
||||
let cachegetUint8Memory0 = null;
|
||||
function getUint8Memory0() {
|
||||
if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
|
||||
cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachegetUint8Memory0;
|
||||
}
|
||||
|
||||
function handleError(e) {
|
||||
wasm.__wbindgen_exn_store(addHeapObject(e));
|
||||
function getStringFromWasm0(ptr, len) {
|
||||
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
|
||||
}
|
||||
/**
|
||||
*/
|
||||
class CompactSymbolTable {
|
||||
|
||||
static __wrap(ptr) {
|
||||
const obj = Object.create(CompactSymbolTable.prototype);
|
||||
obj.ptr = ptr;
|
||||
let WASM_VECTOR_LEN = 0;
|
||||
|
||||
return obj;
|
||||
}
|
||||
let cachedTextEncoder = new TextEncoder('utf-8');
|
||||
|
||||
free() {
|
||||
const ptr = this.ptr;
|
||||
this.ptr = 0;
|
||||
|
||||
wasm.__wbg_compactsymboltable_free(ptr);
|
||||
}
|
||||
/**
|
||||
* @returns {CompactSymbolTable}
|
||||
*/
|
||||
constructor() {
|
||||
const ret = wasm.compactsymboltable_new();
|
||||
return CompactSymbolTable.__wrap(ret);
|
||||
}
|
||||
/**
|
||||
* @returns {Uint32Array}
|
||||
*/
|
||||
take_addr() {
|
||||
const retptr = 8;
|
||||
const ret = wasm.compactsymboltable_take_addr(retptr, this.ptr);
|
||||
const memi32 = getInt32Memory();
|
||||
const v0 = getArrayU32FromWasm(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1]).slice();
|
||||
wasm.__wbindgen_free(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1] * 4);
|
||||
return v0;
|
||||
}
|
||||
/**
|
||||
* @returns {Uint32Array}
|
||||
*/
|
||||
take_index() {
|
||||
const retptr = 8;
|
||||
const ret = wasm.compactsymboltable_take_index(retptr, this.ptr);
|
||||
const memi32 = getInt32Memory();
|
||||
const v0 = getArrayU32FromWasm(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1]).slice();
|
||||
wasm.__wbindgen_free(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1] * 4);
|
||||
return v0;
|
||||
}
|
||||
/**
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
take_buffer() {
|
||||
const retptr = 8;
|
||||
const ret = wasm.compactsymboltable_take_buffer(retptr, this.ptr);
|
||||
const memi32 = getInt32Memory();
|
||||
const v0 = getArrayU8FromWasm(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1]).slice();
|
||||
wasm.__wbindgen_free(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1] * 1);
|
||||
return v0;
|
||||
}
|
||||
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
||||
? function (arg, view) {
|
||||
return cachedTextEncoder.encodeInto(arg, view);
|
||||
}
|
||||
__exports.CompactSymbolTable = CompactSymbolTable;
|
||||
/**
|
||||
* WasmMemBuffer lets you allocate a chunk of memory on the wasm heap and
|
||||
* directly initialize it from JS without a copy. The constructor takes the
|
||||
* allocation size and a callback function which does the initialization.
|
||||
* This is useful if you need to get very large amounts of data from JS into
|
||||
* wasm (for example, the contents of a 1.7GB libxul.so).
|
||||
*/
|
||||
class WasmMemBuffer {
|
||||
: function (arg, view) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
view.set(buf);
|
||||
return {
|
||||
read: arg.length,
|
||||
written: buf.length
|
||||
};
|
||||
});
|
||||
|
||||
static __wrap(ptr) {
|
||||
const obj = Object.create(WasmMemBuffer.prototype);
|
||||
obj.ptr = ptr;
|
||||
function passStringToWasm0(arg, malloc, realloc) {
|
||||
|
||||
return obj;
|
||||
if (realloc === undefined) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
const ptr = malloc(buf.length);
|
||||
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
|
||||
WASM_VECTOR_LEN = buf.length;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
free() {
|
||||
const ptr = this.ptr;
|
||||
this.ptr = 0;
|
||||
let len = arg.length;
|
||||
let ptr = malloc(len);
|
||||
|
||||
wasm.__wbg_wasmmembuffer_free(ptr);
|
||||
const mem = getUint8Memory0();
|
||||
|
||||
let offset = 0;
|
||||
|
||||
for (; offset < len; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
/**
|
||||
* Create the buffer and initialize it synchronously in the callback function.
|
||||
* f is called with one argument: the Uint8Array that wraps our buffer.
|
||||
* f should not return anything; its return value is ignored.
|
||||
* f must not call any exported wasm functions! Anything that causes the
|
||||
* wasm heap to resize will invalidate the typed array\'s internal buffer!
|
||||
* Do not hold on to the array that is passed to f after f completes.
|
||||
* @param {number} byte_length
|
||||
* @param {any} f
|
||||
* @returns {WasmMemBuffer}
|
||||
*/
|
||||
constructor(byte_length, f) {
|
||||
|
||||
if (offset !== len) {
|
||||
if (offset !== 0) {
|
||||
arg = arg.slice(offset);
|
||||
}
|
||||
ptr = realloc(ptr, len, len = offset + arg.length * 3);
|
||||
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
|
||||
const ret = encodeString(arg, view);
|
||||
|
||||
offset += ret.written;
|
||||
}
|
||||
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function isLikeNone(x) {
|
||||
return x === undefined || x === null;
|
||||
}
|
||||
|
||||
let cachegetInt32Memory0 = null;
|
||||
function getInt32Memory0() {
|
||||
if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) {
|
||||
cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachegetInt32Memory0;
|
||||
}
|
||||
|
||||
function makeMutClosure(arg0, arg1, dtor, f) {
|
||||
const state = { a: arg0, b: arg1, cnt: 1, dtor };
|
||||
const real = (...args) => {
|
||||
// First up with a closure we increment the internal reference
|
||||
// count. This ensures that the Rust closure environment won't
|
||||
// be deallocated while we're invoking it.
|
||||
state.cnt++;
|
||||
const a = state.a;
|
||||
state.a = 0;
|
||||
try {
|
||||
const ret = wasm.wasmmembuffer_new(byte_length, addBorrowedObject(f));
|
||||
return WasmMemBuffer.__wrap(ret);
|
||||
return f(a, state.b, ...args);
|
||||
} finally {
|
||||
heap[stack_pointer++] = undefined;
|
||||
if (--state.cnt === 0) {
|
||||
wasm.__wbindgen_export_2.get(state.dtor)(a, state.b);
|
||||
|
||||
} else {
|
||||
state.a = a;
|
||||
}
|
||||
}
|
||||
};
|
||||
real.original = state;
|
||||
|
||||
return real;
|
||||
}
|
||||
function __wbg_adapter_18(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h0f6e06591fd1eecd(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function handleError(f, args) {
|
||||
try {
|
||||
return f.apply(this, args);
|
||||
} catch (e) {
|
||||
wasm.__wbindgen_exn_store(addHeapObject(e));
|
||||
}
|
||||
}
|
||||
function __wbg_adapter_33(arg0, arg1, arg2, arg3) {
|
||||
wasm.wasm_bindgen__convert__closures__invoke2_mut__hb11591fa7d9b8977(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
* ```js
|
||||
* async function getSymbolTable(debugName, breakpadId, libKeyToPathMap) {
|
||||
* const helper = {
|
||||
* getCandidatePathsForBinaryOrPdb: (debugName, breakpadId) => {
|
||||
* const path = libKeyToPathMap.get(`${debugName}/${breakpadId}`);
|
||||
* if (path !== undefined) {
|
||||
* return [path];
|
||||
* }
|
||||
* return [];
|
||||
* },
|
||||
* readFile: async (filename) => {
|
||||
* const byteLength = await getFileSizeInBytes(filename);
|
||||
* const fileHandle = getFileHandle(filename);
|
||||
* return {
|
||||
* getLength: () => byteLength,
|
||||
* readBytesInto: (array, offset) => {
|
||||
* syncReadFilePartIntoBuffer(fileHandle, array, offset);
|
||||
* },
|
||||
* drop: () => {},
|
||||
* };
|
||||
* },
|
||||
* };
|
||||
*
|
||||
* const [addr, index, buffer] = await getCompactSymbolTable(debugName, breakpadId, helper);
|
||||
* return [addr, index, buffer];
|
||||
* }
|
||||
* ```
|
||||
* @param {string} debug_name
|
||||
* @param {string} breakpad_id
|
||||
* @param {any} helper
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
__exports.getCompactSymbolTable = function(debug_name, breakpad_id, helper) {
|
||||
var ptr0 = passStringToWasm0(debug_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len0 = WASM_VECTOR_LEN;
|
||||
var ptr1 = passStringToWasm0(breakpad_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len1 = WASM_VECTOR_LEN;
|
||||
var ret = wasm.getCompactSymbolTable(ptr0, len0, ptr1, len1, addHeapObject(helper));
|
||||
return takeObject(ret);
|
||||
};
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
* ```js
|
||||
* async function getSymbolTable(url, requestJSONString, libKeyToPathMap) {
|
||||
* const helper = {
|
||||
* getCandidatePathsForBinaryOrPdb: (debugName, breakpadId) => {
|
||||
* const path = libKeyToPathMap.get(`${debugName}/${breakpadId}`);
|
||||
* if (path !== undefined) {
|
||||
* return [path];
|
||||
* }
|
||||
* return [];
|
||||
* },
|
||||
* readFile: async (filename) => {
|
||||
* const byteLength = await getFileSizeInBytes(filename);
|
||||
* const fileHandle = getFileHandle(filename);
|
||||
* return {
|
||||
* getLength: () => byteLength,
|
||||
* readBytesInto: (array, offset) => {
|
||||
* syncReadFilePartIntoBuffer(fileHandle, array, offset);
|
||||
* },
|
||||
* drop: () => {},
|
||||
* };
|
||||
* },
|
||||
* };
|
||||
*
|
||||
* const responseJSONString = await queryAPI(deburlugName, requestJSONString, helper);
|
||||
* return responseJSONString;
|
||||
* }
|
||||
* ```
|
||||
* @param {string} url
|
||||
* @param {string} request_json
|
||||
* @param {any} helper
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
__exports.queryAPI = function(url, request_json, helper) {
|
||||
var ptr0 = passStringToWasm0(url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len0 = WASM_VECTOR_LEN;
|
||||
var ptr1 = passStringToWasm0(request_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len1 = WASM_VECTOR_LEN;
|
||||
var ret = wasm.queryAPI(ptr0, len0, ptr1, len1, addHeapObject(helper));
|
||||
return takeObject(ret);
|
||||
};
|
||||
|
||||
async function load(module, imports) {
|
||||
if (typeof Response === 'function' && module instanceof Response) {
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
try {
|
||||
return await WebAssembly.instantiateStreaming(module, imports);
|
||||
|
||||
} catch (e) {
|
||||
if (module.headers.get('Content-Type') != 'application/wasm') {
|
||||
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bytes = await module.arrayBuffer();
|
||||
return await WebAssembly.instantiate(bytes, imports);
|
||||
|
||||
} else {
|
||||
const instance = await WebAssembly.instantiate(module, imports);
|
||||
|
||||
if (instance instanceof WebAssembly.Instance) {
|
||||
return { instance, module };
|
||||
|
||||
} else {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
__exports.WasmMemBuffer = WasmMemBuffer;
|
||||
|
||||
function init(module) {
|
||||
|
||||
let result;
|
||||
async function init(input) {
|
||||
if (typeof input === 'undefined') {
|
||||
let src;
|
||||
if (typeof document === 'undefined') {
|
||||
src = location.href;
|
||||
} else {
|
||||
src = document.currentScript.src;
|
||||
}
|
||||
input = src.replace(/\.js$/, '_bg.wasm');
|
||||
}
|
||||
const imports = {};
|
||||
imports.wbg = {};
|
||||
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
||||
const ret = debugString(getObject(arg1));
|
||||
const ret0 = passStringToWasm(ret);
|
||||
const ret1 = WASM_VECTOR_LEN;
|
||||
getInt32Memory()[arg0 / 4 + 0] = ret0;
|
||||
getInt32Memory()[arg0 / 4 + 1] = ret1;
|
||||
};
|
||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||
throw new Error(getStringFromWasm(arg0, arg1));
|
||||
};
|
||||
imports.wbg.__wbindgen_rethrow = function(arg0) {
|
||||
throw takeObject(arg0);
|
||||
};
|
||||
imports.wbg.__wbindgen_memory = function() {
|
||||
const ret = wasm.memory;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_buffer_aa8ebea80955a01a = function(arg0) {
|
||||
const ret = getObject(arg0).buffer;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_newwithbyteoffsetandlength_3e607c21646a8aef = function(arg0, arg1, arg2) {
|
||||
const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
|
||||
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
|
||||
var ret = getObject(arg0);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_drop_6095f5f9a28379e4 = function() { return handleError(function (arg0) {
|
||||
getObject(arg0).drop();
|
||||
}, arguments) };
|
||||
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
|
||||
takeObject(arg0);
|
||||
};
|
||||
imports.wbg.__wbg_call_9c879b23724d007e = function(arg0, arg1, arg2) {
|
||||
try {
|
||||
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
|
||||
return addHeapObject(ret);
|
||||
} catch (e) {
|
||||
handleError(e)
|
||||
imports.wbg.__wbg_call_3fc07b7d5fc9022d = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
var ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
|
||||
var ret = getStringFromWasm0(arg0, arg1);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_readFile_1005cc171b90cf75 = function(arg0, arg1, arg2) {
|
||||
var ret = getObject(arg0).readFile(getStringFromWasm0(arg1, arg2));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_then_6c9a4bf55755f9b8 = function(arg0, arg1, arg2) {
|
||||
var ret = getObject(arg0).then(getObject(arg1), getObject(arg2));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_cb_drop = function(arg0) {
|
||||
const obj = takeObject(arg0).original;
|
||||
if (obj.cnt-- == 1) {
|
||||
obj.a = 0;
|
||||
return true;
|
||||
}
|
||||
var ret = false;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_getLength_83c461bbda972f3b = function() { return handleError(function (arg0) {
|
||||
var ret = getObject(arg0).getLength();
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_name_966f168ad0e59c92 = function(arg0) {
|
||||
var ret = getObject(arg0).name;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_message_e440fbd911a845a2 = function(arg0) {
|
||||
var ret = getObject(arg0).message;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_memory = function() {
|
||||
var ret = wasm.memory;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_buffer_9e184d6f785de5ed = function(arg0) {
|
||||
var ret = getObject(arg0).buffer;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_newwithbyteoffsetandlength_d92dfdd78c30c55a = function(arg0, arg1, arg2) {
|
||||
var ret = new Uint32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_new_71de2365d17503e7 = function(arg0) {
|
||||
var ret = new Uint32Array(getObject(arg0));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_newwithbyteoffsetandlength_e57ad1f2ce812c03 = function(arg0, arg1, arg2) {
|
||||
var ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_new_e8101319e4cf95fc = function(arg0) {
|
||||
var ret = new Uint8Array(getObject(arg0));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_of_7c797480f9ceac60 = function(arg0, arg1, arg2) {
|
||||
var ret = Array.of(getObject(arg0), getObject(arg1), getObject(arg2));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_json_parse = function(arg0, arg1) {
|
||||
const ret = JSON.parse(getStringFromWasm(arg0, arg1));
|
||||
var ret = JSON.parse(getStringFromWasm0(arg0, arg1));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_readBytesInto_02ee0cacc563822d = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
getObject(arg0).readBytesInto(takeObject(arg1), arg2);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_getCandidatePathsForBinaryOrPdb_6ff1ea4b13b7cbee = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
||||
var ret = getObject(arg0).getCandidatePathsForBinaryOrPdb(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_from_f4f6c9225e58242f = function(arg0) {
|
||||
var ret = Array.from(getObject(arg0));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_length_555f836564bf148d = function(arg0) {
|
||||
var ret = getObject(arg0).length;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_get_b7bbf50adcc94294 = function(arg0, arg1) {
|
||||
var ret = getObject(arg0)[arg1 >>> 0];
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_new_c143a4f563f78c4e = function(arg0, arg1) {
|
||||
try {
|
||||
var state0 = {a: arg0, b: arg1};
|
||||
var cb0 = (arg0, arg1) => {
|
||||
const a = state0.a;
|
||||
state0.a = 0;
|
||||
try {
|
||||
return __wbg_adapter_33(a, state0.b, arg0, arg1);
|
||||
} finally {
|
||||
state0.a = a;
|
||||
}
|
||||
};
|
||||
var ret = new Promise(cb0);
|
||||
return addHeapObject(ret);
|
||||
} finally {
|
||||
state0.a = state0.b = 0;
|
||||
}
|
||||
};
|
||||
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
|
||||
const obj = getObject(arg1);
|
||||
var ret = typeof(obj) === 'string' ? obj : undefined;
|
||||
var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len0 = WASM_VECTOR_LEN;
|
||||
getInt32Memory0()[arg0 / 4 + 1] = len0;
|
||||
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
|
||||
};
|
||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
imports.wbg.__wbg_then_c2361a9d5c9a4fcb = function(arg0, arg1) {
|
||||
var ret = getObject(arg0).then(getObject(arg1));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_resolve_cae3d8f752f5db88 = function(arg0) {
|
||||
var ret = Promise.resolve(getObject(arg0));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper230 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 70, __wbg_adapter_18);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
|
||||
if (module instanceof URL || typeof module === 'string' || module instanceof Request) {
|
||||
|
||||
const response = fetch(module);
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
result = WebAssembly.instantiateStreaming(response, imports)
|
||||
.catch(e => {
|
||||
console.warn("`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||
return response
|
||||
.then(r => r.arrayBuffer())
|
||||
.then(bytes => WebAssembly.instantiate(bytes, imports));
|
||||
});
|
||||
} else {
|
||||
result = response
|
||||
.then(r => r.arrayBuffer())
|
||||
.then(bytes => WebAssembly.instantiate(bytes, imports));
|
||||
}
|
||||
} else {
|
||||
|
||||
result = WebAssembly.instantiate(module, imports)
|
||||
.then(result => {
|
||||
if (result instanceof WebAssembly.Instance) {
|
||||
return { instance: result, module };
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
});
|
||||
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
|
||||
input = fetch(input);
|
||||
}
|
||||
return result.then(({instance, module}) => {
|
||||
wasm = instance.exports;
|
||||
init.__wbindgen_wasm_module = module;
|
||||
|
||||
return wasm;
|
||||
});
|
||||
|
||||
|
||||
const { instance, module } = await load(await input, imports);
|
||||
|
||||
wasm = instance.exports;
|
||||
init.__wbindgen_wasm_module = module;
|
||||
|
||||
return wasm;
|
||||
}
|
||||
|
||||
self.wasm_bindgen = Object.assign(init, __exports);
|
||||
wasm_bindgen = Object.assign(init, __exports);
|
||||
|
||||
})();
|
||||
|
|
|
@ -19,6 +19,7 @@ importScripts(
|
|||
|
||||
/**
|
||||
* @typedef {import("./@types/perf").SymbolicationWorkerInitialMessage} SymbolicationWorkerInitialMessage
|
||||
* @typedef {import("./@types/perf").FileHandle} FileHandle
|
||||
*/
|
||||
|
||||
// This worker uses the wasm module that was generated from https://github.com/mstange/profiler-get-symbols.
|
||||
|
@ -29,60 +30,55 @@ importScripts(
|
|||
// itself.
|
||||
|
||||
/* eslint camelcase: 0*/
|
||||
const { WasmMemBuffer, get_compact_symbol_table } = wasm_bindgen;
|
||||
const { getCompactSymbolTable } = wasm_bindgen;
|
||||
|
||||
// Read an open OS.File instance into the Uint8Array dataBuf.
|
||||
function readFileInto(file, dataBuf) {
|
||||
// Ideally we'd be able to call file.readTo(dataBuf) here, but readTo no
|
||||
// longer exists.
|
||||
// So instead, we copy the file over into wasm memory in 4MB chunks. This
|
||||
// will take 425 invocations for a a 1.7GB file (such as libxul.so for a
|
||||
// Firefox for Android build) and not take up too much memory per call.
|
||||
const dataBufLen = dataBuf.byteLength;
|
||||
// Read parts of an open OS.File instance into the Uint8Array dataBuf.
|
||||
// This reads destBuf.byteLength bytes at offset offset.
|
||||
function readFileBytesInto(file, offset, destBuf) {
|
||||
file.setPosition(offset);
|
||||
// We read the file in 4MB chunks. This limits the amount of temporary
|
||||
// memory we use while we copy the file contents into wasm memory.
|
||||
const chunkSize = 4 * 1024 * 1024;
|
||||
let pos = 0;
|
||||
while (pos < dataBufLen) {
|
||||
const chunkData = file.read({ bytes: chunkSize });
|
||||
let posInDestBuf = 0;
|
||||
let remainingBytes = destBuf.byteLength;
|
||||
while (remainingBytes > 0) {
|
||||
const bytes = remainingBytes > chunkSize ? chunkSize : remainingBytes;
|
||||
const chunkData = file.read({ bytes });
|
||||
const chunkBytes = chunkData.byteLength;
|
||||
if (chunkBytes === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
dataBuf.set(chunkData, pos);
|
||||
pos += chunkBytes;
|
||||
destBuf.set(chunkData, posInDestBuf);
|
||||
posInDestBuf += chunkBytes;
|
||||
remainingBytes -= chunkBytes;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a plain object that is Structured Cloneable and has name and
|
||||
// description properties.
|
||||
// message properties.
|
||||
function createPlainErrorObject(e) {
|
||||
// OS.File.Error has an empty message property; it constructs the error
|
||||
// message on-demand in its toString() method. So we handle those errors
|
||||
// specially.
|
||||
if (!(e instanceof OS.File.Error)) {
|
||||
// Regular errors: just rewrap the object.
|
||||
if (e instanceof Error) {
|
||||
const { name, message, fileName, lineNumber } = e;
|
||||
return { name, message, fileName, lineNumber };
|
||||
}
|
||||
// The WebAssembly code throws errors with fields error_type and error_msg.
|
||||
if (e.error_type) {
|
||||
return {
|
||||
name: e.error_type,
|
||||
message: e.error_msg,
|
||||
};
|
||||
}
|
||||
if (e instanceof OS.File.Error) {
|
||||
// OS.File.Error has an empty message property; it constructs the error
|
||||
// message on-demand in its toString() method. So we handle those errors
|
||||
// specially.
|
||||
return {
|
||||
name: "OSFileError",
|
||||
message: e.toString(),
|
||||
fileName: e.fileName,
|
||||
lineNumber: e.lineNumber,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: e instanceof OS.File.Error ? "OSFileError" : "Error",
|
||||
message: e.toString(),
|
||||
fileName: e.fileName,
|
||||
lineNumber: e.lineNumber,
|
||||
};
|
||||
// Regular errors: just rewrap the object.
|
||||
const { name, message, fileName, lineNumber } = e;
|
||||
return { name, message, fileName, lineNumber };
|
||||
}
|
||||
|
||||
class PathHelper {
|
||||
/**
|
||||
* A FileAndPathHelper object is passed to getCompactSymbolTable, which calls
|
||||
* the methods `getCandidatePathsForBinaryOrPdb` and `readFile` on it.
|
||||
*/
|
||||
class FileAndPathHelper {
|
||||
constructor(libInfoMap, objdirs) {
|
||||
this._libInfoMap = libInfoMap;
|
||||
this._objdirs = objdirs;
|
||||
|
@ -90,12 +86,13 @@ class PathHelper {
|
|||
|
||||
/**
|
||||
* Enumerate all paths at which we could find files with symbol information.
|
||||
* This method is called by wasm code (via the bindings).
|
||||
*
|
||||
* @param {string} debugName
|
||||
* @param {string} breakpadId
|
||||
* @returns {Array<{ path: string, debugPath: string }>}
|
||||
* @returns {Array<string>}
|
||||
*/
|
||||
getCandidatePaths(debugName, breakpadId) {
|
||||
getCandidatePathsForBinaryOrPdb(debugName, breakpadId) {
|
||||
const key = `${debugName}:${breakpadId}`;
|
||||
const lib = this._libInfoMap.get(key);
|
||||
if (!lib) {
|
||||
|
@ -121,91 +118,66 @@ class PathHelper {
|
|||
// a system library.
|
||||
for (const objdirPath of this._objdirs) {
|
||||
// Binaries are usually expected to exist at objdir/dist/bin/filename.
|
||||
candidatePaths.push({
|
||||
path: OS.Path.join(objdirPath, "dist", "bin", name),
|
||||
debugPath: OS.Path.join(objdirPath, "dist", "bin", name),
|
||||
});
|
||||
candidatePaths.push(OS.Path.join(objdirPath, "dist", "bin", name));
|
||||
// Also search in the "objdir" directory itself (not just in dist/bin).
|
||||
// If, for some unforeseen reason, the relevant binary is not inside the
|
||||
// objdirs dist/bin/ directory, this provides a way out because it lets the
|
||||
// user specify the actual location.
|
||||
candidatePaths.push({
|
||||
path: OS.Path.join(objdirPath, name),
|
||||
debugPath: OS.Path.join(objdirPath, name),
|
||||
});
|
||||
candidatePaths.push(OS.Path.join(objdirPath, name));
|
||||
}
|
||||
|
||||
// Check the absolute paths of the library file(s) last.
|
||||
// Check the absolute paths of the library last.
|
||||
// We do this after the objdir search because the library's path may point
|
||||
// to a stripped binary, which will have fewer symbols than the original
|
||||
// binaries in the objdir.
|
||||
candidatePaths.push({ path, debugPath });
|
||||
if (debugPath !== path) {
|
||||
// We're on Windows, and debugPath points to a PDB file.
|
||||
// On non-Windows, path and debugPath are always the same.
|
||||
|
||||
// Check the PDB file before the binary because the PDB has the symbol
|
||||
// information. The binary is only used as a last-ditch fallback
|
||||
// for things like Windows system libraries (e.g. graphics drivers).
|
||||
candidatePaths.push(debugPath);
|
||||
}
|
||||
|
||||
// The location of the binary. If the profile was obtained on this machine
|
||||
// (and not, for example, on an Android device), this file should always
|
||||
// exist.
|
||||
candidatePaths.push(path);
|
||||
|
||||
return candidatePaths;
|
||||
}
|
||||
}
|
||||
|
||||
function getCompactSymbolTableFromPath(binaryPath, debugPath, breakpadId) {
|
||||
// Read the binary file into WASM memory.
|
||||
const binaryFile = OS.File.open(binaryPath, { read: true });
|
||||
const binaryData = new WasmMemBuffer(binaryFile.stat().size, array => {
|
||||
readFileInto(binaryFile, array);
|
||||
});
|
||||
binaryFile.close();
|
||||
|
||||
// Do the same for the debug file, if it is supplied and different from the
|
||||
// binary file. This is only the case on Windows.
|
||||
let debugData = binaryData;
|
||||
if (debugPath && debugPath !== binaryPath) {
|
||||
const debugFile = OS.File.open(debugPath, { read: true });
|
||||
debugData = new WasmMemBuffer(debugFile.stat().size, array => {
|
||||
readFileInto(debugFile, array);
|
||||
});
|
||||
debugFile.close();
|
||||
}
|
||||
|
||||
try {
|
||||
const output = get_compact_symbol_table(binaryData, debugData, breakpadId);
|
||||
const result = [
|
||||
output.take_addr(),
|
||||
output.take_index(),
|
||||
output.take_buffer(),
|
||||
];
|
||||
output.free();
|
||||
return result;
|
||||
} finally {
|
||||
binaryData.free();
|
||||
if (debugData != binaryData) {
|
||||
debugData.free();
|
||||
/**
|
||||
* Asynchronously prepare the file at `path` for synchronous reading.
|
||||
* This method is called by wasm code (via the bindings).
|
||||
*
|
||||
* @param {string} path
|
||||
* @returns {FileHandle}
|
||||
*/
|
||||
async readFile(path) {
|
||||
const file = OS.File.open(path, { read: true });
|
||||
const info = file.stat();
|
||||
if (info.isDir) {
|
||||
throw new Error(`Path "${path}" is a directory.`);
|
||||
}
|
||||
|
||||
const fileSize = info.size;
|
||||
|
||||
// Create and return a FileHandle object. The methods of this object are
|
||||
// called by wasm code (via the bindings).
|
||||
return {
|
||||
getLength: () => fileSize,
|
||||
readBytesInto: (dest, offset) => {
|
||||
readFileBytesInto(file, offset, dest);
|
||||
},
|
||||
drop: () => {
|
||||
file.close();
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getSymbolTableInWorker(debugName, breakpadId, libInfoMap, objdirs) {
|
||||
const helper = new PathHelper(libInfoMap, objdirs);
|
||||
const candidatePaths = helper.getCandidatePaths(debugName, breakpadId);
|
||||
|
||||
const errors = [];
|
||||
for (const { path, debugPath } of candidatePaths) {
|
||||
try {
|
||||
return getCompactSymbolTableFromPath(path, debugPath, breakpadId);
|
||||
} catch (e) {
|
||||
// getCompactSymbolTableFromPath was unsuccessful. So either the
|
||||
// file wasn't parseable or its contents didn't match the specified
|
||||
// breakpadId, or some other error occurred.
|
||||
// Advance to the next candidate path.
|
||||
errors.push(e);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Could not obtain symbols for the library ${debugName} ${breakpadId} ` +
|
||||
`because there was no matching file at any of the candidate paths: ${JSON.stringify(
|
||||
candidatePaths
|
||||
)}. Errors: ${errors.map(e => e.message).join(", ")}`
|
||||
);
|
||||
}
|
||||
|
||||
/** @param {MessageEvent<SymbolicationWorkerInitialMessage>} e */
|
||||
onmessage = async e => {
|
||||
try {
|
||||
|
@ -218,12 +190,8 @@ onmessage = async e => {
|
|||
// Instantiate the WASM module.
|
||||
await wasm_bindgen(module);
|
||||
|
||||
const result = getSymbolTableInWorker(
|
||||
debugName,
|
||||
breakpadId,
|
||||
libInfoMap,
|
||||
objdirs
|
||||
);
|
||||
const helper = new FileAndPathHelper(libInfoMap, objdirs);
|
||||
const result = await getCompactSymbolTable(debugName, breakpadId, helper);
|
||||
postMessage(
|
||||
{ result },
|
||||
result.map(r => r.buffer)
|
||||
|
|
|
@ -45,12 +45,15 @@ const global = this;
|
|||
// The hash check ensures that the contents of the wasm module are what we
|
||||
// expect them to be.
|
||||
// The source code is at https://github.com/mstange/profiler-get-symbols/ .
|
||||
// Documentation is at https://docs.rs/profiler-get-symbols/ .
|
||||
// The sha384 sum can be computed with the following command (tested on macOS):
|
||||
// shasum -b -a 384 profiler_get_symbols_wasm_bg.wasm | awk '{ print $1 }' | xxd -r -p | base64
|
||||
|
||||
// Generated from https://github.com/mstange/profiler-get-symbols/commit/90ee39f1d18d2727f07dc57bd93cff6bc73ce8a0
|
||||
// Generated from https://github.com/mstange/profiler-get-symbols/commit/c1dca28a2a506df40f0a6f32c12ba51ec54b02be
|
||||
const WASM_MODULE_URL =
|
||||
"https://zealous-rosalind-a98ce8.netlify.com/wasm/8f7ca2f70e1cd21b5a2dbe96545672752887bfbd4e7b3b9437e9fc7c3da0a3bedae4584ff734f0c9f08c642e6b66ffab.wasm";
|
||||
"https://storage.googleapis.com/firefox-profiler-get-symbols/c1dca28a2a506df40f0a6f32c12ba51ec54b02be.wasm";
|
||||
const WASM_MODULE_INTEGRITY =
|
||||
"sha384-j3yi9w4c0htaLb6WVFZydSiHv71OezuUN+n8fD2go77a5FhP9zTwyfCMZC5rZv+r";
|
||||
"sha384-ZWi2jwcKJr20rE2gmHjFQGHgsCF9CagkyPLsrIZfmf5QKD2oXgkLa8tMKHK6zPA1";
|
||||
|
||||
const EXPIRY_TIME_IN_MS = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
|
|
|
@ -448,6 +448,12 @@ function withAboutProfiling(callback) {
|
|||
"about:profiling",
|
||||
async contentBrowser => {
|
||||
info("about:profiling is now open in a tab.");
|
||||
await BrowserTestUtils.waitForCondition(
|
||||
() =>
|
||||
contentBrowser.contentDocument.getElementById("root")
|
||||
.firstElementChild,
|
||||
"Document's root has been populated"
|
||||
);
|
||||
return callback(contentBrowser.contentDocument);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
const Services = require("Services");
|
||||
|
||||
const FluentReact = require("devtools/client/shared/vendor/fluent-react");
|
||||
const { L10nRegistry } = require("resource://gre/modules/L10nRegistry.jsm");
|
||||
|
||||
/**
|
||||
* Wrapper over FluentReact. It encapsulates instantiation of the localization
|
||||
|
@ -30,7 +29,10 @@ class FluentL10n {
|
|||
}
|
||||
|
||||
const locales = Services.locale.appLocalesAsBCP47;
|
||||
const generator = L10nRegistry.generateBundles(locales, resourceIds);
|
||||
const generator = L10nRegistry.getInstance().generateBundles(
|
||||
locales,
|
||||
resourceIds
|
||||
);
|
||||
|
||||
this._bundles = [];
|
||||
for await (const bundle of generator) {
|
||||
|
|
|
@ -95,6 +95,8 @@ const URL_ROOT_MOCHI_8888 = CHROME_URL_ROOT.replace(
|
|||
"http://mochi.test:8888/"
|
||||
);
|
||||
|
||||
const TARGET_SWITCHING_PREF = "devtools.target-switching.server.enabled";
|
||||
|
||||
try {
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/shared/test/telemetry-test-helpers.js",
|
||||
|
@ -1124,6 +1126,13 @@ function isWindows() {
|
|||
return Services.appinfo.OS === "WINNT";
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables server target switching
|
||||
*/
|
||||
async function enableTargetSwitching() {
|
||||
await pushPref(TARGET_SWITCHING_PREF, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a given toolbox to get its title updated.
|
||||
*/
|
||||
|
|
|
@ -53,7 +53,6 @@ const STORAGE_PREF = "devtools.storage.enabled";
|
|||
const DOM_CACHE = "dom.caches.enabled";
|
||||
const DUMPEMIT_PREF = "devtools.dump.emit";
|
||||
const DEBUGGERLOG_PREF = "devtools.debugger.log";
|
||||
const TARGET_SWITCHING_PREF = "devtools.target-switching.server.enabled";
|
||||
|
||||
// Allows Cache API to be working on usage `http` test page
|
||||
const CACHES_ON_HTTP_PREF = "dom.caches.testing.enabled";
|
||||
|
@ -226,13 +225,6 @@ function forceCollections() {
|
|||
Cu.forceShrinkingGC();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables server target switching
|
||||
*/
|
||||
async function enableTargetSwitching() {
|
||||
await pushPref(TARGET_SWITCHING_PREF, true);
|
||||
}
|
||||
|
||||
// Sends a click event on the passed DOM node in an async manner
|
||||
function click(node) {
|
||||
node.scrollIntoView();
|
||||
|
|
|
@ -29,6 +29,7 @@ const {
|
|||
DOMQuad,
|
||||
DOMRect,
|
||||
HeapSnapshot,
|
||||
L10nRegistry,
|
||||
NamedNodeMap,
|
||||
NodeFilter,
|
||||
StructuredCloneHolder,
|
||||
|
@ -266,6 +267,7 @@ exports.globals = {
|
|||
FileReader,
|
||||
FormData,
|
||||
isWorker: false,
|
||||
L10nRegistry,
|
||||
loader: {
|
||||
lazyGetter: defineLazyGetter,
|
||||
lazyImporter: defineLazyModuleGetter,
|
||||
|
|
|
@ -71,7 +71,7 @@ exports.CommandsFactory = {
|
|||
},
|
||||
|
||||
/**
|
||||
* For now, this method is only used by browser_target_list_various_descriptors.js
|
||||
* For now, this method is only used by browser_target_command_various_descriptors.js
|
||||
* in order to cover about:debugging codepath, where we connect to remote tabs via
|
||||
* their current outerWindowID.
|
||||
* But:
|
||||
|
|
|
@ -179,7 +179,7 @@ class LegacyServiceWorkersWatcher extends LegacyWorkersWatcher {
|
|||
// has cleaned up its reducers, which happens on "will-navigate".
|
||||
// On the other end, "dom-complete", which is a better mapping of "navigate", is
|
||||
// happening too late (because of resources being throttled), and would cause failures
|
||||
// in test (like browser_target_list_service_workers_navigation.js), as the new worker
|
||||
// in test (like browser_target_command_service_workers_navigation.js), as the new worker
|
||||
// target would already be registered at this point, and seen as something that would
|
||||
// need to be destroyed.
|
||||
if (resource.name === "dom-loading") {
|
||||
|
|
|
@ -15,22 +15,22 @@ support-files =
|
|||
test_sw_page_worker.js
|
||||
test_worker.js
|
||||
|
||||
[browser_target_command_bfcache.js]
|
||||
[browser_target_command_browser_workers.js]
|
||||
[browser_target_command_frames.js]
|
||||
[browser_target_command_getAllTargets.js]
|
||||
[browser_target_command_invalid_api_usage.js]
|
||||
[browser_target_command_preffedoff.js]
|
||||
[browser_target_command_processes.js]
|
||||
[browser_target_command_reload.js]
|
||||
[browser_target_invalid_api_usage.js]
|
||||
[browser_target_list_bfcache.js]
|
||||
[browser_target_list_browser_workers.js]
|
||||
[browser_target_list_frames.js]
|
||||
[browser_target_list_getAllTargets.js]
|
||||
[browser_target_list_preffedoff.js]
|
||||
[browser_target_list_processes.js]
|
||||
[browser_target_list_service_workers.js]
|
||||
[browser_target_list_service_workers_navigation.js]
|
||||
[browser_target_list_switchToTarget.js]
|
||||
[browser_target_list_tab_workers.js]
|
||||
[browser_target_list_tab_workers_bfcache_navigation.js]
|
||||
[browser_target_command_service_workers.js]
|
||||
[browser_target_command_service_workers_navigation.js]
|
||||
[browser_target_command_switchToTarget.js]
|
||||
[browser_target_command_tab_workers.js]
|
||||
[browser_target_command_tab_workers_bfcache_navigation.js]
|
||||
skip-if = debug # Bug 1721859
|
||||
[browser_target_list_various_descriptors.js]
|
||||
[browser_target_command_various_descriptors.js]
|
||||
skip-if =
|
||||
os == "linux" && bits == 64 && !debug #Bug 1701056
|
||||
[browser_target_list_watchTargets.js]
|
||||
[browser_target_command_watchTargets.js]
|
||||
[browser_watcher_actor_getter_caching.js]
|
||||
|
|
|
@ -91,10 +91,12 @@ add_task(async function() {
|
|||
);
|
||||
|
||||
info("Check that navigating away does destroy all targets");
|
||||
const onBrowserLoaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
BrowserTestUtils.loadURI(
|
||||
tab.linkedBrowser,
|
||||
"data:text/html,<meta charset=utf8>Away"
|
||||
);
|
||||
await onBrowserLoaded;
|
||||
|
||||
await waitFor(
|
||||
() => destroyedTargets.length === 2,
|
||||
|
@ -104,29 +106,26 @@ add_task(async function() {
|
|||
info("Navigate back to the first page");
|
||||
gBrowser.goBack();
|
||||
|
||||
// Bug 1722709 - Disable the following assertions until we figure out what's wrong with WorkerDebugger API
|
||||
if (!isFissionEnabled()) {
|
||||
await waitFor(
|
||||
() => targets.length === 4,
|
||||
"Wait for the target list to notify us about the first page workers, restored from the BF Cache"
|
||||
);
|
||||
await waitFor(
|
||||
() => targets.length === 4,
|
||||
"Wait for the target list to notify us about the first page workers, restored from the BF Cache"
|
||||
);
|
||||
|
||||
const mainPageWorkerTargetAfterGoingBack = targets.find(
|
||||
t => t !== mainPageWorkerTarget && t.url == `${WORKER_URL}#simple-worker`
|
||||
);
|
||||
const iframeWorkerTargetAfterGoingBack = targets.find(
|
||||
t =>
|
||||
t !== iframeWorkerTarget &&
|
||||
t.url == `${IFRAME_WORKER_URL}#simple-worker-in-iframe`
|
||||
);
|
||||
const mainPageWorkerTargetAfterGoingBack = targets.find(
|
||||
t => t !== mainPageWorkerTarget && t.url == `${WORKER_URL}#simple-worker`
|
||||
);
|
||||
const iframeWorkerTargetAfterGoingBack = targets.find(
|
||||
t =>
|
||||
t !== iframeWorkerTarget &&
|
||||
t.url == `${IFRAME_WORKER_URL}#simple-worker-in-iframe`
|
||||
);
|
||||
|
||||
ok(
|
||||
mainPageWorkerTargetAfterGoingBack,
|
||||
"The target list handled the worker created from the BF Cache"
|
||||
);
|
||||
ok(
|
||||
iframeWorkerTargetAfterGoingBack,
|
||||
"The target list handled the worker created in the iframe from the BF Cache"
|
||||
);
|
||||
}
|
||||
ok(
|
||||
mainPageWorkerTargetAfterGoingBack,
|
||||
"The target list handled the worker created from the BF Cache"
|
||||
);
|
||||
ok(
|
||||
iframeWorkerTargetAfterGoingBack,
|
||||
"The target list handled the worker created in the iframe from the BF Cache"
|
||||
);
|
||||
});
|
|
@ -47,6 +47,7 @@
|
|||
#include "SessionStoreFunctions.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsImportModule.h"
|
||||
#include "UnitTransforms.h"
|
||||
|
||||
#ifdef NS_PRINTING
|
||||
# include "mozilla/embedding/printingui/PrintingParent.h"
|
||||
|
@ -2551,6 +2552,86 @@ void CanonicalBrowsingContext::CloneDocumentTreeInto(
|
|||
[self = RefPtr{this}]() { self->mClonePromise = nullptr; });
|
||||
}
|
||||
|
||||
bool CanonicalBrowsingContext::StartApzAutoscroll(float aAnchorX,
|
||||
float aAnchorY,
|
||||
nsViewID aScrollId,
|
||||
uint32_t aPresShellId) {
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
mozilla::layers::LayersId layersId{0};
|
||||
|
||||
if (IsInProcess()) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> outer = GetDOMWindow();
|
||||
if (!outer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
widget = widget::WidgetUtils::DOMWindowToWidget(outer);
|
||||
if (widget) {
|
||||
layersId = widget->GetRootLayerTreeId();
|
||||
}
|
||||
} else {
|
||||
RefPtr<BrowserParent> parent = GetBrowserParent();
|
||||
if (!parent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
widget = parent->GetWidget();
|
||||
layersId = parent->GetLayersId();
|
||||
}
|
||||
|
||||
if (!widget || !widget->AsyncPanZoomEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The anchor coordinates that are passed in are relative to the origin
|
||||
// of the screen, but we are sending them to APZ which only knows about
|
||||
// coordinates relative to the widget, so convert them accordingly.
|
||||
CSSPoint anchorCss{aAnchorX, aAnchorY};
|
||||
LayoutDeviceIntPoint anchor =
|
||||
RoundedToInt(anchorCss * widget->GetDefaultScale());
|
||||
anchor -= widget->WidgetToScreenOffset();
|
||||
|
||||
mozilla::layers::ScrollableLayerGuid guid(layersId, aPresShellId, aScrollId);
|
||||
|
||||
return widget->StartAsyncAutoscroll(
|
||||
ViewAs<ScreenPixel>(
|
||||
anchor, PixelCastJustification::LayoutDeviceIsScreenForBounds),
|
||||
guid);
|
||||
}
|
||||
|
||||
void CanonicalBrowsingContext::StopApzAutoscroll(nsViewID aScrollId,
|
||||
uint32_t aPresShellId) {
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
mozilla::layers::LayersId layersId{0};
|
||||
|
||||
if (IsInProcess()) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> outer = GetDOMWindow();
|
||||
if (!outer) {
|
||||
return;
|
||||
}
|
||||
|
||||
widget = widget::WidgetUtils::DOMWindowToWidget(outer);
|
||||
if (widget) {
|
||||
layersId = widget->GetRootLayerTreeId();
|
||||
}
|
||||
} else {
|
||||
RefPtr<BrowserParent> parent = GetBrowserParent();
|
||||
if (!parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
widget = parent->GetWidget();
|
||||
layersId = parent->GetLayersId();
|
||||
}
|
||||
|
||||
if (!widget || !widget->AsyncPanZoomEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::layers::ScrollableLayerGuid guid(layersId, aPresShellId, aScrollId);
|
||||
widget->StopAsyncAutoscroll(guid);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(CanonicalBrowsingContext)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CanonicalBrowsingContext,
|
||||
|
|
|
@ -345,6 +345,10 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||
return mClonePromise;
|
||||
}
|
||||
|
||||
bool StartApzAutoscroll(float aAnchorX, float aAnchorY, nsViewID aScrollId,
|
||||
uint32_t aPresShellId);
|
||||
void StopApzAutoscroll(nsViewID aScrollId, uint32_t aPresShellId);
|
||||
|
||||
protected:
|
||||
// Called when the browsing context is being discarded.
|
||||
void CanonicalDiscard();
|
||||
|
|
|
@ -259,7 +259,7 @@ load 1619322.html
|
|||
asserts(0-1) load 1623918.html # May hit an assertion if the <input> element's anonymous tree hasn't been flushed when IMEContentObserver handles focus
|
||||
load 1656925.html
|
||||
skip-if(Android) load 1665792.html # Print preview on android doesn't fly
|
||||
load 1681729.html
|
||||
load 1693049.html
|
||||
load 1697525.html
|
||||
skip-if(ThreadSanitizer) load 1681729.html
|
||||
skip-if(ThreadSanitizer) load 1693049.html
|
||||
skip-if(ThreadSanitizer) load 1697525.html
|
||||
skip-if(ThreadSanitizer) load 1712198.html # Mysterious failure that should be investigated (bug 1712866).
|
||||
|
|
|
@ -3189,16 +3189,6 @@ void nsFrameLoader::AttributeChanged(mozilla::dom::Element* aElement,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the RequestNotifyAfterRemotePaint message to the current Tab.
|
||||
*/
|
||||
void nsFrameLoader::RequestNotifyAfterRemotePaint() {
|
||||
// If remote browsing (e10s), handle this with the BrowserParent.
|
||||
if (auto* browserParent = GetBrowserParent()) {
|
||||
Unused << browserParent->SendRequestNotifyAfterRemotePaint();
|
||||
}
|
||||
}
|
||||
|
||||
void nsFrameLoader::RequestUpdatePosition(ErrorResult& aRv) {
|
||||
if (auto* browserParent = GetBrowserParent()) {
|
||||
nsresult rv = browserParent->UpdatePosition();
|
||||
|
|
|
@ -218,8 +218,6 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||
void ActivateFrameEvent(const nsAString& aType, bool aCapture,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
void RequestNotifyAfterRemotePaint();
|
||||
|
||||
void RequestUpdatePosition(mozilla::ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> RequestTabStateFlush(mozilla::ErrorResult& aRv);
|
||||
|
|
|
@ -280,6 +280,16 @@ DOMInterfaces = {
|
|||
'nativeType': 'mozilla::intl::FluentBundle',
|
||||
},
|
||||
|
||||
'FluentBundleAsyncIterator': {
|
||||
'headerFile': 'mozilla/intl/L10nRegistry.h',
|
||||
'nativeType': 'mozilla::intl::FluentBundleAsyncIterator',
|
||||
},
|
||||
|
||||
'FluentBundleIterator': {
|
||||
'headerFile': 'mozilla/intl/L10nRegistry.h',
|
||||
'nativeType': 'mozilla::intl::FluentBundleIterator',
|
||||
},
|
||||
|
||||
'FluentPattern': {
|
||||
'headerFile': 'mozilla/intl/FluentBundle.h',
|
||||
'nativeType': 'mozilla::intl::FluentPattern',
|
||||
|
@ -445,6 +455,10 @@ DOMInterfaces = {
|
|||
'nativeType': 'mozilla::intl::L10nFileSource',
|
||||
},
|
||||
|
||||
'L10nRegistry': {
|
||||
'nativeType': 'mozilla::intl::L10nRegistry',
|
||||
},
|
||||
|
||||
'LegacyMozTCPSocket': {
|
||||
'headerFile': 'TCPSocket.h',
|
||||
'wrapperCache': False,
|
||||
|
|
|
@ -3730,20 +3730,26 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
assert needInterfacePrototypeObject
|
||||
|
||||
def defineAlias(alias):
|
||||
if alias == "@@iterator":
|
||||
symbolJSID = "SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::iterator))"
|
||||
if alias == "@@iterator" or alias == "@@asyncIterator":
|
||||
name = alias[2:]
|
||||
|
||||
symbolJSID = (
|
||||
"SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::%s))"
|
||||
% name
|
||||
)
|
||||
prop = "%sId" % name
|
||||
getSymbolJSID = CGGeneric(
|
||||
fill(
|
||||
"JS::Rooted<jsid> iteratorId(aCx, ${symbolJSID});",
|
||||
"JS::Rooted<jsid> ${prop}(aCx, ${symbolJSID});",
|
||||
prop=prop,
|
||||
symbolJSID=symbolJSID,
|
||||
)
|
||||
)
|
||||
defineFn = "JS_DefinePropertyById"
|
||||
prop = "iteratorId"
|
||||
enumFlags = "0" # Not enumerable, per spec.
|
||||
elif alias.startswith("@@"):
|
||||
raise TypeError(
|
||||
"Can't handle any well-known Symbol other than @@iterator"
|
||||
"Can't handle any well-known Symbol other than @@iterator and @@asyncIterator"
|
||||
)
|
||||
else:
|
||||
getSymbolJSID = None
|
||||
|
|
|
@ -43,7 +43,7 @@ class CacheInvalidator {
|
|||
// -
|
||||
|
||||
class AbstractCache {
|
||||
typedef std::vector<const CacheInvalidator*> InvalidatorListT;
|
||||
using InvalidatorListT = std::vector<const CacheInvalidator*>;
|
||||
|
||||
private:
|
||||
InvalidatorListT mInvalidators;
|
||||
|
@ -122,9 +122,8 @@ class CacheWeakMap final {
|
|||
}
|
||||
};
|
||||
|
||||
typedef std::unordered_map<const KeyT*, UniquePtr<Entry>, DerefHash,
|
||||
DerefEqual>
|
||||
MapT;
|
||||
using MapT =
|
||||
std::unordered_map<const KeyT*, UniquePtr<Entry>, DerefHash, DerefEqual>;
|
||||
MapT mMap;
|
||||
|
||||
public:
|
||||
|
|
|
@ -62,8 +62,8 @@ struct ImageCacheEntryData {
|
|||
|
||||
class ImageCacheEntry : public PLDHashEntryHdr {
|
||||
public:
|
||||
typedef ImageCacheKey KeyType;
|
||||
typedef const ImageCacheKey* KeyTypePointer;
|
||||
using KeyType = ImageCacheKey;
|
||||
using KeyTypePointer = const ImageCacheKey*;
|
||||
|
||||
explicit ImageCacheEntry(const KeyType* aKey)
|
||||
: mData(new ImageCacheEntryData(*aKey)) {}
|
||||
|
@ -95,8 +95,8 @@ struct AllCanvasImageCacheKey {
|
|||
|
||||
class AllCanvasImageCacheEntry : public PLDHashEntryHdr {
|
||||
public:
|
||||
typedef AllCanvasImageCacheKey KeyType;
|
||||
typedef const AllCanvasImageCacheKey* KeyTypePointer;
|
||||
using KeyType = AllCanvasImageCacheKey;
|
||||
using KeyTypePointer = const AllCanvasImageCacheKey*;
|
||||
|
||||
explicit AllCanvasImageCacheEntry(const KeyType* aKey)
|
||||
: mImage(aKey->mImage) {}
|
||||
|
|
|
@ -23,7 +23,7 @@ class imgIContainer;
|
|||
namespace mozilla {
|
||||
|
||||
class CanvasImageCache {
|
||||
typedef mozilla::gfx::SourceSurface SourceSurface;
|
||||
using SourceSurface = mozilla::gfx::SourceSurface;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
|
|
@ -259,8 +259,8 @@ bool CanvasRenderingContext2D::PatternIsOpaque(
|
|||
// GeneralPattern class in gfxContext.cpp with this one.
|
||||
class CanvasGeneralPattern {
|
||||
public:
|
||||
typedef CanvasRenderingContext2D::Style Style;
|
||||
typedef CanvasRenderingContext2D::ContextState ContextState;
|
||||
using Style = CanvasRenderingContext2D::Style;
|
||||
using ContextState = CanvasRenderingContext2D::ContextState;
|
||||
|
||||
Pattern& ForStyle(CanvasRenderingContext2D* aCtx, Style aStyle,
|
||||
DrawTarget* aRT) {
|
||||
|
@ -341,7 +341,7 @@ class CanvasGeneralPattern {
|
|||
*/
|
||||
class AdjustedTargetForFilter {
|
||||
public:
|
||||
typedef CanvasRenderingContext2D::ContextState ContextState;
|
||||
using ContextState = CanvasRenderingContext2D::ContextState;
|
||||
|
||||
AdjustedTargetForFilter(CanvasRenderingContext2D* aCtx,
|
||||
DrawTarget* aFinalTarget,
|
||||
|
@ -488,7 +488,7 @@ class AdjustedTargetForFilter {
|
|||
*/
|
||||
class AdjustedTargetForShadow {
|
||||
public:
|
||||
typedef CanvasRenderingContext2D::ContextState ContextState;
|
||||
using ContextState = CanvasRenderingContext2D::ContextState;
|
||||
|
||||
AdjustedTargetForShadow(CanvasRenderingContext2D* aCtx,
|
||||
DrawTarget* aFinalTarget, const gfx::Rect& aBounds,
|
||||
|
@ -574,7 +574,7 @@ class AdjustedTargetForShadow {
|
|||
*/
|
||||
class AdjustedTarget {
|
||||
public:
|
||||
typedef CanvasRenderingContext2D::ContextState ContextState;
|
||||
using ContextState = CanvasRenderingContext2D::ContextState;
|
||||
|
||||
explicit AdjustedTarget(CanvasRenderingContext2D* aCtx,
|
||||
const gfx::Rect* aBounds = nullptr) {
|
||||
|
@ -3490,7 +3490,7 @@ bool CanvasRenderingContext2D::GetHitRegionRect(Element* aElement,
|
|||
*/
|
||||
struct MOZ_STACK_CLASS CanvasBidiProcessor
|
||||
: public nsBidiPresUtils::BidiProcessor {
|
||||
typedef CanvasRenderingContext2D::Style Style;
|
||||
using Style = CanvasRenderingContext2D::Style;
|
||||
|
||||
CanvasBidiProcessor()
|
||||
: nsBidiPresUtils::BidiProcessor(),
|
||||
|
@ -3512,7 +3512,7 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor
|
|||
}
|
||||
}
|
||||
|
||||
typedef CanvasRenderingContext2D::ContextState ContextState;
|
||||
using ContextState = CanvasRenderingContext2D::ContextState;
|
||||
|
||||
virtual void SetText(const char16_t* aText, int32_t aLength,
|
||||
nsBidiDirection aDirection) override {
|
||||
|
|
|
@ -42,8 +42,8 @@ enum class LayersBackend : int8_t;
|
|||
namespace dom {
|
||||
class
|
||||
HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap;
|
||||
typedef HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap
|
||||
CanvasImageSource;
|
||||
using CanvasImageSource =
|
||||
HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap;
|
||||
class ImageBitmap;
|
||||
class ImageData;
|
||||
class UTF8StringOrCanvasGradientOrCanvasPattern;
|
||||
|
|
|
@ -598,9 +598,9 @@ class WebGLVertexArrayJS final : public nsWrapperCache, public webgl::ObjectJS {
|
|||
|
||||
////////////////////////////////////
|
||||
|
||||
typedef dom::MaybeSharedFloat32ArrayOrUnrestrictedFloatSequence Float32ListU;
|
||||
typedef dom::MaybeSharedInt32ArrayOrLongSequence Int32ListU;
|
||||
typedef dom::MaybeSharedUint32ArrayOrUnsignedLongSequence Uint32ListU;
|
||||
using Float32ListU = dom::MaybeSharedFloat32ArrayOrUnrestrictedFloatSequence;
|
||||
using Int32ListU = dom::MaybeSharedInt32ArrayOrLongSequence;
|
||||
using Uint32ListU = dom::MaybeSharedUint32ArrayOrUnsignedLongSequence;
|
||||
|
||||
inline Range<const float> MakeRange(const Float32ListU& list) {
|
||||
if (list.IsFloat32Array()) return MakeRangeAbv(list.GetAsFloat32Array());
|
||||
|
|
|
@ -612,7 +612,7 @@ namespace ipc {
|
|||
|
||||
template <typename Actor>
|
||||
struct IPDLParamTraits<mozilla::dom::IpdlProducer<Actor>> {
|
||||
typedef mozilla::dom::IpdlProducer<Actor> paramType;
|
||||
using paramType = mozilla::dom::IpdlProducer<Actor>;
|
||||
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
|
@ -629,7 +629,7 @@ struct IPDLParamTraits<mozilla::dom::IpdlProducer<Actor>> {
|
|||
|
||||
template <typename Actor>
|
||||
struct IPDLParamTraits<mozilla::dom::IpdlConsumer<Actor>> {
|
||||
typedef mozilla::dom::IpdlConsumer<Actor> paramType;
|
||||
using paramType = mozilla::dom::IpdlConsumer<Actor>;
|
||||
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
|
@ -648,7 +648,7 @@ struct IPDLParamTraits<mozilla::dom::IpdlConsumer<Actor>> {
|
|||
|
||||
template <>
|
||||
struct IPDLParamTraits<mozilla::dom::IpdlQueueBuffer> {
|
||||
typedef mozilla::dom::IpdlQueueBuffer paramType;
|
||||
using paramType = mozilla::dom::IpdlQueueBuffer;
|
||||
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const paramType& aParam) {
|
||||
|
|
|
@ -51,8 +51,8 @@ inline bool operator!(const QueueStatus status) { return !IsSuccess(status); }
|
|||
|
||||
template <typename T>
|
||||
struct RemoveCVR {
|
||||
typedef typename std::remove_reference<typename std::remove_cv<T>::type>::type
|
||||
Type;
|
||||
using Type =
|
||||
typename std::remove_reference<typename std::remove_cv<T>::type>::type;
|
||||
};
|
||||
|
||||
inline size_t UsedBytes(size_t aQueueBufferSize, size_t aRead, size_t aWrite) {
|
||||
|
@ -341,8 +341,8 @@ struct QueueParamTraits<bool> {
|
|||
// (namely ContiguousEnumValidator and ContiguousEnumValidatorInclusive).
|
||||
template <typename E, typename EnumValidator>
|
||||
struct EnumSerializer {
|
||||
typedef E ParamType;
|
||||
typedef typename std::underlying_type<E>::type DataType;
|
||||
using ParamType = E;
|
||||
using DataType = typename std::underlying_type<E>::type;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& aProducerView,
|
||||
|
|
|
@ -343,7 +343,7 @@ bool WebGLContext::CreateAndInitGL(
|
|||
|
||||
// --
|
||||
|
||||
typedef decltype(gl::GLContextProviderEGL::CreateHeadless) fnCreateT;
|
||||
using fnCreateT = decltype(gl::GLContextProviderEGL::CreateHeadless);
|
||||
const auto fnCreate = [&](fnCreateT* const pfnCreate,
|
||||
const char* const info) {
|
||||
nsCString failureId;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
namespace mozilla {
|
||||
namespace webgl {
|
||||
|
||||
typedef uint8_t EffectiveFormatValueT;
|
||||
using EffectiveFormatValueT = uint8_t;
|
||||
|
||||
enum class EffectiveFormat : EffectiveFormatValueT {
|
||||
// GLES 3.0.4, p128-129, "Required Texture Formats"
|
||||
|
|
|
@ -140,17 +140,17 @@ class WebGLImageConverter {
|
|||
|
||||
// gather some compile-time meta-data about the formats at hand.
|
||||
|
||||
typedef typename DataTypeForFormat<SrcFormat>::Type SrcType;
|
||||
typedef typename DataTypeForFormat<DstFormat>::Type DstType;
|
||||
using SrcType = typename DataTypeForFormat<SrcFormat>::Type;
|
||||
using DstType = typename DataTypeForFormat<DstFormat>::Type;
|
||||
|
||||
const WebGLTexelFormat IntermediateSrcFormat =
|
||||
IntermediateFormat<SrcFormat>::Value;
|
||||
const WebGLTexelFormat IntermediateDstFormat =
|
||||
IntermediateFormat<DstFormat>::Value;
|
||||
typedef typename DataTypeForFormat<IntermediateSrcFormat>::Type
|
||||
IntermediateSrcType;
|
||||
typedef typename DataTypeForFormat<IntermediateDstFormat>::Type
|
||||
IntermediateDstType;
|
||||
using IntermediateSrcType =
|
||||
typename DataTypeForFormat<IntermediateSrcFormat>::Type;
|
||||
using IntermediateDstType =
|
||||
typename DataTypeForFormat<IntermediateDstFormat>::Type;
|
||||
|
||||
const size_t NumElementsPerSrcTexel =
|
||||
NumElementsPerTexelForFormat<SrcFormat>();
|
||||
|
|
|
@ -314,27 +314,27 @@ template <WebGLTexelFormat Format, bool IsFloat = IsFloatFormat<Format>::Value,
|
|||
bool Is16bpp = Is16bppFormat<Format>::Value,
|
||||
bool IsHalfFloat = IsHalfFloatFormat<Format>::Value>
|
||||
struct DataTypeForFormat {
|
||||
typedef uint8_t Type;
|
||||
using Type = uint8_t;
|
||||
};
|
||||
|
||||
template <WebGLTexelFormat Format>
|
||||
struct DataTypeForFormat<Format, true, false, false> {
|
||||
typedef float Type;
|
||||
using Type = float;
|
||||
};
|
||||
|
||||
template <WebGLTexelFormat Format>
|
||||
struct DataTypeForFormat<Format, false, true, false> {
|
||||
typedef uint16_t Type;
|
||||
using Type = uint16_t;
|
||||
};
|
||||
|
||||
template <WebGLTexelFormat Format>
|
||||
struct DataTypeForFormat<Format, false, false, true> {
|
||||
typedef uint16_t Type;
|
||||
using Type = uint16_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DataTypeForFormat<WebGLTexelFormat::RGB11F11F10F, true, false, false> {
|
||||
typedef uint32_t Type;
|
||||
using Type = uint32_t;
|
||||
};
|
||||
|
||||
template <WebGLTexelFormat Format>
|
||||
|
|
|
@ -34,9 +34,9 @@
|
|||
|
||||
// Manual reflection of WebIDL typedefs that are different from their
|
||||
// OpenGL counterparts.
|
||||
typedef int64_t WebGLsizeiptr;
|
||||
typedef int64_t WebGLintptr;
|
||||
typedef bool WebGLboolean;
|
||||
using WebGLsizeiptr = int64_t;
|
||||
using WebGLintptr = int64_t;
|
||||
using WebGLboolean = bool;
|
||||
|
||||
// -
|
||||
|
||||
|
@ -326,7 +326,7 @@ enum class UniformBaseType : uint8_t {
|
|||
};
|
||||
const char* ToString(UniformBaseType);
|
||||
|
||||
typedef uint64_t ObjectId;
|
||||
using ObjectId = uint64_t;
|
||||
|
||||
enum class BufferKind : uint8_t {
|
||||
Undefined,
|
||||
|
@ -491,10 +491,10 @@ struct avec3 {
|
|||
bool operator!=(const avec3& rhs) const { return !(*this == rhs); }
|
||||
};
|
||||
|
||||
typedef avec2<int32_t> ivec2;
|
||||
typedef avec3<int32_t> ivec3;
|
||||
typedef avec2<uint32_t> uvec2;
|
||||
typedef avec3<uint32_t> uvec3;
|
||||
using ivec2 = avec2<int32_t>;
|
||||
using ivec3 = avec3<int32_t>;
|
||||
using uvec2 = avec2<uint32_t>;
|
||||
using uvec3 = avec3<uint32_t>;
|
||||
|
||||
inline ivec2 AsVec(const gfx::IntSize& s) { return {s.width, s.height}; }
|
||||
|
||||
|
|
|
@ -52,13 +52,13 @@ class SourceSurface;
|
|||
class nsICanvasRenderingContextInternal : public nsISupports,
|
||||
public nsAPostRefreshObserver {
|
||||
public:
|
||||
typedef mozilla::layers::CanvasLayer CanvasLayer;
|
||||
typedef mozilla::layers::CanvasRenderer CanvasRenderer;
|
||||
typedef mozilla::layers::Layer Layer;
|
||||
typedef mozilla::layers::LayerManager LayerManager;
|
||||
typedef mozilla::layers::WebRenderCanvasData WebRenderCanvasData;
|
||||
typedef mozilla::layers::CompositableHandle CompositableHandle;
|
||||
typedef mozilla::layers::LayerTransactionChild LayerTransactionChild;
|
||||
using CanvasLayer = mozilla::layers::CanvasLayer;
|
||||
using CanvasRenderer = mozilla::layers::CanvasRenderer;
|
||||
using Layer = mozilla::layers::Layer;
|
||||
using LayerManager = mozilla::layers::LayerManager;
|
||||
using WebRenderCanvasData = mozilla::layers::WebRenderCanvasData;
|
||||
using CompositableHandle = mozilla::layers::CompositableHandle;
|
||||
using LayerTransactionChild = mozilla::layers::LayerTransactionChild;
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
|
||||
|
||||
|
|
|
@ -313,6 +313,30 @@ interface CanonicalBrowsingContext : BrowsingContext {
|
|||
[SetterThrows] inherit attribute TouchEventsOverride touchEventsOverride;
|
||||
|
||||
readonly attribute boolean isReplaced;
|
||||
|
||||
|
||||
/**
|
||||
* Notify APZ to start autoscrolling.
|
||||
*
|
||||
* (aAnchorX, aAnchorY) are the coordinates of the autoscroll anchor, in CSS
|
||||
* coordinates relative to the screen.
|
||||
* aScrollId and aPresShellId identify the scroll frame that content chose to
|
||||
* scroll.
|
||||
*
|
||||
* Returns whether we were successfully able to notify APZ.
|
||||
* If this function returns true, APZ (which may live in another process)
|
||||
* may still reject the autoscroll, but it's then APZ's reponsibility
|
||||
* to notify content via an "autoscroll-rejected-by-apz" message.
|
||||
*/
|
||||
boolean startApzAutoscroll(float aAnchorX, float aAnchorY,
|
||||
unsigned long long aScrollId,
|
||||
unsigned long aPresShellId);
|
||||
|
||||
/**
|
||||
* Notify APZ to stop autoscrolling.
|
||||
*/
|
||||
void stopApzAutoscroll(unsigned long long aScrollId,
|
||||
unsigned long aPresShellId);
|
||||
};
|
||||
|
||||
[Exposed=Window, ChromeOnly]
|
||||
|
|
|
@ -76,13 +76,6 @@ interface FrameLoader {
|
|||
// Note, when frameloaders are swapped, also messageManagers are swapped.
|
||||
readonly attribute MessageSender? messageManager;
|
||||
|
||||
/**
|
||||
* Request that the next time a remote layer transaction has been
|
||||
* received by the Compositor, a MozAfterRemoteFrame event be sent
|
||||
* to the window.
|
||||
*/
|
||||
void requestNotifyAfterRemotePaint();
|
||||
|
||||
/**
|
||||
* Force a remote browser to recompute its dimension and screen position.
|
||||
*/
|
||||
|
|
|
@ -87,3 +87,46 @@ interface L10nFileSource {
|
|||
FluentResource? fetchFileSync(UTF8String locale, UTF8String path);
|
||||
};
|
||||
|
||||
dictionary FluentBundleIteratorResult
|
||||
{
|
||||
required FluentBundle? value;
|
||||
required boolean done;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject, Exposed=Window]
|
||||
interface FluentBundleIterator {
|
||||
FluentBundleIteratorResult next();
|
||||
[Alias="@@iterator"] FluentBundleIterator values();
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject, Exposed=Window]
|
||||
interface FluentBundleAsyncIterator {
|
||||
Promise<FluentBundleIteratorResult> next();
|
||||
[Alias="@@asyncIterator"] FluentBundleAsyncIterator values();
|
||||
};
|
||||
|
||||
[ChromeOnly, Exposed=Window]
|
||||
interface L10nRegistry {
|
||||
constructor();
|
||||
|
||||
static L10nRegistry getInstance();
|
||||
|
||||
sequence<UTF8String> getAvailableLocales();
|
||||
|
||||
void registerSources(sequence<L10nFileSource> aSources);
|
||||
void updateSources(sequence<L10nFileSource> aSources);
|
||||
void removeSources(sequence<UTF8String> aSources);
|
||||
|
||||
[Throws]
|
||||
boolean hasSource(UTF8String aName);
|
||||
[Throws]
|
||||
L10nFileSource? getSource(UTF8String aName);
|
||||
sequence<UTF8String> getSourceNames();
|
||||
void clearSources();
|
||||
|
||||
[Throws, NewObject]
|
||||
FluentBundleIterator generateBundlesSync(sequence<UTF8String> aLocales, sequence<UTF8String> aResourceIds);
|
||||
|
||||
[Throws, NewObject]
|
||||
FluentBundleAsyncIterator generateBundles(sequence<UTF8String> aLocales, sequence<UTF8String> aResourceIds);
|
||||
};
|
||||
|
|
|
@ -71,7 +71,9 @@ support-files = wpt/pointerevent_sequence_at_implicit_release_on_drag-manual.htm
|
|||
[test_wpt_pointerevent_drag_interaction-manual.html]
|
||||
support-files = wpt/html/pointerevent_drag_interaction-manual.html
|
||||
[test_wpt_touch_action.html]
|
||||
skip-if = os == 'android' # Bug 1312791
|
||||
skip-if =
|
||||
os == 'android' # Bug 1312791
|
||||
os == 'linux' && headless # Bug 1722906
|
||||
support-files =
|
||||
../../../../gfx/layers/apz/test/mochitest/apz_test_utils.js
|
||||
../../../../gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
|
||||
|
|
|
@ -73,26 +73,6 @@ interface nsIRemoteTab : nsISupports
|
|||
void createAboutBlankContentViewer(in nsIPrincipal aPrincipal,
|
||||
in nsIPrincipal aPartitionedPrincipal);
|
||||
|
||||
/**
|
||||
* Notify APZ to start autoscrolling.
|
||||
* (aAnchorX, aAnchorY) are the coordinates of the autoscroll anchor,
|
||||
* in CSS coordinates relative to the screen. aScrollId and
|
||||
* aPresShellId identify the scroll frame that content chose to scroll.
|
||||
* Returns whether we were successfully able to notify APZ.
|
||||
* If this function returns true, APZ (which may live in another process)
|
||||
* may still reject the autoscroll, but it's then APZ's reponsibility
|
||||
* to notify content via an "autoscroll-rejected-by-apz" message.
|
||||
*/
|
||||
boolean startApzAutoscroll(in float aAnchorX, in float aAnchorY,
|
||||
in nsViewID aScrollId, in uint32_t aPresShellId);
|
||||
|
||||
/**
|
||||
* Notify APZ to stop autoscrolling.
|
||||
* aScrollId and aPresShellId identify the scroll frame that is being
|
||||
* autoscrolled.
|
||||
*/
|
||||
void stopApzAutoscroll(in nsViewID aScrollId, in uint32_t aPresShellId);
|
||||
|
||||
cenum NavigationType : 8 {
|
||||
NAVIGATE_BACK = 0,
|
||||
NAVIGATE_FORWARD = 1,
|
||||
|
|
|
@ -930,11 +930,6 @@ void BrowserChild::ActorDestroy(ActorDestroyReason why) {
|
|||
}
|
||||
}
|
||||
|
||||
CompositorBridgeChild* compositorChild = CompositorBridgeChild::Get();
|
||||
if (compositorChild) {
|
||||
compositorChild->CancelNotifyAfterRemotePaint(this);
|
||||
}
|
||||
|
||||
if (GetTabId() != 0) {
|
||||
NestedBrowserChildMap().erase(GetTabId());
|
||||
}
|
||||
|
@ -3316,17 +3311,6 @@ void BrowserChild::NotifyJankedAnimations(
|
|||
lm->UpdatePartialPrerenderedAnimations(aJankedAnimations);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserChild::RecvRequestNotifyAfterRemotePaint() {
|
||||
// Get the CompositorBridgeChild instance for this content thread.
|
||||
CompositorBridgeChild* compositor = CompositorBridgeChild::Get();
|
||||
|
||||
// Tell the CompositorBridgeChild that, when it gets a RemotePaintIsReady
|
||||
// message that it should forward it us so that we can bounce it to our
|
||||
// BrowserParent.
|
||||
compositor->RequestNotifyAfterRemotePaint(this);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserChild::RecvUIResolutionChanged(
|
||||
const float& aDpi, const int32_t& aRounding, const double& aScale) {
|
||||
nsCOMPtr<Document> document(GetTopLevelDocument());
|
||||
|
|
|
@ -721,8 +721,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
|
|||
mozilla::ipc::IPCResult RecvNavigateByKey(const bool& aForward,
|
||||
const bool& aForDocumentNavigation);
|
||||
|
||||
mozilla::ipc::IPCResult RecvRequestNotifyAfterRemotePaint();
|
||||
|
||||
mozilla::ipc::IPCResult RecvSuppressDisplayport(const bool& aEnabled);
|
||||
|
||||
mozilla::ipc::IPCResult RecvScrollbarPreferenceChanged(ScrollbarPreference);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue