Merge mozilla-central to mozilla-inbound. CLOSED TREE

This commit is contained in:
Csoregi Natalia 2019-05-08 06:40:43 +03:00
Родитель bf9ea71d10 197210b8c1
Коммит 26aadf7f93
201 изменённых файлов: 4450 добавлений и 1328 удалений

Просмотреть файл

@ -411,7 +411,7 @@ pref("permissions.default.geo", 0);
pref("permissions.default.desktop-notification", 0);
pref("permissions.default.shortcuts", 0);
#ifdef NIGHTLY_BUILD
#ifdef EARLY_BETA_OR_EARLIER
pref("permissions.desktop-notification.postPrompt.enabled", true);
#else
pref("permissions.desktop-notification.postPrompt.enabled", false);

Просмотреть файл

@ -1,3 +1,4 @@
[DEFAULT]
[browser_principalSerialization_version1.js]
[browser_principalSerialization_csp.js]

Просмотреть файл

@ -0,0 +1,87 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/*
* Within Bug 965637 we move the CSP away from the Principal. Serialized Principals however
* might still have CSPs serialized within them. This tests ensures that we do not
* encounter a memory corruption when deserializing. It's fine that the deserialized
* CSP is null, but the Principal itself should deserialize correctly.
*/
add_task(async function test_deserialize_principal_with_csp() {
/*
This test should be resilient to changes in principal serialization, if these are failing then it's likely the code will break session storage.
To recreate this for another version, copy the function into the browser console, browse some pages and printHistory.
Generated with:
function printHistory() {
let tests = [];
let entries = SessionStore.getSessionHistory(gBrowser.selectedTab).entries.map((entry) => { return entry.triggeringPrincipal_base64 });
entries.push(E10SUtils.serializePrincipal(gBrowser.selectedTab.linkedBrowser._contentPrincipal));
for (let entry of entries) {
console.log(entry);
let testData = {};
testData.input = entry;
let principal = E10SUtils.deserializePrincipal(testData.input);
testData.output = {};
if (principal.URI === null) {
testData.output.URI = false;
} else {
testData.output.URISpec = principal.URI.spec;
}
testData.output.originAttributes = principal.originAttributes;
testData.output.cspJSON = principal.cspJSON;
tests.push(testData);
}
return tests;
}
printHistory(); // Copy this into: serializedPrincipalsFromFirefox
*/
let serializedPrincipalsFromFirefox = [
{
"input": "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAHmh0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTLwAAAAAAAAAFAAAACAAAAA8AAAAA/////wAAAAD/////AAAACAAAAA8AAAAXAAAABwAAABcAAAAHAAAAFwAAAAcAAAAeAAAAAAAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AQAAAAAAAAAAAAAAAQnZ7Rrl1EAEv+Anzrkj2ayzxMCuvV5MrYfgjSENuz+fAd6UctCANBHTk5kAEEug/UCSBzpUbXhPMJE6uHGBMgjGAAAAAv////8AAAG7AQAAAB5odHRwczovL3d3dy5tb3ppbGxhLm9yZy9lbi1VUy8AAAAAAAAABQAAAAgAAAAPAAAAAP////8AAAAA/////wAAAAgAAAAPAAAAFwAAAAcAAAAXAAAABwAAABcAAAAHAAAAHgAAAAAAAAAA/////wAAAAD/////AAAAAP////8AAAAA/////wEAAAAAAAAAAAABAAAFtgBzAGMAcgBpAHAAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIAAnAHUAbgBzAGEAZgBlAC0AaQBuAGwAaQBuAGUAJwAgACcAdQBuAHMAYQBmAGUALQBlAHYAYQBsACcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdABhAGcAbQBhAG4AYQBnAGUAcgAuAGcAbwBvAGcAbABlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AcwAuAHkAdABpAG0AZwAuAGMAbwBtADsAIABpAG0AZwAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIABkAGEAdABhADoAIABoAHQAdABwAHMAOgAvAC8AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AZABlACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBkAGsAIABoAHQAdABwAHMAOgAvAC8AYwByAGUAYQB0AGkAdgBlAGMAbwBtAG0AbwBuAHMALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwBhAGQALgBkAG8AdQBiAGwAZQBjAGwAaQBjAGsALgBuAGUAdAA7ACAAZABlAGYAYQB1AGwAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AOwAgAGYAcgBhAG0AZQAtAHMAcgBjACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAtAG4AbwBjAG8AbwBrAGkAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAcgBhAGMAawBlAHIAdABlAHMAdAAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AcwB1AHIAdgBlAHkAZwBpAHoAbQBvAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAuAGMAbgAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALgBjAG8AbQA7ACAAcwB0AHkAbABlAC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgACcAdQBuAHMAYQBmAGUALQBpAG4AbABpAG4AZQAnADsAIABjAG8AbgBuAGUAYwB0AC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALwAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALgBjAG4ALwA7ACAAYwBoAGkAbABkAC0AcwByAGMAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC0AbgBvAGMAbwBvAGsAaQBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdAByAGEAYwBrAGUAcgB0AGUAcwB0AC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBzAHUAcgB2AGUAeQBnAGkAegBtAG8ALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC4AYwBuACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAuAGMAbwBtAAA=",
"output": {
"cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}",
"URISpec": "https://www.mozilla.org/en-US/",
"originAttributes": {
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"userContextId": 0,
},
},
},
{
"input": "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAL2h0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTL2ZpcmVmb3gvYWNjb3VudHMvAAAAAAAAAAUAAAAIAAAADwAAAAj/////AAAACP////8AAAAIAAAADwAAABcAAAAYAAAAFwAAABgAAAAXAAAAGAAAAC8AAAAAAAAAL/////8AAAAA/////wAAABf/////AAAAF/////8BAAAAAAAAAAAAAAABCdntGuXUQAS/4CfOuSPZrLPEwK69Xkyth+CNIQ27P58B3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAL2h0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTL2ZpcmVmb3gvYWNjb3VudHMvAAAAAAAAAAUAAAAIAAAADwAAAAj/////AAAACP////8AAAAIAAAADwAAABcAAAAYAAAAFwAAABgAAAAXAAAAGAAAAC8AAAAAAAAAL/////8AAAAA/////wAAABf/////AAAAF/////8BAAAAAAAAAAAAAQAABbYAcwBjAHIAaQBwAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtACAAJwB1AG4AcwBhAGYAZQAtAGkAbgBsAGkAbgBlACcAIAAnAHUAbgBzAGEAZgBlAC0AZQB2AGEAbAAnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBnAG8AbwBnAGwAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHMALgB5AHQAaQBtAGcALgBjAG8AbQA7ACAAaQBtAGcALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtACAAZABhAHQAYQA6ACAAaAB0AHQAcABzADoALwAvAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBkAHMAZQByAHYAaQBjAGUALgBnAG8AbwBnAGwAZQAuAGQAZQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AZABrACAAaAB0AHQAcABzADoALwAvAGMAcgBlAGEAdABpAHYAZQBjAG8AbQBtAG8AbgBzAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AYQBkAC4AZABvAHUAYgBsAGUAYwBsAGkAYwBrAC4AbgBlAHQAOwAgAGQAZQBmAGEAdQBsAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtADsAIABmAHIAYQBtAGUALQBzAHIAYwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALQBuAG8AYwBvAG8AawBpAGUALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB0AHIAYQBjAGsAZQByAHQAZQBzAHQALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHMAdQByAHYAZQB5AGcAaQB6AG0AbwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALgBjAG4AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC4AYwBvAG0AOwAgAHMAdAB5AGwAZQAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIAAnAHUAbgBzAGEAZgBlAC0AaQBuAGwAaQBuAGUAJwA7ACAAYwBvAG4AbgBlAGMAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC8AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC4AYwBuAC8AOwAgAGMAaABpAGwAZAAtAHMAcgBjACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAtAG4AbwBjAG8AbwBrAGkAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAcgBhAGMAawBlAHIAdABlAHMAdAAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AcwB1AHIAdgBlAHkAZwBpAHoAbQBvAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAuAGMAbgAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALgBjAG8AbQAA",
"output": {
"URISpec": "https://www.mozilla.org/en-US/firefox/accounts/",
"originAttributes": {
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"userContextId": 0,
},
"cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}",
},
},
];
for (let test of serializedPrincipalsFromFirefox) {
let principal = E10SUtils.deserializePrincipal(test.input);
is(principal.cspJSON, test.output.cspJSON, "should have CSP");
for (let key in principal.originAttributes) {
is(principal.originAttributes[key], test.output.originAttributes[key], `Ensure value of ${key} is ${test.output.originAttributes[key]}`);
}
if ("URI" in test.output && test.output.URI === false) {
is(principal.URI, null, "Should have not have a URI for system");
} else {
is(principal.URI.spec, test.output.URISpec, `Should have spec ${test.output.URISpec}`);
}
}
});

Просмотреть файл

