Merge mozilla-central to autoland

This commit is contained in:
Carsten "Tomcat" Book 2017-08-15 13:12:22 +02:00
Родитель 64c0c31a2d 6b36e00b7c
Коммит a6ae5910bb
126 изменённых файлов: 1423 добавлений и 720 удалений

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

@ -457,8 +457,8 @@ var BrowserPageActions = {
// like how #star-button is contained in #star-button-box, the latter
// being the bookmark action's node. Look up the ancestor chain.
for (let n = node.parentNode; n && !action; n = n.parentNode) {
if (n.id == "urlbar-icons" || n.localName == "panelview") {
// We reached the urlbar icons container or the panelview container.
if (n.id == "page-action-buttons" || n.localName == "panelview") {
// We reached the page-action-buttons or panelview container.
// Stop looking; no acton was found.
break;
}

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

@ -663,8 +663,8 @@ html|input.urlbar-input[textoverflow]:not([focused]) {
-moz-binding: url("chrome://global/content/bindings/datetimepopup.xml#datetime-popup");
}
#urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon,
#urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon-wrapper > .urlbar-icon,
#urlbar[pageproxystate="invalid"] > #page-action-buttons > .urlbar-icon,
#urlbar[pageproxystate="invalid"] > #page-action-buttons > .urlbar-icon-wrapper > .urlbar-icon,
.urlbar-go-button[pageproxystate="valid"],
.urlbar-go-button:not([parentfocused="true"]),
#urlbar[pageproxystate="invalid"] > #identity-box > #blocked-permissions-container,

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

@ -880,7 +880,7 @@
<label id="switchtab" class="urlbar-display urlbar-display-switchtab" value="&urlbar.switchToTab.label;"/>
<label id="extension" class="urlbar-display urlbar-display-extension" value="&urlbar.extension.label;"/>
</box>
<hbox id="urlbar-icons">
<hbox id="page-action-buttons">
<image id="page-report-button"
class="urlbar-icon"
hidden="true"

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

@ -57,8 +57,7 @@ add_task(async function() {
modules: loader.loadedModules(),
services: Object.keys(Cc).filter(c => {
try {
Cm.isServiceInstantiatedByContractID(c, Ci.nsISupports);
return true;
return Cm.isServiceInstantiatedByContractID(c, Ci.nsISupports);
} catch (e) {
return false;
}

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

@ -80,6 +80,10 @@
["history"]
]
},
"identity": {
"schema": "chrome://extensions/content/schemas/identity.json",
"scopes": ["addon_parent"]
},
"menusInternal": {
"url": "chrome://browser/content/ext-menus.js",
"schema": "chrome://browser/content/schemas/menus.json",

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

@ -163,7 +163,7 @@ this.pageAction = class extends ExtensionAPI {
return {style};
}
// Create an |image| node and add it to the |urlbar-icons|
// Create an |image| node and add it to the |page-action-buttons|
// container in the given window.
addButton(window) {
let document = window.document;
@ -179,7 +179,7 @@ this.pageAction = class extends ExtensionAPI {
document.addEventListener("popupshowing", this);
}
document.getElementById("urlbar-icons").appendChild(button);
document.getElementById("page-action-buttons").appendChild(button);
return button;
}

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

@ -73,6 +73,7 @@ skip-if = (os == 'win' && !debug) # bug 1352668
[browser_ext_devtools_page.js]
[browser_ext_devtools_panel.js]
[browser_ext_devtools_panels_elements.js]
skip-if = true # bug 1382487
[browser_ext_geckoProfiler_symbolicate.js]
[browser_ext_getViews.js]
[browser_ext_identity_indication.js]

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

@ -64,6 +64,7 @@ support-files =
[browser_favicon_firstParty.js]
[browser_favicon_userContextId.js]
[browser_firstPartyIsolation.js]
[browser_firstPartyIsolation_about_newtab.js]
[browser_firstPartyIsolation_aboutPages.js]
[browser_firstPartyIsolation_blobURI.js]
[browser_firstPartyIsolation_js_uri.js]

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

@ -157,7 +157,7 @@ add_task(async function test_aboutURL() {
if ((flags & Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT) &&
!(flags & Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT) &&
networkURLs.indexOf(aboutType) == -1 &&
// Exclude about:newtab see Bug 1021667
// handle about:newtab in browser_firstPartyIsolation_about_newtab.js
aboutType !== "newtab") {
aboutURLs.push(aboutType);
}

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

@ -0,0 +1,40 @@
add_task(async function setup() {
Services.prefs.setBoolPref("privacy.firstparty.isolate", true);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("privacy.firstparty.isolate");
});
});
/**
* Test about:newtab will have firstPartytDomain set when we enable the pref.
*
* We split about:newtab from browser_firstPartyIsolation_aboutPages.js because
* about:newtab needs special care.
*
* In the original test browser_firstPartyIsolation_aboutPages.js, when calling
* tabbrowser.addTab, if it found out the uri is about:newtab, it will use
* the preloaded browser, however the preloaded browser is loaded before when we
* turn on the firstPartyIsolation pref, which won't have the pref set.
*
* To prevent to use the preloaded browser, a simple trick is open a window
* first.
**/
add_task(async function test_aboutNewTab() {
let win = await BrowserTestUtils.openNewBrowserWindow({remote: false});
let gbrowser = win.gBrowser;
let tab = BrowserTestUtils.addTab(gbrowser, "about:newtab");
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
let attrs = { firstPartyDomain: "about.ef2a7dd5-93bc-417f-a698-142c3116864f.mozilla" };
await ContentTask.spawn(tab.linkedBrowser, { attrs }, async function(args) {
info("principal " + content.document.nodePrincipal.origin);
Assert.equal(content.document.nodePrincipal.originAttributes.firstPartyDomain,
args.attrs.firstPartyDomain, "about:newtab should have firstPartyDomain set");
Assert.ok(content.document.nodePrincipal.isCodebasePrincipal,
"The principal should be a codebase principal.");
});
gbrowser.removeTab(tab);
win.close();
});

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

@ -46,8 +46,7 @@ startupRecorder.prototype = {
modules: this.loader.loadedModules(),
services: Object.keys(Cc).filter(c => {
try {
Cm.isServiceInstantiatedByContractID(c, Ci.nsISupports);
return true;
return Cm.isServiceInstantiatedByContractID(c, Ci.nsISupports);
} catch (e) {
return false;
}

2
browser/extensions/pocket/bootstrap.js поставляемый
Просмотреть файл

@ -212,7 +212,7 @@ var PocketPageAction = {
wrapper.appendChild(pocketButton);
wrapper.appendChild(animatableBox);
animatableBox.appendChild(animatableImage);
let iconBox = doc.getElementById("urlbar-icons");
let iconBox = doc.getElementById("page-action-buttons");
iconBox.appendChild(wrapper);
wrapper.hidden = true;
wrapper.addEventListener("click", event => {

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

@ -363,6 +363,7 @@ Section "-Application" APP_IDX
${EndIf}
${RemoveDeprecatedKeys}
${Set32to64DidMigrateReg}
; The previous installer adds several regsitry values to both HKLM and HKCU.
; We now try to add to HKLM and if that fails to HKCU

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

@ -91,6 +91,7 @@
${UpdateShortcutBranding}
${RemoveDeprecatedKeys}
${Set32to64DidMigrateReg}
${SetAppKeys}
${FixClassKeys}
@ -617,6 +618,73 @@
!macroend
!define SetStartMenuInternet "!insertmacro SetStartMenuInternet"
; Add registry keys to support the Firefox 32 bit to 64 bit migration. These
; registry entries are not removed on uninstall at this time. After the Firefox
; 32 bit to 64 bit migration effort is completed these registry entries can be
; removed during install, post update, and uninstall.
!macro Set32to64DidMigrateReg
${GetLongPath} "$INSTDIR" $1
; These registry keys are always in the 32 bit hive since they are never
; needed by a Firefox 64 bit install unless it has been updated from Firefox
; 32 bit.
SetRegView 32
!ifdef HAVE_64BIT_BUILD
; Running Firefox 64 bit on Windows 64 bit
ClearErrors
ReadRegDWORD $2 HKLM "Software\Mozilla\${AppName}\32to64DidMigrate" "$1"
; If there were no errors then the system was updated from Firefox 32 bit to
; Firefox 64 bit and if the value is already 1 then the registry value has
; already been updated in the HKLM registry.
${IfNot} ${Errors}
${AndIf} $2 != 1
ClearErrors
WriteRegDWORD HKLM "Software\Mozilla\${AppName}\32to64DidMigrate" "$1" 1
${If} ${Errors}
; There was an error writing to HKLM so just write it to HKCU
WriteRegDWORD HKCU "Software\Mozilla\${AppName}\32to64DidMigrate" "$1" 1
${Else}
; This will delete the value from HKCU if it exists
DeleteRegValue HKCU "Software\Mozilla\${AppName}\32to64DidMigrate" "$1"
${EndIf}
${EndIf}
ClearErrors
ReadRegDWORD $2 HKCU "Software\Mozilla\${AppName}\32to64DidMigrate" "$1"
; If there were no errors then the system was updated from Firefox 32 bit to
; Firefox 64 bit and if the value is already 1 then the registry value has
; already been updated in the HKCU registry.
${IfNot} ${Errors}
${AndIf} $2 != 1
WriteRegDWORD HKCU "Software\Mozilla\${AppName}\32to64DidMigrate" "$1" 1
${EndIf}
!else
; Running Firefox 32 bit
${If} ${RunningX64}
; Running Firefox 32 bit on a Windows 64 bit system
ClearErrors
ReadRegDWORD $2 HKLM "Software\Mozilla\${AppName}\32to64DidMigrate" "$1"
; If there were errors the value doesn't exist yet.
${If} ${Errors}
ClearErrors
WriteRegDWORD HKLM "Software\Mozilla\${AppName}\32to64DidMigrate" "$1" 0
; If there were errors write the value in HKCU.
${If} ${Errors}
WriteRegDWORD HKCU "Software\Mozilla\${AppName}\32to64DidMigrate" "$1" 0
${EndIf}
${EndIf}
${EndIf}
!endif
ClearErrors
SetRegView lastused
!macroend
!define Set32to64DidMigrateReg "!insertmacro Set32to64DidMigrateReg"
; The IconHandler reference for FirefoxHTML can end up in an inconsistent state
; due to changes not being detected by the IconHandler for side by side
; installs (see bug 268512). The symptoms can be either an incorrect icon or no

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

@ -121,7 +121,7 @@
/* Page action urlbar buttons */
#urlbar-icons {
#page-action-buttons {
-moz-box-align: center;
/* Add more space between the last icon and the urlbar's edge. */
margin-inline-end: 3px;

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

@ -156,17 +156,16 @@ const ResponsePanel = createClass({
sectionName = JSON_SCOPE_NAME;
}
object[sectionName] = json;
} else {
sectionName = RESPONSE_PAYLOAD;
object[sectionName] = {
EDITOR_CONFIG: {
text,
mode: mimeType.replace(/;.+/, ""),
},
};
}
// Others like text/html, text/plain, application/javascript
object[RESPONSE_PAYLOAD] = {
EDITOR_CONFIG: {
text,
mode: json ? "application/json" : mimeType.replace(/;.+/, ""),
},
};
return (
div({ className: "panel-container" },
error && div({ className: "response-error-header", title: error },
@ -175,7 +174,7 @@ const ResponsePanel = createClass({
PropertiesView({
object,
filterPlaceHolder: JSON_FILTER_TEXT,
sectionNames: [sectionName],
sectionNames: Object.keys(object),
}),
)
);

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

@ -170,7 +170,7 @@ add_task(function* () {
box != "json",
"The response json view doesn't display");
is(tabpanel.querySelector(".CodeMirror-code") === null,
box != "textarea",
(box !== "textarea" && box !== "json"),
"The response editor doesn't display");
is(tabpanel.querySelector(".response-image-box") === null,
box != "image",
@ -208,8 +208,8 @@ add_task(function* () {
case "json": {
checkVisibility("json");
is(tabpanel.querySelectorAll(".tree-section").length, 1,
"There should be 1 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".tree-section").length, 2,
"There should be 2 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".empty-notice").length, 0,
"The empty notice should not be displayed in this tabpanel.");

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

@ -23,7 +23,7 @@ add_task(function* () {
});
yield wait;
wait = waitForDOM(document, "#response-panel");
wait = waitForDOM(document, "#response-panel .CodeMirror-code");
EventUtils.sendMouseEvent({ type: "click" },
document.querySelector(".network-details-panel-toggle"));
EventUtils.sendMouseEvent({ type: "click" },
@ -37,13 +37,13 @@ add_task(function* () {
let jsonView = tabpanel.querySelector(".tree-section .treeLabel") || {};
is(jsonView.textContent === L10N.getStr("jsonScopeName"), true,
"The response json view has the intended visibility.");
is(tabpanel.querySelector(".CodeMirror-code") === null, true,
"The response editor doesn't have the intended visibility.");
is(tabpanel.querySelector(".CodeMirror-code") === null, false,
"The response editor has the intended visibility.");
is(tabpanel.querySelector(".response-image-box") === null, true,
"The response image box doesn't have the intended visibility.");
is(tabpanel.querySelectorAll(".tree-section").length, 1,
"There should be 1 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".tree-section").length, 2,
"There should be 2 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".treeRow:not(.tree-section)").length, 1,
"There should be 1 json properties displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".empty-notice").length, 0,

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

@ -48,7 +48,7 @@ add_task(function* () {
time: true
});
wait = waitForDOM(document, "#response-panel");
wait = waitForDOM(document, "#response-panel .CodeMirror-code");
EventUtils.sendMouseEvent({ type: "click" },
document.querySelector(".network-details-panel-toggle"));
EventUtils.sendMouseEvent({ type: "click" },
@ -67,13 +67,13 @@ add_task(function* () {
let jsonView = tabpanel.querySelector(".tree-section .treeLabel") || {};
is(jsonView.textContent === L10N.getStr("jsonScopeName"), true,
"The response json view has the intended visibility.");
is(tabpanel.querySelector(".CodeMirror-code") === null, true,
"The response editor doesn't have the intended visibility.");
is(tabpanel.querySelector(".CodeMirror-code") === null, false,
"The response editor has the intended visibility.");
is(tabpanel.querySelector(".response-image-box") === null, true,
"The response image box doesn't have the intended visibility.");
is(tabpanel.querySelectorAll(".tree-section").length, 1,
"There should be 1 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".tree-section").length, 2,
"There should be 2 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".treeRow:not(.tree-section)").length, 2047,
"There should be 2047 json properties displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".empty-notice").length, 0,

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

@ -62,7 +62,7 @@ add_task(function* () {
is(jsonView.textContent === L10N.getStr("jsonScopeName"), false,
"The response json view doesn't have the intended visibility.");
is(tabpanel.querySelector(".CodeMirror-code") === null, false,
"The response editor doesn't have the intended visibility.");
"The response editor has the intended visibility.");
is(tabpanel.querySelector(".response-image-box") === null, true,
"The response image box doesn't have the intended visibility.");

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

@ -27,8 +27,8 @@ add_task(function* () {
checkResponsePanelDisplaysJSON();
let tabpanel = document.querySelector("#response-panel");
is(tabpanel.querySelectorAll(".tree-section").length, 1,
"There should be 1 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".tree-section").length, 2,
"There should be 2 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".treeRow:not(.tree-section)").length, 1,
"There should be 1 json properties displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".empty-notice").length, 0,
@ -55,8 +55,8 @@ add_task(function* () {
let jsonView = panel.querySelector(".tree-section .treeLabel") || {};
is(jsonView.textContent === L10N.getStr("jsonScopeName"), true,
"The response json view has the intended visibility.");
is(panel.querySelector(".CodeMirror-code") === null, true,
"The response editor doesn't have the intended visibility.");
is(panel.querySelector(".CodeMirror-code") === null, false,
"The response editor has the intended visibility.");
is(panel.querySelector(".response-image-box") === null, true,
"The response image box doesn't have the intended visibility.");
}
@ -66,7 +66,7 @@ add_task(function* () {
* Returns a promise that will resolve when the response panel DOM element is available.
*/
function openResponsePanel() {
let onReponsePanelReady = waitForDOM(document, "#response-panel");
let onReponsePanelReady = waitForDOM(document, "#response-panel .CodeMirror-code");
EventUtils.sendMouseEvent({ type: "click" },
document.querySelector(".network-details-panel-toggle"));
EventUtils.sendMouseEvent({ type: "click" },

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

@ -42,7 +42,7 @@ add_task(function* () {
time: true
});
wait = waitForDOM(document, "#response-panel");
wait = waitForDOM(document, "#response-panel .CodeMirror-code");
EventUtils.sendMouseEvent({ type: "click" },
document.querySelector(".network-details-panel-toggle"));
EventUtils.sendMouseEvent({ type: "click" },
@ -61,13 +61,13 @@ add_task(function* () {
let jsonView = tabpanel.querySelector(".tree-section .treeLabel") || {};
is(jsonView.textContent === L10N.getStr("jsonScopeName"), true,
"The response json view has the intended visibility.");
is(tabpanel.querySelector(".CodeMirror-code") === null, true,
"The response editor doesn't have the intended visibility.");
is(tabpanel.querySelector(".CodeMirror-code") === null, false,
"The response editor has the intended visibility.");
is(tabpanel.querySelector(".response-image-box") === null, true,
"The response image box doesn't have the intended visibility.");
is(tabpanel.querySelectorAll(".tree-section").length, 1,
"There should be 1 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".tree-section").length, 2,
"There should be 2 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".treeRow:not(.tree-section)").length, 1,
"There should be 1 json properties displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".empty-notice").length, 0,

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

@ -43,7 +43,7 @@ add_task(function* () {
time: true
});
wait = waitForDOM(document, "#response-panel");
wait = waitForDOM(document, "#response-panel .CodeMirror-code");
EventUtils.sendMouseEvent({ type: "click" },
document.querySelector(".network-details-panel-toggle"));
EventUtils.sendMouseEvent({ type: "click" },
@ -62,13 +62,13 @@ add_task(function* () {
let jsonView = tabpanel.querySelector(".tree-section .treeLabel") || {};
is(jsonView.textContent === L10N.getStr("jsonScopeName"), true,
"The response json view has the intended visibility.");
is(tabpanel.querySelector(".CodeMirror-code") === null, true,
"The response editor doesn't have the intended visibility.");
is(tabpanel.querySelector(".CodeMirror-code") === null, false,
"The response editor has the intended visibility.");
is(tabpanel.querySelector(".response-image-box") === null, true,
"The response image box doesn't have the intended visibility.");
is(tabpanel.querySelectorAll(".tree-section").length, 1,
"There should be 1 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".tree-section").length, 2,
"There should be 2 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".treeRow:not(.tree-section)").length, 1,
"There should be 1 json properties displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".empty-notice").length, 0,

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

@ -57,7 +57,8 @@ add_task(function* () {
time: true
});
wait = waitForDOM(document, "#response-panel");
info("Testing first request");
wait = waitForDOM(document, "#response-panel .CodeMirror-code");
EventUtils.sendMouseEvent({ type: "click" },
document.querySelector(".network-details-panel-toggle"));
EventUtils.sendMouseEvent({ type: "click" },
@ -66,7 +67,9 @@ add_task(function* () {
testResponseTab("$_0123Fun", "Hello JSONP!");
wait = waitForDOM(document, "#response-panel .tree-section");
info("Testing second request");
wait = waitForDOM(document, "#response-panel .CodeMirror-code");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[1]);
yield wait;
@ -83,13 +86,13 @@ add_task(function* () {
is(tabpanel.querySelector(".tree-section .treeLabel").textContent,
L10N.getFormatStr("jsonpScopeName", func),
"The response json view has the intened visibility and correct title.");
is(tabpanel.querySelector(".CodeMirror-code") === null, true,
"The response editor doesn't have the intended visibility.");
is(tabpanel.querySelector(".CodeMirror-code") === null, false,
"The response editor has the intended visibility.");
is(tabpanel.querySelector(".responseImageBox") === null, true,
"The response image box doesn't have the intended visibility.");
is(tabpanel.querySelectorAll(".tree-section").length, 1,
"There should be 1 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".tree-section").length, 2,
"There should be 2 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".treeRow:not(.tree-section)").length, 1,
"There should be 1 json properties displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".empty-notice").length, 0,

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

@ -1315,6 +1315,16 @@ nsFrameMessageManager::GetProcessMessageManager(nsIMessageSender** aPMM)
return NS_OK;
}
NS_IMETHODIMP
nsFrameMessageManager::GetRemoteType(nsAString& aRemoteType)
{
aRemoteType.Truncate();
if (mCallback) {
return mCallback->DoGetRemoteType(aRemoteType);
}
return NS_OK;
}
namespace {
struct MessageManagerReferentCount

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

@ -92,6 +92,16 @@ public:
return nullptr;
}
virtual nsresult DoGetRemoteType(nsAString& aRemoteType) const
{
aRemoteType.Truncate();
nsIMessageSender* parent = GetProcessMessageManager();
if (parent) {
return parent->GetRemoteType(aRemoteType);
}
return NS_OK;
}
protected:
bool BuildClonedMessageDataForParent(nsIContentParent* aParent,
StructuredCloneData& aData,

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

@ -294,6 +294,12 @@ interface nsIMessageSender : nsIMessageListenerManager
* is null.
*/
readonly attribute nsIMessageSender processMessageManager;
/**
* For remote browsers, this contains the remoteType of the content child.
* Otherwise, it is empty.
*/
readonly attribute AString remoteType;
};
/**

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

@ -430,11 +430,22 @@ nsRange::UnregisterCommonAncestor(nsINode* aNode)
MOZ_ASSERT(ranges);
NS_ASSERTION(ranges->GetEntry(this), "unknown range");
bool isNativeAnon = aNode->IsInNativeAnonymousSubtree();
bool removed = false;
if (ranges->Count() == 1) {
aNode->ClearCommonAncestorForRangeInSelection();
aNode->GetCommonAncestorRangesPtr().reset();
if (!isNativeAnon) {
// For nodes which are in native anonymous subtrees, we optimize away the
// cost of deallocating the hashtable here because we may need to create
// it again shortly afterward. We don't do this for all nodes in order
// to avoid the additional memory usage unconditionally.
aNode->GetCommonAncestorRangesPtr().reset();
removed = true;
}
UnmarkDescendants(aNode);
} else {
}
if (!removed) {
ranges->RemoveEntry(this);
}
}

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

@ -14,6 +14,7 @@ support-files =
[test_bug1303704.html]
[test_bug1315862.html]
[test_bug1323158.html]
disabled = disabled # Bug 1389086 - Intermittent failures
[test_empty_file.html]
disabled = disabled # Bug 1150091 - Issue with support-files
[test_pointerevent_attributes_hoverable_pointers-manual.html]

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

@ -7,8 +7,6 @@
with Files("**"):
BUG_COMPONENT = ("Core", "DOM: IndexedDB")
TEST_DIRS += ['test/extensions']
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

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

@ -2,4 +2,3 @@
support-files = chromeHelpers.js
[test_globalObjects_chrome.xul]
[test_globalObjects_other.xul]

84
dom/indexedDB/test/extensions/bootstrap.js поставляемый
Просмотреть файл

@ -1,84 +0,0 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var Ci = Components.interfaces;
var Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function testForExpectedSymbols(stage, data) {
const expectedSymbols = [ "IDBKeyRange", "indexedDB" ];
for (var symbol of expectedSymbols) {
Services.prefs.setBoolPref("indexeddbtest.bootstrap." + stage + "." +
symbol, symbol in this);
}
}
function GlobalObjectsComponent() {
this.wrappedJSObject = this;
}
GlobalObjectsComponent.prototype =
{
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
runTest() {
const name = "Splendid Test";
let ok = this.ok;
let finishTest = this.finishTest;
let keyRange = IDBKeyRange.only(42);
ok(keyRange, "Got keyRange");
let request = indexedDB.open(name, 1);
request.onerror = function(event) {
ok(false, "indexedDB error, '" + event.target.error.name + "'");
finishTest();
}
request.onsuccess = function(event) {
let db = event.target.result;
ok(db, "Got database");
finishTest();
}
}
};
var gFactory = {
register() {
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
var classID = Components.ID("{d6f85dcb-537d-447e-b783-75d4b405622d}");
var description = "IndexedDBTest";
var contractID = "@mozilla.org/dom/indexeddb/GlobalObjectsComponent;1";
var factory = XPCOMUtils._getFactory(GlobalObjectsComponent);
registrar.registerFactory(classID, description, contractID, factory);
this.unregister = function() {
registrar.unregisterFactory(classID, factory);
delete this.unregister;
};
}
};
function install(data, reason) {
testForExpectedSymbols("install");
}
function startup(data, reason) {
testForExpectedSymbols("startup");
gFactory.register();
}
function shutdown(data, reason) {
testForExpectedSymbols("shutdown");
gFactory.unregister();
}
function uninstall(data, reason) {
testForExpectedSymbols("uninstall");
}

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

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

@ -1,31 +0,0 @@
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:name>IndexedDBTest</em:name>
<em:description>IndexedDB functions for use in testing.</em:description>
<em:creator>Mozilla</em:creator>
<em:version>2016.03.09</em:version>
<em:id>indexedDB-test@mozilla.org</em:id>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:targetApplication>
<Description>
<!-- Firefox -->
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>45.0</em:minVersion>
<em:maxVersion>*</em:maxVersion>
</Description>
</em:targetApplication>
<em:targetApplication>
<Description>
<!-- Fennec -->
<em:id>{aa3c5121-dab2-40e2-81ca-7ea25febc110}</em:id>
<em:minVersion>45.0</em:minVersion>
<em:maxVersion>*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>

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

@ -1,16 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPI_NAME = 'indexedDB'
FINAL_TARGET_FILES += [
'bootstrap.js',
'install.rdf',
]
TEST_HARNESS_FILES.testing.mochitest.extensions += [
'indexedDB-test@mozilla.org.xpi',
]

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

@ -1,58 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<window title="Mozilla Bug 832883"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTest();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript">
<![CDATA[
function* testSteps() {
// Test for IDBKeyRange and indexedDB availability in bootstrap files.
let test = Cc["@mozilla.org/dom/indexeddb/GlobalObjectsComponent;1"].
createInstance(Ci.nsISupports).wrappedJSObject;
test.ok = ok;
test.finishTest = continueToNextStep;
test.runTest();
yield undefined;
Cu.import("resource://gre/modules/AddonManager.jsm");
AddonManager.getAddonByID("indexedDB-test@mozilla.org",
grabEventAndContinueHandler);
let addon = yield undefined;
addon.uninstall();
Cu.import("resource://gre/modules/Services.jsm");
for (var stage of [ "install", "startup", "shutdown", "uninstall" ]) {
for (var symbol of [ "IDBKeyRange", "indexedDB" ]) {
let pref = Services.prefs.getBoolPref("indexeddbtest.bootstrap." + stage +
"." + symbol, false);
ok(pref, "Symbol '" + symbol + "' present during '" + stage + "'");
}
}
finishTest();
yield undefined;
}
window.runTest = function() {
SimpleTest.waitForExplicitFinish();
testGenerator.next();
}
]]>
</script>
<script type="text/javascript" src="chromeHelpers.js"></script>
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=832883"
target="_blank">Mozilla Bug 832883</a>
</body>
</window>

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

@ -2670,6 +2670,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentParent)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCallback)
NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionErrorCallback)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
NS_INTERFACE_MAP_END
@ -2851,6 +2852,20 @@ ContentParent::Observe(nsISupports* aSubject,
return NS_OK;
}
NS_IMETHODIMP
ContentParent::GetInterface(const nsIID& aIID, void** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
if (aIID.Equals(NS_GET_IID(nsIMessageSender))) {
nsCOMPtr<nsIMessageSender> mm = GetMessageManager();
mm.forget(aResult);
return NS_OK;
}
return NS_NOINTERFACE;
}
mozilla::ipc::IPCResult
ContentParent::RecvInitBackground(Endpoint<PBackgroundParent>&& aEndpoint)
{

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

@ -26,6 +26,7 @@
#include "nsPluginTags.h"
#include "nsFrameMessageManager.h"
#include "nsHashKeys.h"
#include "nsIInterfaceRequestor.h"
#include "nsIObserver.h"
#include "nsIThreadInternal.h"
#include "nsIDOMGeoPositionCallback.h"
@ -109,6 +110,7 @@ class ContentParent final : public PContentParent
, public nsIObserver
, public nsIDOMGeoPositionCallback
, public nsIDOMGeoPositionErrorCallback
, public nsIInterfaceRequestor
, public gfx::gfxVarReceiver
, public mozilla::LinkedListElement<ContentParent>
, public gfx::GPUProcessListener
@ -198,6 +200,12 @@ public:
const nsAString& GetRemoteType() const;
virtual nsresult DoGetRemoteType(nsAString& aRemoteType) const override
{
aRemoteType = GetRemoteType();
return NS_OK;
}
enum CPIteratorPolicy {
eLive,
eAll
@ -310,6 +318,7 @@ public:
NS_DECL_NSIOBSERVER
NS_DECL_NSIDOMGEOPOSITIONCALLBACK
NS_DECL_NSIDOMGEOPOSITIONERRORCALLBACK
NS_DECL_NSIINTERFACEREQUESTOR
/**
* MessageManagerCallback methods that we override.

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

@ -8,6 +8,7 @@
#include "MediaEngine.h"
#include "nsDirectoryServiceDefs.h"
#include "mozilla/Unused.h"
// conflicts with #include of scoped_ptr.h
#undef FF
@ -60,6 +61,20 @@ public:
const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
const nsString& aDeviceId) const override;
void Shutdown() override
{
MonitorAutoLock lock(mMonitor);
// Release mImage and it's resources just in case -- also we can be
// held by something in a CC chain, and not be deleted until final-cc,
// which is too late for releasing images. (This should be null'd on
// Stop(), but apparently Stop() may not get called in this case
// somehow.) (Bug 1374164)
Unused << NS_WARN_IF(mImage);
mImage = nullptr;
}
protected:
struct CapabilityCandidate {
explicit CapabilityCandidate(uint8_t index, uint32_t distance = 0)

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

@ -1538,8 +1538,14 @@ HTMLEditor::RelativeFontChangeHelper(int32_t aSizeChange,
if (aNode->IsHTMLElement(nsGkAtoms::font) &&
aNode->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::size)) {
// Cycle through children and adjust relative font size.
for (uint32_t i = aNode->GetChildCount(); i--; ) {
nsresult rv = RelativeFontChangeOnNode(aSizeChange, aNode->GetChildAt(i));
AutoTArray<nsCOMPtr<nsIContent>, 10> childList;
for (nsIContent* child = aNode->GetFirstChild();
child; child = child->GetNextSibling()) {
childList.AppendElement(child);
}
for (const auto& child: childList) {
nsresult rv = RelativeFontChangeOnNode(aSizeChange, child);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -1549,8 +1555,14 @@ HTMLEditor::RelativeFontChangeHelper(int32_t aSizeChange,
}
// Otherwise cycle through the children.
for (uint32_t i = aNode->GetChildCount(); i--; ) {
nsresult rv = RelativeFontChangeHelper(aSizeChange, aNode->GetChildAt(i));
AutoTArray<nsCOMPtr<nsIContent>, 10> childList;
for (nsIContent* child = aNode->GetFirstChild();
child; child = child->GetNextSibling()) {
childList.AppendElement(child);
}
for (const auto& child: childList) {
nsresult rv = RelativeFontChangeHelper(aSizeChange, child);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -1616,8 +1628,14 @@ HTMLEditor::RelativeFontChangeOnNode(int32_t aSizeChange,
// MOOSE: we should group the children together if possible
// into a single "big" or "small". For the moment they are
// each getting their own.
for (uint32_t i = aNode->GetChildCount(); i--; ) {
nsresult rv = RelativeFontChangeOnNode(aSizeChange, aNode->GetChildAt(i));
AutoTArray<nsCOMPtr<nsIContent>, 10> childList;
for (nsIContent* child = aNode->GetFirstChild();
child; child = child->GetNextSibling()) {
childList.AppendElement(child);
}
for (const auto& child: childList) {
nsresult rv = RelativeFontChangeOnNode(aSizeChange, child);
NS_ENSURE_SUCCESS(rv, rv);
}

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

@ -647,10 +647,6 @@ RangeItem::~RangeItem()
{
}
NS_IMPL_CYCLE_COLLECTION(RangeItem, mStartContainer, mEndContainer)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(RangeItem, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(RangeItem, Release)
void
RangeItem::StoreRange(nsRange* aRange)
{
@ -672,4 +668,18 @@ RangeItem::GetRange()
return range.forget();
}
void
RangeItem::Unlink()
{
ImplCycleCollectionUnlink(mStartContainer);
ImplCycleCollectionUnlink(mEndContainer);
}
void
RangeItem::Traverse(nsCycleCollectionTraversalCallback& aCallback, uint32_t aFlags)
{
CycleCollectionNoteChild(aCallback, mStartContainer.get(), "mStartContainer", aFlags);
CycleCollectionNoteChild(aCallback, mEndContainer.get(), "mEndContainer", aFlags);
}
} // namespace mozilla

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

@ -37,8 +37,10 @@ public:
void StoreRange(nsRange* aRange);
already_AddRefed<nsRange> GetRange();
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(RangeItem)
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(RangeItem)
NS_INLINE_DECL_REFCOUNTING(RangeItem)
void Unlink();
void Traverse(nsCycleCollectionTraversalCallback& aCallback, uint32_t aFlags);
nsCOMPtr<nsINode> mStartContainer;
int32_t mStartOffset;
@ -46,6 +48,36 @@ public:
int32_t mEndOffset;
};
inline void
ImplCycleCollectionUnlink(RangeItem& aItem)
{
aItem.Unlink();
}
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
RangeItem& aItem,
const char* aName,
uint32_t aFlags = 0)
{
aItem.Traverse(aCallback, aFlags);
}
inline void
ImplCycleCollectionUnlink(RefPtr<RangeItem>& aItem)
{
aItem->Unlink();
}
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
RefPtr<RangeItem>& aItem,
const char* aName,
uint32_t aFlags = 0)
{
aItem->Traverse(aCallback, aFlags);
}
/**
* mozilla::SelectionState
*

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

@ -31,6 +31,7 @@ DrawTargetCaptureImpl::DrawTargetCaptureImpl(BackendType aBackend,
RefPtr<DrawTarget> screenRefDT =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
mFormat = aFormat;
if (aBackend == screenRefDT->GetBackendType()) {
mRefDT = screenRefDT;
} else {
@ -44,8 +45,6 @@ DrawTargetCaptureImpl::DrawTargetCaptureImpl(BackendType aBackend,
IntSize size(1, 1);
mRefDT = Factory::CreateDrawTarget(aBackend, size, mFormat);
}
mFormat = aFormat;
}
bool

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

@ -41,8 +41,8 @@ DrawTargetTiled::Init(const TileSet& aTiles)
mRect.y = min(mRect.y, mTiles[i].mTileOrigin.y);
mRect.width = newXMost - mRect.x;
mRect.height = newYMost - mRect.y;
mTiles[i].mDrawTarget->SetTransform(Matrix::Translation(mTiles[i].mTileOrigin.x,
mTiles[i].mTileOrigin.y));
mTiles[i].mDrawTarget->SetTransform(Matrix::Translation(-mTiles[i].mTileOrigin.x,
-mTiles[i].mTileOrigin.y));
}
mFormat = mTiles[0].mDrawTarget->GetFormat();
SetPermitSubpixelAA(IsOpaque(mFormat));

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

@ -407,6 +407,15 @@ ShouldLimitDeviceResets(uint32_t count, int32_t deltaMilliseconds)
return false;
}
void
GPUProcessManager::ResetCompositors()
{
// Note: this will recreate devices in addition to recreating compositors.
// This isn't optimal, but this is only used on linux where acceleration
// isn't enabled by default, and this way we don't need a new code path.
SimulateDeviceReset();
}
void
GPUProcessManager::SimulateDeviceReset()
{

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

@ -143,6 +143,9 @@ public:
uint64_t* aOutLayersId,
CompositorOptions* aOutCompositorOptions);
// Destroy and recreate all of the compositors
void ResetCompositors();
void OnProcessLaunchComplete(GPUProcessHost* aHost) override;
void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override;
void SimulateDeviceReset();

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

@ -9,6 +9,8 @@
#include "base/task.h"
#include "gfxPrefs.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/ShadowLayers.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/Preferences.h"
#include "mozilla/SyncRunnable.h"
@ -170,19 +172,15 @@ void
PaintThread::FinishedLayerBatch()
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<CompositorBridgeChild> cbc;
if (!gfxPrefs::LayersOMTPForceSync()) {
cbc = CompositorBridgeChild::Get();
}
RefPtr<PaintThread> self = this;
RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::EndAsyncPainting",
[self, cbc]() -> void
RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::EndAsyncPaintingLayer",
[self]() -> void
{
self->EndAsyncPainting(cbc);
self->EndAsyncPaintingLayer();
});
if (cbc) {
if (!gfxPrefs::LayersOMTPForceSync()) {
sThread->Dispatch(task.forget());
} else {
SyncRunnable::DispatchToThread(sThread, task);
@ -190,7 +188,7 @@ PaintThread::FinishedLayerBatch()
}
void
PaintThread::EndAsyncPainting(CompositorBridgeChild* aBridge)
PaintThread::EndAsyncPaintingLayer()
{
MOZ_ASSERT(IsOnPaintThread());
// Textureclient forces a flush once we "end paint", so
@ -201,12 +199,47 @@ PaintThread::EndAsyncPainting(CompositorBridgeChild* aBridge)
}
mDrawTargetsToFlush.Clear();
}
if (aBridge) {
aBridge->NotifyFinishedAsyncPaintLayer();
void
PaintThread::SynchronizePaintTextures(SyncObjectClient* aSyncObject)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aSyncObject);
RefPtr<CompositorBridgeChild> cbc;
if (!gfxPrefs::LayersOMTPForceSync()) {
cbc = CompositorBridgeChild::Get();
}
RefPtr<SyncObjectClient> syncObject(aSyncObject);
RefPtr<PaintThread> self = this;
RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::SyncTextureData",
[self, cbc, syncObject]() -> void
{
self->SyncTextureData(cbc, syncObject);
});
if (cbc) {
sThread->Dispatch(task.forget());
} else {
SyncRunnable::DispatchToThread(sThread, task);
}
}
void
PaintThread::SyncTextureData(CompositorBridgeChild* aBridge,
SyncObjectClient* aSyncObject)
{
MOZ_ASSERT(IsOnPaintThread());
MOZ_ASSERT(aSyncObject);
aSyncObject->Synchronize();
if (aBridge) {
aBridge->NotifyFinishedAsyncPaintTransaction();
}
}
void
PaintThread::PaintContents(CapturedPaintState* aState,

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

@ -75,6 +75,14 @@ public:
// and the main thread is finished recording this layer.
void FinishedLayerBatch();
// Must be called on the main thread. Tells the paint thread
// to schedule a sync textures after all async paints are done.
// NOTE: The other paint thread functions are on a per PAINT
// or per paint layer basis. This MUST be called at the end
// of a layer transaction as multiple paints can occur
// with multiple layers. We only have to do this once per transaction.
void SynchronizePaintTextures(SyncObjectClient* aSyncObject);
// Sync Runnables need threads to be ref counted,
// But this thread lives through the whole process.
// We're only temporarily using sync runnables so
@ -92,7 +100,9 @@ private:
void PaintContentsAsync(CompositorBridgeChild* aBridge,
CapturedPaintState* aState,
PrepDrawTargetForPaintingCallback aCallback);
void EndAsyncPainting(CompositorBridgeChild* aBridge);
void EndAsyncPaintingLayer();
void SyncTextureData(CompositorBridgeChild* aBridge,
SyncObjectClient* aSyncObject);
static StaticAutoPtr<PaintThread> sSingleton;
static StaticRefPtr<nsIThread> sThread;

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

@ -86,7 +86,6 @@ private:
ViewID aScrollId,
const std::string& aKey,
const std::string& aValue) {
MOZ_ASSERT(gfxPrefs::APZTestLoggingEnabled(), "don't call me");
auto bucketIterator = aDataStore.find(aSequenceNumber);
if (bucketIterator == aDataStore.end()) {
MOZ_ASSERT(false, "LogTestDataImpl called with nonexistent sequence number");
@ -105,8 +104,9 @@ class APZPaintLogHelper {
public:
APZPaintLogHelper(APZTestData* aTestData, SequenceNumber aPaintSequenceNumber)
: mTestData(aTestData),
mPaintSequenceNumber(aPaintSequenceNumber)
{}
mPaintSequenceNumber(aPaintSequenceNumber) {
MOZ_ASSERT(!aTestData || gfxPrefs::APZTestLoggingEnabled(), "don't call me");
}
template <typename Value>
void LogTestData(FrameMetrics::ViewID aScrollId,

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

@ -100,6 +100,7 @@ ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
, mTransactionIncomplete(false)
, mCompositorMightResample(false)
, mNeedsComposite(false)
, mTextureSyncOnPaintThread(false)
, mPaintSequenceNumber(0)
, mDeviceResetSequenceNumber(0)
, mForwarder(new ShadowLayerForwarder(this))
@ -358,6 +359,7 @@ ClientLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
ClientLayer* root = ClientLayer::ToClientLayer(GetRoot());
mTransactionIncomplete = false;
mTextureSyncOnPaintThread = false;
// Apply pending tree updates before recomputing effective
// properties.
@ -725,11 +727,17 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
TimeStamp start = TimeStamp::Now();
// Skip the synchronization for buffer since we also skip the painting during
// device-reset status.
// device-reset status. With OMTP, we have to wait for async paints
// before we synchronize and it's done on the paint thread.
if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
if (mForwarder->GetSyncObject() &&
mForwarder->GetSyncObject()->IsSyncObjectValid()) {
mForwarder->GetSyncObject()->Synchronize();
if (mTextureSyncOnPaintThread) {
// We have to wait for all async paints to finish to do this
PaintThread::Get()->SynchronizePaintTextures(mForwarder->GetSyncObject());
} else {
mForwarder->GetSyncObject()->Synchronize();
}
}
}

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

@ -17,6 +17,7 @@
#include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/FocusTarget.h" // for FocusTarget
#include "mozilla/layers/LayersTypes.h" // for BufferMode, LayersBackend, etc
#include "mozilla/layers/PaintThread.h" // For PaintThread
#include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder, etc
#include "mozilla/layers/APZTestData.h" // for APZTestData
#include "nsCOMPtr.h" // for already_AddRefed
@ -158,6 +159,7 @@ public:
bool IsRepeatTransaction() { return mIsRepeatTransaction; }
void SetTransactionIncomplete() { mTransactionIncomplete = true; }
void SetNeedTextureSyncOnPaintThread() { mTextureSyncOnPaintThread = true; }
bool HasShadowTarget() { return !!mShadowTarget; }
@ -349,6 +351,7 @@ private:
bool mTransactionIncomplete;
bool mCompositorMightResample;
bool mNeedsComposite;
bool mTextureSyncOnPaintThread;
// An incrementing sequence number for paints.
// Incremented in BeginTransaction(), but not for repeat transactions.

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

@ -268,6 +268,7 @@ ClientPaintedLayer::PaintOffMainThread()
if (didUpdate) {
UpdateContentClient(state);
ClientManager()->SetNeedTextureSyncOnPaintThread();
}
return true;
}

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

@ -1623,6 +1623,7 @@ SyncObjectD3D11Host::Synchronize()
SyncObjectD3D11Client::SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Device* aDevice)
: mSyncHandle(aSyncHandle)
, mSyncLock("SyncObjectD3D11")
{
if (!aDevice) {
mDevice = DeviceManagerDx::Get()->GetContentDevice();
@ -1678,9 +1679,19 @@ SyncObjectD3D11Client::IsSyncObjectValid()
return true;
}
// We have only 1 sync object. As a thing that somehow works,
// we copy each of the textures that need to be synced with the compositor
// into our sync object and only use a lock for this sync object.
// This way, we don't have to sync every texture we send to the compositor.
// We only have to do this once per transaction.
void
SyncObjectD3D11Client::Synchronize()
{
// Since this can be called from either the Paint or Main thread.
// We don't want this to race since we initialize the sync texture here
// too.
MutexAutoLock syncLock(mSyncLock);
if (!mSyncedTextures.size()) {
return;
}

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

@ -484,6 +484,7 @@ private:
RefPtr<ID3D11Texture2D> mSyncTexture;
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
std::vector<ID3D11Texture2D*> mSyncedTextures;
Mutex mSyncLock;
};
inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel)

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

@ -1189,15 +1189,18 @@ CompositorBridgeChild::NotifyFinishedAsyncPaint(CapturedPaintState* aState)
}
void
CompositorBridgeChild::NotifyFinishedAsyncPaintLayer()
CompositorBridgeChild::NotifyFinishedAsyncPaintTransaction()
{
MOZ_ASSERT(PaintThread::IsOnPaintThread());
MonitorAutoLock lock(mPaintLock);
// Since this should happen after ALL paints are done and
// at the end of a transaction, this should always be true.
MOZ_RELEASE_ASSERT(mOutstandingAsyncPaints == 0);
// It's possible that we painted so fast that the main thread never reached
// the code that starts delaying messages. If so, mIsWaitingForPaint will be
// false, and we can safely return.
if (mIsWaitingForPaint && mOutstandingAsyncPaints == 0) {
if (mIsWaitingForPaint) {
ResumeIPCAfterAsyncPaint();
// Notify the main thread in case it's blocking. We do this unconditionally

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

@ -242,8 +242,9 @@ public:
// Must only be called from the paint thread. Notifies the CompositorBridge
// that the paint thread has finished ALL async requests from a given
// ClientPaintedLayer's batch.
void NotifyFinishedAsyncPaintLayer();
// transaction. We can resume IPC transactions after ALL
// async paints are done.
void NotifyFinishedAsyncPaintTransaction();
private:
// Private destructor, to discourage deletion outside of Release():

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

@ -463,9 +463,11 @@ CompositorBridgeParent::StopAndClearResources()
});
mWrBridge->Destroy();
mWrBridge = nullptr;
mAsyncImageManager->Destroy();
// WebRenderAPI should be already destructed
mAsyncImageManager = nullptr;
if (mAsyncImageManager) {
mAsyncImageManager->Destroy();
// WebRenderAPI should be already destructed
mAsyncImageManager = nullptr;
}
}
if (mCompositor) {

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

@ -265,21 +265,6 @@ public:
void ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive) override { }
/**
* Request that the compositor be recreated due to a shared device reset.
* This must be called on the main thread, and blocks until a task posted
* to the compositor thread has completed.
*
* Note that this posts a task directly, rather than using synchronous
* IPDL, and waits on a monitor notification from the compositor thread.
* We do this as a best-effort attempt to jump any IPDL messages that
* have not yet been posted (and are sitting around in the IO pipe), to
* minimize the amount of time the main thread is blocked.
*/
bool ResetCompositor(const nsTArray<LayersBackend>& aBackendHints,
uint64_t aSeqNo,
TextureFactoryIdentifier* aOutIdentifier);
/**
* This forces the is-first-paint flag to true. This is intended to
* be called by the widget code when it loses its viewport information

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

@ -244,22 +244,26 @@ CompositorManagerChild::ProcessingError(Result aCode, const char* aReason)
already_AddRefed<nsIEventTarget>
CompositorManagerChild::GetSpecificMessageEventTarget(const Message& aMsg)
{
if (aMsg.type() != PCompositorBridge::Msg_DidComposite__ID) {
return nullptr;
if (aMsg.type() == PCompositorBridge::Msg_DidComposite__ID) {
uint64_t layersId;
PickleIterator iter(aMsg);
if (!IPC::ReadParam(&aMsg, &iter, &layersId)) {
return nullptr;
}
TabChild* tabChild = TabChild::GetFrom(layersId);
if (!tabChild) {
return nullptr;
}
return do_AddRef(tabChild->TabGroup()->EventTargetFor(TaskCategory::Other));
}
uint64_t layersId;
PickleIterator iter(aMsg);
if (!IPC::ReadParam(&aMsg, &iter, &layersId)) {
return nullptr;
if (aMsg.type() == PCompositorBridge::Msg_ParentAsyncMessages__ID) {
return do_AddRef(SystemGroup::EventTargetFor(TaskCategory::Other));
}
TabChild* tabChild = TabChild::GetFrom(layersId);
if (!tabChild) {
return nullptr;
}
return do_AddRef(tabChild->TabGroup()->EventTargetFor(TaskCategory::Other));
return nullptr;
}
void

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

@ -1496,10 +1496,10 @@ static void aaa_walk_edges(SkAnalyticEdge* prevHead, SkAnalyticEdge* nextTail,
} else {
SkFixed rite = currE->fX;
currE->goY(nextY, yShift);
leftE->fX = SkTMax(leftClip, leftE->fX);
SkFixed nextLeft = SkTMax(leftClip, leftE->fX);
rite = SkTMin(rightClip, rite);
currE->fX = SkTMin(rightClip, currE->fX);
blit_trapezoid_row(blitter, y >> 16, left, rite, leftE->fX, currE->fX,
SkFixed nextRite = SkTMin(rightClip, currE->fX);
blit_trapezoid_row(blitter, y >> 16, left, rite, nextLeft, nextRite,
leftDY, currE->fDY, fullAlpha, maskRow, isUsingMask,
noRealBlitter || (fullAlpha == 0xFF && (
edges_too_close(prevRite, left, leftE->fX) ||

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

@ -49,7 +49,7 @@ public:
typedef gfxTextRun::Range Range;
typedef mozilla::gfx::DrawTarget DrawTarget;
struct Params
struct MOZ_STACK_CLASS Params
{
nsIAtom* language = nullptr;
bool explicitLanguage = false;
@ -250,7 +250,9 @@ private:
nsFont mFont;
RefPtr<gfxFontGroup> mFontGroup;
nsCOMPtr<nsIAtom> mLanguage;
nsDeviceContext* mDeviceContext;
// Pointer to the device context for which this fontMetrics object was
// created.
nsDeviceContext* MOZ_NON_OWNING_REF mDeviceContext;
int32_t mP2A;
// The font orientation (horizontal or vertical) for which these metrics

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

@ -337,7 +337,7 @@ protected:
static gfxFontCache *gGlobalCache;
struct Key {
struct MOZ_STACK_CLASS Key {
const gfxFontEntry* mFontEntry;
const gfxFontStyle* mStyle;
const gfxCharacterMap* mUnicodeRangeMap;
@ -367,7 +367,11 @@ protected:
}
enum { ALLOW_MEMMOVE = true };
gfxFont* mFont;
// The cache tracks gfxFont objects whose refcount has dropped to zero,
// so they are not immediately deleted but may be "resurrected" if they
// have not yet expired from the tracker when they are needed again.
// See the custom AddRef/Release methods in gfxFont.
gfxFont* MOZ_UNSAFE_REF("tracking for deferred deletion") mFont;
};
nsTHashtable<HashEntry> mFonts;
@ -543,7 +547,7 @@ public:
/**
* This record contains all the parameters needed to initialize a textrun.
*/
struct Parameters {
struct MOZ_STACK_CLASS Parameters {
// Shape text params suggesting where the textrun will be rendered
DrawTarget *mDrawTarget;
// Pointer to arbitrary user data (which should outlive the textrun)
@ -2221,7 +2225,7 @@ protected:
// The TextRunDrawParams are set up once per textrun; the FontDrawParams
// are dependent on the specific font, so they are set per GlyphRun.
struct TextRunDrawParams {
struct MOZ_STACK_CLASS TextRunDrawParams {
RefPtr<mozilla::gfx::DrawTarget> dt;
gfxContext *context;
gfxFont::Spacing *spacing;
@ -2240,7 +2244,7 @@ struct TextRunDrawParams {
bool paintSVGGlyphs;
};
struct FontDrawParams {
struct MOZ_STACK_CLASS FontDrawParams {
RefPtr<mozilla::gfx::ScaledFont> scaledFont;
RefPtr<mozilla::gfx::GlyphRenderingOptions> renderingOptions;
mozilla::SVGContextPaint *contextPaint;
@ -2254,7 +2258,7 @@ struct FontDrawParams {
bool haveColorGlyphs;
};
struct EmphasisMarkDrawParams {
struct MOZ_STACK_CLASS EmphasisMarkDrawParams {
gfxContext* context;
gfxFont::Spacing* spacing;
gfxTextRun* mark;

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

@ -45,8 +45,12 @@ protected:
gr_font *mGrFont; // owned by the shaper itself
struct CallbackData {
gfxFont* mFont;
mozilla::gfx::DrawTarget* mDrawTarget;
// mFont is a pointer to the font that owns this shaper, so it will
// remain valid throughout our lifetime
gfxFont* MOZ_NON_OWNING_REF mFont;
// initialized to a DrawTarget owned by our caller on every call to
// ShapeText
mozilla::gfx::DrawTarget* MOZ_NON_OWNING_REF mDrawTarget;
};
CallbackData mCallbackData;

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

@ -23,7 +23,9 @@ public:
*/
struct FontCallbackData {
gfxHarfBuzzShaper* mShaper;
mozilla::gfx::DrawTarget* mDrawTarget;
// initialized to a DrawTarget owned by our caller on every call to
// ShapeText
mozilla::gfx::DrawTarget* MOZ_NON_OWNING_REF mDrawTarget;
};
bool Initialize();

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

@ -67,7 +67,9 @@ public:
enum { ALLOW_MEMMOVE = true };
protected:
gfxCharacterMap *mCharMap;
// charMaps are not owned by the shared cmap cache, but it will be notified
// by gfxCharacterMap::Release() when an entry is about to be deleted
gfxCharacterMap* MOZ_NON_OWNING_REF mCharMap;
};
// gfxPlatformFontList is an abstract class for the global font list on the system;

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

@ -140,7 +140,9 @@ private:
nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
hb_blob_t *mSVGData;
gfxFontEntry *mFontEntry;
// pointer to the font entry that owns this gfxSVGGlyphs object
gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry;
const struct Header {
mozilla::AutoSwap_PRUint16 mVersion;

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

@ -561,7 +561,7 @@ HasNonOpaqueNonTransparentColor(gfxContext *aContext, Color& aCurrentColorOut)
}
// helper class for double-buffering drawing with non-opaque color
struct BufferAlphaColor {
struct MOZ_STACK_CLASS BufferAlphaColor {
explicit BufferAlphaColor(gfxContext *aContext)
: mContext(aContext)
{

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

@ -241,7 +241,7 @@ public:
virtual uint32_t GetAppUnitsPerDevUnit() const = 0;
};
struct DrawParams
struct MOZ_STACK_CLASS DrawParams
{
gfxContext* context;
DrawMode drawMode = DrawMode::GLYPH_FILL;
@ -464,7 +464,7 @@ public:
uint8_t mMatchType;
};
class GlyphRunIterator {
class MOZ_STACK_CLASS GlyphRunIterator {
public:
GlyphRunIterator(const gfxTextRun *aTextRun, Range aRange)
: mTextRun(aTextRun)
@ -813,8 +813,12 @@ private:
}
void *mUserData;
gfxFontGroup *mFontGroup; // addrefed on creation, but our reference
// may be released by ReleaseFontGroup()
// mFontGroup is usually a strong reference, but refcounting is managed
// manually because it may be explicitly released by ReleaseFontGroup()
// in the case where the font group actually owns the textrun.
gfxFontGroup* MOZ_OWNING_REF mFontGroup;
gfxSkipChars mSkipChars;
nsTextFrameUtils::Flags mFlags2; // additional flags (see also gfxShapedText::mFlags)
@ -1129,8 +1133,10 @@ protected:
RefPtr<gfxFontFamily> mFamily;
// either a font or a font entry exists
union {
gfxFont* mFont;
gfxFontEntry* mFontEntry;
// Whichever of these fields is actually present will be a strong
// reference, with refcounting handled manually.
gfxFont* MOZ_OWNING_REF mFont;
gfxFontEntry* MOZ_OWNING_REF mFontEntry;
};
bool mNeedsBold : 1;
bool mFontCreated : 1;

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

@ -171,7 +171,7 @@ gfxUserFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeeds
return nullptr;
}
class gfxOTSContext : public ots::OTSContext {
class MOZ_STACK_CLASS gfxOTSContext : public ots::OTSContext {
public:
explicit gfxOTSContext(gfxUserFontEntry* aUserFontEntry)
: mUserFontEntry(aUserFontEntry)

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

@ -746,7 +746,7 @@ protected:
// This field is managed by the nsFontFaceLoader. In the destructor and Cancel()
// methods of nsFontFaceLoader this reference is nulled out.
nsFontFaceLoader* MOZ_NON_OWNING_REF mLoader; // current loader for this entry, if any
gfxUserFontSet* mFontSet; // font-set which owns this userfont entry
gfxUserFontSet* MOZ_NON_OWNING_REF mFontSet; // font-set which owns this userfont entry
RefPtr<gfxFontSrcPrincipal> mPrincipal;
};

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

@ -785,7 +785,7 @@ pub unsafe extern "C" fn wr_api_set_root_display_list(dh: &mut DocumentHandle,
let color = if color.a == 0.0 {
None
} else {
Some(color.into())
Some(color)
};
// See the documentation of set_display_list in api.rs. I don't think
// it makes a difference in gecko at the moment(until APZ is figured out)
@ -802,7 +802,7 @@ pub unsafe extern "C" fn wr_api_set_root_display_list(dh: &mut DocumentHandle,
epoch,
color,
LayoutSize::new(viewport_width, viewport_height),
(pipeline_id, content_size.into(), dl),
(pipeline_id, content_size, dl),
preserve_frame_state,
ResourceUpdates::new());
}
@ -929,7 +929,7 @@ impl WebRenderFrameBuilder {
content_size: LayoutSize) -> WebRenderFrameBuilder {
WebRenderFrameBuilder {
root_pipeline_id: root_pipeline_id,
dl_builder: webrender_api::DisplayListBuilder::new(root_pipeline_id, content_size.into()),
dl_builder: webrender_api::DisplayListBuilder::new(root_pipeline_id, content_size),
scroll_clips_defined: HashSet::new(),
}
}
@ -1004,8 +1004,6 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
filter_count: usize) {
assert!(unsafe { !is_in_render_thread() });
let bounds = bounds.into();
let c_filters = make_slice(filters, filter_count);
let mut filters : Vec<FilterOp> = c_filters.iter().map(|c_filter| {
match c_filter.filter_type {
@ -1063,13 +1061,12 @@ pub extern "C" fn wr_dp_pop_stacking_context(state: &mut WrState) {
#[no_mangle]
pub extern "C" fn wr_dp_define_clip(state: &mut WrState,
rect: LayoutRect,
clip_rect: LayoutRect,
complex: *const WrComplexClipRegion,
complex_count: usize,
mask: *const WrImageMask)
-> u64 {
assert!(unsafe { is_in_main_thread() });
let clip_rect: LayoutRect = rect.into();
let complex_slice = make_slice(complex, complex_count);
let complex_iter = complex_slice.iter().map(|x| x.into());
let mask : Option<ImageMask> = unsafe { mask.as_ref() }.map(|x| x.into());
@ -1109,8 +1106,6 @@ pub extern "C" fn wr_dp_push_scroll_layer(state: &mut WrState,
// Avoid defining multiple scroll clips with the same clip id, as that
// results in undefined behaviour or assertion failures.
if !state.frame_builder.scroll_clips_defined.contains(&clip_id) {
let content_rect: LayoutRect = content_rect.into();
let clip_rect: LayoutRect = clip_rect.into();
state.frame_builder.dl_builder.define_scroll_frame(
Some(clip_id), content_rect, clip_rect, vec![], None,
@ -1133,7 +1128,7 @@ pub extern "C" fn wr_scroll_layer_with_id(dh: &mut DocumentHandle,
new_scroll_origin: LayoutPoint) {
assert!(unsafe { is_in_compositor_thread() });
let clip_id = ClipId::new(scroll_id, pipeline_id);
dh.api.scroll_node_with_id(dh.document_id, new_scroll_origin.into(), clip_id, ScrollClamping::NoClamping);
dh.api.scroll_node_with_id(dh.document_id, new_scroll_origin, clip_id, ScrollClamping::NoClamping);
}
#[no_mangle]
@ -1164,7 +1159,7 @@ pub extern "C" fn wr_dp_push_iframe(state: &mut WrState,
pipeline_id: WrPipelineId) {
assert!(unsafe { is_in_main_thread() });
state.frame_builder.dl_builder.push_iframe(rect.into(), None, pipeline_id);
state.frame_builder.dl_builder.push_iframe(rect, None, pipeline_id);
}
#[no_mangle]
@ -1174,9 +1169,9 @@ pub extern "C" fn wr_dp_push_rect(state: &mut WrState,
color: ColorF) {
assert!(unsafe { !is_in_render_thread() });
state.frame_builder.dl_builder.push_rect(rect.into(),
Some(LocalClip::Rect(clip.into())),
color.into());
state.frame_builder.dl_builder.push_rect(rect,
Some(LocalClip::Rect(clip)),
color);
}
#[no_mangle]
@ -1191,10 +1186,10 @@ pub extern "C" fn wr_dp_push_image(state: &mut WrState,
state.frame_builder
.dl_builder
.push_image(bounds.into(),
Some(LocalClip::Rect(clip.into())),
stretch_size.into(),
tile_spacing.into(),
.push_image(bounds,
Some(LocalClip::Rect(clip)),
stretch_size,
tile_spacing,
image_rendering,
key);
}
@ -1213,7 +1208,7 @@ pub extern "C" fn wr_dp_push_yuv_planar_image(state: &mut WrState,
state.frame_builder
.dl_builder
.push_yuv_image(bounds.into(),
.push_yuv_image(bounds,
Some(LocalClip::Rect(clip.into())),
YuvData::PlanarYCbCr(image_key_0, image_key_1, image_key_2),
color_space,
@ -1233,7 +1228,7 @@ pub extern "C" fn wr_dp_push_yuv_NV12_image(state: &mut WrState,
state.frame_builder
.dl_builder
.push_yuv_image(bounds.into(),
.push_yuv_image(bounds,
Some(LocalClip::Rect(clip.into())),
YuvData::NV12(image_key_0, image_key_1),
color_space,
@ -1252,7 +1247,7 @@ pub extern "C" fn wr_dp_push_yuv_interleaved_image(state: &mut WrState,
state.frame_builder
.dl_builder
.push_yuv_image(bounds.into(),
.push_yuv_image(bounds,
Some(LocalClip::Rect(clip.into())),
YuvData::InterleavedYCbCr(image_key_0),
color_space,
@ -1277,7 +1272,7 @@ pub extern "C" fn wr_dp_push_text(state: &mut WrState,
let glyph_options = None; // TODO
state.frame_builder
.dl_builder
.push_text(bounds.into(),
.push_text(bounds,
Some(LocalClip::Rect(clip.into())),
&glyph_slice,
font_key,
@ -1307,9 +1302,9 @@ pub extern "C" fn wr_dp_push_border(state: &mut WrState,
});
state.frame_builder
.dl_builder
.push_border(rect.into(),
.push_border(rect,
Some(LocalClip::Rect(clip.into())),
widths.into(),
widths,
border_details);
}
@ -1465,11 +1460,11 @@ pub extern "C" fn wr_dp_push_radial_gradient(state: &mut WrState,
extend_mode.into());
state.frame_builder
.dl_builder
.push_radial_gradient(rect.into(),
.push_radial_gradient(rect,
Some(LocalClip::Rect(clip.into())),
gradient,
tile_size.into(),
tile_spacing.into());
tile_size,
tile_spacing);
}
#[no_mangle]
@ -1487,11 +1482,11 @@ pub extern "C" fn wr_dp_push_box_shadow(state: &mut WrState,
state.frame_builder
.dl_builder
.push_box_shadow(rect.into(),
.push_box_shadow(rect,
Some(LocalClip::Rect(clip.into())),
box_bounds.into(),
box_bounds,
offset,
color.into(),
color,
blur_radius,
spread_radius,
border_radius,

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

@ -774,7 +774,7 @@ WR_FUNC;
WR_INLINE
uint64_t wr_dp_define_clip(WrState *aState,
LayoutRect aRect,
LayoutRect aClipRect,
const WrComplexClipRegion *aComplex,
size_t aComplexCount,
const WrImageMask *aMask)

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

@ -157,13 +157,15 @@ ImageResource::SendOnUnlockedDraw(uint32_t aFlags)
mProgressTracker->OnUnlockedDraw();
} else {
NotNull<RefPtr<ImageResource>> image = WrapNotNull(this);
NS_DispatchToMainThread(NS_NewRunnableFunction(
nsCOMPtr<nsIEventTarget> eventTarget = mProgressTracker->GetEventTarget();
nsCOMPtr<nsIRunnable> ev = NS_NewRunnableFunction(
"image::ImageResource::SendOnUnlockedDraw", [=]() -> void {
RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
if (tracker) {
tracker->OnUnlockedDraw();
}
}));
});
eventTarget->Dispatch(ev.forget(), NS_DISPATCH_NORMAL);
}
}

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

@ -456,12 +456,20 @@ RasterImage::OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey)
bool animatedFramesDiscarded =
mAnimationState && aSurfaceKey.Playback() == PlaybackType::eAnimated;
nsCOMPtr<nsIEventTarget> eventTarget;
if (mProgressTracker) {
eventTarget = mProgressTracker->GetEventTarget();
} else {
eventTarget = do_GetMainThread();
}
RefPtr<RasterImage> image = this;
NS_DispatchToMainThread(NS_NewRunnableFunction(
nsCOMPtr<nsIRunnable> ev = NS_NewRunnableFunction(
"RasterImage::OnSurfaceDiscarded",
[=]() -> void {
image->OnSurfaceDiscardedInternal(animatedFramesDiscarded);
}));
});
eventTarget->Dispatch(ev.forget(), NS_DISPATCH_NORMAL);
}
void

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

@ -246,11 +246,11 @@ public:
bool IsEmpty() const { return mSurfaces.Count() == 0; }
void Insert(NotNull<CachedSurface*> aSurface)
MOZ_MUST_USE bool Insert(NotNull<CachedSurface*> aSurface)
{
MOZ_ASSERT(!mLocked || aSurface->IsPlaceholder() || aSurface->IsLocked(),
"Inserting an unlocked surface for a locked image");
mSurfaces.Put(aSurface->GetSurfaceKey(), aSurface);
return mSurfaces.Put(aSurface->GetSurfaceKey(), aSurface, fallible);
}
void Remove(NotNull<CachedSurface*> aSurface)
@ -480,7 +480,8 @@ public:
// We require that locking succeed if the image is locked and we're not
// inserting a placeholder; the caller may need to know this to handle
// errors correctly.
if (cache->IsLocked() && !surface->IsPlaceholder()) {
bool mustLock = cache->IsLocked() && !surface->IsPlaceholder();
if (mustLock) {
surface->SetLocked(true);
if (!surface->IsLocked()) {
return InsertOutcome::FAILURE;
@ -489,9 +490,14 @@ public:
// Insert.
MOZ_ASSERT(cost <= mAvailableCost, "Inserting despite too large a cost");
cache->Insert(surface);
StartTracking(surface, aAutoLock);
if (!cache->Insert(surface)) {
if (mustLock) {
surface->SetLocked(false);
}
return InsertOutcome::FAILURE;
}
StartTracking(surface, aAutoLock);
return InsertOutcome::SUCCESS;
}
@ -909,7 +915,8 @@ private:
explicit SurfaceTracker(uint32_t aSurfaceCacheExpirationTimeMS)
: ExpirationTrackerImpl<CachedSurface, 2,
StaticMutex, StaticMutexAutoLock>(
aSurfaceCacheExpirationTimeMS, "SurfaceTracker")
aSurfaceCacheExpirationTimeMS, "SurfaceTracker",
SystemGroup::EventTargetFor(TaskCategory::Other))
{ }
protected:

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

@ -1104,7 +1104,8 @@ protected:
imgCacheExpirationTracker::imgCacheExpirationTracker()
: nsExpirationTracker<imgCacheEntry, 3>(TIMEOUT_SECONDS * 1000,
"imgCacheExpirationTracker")
"imgCacheExpirationTracker",
SystemGroup::EventTargetFor(TaskCategory::Other))
{ }
void

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

@ -347,7 +347,10 @@ imgRequest::Cancel(nsresult aStatus)
if (NS_IsMainThread()) {
ContinueCancel(aStatus);
} else {
NS_DispatchToMainThread(new imgRequestMainThreadCancel(this, aStatus));
RefPtr<ProgressTracker> progressTracker = GetProgressTracker();
nsCOMPtr<nsIEventTarget> eventTarget = progressTracker->GetEventTarget();
nsCOMPtr<nsIRunnable> ev = new imgRequestMainThreadCancel(this, aStatus);
eventTarget->Dispatch(ev.forget(), NS_DISPATCH_NORMAL);
}
}
@ -1141,22 +1144,35 @@ imgRequest::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
if (result.mImage) {
image = result.mImage;
nsCOMPtr<nsIEventTarget> eventTarget;
// Update our state to reflect this new part.
{
MutexAutoLock lock(mMutex);
mImage = image;
// We only get an event target if we are not on the main thread, because
// we have to dispatch in that case. If we are on the main thread, but
// on a different scheduler group than ProgressTracker would give us,
// that is okay because nothing in imagelib requires that, just our
// listeners (which have their own checks).
if (!NS_IsMainThread()) {
eventTarget = mProgressTracker->GetEventTarget();
MOZ_ASSERT(eventTarget);
}
mProgressTracker = nullptr;
}
// Some property objects are not threadsafe, and we need to send
// OnImageAvailable on the main thread, so finish on the main thread.
if (NS_IsMainThread()) {
if (!eventTarget) {
MOZ_ASSERT(NS_IsMainThread());
FinishPreparingForNewPart(result);
} else {
nsCOMPtr<nsIRunnable> runnable =
new FinishPreparingForNewPartRunnable(this, Move(result));
NS_DispatchToMainThread(runnable);
eventTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
}
}

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

@ -0,0 +1,52 @@
// Check that setters throw TypeError when passed no arguments, instead of crashing.
function check(obj) {
let proto = Object.getPrototypeOf(obj);
let props = Object.getOwnPropertyNames(proto);
for (let prop of props) {
let desc = Object.getOwnPropertyDescriptor(proto, prop);
if (desc.set) {
print("bleah: " + uneval(prop));
assertEq(typeof desc.set, 'function');
try {
desc.set.call(obj);
assertEq("should have thrown TypeError", false);
} catch (e) {
assertEq(e instanceof TypeError, true);
}
}
}
}
var dbg = new Debugger;
var g = newGlobal();
var gw = dbg.addDebuggee(g);
// Debugger
check(dbg);
// Debugger.Memory
check(dbg.memory);
// Debugger.Object
g.eval('function f() { debugger; }');
var fw = gw.getOwnPropertyDescriptor('f').value;
check(fw);
// Debugger.Script
check(fw.script);
// Debugger.Source
check(fw.script.source);
// Debugger.Environment
check(fw.environment);
// Debugger.Frame
var log = '';
dbg.onDebuggerStatement = function(frame) {
log += 'd';
check(frame);
}
g.eval('f()');
assertEq(log, 'd');

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

@ -7641,9 +7641,11 @@ DebuggerSource_getIntroductionType(JSContext* cx, unsigned argc, Value* vp)
static bool
DebuggerSource_setSourceMapURL(JSContext* cx, unsigned argc, Value* vp)
{
THIS_DEBUGSOURCE_SOURCE(cx, argc, vp, "sourceMapURL", args, obj, sourceObject);
THIS_DEBUGSOURCE_SOURCE(cx, argc, vp, "set sourceMapURL", args, obj, sourceObject);
ScriptSource* ss = sourceObject->source();
MOZ_ASSERT(ss);
if (!args.requireAtLeast(cx, "set sourceMapURL", 1))
return false;
JSString* str = ToString<CanGC>(cx, args[0]);
if (!str)

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

@ -1706,6 +1706,12 @@ AssembleSandboxMemoryReporterName(JSContext* cx, nsCString& sandboxName)
// Use a default name when the caller did not provide a sandboxName.
if (sandboxName.IsEmpty())
sandboxName = NS_LITERAL_CSTRING("[anonymous sandbox]");
#ifndef DEBUG
// Adding the caller location is fairly expensive, so in non-debug builds,
// only add it if we don't have an explicit sandbox name.
else
return NS_OK;
#endif
// Get the xpconnect native call context.
XPCCallContext* cc = XPCJSContext::Get()->GetCallContext();

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

@ -251,16 +251,23 @@ bool CompartmentPrivate::TryParseLocationURI(CompartmentPrivate::LocationHint aL
return false;
// Handle Sandbox location strings.
// A sandbox string looks like this:
// A sandbox string looks like this, for anonymous sandboxes, and builds
// where Sandbox location tagging is enabled:
//
// <sandboxName> (from: <js-stack-frame-filename>:<lineno>)
//
// where <sandboxName> is user-provided via Cu.Sandbox()
// and <js-stack-frame-filename> and <lineno> is the stack frame location
// from where Cu.Sandbox was called.
//
// Otherwise, it is simply the caller-provided name, which is usually a URI.
//
// <js-stack-frame-filename> furthermore is "free form", often using a
// "uri -> uri -> ..." chain. The following code will and must handle this
// common case.
//
// It should be noted that other parts of the code may already rely on the
// "format" of these strings, such as the add-on SDK.
// "format" of these strings.
static const nsDependentCString from("(from: ");
static const nsDependentCString arrow(" -> ");

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

@ -10,10 +10,12 @@
#include "jsprf.h"
#include "nsArrayEnumerator.h"
#include "nsContentUtils.h"
#include "nsINamed.h"
#include "nsIScriptError.h"
#include "nsWrapperCache.h"
#include "AccessCheck.h"
#include "nsJSUtils.h"
#include "nsPrintfCString.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/DOMException.h"
@ -449,6 +451,97 @@ NS_DEFINE_STATIC_IID_ACCESSOR(WrappedJSIdentity,
/***************************************************************************/
namespace {
class WrappedJSNamed final : public nsINamed
{
nsCString mName;
~WrappedJSNamed() {}
public:
NS_DECL_ISUPPORTS
explicit WrappedJSNamed(const nsACString& aName) : mName(aName) {}
NS_IMETHOD GetName(nsACString& aName) override
{
aName = mName;
aName.AppendLiteral(":JS");
return NS_OK;
}
};
NS_IMPL_ISUPPORTS(WrappedJSNamed, nsINamed)
nsCString
GetFunctionName(JSContext* cx, HandleObject obj)
{
RootedObject inner(cx, js::UncheckedUnwrap(obj));
JSAutoCompartment ac(cx, inner);
RootedFunction fun(cx, JS_GetObjectFunction(inner));
if (!fun) {
// If the object isn't a function, it's likely that it has a single
// function property (for things like nsITimerCallback). In this case,
// return the name of that function property.
Rooted<IdVector> idArray(cx, IdVector(cx));
if (!JS_Enumerate(cx, inner, &idArray)) {
JS_ClearPendingException(cx);
return nsCString("error");
}
if (idArray.length() != 1)
return nsCString("nonfunction");
RootedId id(cx, idArray[0]);
RootedValue v(cx);
if (!JS_GetPropertyById(cx, inner, id, &v)) {
JS_ClearPendingException(cx);
return nsCString("nonfunction");
}
if (!v.isObject())
return nsCString("nonfunction");
RootedObject vobj(cx, &v.toObject());
return GetFunctionName(cx, vobj);
}
RootedString funName(cx, JS_GetFunctionDisplayId(fun));
RootedScript script(cx, JS_GetFunctionScript(cx, fun));
const char* filename = script ? JS_GetScriptFilename(script) : "anonymous";
const char* filenameSuffix = strrchr(filename, '/');
if (filenameSuffix) {
filenameSuffix++;
} else {
filenameSuffix = filename;
}
nsCString displayName("anonymous");
if (funName) {
nsCString* displayNamePtr = &displayName;
RootedValue funNameVal(cx, StringValue(funName));
if (!XPCConvert::JSData2Native(&displayNamePtr, funNameVal, nsXPTType::T_UTF8STRING,
nullptr, nullptr))
{
JS_ClearPendingException(cx);
return nsCString("anonymous");
}
}
displayName.Append('[');
displayName.Append(filenameSuffix, strlen(filenameSuffix));
displayName.Append(']');
return displayName;
}
} // anonymous namespace
/***************************************************************************/
// static
bool
nsXPCWrappedJSClass::IsWrappedJS(nsISupports* aPtr)
@ -590,6 +683,16 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self,
}
}
// If we're asked to QI to nsINamed, we pretend that this is possible. We'll
// try to return a name that makes sense for the wrapped JS value.
if (aIID.Equals(NS_GET_IID(nsINamed))) {
RootedObject obj(RootingCx(), self->GetJSObject());
nsCString name = GetFunctionName(ccx, obj);
RefPtr<WrappedJSNamed> named = new WrappedJSNamed(name);
*aInstancePtr = named.forget().take();
return NS_OK;
}
// else...
// no can do
*aInstancePtr = nullptr;

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

@ -0,0 +1,41 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
var Cu = Components.utils;
var Cc = Components.classes;
var Ci = Components.interfaces;
function callback() {}
let sandbox = Cu.Sandbox(this);
let callbackWrapped = Cu.evalInSandbox("(function wrapped() {})", sandbox);
function run_test() {
let functions = [
[{ notify: callback }, "callback[test_function_names.js]:JS"],
[{ notify: { notify: callback } }, "callback[test_function_names.js]:JS"],
[callback, "callback[test_function_names.js]:JS"],
[function() {}, "run_test/functions<[test_function_names.js]:JS"],
[function foobar() {}, "foobar[test_function_names.js]:JS"],
[function Δ() {}, "Δ[test_function_names.js]:JS"],
[{ notify1: callback, notify2: callback }, "nonfunction:JS"],
[{ notify: 10 }, "nonfunction:JS"],
[{}, "nonfunction:JS"],
[{ notify: callbackWrapped }, "wrapped[test_function_names.js]:JS"],
];
// Use the observer service so we can get double-wrapped functions.
var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
function observer(subject, topic, data)
{
let named = subject.QueryInterface(Ci.nsINamed);
do_check_eq(named.name, data);
dump(`name: ${named.name}\n`);
}
obs.addObserver(observer, "test-obs-fun", false);
for (let [f, requiredName] of functions) {
obs.notifyObservers(f, "test-obs-fun", requiredName);
}
}

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

@ -136,3 +136,4 @@ head = head_watchdog.js
[test_xray_regexp.js]
[test_resolve_dead_promise.js]
[test_asyncLoadSubScriptError.js]
[test_function_names.js]

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

@ -159,8 +159,8 @@ HTTP == background-referrer.html background-referrer-ref.html
== attachment-local-clipping-color-1.html attachment-local-clipping-color-1-ref.html
== attachment-local-clipping-color-2.html attachment-local-clipping-color-1-ref.html # Same ref as the previous test.
== attachment-local-clipping-color-3.html attachment-local-clipping-color-3-ref.html
fuzzy-if(skiaContent,1,300) fuzzy-if(webrender,14-14,1134-1134) == attachment-local-clipping-color-4.html attachment-local-clipping-color-4-ref.html
fuzzy-if(skiaContent,1,400) fuzzy-if(webrender,14-14,1134-1134) == attachment-local-clipping-color-5.html attachment-local-clipping-color-4-ref.html
fuzzy-if(skiaContent,1,300) fuzzy-if(webrender,14-14,1119-1134) == attachment-local-clipping-color-4.html attachment-local-clipping-color-4-ref.html
fuzzy-if(skiaContent,1,400) fuzzy-if(webrender,14-14,1119-1134) == attachment-local-clipping-color-5.html attachment-local-clipping-color-4-ref.html
fuzzy(50,500) fuzzy-if(skiaContent,51,320) fails-if(webrender) == attachment-local-clipping-color-6.html attachment-local-clipping-color-6-ref.html
== attachment-local-clipping-image-1.html attachment-local-clipping-image-1-ref.html

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

@ -52,7 +52,7 @@ fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) == clipping-5-image.html
fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) fuzzy-if(skiaContent,1,77) == clipping-5-overflow-hidden.html clipping-5-ref.html
fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) fuzzy-if(Android,5,21) fuzzy-if(skiaContent,1,97) == clipping-5-refi.html clipping-5-ref.html
fuzzy-if(true,1,7) fuzzy-if(d2d,48,94) fuzzy-if(cocoaWidget,1,99) fuzzy-if(Android,99,115) fuzzy-if(skiaContent,1,77) == clipping-5-refc.html clipping-5-ref.html # bug 732535
fuzzy-if(winWidget,105,71) fuzzy-if(Android,8,469) fuzzy-if(skiaContent,7,58) fuzzy-if(d3d11&&advancedLayers,120,319) fuzzy-if(webrender,7-7,62-62) fuzzy-if(winWidget&&stylo,137,226-319) == clipping-6.html clipping-6-ref.html # PaintedLayer and MaskLayer with transforms that aren't identical
fuzzy-if(winWidget,105,71) fuzzy-if(Android,8,469) fuzzy-if(skiaContent,7,58) fuzzy-if(d3d11&&advancedLayers,120,319) fuzzy-if(webrender,7-7,59-62) fuzzy-if(winWidget&&stylo,137,226-319) == clipping-6.html clipping-6-ref.html # PaintedLayer and MaskLayer with transforms that aren't identical
fuzzy-if(true,2,29) fuzzy-if(d2d,46,50) fuzzy-if(Android,255,586) fuzzy-if(skiaContent,28,96) == clipping-7.html clipping-7-ref.html # ColorLayer and MaskLayer with transforms that aren't identical. Reference image rendered without using layers (which causes fuzzy failures).
fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) == clipping-and-zindex-1.html clipping-and-zindex-1-ref.html
fuzzy-if(cocoaWidget,1,4) fuzzy-if(d3d11&&advancedLayers,30,3) == intersecting-clipping-1-canvas.html intersecting-clipping-1-refc.html

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

@ -1138,7 +1138,7 @@ fails-if(!styloVsGecko) == 428810-3e-rtl-insets.html 428810-empty-rtl-insets-ref
== 433700.html 433700-ref.html
== 436356-1.html 436356-1-ref.html
== 436356-2.html 436356-2-ref.html
fuzzy-if(skiaContent,3,1) == 438537-1.html 438537-1-ref.html
fuzzy-if(skiaContent,4,2) == 438537-1.html 438537-1-ref.html
== 438981-1.xhtml about:blank
== 438987-1.html 438987-1-ref.html
fuzzy-if(skiaContent,1,3280) == 438987-2a.html 438987-2-ref.html
@ -1663,7 +1663,7 @@ HTTP(..) == 635639-1.html 635639-1-ref.html
HTTP(..) == 635639-2.html 635639-2-ref.html
random == 637597-1.html 637597-1-ref.html # bug 637597 was never really fixed!
fuzzy-if(Android,8,500) == 637852-1.html 637852-1-ref.html
fuzzy-if(Android,8,500) fuzzy-if(skiaContent,2,1) fuzzy-if(webrender,3,19) == 637852-2.html 637852-2-ref.html
fuzzy-if(Android,8,500) fuzzy-if(skiaContent,3,1) fuzzy-if(webrender,3,19) == 637852-2.html 637852-2-ref.html
fuzzy-if(Android,8,500) == 637852-3.html 637852-3-ref.html
fails-if(webrender&&asyncPan) == 641770-1.html 641770-1-ref.html # bug 1374326 for webrender+APZ
== 641856-1.html 641856-1-ref.html

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

@ -6,7 +6,7 @@
== 318022-1.html 318022-1-ref.html
== 403669-1.html 403669-1-ref.html
== 381497-n.html 381497-f.html
== test-async-print.html 272830-1-ref.html
== test-async-paged.html 272830-1-ref.html
== 129941-1a.html 129941-1-ref.html
== 129941-1b.html 129941-1-ref.html
== 129941-1c.html 129941-1-ref.html

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

@ -565,6 +565,11 @@ pref("apz.overscroll.enabled", true);
pref("apz.touch_move_tolerance", "0.03");
pref("apz.touch_start_tolerance", "0.06");
#ifdef NIGHTLY_BUILD
// Temporary fix of Bug 1390145 for Fennec Nightly
pref("apz.frame_delay.enabled", false);
#endif
pref("layers.progressive-paint", true);
pref("layers.low-precision-buffer", true);
pref("layers.low-precision-resolution", "0.25");

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

@ -131,18 +131,6 @@ public class GeckoAppShell
return extras;
}
@Override
public void uncaughtException(final Thread thread, final Throwable exc) {
if (GeckoThread.isState(GeckoThread.State.EXITING) ||
GeckoThread.isState(GeckoThread.State.EXITED)) {
// We've called System.exit. All exceptions after this point are Android
// berating us for being nasty to it.
return;
}
super.uncaughtException(thread, exc);
}
@Override
public boolean reportException(final Thread thread, final Throwable exc) {
try {

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

@ -79,17 +79,28 @@ public final class HardwareUtils {
return SysInfo.getMemSize();
}
private static String getPreferredAbi() {
String abi = null;
if (Build.VERSION.SDK_INT >= 21) {
abi = Build.SUPPORTED_ABIS[0];
}
if (abi == null) {
abi = Build.CPU_ABI;
}
return abi;
}
public static boolean isARMSystem() {
return Build.CPU_ABI != null && Build.CPU_ABI.equals("armeabi-v7a");
return "armeabi-v7a".equals(getPreferredAbi());
}
public static boolean isARM64System() {
// 64-bit support was introduced in 21.
return Build.VERSION.SDK_INT >= 21 && "arm64-v8a".equals(Build.SUPPORTED_ABIS[0]);
return "arm64-v8a".equals(getPreferredAbi());
}
public static boolean isX86System() {
if (Build.CPU_ABI != null && Build.CPU_ABI.equals("x86")) {
if ("x86".equals(getPreferredAbi())) {
return true;
}
if (Build.VERSION.SDK_INT >= 21) {
@ -109,7 +120,7 @@ public final class HardwareUtils {
// in which case CPU_ABI is not reliable.
return "x86";
}
return Build.CPU_ABI;
return getPreferredAbi();
}
/**
@ -141,7 +152,8 @@ public final class HardwareUtils {
return true;
}
Log.w(LOGTAG, "Unknown app/system ABI combination: " + BuildConfig.MOZ_APP_ABI + " / " + Build.CPU_ABI);
Log.w(LOGTAG, "Unknown app/system ABI combination: " +
BuildConfig.MOZ_APP_ABI + " / " + getRealAbi());
return true;
}
}

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

@ -2020,7 +2020,6 @@ nsSocketTransport::ReleaseFD_Locked(PRFileDesc *fd)
mLock.AssertCurrentThreadOwns();
NS_ASSERTION(mFD == fd, "wrong fd");
SOCKET_LOG(("JIMB: ReleaseFD_Locked: mFDref = %" PRIuPTR "\n", mFDref));
if (--mFDref == 0) {
if (gIOService->IsNetTearingDown() &&

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

@ -18,28 +18,17 @@ pre, #log {
<div id="trailing-space" class="spacer"></div>
<script>
// Pick this number to be comfortably greater than the length of two frames at 60Hz.
var timeSkew = 40;
var topWindowEntries = [];
var iframeWindowEntries = [];
var targetIframe;
var topWindowTimeOnTestStart;
var topWindowTimeBeforeCreatingIframe;
var topWindowTimeBeforeNotification;
var iframeWindowTimeBeforeNotification;
var timeSkew;
function waitFor(numFrames, callback) {
if (numFrames <= 0) {
callback();
return;
}
window.requestAnimationFrame(waitFor.bind(null, numFrames - 1, callback));
}
async_test(function(t) {
topWindowTimeOnTestStart = performance.now();
waitFor(3, function () {
topWindowTimeBeforeCreatingIframe = performance.now();
timeSkew = topWindowTimeBeforeCreatingIframe - topWindowTimeOnTestStart;
t.step_timeout(function() {
targetIframe = document.createElement("iframe");
assert_true(!!targetIframe, "iframe exists");
targetIframe.src = "resources/timestamp-subframe.html";
@ -66,7 +55,7 @@ async_test(function(t) {
runTestCycle(step1, "First rAF after iframe is loaded.");
t.done();
};
});
}, timeSkew);
}, "Check that timestamps correspond to the to execution context that created the observer.");
function step1() {
@ -84,16 +73,14 @@ function step2() {
var topWindowTimeAfterNotification = performance.now();
var iframeWindowTimeAfterNotification = targetIframe.contentWindow.performance.now();
// Test results are only significant if there's a gap between
// top window time and iframe window time.
assert_greater_than(topWindowTimeBeforeNotification, iframeWindowTimeAfterNotification,
"Time ranges for top and iframe windows are disjoint. Times: " +
[topWindowTimeOnTestStart, topWindowTimeBeforeCreatingIframe,
topWindowTimeBeforeNotification, topWindowTimeAfterNotification,
iframeWindowTimeBeforeNotification, iframeWindowTimeAfterNotification,
topWindowEntries[1].time - topWindowTimeBeforeNotification,
iframeWindowEntries[1].time - iframeWindowTimeBeforeNotification
]);
assert_approx_equals(
topWindowEntries[1].time - topWindowTimeBeforeNotification,
iframeWindowEntries[1].time - iframeWindowTimeBeforeNotification,
// Since all intersections are computed in a tight loop between 2 frames,
// an epsilon of 16ms (the length of one frame at 60Hz) turned out to be
// reliable, even at slow frame rates.
16,
"Notification times are relative to the expected time origins");
assert_equals(topWindowEntries.length, 2, "Top window observer has two notifications.");
assert_between_inclusive(

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

@ -41,10 +41,6 @@ Cu.importGlobalProperties(["TextEncoder"]);
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
/* globals processCount */
XPCOMUtils.defineLazyPreferenceGetter(this, "processCount", "dom.ipc.processCount.extension");
XPCOMUtils.defineLazyModuleGetters(this, {
AddonManager: "resource://gre/modules/AddonManager.jsm",
AddonManagerPrivate: "resource://gre/modules/AddonManager.jsm",
@ -75,6 +71,7 @@ XPCOMUtils.defineLazyServiceGetters(this, {
uuidGen: ["@mozilla.org/uuid-generator;1", "nsIUUIDGenerator"],
});
XPCOMUtils.defineLazyPreferenceGetter(this, "processCount", "dom.ipc.processCount.extension");
XPCOMUtils.defineLazyPreferenceGetter(this, "useRemoteWebExtensions",
"extensions.webextensions.remote", false);
@ -231,8 +228,6 @@ var UninstallObserver = {
init() {
if (!this.initialized) {
AddonManager.addAddonListener(this);
XPCOMUtils.defineLazyPreferenceGetter(this, "leaveStorage", LEAVE_STORAGE_PREF, false);
XPCOMUtils.defineLazyPreferenceGetter(this, "leaveUuid", LEAVE_UUID_PREF, false);
this.initialized = true;
}
},
@ -252,7 +247,7 @@ var UninstallObserver = {
return;
}
if (!this.leaveStorage) {
if (!Services.prefs.getBoolPref(LEAVE_STORAGE_PREF, false)) {
// Clear browser.local.storage
AsyncShutdown.profileChangeTeardown.addBlocker(
`Clear Extension Storage ${addon.id}`,
@ -277,7 +272,7 @@ var UninstallObserver = {
Services.perms.removeFromPrincipal(principal, "persistent-storage");
}
if (!this.leaveUuid) {
if (!Services.prefs.getBoolPref(LEAVE_UUID_PREF, false)) {
// Clear the entry in the UUID map
UUIDMap.remove(addon.id);
}
@ -297,6 +292,7 @@ UninstallObserver.init();
this.ExtensionData = class {
constructor(rootURI) {
this.rootURI = rootURI;
this.resourceURL = rootURI.spec;
this.manifest = null;
this.id = null;
@ -529,67 +525,90 @@ this.ExtensionData = class {
let normalized = Schemas.normalize(this.manifest, "manifest.WebExtensionManifest", context);
if (normalized.error) {
this.manifestError(normalized.error);
} else {
return normalized.value;
return null;
}
let manifest = normalized.value;
let id;
try {
if (manifest.applications.gecko.id) {
id = manifest.applications.gecko.id;
}
} catch (e) {
// Errors are handled by the type checks above.
}
let apiNames = new Set();
let dependencies = new Set();
let hostPermissions = new Set();
let permissions = new Set();
for (let perm of manifest.permissions) {
if (perm === "geckoProfiler") {
const acceptedExtensions = Services.prefs.getStringPref("extensions.geckoProfiler.acceptedExtensionIds", "");
if (!acceptedExtensions.split(",").includes(id)) {
this.manifestError("Only whitelisted extensions are allowed to access the geckoProfiler.");
continue;
}
}
let type = classifyPermission(perm);
if (type.origin) {
let matcher = new MatchPattern(perm, {ignorePath: true});
perm = matcher.pattern;
hostPermissions.add(perm);
} else if (type.api) {
apiNames.add(type.api);
}
permissions.add(perm);
}
// An extension always gets permission to its own url.
if (this.id) {
let matcher = new MatchPattern(this.getURL(), {ignorePath: true});
hostPermissions.add(matcher.pattern);
}
for (let api of apiNames) {
dependencies.add(`${api}@experiments.addons.mozilla.org`);
}
// Normalize all patterns to contain a single leading /
let webAccessibleResources = (manifest.web_accessible_resources || [])
.map(path => path.replace(/^\/*/, "/"));
return {apiNames, dependencies, hostPermissions, id, manifest, permissions,
webAccessibleResources};
});
}
// Reads the extension's |manifest.json| file, and stores its
// parsed contents in |this.manifest|.
async loadManifest() {
[this.manifest] = await Promise.all([
let [manifestData] = await Promise.all([
this.parseManifest(),
Management.lazyInit(),
]);
if (!this.manifest) {
if (!manifestData) {
return;
}
try {
// Do not override the add-on id that has been already assigned.
if (!this.id && this.manifest.applications.gecko.id) {
this.id = this.manifest.applications.gecko.id;
}
} catch (e) {
// Errors are handled by the type checks above.
// Do not override the add-on id that has been already assigned.
if (!this.id) {
this.id = manifestData.id;
}
let whitelist = [];
for (let perm of this.manifest.permissions) {
if (perm === "geckoProfiler") {
const acceptedExtensions = Services.prefs.getStringPref("extensions.geckoProfiler.acceptedExtensionIds", "");
if (!acceptedExtensions.split(",").includes(this.id)) {
this.manifestError("Only whitelisted extensions are allowed to access the geckoProfiler.");
continue;
}
}
this.manifest = manifestData.manifest;
this.apiNames = manifestData.apiNames;
this.dependencies = manifestData.dependencies;
this.permissions = manifestData.permissions;
let type = classifyPermission(perm);
if (type.origin) {
let matcher = new MatchPattern(perm, {ignorePath: true});
whitelist.push(matcher);
perm = matcher.pattern;
} else if (type.api) {
this.apiNames.add(type.api);
}
this.permissions.add(perm);
}
// An extension always gets permission to its own url.
if (this.id) {
let matcher = new MatchPattern(this.getURL(), {ignorePath: true});
whitelist.push(matcher);
}
this.whiteListedHosts = new MatchPatternSet(whitelist);
for (let api of this.apiNames) {
this.dependencies.add(`${api}@experiments.addons.mozilla.org`);
}
this.webAccessibleResources = manifestData.webAccessibleResources.map(res => new MatchGlob(res));
this.whiteListedHosts = new MatchPatternSet(manifestData.hostPermissions);
return this.manifest;
}
@ -947,23 +966,24 @@ this.Extension = class extends ExtensionData {
() => super.parseManifest());
}
loadManifest() {
return super.loadManifest().then(manifest => {
if (this.errors.length) {
return Promise.reject({errors: this.errors});
}
async loadManifest() {
let manifest = await super.loadManifest();
if (this.errors.length) {
return Promise.reject({errors: this.errors});
}
if (this.apiNames.size) {
// Load Experiments APIs that this extension depends on.
return Promise.all(
Array.from(this.apiNames, api => ExtensionCommon.ExtensionAPIs.load(api))
).then(apis => {
for (let API of apis) {
this.apis.push(new API(this));
}
let apis = await Promise.all(
Array.from(this.apiNames, api => ExtensionCommon.ExtensionAPIs.load(api)));
return manifest;
});
});
for (let API of apis) {
this.apis.push(new API(this));
}
}
return manifest;
}
// Representation of the extension to send to content
@ -975,9 +995,9 @@ this.Extension = class extends ExtensionData {
uuid: this.uuid,
instanceId: this.instanceId,
manifest: this.manifest,
resourceURL: this.addonData.resourceURI.spec,
resourceURL: this.resourceURL,
baseURL: this.baseURI.spec,
content_scripts: this.manifest.content_scripts || [], // eslint-disable-line camelcase
contentScripts: this.contentScripts,
webAccessibleResources: this.webAccessibleResources.map(res => res.glob),
whiteListedHosts: this.whiteListedHosts.patterns.map(pat => pat.pattern),
localeData: this.localeData.serialize(),
@ -987,6 +1007,10 @@ this.Extension = class extends ExtensionData {
};
}
get contentScripts() {
return this.manifest.content_scripts || [];
}
broadcast(msg, data) {
return new Promise(resolve => {
let {ppmm} = Services;
@ -1075,28 +1099,44 @@ this.Extension = class extends ExtensionData {
return super.initLocale(locale);
}
initUnlimitedStoragePermission() {
const principal = this.principal;
updatePermissions(reason) {
const {principal} = this;
// Check if the site permission has already been set for the extension by the WebExtensions
// internals (instead of being manually allowed by the user).
const hasSitePermission = Services.perms.testPermissionFromPrincipal(
principal, "WebExtensions-unlimitedStorage"
);
const testPermission = perm =>
Services.perms.testPermissionFromPrincipal(principal, perm);
if (this.hasPermission("unlimitedStorage")) {
// Set the indexedDB permission and a custom "WebExtensions-unlimitedStorage" to remember
// that the permission hasn't been selected manually by the user.
Services.perms.addFromPrincipal(principal, "WebExtensions-unlimitedStorage",
Services.perms.ALLOW_ACTION);
Services.perms.addFromPrincipal(principal, "indexedDB", Services.perms.ALLOW_ACTION);
Services.perms.addFromPrincipal(principal, "persistent-storage", Services.perms.ALLOW_ACTION);
} else if (hasSitePermission) {
// Remove the indexedDB permission if it has been enabled using the
// unlimitedStorage WebExtensions permissions.
Services.perms.removeFromPrincipal(principal, "WebExtensions-unlimitedStorage");
Services.perms.removeFromPrincipal(principal, "indexedDB");
Services.perms.removeFromPrincipal(principal, "persistent-storage");
// Only update storage permissions when the extension changes in
// some way.
if (reason !== "APP_STARTUP" && reason !== "APP_SHUTDOWN") {
if (this.hasPermission("unlimitedStorage")) {
// Set the indexedDB permission and a custom "WebExtensions-unlimitedStorage" to remember
// that the permission hasn't been selected manually by the user.
Services.perms.addFromPrincipal(principal, "WebExtensions-unlimitedStorage",
Services.perms.ALLOW_ACTION);
Services.perms.addFromPrincipal(principal, "indexedDB", Services.perms.ALLOW_ACTION);
Services.perms.addFromPrincipal(principal, "persistent-storage", Services.perms.ALLOW_ACTION);
} else {
// Remove the indexedDB permission if it has been enabled using the
// unlimitedStorage WebExtensions permissions.
Services.perms.removeFromPrincipal(principal, "WebExtensions-unlimitedStorage");
Services.perms.removeFromPrincipal(principal, "indexedDB");
Services.perms.removeFromPrincipal(principal, "persistent-storage");
}
}
// Never change geolocation permissions at shutdown, since it uses a
// session-only permission.
if (reason !== "APP_SHUTDOWN") {
if (this.hasPermission("geolocation")) {
if (testPermission("geo") === Services.perms.UNKNOWN_ACTION) {
Services.perms.addFromPrincipal(principal, "geo",
Services.perms.ALLOW_ACTION,
Services.perms.EXPIRE_SESSION);
}
} else if (reason !== "APP_STARTUP" &&
testPermission("geo") === Services.perms.ALLOW_ACTION) {
Services.perms.removeFromPrincipal(principal, "geo");
}
}
}
@ -1160,17 +1200,10 @@ this.Extension = class extends ExtensionData {
{ignorePath: true});
}
// Normalize all patterns to contain a single leading /
let resources = (this.manifest.web_accessible_resources || [])
.map(path => path.replace(/^\/*/, "/"));
this.webAccessibleResources = resources.map(res => new MatchGlob(res));
this.policy.active = false;
this.policy = processScript.initExtension(this.serialize(), this);
this.policy = processScript.initExtension(this);
this.initUnlimitedStoragePermission();
this.updatePermissions(this.startupReason);
// The "startup" Management event sent on the extension instance itself
// is emitted just before the Management "startup" event,
@ -1281,6 +1314,8 @@ this.Extension = class extends ExtensionData {
Services.ppmm.removeMessageListener(this.MESSAGE_EMIT_EVENT, this);
this.updatePermissions(this.shutdownReason);
if (!this.manifest) {
this.policy.active = false;

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

@ -499,7 +499,7 @@ class BrowserExtensionContent extends EventEmitter {
Services.cpmm.addMessageListener(this.MESSAGE_EMIT_EVENT, this);
defineLazyGetter(this, "scripts", () => {
return data.content_scripts.map(scriptData => new ExtensionContent.Script(this, scriptData));
return data.contentScripts.map(scriptData => new ExtensionContent.Script(this, scriptData));
});
this.webAccessibleResources = data.webAccessibleResources.map(res => new MatchGlob(res));

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

@ -941,7 +941,7 @@ class SchemaAPIManager extends EventEmitter {
this._modulesJSONLoaded = false;
this.schemaURLs = new Set();
this.schemaURLs = new Map();
this.apis = new DefaultWeakMap(() => new Map());
@ -1002,7 +1002,10 @@ class SchemaAPIManager extends EventEmitter {
this.modules.set(name, details);
if (details.schema) {
this.schemaURLs.add(details.schema);
let content = (details.scopes &&
(details.scopes.includes("content_parent") ||
details.scopes.includes("content_child")));
this.schemaURLs.set(details.schema, {content});
}
for (let event of details.events || []) {
@ -1245,7 +1248,7 @@ class SchemaAPIManager extends EventEmitter {
_createExtGlobal() {
let global = Cu.Sandbox(Services.scriptSecurityManager.getSystemPrincipal(), {
wantXrays: false,
sandboxName: `Namespace of ext-*.js scripts for ${this.processType}`,
sandboxName: `Namespace of ext-*.js scripts for ${this.processType} (from: resource://gre/modules/ExtensionCommon.jsm)`,
});
Object.assign(global, {global, Cc, Ci, Cu, Cr, XPCOMUtils, ChromeWorker, ExtensionAPI, ExtensionCommon, MatchPattern, MatchPatternSet, StructuredCloneHolder, extensions: this});

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

@ -118,13 +118,13 @@ let apiManager = new class extends SchemaAPIManager {
// Load order matters here. The base manifest defines types which are
// extended by other schemas, so needs to be loaded first.
return Schemas.load(BASE_SCHEMA).then(() => {
return Schemas.load(BASE_SCHEMA, AppConstants.DEBUG).then(() => {
let promises = [];
for (let [/* name */, url] of XPCOMUtils.enumerateCategoryEntries(CATEGORY_EXTENSION_SCHEMAS)) {
promises.push(Schemas.load(url));
}
for (let url of this.schemaURLs) {
promises.push(Schemas.load(url));
for (let [url, {content}] of this.schemaURLs) {
promises.push(Schemas.load(url, content));
}
for (let url of schemaURLs) {
promises.push(Schemas.load(url));
@ -447,7 +447,7 @@ defineLazyGetter(ProxyContextParent.prototype, "apiObj", function() {
});
defineLazyGetter(ProxyContextParent.prototype, "sandbox", function() {
return Cu.Sandbox(this.principal);
return Cu.Sandbox(this.principal, {sandboxName: this.uri.spec});
});
/**
@ -564,17 +564,26 @@ class DevToolsExtensionPageContextParent extends ExtensionPageContextParent {
ParentAPIManager = {
proxyContexts: new Map(),
parentMessageManagers: new Set(),
init() {
Services.obs.addObserver(this, "message-manager-close");
Services.obs.addObserver(this, "ipc:content-created");
Services.mm.addMessageListener("API:CreateProxyContext", this);
Services.mm.addMessageListener("API:CloseProxyContext", this, true);
Services.mm.addMessageListener("API:Call", this);
Services.mm.addMessageListener("API:AddListener", this);
Services.mm.addMessageListener("API:RemoveListener", this);
this.schemaHook = this.schemaHook.bind(this);
},
observe(subject, topic, data) {
attachMessageManager(extension, processMessageManager) {
extension.parentMessageManager = processMessageManager;
},
async observe(subject, topic, data) {
if (topic === "message-manager-close") {
let mm = subject;
for (let [childId, context] of this.proxyContexts) {
@ -589,6 +598,23 @@ ParentAPIManager = {
extension.parentMessageManager = null;
}
}
this.parentMessageManagers.delete(mm);
} else if (topic === "ipc:content-created") {
let mm = subject.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIMessageSender);
if (mm.remoteType === E10SUtils.EXTENSION_REMOTE_TYPE) {
this.parentMessageManagers.add(mm);
mm.sendAsyncMessage("Schema:Add", Schemas.schemaJSON);
Schemas.schemaHook = this.schemaHook;
}
}
},
schemaHook(schemas) {
for (let mm of this.parentMessageManagers) {
mm.sendAsyncMessage("Schema:Add", schemas);
}
},
@ -648,7 +674,7 @@ ParentAPIManager = {
if (!extension.parentMessageManager) {
let expectedRemoteType = extension.remote ? E10SUtils.EXTENSION_REMOTE_TYPE : null;
if (target.remoteType === expectedRemoteType) {
extension.parentMessageManager = processMessageManager;
this.attachMessageManager(extension, processMessageManager);
}
}

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

@ -236,25 +236,38 @@ class EventEmitter {
/**
* Triggers all listeners for the given event, and returns a promise
* which resolves when all listeners have been called, and any
* promises they have returned have likewise resolved.
* Triggers all listeners for the given event. If any listeners return
* a value, returns a promise which resolves when all returned
* promises have resolved. Otherwise, returns undefined.
*
* @param {string} event
* The name of the event to emit.
* @param {any} args
* Arbitrary arguments to pass to the listener functions, after
* the event name.
* @returns {Promise}
* @returns {Promise?}
*/
emit(event, ...args) {
let listeners = this[LISTENERS].get(event) || new Set();
let listeners = this[LISTENERS].get(event);
let promises = Array.from(listeners, listener => {
return runSafeSyncWithoutClone(listener, event, ...args);
});
if (listeners) {
let promises = [];
return Promise.all(promises);
for (let listener of listeners) {
try {
let result = listener(event, ...args);
if (result !== undefined) {
promises.push(result);
}
} catch (e) {
Cu.reportError(e);
}
}
if (promises.length) {
return Promise.all(promises);
}
}
}
}

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

@ -105,16 +105,12 @@ const Cc = Components.classes;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionUtils",
"resource://gre/modules/ExtensionUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
"resource://gre/modules/PromiseUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "MessageManagerProxy",
() => ExtensionUtils.MessageManagerProxy);
const {
MessageManagerProxy,
} = ExtensionUtils;
/**
* Handles the mapping and dispatching of messages to their registered
@ -538,7 +534,11 @@ this.MessageChannel = {
return Promise.resolve(); // Not expecting any reply.
}
let deferred = PromiseUtils.defer();
let deferred = {};
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
});
deferred.sender = recipient;
deferred.messageManager = target;
deferred.channelId = channelId;

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