@ -121,32 +121,6 @@ add_task(async function test_realHistoryCheck() {
"cspJSON": "{}",
},
},
{
"input": "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAHmh0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTLwAAAAAAAAAFAAAACAAAAA8AAAAA/////wAAAAD/////AAAACAAAAA8AAAAXAAAABwAAABcAAAAHAAAAFwAAAAcAAAAeAAAAAAAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AQAAAAAAAAAAAAAAAQnZ7Rrl1EAEv+Anzrkj2ayzxMCuvV5MrYfgjSENuz+fAd6UctCANBHTk5kAEEug/UCSBzpUbXhPMJE6uHGBMgjGAAAAAv////8AAAG7AQAAAB5odHRwczovL3d3dy5tb3ppbGxhLm9yZy9lbi1VUy8AAAAAAAAABQAAAAgAAAAPAAAAAP////8AAAAA/////wAAAAgAAAAPAAAAFwAAAAcAAAAXAAAABwAAABcAAAAHAAAAHgAAAAAAAAAA/////wAAAAD/////AAAAAP////8AAAAA/////wEAAAAAAAAAAAABAAAFtgBzAGMAcgBpAHAAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIAAnAHUAbgBzAGEAZgBlAC0AaQBuAGwAaQBuAGUAJwAgACcAdQBuAHMAYQBmAGUALQBlAHYAYQBsACcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdABhAGcAbQBhAG4AYQBnAGUAcgAuAGcAbwBvAGcAbABlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AcwAuAHkAdABpAG0AZwAuAGMAbwBtADsAIABpAG0AZwAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIABkAGEAdABhADoAIABoAHQAdABwAHMAOgAvAC8AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AZABlACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBkAGsAIABoAHQAdABwAHMAOgAvAC8AYwByAGUAYQB0AGkAdgBlAGMAbwBtAG0AbwBuAHMALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwBhAGQALgBkAG8AdQBiAGwAZQBjAGwAaQBjAGsALgBuAGUAdAA7ACAAZABlAGYAYQB1AGwAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AOwAgAGYAcgBhAG0AZQAtAHMAcgBjACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAtAG4AbwBjAG8AbwBrAGkAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAcgBhAGMAawBlAHIAdABlAHMAdAAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AcwB1AHIAdgBlAHkAZwBpAHoAbQBvAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAuAGMAbgAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALgBjAG8AbQA7ACAAcwB0AHkAbABlAC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgACcAdQBuAHMAYQBmAGUALQBpAG4AbABpAG4AZQAnADsAIABjAG8AbgBuAGUAYwB0AC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALwAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALgBjAG4ALwA7ACAAYwBoAGkAbABkAC0AcwByAGMAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC0AbgBvAGMAbwBvAGsAaQBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdAByAGEAYwBrAGUAcgB0AGUAcwB0AC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBzAHUAcgB2AGUAeQBnAGkAegBtAG8ALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC4AYwBuACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAuAGMAbwBtAAA=",
"output": {
"cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}",
"URISpec": "https://www.mozilla.org/en-US/",
"originAttributes": {
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"userContextId": 0,
},
},
},
{
"input": "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAL2h0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTL2ZpcmVmb3gvYWNjb3VudHMvAAAAAAAAAAUAAAAIAAAADwAAAAj/////AAAACP////8AAAAIAAAADwAAABcAAAAYAAAAFwAAABgAAAAXAAAAGAAAAC8AAAAAAAAAL/////8AAAAA/////wAAABf/////AAAAF/////8BAAAAAAAAAAAAAAABCdntGuXUQAS/4CfOuSPZrLPEwK69Xkyth+CNIQ27P58B3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAL2h0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTL2ZpcmVmb3gvYWNjb3VudHMvAAAAAAAAAAUAAAAIAAAADwAAAAj/////AAAACP////8AAAAIAAAADwAAABcAAAAYAAAAFwAAABgAAAAXAAAAGAAAAC8AAAAAAAAAL/////8AAAAA/////wAAABf/////AAAAF/////8BAAAAAAAAAAAAAQAABbYAcwBjAHIAaQBwAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtACAAJwB1AG4AcwBhAGYAZQAtAGkAbgBsAGkAbgBlACcAIAAnAHUAbgBzAGEAZgBlAC0AZQB2AGEAbAAnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBnAG8AbwBnAGwAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHMALgB5AHQAaQBtAGcALgBjAG8AbQA7ACAAaQBtAGcALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtACAAZABhAHQAYQA6ACAAaAB0AHQAcABzADoALwAvAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBkAHMAZQByAHYAaQBjAGUALgBnAG8AbwBnAGwAZQAuAGQAZQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AZABrACAAaAB0AHQAcABzADoALwAvAGMAcgBlAGEAdABpAHYAZQBjAG8AbQBtAG8AbgBzAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AYQBkAC4AZABvAHUAYgBsAGUAYwBsAGkAYwBrAC4AbgBlAHQAOwAgAGQAZQBmAGEAdQBsAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtADsAIABmAHIAYQBtAGUALQBzAHIAYwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALQBuAG8AYwBvAG8AawBpAGUALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB0AHIAYQBjAGsAZQByAHQAZQBzAHQALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHMAdQByAHYAZQB5AGcAaQB6AG0AbwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALgBjAG4AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC4AYwBvAG0AOwAgAHMAdAB5AGwAZQAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIAAnAHUAbgBzAGEAZgBlAC0AaQBuAGwAaQBuAGUAJwA7ACAAYwBvAG4AbgBlAGMAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC8AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC4AYwBuAC8AOwAgAGMAaABpAGwAZAAtAHMAcgBjACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAtAG4AbwBjAG8AbwBrAGkAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAcgBhAGMAawBlAHIAdABlAHMAdAAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AcwB1AHIAdgBlAHkAZwBpAHoAbQBvAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAuAGMAbgAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALgBjAG8AbQAA",
"output": {
"URISpec": "https://www.mozilla.org/en-US/firefox/accounts/",
"originAttributes": {
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"userContextId": 0,
},
"cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}",
},
},
{
"input": "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAe2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTLz91dG1fc291cmNlPXd3dy5tb3ppbGxhLm9yZyZ1dG1fbWVkaXVtPXJlZmVycmFsJnV0bV9jYW1wYWlnbj1uYXYmdXRtX2NvbnRlbnQ9ZGV2ZWxvcGVycwAAAAAAAAAFAAAACAAAABUAAAAA/////wAAAAD/////AAAACAAAABUAAAAdAAAAXgAAAB0AAAAHAAAAHQAAAAcAAAAkAAAAAAAAAAD/////AAAAAP////8AAAAlAAAAVgAAAAD/////AQAAAAAAAAAAAAAAAA==",
"output": {

Просмотреть файл

@ -0,0 +1,419 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* This test records I/O syscalls done on the main thread during startup.
*
* To run this test similar to try server, you need to run:
* ./mach package
* ./mach test --appname=dist <path to test>
*
* If you made changes that cause this test to fail, it's likely because you
* are touching more files or directories during startup.
* Most code has no reason to use main thread I/O.
* If for some reason accessing the file system on the main thread is currently
* unavoidable, consider defering the I/O as long as you can, ideally after
* the end of startup.
*/
"use strict";
/* Set this to true only for debugging purpose; it makes the output noisy. */
const kDumpAllStacks = false;
// Shortcuts for conditions.
const LINUX = AppConstants.platform == "linux";
const WIN = AppConstants.platform == "win";
const MAC = AppConstants.platform == "macosx";
/* Paths in the whitelist can:
* - be a full path, eg. "/etc/mime.types"
* - have a prefix which will be resolved using Services.dirsvc
* eg. "GreD:omni.ja"
* It's possible to have only a prefix, in thise case the directory will
* still be resolved, eg. "UAppData:"
* - use * at the begining and/or end as a wildcard
* The folder separator is '/' even for Windows paths, where it'll be
* automatically converted to '\'.
*
* Specifying 'ignoreIfUnused: true' will make the test ignore unused entries;
* without this the test is strict and will fail if a whitelist entry isn't used.
*
* Each entry specifies the maximum number of times an operation is expected to
* occur.
* The operations currently reported by the I/O interposer are:
* create/open: only supported on Windows currently. The test currently
* ignores these markers to have a shorter initial whitelist.
* Adding Unix support is bug 1533779.
* stat: supported on all platforms when checking the last modified date or
* file size. Supported only on Windows when checking if a file exists;
* fixing this inconsistency is bug 1536109.
* read: supported on all platforms, but unix platforms will only report read
* calls going through NSPR.
* write: supported on all platforms, but Linux will only report write calls
* going through NSPR.
* close: supported only on Unix, and only for close calls going through NSPR.
* Adding Windows support is bug 1524574.
* fsync: supported only on Windows.
*
* If an entry specifies more than one operation, if at least one of them is
* encountered, the test won't report a failure for the entry. This helps when
* whitelisting cases where the reported operations aren't the same on all
* platforms due to the I/O interposer inconsistencies across platforms
* documented above.
*/
const processes = {
"Web Content": [
{
path: "GreD:omni.ja",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
},
{ // bug 1376994
path: "XCurProcD:omni.ja",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
},
{ // bug 1543761
path: "GreD:chrome.manifest",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
close: 1,
},
{ // bug 1376994, bug 1543761
path: "XCurProcD:chrome.manifest",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
close: 1,
},
{ // Exists call in ScopedXREEmbed::SetAppDir
path: "XCurProcD:",
condition: WIN,
stat: 1,
},
{ // bug 1357205
path: "XREAppFeat:webcompat@mozilla.org.xpi",
condition: !WIN,
stat: 1,
},
{ // bug 1357205
path: "XREAppFeat:formautofill@mozilla.org.xpi",
condition: !WIN,
stat: 1,
},
],
"Privileged Content": [
{
path: "GreD:omni.ja",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
},
{ // bug 1376994
path: "XCurProcD:omni.ja",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
},
{ // bug 1543761
path: "GreD:chrome.manifest",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
close: 1,
},
{ // bug 1376994, bug 1543761
path: "XCurProcD:chrome.manifest",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
close: 1,
},
{ // Exists call in ScopedXREEmbed::SetAppDir
path: "XCurProcD:",
condition: WIN,
stat: 1,
},
{ // bug 1357205
path: "XREAppFeat:webcompat@mozilla.org.xpi",
condition: !WIN,
stat: 1,
},
],
"WebExtensions": [
{
path: "GreD:omni.ja",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
},
{ // bug 1376994
path: "XCurProcD:omni.ja",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
},
{ // bug 1543761
path: "GreD:chrome.manifest",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
close: 1,
},
{ // bug 1376994, bug 1543761
path: "XCurProcD:chrome.manifest",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
close: 1,
},
{ // Exists call in ScopedXREEmbed::SetAppDir
path: "XCurProcD:",
condition: WIN,
stat: 1,
},
{ // bug 1357205
path: "XREAppFeat:webcompat@mozilla.org.xpi",
condition: !WIN,
stat: 1,
},
{ // bug 1357205
path: "XREAppFeat:formautofill@mozilla.org.xpi",
condition: !WIN,
stat: 1,
},
{ // bug 1357205
path: "XREAppFeat:screenshots@mozilla.org.xpi",
condition: !WIN,
close: 1,
},
],
};
function expandWhitelistPath(path) {
if (path.includes(":")) {
let [prefix, suffix] = path.split(":");
let [key, property] = prefix.split(".");
let dir = Services.dirsvc.get(key, Ci.nsIFile);
if (property) {
dir = dir[property];
}
// Resolve symLinks.
let dirPath = dir.path;
while (dir && !dir.isSymlink()) {
dir = dir.parent;
}
if (dir) {
dirPath = dirPath.replace(dir.path, dir.target);
}
path = dirPath;
if (suffix) {
path += "/" + suffix;
}
}
if (AppConstants.platform == "win") {
path = path.replace(/\//g, "\\");
}
return path;
}
function getStackFromProfile(profile, stack) {
const stackPrefixCol = profile.stackTable.schema.prefix;
const stackFrameCol = profile.stackTable.schema.frame;
const frameLocationCol = profile.frameTable.schema.location;
let result = [];
while (stack) {
let sp = profile.stackTable.data[stack];
let frame = profile.frameTable.data[sp[stackFrameCol]];
stack = sp[stackPrefixCol];
frame = profile.stringTable[frame[frameLocationCol]];
if (frame != "js::RunScript" && !frame.startsWith("next (self-hosted:")) {
result.push(frame);
}
}
return result;
}
function getIOMarkersFromProfile(profile) {
const nameCol = profile.markers.schema.name;
const dataCol = profile.markers.schema.data;
let markers = [];
for (let m of profile.markers.data) {
let markerName = profile.stringTable[m[nameCol]];
if (markerName != "FileIO")
continue;
let markerData = m[dataCol];
if (markerData.source == "sqlite-mainthread") {
continue;
}
let samples = markerData.stack.samples;
let stack = samples.data[0][samples.schema.stack];
markers.push({operation: markerData.operation,
filename: markerData.filename,
source: markerData.source,
stackId: stack});
}
return markers;
}
function pathMatches(path, filename) {
path = path.toLowerCase();
return path == filename || // Full match
// Wildcard on both sides of the path
(path.startsWith("*") && path.endsWith("*") &&
filename.includes(path.slice(1, -1))) ||
// Wildcard suffix
(path.endsWith("*") && filename.startsWith(path.slice(0, -1))) ||
// Wildcard prefix
(path.startsWith("*") && filename.endsWith(path.slice(1)));
}
add_task(async function() {
if (!AppConstants.NIGHTLY_BUILD && !AppConstants.MOZ_DEV_EDITION && !AppConstants.DEBUG) {
ok(!("@mozilla.org/test/startuprecorder;1" in Cc),
"the startup recorder component shouldn't exist in this non-nightly/non-devedition/" +
"non-debug build.");
return;
}
{
let omniJa = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
omniJa.append("omni.ja");
if (!omniJa.exists()) {
ok(false, "This test requires a packaged build, " +
"run 'mach package' and then use --appname=dist");
return;
}
}
let startupRecorder = Cc["@mozilla.org/test/startuprecorder;1"].getService().wrappedJSObject;
await startupRecorder.done;
for (let process in processes) {
processes[process] =
processes[process].filter(entry => !("condition" in entry) || entry.condition);
processes[process].forEach(entry => {
entry.path = expandWhitelistPath(entry.path, entry.canonicalize);
});
}
let tmpPath = expandWhitelistPath(MAC ? "TmpD:" : "/dev/shm").toLowerCase();
let shouldPass = true;
for (let procName in processes) {
let whitelist = processes[procName];
info(`whitelisted paths for ${procName} process:\n` +
whitelist.map(e => {
let operations = Object.keys(e).filter(k => !["path", "condition"].includes(k))
.map(k => `${k}: ${e[k]}`);
return ` ${e.path} - ${operations.join(", ")}`;
}).join("\n"));
let profile;
for (let process of startupRecorder.data.profile.processes) {
if (process.threads[0].processName == procName) {
profile = process.threads[0];
break;
}
}
if (procName == "Privileged Content" && !profile) {
// The Privileged Content is started from an idle task that may not have
// been executed yet at the time we captured the startup profile in
// startupRecorder.
todo(false, `profile for ${procName} process not found`);
} else {
ok(profile, `Found profile for ${procName} process`);
}
if (!profile) {
continue;
}
let markers = getIOMarkersFromProfile(profile);
for (let marker of markers) {
if (marker.operation == "create/open") {
// TODO: handle these I/O markers once they are supported on
// non-Windows platforms.
continue;
}
// Convert to lower case before comparing because the OS X test slaves
// have the 'Firefox' folder in 'Library/Application Support' created
// as 'firefox' for some reason.
let filename = marker.filename.toLowerCase();
if (!filename) {
// We are still missing the filename on some mainthreadio markers,
// these markers are currently useless for the purpose of this test.
continue;
}
if (!WIN) {
if (filename == "/dev/urandom") {
continue;
}
// Ignore I/O due to IPC. This doesn't really touch the disk.
if (filename.startsWith(tmpPath + "/org.chromium.")) {
continue;
}
}
let expected = false;
for (let entry of whitelist) {
if (pathMatches(entry.path, filename)) {
entry[marker.operation] = (entry[marker.operation] || 0) - 1;
entry._used = true;
expected = true;
break;
}
}
if (!expected) {
record(false,
`unexpected ${marker.operation} on ${marker.filename} in ${procName} process`,
undefined,
" " + getStackFromProfile(profile, marker.stackId).join("\n "));
shouldPass = false;
}
info(`(${marker.source}) ${marker.operation} - ${marker.filename}`);
if (kDumpAllStacks) {
info(getStackFromProfile(profile, marker.stackId).map(f => " " + f)
.join("\n"));
}
}
for (let entry of whitelist) {
for (let op in entry) {
if (["path", "condition", "ignoreIfUnused", "_used"].includes(op)) {
continue;
}
let message = `${op} on ${entry.path} `;
if (entry[op] == 0) {
message += "as many times as expected";
} else if (entry[op] > 0) {
message += `allowed ${entry[op]} more times`;
} else {
message += `${entry[op] * -1} more times than expected`;
}
ok(entry[op] >= 0, `${message} in ${procName} process`);
}
if (!("_used" in entry) && !entry.ignoreIfUnused) {
ok(false, `unused whitelist entry ${procName}: ${entry.path}`);
}
}
}
if (shouldPass) {
ok(shouldPass, "No unexpected main thread I/O during startup");
} else {
const filename = "child-startup-mainthreadio-profile.json";
let path = Cc["@mozilla.org/process/environment;1"]
.getService(Ci.nsIEnvironment)
.get("MOZ_UPLOAD_DIR");
let encoder = new TextEncoder();
let profilePath = OS.Path.join(path, filename);
await OS.File.writeAtomic(profilePath,
encoder.encode(JSON.stringify(startupRecorder.data.profile)));
ok(false,
"Found some unexpected main thread I/O during child process startup; " +
"profile uploaded in " + filename);
}
});

Просмотреть файл

@ -0,0 +1,933 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* This test records I/O syscalls done on the main thread during startup.
*
* To run this test similar to try server, you need to run:
* ./mach package
* ./mach test --appname=dist <path to test>
*
* If you made changes that cause this test to fail, it's likely because you
* are touching more files or directories during startup.
* Most code has no reason to use main thread I/O.
* If for some reason accessing the file system on the main thread is currently
* unavoidable, consider defering the I/O as long as you can, ideally after
* the end of startup.
* If your code isn't strictly required to show the first browser window,
* it shouldn't be loaded before we are done with first paint.
* Finally, if your code isn't really needed during startup, it should not be
* loaded before we have started handling user events.
*/
"use strict";
const { AddonManager } = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
/* Set this to true only for debugging purpose; it makes the output noisy. */
const kDumpAllStacks = false;
// Shortcuts for conditions.
const LINUX = AppConstants.platform == "linux";
const WIN = AppConstants.platform == "win";
const MAC = AppConstants.platform == "macosx";
/* Paths in the whitelist can:
* - be a full path, eg. "/etc/mime.types"
* - have a prefix which will be resolved using Services.dirsvc
* eg. "GreD:omni.ja"
* It's possible to have only a prefix, in thise case the directory will
* still be resolved, eg. "UAppData:"
* - use * at the begining and/or end as a wildcard
* - For Windows specific entries that require resolving the path to its
* canonical form, ie. the old DOS 8.3 format, use canonicalize: true.
* This is needed for stat calls to non-existent files.
* The folder separator is '/' even for Windows paths, where it'll be
* automatically converted to '\'.
*
* Specifying 'ignoreIfUnused: true' will make the test ignore unused entries;
* without this the test is strict and will fail if a whitelist entry isn't used.
*
* Each entry specifies the maximum number of times an operation is expected to
* occur.
* The operations currently reported by the I/O interposer are:
* create/open: only supported on Windows currently. The test currently
* ignores these markers to have a shorter initial whitelist.
* Adding Unix support is bug 1533779.
* stat: supported on all platforms when checking the last modified date or
* file size. Supported only on Windows when checking if a file exists;
* fixing this inconsistency is bug 1536109.
* read: supported on all platforms, but unix platforms will only report read
* calls going through NSPR.
* write: supported on all platforms, but Linux will only report write calls
* going through NSPR.
* close: supported only on Unix, and only for close calls going through NSPR.
* Adding Windows support is bug 1524574.
* fsync: supported only on Windows.
*
* If an entry specifies more than one operation, if at least one of them is
* encountered, the test won't report a failure for the entry. This helps when
* whitelisting cases where the reported operations aren't the same on all
* platforms due to the I/O interposer inconsistencies across platforms
* documented above.
*/
const startupPhases = {
// Anything done before or during app-startup must have a compelling reason
// to run before we have even selected the user profile.
"before profile selection": [
{ // bug 1541226
path: "UAppData:",
condition: WIN,
stat: 3,
},
{ // bug 1541200
path: "UAppData:Crash Reports/InstallTime20*",
condition: AppConstants.MOZ_CRASHREPORTER,
stat: 1, // only caught on Windows.
read: 1,
write: 2,
close: 1,
},
{ // bug 1541200
path: "UAppData:Crash Reports/LastCrash",
condition: WIN && AppConstants.MOZ_CRASHREPORTER,
stat: 1, // only caught on Windows.
read: 1,
},
{ // bug 1541200
path: "UAppData:Crash Reports/LastCrash",
condition: !WIN && AppConstants.MOZ_CRASHREPORTER,
ignoreIfUnused: true, // only if we ever crashed on this machine
read: 1,
close: 1,
},
{ // bug 1541226
path: "DefProfLRt.parent:",
condition: WIN,
stat: 1,
},
{ // At least the read seems unavoidable for a regular startup.
path: "UAppData:profiles.ini",
condition: MAC,
stat: 1,
read: 1,
close: 1,
},
{ // bug 1546931
path: "UAppData:installs.ini",
condition: WIN || MAC,
ignoreIfUnused: true, // only if a real profile exists on the system.
read: 1,
stat: 2,
close: 1,
},
{ // At least the read seems unavoidable for a regular startup.
path: "UAppData:profiles.ini",
condition: WIN,
ignoreIfUnused: true, // only if a real profile exists on the system.
read: 1,
stat: 1,
},
{ // bug 1541226, bug 1363586, bug 1541593
path: "ProfD:",
condition: WIN,
stat: 3,
},
{
path: "ProfLD:.startup-incomplete",
condition: !WIN, // Visible on Windows with an open marker
close: 1,
},
{ // bug 1541491 to stop using this file, bug 1541494 to write correctly.
path: "ProfLD:compatibility.ini",
condition: !WIN, // Visible on Windows with an open marker
write: 18,
close: 1,
},
{
path: "GreD:omni.ja",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
},
{ // bug 1376994
path: "XCurProcD:omni.ja",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
},
{
path: "ProfD:parent.lock",
condition: WIN,
stat: 1,
},
{ // bug 1541603
path: "ProfD:minidumps",
condition: WIN,
stat: 1,
},
{ // bug 1543746
path: "XCurProcD:defaults/preferences",
condition: WIN,
stat: 1,
},
{ // bug 1544034
path: "ProfLDS:startupCache/scriptCache-child-current.bin",
condition: WIN,
stat: 1,
},
{ // bug 1544034
path: "ProfLDS:startupCache/scriptCache-child.bin",
condition: WIN,
stat: 1,
},
{ // bug 1544034
path: "ProfLDS:startupCache/scriptCache-current.bin",
condition: WIN,
stat: 1,
},
{ // bug 1544034
path: "ProfLDS:startupCache/scriptCache.bin",
condition: WIN,
stat: 1,
},
{ // bug 1544037
path: "ProfLDS:startupCache/startupCache." +
(Services.appinfo.is64Bit ? 8 : 4) + ".little",
condition: WIN,
stat: 1,
},
{ // bug 1541601
path: "PrfDef:channel-prefs.js",
stat: 1,
read: 1,
close: 1,
},
{ // bug 1543761
path: "GreD:chrome.manifest",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
close: 1,
},
{ // bug 1376994, bug 1543761
path: "XCurProcD:chrome.manifest",
condition: !WIN, // Visible on Windows with an open marker
stat: 1,
close: 1,
},
{ // At least the read seems unavoidable
path: "PrefD:prefs.js",
stat: 1,
read: 1,
close: 1,
},
{ // bug 1543752
path: "PrefD:user.js",
stat: 1,
read: 1,
close: 1,
},
{
path: "*ld.so.conf*",
condition: LINUX,
ignoreIfUnused: true,
read: 22,
close: 11,
},
{ // bug 1546838
path: "ProfD:xulstore/data.mdb",
condition: WIN,
write: 1,
fsync: 1,
},
],
"before opening first browser window": [
{ // bug 1541226
path: "ProfD:",
condition: WIN,
stat: 2,
},
{
path: "XCurProcD:blocklist.xml",
condition: WIN,
stat: 1,
},
{ // bug 1534745
path: "ProfD:cookies.sqlite-journal",
condition: !LINUX,
stat: 3,
write: 4,
},
{ // bug 1534745
path: "ProfD:cookies.sqlite",
condition: !LINUX,
stat: 2,
read: 2,
write: 1,
},
{ // bug 1534745
path: "ProfD:cookies.sqlite-wal",
condition: WIN,
stat: 2,
},
{ // bug 975996
path: "ProfD:permissions.sqlite",
condition: WIN || MAC,
fsync: 7,
read: 2,
stat: 1,
write: 10,
},
{ // bug 975996
path: "ProfD:permissions.sqlite-journal",
condition: WIN || MAC,
fsync: 7,
stat: 26,
write: 38,
},
{ // bug 975996
path: "ProfD:permissions.sqlite-wal",
condition: WIN,
stat: 20,
},
{ // Seems done by OS X and outside of our control.
path: "*.savedState/restorecount.plist",
condition: MAC,
ignoreIfUnused: true,
write: 1,
},
{
path: "*ld.so.conf*",
condition: LINUX,
ignoreIfUnused: true,
read: 22,
close: 11,
},
{ // bug 1545167
path: "/etc/mime.types",
condition: LINUX,
read: 3,
close: 3,
},
{
path: "UChrm:userChrome.css",
condition: WIN,
stat: 1,
},
{ // bug 1541233
path: "UChrm:userContent.css",
condition: WIN,
stat: 1,
},
{ // bug 1541246
path: "XREUSysExt:",
condition: WIN,
stat: 1,
},
{ // bug 1541246
path: "XRESysExtDev:",
condition: WIN,
stat: 1,
},
{ // bug 1541246
path: "ProfD:extensions",
condition: WIN,
stat: 1,
},
{ // bug 1541246
path: "XCurProcD:extensions",
condition: WIN,
stat: 1,
},
{ // bug 1541246
path: "UAppData:",
ignoreIfUnused: true, // sometimes before opening first browser window,
// sometimes before first paint
condition: WIN,
stat: 1,
},
{ // bug 1546838
path: "ProfD:xulstore/data.mdb",
condition: WIN,
read: 1,
},
],
// We reach this phase right after showing the first browser window.
// This means that any I/O at this point delayed first paint.
"before first paint": [
{ // bug 1541226
path: "ProfD:",
condition: WIN,
stat: 1,
},
{ // bug 1545119
path: "OldUpdRootD:",
condition: WIN,
stat: 1,
},
{ // bug 1446012
path: "UpdRootD:updates/0/update.status",
condition: WIN,
stat: 1,
},
{ // bug 1545123
path: "ProfD:pluginreg.dat",
condition: WIN,
stat: 1,
},
{ // bug 1545123
path: "ProfD:pluginreg.dat.tmp",
stat: 1,
write: 64,
close: 1,
},
{ // bug 1545123
path: "ProfD:plugins",
condition: WIN,
stat: 1,
},
{ // bug 1545123
path: "APlugns:",
condition: WIN,
stat: 1,
},
{ // bug 1545123
path: "UserPlugins.parent:",
condition: WIN,
stat: 1,
},
{ // bug 1545123
path: "UserPlugins:",
condition: WIN,
stat: 1,
},
{ // bug 1545123
path: "ProfD:plugins/nptest.dll",
condition: WIN,
stat: 1,
},
{ // bug 1545123
path: "ProfD:plugins/npsecondtest.dll",
condition: WIN,
stat: 1,
},
{ // bug 1545123
path: "ProfD:plugins/npthirdtest.dll",
condition: WIN,
stat: 1,
},
{ // bug 1545123
path: "ProfD:plugins/npswftest.dll",
condition: WIN,
stat: 1,
},
{
path: "XREAppFeat:formautofill@mozilla.org.xpi",
condition: !WIN,
stat: 1,
close: 1,
},
{ // bug 1545167
path: "/etc/mime.types",
condition: LINUX,
read: 1,
close: 1,
},
{ // We only hit this for new profiles.
path: "XREAppDist:distribution.ini",
condition: WIN,
stat: 1,
},
{
path: "*WindowsApps/microsoft.windowscommunicationsapps*",
condition: WIN,
ignoreIfUnused: true,
stat: 3,
},
{ // bug 1545139
path: "*Fonts/StaticCache.dat",
condition: WIN,
ignoreIfUnused: true, // Only on Win7
read: 1,
},
{ // bug 1541246
path: "UAppData:",
ignoreIfUnused: true, // sometimes before opening first browser window,
// sometimes before first paint
condition: WIN,
stat: 1,
},
{ // Not in packaged builds; useful for artifact builds.
path: "GreD:ScalarArtifactDefinitions.json",
condition: WIN && !AppConstants.MOZILLA_OFFICIAL,
stat: 1,
},
{ // Not in packaged builds; useful for artifact builds.
path: "GreD:EventArtifactDefinitions.json",
condition: WIN && !AppConstants.MOZILLA_OFFICIAL,
stat: 1,
},
{ // bug 1546838
path: "ProfD:xulstore/data.mdb",
condition: MAC,
write: 3,
},
{ // bug 1543090
path: "GreD:omni.ja",
condition: WIN,
stat: 1,
},
{ // bug 1543090
path: "XCurProcD:omni.ja",
condition: WIN,
stat: 2,
},
],
// We are at this phase once we are ready to handle user events.
// Any IO at this phase or before gets in the way of the user
// interacting with the first browser window.
"before handling user events": [
{
path: "GreD:update.test",
ignoreIfUnused: true,
condition: LINUX,
close: 1,
},
{ // bug 1370516 - NSS should be initialized off main thread.
path: "ProfD:cert9.db",
condition: WIN,
read: 2,
stat: 2,
},
{ // bug 1370516 - NSS should be initialized off main thread.
path: "ProfD:cert9.db",
condition: WIN,
ignoreIfUnused: true, // if canonicalize(ProfD) == ProfD, we'll use the previous entry.
canonicalize: true,
stat: 2,
},
{ // bug 1370516 - NSS should be initialized off main thread.
path: "ProfD:cert9.db-journal",
condition: WIN,
canonicalize: true,
stat: 2,
},
{ // bug 1370516 - NSS should be initialized off main thread.
path: "ProfD:cert9.db-wal",
condition: WIN,
canonicalize: true,
stat: 2,
},
{ // bug 1370516 - NSS should be initialized off main thread.
path: "ProfD:pkcs11.txt",
condition: WIN,
read: 2,
},
{ // bug 1370516 - NSS should be initialized off main thread.
path: "ProfD:key4.db",
condition: WIN,
read: 2,
stat: 2,
},
{ // bug 1370516 - NSS should be initialized off main thread.
path: "ProfD:key4.db",
condition: WIN,
ignoreIfUnused: true, // if canonicalize(ProfD) == ProfD, we'll use the previous entry.
canonicalize: true,
stat: 2,
},
{ // bug 1370516 - NSS should be initialized off main thread.
path: "ProfD:key4.db-journal",
condition: WIN,
canonicalize: true,
stat: 5,
},
{ // bug 1370516 - NSS should be initialized off main thread.
path: "ProfD:key4.db-wal",
condition: WIN,
canonicalize: true,
stat: 5,
},
{
path: "XREAppFeat:webcompat-reporter@mozilla.org.xpi",
condition: !WIN,
ignoreIfUnused: true,
stat: 1,
close: 1,
},
{ // bug 1003968
path: "XREAppDist:searchplugins",
condition: WIN,
stat: 1,
},
{
path: "XCurProcD:extensions",
condition: WIN,
stat: 1,
},
{ // bug 1543090
path: "GreD:omni.ja",
condition: WIN,
stat: 1,
},
{ // bug 1543090
path: "XCurProcD:omni.ja",
condition: WIN,
stat: 2,
},
],
// Things that are expected to be completely out of the startup path
// and loaded lazily when used for the first time by the user should
// be blacklisted here.
"before becoming idle": [
{
path: "XREAppFeat:screenshots@mozilla.org.xpi",
ignoreIfUnused: true,
close: 1,
},
{
path: "XREAppFeat:webcompat-reporter@mozilla.org.xpi",
ignoreIfUnused: true,
stat: 1,
close: 1,
},
{ // bug 1391590
path: "ProfD:places.sqlite-journal",
ignoreIfUnused: true,
fsync: 1,
stat: 4,
write: 2,
},
{ // bug 1391590
path: "ProfD:places.sqlite-wal",
ignoreIfUnused: true,
stat: 4,
fsync: 3,
write: 148,
},
{ // bug 1391590
path: "ProfD:places.sqlite-shm",
condition: WIN,
ignoreIfUnused: true,
stat: 1,
},
{ // bug 1391590
path: "ProfD:places.sqlite",
ignoreIfUnused: true,
fsync: 2,
read: 1,
stat: 3,
write: 1310,
},
{ // bug 1391590
path: "ProfD:favicons.sqlite-journal",
ignoreIfUnused: true,
fsync: 2,
stat: 7,
write: 7,
},
{ // bug 1391590
path: "ProfD:favicons.sqlite-wal",
ignoreIfUnused: true,
fsync: 2,
stat: 7,
write: 15,
},
{ // bug 1391590
path: "ProfD:favicons.sqlite-shm",
condition: WIN,
ignoreIfUnused: true,
stat: 2,
},
{ // bug 1391590
path: "ProfD:favicons.sqlite",
ignoreIfUnused: true,
fsync: 3,
read: 4,
stat: 4,
write: 1300,
},
{
path: "ProfD:key4.db-journal",
condition: WIN,
canonicalize: true,
stat: 2,
},
{
path: "ProfD:key4.db-wal",
condition: WIN,
canonicalize: true,
stat: 2,
},
{
path: "ProfD:",
condition: WIN,
ignoreIfUnused: true,
stat: 3,
},
{ // bug 1543090
path: "XCurProcD:omni.ja",
condition: WIN,
stat: 7,
},
],
};
for (let name of ["d3d11layers", "d3d9video", "glcontext", "d3d11video", "wmfvpxvideo"]) {
startupPhases["before first paint"].push({
path: `ProfD:${name}.guard`,
ignoreIfUnused: true,
stat: 1,
});
}
function expandWhitelistPath(path, canonicalize = false) {
if (path.includes(":")) {
let [prefix, suffix] = path.split(":");
let [key, property] = prefix.split(".");
let dir = Services.dirsvc.get(key, Ci.nsIFile);
if (property) {
dir = dir[property];
}
if (canonicalize) {
path = dir.QueryInterface(Ci.nsILocalFileWin).canonicalPath;
} else {
// Resolve symLinks.
let dirPath = dir.path;
while (dir && !dir.isSymlink()) {
dir = dir.parent;
}
if (dir) {
dirPath = dirPath.replace(dir.path, dir.target);
}
path = dirPath;
}
if (suffix) {
path += "/" + suffix;
}
}
if (AppConstants.platform == "win") {
path = path.replace(/\//g, "\\");
}
return path;
}
function getStackFromProfile(profile, stack) {
const stackPrefixCol = profile.stackTable.schema.prefix;
const stackFrameCol = profile.stackTable.schema.frame;
const frameLocationCol = profile.frameTable.schema.location;
let result = [];
while (stack) {
let sp = profile.stackTable.data[stack];
let frame = profile.frameTable.data[sp[stackFrameCol]];
stack = sp[stackPrefixCol];
frame = profile.stringTable[frame[frameLocationCol]];
if (frame != "js::RunScript" && !frame.startsWith("next (self-hosted:")) {
result.push(frame);
}
}
return result;
}
function pathMatches(path, filename) {
path = path.toLowerCase();
return path == filename || // Full match
// Wildcard on both sides of the path
(path.startsWith("*") && path.endsWith("*") &&
filename.includes(path.slice(1, -1))) ||
// Wildcard suffix
(path.endsWith("*") && filename.startsWith(path.slice(0, -1))) ||
// Wildcard prefix
(path.startsWith("*") && filename.endsWith(path.slice(1)));
}
add_task(async function() {
if (!AppConstants.NIGHTLY_BUILD && !AppConstants.MOZ_DEV_EDITION && !AppConstants.DEBUG) {
ok(!("@mozilla.org/test/startuprecorder;1" in Cc),
"the startup recorder component shouldn't exist in this non-nightly/non-devedition/" +
"non-debug build.");
return;
}
{
let omniJa = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
omniJa.append("omni.ja");
if (!omniJa.exists()) {
ok(false, "This test requires a packaged build, " +
"run 'mach package' and then use --appname=dist");
return;
}
}
let startupRecorder = Cc["@mozilla.org/test/startuprecorder;1"].getService().wrappedJSObject;
await startupRecorder.done;
// Add system add-ons to the whitelist dynamically.
// They should go in the omni.ja file (bug 1357205).
{
let addons = await AddonManager.getAddonsByTypes(["extension"]);
for (let addon of addons) {
if (addon.isSystem) {
startupPhases["before opening first browser window"].push({
path: `XREAppFeat:${addon.id}.xpi`,
stat: 3,
close: 2,
});
startupPhases["before handling user events"].push({
path: `XREAppFeat:${addon.id}.xpi`,
condition: WIN,
stat: 2,
});
}
}
}
// Check for main thread I/O markers in the startup profile.
let profile = startupRecorder.data.profile.threads[0];
let phases = {};
{
const nameCol = profile.markers.schema.name;
const dataCol = profile.markers.schema.data;
let markersForCurrentPhase = [];
for (let m of profile.markers.data) {
let markerName = profile.stringTable[m[nameCol]];
if (markerName.startsWith("startupRecorder:")) {
phases[markerName.split("startupRecorder:")[1]] = markersForCurrentPhase;
markersForCurrentPhase = [];
continue;
}
if (markerName != "FileIO")
continue;
let markerData = m[dataCol];
if (markerData.source == "sqlite-mainthread") {
continue;
}
let samples = markerData.stack.samples;
let stack = samples.data[0][samples.schema.stack];
markersForCurrentPhase.push({operation: markerData.operation,
filename: markerData.filename,
source: markerData.source,
stackId: stack});
}
}
for (let phase in startupPhases) {
startupPhases[phase] =
startupPhases[phase].filter(entry => !("condition" in entry) || entry.condition);
startupPhases[phase].forEach(entry => {
entry.path = expandWhitelistPath(entry.path, entry.canonicalize);
});
}
let tmpPath = expandWhitelistPath(MAC ? "TmpD:" : "/dev/shm").toLowerCase();
let shouldPass = true;
for (let phase in phases) {
let whitelist = startupPhases[phase];
info(`whitelisted paths ${phase}:\n` +
whitelist.map(e => {
let operations = Object.keys(e).filter(k => k != "path")
.map(k => `${k}: ${e[k]}`);
return ` ${e.path} - ${operations.join(", ")}`;
}).join("\n"));
let markers = phases[phase];
for (let marker of markers) {
if (marker.operation == "create/open") {
// TODO: handle these I/O markers once they are supported on
// non-Windows platforms.
continue;
}
// Convert to lower case before comparing because the OS X test slaves
// have the 'Firefox' folder in 'Library/Application Support' created
// as 'firefox' for some reason.
let filename = marker.filename.toLowerCase();
if (!filename) {
// We are still missing the filename on some mainthreadio markers,
// these markers are currently useless for the purpose of this test.
continue;
}
if (!WIN) {
if (filename == "/dev/urandom") {
continue;
}
// Ignore I/O due to IPC. This doesn't really touch the disk.
if (filename.startsWith(tmpPath + "/org.chromium.")) {
continue;
}
}
let expected = false;
for (let entry of whitelist) {
if (pathMatches(entry.path, filename)) {
entry[marker.operation] = (entry[marker.operation] || 0) - 1;
entry._used = true;
expected = true;
break;
}
}
if (!expected) {
record(false,
`unexpected ${marker.operation} on ${marker.filename} ${phase}`,
undefined,
" " + getStackFromProfile(profile, marker.stackId).join("\n "));
shouldPass = false;
}
info(`(${marker.source}) ${marker.operation} - ${marker.filename}`);
if (kDumpAllStacks) {
info(getStackFromProfile(profile, marker.stackId).map(f => " " + f)
.join("\n"));
}
}
for (let entry of whitelist) {
for (let op in entry) {
if (["path", "condition", "canonicalize", "ignoreIfUnused", "_used"].includes(op)) {
continue;
}
let message = `${op} on ${entry.path} `;
if (entry[op] == 0) {
message += "as many times as expected";
} else if (entry[op] > 0) {
message += `allowed ${entry[op]} more times`;
} else {
message += `${entry[op] * -1} more times than expected`;
}
ok(entry[op] >= 0, `${message} ${phase}`);
}
if (!("_used" in entry) && !entry.ignoreIfUnused) {
ok(false, `unused whitelist entry ${phase}: ${entry.path}`);
}
}
}
if (shouldPass) {
ok(shouldPass, "No unexpected main thread I/O during startup");
} else {
const filename = "startup-mainthreadio-profile.json";
let path = Cc["@mozilla.org/process/environment;1"]
.getService(Ci.nsIEnvironment)
.get("MOZ_UPLOAD_DIR");
let encoder = new TextEncoder();
let profilePath = OS.Path.join(path, filename);
await OS.File.writeAtomic(profilePath,
encoder.encode(JSON.stringify(startupRecorder.data.profile)));
ok(false,
"Found some unexpected main thread I/O during startup; profile uploaded in " +
filename);
}
});

Просмотреть файл

@ -0,0 +1,20 @@
[DEFAULT]
# Currently disabled on debug due to debug-only failures, see bug 1549723.
skip-if = debug
# to avoid overhead when running the browser normally, startupRecorder.js will
# do almost nothing unless browser.startup.record is true.
# gfx.canvas.willReadFrequently.enable is just an optimization, but needs to be
# set during early startup to have an impact as a canvas will be used by
# startupRecorder.js
prefs =
# Skip migration work in BG__migrateUI for browser_startup.js since it isn't
# representative of common startup, and triggers Places I/O.
browser.migration.version=9999999
browser.startup.record=true
gfx.canvas.willReadFrequently.enable=true
environment =
MOZ_PROFILER_STARTUP=1
MOZ_PROFILER_STARTUP_FEATURES=js,mainthreadio
MOZ_PROFILER_STARTUP_ENTRIES=10000000
[../browser_startup_mainthreadio.js]
[../browser_startup_content_mainthreadio.js]

Просмотреть файл

@ -28,6 +28,7 @@ support-files =
[browser_trackingUI_open_preferences.js]
[browser_trackingUI_pbmode_exceptions.js]
[browser_trackingUI_report_breakage.js]
skip-if = os == 'linux' && (debug || asan) # Bug 1546797
[browser_trackingUI_state.js]
skip-if = serviceworker_e10s # see https://bugzilla.mozilla.org/show_bug.cgi?id=1511303#c1
[browser_trackingUI_state_all_disabled.js]

Просмотреть файл

@ -34,6 +34,7 @@ BROWSER_CHROME_MANIFESTS += [
'content/test/pageinfo/browser.ini',
'content/test/performance/browser.ini',
'content/test/performance/hidpi/browser.ini',
'content/test/performance/io/browser.ini',
'content/test/performance/legacyurlbar/browser.ini',
'content/test/performance/lowdpi/browser.ini',
'content/test/permissions/browser.ini',

Просмотреть файл

@ -130,6 +130,20 @@
</popupnotificationcontent>
</popupnotification>
<popupnotification id="appMenu-update-unsupported-notification"
popupid="update-unsupported"
data-lazy-l10n-id="appmenu-update-unsupported"
data-l10n-attrs="buttonlabel, buttonaccesskey, secondarybuttonlabel, secondarybuttonaccesskey"
closebuttonhidden="true"
dropmarkerhidden="true"
checkboxhidden="true"
buttonhighlight="true"
hidden="true">
<popupnotificationcontent id="update-unsupported-notification-content" orient="vertical">
<description id="update-unsupported-description" data-lazy-l10n-id="appmenu-update-unsupported-message"></description>
</popupnotificationcontent>
</popupnotification>
<popupnotification id="appMenu-update-restart-notification"
popupid="update-restart"
data-lazy-l10n-id="appmenu-update-restart"
@ -217,6 +231,7 @@
<toolbarbutton class="panel-banner-item"
label-update-available="&updateAvailable.panelUI.label;"
label-update-manual="&updateManual.panelUI.label;"
label-update-unsupported="&updateUnsupported.panelUI.label;"
label-update-restart="&updateRestart.panelUI.label2;"
oncommand="PanelUI._onBannerItemSelected(event)"
wrap="true"

Просмотреть файл

@ -466,6 +466,12 @@ add_task(async function testPolicyCategorization() {
// Cleanup after this particular test.
if (Services.policies.status != Ci.nsIEnterprisePolicies.INACTIVE) {
await EnterprisePolicyTesting.setupPolicyEngineWithJson({
policies: {"Cookies": {
"Locked": false,
},
},
});
await EnterprisePolicyTesting.setupPolicyEngineWithJson("");
}
is(Services.policies.status, Ci.nsIEnterprisePolicies.INACTIVE, "Engine is inactive at the end of the test");

Просмотреть файл

@ -11,9 +11,7 @@
*/
const TEST_PATH = "http://example.net/browser/browser/components/resistfingerprinting/test/browser/";
const DEFAULT_ROUNDED_WIDTH_STEP = 200;
const DEFAULT_ROUNDED_HEIGHT_STEP = 100;
const { RFPHelper } = ChromeUtils.import("resource://gre/modules/RFPHelper.jsm");
// A set of test cases which defines the width and the height of the outer window.
const TEST_CASES = [
@ -50,10 +48,9 @@ function handleOSFuzziness(aContent, aTarget) {
function checkForDefaultSetting(
aContentWidth, aContentHeight, aRealWidth, aRealHeight) {
// The default behavior for rounding is to round window with 200x100 stepping.
// So, we can get the rounded size by subtracting the remainder.
let targetWidth = aRealWidth - (aRealWidth % DEFAULT_ROUNDED_WIDTH_STEP);
let targetHeight = aRealHeight - (aRealHeight % DEFAULT_ROUNDED_HEIGHT_STEP);
// We can get the rounded size by subtracting twice the margin.
let targetWidth = aRealWidth - (2 * RFPHelper.steppedRange(aRealWidth));
let targetHeight = aRealHeight - (2 * RFPHelper.steppedRange(aRealHeight));
// This platform-specific code is explained in the large comment below.
if (getPlatform() != "linux") {

Просмотреть файл

@ -63,6 +63,7 @@ startupRecorder.prototype = {
if (!Services.prefs.getBoolPref("browser.startup.record", false))
return;
Services.profiler.AddMarker("startupRecorder:" + name);
this.data.code[name] = {
components: Cu.loadedComponents,
modules: Cu.loadedModules,
@ -163,8 +164,24 @@ startupRecorder.prototype = {
Services.prefs.readStats((key, value) => this.data.prefStats[key] = value);
}
paints = null;
this._resolve();
this._resolve = null;
let env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
if (!env.exists("MOZ_PROFILER_STARTUP")) {
this._resolve();
this._resolve = null;
return;
}
Services.profiler.getProfileDataAsync().then(profileData => {
this.data.profile = profileData;
// There's no equivalent StartProfiler call in this file because the
// profiler is started using the MOZ_PROFILER_STARTUP environment
// variable in browser/base/content/test/performance/browser.ini
Services.profiler.StopProfiler();
this._resolve();
this._resolve = null;
});
});
} else {
const topicsToNames = {

Просмотреть файл

@ -479,8 +479,9 @@ class UrlbarView {
favicon.src = result.payload.icon || UrlbarUtils.ICON.DEFAULT;
}
let title = item._elements.get("title");
this._addTextContentWithHighlights(
item._elements.get("title"), result.title, result.titleHighlights);
title, result.title, result.titleHighlights);
let tagsContainer = item._elements.get("tagsContainer");
tagsContainer.textContent = "";
@ -495,6 +496,7 @@ class UrlbarView {
}
let action = "";
let isVisitAction = false;
let setURL = false;
switch (result.type) {
case UrlbarUtils.RESULT_TYPE.TAB_SWITCH:
@ -510,21 +512,20 @@ class UrlbarView {
[result.payload.engine], 1);
break;
case UrlbarUtils.RESULT_TYPE.KEYWORD:
if (result.payload.input.trim() == result.payload.keyword) {
action = bundle.GetStringFromName("visit");
}
isVisitAction = result.payload.input.trim() == result.payload.keyword;
break;
case UrlbarUtils.RESULT_TYPE.OMNIBOX:
action = result.payload.content;
break;
default:
if (result.heuristic) {
action = bundle.GetStringFromName("visit");
isVisitAction = true;
} else {
setURL = true;
}
break;
}
let url = item._elements.get("url");
if (setURL) {
this._addTextContentWithHighlights(url, result.payload.displayUrl,
@ -532,7 +533,15 @@ class UrlbarView {
} else {
url.textContent = "";
}
if (isVisitAction) {
action = bundle.GetStringFromName("visit");
title.setAttribute("isurl", "true");
} else {
title.removeAttribute("isurl");
}
item._elements.get("action").textContent = action;
item._elements.get("titleSeparator").hidden = !action && !setURL;
}

Просмотреть файл

@ -18,6 +18,13 @@ appmenu-update-manual =
appmenu-update-manual-message = Download a fresh copy of { -brand-shorter-name } and well help you to install it.
appmenu-update-whats-new =
.value = See whats new.
appmenu-update-unsupported =
.label = { -brand-shorter-name } is unable to update to the latest version.
.buttonlabel = Learn more
.buttonaccesskey = L
.secondarybuttonlabel = Close
.secondarybuttonaccesskey = C
appmenu-update-unsupported-message = The latest version of { -brand-shorter-name } is not supported on your system.
appmenu-update-restart =
.label = Restart to update { -brand-shorter-name }.
.buttonlabel = Restart and Restore

Просмотреть файл

@ -924,6 +924,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
<!ENTITY updateAvailable.panelUI.label "Download &brandShorterName; update">
<!ENTITY updateManual.panelUI.label "Download a fresh copy of &brandShorterName;">
<!ENTITY updateUnsupported.panelUI.label "You cannot perform further updates">
<!ENTITY updateRestart.panelUI.label2 "Restart to update &brandShorterName;">
<!ENTITY newTabControlled.header.message "Your New Tab has changed.">

Просмотреть файл

@ -68,8 +68,8 @@
#PanelUI-menu-button[badge-status="update-available"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
#PanelUI-menu-button[badge-status="update-manual"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
#PanelUI-menu-button[badge-status="update-restart"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
background: #74BF43 url(chrome://browser/skin/update-badge.svg) no-repeat center;
#PanelUI-menu-button[badge-status="update-restart"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
#PanelUI-menu-button[badge-status="update-unsupported"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
border-radius: 50%;
box-shadow: none;
/* "!important" is necessary to override the rule in toolbarbutton.css */
@ -79,8 +79,25 @@
min-height: 12px;
}
.panel-banner-item[notificationid^=update]::after {
#PanelUI-menu-button[badge-status="update-available"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
#PanelUI-menu-button[badge-status="update-manual"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
#PanelUI-menu-button[badge-status="update-restart"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
background: #74BF43 url(chrome://browser/skin/update-badge.svg) no-repeat center;
}
#PanelUI-menu-button[badge-status="update-unsupported"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
background: #FFE900 url(chrome://browser/skin/update-badge.svg) no-repeat center;
}
.panel-banner-item[notificationid="update-available"]::after,
.panel-banner-item[notificationid="update-manual"]::after,
.panel-banner-item[notificationid="update-restart"]::after {
background: #74BF43 url(chrome://browser/skin/update-badge.svg) no-repeat center;
border-radius: 50%;
}
.panel-banner-item[notificationid="update-unsupported"]::after {
background: #FFE900 url(chrome://browser/skin/update-badge.svg) no-repeat center;
border-radius: 50%;
}
@ -940,7 +957,7 @@ panelmultiview[mainViewId="PanelUI-fxa"] #PanelUI-remotetabs-syncnow {
:root[lwt-popup-brighttext] .panel-banner-item:not([disabled]) {
background-color: rgba(48,230,11,.1);
color: #F9F9FA !important;
color: @appmenuWarningColorBrightText@ !important;
}
:root[lwt-popup-brighttext] .panel-banner-item:not([disabled]):hover {
@ -951,6 +968,30 @@ panelmultiview[mainViewId="PanelUI-fxa"] #PanelUI-remotetabs-syncnow {
background-color: rgba(48,230,11,.2);
}
.panel-banner-item[notificationid="update-unsupported"] {
background-color: @appmenuWarningBackgroundColor@;
}
.panel-banner-item[notificationid="update-unsupported"]:not([disabled]):hover {
background-color: @appmenuWarningBackgroundColorHover@;
}
.panel-banner-item[notificationid="update-unsupported"]:not([disabled]):hover:active {
background-color: @appmenuWarningBackgroundColorActive@;
}
:root[lwt-popup-brighttext] .panel-banner-item[notificationid="update-unsupported"]:not([disabled]) {
background-color: @appmenuWarningBackgroundColorBrightText@;
}
:root[lwt-popup-brighttext] .panel-banner-item[notificationid="update-unsupported"]:not([disabled]):hover {
background-color: @appmenuWarningBackgroundColorHoverBrightText@;
}
:root[lwt-popup-brighttext] .panel-banner-item[notificationid="update-unsupported"]:not([disabled]):active {
background-color: @appmenuWarningBackgroundColorActiveBrightText@;
}
#customization-palette .toolbarbutton-multiline-text,
#customization-palette .toolbarbutton-text {
display: none;

Просмотреть файл

@ -381,3 +381,8 @@ html|*#webRTC-previewVideo {
background: #74BF43 url(chrome://browser/skin/notification-icons/update.svg) no-repeat center;
border-radius: 50%;
}
.popup-notification-icon[popupid="update-unsupported"] {
background: #FFE900 url(chrome://browser/skin/notification-icons/update.svg) no-repeat center;
border-radius: 50%;
}

Просмотреть файл

@ -58,7 +58,6 @@
border-radius: 2px;
display: flex;
flex-direction: column;
text-align: left;
height: 150px;
cursor: pointer;
position: relative;
@ -74,7 +73,7 @@
}
#editBookmarkPanelRecommendationTitle {
font-size: 1.5rem;
font-size: 16px;
font-weight: 400;
line-height: 1.25;
margin-bottom: 6px;
@ -82,7 +81,7 @@
}
#editBookmarkPanelRecommendationContent {
font-size: 1rem;
font-size: 11px;
line-height: 1.5;
margin: 0;
}
@ -102,13 +101,15 @@
#editBookmarkPanelRecommendation #cfrClose {
position: absolute;
right: 18px;
top: 18px;
padding: 3px 2px;
inset-inline-end: 16px;
top: 15px;
width: 12px;
height: 12px;
background-image: url(chrome://browser/skin/stop.svg);
background-size: 12px;
background-repeat: no-repeat;
background-position: center;
-moz-context-properties: fill, fill-opacity;
fill: currentColor;
fill-opacity: 0.6;

Просмотреть файл

@ -72,10 +72,15 @@
mask-image: linear-gradient(to left, transparent, black 2em);
}
.urlbarView-title[overflow]:-moz-locale-dir(rtl) {
.urlbarView-title[overflow]:not([isurl]):-moz-locale-dir(rtl) {
mask-image: linear-gradient(to right, transparent, black 2em);
}
.urlbarView-title[isurl]:-moz-locale-dir(rtl),
.urlbarView-url:-moz-locale-dir(rtl) {
direction: ltr !important;
}
.urlbarView-row:hover {
background: var(--arrowpanel-dimmed);
}
@ -156,10 +161,6 @@
color: var(--urlbar-popup-url-color);
}
.urlbarView-url:-moz-locale-dir(rtl) {
direction: ltr !important;
}
.urlbarView-row[selected] > .urlbarView-row-inner > .urlbarView-title-separator::before,
.urlbarView-row[selected] > .urlbarView-row-inner > .urlbarView-secondary {
color: inherit;

Просмотреть файл

@ -59,7 +59,18 @@ const {
const CONNECTION_TIMING_OUT_DELAY = 3000;
const CONNECTION_CANCEL_DELAY = 13000;
async function getRuntimeIcon(channel) {
async function getRuntimeIcon(runtime, channel) {
if (runtime.isFenix) {
switch (channel) {
case "release":
case "beta":
return "chrome://devtools/skin/images/aboutdebugging-fenix.svg";
case "aurora":
default:
return "chrome://devtools/skin/images/aboutdebugging-fenix-nightly.svg";
}
}
return (channel === "release" || channel === "beta" || channel === "aurora")
? `chrome://devtools/skin/images/aboutdebugging-firefox-${ channel }.svg`
: "chrome://devtools/skin/images/aboutdebugging-firefox-nightly.svg";
@ -107,7 +118,7 @@ function connectRuntime(id) {
const deviceDescription = await clientWrapper.getDeviceDescription();
const compatibilityReport = await clientWrapper.checkVersionCompatibility();
const icon = await getRuntimeIcon(deviceDescription.channel);
const icon = await getRuntimeIcon(runtime, deviceDescription.channel);
const {
CHROME_DEBUG_ENABLED,
@ -129,6 +140,19 @@ function connectRuntime(id) {
await clientWrapper.getPreference(SERVICE_WORKERS_ENABLED, true);
const serviceWorkersAvailable = serviceWorkersEnabled && !privateBrowsing;
// Fenix specific workarounds are needed until we can get proper server side APIs
// to detect Fenix and get the proper application names and versions.
// See https://github.com/mozilla-mobile/fenix/issues/2016.
// For Fenix runtimes, the ADB runtime name is more accurate than the one returned
// by the Device actor.
const runtimeName = runtime.isFenix ? runtime.name : deviceDescription.name;
// For Fenix runtimes, the version we should display is the application version
// retrieved from ADB, and not the Gecko version returned by the Device actor.
const version = runtime.isFenix ?
runtime.extra.adbPackageVersion : deviceDescription.version;
const runtimeDetails = {
clientWrapper,
compatibilityReport,
@ -137,10 +161,10 @@ function connectRuntime(id) {
info: {
deviceName: deviceDescription.deviceName,
icon,
name: deviceDescription.name,
name: runtimeName,
os: deviceDescription.os,
type: runtime.type,
version: deviceDescription.version,
version,
},
isMultiE10s: deviceDescription.isMultiE10s,
serviceWorkersAvailable,
@ -345,6 +369,7 @@ function updateNetworkRuntimes(locations) {
isConnectionFailed: false,
isConnectionNotResponding: false,
isConnectionTimeout: false,
isFenix: false,
isUnavailable: false,
isUnplugged: false,
isUnknown: false,
@ -366,11 +391,13 @@ function updateUSBRuntimes(adbRuntimes) {
extra: {
connectionParameters,
deviceName: adbRuntime.deviceName,
adbPackageVersion: adbRuntime.versionName,
},
isConnecting: false,
isConnectionFailed: false,
isConnectionNotResponding: false,
isConnectionTimeout: false,
isFenix: adbRuntime.isFenix,
isUnavailable: adbRuntime.isUnavailable,
isUnplugged: adbRuntime.isUnplugged,
name: adbRuntime.shortName,

Просмотреть файл

@ -37,7 +37,7 @@ class RuntimeInfo extends PureComponent {
},
dom.img(
{
className: "main-heading__icon runtime-info__icon",
className: "main-heading__icon runtime-info__icon qa-runtime-icon",
src: icon,
}
),

Просмотреть файл

@ -16,8 +16,10 @@ class UsbRuntime {
this.deviceName = adbRuntime.deviceName;
this.shortName = adbRuntime.shortName;
this.socketPath = adbRuntime.socketPath;
this.isFenix = adbRuntime.isFenix;
this.isUnavailable = false;
this.isUnplugged = false;
this.versionName = adbRuntime.versionName;
}
}
@ -32,8 +34,10 @@ class UnavailableUsbRuntime {
this.deviceName = adbDevice.name;
this.shortName = "Unavailable runtime";
this.socketPath = null;
this.isFenix = false;
this.isUnavailable = true;
this.isUnplugged = false;
this.versionName = null;
}
}
@ -48,8 +52,10 @@ class UnpluggedUsbRuntime {
this.deviceName = deviceName;
this.shortName = "Unplugged runtime";
this.socketPath = null;
this.isFenix = false;
this.isUnavailable = true;
this.isUnplugged = true;
this.versionName = null;
}
}

Просмотреть файл

@ -105,7 +105,12 @@ function runtimesReducer(state = RuntimesState(), action) {
case CONNECT_RUNTIME_SUCCESS: {
const { id, runtimeDetails, type } = action.runtime;
remoteClientManager.setClient(id, type, runtimeDetails.clientWrapper.client);
// Update the remoteClientManager with the connected runtime.
const client = runtimeDetails.clientWrapper.client;
const runtimeInfo = runtimeDetails.info;
remoteClientManager.setClient(id, type, client, runtimeInfo);
const updatedState = {
isConnecting: false,
isConnectionFailed: false,

Просмотреть файл

@ -105,6 +105,10 @@ const runtimeExtra = {
// device name
// unavailable on this-firefox and network-location runtimes
deviceName: PropTypes.string,
// version of the application coming from ADB, only available via USB. Useful for Fenix
// runtimes, because the version can't be retrieved from Service.appInfo.
adbPackageVersion: PropTypes.string,
};
const runtime = {
@ -129,6 +133,11 @@ const runtime = {
// this flag will be true when the connection was timeout.
isConnectionTimeout: PropTypes.bool.isRequired,
// this flag will be true when the detected runtime is Fenix (Firefox Preview).
// Fenix need specific logic to get their display name, version and logos.
// Discussion ongoing in https://github.com/mozilla-mobile/fenix/issues/2016
isFenix: PropTypes.bool.isRequired,
// unavailable runtimes are placeholders for devices where the runtime has not been
// started yet. For instance an ADB device connected without a compatible runtime
// running.

Просмотреть файл

@ -70,6 +70,7 @@ skip-if = (os == "win" && ccov) # Bug 1521349
[browser_aboutdebugging_devtoolstoolbox_target_destroyed.js]
skip-if = debug || asan # This test leaks. See bug 1529005
[browser_aboutdebugging_devtoolstoolbox_tooltip_markupview.js]
[browser_aboutdebugging_fenix_runtime_display.js]
[browser_aboutdebugging_message_close.js]
[browser_aboutdebugging_navigate.js]
[browser_aboutdebugging_persist_connection.js]

Просмотреть файл

@ -0,0 +1,144 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const RUNTIME_ID = "1337id";
const DEVICE_NAME = "Fancy Phone";
const SERVER_RUNTIME_NAME = "Mozilla Firefox";
const ADB_RUNTIME_NAME = "Firefox Preview";
const SERVER_VERSION = "v7.3.31";
const ADB_VERSION = "v1.3.37";
const FENIX_RELEASE_ICON_SRC = "chrome://devtools/skin/images/aboutdebugging-fenix.svg";
const FENIX_NIGHTLY_ICON_SRC =
"chrome://devtools/skin/images/aboutdebugging-fenix-nightly.svg";
/**
* Check that Fenix runtime information is correctly displayed in about:debugging.
*/
add_task(async function() {
const mocks = new Mocks();
mocks.createUSBRuntime(RUNTIME_ID, {
deviceName: DEVICE_NAME,
isFenix: true,
name: SERVER_RUNTIME_NAME,
shortName: ADB_RUNTIME_NAME,
versionName: ADB_VERSION,
version: SERVER_VERSION,
});
// open a remote runtime page
const { document, tab, window } = await openAboutDebugging();
await selectThisFirefoxPage(document, window.AboutDebugging.store);
mocks.emitUSBUpdate();
await connectToRuntime(DEVICE_NAME, document);
await selectRuntime(DEVICE_NAME, ADB_RUNTIME_NAME, document);
info("Check that the runtime information is displayed as expected");
const runtimeInfo = document.querySelector(".qa-runtime-name");
ok(runtimeInfo, "Runtime info for the Fenix runtime is displayed");
const runtimeInfoText = runtimeInfo.textContent;
ok(runtimeInfoText.includes(ADB_RUNTIME_NAME), "Name is the ADB name");
ok(!runtimeInfoText.includes(SERVER_RUNTIME_NAME),
"Name does not include the server name");
ok(runtimeInfoText.includes(ADB_VERSION), "Version contains the ADB version");
ok(!runtimeInfoText.includes(SERVER_VERSION),
"Version does not contain the server version");
const runtimeIcon = document.querySelector(".qa-runtime-icon");
is(runtimeIcon.src, FENIX_RELEASE_ICON_SRC, "The runtime icon is the Fenix icon");
info("Remove USB runtime");
mocks.removeUSBRuntime(RUNTIME_ID);
mocks.emitUSBUpdate();
await waitUntilUsbDeviceIsUnplugged(DEVICE_NAME, document);
await removeTab(tab);
});
/**
* Check that Fenix runtime information is correctly displayed in about:devtools-toolbox.
*/
add_task(async function() {
// We use a real local client combined with a mocked USB runtime to be able to open
// about:devtools-toolbox on a real target.
const clientWrapper = await createLocalClientWrapper();
// Mock getDeviceDescription() to force the local client to return "nightly" as the
// channel. Otherwise the value of the icon source would depend on the current channel.
const deviceDescription = await clientWrapper.getDeviceDescription();
clientWrapper.getDeviceDescription = function() {
return Object.assign({}, deviceDescription, {
channel: "nightly",
});
};
const mocks = new Mocks();
mocks.createUSBRuntime(RUNTIME_ID, {
clientWrapper: clientWrapper,
deviceName: DEVICE_NAME,
isFenix: true,
name: SERVER_RUNTIME_NAME,
shortName: ADB_RUNTIME_NAME,
versionName: ADB_VERSION,
version: SERVER_VERSION,
});
// open a remote runtime page
const { document, tab, window } = await openAboutDebugging();
await selectThisFirefoxPage(document, window.AboutDebugging.store);
mocks.emitUSBUpdate();
info("Select the runtime page for the USB runtime");
const onRequestSuccess = waitForRequestsSuccess(window.AboutDebugging.store);
await connectToRuntime(DEVICE_NAME, document);
await selectRuntime(DEVICE_NAME, ADB_RUNTIME_NAME, document);
info("Wait for requests to finish the USB runtime is backed by a real local client");
await onRequestSuccess;
info("Wait for the about:debugging target to be available");
await waitUntil(() => findDebugTargetByText("about:debugging", document));
const { devtoolsDocument, devtoolsTab } =
await openAboutDevtoolsToolbox(document, tab, window);
const runtimeInfo = devtoolsDocument.querySelector(".qa-runtime-info");
const runtimeInfoText = runtimeInfo.textContent;
ok(runtimeInfoText.includes(ADB_RUNTIME_NAME), "Name is the ADB runtime name");
ok(runtimeInfoText.includes(ADB_VERSION), "Version is the ADB version");
const runtimeIcon = devtoolsDocument.querySelector(".qa-runtime-icon");
is(runtimeIcon.src, FENIX_NIGHTLY_ICON_SRC, "The runtime icon is the Fenix icon");
info("Wait for all pending requests to settle on the DebuggerClient");
await clientWrapper.client.waitForRequestsToSettle();
await closeAboutDevtoolsToolbox(document, devtoolsTab, window);
info("Remove USB runtime");
mocks.removeUSBRuntime(RUNTIME_ID);
mocks.emitUSBUpdate();
await waitUntilUsbDeviceIsUnplugged(DEVICE_NAME, document);
await removeTab(tab);
await clientWrapper.close();
});
async function createLocalClientWrapper() {
info("Create a local DebuggerClient");
const { DebuggerServer } = require("devtools/server/main");
const { DebuggerClient } = require("devtools/shared/client/debugger-client");
const { ClientWrapper } =
require("devtools/client/aboutdebugging-new/src/modules/client-wrapper");
DebuggerServer.init();
DebuggerServer.registerAllActors();
const client = new DebuggerClient(DebuggerServer.connectPipe());
await client.connect();
return new ClientWrapper(client);
}

Просмотреть файл

@ -124,34 +124,44 @@ class Mocks {
* The id of the runtime.
* @param {Object} optional object used to create the fake runtime & device
* - channel: {String} Release channel, for instance "release", "nightly"
* - clientWrapper: {ClientWrapper} optional ClientWrapper for this runtime
* - deviceId: {String} Device id
* - deviceName: {String} Device name
* - isFenix: {Boolean} set by ADB if the package name matches a Fenix package
* - name: {String} Application name, for instance "Firefox"
* - shortName: {String} Short name for the device
* - socketPath: {String} (should only be used for connecting, so not here)
* - version: {String} Version, for instance "63.0a"
* - versionName: {String} Version return by ADB "63.0a"
* @return {Object} Returns the mock client created for this runtime so that methods
* can be overridden on it.
*/
createUSBRuntime(id, runtimeInfo = {}) {
// Add a new runtime to the list of scanned runtimes.
this._usbRuntimes.push({
id: id,
socketPath: runtimeInfo.socketPath || "test/path",
deviceId: runtimeInfo.deviceId || "test device id",
deviceName: runtimeInfo.deviceName || "test device name",
id: id,
isFenix: runtimeInfo.isFenix,
shortName: runtimeInfo.shortName || "testshort",
socketPath: runtimeInfo.socketPath || "test/path",
versionName: runtimeInfo.versionName || "1.0",
});
// Add a valid client that can be returned for this particular runtime id.
const mockUsbClient = createClientMock();
mockUsbClient.getDeviceDescription = () => {
return {
channel: runtimeInfo.channel || "release",
name: runtimeInfo.name || "TestBrand",
version: runtimeInfo.version || "1.0",
let mockUsbClient = runtimeInfo.clientWrapper;
if (!mockUsbClient) {
// If no clientWrapper was provided, create a mock client here.
mockUsbClient = createClientMock();
mockUsbClient.getDeviceDescription = () => {
return {
channel: runtimeInfo.channel || "release",
name: runtimeInfo.name || "TestBrand",
version: runtimeInfo.version || "1.0",
};
};
};
}
this._clients[RUNTIMES.USB][id] = mockUsbClient;
return mockUsbClient;

Просмотреть файл

@ -18,10 +18,10 @@ class DebugTargetInfo extends PureComponent {
return {
debugTargetData: PropTypes.shape({
connectionType: PropTypes.oneOf(Object.values(CONNECTION_TYPES)).isRequired,
deviceDescription: PropTypes.shape({
brandName: PropTypes.string.isRequired,
channel: PropTypes.string.isRequired,
runtimeInfo: PropTypes.shape({
deviceName: PropTypes.string,
icon: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
version: PropTypes.string.isRequired,
}).isRequired,
targetType: PropTypes.oneOf(Object.values(DEBUG_TARGET_TYPES)).isRequired,
@ -58,12 +58,12 @@ class DebugTargetInfo extends PureComponent {
getRuntimeText() {
const { debugTargetData, L10N } = this.props;
const { brandName, version } = debugTargetData.deviceDescription;
const { name, version } = debugTargetData.runtimeInfo;
const { connectionType } = debugTargetData;
return (connectionType === CONNECTION_TYPES.THIS_FIREFOX)
? L10N.getFormatStr("toolbox.debugTargetInfo.runtimeLabel.thisFirefox", version)
: L10N.getFormatStr("toolbox.debugTargetInfo.runtimeLabel", brandName, version);
: L10N.getFormatStr("toolbox.debugTargetInfo.runtimeLabel", name, version);
}
getAssetsForConnectionType() {
@ -143,18 +143,20 @@ class DebugTargetInfo extends PureComponent {
}
renderRuntime() {
const { channel, deviceName } = this.props.debugTargetData.deviceDescription;
if (!this.props.debugTargetData.runtimeInfo) {
// Skip the runtime render if no runtimeInfo is available.
// Runtime info is retrieved from the remote-client-manager, which might not be
// setup if about:devtools-toolbox was not opened from about:debugging.
return null;
}
const channelIcon =
(channel === "release" || channel === "beta" || channel === "aurora") ?
`chrome://devtools/skin/images/aboutdebugging-firefox-${ channel }.svg` :
"chrome://devtools/skin/images/aboutdebugging-firefox-nightly.svg";
const { icon, deviceName } = this.props.debugTargetData.runtimeInfo;
return dom.span(
{
className: "iconized-label",
className: "iconized-label qa-runtime-info",
},
dom.img({ src: channelIcon, className: "channel-icon" }),
dom.img({ src: icon, className: "channel-icon qa-runtime-icon" }),
dom.b({ className: "devtools-ellipsis-text" }, this.getRuntimeText()),
dom.span({ className: "devtools-ellipsis-text" }, deviceName),
);

Просмотреть файл

@ -98,7 +98,7 @@ class ToolboxToolbar extends Component {
visibleToolboxButtonCount: PropTypes.number,
// Data to show debug target info, if needed
debugTargetData: PropTypes.shape({
deviceDescription: PropTypes.object.isRequired,
runtimeInfo: PropTypes.object.isRequired,
targetType: PropTypes.string.isRequired,
}),
};

Просмотреть файл

@ -13,7 +13,7 @@ add_task(async function() {
info("Preload a local DebuggerClient as this-firefox in the remoteClientManager");
const { remoteClientManager } =
require("devtools/client/shared/remote-debugging/remote-client-manager");
remoteClientManager.setClient("this-firefox", "this-firefox", debuggerClient);
remoteClientManager.setClient("this-firefox", "this-firefox", debuggerClient, {});
registerCleanupFunction(() => {
remoteClientManager.removeAllClients();
});

Просмотреть файл

@ -14,10 +14,10 @@ exports[`DebugTargetInfo component Connection info renders the expected snapshot
toolbox.debugTargetInfo.connection.usb
</span>
<span
className="iconized-label"
className="iconized-label qa-runtime-info"
>
<img
className="channel-icon"
className="channel-icon qa-runtime-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
@ -66,10 +66,10 @@ exports[`DebugTargetInfo component Target icon renders the expected snapshot for
toolbox.debugTargetInfo.connection.usb
</span>
<span
className="iconized-label"
className="iconized-label qa-runtime-info"
>
<img
className="channel-icon"
className="channel-icon qa-runtime-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
@ -118,10 +118,10 @@ exports[`DebugTargetInfo component Target icon renders the expected snapshot for
toolbox.debugTargetInfo.connection.usb
</span>
<span
className="iconized-label"
className="iconized-label qa-runtime-info"
>
<img
className="channel-icon"
className="channel-icon qa-runtime-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
@ -170,10 +170,10 @@ exports[`DebugTargetInfo component Target icon renders the expected snapshot for
toolbox.debugTargetInfo.connection.usb
</span>
<span
className="iconized-label"
className="iconized-label qa-runtime-info"
>
<img
className="channel-icon"
className="channel-icon qa-runtime-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
@ -222,10 +222,10 @@ exports[`DebugTargetInfo component Target icon renders the expected snapshot for
toolbox.debugTargetInfo.connection.usb
</span>
<span
className="iconized-label"
className="iconized-label qa-runtime-info"
>
<img
className="channel-icon"
className="channel-icon qa-runtime-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
@ -265,10 +265,10 @@ exports[`DebugTargetInfo component Target title renders the expected snapshot fo
className="debug-target-info qa-debug-target-info"
>
<span
className="iconized-label"
className="iconized-label qa-runtime-info"
>
<img
className="channel-icon"
className="channel-icon qa-runtime-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
@ -306,10 +306,10 @@ exports[`DebugTargetInfo component Target title renders the expected snapshot fo
className="debug-target-info qa-debug-target-info"
>
<span
className="iconized-label"
className="iconized-label qa-runtime-info"
>
<img
className="channel-icon"
className="channel-icon qa-runtime-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b

Просмотреть файл

@ -32,31 +32,33 @@ const TEST_TOOLBOX = {
name: "Test Tab Name",
url: "http://some.target/url",
},
doc: {},
};
const TEST_TOOLBOX_NO_NAME = {
target: {
url: "http://some.target/without/a/name",
},
doc: {},
};
const USB_DEVICE_DESCRIPTION = {
brandName: "usbRuntimeBrandName",
channel: "release",
deviceName: "usbDeviceName",
icon: "chrome://devtools/skin/images/aboutdebugging-firefox-release.svg",
name: "usbRuntimeBrandName",
version: "1.0.0",
};
const THIS_FIREFOX_DEVICE_DESCRIPTION = {
brandName: "thisFirefoxRuntimeBrandName",
channel: "release",
icon: "chrome://devtools/skin/images/aboutdebugging-firefox-release.svg",
version: "1.0.0",
name: "thisFirefoxRuntimeBrandName",
};
const USB_TARGET_INFO = {
debugTargetData: {
connectionType: CONNECTION_TYPES.USB,
deviceDescription: USB_DEVICE_DESCRIPTION,
runtimeInfo: USB_DEVICE_DESCRIPTION,
targetType: DEBUG_TARGET_TYPES.TAB,
},
toolbox: TEST_TOOLBOX,
@ -66,7 +68,7 @@ const USB_TARGET_INFO = {
const THIS_FIREFOX_TARGET_INFO = {
debugTargetData: {
connectionType: CONNECTION_TYPES.THIS_FIREFOX,
deviceDescription: THIS_FIREFOX_DEVICE_DESCRIPTION,
runtimeInfo: THIS_FIREFOX_DEVICE_DESCRIPTION,
targetType: DEBUG_TARGET_TYPES.TAB,
},
toolbox: TEST_TOOLBOX,
@ -76,7 +78,7 @@ const THIS_FIREFOX_TARGET_INFO = {
const THIS_FIREFOX_NO_NAME_TARGET_INFO = {
debugTargetData: {
connectionType: CONNECTION_TYPES.THIS_FIREFOX,
deviceDescription: THIS_FIREFOX_DEVICE_DESCRIPTION,
runtimeInfo: THIS_FIREFOX_DEVICE_DESCRIPTION,
targetType: DEBUG_TARGET_TYPES.TAB,
},
toolbox: TEST_TOOLBOX_NO_NAME,

Просмотреть файл

@ -463,7 +463,7 @@ Toolbox.prototype = {
// Displays DebugTargetInfo which shows the basic information of debug target,
// if `about:devtools-toolbox` URL opens directly.
// DebugTargetInfo requires this._debugTargetData to be populated
this._debugTargetData = await this._getDebugTargetData();
this._debugTargetData = this._getDebugTargetData();
}
const domHelper = new DOMHelpers(this.win);
@ -794,20 +794,19 @@ Toolbox.prototype = {
}
},
_getDebugTargetData: async function() {
_getDebugTargetData: function() {
const url = new URL(this.win.location);
const searchParams = new this.win.URLSearchParams(url.search);
const targetType = searchParams.get("type") || DEBUG_TARGET_TYPES.TAB;
const deviceFront = await this.target.client.mainRoot.getFront("device");
const deviceDescription = await deviceFront.getDescription();
const remoteId = searchParams.get("remoteId");
const runtimeInfo = remoteClientManager.getRuntimeInfoByRemoteId(remoteId);
const connectionType = remoteClientManager.getConnectionTypeByRemoteId(remoteId);
return {
connectionType,
deviceDescription,
runtimeInfo,
targetType,
};
},

Просмотреть файл

@ -75,6 +75,8 @@ devtools.jar:
skin/images/checkbox.svg (themes/images/checkbox.svg)
skin/images/filter-swatch.svg (themes/images/filter-swatch.svg)
skin/images/aboutdebugging-connect-icon.svg (themes/images/aboutdebugging-connect-icon.svg)
skin/images/aboutdebugging-fenix-nightly.svg (themes/images/aboutdebugging-fenix-nightly.svg)
skin/images/aboutdebugging-fenix.svg (themes/images/aboutdebugging-fenix.svg)
skin/images/aboutdebugging-firefox-aurora.svg (themes/images/aboutdebugging-firefox-aurora.svg)
skin/images/aboutdebugging-firefox-beta.svg (themes/images/aboutdebugging-firefox-beta.svg)
skin/images/aboutdebugging-firefox-logo.svg (themes/images/aboutdebugging-firefox-logo.svg)

Просмотреть файл

@ -30,8 +30,6 @@ const SWAPPED_BROWSER_STATE = [
"_characterSet",
"_contentPrincipal",
"_imageDocument",
"_fullZoom",
"_textZoom",
"_isSyntheticDocument",
"_innerWindowID",
];

Просмотреть файл

@ -352,6 +352,25 @@ ResponsiveUI.prototype = {
debug("Wait until swap start");
await this.swap.start();
// Set the ui toolWindow to fullZoom and textZoom of 100%. Directly change
// the zoom levels of the toolwindow docshell. That doesn't affect the zoom
// of the RDM content, but it does send events that confuse the Zoom UI.
// So before we adjust the zoom levels of the toolWindow, we first cache
// the reported zoom levels of the RDM content, because we'll have to
// re-apply them to re-sync the Zoom UI.
// Cache the values now and we'll re-apply them near the end of this function.
// This is important since other steps here can also cause the Zoom UI update
// event to be sent for other browsers, and this means that the changes from
// our Zoom UI update event would be overwritten. After this function, future
// changes to zoom levels will send Zoom UI update events in an order that
// keeps the Zoom UI synchronized with the RDM content zoom levels.
const fullZoom = this.tab.linkedBrowser.fullZoom;
const textZoom = this.tab.linkedBrowser.textZoom;
ui.toolWindow.docShell.contentViewer.fullZoom = 1;
ui.toolWindow.docShell.contentViewer.textZoom = 1;
this.tab.addEventListener("BeforeTabRemotenessChange", this);
// Notify the inner browser to start the frame script
@ -371,6 +390,11 @@ ResponsiveUI.prototype = {
new SettingOnboardingTooltip(ui.toolWindow.document);
}
// Re-apply our cached zoom levels. Other Zoom UI update events have finished
// by now.
this.tab.linkedBrowser.fullZoom = fullZoom;
this.tab.linkedBrowser.textZoom = textZoom;
// Non-blocking message to tool UI to start any delayed init activities
message.post(this.toolWindow, "post-init");

Просмотреть файл

@ -17,6 +17,7 @@ function setZoomForBrowser(browser, zoom) {
add_task(async function() {
const INITIAL_ZOOM_LEVEL = 1;
const PRE_RDM_ZOOM_LEVEL = 1.5;
const MID_RDM_ZOOM_LEVEL = 2;
const tab = await addTab(TEST_URL);
@ -24,8 +25,17 @@ add_task(async function() {
await load(browser, TEST_URL);
// Get the initial zoom level.
const initialOuterZoom = getZoomForBrowser(browser);
is(initialOuterZoom, INITIAL_ZOOM_LEVEL, "Initial outer zoom should be " +
INITIAL_ZOOM_LEVEL + ".");
// Change the zoom level before we open RDM.
setZoomForBrowser(browser, INITIAL_ZOOM_LEVEL);
setZoomForBrowser(browser, PRE_RDM_ZOOM_LEVEL);
const preRDMOuterZoom = getZoomForBrowser(browser);
is(preRDMOuterZoom, PRE_RDM_ZOOM_LEVEL, "Pre-RDM outer zoom should be " +
PRE_RDM_ZOOM_LEVEL + ".");
// Start RDM on the tab. This will fundamentally change the way that browser behaves.
// It will now pass all of its messages through to the RDM docshell, meaning that when
@ -37,18 +47,18 @@ add_task(async function() {
// interactively. Interactively, many features of the container docShell -- including
// zoom -- are copied over to the RDM browser. In the test harness, this seems to first
// reset the docShell before toggling RDM, which makes checking the initial zoom of the
// UI and the RDM pane not useful.
// RDM pane not useful.
const initialUIZoom = uiDocShell.contentViewer.fullZoom;
isnot(initialUIZoom, MID_RDM_ZOOM_LEVEL,
"We should have a different UI initial zoom, so we can ensure it stays unchanged.");
const preZoomUIZoom = uiDocShell.contentViewer.fullZoom;
is(preZoomUIZoom, INITIAL_ZOOM_LEVEL,
"Pre-zoom UI zoom should be " + INITIAL_ZOOM_LEVEL + ".");
// Set the zoom level. This should tunnel to the inner browser and leave the UI alone.
setZoomForBrowser(browser, MID_RDM_ZOOM_LEVEL);
// The UI zoom should be unchanged by this.
const postZoomUIZoom = uiDocShell.contentViewer.fullZoom;
is(postZoomUIZoom, initialUIZoom, "UI zoom should be unchanged by RDM zoom.");
is(postZoomUIZoom, preZoomUIZoom, "UI zoom should be unchanged by RDM zoom.");
// The RDM zoom should be changed.
const finalRDMZoom = getZoomForBrowser(browser);
@ -56,4 +66,8 @@ add_task(async function() {
// Leave RDM. This should cause the outer pane to take on the full zoom of the RDM pane.
await closeRDM(tab);
// Bug 1541692: the following todo_is check will become an is check when this bug lands.
const finalOuterZoom = getZoomForBrowser(browser);
todo_is(finalOuterZoom, finalRDMZoom, "Final outer zoom should match last RDM zoom.");
});

Просмотреть файл

@ -13,6 +13,7 @@ const { CONNECTION_TYPES } = require("devtools/client/shared/remote-debugging/co
class RemoteClientManager {
constructor() {
this._clients = new Map();
this._runtimeInfoMap = new Map();
this._onClientClosed = this._onClientClosed.bind(this);
}
@ -24,10 +25,15 @@ class RemoteClientManager {
* @param {String} type
* Remote runtime type (see devtools/client/aboutdebugging-new/src/types).
* @param {DebuggerClient} client
* @param {Object} runtimeInfo
* See runtimeInfo type from client/aboutdebugging-new/src/types/runtime.js
*/
setClient(id, type, client) {
setClient(id, type, client, runtimeInfo) {
const key = this._getKey(id, type);
this._clients.set(key, client);
if (runtimeInfo) {
this._runtimeInfoMap.set(key, runtimeInfo);
}
client.addOneTimeListener("closed", this._onClientClosed);
}
@ -66,20 +72,26 @@ class RemoteClientManager {
* using getRemoteId.
*/
getClientByRemoteId(remoteId) {
const key = decodeURIComponent(remoteId);
const key = this._getKeyByRemoteId(remoteId);
return this._clients.get(key);
}
/**
* Retrieve the runtime info for a remote id. To display metadata about a runtime, such
* as name, device name, version... this runtimeInfo should be used rather than calling
* APIs on the client.
*/
getRuntimeInfoByRemoteId(remoteId) {
const key = this._getKeyByRemoteId(remoteId);
return this._runtimeInfoMap.get(key);
}
/**
* Retrieve a managed client for a remote id. The remote id should have been generated
* using getRemoteId.
*/
getConnectionTypeByRemoteId(remoteId) {
if (!remoteId) {
return CONNECTION_TYPES.THIS_FIREFOX;
}
const key = decodeURIComponent(remoteId);
const key = this._getKeyByRemoteId(remoteId);
for (const type of Object.values(CONNECTION_TYPES)) {
if (key.endsWith(type)) {
return type;
@ -92,11 +104,23 @@ class RemoteClientManager {
return id + "-" + type;
}
_getKeyByRemoteId(remoteId) {
if (!remoteId) {
// If no remote id was provided, return the key corresponding to the local
// this-firefox runtime.
const { THIS_FIREFOX } = CONNECTION_TYPES;
return this._getKey(THIS_FIREFOX, THIS_FIREFOX);
}
return decodeURIComponent(remoteId);
}
_removeClientByKey(key) {
const client = this._clients.get(key);
if (client) {
client.removeListener("closed", this._onClientClosed);
this._clients.delete(key);
this._runtimeInfoMap.delete(key);
}
}

Просмотреть файл

@ -11,6 +11,7 @@ const { CONNECTION_TYPES } =
add_task(async function testRemoteClientManager() {
for (const type of Object.values(CONNECTION_TYPES)) {
const fakeClient = createFakeClient();
const runtimeInfo = {};
const clientId = "clientId";
const remoteId = remoteClientManager.getRemoteId(clientId, type);
@ -24,14 +25,18 @@ add_task(async function testRemoteClientManager() {
`[${type}]: getClient returns null if no client was set`);
equal(remoteClientManager.getClientByRemoteId(remoteId), null,
`[${type}]: getClientByRemoteId returns null if no client was set`);
equal(remoteClientManager.getRuntimeInfoByRemoteId(remoteId), null,
`[${type}]: getRuntimeInfoByRemoteId returns null if no client was set`);
remoteClientManager.setClient(clientId, type, fakeClient);
remoteClientManager.setClient(clientId, type, fakeClient, runtimeInfo);
equal(remoteClientManager.hasClient(clientId, type), true,
`[${type}]: hasClient returns true`);
equal(remoteClientManager.getClient(clientId, type), fakeClient,
`[${type}]: getClient returns the correct client`);
equal(remoteClientManager.getClientByRemoteId(remoteId), fakeClient,
`[${type}]: getClientByRemoteId returns the correct client`);
equal(remoteClientManager.getRuntimeInfoByRemoteId(remoteId), runtimeInfo,
`[${type}]: getRuntimeInfoByRemoteId returns the correct object`);
remoteClientManager.removeClient(clientId, type);
equal(remoteClientManager.hasClient(clientId, type), false,
@ -40,7 +45,28 @@ add_task(async function testRemoteClientManager() {
`[${type}]: getClient returns null after removing the client`);
equal(remoteClientManager.getClientByRemoteId(remoteId), null,
`[${type}]: getClientByRemoteId returns null after removing the client`);
equal(remoteClientManager.getRuntimeInfoByRemoteId(), null,
`[${type}]: getRuntimeInfoByRemoteId returns null after removing the client`);
}
// Test various fallback scenarios for APIs relying on remoteId, when called without a
// remoteId, we expect to get the information for the local this-firefox runtime.
const { THIS_FIREFOX } = CONNECTION_TYPES;
const thisFirefoxClient = createFakeClient();
const thisFirefoxInfo = {};
remoteClientManager.setClient(THIS_FIREFOX, THIS_FIREFOX, thisFirefoxClient,
thisFirefoxInfo);
equal(remoteClientManager.getClientByRemoteId(), thisFirefoxClient,
`[fallback]: getClientByRemoteId returns this-firefox if remoteId is null`);
equal(remoteClientManager.getRuntimeInfoByRemoteId(), thisFirefoxInfo,
`[fallback]: getRuntimeInfoByRemoteId returns this-firefox if remoteId is null`);
const otherRemoteId = remoteClientManager.getRemoteId("clientId", CONNECTION_TYPES.USB);
equal(remoteClientManager.getClientByRemoteId(otherRemoteId), null,
`[fallback]: getClientByRemoteId does not fallback if remoteId is non-null`);
equal(remoteClientManager.getRuntimeInfoByRemoteId(otherRemoteId), null,
`[fallback]: getRuntimeInfoByRemoteId does not fallback if remoteId is non-null`);
});
add_task(async function testRemoteClientManagerWithUnknownType() {

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 7.2 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 7.2 KiB

Просмотреть файл

@ -191,7 +191,7 @@ var PromisesActor = protocol.ActorClassWithSpec(promisesSpec, {
return;
}
this._navigationLifetimePool.cleanup();
this._navigationLifetimePool.destroy();
this.dbg.removeAllDebuggees();
this.dbg.addDebuggees();
}),

Просмотреть файл

@ -6,6 +6,7 @@
const { RuntimeTypes } = require("devtools/client/webide/modules/runtime-types");
const { prepareTCPConnection } = require("devtools/shared/adb/commands/index");
const { shell } = require("devtools/shared/adb/commands/index");
class AdbRuntime {
constructor(adbDevice, socketPath) {
@ -15,10 +16,24 @@ class AdbRuntime {
this._socketPath = socketPath;
}
async init() {
const packageName = this._packageName();
const query = `dumpsys package ${packageName} | grep versionName`;
const versionNameString = await shell(this._adbDevice.id, query);
const matches = versionNameString.match(/versionName=([\d.]+)/);
if (matches && matches[1]) {
this._versionName = matches[1];
}
}
get id() {
return this._adbDevice.id + "|" + this._socketPath;
}
get isFenix() {
return this._packageName().includes("org.mozilla.fenix");
}
get deviceId() {
return this._adbDevice.id;
}
@ -27,8 +42,35 @@ class AdbRuntime {
return this._adbDevice.name;
}
get versionName() {
return this._versionName;
}
get shortName() {
return `Firefox ${this._channel()}`;
const packageName = this._packageName();
switch (packageName) {
case "org.mozilla.firefox":
return "Firefox";
case "org.mozilla.firefox_beta":
return "Firefox Beta";
case "org.mozilla.fennec":
case "org.mozilla.fennec_aurora":
// This package name is now the one for Firefox Nightly distributed
// through the Google Play Store since "dawn project"
// cf. https://bugzilla.mozilla.org/show_bug.cgi?id=1357351#c8
return "Firefox Nightly";
case "org.mozilla.fenix":
// The current Nightly build for Fenix is available under this package name
// but the official packages will use fenix, fenix.beta and fenix.nightly.
return "Firefox Preview";
case "org.mozilla.fenix.beta":
return "Firefox Preview Beta";
case "org.mozilla.fenix.nightly":
return "Firefox Preview Nightly";
default:
return "Firefox Custom";
}
}
get socketPath() {
@ -47,25 +89,6 @@ class AdbRuntime {
});
}
_channel() {
const packageName = this._packageName();
switch (packageName) {
case "org.mozilla.firefox":
return "";
case "org.mozilla.firefox_beta":
return "Beta";
case "org.mozilla.fennec":
case "org.mozilla.fennec_aurora":
// This package name is now the one for Firefox Nightly distributed
// through the Google Play Store since "dawn project"
// cf. https://bugzilla.mozilla.org/show_bug.cgi?id=1357351#c8
return "Nightly";
default:
return "Custom";
}
}
_packageName() {
// If using abstract socket address, it is "@org.mozilla.firefox/..."
// If using path base socket, it is "/data/data/<package>...""

Просмотреть файл

@ -134,7 +134,13 @@ class Adb extends EventEmitter {
async _getDeviceRuntimes(device) {
const socketPaths = [...await device.getRuntimeSocketPaths()];
return socketPaths.map(socketPath => new AdbRuntime(device, socketPath));
const runtimes = [];
for (const socketPath of socketPaths) {
const runtime = new AdbRuntime(device, socketPath);
await runtime.init();
runtimes.push(runtime);
}
return runtimes;
}
}

Просмотреть файл

@ -50,6 +50,7 @@ inline void nsIContent::SetPrimaryFrame(nsIFrame* aFrame) {
"Losing track of existing primary frame");
if (aFrame) {
MOZ_ASSERT(!aFrame->IsPlaceholderFrame());
if (MOZ_LIKELY(!IsHTMLElement(nsGkAtoms::area)) ||
aFrame->GetContent() == this) {
aFrame->SetIsPrimaryFrame(true);

Просмотреть файл

@ -307,12 +307,12 @@ WINDOW_EVENT(pageshow, ePageShow, EventNameType_HTMLBodyOrFramesetOnly,
WINDOW_EVENT(popstate, ePopState,
EventNameType_XUL | EventNameType_HTMLBodyOrFramesetOnly,
eBasicEventClass)
// Not supported yet
// WINDOW_EVENT(redo)
WINDOW_EVENT(rejectionhandled, eRejectionHandled,
EventNameType_HTMLBodyOrFramesetOnly, eBasicEventClass)
WINDOW_EVENT(storage, eStorage, EventNameType_HTMLBodyOrFramesetOnly,
eBasicEventClass)
// Not supported yet
// WINDOW_EVENT(undo)
WINDOW_EVENT(unhandledrejection, eUnhandledRejection,
EventNameType_HTMLBodyOrFramesetOnly, eBasicEventClass)
WINDOW_EVENT(unload, eUnload,
(EventNameType_XUL | EventNameType_SVGSVG |
EventNameType_HTMLBodyOrFramesetOnly),

Просмотреть файл

@ -617,9 +617,11 @@ bool AudioCallbackDriver::Init() {
output.channels = mOutputChannels;
output.layout = CUBEB_LAYOUT_UNDEFINED;
output.prefs = CubebUtils::GetDefaultStreamPrefs();
#if !defined(XP_WIN)
if (mInputDevicePreference == CUBEB_DEVICE_PREF_VOICE) {
output.prefs |= static_cast<cubeb_stream_prefs>(CUBEB_STREAM_PREF_VOICE);
}
#endif
uint32_t latency_frames = CubebUtils::GetCubebMSGLatencyInFrames(&output);

Просмотреть файл

@ -2199,13 +2199,13 @@ class RTCRtpReceiver {
_getRtpSourcesByType(type) {
this._fetchRtpSources();
// Only return the values from within the last 10 seconds as per the spec
let cutoffTime = this._rtpSourcesJsTimestamp - 10 * 1000;
let sources = [...this._rtpSources.values()].filter(
const cutoffTime = this._rtpSourcesJsTimestamp - 10 * 1000;
return [...this._rtpSources.values()].filter(
(entry) => {
return entry.sourceType == type &&
(entry.timestamp + entry.sourceClockOffset) >= cutoffTime;
}).map(e => {
let newEntry = {
const newEntry = {
source: e.source,
timestamp: e.timestamp + e.sourceClockOffset,
audioLevel: e.audioLevel,
@ -2214,8 +2214,7 @@ class RTCRtpReceiver {
Object.assign(newEntry, {voiceActivityFlag: e.voiceActivityFlag});
}
return newEntry;
});
return sources;
}).sort((a, b) => b.timestamp - a.timestamp);
}
getContributingSources() {

Просмотреть файл

@ -226,6 +226,7 @@ void CamerasParent::StopVideoCapture() {
}
nsresult rv = GetShutdownBarrier()->RemoveBlocker(self);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
Unused << rv;
return NS_OK;
}));
if (NS_FAILED(rv)) {

Просмотреть файл

@ -96,7 +96,12 @@ function check_mp4(v, enabled) {
check(codec, "probably");
ok(MediaSource.isTypeSupported(codec), "VP9 in MP4 should be supported in MSE");
});
check("video/mp4; codecs=\"av1\"", "probably");
if (IsAndroid()) {
check("video/mp4; codecs=\"av1\"", "");
} else {
check("video/mp4; codecs=\"av1\"", "probably");
}
}
function check_mp3(v, enabled) {
@ -138,6 +143,10 @@ function getPref(name) {
return pref;
}
function IsAndroid() {
return getAndroidVersion() >= 0;
}
function IsSupportedAndroid() {
return getAndroidVersion() >= 14;
}

Просмотреть файл

@ -111,6 +111,24 @@
is(JSON.stringify(contributingSources),
JSON.stringify(remoteReceiver.getContributingSources()),
"getContributingSources is cached");
// Check that sources are sorted in descending order by time stamp
const timestamp3 = SpWrap(test.pcLocal).mozGetNowInRtpSourceReferenceTime();
// Larger offsets are further back in time
const testOffsets = [3, 7, 5, 6, 1, 4];
for (const offset of testOffsets) {
SpWrap(test.pcLocal).mozInsertAudioLevelForContributingSource(
localReceiver,
offset, // Using offset for SSRC for convenience
timestamp3 - offset,
true,
offset);
}
const sources = localReceiver.getContributingSources();
const sourceOffsets = sources.map(s => s.source);
is(JSON.stringify(sourceOffsets),
JSON.stringify([...testOffsets].sort((a, b) => a - b)),
`Contributing sources are sorted in descending order by timestamp:`
+ ` ${JSON.stringify(sources)}`);
};
var test;

Просмотреть файл

@ -302,12 +302,12 @@ void AudioBuffer::CopyFromChannel(const Float32Array& aDestination,
uint32_t aStartInChannel, ErrorResult& aRv) {
aDestination.ComputeLengthAndData();
uint32_t length = aDestination.Length();
if (aChannelNumber >= NumberOfChannels() || aStartInChannel > Length()) {
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return;
}
uint32_t count = std::min(Length() - aStartInChannel, aDestination.Length());
JS::AutoCheckCannotGC nogc;
JSObject* channelArray = mJSChannels[aChannelNumber];
if (channelArray) {
@ -323,18 +323,17 @@ void AudioBuffer::CopyFromChannel(const Float32Array& aDestination,
// The sourceData arrays should all have originated in
// RestoreJSChannelData, where they are created unshared.
MOZ_ASSERT(!isShared);
PodMove(aDestination.Data(), sourceData + aStartInChannel,
std::min(Length() - aStartInChannel, length));
PodMove(aDestination.Data(), sourceData + aStartInChannel, count);
return;
}
if (!mSharedChannels.IsNull()) {
CopyChannelDataToFloat(mSharedChannels, aChannelNumber, aStartInChannel,
aDestination.Data(), length);
aDestination.Data(), count);
return;
}
PodZero(aDestination.Data(), length);
PodZero(aDestination.Data(), count);
}
void AudioBuffer::CopyToChannel(JSContext* aJSContext,
@ -343,7 +342,6 @@ void AudioBuffer::CopyToChannel(JSContext* aJSContext,
uint32_t aStartInChannel, ErrorResult& aRv) {
aSource.ComputeLengthAndData();
uint32_t length = aSource.Length();
if (aChannelNumber >= NumberOfChannels() || aStartInChannel > Length()) {
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return;
@ -362,13 +360,13 @@ void AudioBuffer::CopyToChannel(JSContext* aJSContext,
return;
}
uint32_t count = std::min(Length() - aStartInChannel, aSource.Length());
bool isShared = false;
float* channelData = JS_GetFloat32ArrayData(channelArray, &isShared, nogc);
// The channelData arrays should all have originated in
// RestoreJSChannelData, where they are created unshared.
MOZ_ASSERT(!isShared);
PodMove(channelData + aStartInChannel, aSource.Data(),
std::min(Length() - aStartInChannel, length));
PodMove(channelData + aStartInChannel, aSource.Data(), count);
}
void AudioBuffer::GetChannelData(JSContext* aJSContext, uint32_t aChannel,

Просмотреть файл

@ -326,4 +326,4 @@ skip-if = verify || serviceworker_e10s
[test_file_upload.html]
support-files = script_file_upload.js sw_file_upload.js server_file_upload.sjs
[test_self_update_worker.html]
skip-if = serviceworker_e10s
skip-if = serviceworker_e10s || (toolkit == 'android' && !is_fennec)

Просмотреть файл

@ -155,7 +155,11 @@ interface WindowEventHandlers {
attribute EventHandler onpagehide;
attribute EventHandler onpageshow;
attribute EventHandler onpopstate;
[Func="mozilla::dom::DOMPrefs::dom_promise_rejection_events_enabled"]
attribute EventHandler onrejectionhandled;
attribute EventHandler onstorage;
[Func="mozilla::dom::DOMPrefs::dom_promise_rejection_events_enabled"]
attribute EventHandler onunhandledrejection;
attribute EventHandler onunload;
};

Просмотреть файл

@ -26,6 +26,10 @@ interface WorkerGlobalScope : EventTarget {
attribute EventHandler onoffline;
attribute EventHandler ononline;
[Func="mozilla::dom::DOMPrefs::dom_promise_rejection_events_enabled"]
attribute EventHandler onrejectionhandled;
[Func="mozilla::dom::DOMPrefs::dom_promise_rejection_events_enabled"]
attribute EventHandler onunhandledrejection;
// also has additional members in a partial interface
};

Просмотреть файл

@ -130,6 +130,8 @@ class WorkerGlobalScope : public DOMEventTargetHelper,
IMPL_EVENT_HANDLER(online)
IMPL_EVENT_HANDLER(offline)
IMPL_EVENT_HANDLER(rejectionhandled)
IMPL_EVENT_HANDLER(unhandledrejection)
void Dump(const Optional<nsAString>& aString) const;

Просмотреть файл

@ -2540,7 +2540,7 @@ nsresult EditorBase::InsertTextWithTransaction(
// In some cases, the node may be the anonymous div elemnt or a mozBR
// element. Let's try to look for better insertion point in the nearest
// text node if there is.
EditorRawDOMPoint pointToInsert = FindBetterInsertionPoint(aPointToInsert);
EditorDOMPoint pointToInsert = FindBetterInsertionPoint(aPointToInsert);
// If a neighboring text node already exists, use that
if (!pointToInsert.IsInTextNode()) {
@ -2573,7 +2573,7 @@ nsresult EditorBase::InsertTextWithTransaction(
NS_ENSURE_TRUE(newOffset.isValid(), NS_ERROR_FAILURE);
}
nsresult rv = InsertTextIntoTextNodeWithTransaction(
aStringToInsert, *pointToInsert.GetContainerAsText(),
aStringToInsert, MOZ_KnownLive(*pointToInsert.GetContainerAsText()),
pointToInsert.Offset());
NS_ENSURE_SUCCESS(rv, rv);
if (aPointAfterInsertedString) {
@ -2588,7 +2588,7 @@ nsresult EditorBase::InsertTextWithTransaction(
NS_ENSURE_TRUE(newOffset.isValid(), NS_ERROR_FAILURE);
// we are inserting text into an existing text node.
nsresult rv = InsertTextIntoTextNodeWithTransaction(
aStringToInsert, *pointToInsert.GetContainerAsText(),
aStringToInsert, MOZ_KnownLive(*pointToInsert.GetContainerAsText()),
pointToInsert.Offset());
NS_ENSURE_SUCCESS(rv, rv);
if (aPointAfterInsertedString) {

Просмотреть файл

@ -911,6 +911,7 @@ class EditorBase : public nsIEditor,
* E.g., adjusting whitespaces during composition.
* false, otherwise.
*/
MOZ_CAN_RUN_SCRIPT
nsresult InsertTextIntoTextNodeWithTransaction(
const nsAString& aStringToInsert, Text& aTextNode, int32_t aOffset,
bool aSuppressIME = false);

Просмотреть файл

@ -1543,8 +1543,9 @@ nsresult HTMLEditRules::WillInsertText(EditSubAction aEditSubAction,
}
// is it a return?
else if (subStr.Equals(newlineStr)) {
RefPtr<Element> newBRElement = wsObj.InsertBreak(
*SelectionRefPtr(), currentPoint, nsIEditor::eNone);
RefPtr<Element> newBRElement =
wsObj.InsertBreak(MOZ_KnownLive(*SelectionRefPtr()), currentPoint,
nsIEditor::eNone);
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
@ -1853,9 +1854,9 @@ EditActionResult HTMLEditRules::WillInsertParagraphSeparator() {
if (HTMLEditUtils::IsHeader(*blockParent)) {
// Headers: close (or split) header
nsresult rv =
ReturnInHeader(*blockParent, *atStartOfSelection.GetContainer(),
atStartOfSelection.Offset());
nsresult rv = ReturnInHeader(
*blockParent, MOZ_KnownLive(*atStartOfSelection.GetContainer()),
atStartOfSelection.Offset());
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
}
@ -1952,8 +1953,8 @@ nsresult HTMLEditRules::InsertBRElement(const EditorDOMPoint& aPointToBreak) {
}
pointToBreak = splitLinkNodeResult.SplitPoint();
}
brElement =
wsObj.InsertBreak(*SelectionRefPtr(), pointToBreak, nsIEditor::eNone);
brElement = wsObj.InsertBreak(MOZ_KnownLive(*SelectionRefPtr()),
pointToBreak, nsIEditor::eNone);
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
@ -2432,8 +2433,9 @@ nsresult HTMLEditRules::WillDeleteSelection(
so = range->StartOffset();
eo = range->EndOffset();
}
rv = WSRunObject::PrepareToDeleteRange(
&HTMLEditorRef(), address_of(visNode), &so, address_of(visNode), &eo);
rv = WSRunObject::PrepareToDeleteRange(MOZ_KnownLive(&HTMLEditorRef()),
address_of(visNode), &so,
address_of(visNode), &eo);
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
@ -2577,8 +2579,8 @@ nsresult HTMLEditRules::WillDeleteSelection(
return NS_ERROR_FAILURE;
}
nsIContent* otherContent = otherNode->AsContent();
rv = WSRunObject::PrepareToDeleteNode(&HTMLEditorRef(),
otherContent);
rv = WSRunObject::PrepareToDeleteNode(
MOZ_KnownLive(&HTMLEditorRef()), MOZ_KnownLive(otherContent));
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
@ -2603,8 +2605,8 @@ nsresult HTMLEditRules::WillDeleteSelection(
return NS_ERROR_FAILURE;
}
// Found break or image, or hr.
rv = WSRunObject::PrepareToDeleteNode(&HTMLEditorRef(),
visNode->AsContent());
rv = WSRunObject::PrepareToDeleteNode(
MOZ_KnownLive(&HTMLEditorRef()), MOZ_KnownLive(visNode->AsContent()));
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
@ -2877,7 +2879,7 @@ nsresult HTMLEditRules::WillDeleteSelection(
// surrounding whitespace in preparation to delete selection.
if (!IsPlaintextEditor()) {
AutoTransactionsConserveSelection dontChangeMySelection(HTMLEditorRef());
rv = WSRunObject::PrepareToDeleteRange(&HTMLEditorRef(),
rv = WSRunObject::PrepareToDeleteRange(MOZ_KnownLive(&HTMLEditorRef()),
address_of(startNode), &startOffset,
address_of(endNode), &endOffset);
if (NS_WARN_IF(!CanHandleEditAction())) {
@ -3535,8 +3537,8 @@ EditActionResult HTMLEditRules::TryToJoinBlocksWithTransaction(
// if you backspace from li into p.
// Adjust whitespace at block boundaries
nsresult rv =
WSRunObject::PrepareToJoinBlocks(&HTMLEditorRef(), leftBlock, rightBlock);
nsresult rv = WSRunObject::PrepareToJoinBlocks(
MOZ_KnownLive(&HTMLEditorRef()), leftBlock, rightBlock);
if (NS_WARN_IF(!CanHandleEditAction())) {
return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
}
@ -7678,7 +7680,7 @@ nsresult HTMLEditRules::ReturnInHeader(Element& aHeader, nsINode& aNode,
// Get ws code to adjust any ws
nsCOMPtr<nsINode> node = &aNode;
nsresult rv = WSRunObject::PrepareToSplitAcrossBlocks(
&HTMLEditorRef(), address_of(node), &aOffset);
MOZ_KnownLive(&HTMLEditorRef()), address_of(node), &aOffset);
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
@ -8000,7 +8002,7 @@ nsresult HTMLEditRules::SplitParagraph(
nsCOMPtr<nsINode> selNode = aStartOfRightNode.GetContainer();
int32_t selOffset = aStartOfRightNode.Offset();
nsresult rv = WSRunObject::PrepareToSplitAcrossBlocks(
&HTMLEditorRef(), address_of(selNode), &selOffset);
MOZ_KnownLive(&HTMLEditorRef()), address_of(selNode), &selOffset);
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
@ -8196,7 +8198,7 @@ nsresult HTMLEditRules::ReturnInListItem(Element& aListItem, nsINode& aNode,
// adjust any ws.
nsCOMPtr<nsINode> selNode = &aNode;
nsresult rv = WSRunObject::PrepareToSplitAcrossBlocks(
&HTMLEditorRef(), address_of(selNode), &aOffset);
MOZ_KnownLive(&HTMLEditorRef()), address_of(selNode), &aOffset);
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}

Просмотреть файл

@ -658,6 +658,7 @@ class HTMLEditRules : public TextEditRules {
* @param aOffset Typically, Selection start offset in the
* start container, where to be split.
*/
MOZ_CAN_RUN_SCRIPT
MOZ_MUST_USE nsresult ReturnInHeader(Element& aHeader, nsINode& aNode,
int32_t aOffset);
@ -672,6 +673,7 @@ class HTMLEditRules : public TextEditRules {
* unexpected situation. If this method tries to
* split the paragraph, marked as handled.
*/
MOZ_CAN_RUN_SCRIPT
MOZ_MUST_USE EditActionResult ReturnInParagraph(Element& aParentDivOrP);
/**
@ -687,7 +689,7 @@ class HTMLEditRules : public TextEditRules {
* removed.
*/
template <typename PT, typename CT>
MOZ_MUST_USE nsresult SplitParagraph(
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult SplitParagraph(
Element& aParentDivOrP,
const EditorDOMPointBase<PT, CT>& aStartOfRightNode, nsIContent* aBRNode);

Просмотреть файл

@ -289,8 +289,9 @@ nsresult WSRunObject::InsertText(Document& aDocument,
} else if (afterRun->mType == WSType::normalWS) {
// Try to change an nbsp to a space, if possible, just to prevent nbsp
// proliferation
nsresult rv = CheckLeadingNBSP(afterRun, pointToInsert.GetContainer(),
pointToInsert.Offset());
nsresult rv = CheckLeadingNBSP(
afterRun, MOZ_KnownLive(pointToInsert.GetContainer()),
pointToInsert.Offset());
NS_ENSURE_SUCCESS(rv, rv);
}
@ -413,8 +414,8 @@ nsresult WSRunObject::DeleteWSBackward() {
nsCOMPtr<nsINode> startNode = startNodeText.get();
nsCOMPtr<nsINode> endNode = endNodeText.get();
nsresult rv = WSRunObject::PrepareToDeleteRange(
mHTMLEditor, address_of(startNode), &startOffset, address_of(endNode),
&endOffset);
MOZ_KnownLive(mHTMLEditor), address_of(startNode), &startOffset,
address_of(endNode), &endOffset);
NS_ENSURE_SUCCESS(rv, rv);
// finally, delete that ws
@ -432,8 +433,8 @@ nsresult WSRunObject::DeleteWSBackward() {
int32_t startOffset = point.mOffset;
int32_t endOffset = point.mOffset + 1;
nsresult rv = WSRunObject::PrepareToDeleteRange(
mHTMLEditor, address_of(node), &startOffset, address_of(node),
&endOffset);
MOZ_KnownLive(mHTMLEditor), address_of(node), &startOffset,
address_of(node), &endOffset);
NS_ENSURE_SUCCESS(rv, rv);
// finally, delete that ws
@ -476,8 +477,8 @@ nsresult WSRunObject::DeleteWSForward() {
// Adjust surrounding ws
nsCOMPtr<nsINode> startNode(startNodeText), endNode(endNodeText);
nsresult rv = WSRunObject::PrepareToDeleteRange(
mHTMLEditor, address_of(startNode), &startOffset, address_of(endNode),
&endOffset);
MOZ_KnownLive(mHTMLEditor), address_of(startNode), &startOffset,
address_of(endNode), &endOffset);
NS_ENSURE_SUCCESS(rv, rv);
// Finally, delete that ws
@ -495,8 +496,8 @@ nsresult WSRunObject::DeleteWSForward() {
int32_t startOffset = point.mOffset;
int32_t endOffset = point.mOffset + 1;
nsresult rv = WSRunObject::PrepareToDeleteRange(
mHTMLEditor, address_of(node), &startOffset, address_of(node),
&endOffset);
MOZ_KnownLive(mHTMLEditor), address_of(node), &startOffset,
address_of(node), &endOffset);
NS_ENSURE_SUCCESS(rv, rv);
// Finally, delete that ws
@ -1501,7 +1502,8 @@ nsresult WSRunObject::InsertNBSPAndRemoveFollowingASCIIWhitespaces(
// First, insert an NBSP.
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
nsresult rv = htmlEditor->InsertTextIntoTextNodeWithTransaction(
nsDependentSubstring(&kNBSP, 1), *aPoint.mTextNode, aPoint.mOffset, true);
nsDependentSubstring(&kNBSP, 1), MOZ_KnownLive(*aPoint.mTextNode),
aPoint.mOffset, true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -1833,7 +1835,7 @@ nsresult WSRunObject::CheckTrailingNBSPOfRun(WSFragment* aRun) {
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
nsAutoString spaceStr(char16_t(32));
nsresult rv = htmlEditor->InsertTextIntoTextNodeWithTransaction(
spaceStr, *thePoint.mTextNode, thePoint.mOffset, true);
spaceStr, MOZ_KnownLive(*thePoint.mTextNode), thePoint.mOffset, true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -1926,7 +1928,7 @@ nsresult WSRunObject::ReplacePreviousNBSPIfUnncessary(
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
nsAutoString spaceStr(char16_t(32));
nsresult rv = htmlEditor->InsertTextIntoTextNodeWithTransaction(
spaceStr, *thePoint.mTextNode, thePoint.mOffset, true);
spaceStr, MOZ_KnownLive(*thePoint.mTextNode), thePoint.mOffset, true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -1973,7 +1975,7 @@ nsresult WSRunObject::CheckLeadingNBSP(WSFragment* aRun, nsINode* aNode,
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
nsAutoString spaceStr(char16_t(32));
nsresult rv = htmlEditor->InsertTextIntoTextNodeWithTransaction(
spaceStr, *thePoint.mTextNode, thePoint.mOffset, true);
spaceStr, MOZ_KnownLive(*thePoint.mTextNode), thePoint.mOffset, true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

Просмотреть файл

@ -184,6 +184,7 @@ class MOZ_STACK_CLASS WSRunObject final {
// PrepareToJoinBlocks fixes up ws at the end of aLeftBlock and the
// beginning of aRightBlock in preperation for them to be joined. Example
// of fixup: trailingws in aLeftBlock needs to be removed.
MOZ_CAN_RUN_SCRIPT
static nsresult PrepareToJoinBlocks(HTMLEditor* aHTMLEditor,
dom::Element* aLeftBlock,
dom::Element* aRightBlock);
@ -195,6 +196,7 @@ class MOZ_STACK_CLASS WSRunObject final {
// adjusting ws.
// example of fixup: trailingws before {aStartNode,aStartOffset}
// needs to be removed.
MOZ_CAN_RUN_SCRIPT
static nsresult PrepareToDeleteRange(HTMLEditor* aHTMLEditor,
nsCOMPtr<nsINode>* aStartNode,
int32_t* aStartOffset,
@ -204,6 +206,7 @@ class MOZ_STACK_CLASS WSRunObject final {
// PrepareToDeleteNode fixes up ws before and after aContent in preparation
// for aContent to be deleted. Example of fixup: trailingws before
// aContent needs to be removed.
MOZ_CAN_RUN_SCRIPT
static nsresult PrepareToDeleteNode(HTMLEditor* aHTMLEditor,
nsIContent* aContent);
@ -212,6 +215,7 @@ class MOZ_STACK_CLASS WSRunObject final {
// Note that the aSplitNode and aSplitOffset are adjusted in response to
// any DOM changes we make while adjusting ws. Example of fixup: normalws
// before {aSplitNode,aSplitOffset} needs to end with nbsp.
MOZ_CAN_RUN_SCRIPT
static nsresult PrepareToSplitAcrossBlocks(HTMLEditor* aHTMLEditor,
nsCOMPtr<nsINode>* aSplitNode,
int32_t* aSplitOffset);
@ -236,7 +240,7 @@ class MOZ_STACK_CLASS WSRunObject final {
* node, returns nullptr.
*/
template <typename PT, typename CT>
already_AddRefed<dom::Element> InsertBreak(
MOZ_CAN_RUN_SCRIPT already_AddRefed<dom::Element> InsertBreak(
Selection& aSelection, const EditorDOMPointBase<PT, CT>& aPointToInsert,
nsIEditor::EDirection aSelect);
@ -267,12 +271,12 @@ class MOZ_STACK_CLASS WSRunObject final {
// point (the point to create the wsRunObject, passed to its constructor).
// It makes any needed conversion to adjacent ws to retain its
// significance.
nsresult DeleteWSBackward();
MOZ_CAN_RUN_SCRIPT nsresult DeleteWSBackward();
// DeleteWSForward deletes a single visible piece of ws after the ws point
// (the point to create the wsRunObject, passed to its constructor). It
// makes any needed conversion to adjacent ws to retain its significance.
nsresult DeleteWSForward();
MOZ_CAN_RUN_SCRIPT nsresult DeleteWSForward();
// PriorVisibleNode() returns the first piece of visible thing before aPoint.
// If there is no visible ws qualifying it returns what is before the ws run.
@ -310,7 +314,7 @@ class MOZ_STACK_CLASS WSRunObject final {
// AdjustWhitespace examines the ws object for nbsp's that can
// be safely converted to regular ascii space and converts them.
nsresult AdjustWhitespace();
MOZ_CAN_RUN_SCRIPT nsresult AdjustWhitespace();
protected:
// WSFragment represents a single run of ws (all leadingws, or all normalws,
@ -370,8 +374,8 @@ class MOZ_STACK_CLASS WSRunObject final {
nsIContent* GetNextWSNodeInner(nsINode* aStartNode, nsINode* aBlockParent);
nsIContent* GetNextWSNode(const EditorDOMPoint& aPoint,
nsINode* aBlockParent);
nsresult PrepareToDeleteRangePriv(WSRunObject* aEndObject);
nsresult PrepareToSplitAcrossBlocksPriv();
MOZ_CAN_RUN_SCRIPT nsresult PrepareToDeleteRangePriv(WSRunObject* aEndObject);
MOZ_CAN_RUN_SCRIPT nsresult PrepareToSplitAcrossBlocksPriv();
/**
* DeleteRange() removes the range between aStartPoint and aEndPoint.
@ -422,6 +426,7 @@ class MOZ_STACK_CLASS WSRunObject final {
* InsertNBSPAndRemoveFollowingASCIIWhitespaces() inserts an NBSP first.
* Then, if following characters are ASCII whitespaces, will remove them.
*/
MOZ_CAN_RUN_SCRIPT
nsresult InsertNBSPAndRemoveFollowingASCIIWhitespaces(WSPoint aPoint);
/**
@ -475,7 +480,7 @@ class MOZ_STACK_CLASS WSRunObject final {
bool aForward) const;
char16_t GetCharAt(dom::Text* aTextNode, int32_t aOffset) const;
nsresult CheckTrailingNBSPOfRun(WSFragment* aRun);
MOZ_CAN_RUN_SCRIPT nsresult CheckTrailingNBSPOfRun(WSFragment* aRun);
/**
* ReplacePreviousNBSPIfUnncessary() replaces previous character of aPoint
@ -486,9 +491,10 @@ class MOZ_STACK_CLASS WSRunObject final {
* unnecessary NBSP will be checked.
*/
template <typename PT, typename CT>
nsresult ReplacePreviousNBSPIfUnncessary(
MOZ_CAN_RUN_SCRIPT nsresult ReplacePreviousNBSPIfUnncessary(
WSFragment* aRun, const EditorDOMPointBase<PT, CT>& aPoint);
MOZ_CAN_RUN_SCRIPT
nsresult CheckLeadingNBSP(WSFragment* aRun, nsINode* aNode, int32_t aOffset);
nsresult Scrub();

Просмотреть файл

@ -104,6 +104,7 @@ void CompositorVsyncScheduler::Destroy() {
mCompositeRequestedAt = TimeStamp();
CancelCurrentCompositeTask();
CancelCurrentVRTask();
}
void CompositorVsyncScheduler::PostCompositeTask(
@ -122,7 +123,7 @@ void CompositorVsyncScheduler::PostCompositeTask(
void CompositorVsyncScheduler::PostVRTask(TimeStamp aTimestamp) {
MonitorAutoLock lockVR(mCurrentVRTaskMonitor);
if (mCurrentVRTask == nullptr && CompositorThreadHolder::Loop()) {
RefPtr<Runnable> task = NewRunnableMethod<TimeStamp>(
RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<TimeStamp>(
"layers::CompositorVsyncScheduler::DispatchVREvents", this,
&CompositorVsyncScheduler::DispatchVREvents, aTimestamp);
mCurrentVRTask = task;
@ -190,6 +191,16 @@ bool CompositorVsyncScheduler::NotifyVsync(const VsyncEvent& aVsync) {
return true;
}
void CompositorVsyncScheduler::CancelCurrentVRTask() {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread() ||
NS_IsMainThread());
MonitorAutoLock lock(mCurrentVRTaskMonitor);
if (mCurrentVRTask) {
mCurrentVRTask->Cancel();
mCurrentVRTask = nullptr;
}
}
void CompositorVsyncScheduler::CancelCurrentCompositeTask() {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread() ||
NS_IsMainThread());

Просмотреть файл

@ -120,6 +120,11 @@ class CompositorVsyncScheduler {
// such a task already queued. Can be called from any thread.
void PostVRTask(TimeStamp aTimestamp);
/**
* Cancel any VR task that has been scheduled but hasn't run yet.
*/
void CancelCurrentVRTask();
// This gets run at vsync time and "does" a composite (which really means
// update internal state and call the owner to do the composite).
void Composite(VsyncId aId, TimeStamp aVsyncTimestamp);
@ -159,7 +164,7 @@ class CompositorVsyncScheduler {
RefPtr<CancelableRunnable> mCurrentCompositeTask;
mozilla::Monitor mCurrentVRTaskMonitor;
RefPtr<Runnable> mCurrentVRTask;
RefPtr<CancelableRunnable> mCurrentVRTask;
};
} // namespace layers

Просмотреть файл

@ -1043,8 +1043,9 @@ impl AlphaBatchBuilder {
.expect("BUG: 3d primitive was not assigned a surface");
let (uv_rect_address, _) = render_tasks.resolve_surface(
ctx.surfaces[raster_config.surface_index.0]
.surface
.expect("BUG: no surface"),
.render_tasks
.expect("BUG: no surface")
.root,
gpu_cache,
);
@ -1097,7 +1098,10 @@ impl AlphaBatchBuilder {
render_tasks,
).unwrap_or(OPAQUE_TASK_ADDRESS);
let surface = ctx.surfaces[raster_config.surface_index.0].surface;
let surface = ctx
.surfaces[raster_config.surface_index.0]
.render_tasks
.map(|s| s.root);
match raster_config.composite_mode {
PictureCompositeMode::TileCache { .. } => {

Просмотреть файл

@ -903,6 +903,9 @@ pub struct Capabilities {
/// is available on some mobile GPUs. This allows fast access to
/// the per-pixel tile memory.
pub supports_pixel_local_storage: bool,
/// Whether KHR_debug is supported for getting debug messages from
/// the driver.
pub supports_khr_debug: bool,
}
#[derive(Clone, Debug)]
@ -1134,16 +1137,6 @@ impl Device {
cached_programs: Option<Rc<ProgramCache>>,
allow_pixel_local_storage_support: bool,
) -> Device {
// On debug builds, assert that each GL call is error-free. We don't do
// this on release builds because the synchronous call can stall the
// pipeline.
if cfg!(debug_assertions) {
gl = gl::ErrorReactingGl::wrap(gl, |gl, name, code| {
Self::echo_driver_messages(gl);
panic!("Caught GL error {:x} at {}", code, name);
});
}
let mut max_texture_size = [0];
let mut max_texture_layers = [0];
unsafe {
@ -1165,6 +1158,19 @@ impl Device {
extensions.push(gl.get_string_i(gl::EXTENSIONS, i));
}
// On debug builds, assert that each GL call is error-free. We don't do
// this on release builds because the synchronous call can stall the
// pipeline.
let supports_khr_debug = supports_extension(&extensions, "GL_KHR_debug");
if cfg!(debug_assertions) {
gl = gl::ErrorReactingGl::wrap(gl, move |gl, name, code| {
if supports_khr_debug {
Self::log_driver_messages(gl);
}
panic!("Caught GL error {:x} at {}", code, name);
});
}
// Our common-case image data in Firefox is BGRA, so we make an effort
// to use BGRA as the internal texture storage format to avoid the need
// to swizzle during upload. Currently we only do this on GLES (and thus
@ -1285,6 +1291,7 @@ impl Device {
supports_copy_image_sub_data,
supports_blit_to_texture_array,
supports_pixel_local_storage,
supports_khr_debug,
},
bgra_format_internal,
@ -3093,7 +3100,13 @@ impl Device {
}
}
pub fn echo_driver_messages(gl: &gl::Gl) {
pub fn echo_driver_messages(&self) {
if self.capabilities.supports_khr_debug {
Device::log_driver_messages(self.gl());
}
}
fn log_driver_messages(gl: &gl::Gl) {
for msg in gl.get_debug_messages() {
let level = match msg.severity {
gl::DEBUG_SEVERITY_HIGH => Level::Error,

Просмотреть файл

@ -15,7 +15,7 @@ use crate::hit_test::{HitTester, HitTestingScene};
use crate::hit_test::HitTestingSceneStats;
use crate::internal_types::{FastHashMap, PlaneSplitter};
use crate::picture::{PictureUpdateState, SurfaceInfo, ROOT_SURFACE_INDEX, SurfaceIndex};
use crate::picture::{RetainedTiles, TileCache, DirtyRegion};
use crate::picture::{RetainedTiles, TileCache, DirtyRegion, SurfaceRenderTasks};
use crate::prim_store::{PrimitiveStore, SpaceMapper, PictureIndex, PrimitiveDebugId, PrimitiveScratchBuffer};
#[cfg(feature = "replay")]
use crate::prim_store::{PrimitiveStoreStats};
@ -29,6 +29,7 @@ use crate::segment::SegmentBuilder;
use std::{f32, mem};
use std::sync::Arc;
use crate::tiling::{Frame, RenderPassKind, RenderTargetContext, RenderTarget};
use crate::util::MaxRect;
#[derive(Clone, Copy, Debug, PartialEq)]
@ -444,7 +445,10 @@ impl FrameBuilder {
.surfaces
.first_mut()
.unwrap()
.surface = Some(root_render_task_id);
.render_tasks = Some(SurfaceRenderTasks {
root: root_render_task_id,
port: root_render_task_id,
});
// Push a default dirty region which culls primitives
// against the screen world rect, in absence of any
@ -460,6 +464,7 @@ impl FrameBuilder {
.pictures[self.root_pic_index.0]
.take_context(
self.root_pic_index,
WorldRect::max_rect(),
root_spatial_node_index,
root_spatial_node_index,
ROOT_SURFACE_INDEX,
@ -492,17 +497,6 @@ impl FrameBuilder {
frame_state.pop_dirty_region();
let child_tasks = frame_state
.surfaces[ROOT_SURFACE_INDEX.0]
.take_render_tasks();
for child_task_id in child_tasks {
frame_state.render_tasks.add_dependency(
root_render_task_id,
child_task_id,
);
}
Some(root_render_task_id)
}

Просмотреть файл

@ -1780,6 +1780,17 @@ pub struct SurfaceIndex(pub usize);
pub const ROOT_SURFACE_INDEX: SurfaceIndex = SurfaceIndex(0);
#[derive(Debug, Copy, Clone)]
pub struct SurfaceRenderTasks {
/// The root of the render task chain for this surface. This
/// is attached to parent tasks, and also the surface that
/// gets added during batching.
pub root: RenderTaskId,
/// The port of the render task change for this surface. This
/// is where child tasks for this surface get attached to.
pub port: RenderTaskId,
}
/// Information about an offscreen surface. For now,
/// it contains information about the size and coordinate
/// system of the surface. In the future, it will contain
@ -1799,9 +1810,7 @@ pub struct SurfaceInfo {
pub raster_spatial_node_index: SpatialNodeIndex,
pub surface_spatial_node_index: SpatialNodeIndex,
/// This is set when the render task is created.
pub surface: Option<RenderTaskId>,
/// A list of render tasks that are dependencies of this surface.
pub tasks: Vec<RenderTaskId>,
pub render_tasks: Option<SurfaceRenderTasks>,
/// How much the local surface rect should be inflated (for blur radii).
pub inflation_factor: f32,
/// The device pixel ratio specific to this surface.
@ -1839,21 +1848,14 @@ impl SurfaceInfo {
SurfaceInfo {
rect: PictureRect::zero(),
map_local_to_surface,
surface: None,
render_tasks: None,
raster_spatial_node_index,
surface_spatial_node_index,
tasks: Vec::new(),
inflation_factor,
device_pixel_scale,
allow_subpixel_aa,
}
}
/// Take the set of child render tasks for this surface. This is
/// used when constructing the render task tree.
pub fn take_render_tasks(&mut self) -> Vec<RenderTaskId> {
mem::replace(&mut self.tasks, Vec::new())
}
}
#[derive(Debug)]
@ -2152,7 +2154,7 @@ pub struct PicturePrimitive {
pub prim_list: PrimitiveList,
#[cfg_attr(feature = "capture", serde(skip))]
pub state: Option<(PictureState, PictureContext)>,
pub state: Option<PictureState>,
/// The pipeline that the primitives on this picture belong to.
pub pipeline_id: PipelineId,
@ -2350,9 +2352,10 @@ impl PicturePrimitive {
pub fn take_context(
&mut self,
pic_index: PictureIndex,
clipped_prim_bounding_rect: WorldRect,
surface_spatial_node_index: SpatialNodeIndex,
raster_spatial_node_index: SpatialNodeIndex,
surface_index: SurfaceIndex,
parent_surface_index: SurfaceIndex,
frame_state: &mut FrameBuildingState,
frame_context: &FrameBuildingContext,
) -> Option<(PictureContext, PictureState, PrimitiveList)> {
@ -2378,7 +2381,7 @@ impl PicturePrimitive {
(
raster_spatial_node_index,
surface_spatial_node_index,
surface_index,
parent_surface_index,
0.0,
)
}
@ -2418,6 +2421,304 @@ impl PicturePrimitive {
}
};
let (is_composite, is_passthrough) = match self.raster_config {
Some(ref rc @ RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, .. }) => {
// For a picture surface, just push any child tasks and tile
// blits up to the parent surface.
let port = frame_state
.surfaces[parent_surface_index.0]
.render_tasks
.expect("bug: no render tasks set for parent!")
.port;
frame_state
.surfaces[rc.surface_index.0]
.render_tasks = Some(SurfaceRenderTasks {
root: RenderTaskId::INVALID,
port,
});
(false, false)
},
Some(ref raster_config) => {
let pic_rect = PictureRect::from_untyped(&self.snapped_local_rect.to_untyped());
let device_pixel_scale = frame_state
.surfaces[raster_config.surface_index.0]
.device_pixel_scale;
let (clipped, unclipped) = match get_raster_rects(
pic_rect,
&map_pic_to_raster,
&map_raster_to_world,
clipped_prim_bounding_rect,
device_pixel_scale,
) {
Some(info) => info,
None => {
return None
}
};
let transform = map_pic_to_raster.get_transform();
let (root, port) = match raster_config.composite_mode {
PictureCompositeMode::TileCache { .. } => {
unreachable!();
}
PictureCompositeMode::Filter(FilterOp::Blur(blur_radius)) => {
let blur_std_deviation = blur_radius * device_pixel_scale.0;
let scale_factors = scale_factors(&transform);
let blur_std_deviation = DeviceSize::new(
blur_std_deviation * scale_factors.0,
blur_std_deviation * scale_factors.1
);
let inflation_factor = frame_state.surfaces[raster_config.surface_index.0].inflation_factor;
let inflation_factor = (inflation_factor * device_pixel_scale.0).ceil() as i32;
// The clipped field is the part of the picture that is visible
// on screen. The unclipped field is the screen-space rect of
// the complete picture, if no screen / clip-chain was applied
// (this includes the extra space for blur region). To ensure
// that we draw a large enough part of the picture to get correct
// blur results, inflate that clipped area by the blur range, and
// then intersect with the total screen rect, to minimize the
// allocation size.
let mut device_rect = clipped
.inflate(inflation_factor, inflation_factor)
.intersection(&unclipped.to_i32())
.unwrap();
// Adjust the size to avoid introducing sampling errors during the down-scaling passes.
// what would be even better is to rasterize the picture at the down-scaled size
// directly.
device_rect.size = RenderTask::adjusted_blur_source_size(
device_rect.size,
blur_std_deviation,
);
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&device_rect,
device_pixel_scale,
true,
);
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, device_rect.size),
unclipped.size,
pic_index,
device_rect.origin,
Vec::new(),
uv_rect_kind,
raster_spatial_node_index,
device_pixel_scale,
);
let picture_task_id = frame_state.render_tasks.add(picture_task);
let blur_render_task = RenderTask::new_blur(
blur_std_deviation,
picture_task_id,
frame_state.render_tasks,
RenderTargetKind::Color,
ClearMode::Transparent,
);
let render_task_id = frame_state.render_tasks.add(blur_render_task);
(render_task_id, picture_task_id)
}
PictureCompositeMode::Filter(FilterOp::DropShadow(_, blur_radius, _)) => {
let blur_std_deviation = blur_radius * device_pixel_scale.0;
let blur_range = (blur_std_deviation * BLUR_SAMPLE_SCALE).ceil() as i32;
let rounded_std_dev = blur_std_deviation.round();
let rounded_std_dev = DeviceSize::new(rounded_std_dev, rounded_std_dev);
// The clipped field is the part of the picture that is visible
// on screen. The unclipped field is the screen-space rect of
// the complete picture, if no screen / clip-chain was applied
// (this includes the extra space for blur region). To ensure
// that we draw a large enough part of the picture to get correct
// blur results, inflate that clipped area by the blur range, and
// then intersect with the total screen rect, to minimize the
// allocation size.
let mut device_rect = clipped.inflate(blur_range, blur_range)
.intersection(&unclipped.to_i32())
.unwrap();
device_rect.size = RenderTask::adjusted_blur_source_size(
device_rect.size,
rounded_std_dev,
);
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&device_rect,
device_pixel_scale,
true,
);
let mut picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, device_rect.size),
unclipped.size,
pic_index,
device_rect.origin,
Vec::new(),
uv_rect_kind,
raster_spatial_node_index,
device_pixel_scale,
);
picture_task.mark_for_saving();
let picture_task_id = frame_state.render_tasks.add(picture_task);
let blur_render_task = RenderTask::new_blur(
rounded_std_dev,
picture_task_id,
frame_state.render_tasks,
RenderTargetKind::Color,
ClearMode::Transparent,
);
self.secondary_render_task_id = Some(picture_task_id);
let render_task_id = frame_state.render_tasks.add(blur_render_task);
(render_task_id, picture_task_id)
}
PictureCompositeMode::MixBlend(..) if !frame_context.fb_config.gpu_supports_advanced_blend => {
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&clipped,
device_pixel_scale,
true,
);
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, clipped.size),
unclipped.size,
pic_index,
clipped.origin,
Vec::new(),
uv_rect_kind,
raster_spatial_node_index,
device_pixel_scale,
);
let readback_task_id = frame_state.render_tasks.add(
RenderTask::new_readback(clipped)
);
frame_state.render_tasks.add_dependency(
frame_state.surfaces[parent_surface_index.0].render_tasks.unwrap().port,
readback_task_id,
);
self.secondary_render_task_id = Some(readback_task_id);
let render_task_id = frame_state.render_tasks.add(picture_task);
(render_task_id, render_task_id)
}
PictureCompositeMode::Filter(..) => {
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&clipped,
device_pixel_scale,
true,
);
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, clipped.size),
unclipped.size,
pic_index,
clipped.origin,
Vec::new(),
uv_rect_kind,
raster_spatial_node_index,
device_pixel_scale,
);
let render_task_id = frame_state.render_tasks.add(picture_task);
(render_task_id, render_task_id)
}
PictureCompositeMode::ComponentTransferFilter(..) => {
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&clipped,
device_pixel_scale,
true,
);
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, clipped.size),
unclipped.size,
pic_index,
clipped.origin,
Vec::new(),
uv_rect_kind,
raster_spatial_node_index,
device_pixel_scale,
);
let render_task_id = frame_state.render_tasks.add(picture_task);
(render_task_id, render_task_id)
}
PictureCompositeMode::MixBlend(..) |
PictureCompositeMode::Blit(_) => {
// The SplitComposite shader used for 3d contexts doesn't snap
// to pixels, so we shouldn't snap our uv coordinates either.
let supports_snapping = match self.context_3d {
Picture3DContext::In{ .. } => false,
_ => true,
};
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&clipped,
device_pixel_scale,
supports_snapping,
);
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, clipped.size),
unclipped.size,
pic_index,
clipped.origin,
Vec::new(),
uv_rect_kind,
raster_spatial_node_index,
device_pixel_scale,
);
let render_task_id = frame_state.render_tasks.add(picture_task);
(render_task_id, render_task_id)
}
};
frame_state.surfaces[raster_config.surface_index.0].render_tasks = Some(SurfaceRenderTasks {
root,
port,
});
frame_state.render_tasks.add_dependency(
frame_state.surfaces[parent_surface_index.0].render_tasks.unwrap().port,
root,
);
(true, false)
}
None => {
(false, true)
}
};
let state = PictureState {
//TODO: check for MAX_CACHE_SIZE here?
map_local_to_pic,
@ -2427,18 +2728,6 @@ impl PicturePrimitive {
plane_splitter,
};
let (is_composite, is_passthrough) = match self.raster_config {
Some(RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, .. }) => {
(false, false)
},
Some(_) => {
(true, false)
}
None => {
(false, true)
}
};
let mut dirty_region_count = 0;
// If this is a picture cache, push the dirty region to ensure any
@ -2488,10 +2777,10 @@ impl PicturePrimitive {
}
self.prim_list = prim_list;
self.state = Some((state, context));
self.state = Some(state);
}
pub fn take_state_and_context(&mut self) -> (PictureState, PictureContext) {
pub fn take_state(&mut self) -> PictureState {
self.state.take().expect("bug: no state present!")
}
@ -2876,14 +3165,11 @@ impl PicturePrimitive {
pub fn prepare_for_render(
&mut self,
pic_index: PictureIndex,
clipped_prim_bounding_rect: WorldRect,
surface_index: SurfaceIndex,
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
data_stores: &mut DataStores,
) -> bool {
let (mut pic_state_for_children, pic_context) = self.take_state_and_context();
let mut pic_state_for_children = self.take_state();
if let Some(ref mut splitter) = pic_state_for_children.plane_splitter {
self.resolve_split_planes(splitter, frame_state);
@ -2896,36 +3182,6 @@ impl PicturePrimitive {
}
};
let (raster_spatial_node_index, child_tasks, device_pixel_scale) = {
let surface_info = &mut frame_state.surfaces[raster_config.surface_index.0];
(
surface_info.raster_spatial_node_index,
surface_info.take_render_tasks(),
surface_info.device_pixel_scale,
)
};
let (map_raster_to_world, map_pic_to_raster) = create_raster_mappers(
self.spatial_node_index,
raster_spatial_node_index,
frame_context.screen_world_rect,
frame_context.clip_scroll_tree,
);
let pic_rect = PictureRect::from_untyped(&self.snapped_local_rect.to_untyped());
let (clipped, unclipped) = match get_raster_rects(
pic_rect,
&map_pic_to_raster,
&map_raster_to_world,
clipped_prim_bounding_rect,
device_pixel_scale,
) {
Some(info) => info,
None => return false,
};
let transform = map_pic_to_raster.get_transform();
// TODO(gw): Almost all of the Picture types below use extra_gpu_cache_data
// to store the same type of data. The exception is the filter
// with a ColorMatrix, which stores the color matrix here. It's
@ -2933,136 +3189,10 @@ impl PicturePrimitive {
// Perhaps store the color matrix after the common data, even though
// it's not used by that shader.
let surface = match raster_config.composite_mode {
PictureCompositeMode::TileCache { .. } => {
// For a picture surface, just push any child tasks and tile
// blits up to the parent surface.
let surface = &mut frame_state.surfaces[surface_index.0];
surface.tasks.extend(child_tasks);
return true;
}
PictureCompositeMode::Filter(FilterOp::Blur(blur_radius)) => {
let blur_std_deviation = blur_radius * device_pixel_scale.0;
let scale_factors = scale_factors(&transform);
let blur_std_deviation = DeviceSize::new(
blur_std_deviation * scale_factors.0,
blur_std_deviation * scale_factors.1
);
let inflation_factor = frame_state.surfaces[raster_config.surface_index.0].inflation_factor;
let inflation_factor = (inflation_factor * device_pixel_scale.0).ceil() as i32;
// The clipped field is the part of the picture that is visible
// on screen. The unclipped field is the screen-space rect of
// the complete picture, if no screen / clip-chain was applied
// (this includes the extra space for blur region). To ensure
// that we draw a large enough part of the picture to get correct
// blur results, inflate that clipped area by the blur range, and
// then intersect with the total screen rect, to minimize the
// allocation size.
let mut device_rect = clipped
.inflate(inflation_factor, inflation_factor)
.intersection(&unclipped.to_i32())
.unwrap();
// Adjust the size to avoid introducing sampling errors during the down-scaling passes.
// what would be even better is to rasterize the picture at the down-scaled size
// directly.
device_rect.size = RenderTask::adjusted_blur_source_size(
device_rect.size,
blur_std_deviation,
);
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&device_rect,
device_pixel_scale,
true,
);
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, device_rect.size),
unclipped.size,
pic_index,
device_rect.origin,
child_tasks,
uv_rect_kind,
pic_context.raster_spatial_node_index,
device_pixel_scale,
);
let picture_task_id = frame_state.render_tasks.add(picture_task);
let blur_render_task = RenderTask::new_blur(
blur_std_deviation,
picture_task_id,
frame_state.render_tasks,
RenderTargetKind::Color,
ClearMode::Transparent,
);
let render_task_id = frame_state.render_tasks.add(blur_render_task);
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
render_task_id
}
PictureCompositeMode::Filter(FilterOp::DropShadow(offset, blur_radius, color)) => {
let blur_std_deviation = blur_radius * device_pixel_scale.0;
let blur_range = (blur_std_deviation * BLUR_SAMPLE_SCALE).ceil() as i32;
let rounded_std_dev = blur_std_deviation.round();
let rounded_std_dev = DeviceSize::new(rounded_std_dev, rounded_std_dev);
// The clipped field is the part of the picture that is visible
// on screen. The unclipped field is the screen-space rect of
// the complete picture, if no screen / clip-chain was applied
// (this includes the extra space for blur region). To ensure
// that we draw a large enough part of the picture to get correct
// blur results, inflate that clipped area by the blur range, and
// then intersect with the total screen rect, to minimize the
// allocation size.
let mut device_rect = clipped.inflate(blur_range, blur_range)
.intersection(&unclipped.to_i32())
.unwrap();
device_rect.size = RenderTask::adjusted_blur_source_size(
device_rect.size,
rounded_std_dev,
);
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&device_rect,
device_pixel_scale,
true,
);
let mut picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, device_rect.size),
unclipped.size,
pic_index,
device_rect.origin,
child_tasks,
uv_rect_kind,
pic_context.raster_spatial_node_index,
device_pixel_scale,
);
picture_task.mark_for_saving();
let picture_task_id = frame_state.render_tasks.add(picture_task);
let blur_render_task = RenderTask::new_blur(
rounded_std_dev,
picture_task_id,
frame_state.render_tasks,
RenderTargetKind::Color,
ClearMode::Transparent,
);
self.secondary_render_task_id = Some(picture_task_id);
let render_task_id = frame_state.render_tasks.add(blur_render_task);
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
match raster_config.composite_mode {
PictureCompositeMode::TileCache { .. } => {}
PictureCompositeMode::Filter(FilterOp::Blur(..)) => {}
PictureCompositeMode::Filter(FilterOp::DropShadow(offset, _, color)) => {
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
// TODO(gw): This is very hacky code below! It stores an extra
// brush primitive below for the special case of a
@ -3090,40 +3220,8 @@ impl PicturePrimitive {
request.push(shadow_rect);
request.push([0.0, 0.0, 0.0, 0.0]);
}
render_task_id
}
PictureCompositeMode::MixBlend(..) if !frame_context.fb_config.gpu_supports_advanced_blend => {
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&clipped,
device_pixel_scale,
true,
);
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, clipped.size),
unclipped.size,
pic_index,
clipped.origin,
child_tasks,
uv_rect_kind,
pic_context.raster_spatial_node_index,
device_pixel_scale,
);
let readback_task_id = frame_state.render_tasks.add(
RenderTask::new_readback(clipped)
);
self.secondary_render_task_id = Some(readback_task_id);
frame_state.surfaces[surface_index.0].tasks.push(readback_task_id);
let render_task_id = frame_state.render_tasks.add(picture_task);
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
render_task_id
}
PictureCompositeMode::MixBlend(..) if !frame_context.fb_config.gpu_supports_advanced_blend => {}
PictureCompositeMode::Filter(ref filter) => {
if let FilterOp::ColorMatrix(m) = *filter {
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
@ -3132,92 +3230,14 @@ impl PicturePrimitive {
}
}
}
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&clipped,
device_pixel_scale,
true,
);
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, clipped.size),
unclipped.size,
pic_index,
clipped.origin,
child_tasks,
uv_rect_kind,
pic_context.raster_spatial_node_index,
device_pixel_scale,
);
let render_task_id = frame_state.render_tasks.add(picture_task);
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
render_task_id
}
PictureCompositeMode::ComponentTransferFilter(handle) => {
let filter_data = &mut data_stores.filter_data[handle];
filter_data.update(frame_state);
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&clipped,
device_pixel_scale,
true,
);
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, clipped.size),
unclipped.size,
pic_index,
clipped.origin,
child_tasks,
uv_rect_kind,
pic_context.raster_spatial_node_index,
device_pixel_scale,
);
let render_task_id = frame_state.render_tasks.add(picture_task);
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
render_task_id
}
PictureCompositeMode::MixBlend(..) |
PictureCompositeMode::Blit(_) => {
// The SplitComposite shader used for 3d contexts doesn't snap
// to pixels, so we shouldn't snap our uv coordinates either.
let supports_snapping = match self.context_3d {
Picture3DContext::In{ .. } => false,
_ => true,
};
let uv_rect_kind = calculate_uv_rect_kind(
&pic_rect,
&transform,
&clipped,
device_pixel_scale,
supports_snapping,
);
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, clipped.size),
unclipped.size,
pic_index,
clipped.origin,
child_tasks,
uv_rect_kind,
pic_context.raster_spatial_node_index,
device_pixel_scale,
);
let render_task_id = frame_state.render_tasks.add(picture_task);
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
render_task_id
}
};
frame_state.surfaces[raster_config.surface_index.0].surface = Some(surface);
PictureCompositeMode::Blit(_) => {}
}
true
}

Просмотреть файл

@ -988,7 +988,10 @@ impl BrushSegment {
);
let clip_task_id = frame_state.render_tasks.add(clip_task);
frame_state.surfaces[surface_index.0].tasks.push(clip_task_id);
frame_state.render_tasks.add_dependency(
frame_state.surfaces[surface_index.0].render_tasks.unwrap().port,
clip_task_id,
);
ClipMaskKind::Mask(clip_task_id)
}
None => {
@ -2470,8 +2473,13 @@ impl PrimitiveStore {
PrimitiveInstanceKind::Picture { pic_index ,.. } => {
let pic = &mut self.pictures[pic_index.0];
let clipped_prim_bounding_rect = scratch
.prim_info[prim_instance.visibility_info.0 as usize]
.clipped_world_rect;
match pic.take_context(
pic_index,
clipped_prim_bounding_rect,
pic_context.surface_spatial_node_index,
pic_context.raster_spatial_node_index,
pic_context.surface_index,
@ -2484,6 +2492,8 @@ impl PrimitiveStore {
println!("\tculled for carrying an invisible composite filter");
}
prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
return false;
}
}
@ -3071,9 +3081,6 @@ impl PrimitiveStore {
let pic = &mut self.pictures[pic_index.0];
let prim_info = &scratch.prim_info[prim_instance.visibility_info.0 as usize];
if pic.prepare_for_render(
*pic_index,
prim_info.clipped_world_rect,
pic_context.surface_index,
frame_context,
frame_state,
data_stores,
@ -3747,7 +3754,10 @@ impl PrimitiveInstance {
let clip_task_index = ClipTaskIndex(scratch.clip_mask_instances.len() as _);
scratch.clip_mask_instances.push(ClipMaskKind::Mask(clip_task_id));
prim_info.clip_task_index = clip_task_index;
frame_state.surfaces[pic_context.surface_index.0].tasks.push(clip_task_id);
frame_state.render_tasks.add_dependency(
frame_state.surfaces[pic_context.surface_index.0].render_tasks.unwrap().port,
clip_task_id,
);
}
}
}

Просмотреть файл

@ -3168,7 +3168,7 @@ impl Renderer {
}
if self.debug_flags.contains(DebugFlags::ECHO_DRIVER_MESSAGES) {
Device::echo_driver_messages(self.device.gl());
self.device.echo_driver_messages();
}
results.stats.texture_upload_kb = self.profile_counters.texture_data_uploaded.get();

Просмотреть файл

@ -2258,7 +2258,7 @@ bool BytecodeEmitter::allocateResumeIndex(ptrdiff_t offset,
static constexpr uint32_t MaxResumeIndex = JS_BITMASK(24);
static_assert(
MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_CLOSING),
MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_RUNNING),
"resumeIndex should not include magic AbstractGeneratorObject "
"resumeIndex values");
static_assert(

Просмотреть файл

@ -1,3 +1,6 @@
// |jit-test| crash; skip-if: getBuildConfiguration()['arm64']
//
// Test skipped on ARM64 due to bug 1549763.
for (var actual = .5; actual < 100; actual++) {
var test2 = {

Просмотреть файл

@ -0,0 +1,116 @@
function testNativeGetter() {
function test() {
var xs = [Symbol("a"), Symbol("b")];
var ys = ["a", "b"];
for (var i = 0; i < 100; ++i) {
var r = xs[i & 1].description;
assertEq(r, ys[i & 1]);
}
}
for (var i = 0; i < 2; ++i) test();
}
testNativeGetter();
function testScriptedGetter() {
Object.defineProperty(Symbol.prototype, "desc", {
get() {
"use strict";
assertEq(typeof this, "symbol");
return this.description;
}
});
function test() {
var xs = [Symbol("a"), Symbol("b")];
var ys = ["a", "b"];
for (var i = 0; i < 100; ++i) {
var r = xs[i & 1].desc;
assertEq(r, ys[i & 1]);
}
}
for (var i = 0; i < 2; ++i) test();
}
testScriptedGetter();
function testScriptedGetterNonStrict() {
Object.defineProperty(Symbol.prototype, "desc_nonstrict", {
get() {
assertEq(typeof this, "object");
return this.description;
}
});
function test() {
var xs = [Symbol("a"), Symbol("b")];
var ys = ["a", "b"];
for (var i = 0; i < 100; ++i) {
var r = xs[i & 1].desc_nonstrict;
assertEq(r, ys[i & 1]);
}
}
for (var i = 0; i < 2; ++i) test();
}
testScriptedGetterNonStrict();
function testNativeGetterPrototype() {
Object.defineProperty(Object.prototype, "description_proto",
Object.getOwnPropertyDescriptor(Symbol.prototype, "description"));
function test() {
var xs = [Symbol("a"), Symbol("b")];
var ys = ["a", "b"];
for (var i = 0; i < 100; ++i) {
var r = xs[i & 1].description_proto;
assertEq(r, ys[i & 1]);
}
}
for (var i = 0; i < 2; ++i) test();
}
testNativeGetterPrototype();
function testScriptedGetterPrototype() {
Object.defineProperty(Object.prototype, "desc_proto", {
get() {
"use strict";
assertEq(typeof this, "symbol");
return this.description;
}
});
function test() {
var xs = [Symbol("a"), Symbol("b")];
var ys = ["a", "b"];
for (var i = 0; i < 100; ++i) {
var r = xs[i & 1].desc_proto;
assertEq(r, ys[i & 1]);
}
}
for (var i = 0; i < 2; ++i) test();
}
testScriptedGetterPrototype();
function testScriptedGetterNonStrictPrototype() {
Object.defineProperty(Object.prototype, "desc_nonstrict_proto", {
get() {
assertEq(typeof this, "object");
return this.description;
}
});
function test() {
var xs = [Symbol("a"), Symbol("b")];
var ys = ["a", "b"];
for (var i = 0; i < 100; ++i) {
var r = xs[i & 1].desc_nonstrict_proto;
assertEq(r, ys[i & 1]);
}
}
for (var i = 0; i < 2; ++i) test();
}
testScriptedGetterNonStrictPrototype();

Просмотреть файл

@ -0,0 +1,21 @@
// An onPop handler can return its input argument for async generators. The
// debugger correctly adjusts the state of the async generator object.
let g = newGlobal({newCompartment: true});
g.eval(`
async function* f() {}
`);
let hits = 0;
let dbg = new Debugger(g);
dbg.onEnterFrame = frame => {
frame.onPop = completion => {
hits++;
return completion;
};
};
let it = g.f();
let p = it.next();
assertEq(hits, 1);

Просмотреть файл

@ -91,6 +91,13 @@ class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler {
enum class NativeCallType { Native, ClassHook };
bool emitCallNativeShared(NativeCallType callType);
MOZ_MUST_USE bool emitCallScriptedGetterResultShared(
TypedOrValueRegister receiver);
template <typename T, typename CallVM>
MOZ_MUST_USE bool emitCallNativeGetterResultShared(T receiver,
const CallVM& emitCallVM);
public:
friend class AutoStubFrame;
@ -553,9 +560,8 @@ bool BaselineCacheIRCompiler::emitGuardHasGetterSetter() {
return true;
}
bool BaselineCacheIRCompiler::emitCallScriptedGetterResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
Register obj = allocator.useRegister(masm, reader.objOperandId());
bool BaselineCacheIRCompiler::emitCallScriptedGetterResultShared(
TypedOrValueRegister receiver) {
Address getterAddr(stubAddress(reader.stubOffset()));
bool isSameRealm = reader.readBool();
@ -589,10 +595,10 @@ bool BaselineCacheIRCompiler::emitCallScriptedGetterResult() {
// JitStackAlignment.
masm.alignJitStackBasedOnNArgs(0);
// Getter is called with 0 arguments, just |obj| as thisv.
// Getter is called with 0 arguments, just |receiver| as thisv.
// Note that we use Push, not push, so that callJit will align the stack
// properly on ARM.
masm.Push(TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
masm.Push(receiver);
EmitBaselineCreateStubFrameDescriptor(masm, scratch, JitFrameLayout::Size());
masm.Push(Imm32(0)); // ActualArgc is 0
@ -622,9 +628,24 @@ bool BaselineCacheIRCompiler::emitCallScriptedGetterResult() {
return true;
}
bool BaselineCacheIRCompiler::emitCallNativeGetterResult() {
bool BaselineCacheIRCompiler::emitCallScriptedGetterResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
Register obj = allocator.useRegister(masm, reader.objOperandId());
return emitCallScriptedGetterResultShared(
TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
}
bool BaselineCacheIRCompiler::emitCallScriptedGetterByValueResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
return emitCallScriptedGetterResultShared(val);
}
template <typename T, typename CallVM>
bool BaselineCacheIRCompiler::emitCallNativeGetterResultShared(
T receiver, const CallVM& emitCallVM) {
Address getterAddr(stubAddress(reader.stubOffset()));
AutoScratchRegister scratch(allocator, masm);
@ -637,17 +658,37 @@ bool BaselineCacheIRCompiler::emitCallNativeGetterResult() {
// Load the callee in the scratch register.
masm.loadPtr(getterAddr, scratch);
masm.Push(obj);
masm.Push(receiver);
masm.Push(scratch);
using Fn =
bool (*)(JSContext*, HandleFunction, HandleObject, MutableHandleValue);
callVM<Fn, CallNativeGetter>(masm);
emitCallVM();
stubFrame.leave(masm);
return true;
}
bool BaselineCacheIRCompiler::emitCallNativeGetterResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
Register obj = allocator.useRegister(masm, reader.objOperandId());
return emitCallNativeGetterResultShared(obj, [this]() {
using Fn =
bool (*)(JSContext*, HandleFunction, HandleObject, MutableHandleValue);
callVM<Fn, CallNativeGetter>(masm);
});
}
bool BaselineCacheIRCompiler::emitCallNativeGetterByValueResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
return emitCallNativeGetterResultShared(val, [this]() {
using Fn =
bool (*)(JSContext*, HandleFunction, HandleValue, MutableHandleValue);
callVM<Fn, CallNativeGetterByValue>(masm);
});
}
bool BaselineCacheIRCompiler::emitCallProxyGetResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
Register obj = allocator.useRegister(masm, reader.objOperandId());

Просмотреть файл

@ -920,23 +920,26 @@ static void EmitCallGetterResultNoGuards(CacheIRWriter& writer, JSObject* obj,
MOZ_ASSERT(target->isBuiltinNative());
writer.callNativeGetterResult(receiverId, target);
writer.typeMonitorResult();
} break;
break;
}
case CanAttachScriptedGetter: {
JSFunction* target = &shape->getterValue().toObject().as<JSFunction>();
MOZ_ASSERT(target->hasJitEntry());
writer.callScriptedGetterResult(receiverId, target);
writer.typeMonitorResult();
} break;
break;
}
default:
// CanAttachNativeGetProp guarantees that the getter is either a native or
// a scripted function.
MOZ_ASSERT_UNREACHABLE("Can't attach getter");
break;
}
}
static void EmitCallGetterResult(CacheIRWriter& writer, JSObject* obj,
JSObject* holder, Shape* shape,
ObjOperandId objId, ObjOperandId receiverId,
ICState::Mode mode) {
static void EmitCallGetterResultGuards(CacheIRWriter& writer, JSObject* obj,
JSObject* holder, Shape* shape,
ObjOperandId objId, ICState::Mode mode) {
// Use the megamorphic guard if we're in megamorphic mode, except if |obj|
// is a Window as GuardHasGetterSetter doesn't support this yet (Window may
// require outerizing).
@ -953,7 +956,13 @@ static void EmitCallGetterResult(CacheIRWriter& writer, JSObject* obj,
} else {
writer.guardHasGetterSetter(objId, shape);
}
}
static void EmitCallGetterResult(CacheIRWriter& writer, JSObject* obj,
JSObject* holder, Shape* shape,
ObjOperandId objId, ObjOperandId receiverId,
ICState::Mode mode) {
EmitCallGetterResultGuards(writer, obj, holder, shape, objId, mode);
EmitCallGetterResultNoGuards(writer, obj, holder, shape, receiverId);
}
@ -963,6 +972,36 @@ static void EmitCallGetterResult(CacheIRWriter& writer, JSObject* obj,
EmitCallGetterResult(writer, obj, holder, shape, objId, objId, mode);
}
static void EmitCallGetterByValueResult(CacheIRWriter& writer, JSObject* obj,
JSObject* holder, Shape* shape,
ObjOperandId objId,
ValOperandId receiverId,
ICState::Mode mode) {
EmitCallGetterResultGuards(writer, obj, holder, shape, objId, mode);
switch (IsCacheableGetPropCall(obj, holder, shape)) {
case CanAttachNativeGetter: {
JSFunction* target = &shape->getterValue().toObject().as<JSFunction>();
MOZ_ASSERT(target->isBuiltinNative());
writer.callNativeGetterByValueResult(receiverId, target);
writer.typeMonitorResult();
break;
}
case CanAttachScriptedGetter: {
JSFunction* target = &shape->getterValue().toObject().as<JSFunction>();
MOZ_ASSERT(target->hasJitEntry());
writer.callScriptedGetterByValueResult(receiverId, target);
writer.typeMonitorResult();
break;
}
default:
// CanAttachNativeGetProp guarantees that the getter is either a native or
// a scripted function.
MOZ_ASSERT_UNREACHABLE("Can't attach getter");
break;
}
}
void GetPropIRGenerator::attachMegamorphicNativeSlot(ObjOperandId objId,
jsid id,
bool handleMissing) {
@ -1850,33 +1889,59 @@ AttachDecision GetPropIRGenerator::tryAttachPrimitive(ValOperandId valId,
RootedNativeObject holder(cx_);
NativeGetPropCacheability type = CanAttachNativeGetProp(
cx_, proto, id, &holder, &shape, pc_, resultFlags_);
if (type == CanAttachTemporarilyUnoptimizable) {
return AttachDecision::TemporarilyUnoptimizable;
}
if (type != CanAttachReadSlot) {
return AttachDecision::NoAction;
}
switch (type) {
case CanAttachNone:
return AttachDecision::NoAction;
case CanAttachTemporarilyUnoptimizable:
return AttachDecision::TemporarilyUnoptimizable;
case CanAttachReadSlot: {
if (holder) {
// Instantiate this property, for use during Ion compilation.
if (IsIonEnabled(cx_)) {
EnsureTrackPropertyTypes(cx_, holder, id);
}
}
if (holder) {
// Instantiate this property, for use during Ion compilation.
if (IsIonEnabled(cx_)) {
EnsureTrackPropertyTypes(cx_, holder, id);
if (val_.isNumber()) {
writer.guardIsNumber(valId);
} else {
writer.guardType(valId, val_.type());
}
maybeEmitIdGuard(id);
ObjOperandId protoId = writer.loadObject(proto);
EmitReadSlotResult(writer, proto, holder, shape, protoId);
EmitReadSlotReturn(writer, proto, holder, shape);
trackAttached("PrimitiveSlot");
return AttachDecision::Attach;
}
case CanAttachScriptedGetter:
case CanAttachNativeGetter: {
MOZ_ASSERT(!idempotent());
// The primitive stubs don't currently support |super| access.
if (isSuper()) {
return AttachDecision::NoAction;
}
if (val_.isNumber()) {
writer.guardIsNumber(valId);
} else {
writer.guardType(valId, val_.type());
}
maybeEmitIdGuard(id);
ObjOperandId protoId = writer.loadObject(proto);
EmitCallGetterByValueResult(writer, proto, holder, shape, protoId, valId,
mode_);
trackAttached("PrimitiveGetter");
return AttachDecision::Attach;
}
}
if (val_.isNumber()) {
writer.guardIsNumber(valId);
} else {
writer.guardType(valId, val_.type());
}
maybeEmitIdGuard(id);
ObjOperandId protoId = writer.loadObject(proto);
EmitReadSlotResult(writer, proto, holder, shape, protoId);
EmitReadSlotReturn(writer, proto, holder, shape);
trackAttached("Primitive");
return AttachDecision::Attach;
MOZ_CRASH("Bad NativeGetPropCacheability");
}
AttachDecision GetPropIRGenerator::tryAttachStringLength(ValOperandId valId,

Просмотреть файл

@ -326,7 +326,9 @@ extern const uint32_t ArgLengths[];
_(LoadEnvironmentDynamicSlotResult, Id, Field) \
_(LoadObjectResult, Id) \
_(CallScriptedGetterResult, Id, Field, Byte) \
_(CallScriptedGetterByValueResult, Id, Field, Byte) \
_(CallNativeGetterResult, Id, Field) \
_(CallNativeGetterByValueResult, Id, Field) \
_(CallProxyGetResult, Id, Field) \
_(CallProxyGetByValueResult, Id, Id) \
_(CallProxyHasPropResult, Id, Id, Byte) \
@ -1639,10 +1641,19 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
addStubField(uintptr_t(getter), StubField::Type::JSObject);
buffer_.writeByte(cx_->realm() == getter->realm());
}
void callScriptedGetterByValueResult(ValOperandId obj, JSFunction* getter) {
writeOpWithOperandId(CacheOp::CallScriptedGetterByValueResult, obj);
addStubField(uintptr_t(getter), StubField::Type::JSObject);
buffer_.writeByte(cx_->realm() == getter->realm());
}
void callNativeGetterResult(ObjOperandId obj, JSFunction* getter) {
writeOpWithOperandId(CacheOp::CallNativeGetterResult, obj);
addStubField(uintptr_t(getter), StubField::Type::JSObject);
}
void callNativeGetterByValueResult(ValOperandId obj, JSFunction* getter) {
writeOpWithOperandId(CacheOp::CallNativeGetterByValueResult, obj);
addStubField(uintptr_t(getter), StubField::Type::JSObject);
}
void callProxyGetResult(ObjOperandId obj, jsid id) {
writeOpWithOperandId(CacheOp::CallProxyGetResult, obj);
addStubField(uintptr_t(JSID_BITS(id)), StubField::Type::Id);

Просмотреть файл

@ -4358,13 +4358,13 @@ bool CacheIRCompiler::emitCallIsSuspendedGeneratorResult() {
&GeneratorObject::class_, scratch2, scratch,
&returnFalse);
// If the resumeIndex slot holds an int32 value < RESUME_INDEX_CLOSING,
// If the resumeIndex slot holds an int32 value < RESUME_INDEX_RUNNING,
// the generator is suspended.
Address addr(scratch, AbstractGeneratorObject::offsetOfResumeIndexSlot());
masm.branchTestInt32(Assembler::NotEqual, addr, &returnFalse);
masm.unboxInt32(addr, scratch);
masm.branch32(Assembler::AboveOrEqual, scratch,
Imm32(AbstractGeneratorObject::RESUME_INDEX_CLOSING),
Imm32(AbstractGeneratorObject::RESUME_INDEX_RUNNING),
&returnFalse);
masm.moveValue(BooleanValue(true), output.valueReg());

Просмотреть файл

@ -113,6 +113,11 @@ class MOZ_RAII IonCacheIRCompiler : public CacheIRCompiler {
}
MOZ_MUST_USE bool emitAddAndStoreSlotShared(CacheOp op);
MOZ_MUST_USE bool emitCallScriptedGetterResultShared(
TypedOrValueRegister receiver, TypedOrValueRegister output);
MOZ_MUST_USE bool emitCallNativeGetterResultShared(
TypedOrValueRegister receiver, const AutoOutputRegister& output,
AutoSaveLiveRegisters& save);
bool needsPostBarrier() const {
return ic_->asSetPropertyIC()->needsPostBarrier();
@ -925,12 +930,8 @@ bool IonCacheIRCompiler::emitGuardHasGetterSetter() {
return true;
}
bool IonCacheIRCompiler::emitCallScriptedGetterResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register obj = allocator.useRegister(masm, reader.objOperandId());
bool IonCacheIRCompiler::emitCallScriptedGetterResultShared(
TypedOrValueRegister receiver, TypedOrValueRegister output) {
JSFunction* target = &objectStubField(reader.stubOffset())->as<JSFunction>();
AutoScratchRegister scratch(allocator, masm);
@ -961,7 +962,7 @@ bool IonCacheIRCompiler::emitCallScriptedGetterResult() {
for (size_t i = 0; i < target->nargs(); i++) {
masm.Push(UndefinedValue());
}
masm.Push(TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
masm.Push(receiver);
if (!isSameRealm) {
masm.switchToRealm(target->realm(), scratch);
@ -997,16 +998,34 @@ bool IonCacheIRCompiler::emitCallScriptedGetterResult() {
return true;
}
bool IonCacheIRCompiler::emitCallNativeGetterResult() {
bool IonCacheIRCompiler::emitCallScriptedGetterResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register obj = allocator.useRegister(masm, reader.objOperandId());
return emitCallScriptedGetterResultShared(
TypedOrValueRegister(MIRType::Object, AnyRegister(obj)), output);
}
bool IonCacheIRCompiler::emitCallScriptedGetterByValueResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
return emitCallScriptedGetterResultShared(val, output);
}
bool IonCacheIRCompiler::emitCallNativeGetterResultShared(
TypedOrValueRegister receiver, const AutoOutputRegister& output,
AutoSaveLiveRegisters& save) {
JSFunction* target = &objectStubField(reader.stubOffset())->as<JSFunction>();
MOZ_ASSERT(target->isNative());
AutoScratchRegister argJSContext(allocator, masm);
AutoScratchRegisterMaybeOutput argJSContext(allocator, masm, output);
AutoScratchRegister argUintN(allocator, masm);
AutoScratchRegister argVp(allocator, masm);
AutoScratchRegister scratch(allocator, masm);
@ -1019,8 +1038,8 @@ bool IonCacheIRCompiler::emitCallNativeGetterResult() {
// are the function arguments.
// Construct vp array:
// Push object value for |this|
masm.Push(TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
// Push receiver value for |this|
masm.Push(receiver);
// Push callee/outparam.
masm.Push(ObjectValue(*target));
@ -1071,6 +1090,27 @@ bool IonCacheIRCompiler::emitCallNativeGetterResult() {
return true;
}
bool IonCacheIRCompiler::emitCallNativeGetterResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register obj = allocator.useRegister(masm, reader.objOperandId());
return emitCallNativeGetterResultShared(
TypedOrValueRegister(MIRType::Object, AnyRegister(obj)), output, save);
}
bool IonCacheIRCompiler::emitCallNativeGetterByValueResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
return emitCallNativeGetterResultShared(val, output, save);
}
bool IonCacheIRCompiler::emitCallProxyGetResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);

Просмотреть файл

@ -56,6 +56,7 @@ namespace jit {
_(BoxNonStrictThis, js::BoxNonStrictThis) \
_(BuiltinProtoOperation, js::BuiltinProtoOperation) \
_(CallNativeGetter, js::jit::CallNativeGetter) \
_(CallNativeGetterByValue, js::jit::CallNativeGetterByValue) \
_(CallNativeSetter, js::jit::CallNativeSetter) \
_(CharCodeAt, js::jit::CharCodeAt) \
_(CheckClassHeritageOperation, js::CheckClassHeritageOperation) \

Просмотреть файл

@ -1559,6 +1559,25 @@ bool CallNativeGetter(JSContext* cx, HandleFunction callee, HandleObject obj,
return true;
}
bool CallNativeGetterByValue(JSContext* cx, HandleFunction callee,
HandleValue receiver, MutableHandleValue result) {
AutoRealm ar(cx, callee);
MOZ_ASSERT(callee->isNative());
JSNative natfun = callee->native();
JS::AutoValueArray<2> vp(cx);
vp[0].setObject(*callee.get());
vp[1].set(receiver);
if (!natfun(cx, 0, vp.begin())) {
return false;
}
result.set(vp[0]);
return true;
}
bool CallNativeSetter(JSContext* cx, HandleFunction callee, HandleObject obj,
HandleValue rhs) {
AutoRealm ar(cx, callee);

Просмотреть файл

@ -1056,6 +1056,10 @@ MOZ_MUST_USE bool BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame,
MOZ_MUST_USE bool CallNativeGetter(JSContext* cx, HandleFunction callee,
HandleObject obj, MutableHandleValue result);
MOZ_MUST_USE bool CallNativeGetterByValue(JSContext* cx, HandleFunction callee,
HandleValue receiver,
MutableHandleValue result);
MOZ_MUST_USE bool CallNativeSetter(JSContext* cx, HandleFunction callee,
HandleObject obj, HandleValue rhs);

Просмотреть файл

@ -1676,7 +1676,7 @@ static void AdjustGeneratorResumptionValue(JSContext* cx,
// bytecode, so we have to simulate that here. For async generators, our
// C++ implementation of AsyncGeneratorResolve will do this. So don't do it
// twice:
if (!frame.callee()->isAsync()) {
if (!genObj->is<AsyncGeneratorObject>()) {
JSObject* pair = CreateIterResultObject(cx, vp, true);
if (!pair) {
getAndClearExceptionThenThrow();
@ -1687,6 +1687,12 @@ static void AdjustGeneratorResumptionValue(JSContext* cx,
// 2. The generator must be closed.
genObj->setClosed();
// Async generators have additionally bookkeeping which must be adjusted
// when switching over to the closed state.
if (genObj->is<AsyncGeneratorObject>()) {
genObj->as<AsyncGeneratorObject>().setCompleted();
}
} else if (frame.callee()->isAsync()) {
if (AbstractGeneratorObject* genObj =
GetGeneratorObjectForFrame(cx, frame)) {
@ -2083,7 +2089,7 @@ ResumeMode Debugger::fireEnterFrame(JSContext* cx, MutableHandleValue vp) {
// Assert that the hook won't be able to re-enter the generator.
if (iter.hasScript() && *iter.pc() == JSOP_AFTERYIELD) {
auto* genObj = GetGeneratorObjectForFrame(cx, iter.abstractFramePtr());
MOZ_ASSERT(genObj->isRunning() || genObj->isClosing());
MOZ_ASSERT(genObj->isRunning());
}
#endif

Просмотреть файл

@ -100,7 +100,7 @@ bool AbstractGeneratorObject::suspend(JSContext* cx, HandleObject obj,
void AbstractGeneratorObject::finalSuspend(HandleObject obj) {
auto* genObj = &obj->as<AbstractGeneratorObject>();
MOZ_ASSERT(genObj->isRunning() || genObj->isClosing());
MOZ_ASSERT(genObj->isRunning());
genObj->setClosed();
}
@ -139,6 +139,7 @@ bool js::GeneratorThrowOrReturn(JSContext* cx, AbstractFramePtr frame,
Handle<AbstractGeneratorObject*> genObj,
HandleValue arg,
GeneratorResumeKind resumeKind) {
MOZ_ASSERT(genObj->isRunning());
if (resumeKind == GeneratorResumeKind::Throw) {
cx->setPendingExceptionAndCaptureStack(arg);
} else {
@ -149,7 +150,6 @@ bool js::GeneratorThrowOrReturn(JSContext* cx, AbstractFramePtr frame,
RootedValue closing(cx, MagicValue(JS_GENERATOR_CLOSING));
cx->setPendingException(closing, nullptr);
genObj->setClosing();
}
return false;
}
@ -309,7 +309,7 @@ bool AbstractGeneratorObject::isAfterAwait() {
}
bool AbstractGeneratorObject::isAfterYieldOrAwait(JSOp op) {
if (isClosed() || isClosing() || isRunning()) {
if (isClosed() || isRunning()) {
return false;
}

Просмотреть файл

@ -20,10 +20,9 @@ enum class GeneratorResumeKind { Next, Throw, Return };
class AbstractGeneratorObject : public NativeObject {
public:
// Magic values stored in the resumeIndex slot when the generator is
// Magic value stored in the resumeIndex slot when the generator is
// running or closing. See the resumeIndex comment below.
static const int32_t RESUME_INDEX_RUNNING = INT32_MAX;
static const int32_t RESUME_INDEX_CLOSING = INT32_MAX - 1;
enum {
CALLEE_SLOT = 0,
@ -116,8 +115,7 @@ class AbstractGeneratorObject : public NativeObject {
// The resumeIndex slot is abused for a few purposes. It's undefined if
// it hasn't been set yet (before the initial yield), and null if the
// generator is closed. If the generator is running, the resumeIndex is
// RESUME_INDEX_RUNNING. If the generator is in that bizarre "closing"
// state, the resumeIndex is RESUME_INDEX_CLOSING.
// RESUME_INDEX_RUNNING.
//
// If the generator is suspended, it's the resumeIndex (stored as
// JSOP_INITIALYIELD/JSOP_YIELD/JSOP_AWAIT operand) of the yield instruction
@ -130,35 +128,26 @@ class AbstractGeneratorObject : public NativeObject {
bool isRunning() const {
return getFixedSlot(RESUME_INDEX_SLOT) == Int32Value(RESUME_INDEX_RUNNING);
}
bool isClosing() const {
return getFixedSlot(RESUME_INDEX_SLOT) == Int32Value(RESUME_INDEX_CLOSING);
}
bool isSuspended() const {
// Note: also update Baseline's IsSuspendedGenerator code if this
// changes.
static_assert(RESUME_INDEX_CLOSING < RESUME_INDEX_RUNNING,
"test below should return false for RESUME_INDEX_RUNNING");
Value resumeIndex = getFixedSlot(RESUME_INDEX_SLOT);
return resumeIndex.isInt32() && resumeIndex.toInt32() < RESUME_INDEX_CLOSING;
return resumeIndex.isInt32() && resumeIndex.toInt32() < RESUME_INDEX_RUNNING;
}
void setRunning() {
MOZ_ASSERT(isSuspended());
setFixedSlot(RESUME_INDEX_SLOT, Int32Value(RESUME_INDEX_RUNNING));
}
void setClosing() {
MOZ_ASSERT(isRunning());
setFixedSlot(RESUME_INDEX_SLOT, Int32Value(RESUME_INDEX_CLOSING));
}
void setResumeIndex(jsbytecode* pc) {
MOZ_ASSERT(*pc == JSOP_INITIALYIELD || *pc == JSOP_YIELD ||
*pc == JSOP_AWAIT);
MOZ_ASSERT_IF(JSOp(*pc) == JSOP_INITIALYIELD,
getFixedSlot(RESUME_INDEX_SLOT).isUndefined());
MOZ_ASSERT_IF(JSOp(*pc) != JSOP_INITIALYIELD, isRunning() || isClosing());
MOZ_ASSERT_IF(JSOp(*pc) != JSOP_INITIALYIELD, isRunning());
uint32_t resumeIndex = GET_UINT24(pc);
MOZ_ASSERT(resumeIndex < uint32_t(RESUME_INDEX_CLOSING));
MOZ_ASSERT(resumeIndex < uint32_t(RESUME_INDEX_RUNNING));
setFixedSlot(RESUME_INDEX_SLOT, Int32Value(resumeIndex));
MOZ_ASSERT(isSuspended());

Просмотреть файл

@ -966,7 +966,7 @@ static bool intrinsic_GeneratorIsRunning(JSContext* cx, unsigned argc,
MOZ_ASSERT(args[0].isObject());
GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
args.rval().setBoolean(genObj->isRunning() || genObj->isClosing());
args.rval().setBoolean(genObj->isRunning());
return true;
}

Просмотреть файл

@ -2420,8 +2420,7 @@ nsView* nsDocumentViewer::FindContainerView() {
return nullptr;
}
nsIFrame* subdocFrame =
nsLayoutUtils::GetRealPrimaryFrameFor(containerElement);
nsIFrame* subdocFrame = containerElement->GetPrimaryFrame();
if (!subdocFrame) {
// XXX Silenced by default in bug 1175289
LAYOUT_WARNING("Subdocument container has no frame");

Просмотреть файл

@ -1579,16 +1579,6 @@ bool nsLayoutUtils::IsPrimaryStyleFrame(const nsIFrame* aFrame) {
return aFrame->IsPrimaryFrame();
}
/* static */
nsIFrame* nsLayoutUtils::GetRealPrimaryFrameFor(const nsIContent* aContent) {
nsIFrame* frame = aContent->GetPrimaryFrame();
if (!frame) {
return nullptr;
}
return nsPlaceholderFrame::GetRealFrameFor(frame);
}
nsIFrame* nsLayoutUtils::GetFloatFromPlaceholder(nsIFrame* aFrame) {
NS_ASSERTION(aFrame->IsPlaceholderFrame(), "Must have a placeholder here");
if (aFrame->GetStateBits() & PLACEHOLDER_FOR_FLOAT) {

Просмотреть файл

@ -434,15 +434,6 @@ class nsLayoutUtils {
*/
static bool IsPrimaryStyleFrame(const nsIFrame* aFrame);
/**
* Gets the real primary frame associated with the content object.
*
* In the case of absolutely positioned elements and floated elements,
* the real primary frame is the frame that is out of the flow and not the
* placeholder frame.
*/
static nsIFrame* GetRealPrimaryFrameFor(const nsIContent* aContent);
#ifdef DEBUG
// TODO: remove, see bug 598468.
static bool gPreventAssertInCompareTreePosition;

Просмотреть файл

@ -1905,7 +1905,10 @@ bool BuildTextRunsScanner::ContinueTextRunAcrossFrames(nsTextFrame* aFrame1,
}
const nsStyleText* textStyle2 = sc2->StyleText();
if (sc1 == sc2) return true;
if (textStyle1->mTextTransform != textStyle2->mTextTransform ||
textStyle1->EffectiveWordBreak() != textStyle2->EffectiveWordBreak()) {
return false;
}
nsPresContext* pc = aFrame1->PresContext();
MOZ_ASSERT(pc == aFrame2->PresContext());
@ -1916,7 +1919,6 @@ bool BuildTextRunsScanner::ContinueTextRunAcrossFrames(nsTextFrame* aFrame1,
nscoord letterSpacing2 = LetterSpacing(aFrame2);
return fontStyle1->mFont == fontStyle2->mFont &&
fontStyle1->mLanguage == fontStyle2->mLanguage &&
textStyle1->mTextTransform == textStyle2->mTextTransform &&
nsLayoutUtils::GetTextRunFlagsForStyle(sc1, pc, fontStyle1, textStyle1,
letterSpacing1) ==
nsLayoutUtils::GetTextRunFlagsForStyle(sc2, pc, fontStyle2,
@ -2570,7 +2572,8 @@ void BuildTextRunsScanner::SetupBreakSinksForTextRun(gfxTextRun* aTextRun,
const void* aTextPtr) {
using mozilla::intl::LineBreaker;
auto wordBreak = mLineContainer->StyleText()->EffectiveWordBreak();
auto wordBreak =
mMappedFlows[0].mStartFrame->StyleText()->EffectiveWordBreak();
switch (wordBreak) {
case StyleWordBreak::BreakAll:
mLineBreaker.SetWordBreak(LineBreaker::kWordBreak_BreakAll);
@ -5855,7 +5858,7 @@ void nsTextFrame::PaintOneShadow(const PaintShadowParams& aParams,
// Gecko already inflates the bounding rect of text shadows,
// so tell WR not to inflate again.
wrShadow.should_inflate = false;
wrShadow.should_inflate = true;
wrShadow.offset = {
PresContext()->AppUnitsToFloatDevPixels(aShadowDetails->mXOffset),

Просмотреть файл

@ -8985,16 +8985,10 @@ bool nsDisplayText::CreateWebRenderCommands(
auto* f = static_cast<nsTextFrame*>(mFrame);
auto appUnitsPerDevPixel = f->PresContext()->AppUnitsPerDevPixel();
// FIXME: the webrender backend is having a lot of snapping issues, and
// having it do inflation for us is causing problems. For now, we pass
// down the wrong bounds. Try to turn this back on when things are in
// better shape.
//
// nsRect bounds = f->WebRenderBounds() + ToReferenceFrame();
nsRect bounds = f->WebRenderBounds() + ToReferenceFrame();
// Bug 748228
// bounds.Inflate(appUnitsPerDevPixel);
bounds.Inflate(appUnitsPerDevPixel);
nsRect bounds = mBounds;
if (bounds.IsEmpty()) {
return true;
}

Просмотреть файл

@ -2102,7 +2102,7 @@ pref(layout.css.supports-selector.enabled,true) == 1499386.html 1499386-ref.html
pref(layout.css.supports-selector.enabled,false) != 1499386.html 1499386-ref.html
== 1509425-1.html 1509425-1-ref.html
== 1511570.html 1511570-ref.html
fuzzy-if(!webrender,1-5,66-547) fails-if(webrender) == 1529992-1.html 1529992-1-ref.html
fuzzy-if(!webrender,1-5,66-547) == 1529992-1.html 1529992-1-ref.html
fuzzy-if(!webrender,0-6,0-34) fails-if(webrender) == 1529992-2.html 1529992-2-ref.html
== 1535040-1.html 1535040-1-ref.html
== 1545360-1.xhtml 1545360-1-ref.xhtml

Просмотреть файл

@ -5,7 +5,7 @@ random-if(Android) == basic-negcoord.xul basic-negcoord-ref.xul
!= blur.xul blur-notref.xul
== color-inherit.xul color-inherit-ref.xul
== multiple-noblur.xul multiple-noblur-ref.xul
== blur-opacity.html blur-opacity-ref.html
fuzzy-if(webrender&&gtkWidget,128-128,160-160) == blur-opacity.html blur-opacity-ref.html
== basic.html basic-ref.html
== basic-negcoord.html basic-negcoord-ref.html

Просмотреть файл

@ -141,12 +141,12 @@ class IntegerRange {
template <typename T, bool = IsUnsigned<T>::value>
struct GeqZero {
static bool check(T t) { return t >= 0; }
static bool isNonNegative(T t) { return t >= 0; }
};
template <typename T>
struct GeqZero<T, true> {
static bool check(T t) { return true; }
static bool isNonNegative(T t) { return true; }
};
} // namespace detail
@ -154,7 +154,7 @@ struct GeqZero<T, true> {
template <typename IntType>
detail::IntegerRange<IntType> IntegerRange(IntType aEnd) {
static_assert(IsIntegral<IntType>::value, "value must be integral");
MOZ_ASSERT(detail::GeqZero<IntType>::check(aEnd),
MOZ_ASSERT(detail::GeqZero<IntType>::isNonNegative(aEnd),
"Should never have negative value here");
return detail::IntegerRange<IntType>(aEnd);
}

Просмотреть файл

@ -766,7 +766,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
* Note that this does not hash the actual contents; you must take
* care of that yourself, perhaps by using a match.
*/
mozilla::HashNumber addTagToHash(mozilla::HashNumber hashValue) {
mozilla::HashNumber addTagToHash(mozilla::HashNumber hashValue) const {
return mozilla::AddToHash(hashValue, tag);
}
};

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 46 KiB

Просмотреть файл

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<org.mozilla.gecko.preferences.NotificationSettingsLinkPreference
android:key="android.not_a_preference.notifications.settings_link"
android:title="@string/pref_notification_settings_link" />
<SwitchPreference android:key="android.not_a_preference.notifications.whats_new"
android:title="@string/pref_whats_new_notification"
android:summary="@string/pref_whats_new_notification_summary"

Просмотреть файл

@ -209,19 +209,15 @@ public class GeckoApplication extends Application
db.expireHistory(getContentResolver(), BrowserContract.ExpirePriority.NORMAL);
}
});
GeckoNetworkManager.getInstance().stop();
}
public void onApplicationForeground() {
if (mIsInitialResume) {
GeckoBatteryManager.getInstance().start(this);
GeckoNetworkManager.getInstance().start(this);
mIsInitialResume = false;
} else if (mPausedGecko) {
GeckoThread.onResume();
mPausedGecko = false;
GeckoNetworkManager.getInstance().start(this);
}
mInBackground = false;

Просмотреть файл

@ -23,6 +23,10 @@ public class DefaultBrowserPreference extends LinkPreference {
super(context, attrs, defStyle);
}
/**
* Open Default apps screen of Settings for API Levels>=24.
* Support URL will open for lower API levels.
*/
@Override
protected void onClick() {
if (GeckoPreferences.PREFS_DEFAULT_BROWSER.equals(getKey()) && AppConstants.Versions.feature24Plus) {

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше