Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2015-07-10 14:12:39 +02:00
Родитель b85632bb8a faca8471fb
Коммит 90581b5c82
126 изменённых файлов: 1712 добавлений и 649 удалений

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

@ -28,7 +28,7 @@
oncommand="MailIntegration.sendLinkForBrowser(gBrowser.selectedBrowser);"/>
<command id="cmd_pageSetup" oncommand="PrintUtils.showPageSetup();"/>
<command id="cmd_print" oncommand="PrintUtils.print(window.gBrowser.selectedBrowser.contentWindowAsCPOW, window.gBrowser.selectedBrowser);"/>
<command id="cmd_print" oncommand="PrintUtils.printWindow(window.gBrowser.selectedBrowser.outerWindowID, window.gBrowser.selectedBrowser);"/>
<command id="cmd_printPreview" oncommand="PrintUtils.printPreview(PrintPreviewListener);"/>
<command id="cmd_close" oncommand="BrowserCloseTabOrWindow()" reserved="true"/>
<command id="cmd_closeWindow" oncommand="BrowserTryToCloseWindow()" reserved="true"/>

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

@ -3,7 +3,10 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
let TrackingProtection = {
PREF_ENABLED: "privacy.trackingprotection.enabled",
PREF_ENABLED_GLOBALLY: "privacy.trackingprotection.enabled",
PREF_ENABLED_IN_PRIVATE_WINDOWS: "privacy.trackingprotection.pbmode.enabled",
enabledGlobally: false,
enabledInPrivateWindows: false,
init() {
let $ = selector => document.querySelector(selector);
@ -11,21 +14,32 @@ let TrackingProtection = {
this.content = $("#tracking-protection-content");
this.updateEnabled();
Services.prefs.addObserver(this.PREF_ENABLED, this, false);
Services.prefs.addObserver(this.PREF_ENABLED_GLOBALLY, this, false);
Services.prefs.addObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this, false);
this.enabledHistogram.add(this.enabled);
this.enabledHistogram.add(this.enabledGlobally);
},
uninit() {
Services.prefs.removeObserver(this.PREF_ENABLED, this);
Services.prefs.removeObserver(this.PREF_ENABLED_GLOBALLY, this);
Services.prefs.removeObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this);
},
observe() {
this.updateEnabled();
},
get enabled() {
return this.enabledGlobally ||
(this.enabledInPrivateWindows &&
PrivateBrowsingUtils.isWindowPrivate(window));
},
updateEnabled() {
this.enabled = Services.prefs.getBoolPref(this.PREF_ENABLED);
this.enabledGlobally =
Services.prefs.getBoolPref(this.PREF_ENABLED_GLOBALLY);
this.enabledInPrivateWindows =
Services.prefs.getBoolPref(this.PREF_ENABLED_IN_PRIVATE_WINDOWS);
this.container.hidden = !this.enabled;
},

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

@ -1787,8 +1787,8 @@ function HandleAppCommandEvent(evt) {
BrowserOpenFileWindow();
break;
case "Print":
PrintUtils.print(gBrowser.selectedBrowser.contentWindowAsCPOW,
gBrowser.selectedBrowser);
PrintUtils.printWindow(gBrowser.selectedBrowser.outerWindowID,
gBrowser.selectedBrowser);
break;
case "Save":
saveDocument(gBrowser.selectedBrowser.contentDocumentAsCPOW);

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

@ -1681,7 +1681,7 @@ nsContextMenu.prototype = {
},
printFrame: function CM_printFrame() {
PrintUtils.print(this.target.ownerDocument.defaultView, this.browser);
PrintUtils.printWindow(this.frameOuterWindowID, this.browser);
},
switchPageDirection: function CM_switchPageDirection() {

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

@ -410,10 +410,17 @@ skip-if = e10s # Bug 1100664 - test relies on linkedBrowser.docShell
[browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js]
run-if = e10s
[browser_trackingUI_1.js]
tags = trackingprotection
support-files =
trackingPage.html
benignPage.html
[browser_trackingUI_2.js]
tags = trackingprotection
support-files =
trackingPage.html
benignPage.html
[browser_trackingUI_3.js]
tags = trackingprotection
support-files =
trackingPage.html
benignPage.html

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

@ -7,34 +7,40 @@
// * A page with no tracking elements is loaded.
// * A page with tracking elements is loaded and they are blocked.
// * A page with tracking elements is loaded and they are not blocked.
// See also Bugs 1175327 and 1043801.
// See also Bugs 1175327, 1043801, 1178985
let PREF = "privacy.trackingprotection.enabled";
let BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html";
let TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html";
const PREF = "privacy.trackingprotection.enabled";
const PB_PREF = "privacy.trackingprotection.pbmode.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html";
let TrackingProtection = null;
let browser = null;
registerCleanupFunction(function() {
TrackingProtection = null;
TrackingProtection = browser = null;
Services.prefs.clearUserPref(PREF);
gBrowser.removeCurrentTab();
Services.prefs.clearUserPref(PB_PREF);
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
function hidden(sel) {
let win = gBrowser.ownerGlobal;
let win = browser.ownerGlobal;
let el = win.document.querySelector(sel);
let display = win.getComputedStyle(el).getPropertyValue("display", null);
return display === "none";
}
function clickButton(sel) {
let win = gBrowser.ownerGlobal;
let win = browser.ownerGlobal;
let el = win.document.querySelector(sel);
el.doCommand();
}
function testBenignPage() {
info("Non-tracking content must not be blocked");
ok (!TrackingProtection.container.hidden, "The container is visible");
ok (!TrackingProtection.content.hasAttribute("block-disabled"), "blocking not disabled");
ok (!TrackingProtection.content.hasAttribute("block-active"), "blocking is not active");
@ -49,6 +55,7 @@ function testBenignPage() {
function testTrackingPage() {
info("Tracking content must be blocked");
ok (!TrackingProtection.container.hidden, "The container is visible");
ok (!TrackingProtection.content.hasAttribute("block-disabled"), "blocking not disabled");
ok (TrackingProtection.content.hasAttribute("block-active"), "blocking is active");
@ -63,6 +70,7 @@ function testTrackingPage() {
function testTrackingPageWhitelisted() {
info("Tracking content must be white-listed and not blocked");
ok (!TrackingProtection.container.hidden, "The container is visible");
ok (TrackingProtection.content.hasAttribute("block-disabled"), "blocking is disabled");
ok (!TrackingProtection.content.hasAttribute("block-active"), "blocking is not active");
@ -75,19 +83,7 @@ function testTrackingPageWhitelisted() {
ok (hidden("#tracking-blocked"), "labelTrackingBlocked is hidden");
}
add_task(function* () {
yield updateTrackingProtectionDatabase();
let tab = gBrowser.selectedTab = gBrowser.addTab();
TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "Functionality is attached to the browser window");
is (TrackingProtection.enabled, Services.prefs.getBoolPref(PREF),
"TP.enabled is based on the original pref value");
Services.prefs.setBoolPref(PREF, true);
ok (TrackingProtection.enabled, "TP is enabled after setting the pref");
function* testTrackingProtectionForTab(tab) {
info("Load a test page not containing tracking elements");
yield promiseTabLoadEvent(tab, BENIGN_PAGE);
testBenignPage();
@ -109,4 +105,45 @@ add_task(function* () {
info("Wait for tab to reload following TP black-listing");
yield promiseTabLoadEvent(tab);
testTrackingPage();
}
add_task(function* testNormalBrowsing() {
yield updateTrackingProtectionDatabase();
browser = gBrowser;
let tab = browser.selectedTab = browser.addTab();
TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the browser window");
is (TrackingProtection.enabled, Services.prefs.getBoolPref(PREF),
"TP.enabled is based on the original pref value");
Services.prefs.setBoolPref(PREF, true);
ok (TrackingProtection.enabled, "TP is enabled after setting the pref");
yield testTrackingProtectionForTab(tab);
Services.prefs.setBoolPref(PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled after setting the pref");
});
add_task(function* testPrivateBrowsing() {
let privateWin = yield promiseOpenAndLoadWindow({private: true}, true);
browser = privateWin.gBrowser;
let tab = browser.selectedTab = browser.addTab();
TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the private window");
is (TrackingProtection.enabled, Services.prefs.getBoolPref(PB_PREF),
"TP.enabled is based on the pb pref value");
Services.prefs.setBoolPref(PB_PREF, true);
ok (TrackingProtection.enabled, "TP is enabled after setting the pref");
yield testTrackingProtectionForTab(tab);
Services.prefs.setBoolPref(PB_PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled after setting the pref");
privateWin.close();
});

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

@ -4,45 +4,73 @@
// Test that the Tracking Protection section is never visible in the
// Control Center when the feature is off.
// See also Bugs 1175327 and 1043801.
// See also Bugs 1175327, 1043801, 1178985.
let PREF = "privacy.trackingprotection.enabled";
let BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html";
let TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html";
const PREF = "privacy.trackingprotection.enabled";
const PB_PREF = "privacy.trackingprotection.pbmode.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html";
let TrackingProtection = null;
let browser = null;
registerCleanupFunction(function() {
TrackingProtection = null;
TrackingProtection = browser = null;
Services.prefs.clearUserPref(PREF);
gBrowser.removeCurrentTab();
Services.prefs.clearUserPref(PB_PREF);
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
function testTrackingPageOff() {
ok (TrackingProtection.container.hidden, "The container is hidden");
}
function testBenignPageOff() {
ok (TrackingProtection.container.hidden, "The container is hidden");
}
add_task(function* () {
add_task(function* testNormalBrowsing() {
yield updateTrackingProtectionDatabase();
let tab = gBrowser.selectedTab = gBrowser.addTab();
browser = gBrowser;
let tab = browser.selectedTab = browser.addTab();
TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the browser window");
is (TrackingProtection.enabled, Services.prefs.getBoolPref(PREF),
"TP.enabled is based on the original pref value");
Services.prefs.setBoolPref(PREF, true);
ok (TrackingProtection.enabled, "TP is enabled after setting the pref");
Services.prefs.setBoolPref(PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled after setting the pref");
info("Load a test page containing tracking elements");
yield promiseTabLoadEvent(tab, TRACKING_PAGE);
testTrackingPageOff();
ok (TrackingProtection.container.hidden, "The container is hidden");
info("Load a test page not containing tracking elements");
yield promiseTabLoadEvent(tab, BENIGN_PAGE);
testBenignPageOff();
ok (TrackingProtection.container.hidden, "The container is hidden");
});
add_task(function* testPrivateBrowsing() {
let privateWin = yield promiseOpenAndLoadWindow({private: true}, true);
browser = privateWin.gBrowser;
let tab = browser.selectedTab = browser.addTab();
TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the private window");
is (TrackingProtection.enabled, Services.prefs.getBoolPref(PB_PREF),
"TP.enabled is based on the pb pref value");
Services.prefs.setBoolPref(PB_PREF, true);
ok (TrackingProtection.enabled, "TP is enabled after setting the pref");
Services.prefs.setBoolPref(PB_PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled after setting the pref");
info("Load a test page containing tracking elements");
yield promiseTabLoadEvent(tab, TRACKING_PAGE);
ok (TrackingProtection.container.hidden, "The container is hidden");
info("Load a test page not containing tracking elements");
yield promiseTabLoadEvent(tab, BENIGN_PAGE);
ok (TrackingProtection.container.hidden, "The container is hidden");
privateWin.close();
});

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

@ -0,0 +1,59 @@
/* 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/. */
// Test that the Tracking Protection is correctly enabled / disabled
// in both normal and private windows given all possible states of the prefs:
// privacy.trackingprotection.enabled
// privacy.trackingprotection.pbmode.enabled
// See also Bug 1178985.
const PREF = "privacy.trackingprotection.enabled";
const PB_PREF = "privacy.trackingprotection.pbmode.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF);
Services.prefs.clearUserPref(PB_PREF);
});
add_task(function* testNormalBrowsing() {
let browser = gBrowser;
let TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the browser window");
Services.prefs.setBoolPref(PREF, true);
Services.prefs.setBoolPref(PB_PREF, false);
ok (TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=false)");
Services.prefs.setBoolPref(PB_PREF, true);
ok (TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=true)");
Services.prefs.setBoolPref(PREF, false);
Services.prefs.setBoolPref(PB_PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled (ENABLED=false,PB=false)");
Services.prefs.setBoolPref(PB_PREF, true);
ok (!TrackingProtection.enabled, "TP is disabled (ENABLED=false,PB=true)");
});
add_task(function* testPrivateBrowsing() {
let privateWin = yield promiseOpenAndLoadWindow({private: true}, true);
let browser = privateWin.gBrowser;
let TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the browser window");
Services.prefs.setBoolPref(PREF, true);
Services.prefs.setBoolPref(PB_PREF, false);
ok (TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=false)");
Services.prefs.setBoolPref(PB_PREF, true);
ok (TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=true)");
Services.prefs.setBoolPref(PREF, false);
Services.prefs.setBoolPref(PB_PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled (ENABLED=false,PB=false)");
Services.prefs.setBoolPref(PB_PREF, true);
ok (TrackingProtection.enabled, "TP is enabled (ENABLED=false,PB=true)");
privateWin.close();
});

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

@ -52,3 +52,43 @@ add_task(function* () {
});
ok(!overlayIsVisible, "overlay should be hidden.");
});
// Test that the overlay cannot be interacted with after the user closes the overlay
add_task(function* () {
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in");
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in");
yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html");
// Work around for delayed PluginBindingAttached
yield promiseUpdatePluginBindings(gBrowser.selectedBrowser);
let overlayHidden = yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
let doc = content.document;
let plugin = doc.getElementById("test");
let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
let closeIcon = doc.getAnonymousElementByAttribute(plugin, "anonid", "closeIcon")
let closeIconBounds = closeIcon.getBoundingClientRect();
let overlayBounds = overlay.getBoundingClientRect();
let overlayLeft = (overlayBounds.left + overlayBounds.right) / 2;
let overlayTop = (overlayBounds.left + overlayBounds.right) / 2 ;
let closeIconLeft = (closeIconBounds.left + closeIconBounds.right) / 2;
let closeIconTop = (closeIconBounds.top + closeIconBounds.bottom) / 2;
let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
// Simulate clicking on the close icon.
utils.sendMouseEvent("mousedown", closeIconLeft, closeIconTop, 0, 1, 0, false, 0, 0);
utils.sendMouseEvent("mouseup", closeIconLeft, closeIconTop, 0, 1, 0, false, 0, 0);
// Simulate clicking on the overlay.
utils.sendMouseEvent("mousedown", overlayLeft, overlayTop, 0, 1, 0, false, 0, 0);
utils.sendMouseEvent("mouseup", overlayLeft, overlayTop, 0, 1, 0, false, 0, 0);
return plugin && !overlay.classList.contains("visible");
});
let notification = PopupNotifications.getNotification("click-to-play-plugins");
ok(notification.dismissed, "No notification should be shown");
ok(overlayHidden, "Overlay should be hidden");
});

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

@ -4,54 +4,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Cu = Components.utils;
const Ci = Components.interfaces;
const Cc = Components.classes;
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let TargetFactory = devtools.TargetFactory;
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
// shared-head.js handles imports, constants, and utility functions
Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/browser/devtools/framework/test/shared-head.js", this);
const BASE_URI = "http://mochi.test:8888/browser/browser/devtools/fontinspector/test/"
// All test are asynchronous
waitForExplicitFinish();
DevToolsUtils.testing = true;
SimpleTest.registerCleanupFunction(() => {
DevToolsUtils.testing = false;
});
registerCleanupFunction(function*() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
yield gDevTools.closeToolbox(target);
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
/**
* Add a new test tab in the browser and load the given url.
* @param {String} url The url to be loaded in the new tab
* @return a promise that resolves to the tab object when the url is loaded
*/
function loadTab(url) {
let deferred = promise.defer();
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
let browser = gBrowser.getBrowserForTab(tab);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
deferred.resolve({tab: tab, browser: browser});
}, true);
return deferred.promise;
}
/**
* Open the toolbox, with the inspector tool visible.
* @param {Function} cb Optional callback, if you don't want to use the returned
@ -114,7 +71,7 @@ let openInspector = Task.async(function*(cb) {
*/
let openFontInspectorForURL = Task.async(function* (url) {
info("Opening tab " + url);
yield loadTab(url);
yield addTab(url);
let { toolbox, inspector } = yield openInspector();

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

@ -13,7 +13,6 @@ thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.doc is undefine
// Tests devtools API
const Cu = Components.utils;
const toolId1 = "test-tool-1";
const toolId2 = "test-tool-2";

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

@ -3,8 +3,6 @@
// Tests devtools API
const Cu = Components.utils;
function test() {
addTab("about:blank").then(runTests);
}

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

@ -3,8 +3,6 @@
// Tests devtools API
const Cu = Components.utils;
let toolbox, target;
let tempScope = {};

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

@ -4,7 +4,6 @@
// Test that the sidebar widget auto-registers existing tabs.
const Cu = Components.utils;
const {ToolSidebar} = devtools.require("devtools/framework/sidebar");
const testToolURL = "data:text/xml;charset=utf8,<?xml version='1.0'?>" +

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

@ -3,12 +3,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This shared-head.js file is used for multiple directories in devtools.
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
const {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {ScratchpadManager} = Cu.import("resource:///modules/devtools/scratchpad-manager.jsm", {});
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {require} = devtools;
const {TargetFactory} = devtools;
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
const promise = require("promise");
const TEST_DIR = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
const CHROME_URL_ROOT = TEST_DIR + "/";
@ -38,13 +42,15 @@ registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.toolbox.previousHost");
});
registerCleanupFunction(function cleanup() {
registerCleanupFunction(function* cleanup() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
yield gDevTools.closeToolbox(target);
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
/**
* Add a new test tab in the browser and load the given url.
* @param {String} url The url to be loaded in the new tab
@ -54,13 +60,12 @@ function addTab(url) {
info("Adding a new tab with URL: '" + url + "'");
let def = promise.defer();
let tab = gBrowser.selectedTab = gBrowser.addTab();
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
info("URL '" + url + "' loading complete");
def.resolve(tab);
}, true);
content.location = url;
return def.promise;
}

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

@ -623,10 +623,13 @@ PluginContent.prototype = {
let plugin = document.getBindingParent(event.target);
let contentWindow = plugin.ownerDocument.defaultView.top;
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
let overlay = this.getPluginUI(plugin, "main");
// Have to check that the target is not the link to update the plugin
if (!(event.originalTarget instanceof contentWindow.HTMLAnchorElement) &&
(event.originalTarget.getAttribute('anonid') != 'closeIcon') &&
event.button == 0 && event.isTrusted) {
overlay.classList.contains('visible') &&
event.button == 0 &&
event.isTrusted) {
this._showClickToPlayNotification(plugin, true);
event.stopPropagation();
event.preventDefault();

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

@ -246,13 +246,15 @@ public:
* still running but we only consider it playing when it is in its active
* interval. This definition is used for fetching the animations that are
* candidates for running on the compositor (since we don't ship animations
* to the compositor when they are in their delay phase or paused).
* to the compositor when they are in their delay phase or paused including
* being effectively paused due to having a zero playback rate).
*/
bool IsPlaying() const
{
// We need to have an effect in its active interval, and
// be either running or waiting to run.
// be either running or waiting to run with a non-zero playback rate.
return HasInPlayEffect() &&
mPlaybackRate != 0.0 &&
(PlayState() == AnimationPlayState::Running ||
mPendingState == PendingState::PlayPending);
}

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

@ -77,6 +77,10 @@ public:
NS_DECL_NSIREQUEST
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIEVENTTARGET
// missing from NS_DECL_NSIEVENTTARGET because MSVC
nsresult Dispatch(nsIRunnable* aEvent, uint32_t aFlags) {
return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
}
explicit WebSocketImpl(WebSocket* aWebSocket)
: mWebSocket(aWebSocket)
@ -2582,7 +2586,7 @@ class WorkerRunnableDispatcher final : public WorkerRunnable
public:
WorkerRunnableDispatcher(WebSocketImpl* aImpl, WorkerPrivate* aWorkerPrivate,
nsIRunnable* aEvent)
already_AddRefed<nsIRunnable>&& aEvent)
: WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
, mWebSocketImpl(aImpl)
, mEvent(aEvent)
@ -2627,11 +2631,19 @@ private:
} // anonymous namespace
NS_IMETHODIMP
WebSocketImpl::Dispatch(nsIRunnable* aEvent, uint32_t aFlags)
WebSocketImpl::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
{
nsCOMPtr<nsIRunnable> event(aEvent);
return Dispatch(event.forget(), aFlags);
}
NS_IMETHODIMP
WebSocketImpl::Dispatch(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aFlags)
{
nsCOMPtr<nsIRunnable> event_ref(aEvent);
// If the target is the main-thread we can just dispatch the runnable.
if (mIsMainThread) {
return NS_DispatchToMainThread(aEvent);
return NS_DispatchToMainThread(event_ref.forget());
}
MutexAutoLock lock(mMutex);
@ -2648,7 +2660,7 @@ WebSocketImpl::Dispatch(nsIRunnable* aEvent, uint32_t aFlags)
// If the target is a worker, we have to use a custom WorkerRunnableDispatcher
// runnable.
nsRefPtr<WorkerRunnableDispatcher> event =
new WorkerRunnableDispatcher(this, mWorkerPrivate, aEvent);
new WorkerRunnableDispatcher(this, mWorkerPrivate, event_ref.forget());
if (!event->Dispatch(nullptr)) {
return NS_ERROR_FAILURE;

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

@ -1629,14 +1629,24 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear,
nsIFrame* contentFrame = content->GetPrimaryFrame();
nsIObjectFrame* objectFrame = do_QueryFrame(contentFrame);
if (aAdjustWidgets && objectFrame && !sTestMode) {
// note that the presshell's widget is being retrieved here, not the one
// for the object frame.
nsViewManager* vm = presShell->GetViewManager();
if (vm) {
nsCOMPtr<nsIWidget> widget;
vm->GetRootWidget(getter_AddRefs(widget));
if (widget)
widget->SetFocus(false);
if (XRE_IsContentProcess()) {
// set focus to the top level window via the chrome process.
nsCOMPtr<nsITabChild> tabChild = do_GetInterface(docShell);
if (tabChild) {
static_cast<TabChild*>(tabChild.get())->SendDispatchFocusToTopLevelWindow();
}
} else {
// note that the presshell's widget is being retrieved here, not the one
// for the object frame.
nsViewManager* vm = presShell->GetViewManager();
if (vm) {
nsCOMPtr<nsIWidget> widget;
vm->GetRootWidget(getter_AddRefs(widget));
if (widget) {
// set focus to the top level window but don't raise it.
widget->SetFocus(false);
}
}
}
}
}

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

@ -230,7 +230,7 @@ public:
* MayStartLayout() until SetMayStartLayout(true) is called on it. Making
* sure this happens is the responsibility of the caller of
* StartDocumentLoad().
*/
*/
virtual nsresult StartDocumentLoad(const char* aCommand,
nsIChannel* aChannel,
nsILoadGroup* aLoadGroup,
@ -356,8 +356,8 @@ public:
}
/**
* Set the document's character encoding. |aCharSetID| should be canonical.
* That is, callers are responsible for the charset alias resolution.
* Set the document's character encoding. |aCharSetID| should be canonical.
* That is, callers are responsible for the charset alias resolution.
*/
virtual void SetDocumentCharacterSet(const nsACString& aCharSetID) = 0;
@ -456,7 +456,7 @@ public:
{
mBidiEnabled = true;
}
/**
* Check if the document contains (or has contained) any MathML elements.
*/
@ -464,7 +464,7 @@ public:
{
return mMathMLEnabled;
}
void SetMathMLEnabled()
{
mMathMLEnabled = true;
@ -477,7 +477,7 @@ public:
{
return mIsInitialDocumentInWindow;
}
/**
* Tell this document that it's the initial document in its window. See
* comments on mIsInitialDocumentInWindow for when this should be called.
@ -486,7 +486,7 @@ public:
{
mIsInitialDocumentInWindow = aIsInitialDocument;
}
/**
* Get the bidi options for this document.
@ -687,7 +687,7 @@ public:
{
mParentDocument = aParent;
}
/**
* Are plugins allowed in this document ?
*/
@ -838,7 +838,7 @@ public:
Element* GetHeadElement() {
return GetHtmlChildElement(nsGkAtoms::head);
}
/**
* Accessors to the collection of stylesheets owned by this document.
* Style sheets are ordered, most significant last.
@ -873,7 +873,7 @@ public:
* @throws no exceptions
*/
virtual int32_t GetNumberOfStyleSheets() const = 0;
/**
* Get a particular stylesheet
* @param aIndex the index the stylesheet lives at. This is zero-based
@ -881,7 +881,7 @@ public:
* @throws no exceptions
*/
virtual nsIStyleSheet* GetStyleSheetAt(int32_t aIndex) const = 0;
/**
* Insert a sheet at a particular spot in the stylesheet list (zero-based)
* @param aSheet the sheet to insert
@ -925,7 +925,7 @@ public:
* and that observers should be notified and style sets updated
*/
virtual void SetStyleSheetApplicableState(nsIStyleSheet* aSheet,
bool aApplicable) = 0;
bool aApplicable) = 0;
enum additionalSheetType {
eAgentSheet,
@ -1029,7 +1029,7 @@ public:
nsPIDOMWindow* outer = mWindow ? mWindow->GetOuterWindow() : nullptr;
return outer && outer->IsBackground();
}
/**
* Return the inner window used as the script compilation scope for
* this document. If you're not absolutely sure you need this, use
@ -1060,7 +1060,7 @@ public:
/**
* Get the script loader for this document
*/
*/
virtual nsScriptLoader* ScriptLoader() = 0;
/**
@ -1159,7 +1159,7 @@ public:
* exit fullscreen.
*
* If aDocument is non null, all documents from aDocument's fullscreen root
* to the fullscreen leaf exit fullscreen.
* to the fullscreen leaf exit fullscreen.
*
* Note that the fullscreen leaf is the bottom-most document which is
* fullscreen, it may have non-fullscreen child documents. The fullscreen
@ -1474,7 +1474,7 @@ public:
* The document should save form control state.
*/
virtual void RemovedFromDocShell() = 0;
/**
* Get the layout history state that should be used to save and restore state
* for nodes in this document. This may return null; if that happens state
@ -1583,7 +1583,7 @@ public:
nsCompatibility GetCompatibilityMode() const {
return mCompatMode;
}
/**
* Check whether we've ever fired a DOMTitleChanged event for this
* document.
@ -1717,7 +1717,7 @@ public:
{
return mDisplayDocument;
}
/**
* Set the display document for this document. aDisplayDocument must not be
* null.
@ -1759,7 +1759,7 @@ public:
return mObservers;
}
protected:
nsAutoTArray< nsCOMPtr<nsIObserver>, 8 > mObservers;
nsAutoTArray< nsCOMPtr<nsIObserver>, 8 > mObservers;
};
/**
@ -2169,9 +2169,9 @@ public:
virtual Element* FindImageMap(const nsAString& aNormalizedMapName) = 0;
// Add aLink to the set of links that need their status resolved.
// Add aLink to the set of links that need their status resolved.
void RegisterPendingLinkUpdate(mozilla::dom::Link* aLink);
// Remove aLink from the set of links that need their status resolved.
// This function must be called when links are removed from the document.
void UnregisterPendingLinkUpdate(mozilla::dom::Link* aElement);
@ -2203,7 +2203,7 @@ public:
uint32_t aParamsLength = 0) const;
virtual void PostVisibilityUpdateEvent() = 0;
bool IsSyntheticDocument() const { return mIsSyntheticDocument; }
void SetNeedLayoutFlush() {
@ -2708,7 +2708,7 @@ protected:
// If true, whoever is creating the document has gotten it to the
// point where it's safe to start layout on it.
bool mMayStartLayout;
// True iff we've ever fired a DOMTitleChanged event for this document
bool mHaveFiredTitleChange;
@ -2727,7 +2727,7 @@ protected:
// True iff DNS prefetch is allowed for this document. Note that if the
// document has no window, DNS prefetch won't be performed no matter what.
bool mAllowDNSPrefetch;
// True when this document is a static clone of a normal document
bool mIsStaticDocument;
@ -2875,7 +2875,7 @@ protected:
// if this document is part of a multipart document,
// the ID can be used to distinguish it from the other parts.
uint32_t mPartID;
// Cycle collector generation in which we're certain that this document
// won't be collected
uint32_t mMarkedCCGeneration;
@ -3024,8 +3024,8 @@ NS_NewVideoDocument(nsIDocument** aInstancePtrResult);
// Also, both aDocumentURI and aBaseURI must not be null.
nsresult
NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
const nsAString& aNamespaceURI,
const nsAString& aQualifiedName,
const nsAString& aNamespaceURI,
const nsAString& aQualifiedName,
nsIDOMDocumentType* aDoctype,
nsIURI* aDocumentURI,
nsIURI* aBaseURI,

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

@ -6,6 +6,7 @@
#include "nsWrapperCacheInlines.h"
#include "js/Class.h"
#include "js/Proxy.h"
#include "mozilla/dom/DOMJSProxyHandler.h"
#include "mozilla/HoldDropJSObjects.h"
@ -15,6 +16,14 @@
using namespace mozilla;
using namespace mozilla::dom;
#ifdef DEBUG
/* static */ bool
nsWrapperCache::HasJSObjectMovedOp(JSObject* aWrapper)
{
return js::HasObjectMovedOp(aWrapper);
}
#endif
/* static */ void
nsWrapperCache::HoldJSObjects(void* aScriptObjectHolder,
nsScriptObjectTracer* aTracer)

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

@ -9,7 +9,6 @@
#include "nsCycleCollectionParticipant.h"
#include "mozilla/Assertions.h"
#include "js/Class.h"
#include "js/Id.h" // must come before js/RootingAPI.h
#include "js/Value.h" // must come before js/RootingAPI.h
#include "js/RootingAPI.h"
@ -66,6 +65,7 @@ class nsWindowRoot;
* have to include some JS headers that don't play nicely with the rest of the
* codebase. Include nsWrapperCacheInlines.h if you need to call those methods.
*/
class nsWrapperCache
{
public:
@ -103,11 +103,18 @@ public:
return GetWrapperJSObject();
}
#ifdef DEBUG
private:
static bool HasJSObjectMovedOp(JSObject* aWrapper);
public:
#endif
void SetWrapper(JSObject* aWrapper)
{
MOZ_ASSERT(!PreservingWrapper(), "Clearing a preserved wrapper!");
MOZ_ASSERT(aWrapper, "Use ClearWrapper!");
MOZ_ASSERT(js::HasObjectMovedOp(aWrapper),
MOZ_ASSERT(HasJSObjectMovedOp(aWrapper),
"Object has not provided the hook to update the wrapper if it is moved");
SetWrapperJSObject(aWrapper);

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

@ -108,6 +108,28 @@ ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
NamesOfInterfacesWithProtos(aProtoId));
}
bool
ThrowMethodFailed(JSContext* cx, ErrorResult& rv)
{
if (rv.IsUncatchableException()) {
// Nuke any existing exception on aCx, to make sure we're uncatchable.
JS_ClearPendingException(cx);
// Don't do any reporting. Just return false, to create an
// uncatchable exception.
return false;
}
if (rv.IsErrorWithMessage()) {
rv.ReportErrorWithMessage(cx);
return false;
}
if (rv.IsJSException()) {
rv.ReportJSException(cx);
return false;
}
rv.ReportGenericError(cx);
return false;
}
bool
ThrowNoSetterArg(JSContext* aCx, prototypes::ID aProtoId)
{
@ -289,17 +311,6 @@ ErrorResult::StealJSException(JSContext* cx,
mResult = NS_OK;
}
void
ErrorResult::ReportNotEnoughArgsError(JSContext* cx,
const char* ifaceName,
const char* memberName)
{
MOZ_ASSERT(ErrorCode() == NS_ERROR_XPC_NOT_ENOUGH_ARGS);
nsPrintfCString errorMessage("%s.%s", ifaceName, memberName);
ThrowErrorMessage(cx, dom::MSG_MISSING_ARGUMENTS, errorMessage.get());
}
void
ErrorResult::ReportGenericError(JSContext* cx)
{
@ -2657,7 +2668,7 @@ ConvertExceptionToPromise(JSContext* cx,
if (rv.Failed()) {
// We just give up. Make sure to not leak memory on the
// ErrorResult, but then just put the original exception back.
ThrowMethodFailedWithDetails(cx, rv, "", "");
ThrowMethodFailed(cx, rv);
JS_SetPendingException(cx, exn);
return false;
}

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

@ -89,33 +89,8 @@ ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
const ErrNum aErrorNumber,
prototypes::ID aProtoId);
inline bool
ThrowMethodFailedWithDetails(JSContext* cx, ErrorResult& rv,
const char* ifaceName,
const char* memberName)
{
if (rv.IsUncatchableException()) {
// Nuke any existing exception on aCx, to make sure we're uncatchable.
JS_ClearPendingException(cx);
// Don't do any reporting. Just return false, to create an
// uncatchable exception.
return false;
}
if (rv.IsErrorWithMessage()) {
rv.ReportErrorWithMessage(cx);
return false;
}
if (rv.IsJSException()) {
rv.ReportJSException(cx);
return false;
}
if (rv.IsNotEnoughArgsError()) {
rv.ReportNotEnoughArgsError(cx, ifaceName, memberName);
return false;
}
rv.ReportGenericError(cx);
return false;
}
bool
ThrowMethodFailed(JSContext* cx, ErrorResult& rv);
// Returns true if the JSClass is used for DOM objects.
inline bool

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

@ -1709,7 +1709,7 @@ class CGConstructNavigatorObject(CGAbstractMethod):
nsRefPtr<mozilla::dom::${descriptorName}> result = ConstructNavigatorObjectHelper(aCx, global, rv);
rv.WouldReportJSException();
if (rv.Failed()) {
ThrowMethodFailedWithDetails(aCx, rv, "${descriptorName}", "navigatorConstructor");
ThrowMethodFailed(aCx, rv);
return nullptr;
}
if (!GetOrCreateDOMReflector(aCx, result, &v)) {
@ -7012,9 +7012,7 @@ class CGPerSignatureCall(CGThing):
return wrapCode
def getErrorReport(self):
return CGGeneric('return ThrowMethodFailedWithDetails(cx, rv, "%s", "%s");\n'
% (self.descriptor.interface.identifier.name,
self.idlNode.identifier.name))
return CGGeneric('return ThrowMethodFailed(cx, rv);\n')
def define(self):
return (self.cgRoot.define() + self.wrap_return_value())
@ -7969,7 +7967,7 @@ class CGEnumerateHook(CGAbstractBindingMethod):
self->GetOwnPropertyNames(cx, names, rv);
rv.WouldReportJSException();
if (rv.Failed()) {
return ThrowMethodFailedWithDetails(cx, rv, "%s", "enumerate");
return ThrowMethodFailed(cx, rv);
}
bool dummy;
for (uint32_t i = 0; i < names.Length(); ++i) {
@ -10026,7 +10024,7 @@ class CGEnumerateOwnPropertiesViaGetOwnPropertyNames(CGAbstractBindingMethod):
self->GetOwnPropertyNames(cx, names, rv);
rv.WouldReportJSException();
if (rv.Failed()) {
return ThrowMethodFailedWithDetails(cx, rv, "%s", "enumerate");
return ThrowMethodFailed(cx, rv);
}
// OK to pass null as "proxy" because it's ignored if
// shadowPrototypeProperties is true

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

@ -110,12 +110,6 @@ public:
void ReportJSException(JSContext* cx);
bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; }
void ThrowNotEnoughArgsError() { mResult = NS_ERROR_XPC_NOT_ENOUGH_ARGS; }
void ReportNotEnoughArgsError(JSContext* cx,
const char* ifaceName,
const char* memberName);
bool IsNotEnoughArgsError() const { return ErrorCode() == NS_ERROR_XPC_NOT_ENOUGH_ARGS; }
// Report a generic error. This should only be used if we're not
// some more specific exception type.
void ReportGenericError(JSContext* cx);
@ -189,8 +183,7 @@ private:
MOZ_ASSERT(!IsErrorWithMessage(), "Don't overwrite errors with message");
MOZ_ASSERT(aRv != NS_ERROR_DOM_JS_EXCEPTION, "Use ThrowJSException()");
MOZ_ASSERT(!IsJSException(), "Don't overwrite JS exceptions");
MOZ_ASSERT(aRv != NS_ERROR_XPC_NOT_ENOUGH_ARGS, "Use ThrowNotEnoughArgsError()");
MOZ_ASSERT(!IsNotEnoughArgsError(), "Don't overwrite not enough args error");
MOZ_ASSERT(aRv != NS_ERROR_XPC_NOT_ENOUGH_ARGS, "May need to bring back ThrowNotEnoughArgsError");
mResult = aRv;
}

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

@ -56,7 +56,7 @@ ToJSValue(JSContext* aCx,
MOZ_ASSERT(!aArgument.IsUncatchableException(),
"Doesn't make sense to convert uncatchable exception to a JS value!");
AutoForceSetExceptionOnContext forceExn(aCx);
DebugOnly<bool> throwResult = ThrowMethodFailedWithDetails(aCx, aArgument, "", "");
DebugOnly<bool> throwResult = ThrowMethodFailed(aCx, aArgument);
MOZ_ASSERT(!throwResult);
DebugOnly<bool> getPendingResult = JS_GetPendingException(aCx, aValue);
MOZ_ASSERT(getPendingResult);

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

@ -1047,7 +1047,7 @@ ContentParent::RecvBridgeToChildProcess(const ContentParentId& aCpId)
ContentParentId parentId;
if (cpm->GetParentProcessId(cp->ChildID(), &parentId) &&
parentId == this->ChildID()) {
return PContentBridge::Bridge(this, cp);
return NS_SUCCEEDED(PContentBridge::Bridge(this, cp));
}
}

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

@ -140,6 +140,13 @@ parent:
*/
sync GetWidgetNativeData() returns (WindowsHandle value);
/**
* When content moves focus from a native plugin window that's a child
* of the native browser window we need to move native focus to the
* browser. Otherwise the plugin window will never relinquish focus.
*/
sync DispatchFocusToTopLevelWindow();
parent:
/**
* When child sends this message, parent should move focus to

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

@ -2473,10 +2473,9 @@ TabParent::RecvGetMaxTouchPoints(uint32_t* aTouchPoints)
return true;
}
bool
TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
already_AddRefed<nsIWidget>
TabParent::GetTopLevelWidget()
{
*aValue = 0;
nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
if (content) {
nsIPresShell* shell = content->OwnerDoc()->GetShell();
@ -2484,12 +2483,31 @@ TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
nsViewManager* vm = shell->GetViewManager();
nsCOMPtr<nsIWidget> widget;
vm->GetRootWidget(getter_AddRefs(widget));
if (widget) {
*aValue = reinterpret_cast<WindowsHandle>(
widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW));
}
return widget.forget();
}
}
return nullptr;
}
bool
TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
{
*aValue = 0;
nsCOMPtr<nsIWidget> widget = GetTopLevelWidget();
if (widget) {
*aValue = reinterpret_cast<WindowsHandle>(
widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW));
}
return true;
}
bool
TabParent::RecvDispatchFocusToTopLevelWindow()
{
nsCOMPtr<nsIWidget> widget = GetTopLevelWidget();
if (widget) {
widget->SetFocus(false);
}
return true;
}

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

@ -116,7 +116,7 @@ public:
}
already_AddRefed<nsILoadContext> GetLoadContext();
already_AddRefed<nsIWidget> GetTopLevelWidget();
nsIXULBrowserWindow* GetXULBrowserWindow();
void Destroy();
@ -218,6 +218,7 @@ public:
virtual bool RecvGetDefaultScale(double* aValue) override;
virtual bool RecvGetMaxTouchPoints(uint32_t* aTouchPoints) override;
virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue) override;
virtual bool RecvDispatchFocusToTopLevelWindow() override;
virtual bool RecvZoomToRect(const uint32_t& aPresShellId,
const ViewID& aViewId,
const CSSRect& aRect) override;

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

@ -199,7 +199,8 @@ AudioSink::AudioLoop()
CheckedInt64 sampleTime = UsecsToFrames(AudioQueue().PeekFront()->mTime, mInfo.mRate);
// Calculate the number of frames that have been pushed onto the audio hardware.
CheckedInt64 playedFrames = UsecsToFrames(mStartTime, mInfo.mRate) + mWritten;
CheckedInt64 playedFrames = UsecsToFrames(mStartTime, mInfo.mRate) +
static_cast<int64_t>(mWritten);
CheckedInt64 missingFrames = sampleTime - playedFrames;
if (!missingFrames.isValid() || !sampleTime.isValid()) {

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

@ -9,6 +9,7 @@
#include "nsISupportsImpl.h"
#include "MediaDecoderReader.h"
#include "mozilla/dom/AudioChannelBinding.h"
#include "mozilla/Atomics.h"
namespace mozilla {
@ -116,7 +117,7 @@ private:
const int64_t mStartTime;
// PCM frames written to the stream so far.
int64_t mWritten;
Atomic<int64_t> mWritten;
// Keep the last good position returned from the audio stream. Used to ensure
// position returned by GetPosition() is mono-increasing in spite of audio

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

@ -74,9 +74,16 @@ void FileBlockCache::Close()
// opening more streams, while the media cache is shutting down and
// releasing memory etc! Also note we close mFD in the destructor so
// as to not disturb any IO that's currently running.
nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(mThread);
mThread = nullptr;
NS_DispatchToMainThread(event);
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
if (mainThread) {
nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(mThread);
mainThread->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
} else {
// we're on Mainthread already, *and* the event queues are already
// shut down, so no events should occur - certainly not creations of
// new streams.
mThread->Shutdown();
}
}
}

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

@ -1409,8 +1409,14 @@ MediaCache::QueueUpdate()
if (mUpdateQueued)
return;
mUpdateQueued = true;
nsCOMPtr<nsIRunnable> event = new UpdateEvent();
NS_DispatchToMainThread(event);
// XXX MediaCache does updates when decoders are still running at
// shutdown and get freed in the final cycle-collector cleanup. So
// don't leak a runnable in that case.
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
if (mainThread) {
nsCOMPtr<nsIRunnable> event = new UpdateEvent();
mainThread->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
}
}
void

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

@ -647,19 +647,19 @@ void
MediaOperationTask::ReturnCallbackError(nsresult rv, const char* errorLog)
{
MM_LOG(("%s , rv=%d", errorLog, rv));
NS_DispatchToMainThread(new ReleaseMediaOperationResource(mStream.forget(),
mOnTracksAvailableCallback.forget()));
NS_DispatchToMainThread(do_AddRef(new ReleaseMediaOperationResource(mStream.forget(),
mOnTracksAvailableCallback.forget())));
nsString log;
log.AssignASCII(errorLog);
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess;
nsRefPtr<MediaMgrError> error = new MediaMgrError(
NS_LITERAL_STRING("InternalError"), log);
NS_DispatchToMainThread(
NS_DispatchToMainThread(do_AddRef(
new ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>(onSuccess,
mOnFailure,
*error,
mWindowID));
mWindowID)));
}
/**
@ -1067,9 +1067,9 @@ public:
MOZ_ASSERT(!mOnSuccess);
MOZ_ASSERT(!mOnFailure);
NS_DispatchToMainThread(runnable);
NS_DispatchToMainThread(runnable.forget());
// Do after ErrorCallbackRunnable Run()s, as it checks active window list
NS_DispatchToMainThread(new GetUserMediaListenerRemove(mWindowID, mListener));
NS_DispatchToMainThread(do_AddRef(new GetUserMediaListenerRemove(mWindowID, mListener)));
}
void
@ -1111,12 +1111,12 @@ public:
peerIdentity = new PeerIdentity(mConstraints.mPeerIdentity);
}
NS_DispatchToMainThread(new GetUserMediaStreamRunnable(
NS_DispatchToMainThread(do_AddRef(new GetUserMediaStreamRunnable(
mOnSuccess, mOnFailure, mWindowID, mListener,
(mAudioDevice? mAudioDevice->GetSource() : nullptr),
(mVideoDevice? mVideoDevice->GetSource() : nullptr),
peerIdentity
));
)));
MOZ_ASSERT(!mOnSuccess);
MOZ_ASSERT(!mOnFailure);
@ -1290,7 +1290,7 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId, MediaSourceEnum aVideoType
}
SourceSet* handoff = result.forget();
NS_DispatchToMainThread(NewRunnableFrom([id, handoff]() mutable {
NS_DispatchToMainThread(do_AddRef(NewRunnableFrom([id, handoff]() mutable {
ScopedDeletePtr<SourceSet> result(handoff); // grab result
nsRefPtr<MediaManager> mgr = MediaManager_GetInstance();
if (!mgr) {
@ -1301,7 +1301,7 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId, MediaSourceEnum aVideoType
p->Resolve(result.forget());
}
return NS_OK;
}));
})));
}));
return p.forget();
}
@ -2253,7 +2253,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
// must explicitly do this before dispatching the reply, since the reply may kill us with Stop()
mBackend = nullptr; // last reference, will invoke Shutdown() again
if (NS_FAILED(NS_DispatchToMainThread(mReply))) {
if (NS_FAILED(NS_DispatchToMainThread(mReply.forget()))) {
LOG(("Will leak thread: DispatchToMainthread of reply runnable failed in MediaManager shutdown"));
}
}
@ -2727,7 +2727,7 @@ GetUserMediaCallbackMediaStreamListener::NotifyFinished(MediaStreamGraph* aGraph
{
mFinished = true;
Invalidate(); // we know it's been activated
NS_DispatchToMainThread(new GetUserMediaListenerRemove(mWindowID, this));
NS_DispatchToMainThread(do_AddRef(new GetUserMediaListenerRemove(mWindowID, this)));
}
// Called from the MediaStreamGraph thread

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

@ -601,6 +601,7 @@ MediaStreamGraphImpl::UpdateStreamOrder()
if (CurrentDriver()->AsAudioCallbackDriver()->IsStarted()) {
if (mLifecycleState == LIFECYCLE_RUNNING) {
SystemClockDriver* driver = new SystemClockDriver(this);
mMixer.RemoveCallback(CurrentDriver()->AsAudioCallbackDriver());
CurrentDriver()->SwitchAtNextIteration(driver);
}
}
@ -3456,6 +3457,7 @@ MediaStreamGraphImpl::ApplyAudioContextOperationImpl(AudioNodeStream* aStream,
EnqueueStreamAndPromiseForOperation(aStream, aPromise, aOperation);
SystemClockDriver* driver = new SystemClockDriver(this);
mMixer.RemoveCallback(CurrentDriver()->AsAudioCallbackDriver());
CurrentDriver()->SwitchAtNextIteration(driver);
} else {
// We are closing or suspending an AudioContext, but something else is

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

@ -45,7 +45,19 @@ public:
// Forward behaviour to wrapped thread pool implementation.
NS_FORWARD_SAFE_NSITHREADPOOL(mPool);
NS_FORWARD_SAFE_NSIEVENTTARGET(mEventTarget);
// See bug 1155059 - MSVC forces us to not declare Dispatch normally in idl
// NS_FORWARD_SAFE_NSIEVENTTARGET(mEventTarget);
nsresult Dispatch(nsIRunnable *event, uint32_t flags) { return !mEventTarget ? NS_ERROR_NULL_POINTER : mEventTarget->Dispatch(event, flags); }
NS_IMETHOD DispatchFromScript(nsIRunnable *event, uint32_t flags) override {
return Dispatch(event, flags);
}
NS_IMETHOD Dispatch(already_AddRefed<nsIRunnable>&& event, uint32_t flags) override
{ return !mEventTarget ? NS_ERROR_NULL_POINTER : mEventTarget->Dispatch(Move(event), flags); }
NS_IMETHOD IsOnCurrentThread(bool *_retval) override { return !mEventTarget ? NS_ERROR_NULL_POINTER : mEventTarget->IsOnCurrentThread(_retval); }
// Creates necessary statics. Called once at startup.
static void InitStatics();

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

@ -1052,7 +1052,7 @@ GMPParent::EnsureProcessLoaded(base::ProcessId* aID)
bool
GMPParent::Bridge(GMPServiceParent* aGMPServiceParent)
{
if (!PGMPContent::Bridge(aGMPServiceParent, this)) {
if (NS_FAILED(PGMPContent::Bridge(aGMPServiceParent, this))) {
return false;
}
++mGMPContentChildCount;

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

@ -129,7 +129,18 @@ mozilla::plugins::SetupBridge(uint32_t aPluginId,
// We'll handle the bridging asynchronously
return true;
}
return PPluginModule::Bridge(aContentParent, chromeParent);
*rv = PPluginModule::Bridge(aContentParent, chromeParent);
if (NS_FAILED(*rv)) {
#if defined(MOZ_CRASHREPORTER)
// We are going to abort due to the failure, lets note the cause
// in the report for diagnosing.
nsAutoCString error;
error.AppendPrintf("%X", *rv);
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BridgePluginError"), error);
#endif
return false;
}
return true;
}
#ifdef MOZ_CRASHREPORTER_INJECTOR

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

@ -1215,10 +1215,17 @@ Promise::MaybeReportRejected()
// Now post an event to do the real reporting async
// Since Promises preserve their wrapper, it is essential to nsRefPtr<> the
// AsyncErrorReporter, otherwise if the call to DispatchToMainThread fails, it
// will leak. See Bug 958684.
nsRefPtr<AsyncErrorReporter> r =
new AsyncErrorReporter(CycleCollectedJSRuntime::Get()->Runtime(), xpcReport);
NS_DispatchToMainThread(r);
// will leak. See Bug 958684. So... don't use DispatchToMainThread()
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
if (NS_WARN_IF(!mainThread)) {
// Would prefer NS_ASSERTION, but that causes failure in xpcshell tests
NS_WARNING("!!! Trying to report rejected Promise after MainThread shutdown");
}
if (mainThread) {
nsRefPtr<AsyncErrorReporter> r =
new AsyncErrorReporter(CycleCollectedJSRuntime::Get()->Runtime(), xpcReport);
mainThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
}
}
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
@ -1635,7 +1642,7 @@ PromiseWorkerProxy::RunCallback(JSContext* aCx,
if (!runnable->Dispatch(aCx)) {
nsRefPtr<WorkerControlRunnable> runnable =
new PromiseWorkerProxyControlRunnable(mWorkerPrivate, this);
mWorkerPrivate->DispatchControlRunnable(runnable);
mWorkerPrivate->DispatchControlRunnable(runnable.forget());
}
}

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

@ -1756,7 +1756,7 @@ RuntimeService::ScheduleWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
nsCOMPtr<nsIRunnable> runnable =
new WorkerThreadPrimaryRunnable(aWorkerPrivate, thread, JS_GetParentRuntime(aCx));
if (NS_FAILED(thread->DispatchPrimaryRunnable(friendKey, runnable))) {
if (NS_FAILED(thread->DispatchPrimaryRunnable(friendKey, runnable.forget()))) {
UnregisterWorker(aCx, aWorkerPrivate);
JS_ReportError(aCx, "Could not dispatch to thread!");
return false;

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

@ -322,7 +322,10 @@ public:
return false;
}
NS_SUCCEEDED(NS_DispatchToMainThread(this));
nsCOMPtr<nsIRunnable> that(this);
if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(this)))) {
NS_ASSERTION(false, "Failed to dispatch update back to MainThread in ServiceWorker");
}
return true;
}
@ -812,6 +815,8 @@ ServiceWorkerRegistrationWorkerThread::Update()
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
// XXX: this pattern guarantees we won't know which thread UpdateRunnable
// will die on (here or MainThread)
nsRefPtr<UpdateRunnable> r = new UpdateRunnable(worker, mScope);
r->Dispatch();
}

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

@ -1838,7 +1838,14 @@ public:
protected:
NS_IMETHOD
Dispatch(nsIRunnable* aRunnable, uint32_t aFlags) override
DispatchFromScript(nsIRunnable* aRunnable, uint32_t aFlags) override
{
nsCOMPtr<nsIRunnable> runnable(aRunnable);
return Dispatch(runnable.forget(), aFlags);
}
NS_IMETHOD
Dispatch(already_AddRefed<nsIRunnable>&& aRunnable, uint32_t aFlags) override
{
// This should only happen on the timer thread.
MOZ_ASSERT(!NS_IsMainThread());
@ -1849,7 +1856,8 @@ protected:
// Run the runnable we're given now (should just call DummyCallback()),
// otherwise the timer thread will leak it... If we run this after
// dispatch running the event can race against resetting the timer.
aRunnable->Run();
nsCOMPtr<nsIRunnable> runnable(aRunnable);
runnable->Run();
// This can fail if we're racing to terminate or cancel, should be handled
// by the terminate or cancel code.
@ -2872,10 +2880,11 @@ WorkerPrivateParent<Derived>::WrapObject(JSContext* aCx, JS::Handle<JSObject*> a
template <class Derived>
nsresult
WorkerPrivateParent<Derived>::DispatchPrivate(WorkerRunnable* aRunnable,
WorkerPrivateParent<Derived>::DispatchPrivate(already_AddRefed<WorkerRunnable>&& aRunnable,
nsIEventTarget* aSyncLoopTarget)
{
// May be called on any thread!
nsRefPtr<WorkerRunnable> runnable(aRunnable);
WorkerPrivate* self = ParentAsWorkerPrivate();
@ -2886,7 +2895,7 @@ WorkerPrivateParent<Derived>::DispatchPrivate(WorkerRunnable* aRunnable,
if (!self->mThread) {
if (ParentStatus() == Pending || self->mStatus == Pending) {
mPreStartRunnables.AppendElement(aRunnable);
mPreStartRunnables.AppendElement(runnable);
return NS_OK;
}
@ -2904,9 +2913,9 @@ WorkerPrivateParent<Derived>::DispatchPrivate(WorkerRunnable* aRunnable,
nsresult rv;
if (aSyncLoopTarget) {
rv = aSyncLoopTarget->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
rv = aSyncLoopTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
} else {
rv = self->mThread->Dispatch(WorkerThreadFriendKey(), aRunnable);
rv = self->mThread->DispatchAnyThread(WorkerThreadFriendKey(), runnable.forget());
}
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -2956,13 +2965,11 @@ WorkerPrivateParent<Derived>::DisableDebugger()
template <class Derived>
nsresult
WorkerPrivateParent<Derived>::DispatchControlRunnable(
WorkerControlRunnable* aWorkerControlRunnable)
already_AddRefed<WorkerControlRunnable>&& aWorkerControlRunnable)
{
// May be called on any thread!
MOZ_ASSERT(aWorkerControlRunnable);
nsRefPtr<WorkerControlRunnable> runnable = aWorkerControlRunnable;
nsRefPtr<WorkerControlRunnable> runnable(aWorkerControlRunnable);
MOZ_ASSERT(runnable);
WorkerPrivate* self = ParentAsWorkerPrivate();
@ -2996,13 +3003,13 @@ WorkerPrivateParent<Derived>::DispatchControlRunnable(
template <class Derived>
nsresult
WorkerPrivateParent<Derived>::DispatchDebuggerRunnable(
WorkerRunnable *aDebuggerRunnable)
already_AddRefed<WorkerRunnable>&& aDebuggerRunnable)
{
// May be called on any thread!
MOZ_ASSERT(aDebuggerRunnable);
nsRefPtr<WorkerRunnable> runnable(aDebuggerRunnable);
nsRefPtr<WorkerRunnable> runnable = aDebuggerRunnable;
MOZ_ASSERT(runnable);
WorkerPrivate* self = ParentAsWorkerPrivate();
@ -3026,19 +3033,20 @@ WorkerPrivateParent<Derived>::DispatchDebuggerRunnable(
template <class Derived>
already_AddRefed<WorkerRunnable>
WorkerPrivateParent<Derived>::MaybeWrapAsWorkerRunnable(nsIRunnable* aRunnable)
WorkerPrivateParent<Derived>::MaybeWrapAsWorkerRunnable(already_AddRefed<nsIRunnable>&& aRunnable)
{
// May be called on any thread!
MOZ_ASSERT(aRunnable);
nsCOMPtr<nsIRunnable> runnable(aRunnable);
MOZ_ASSERT(runnable);
nsRefPtr<WorkerRunnable> workerRunnable =
WorkerRunnable::FromRunnable(aRunnable);
WorkerRunnable::FromRunnable(runnable);
if (workerRunnable) {
return workerRunnable.forget();
}
nsCOMPtr<nsICancelableRunnable> cancelable = do_QueryInterface(aRunnable);
nsCOMPtr<nsICancelableRunnable> cancelable = do_QueryInterface(runnable);
if (!cancelable) {
MOZ_CRASH("All runnables destined for a worker thread must be cancelable!");
}
@ -5447,7 +5455,7 @@ WorkerPrivate::RunBeforeNextEvent(nsIRunnable* aRunnable)
// to run.
if (mPreemptingRunnableInfos.Length() == 1 && !NS_HasPendingEvents(mThread)) {
nsRefPtr<DummyRunnable> dummyRunnable = new DummyRunnable(this);
if (NS_FAILED(Dispatch(dummyRunnable))) {
if (NS_FAILED(Dispatch(dummyRunnable.forget()))) {
NS_WARNING("RunBeforeNextEvent called after the thread is shutting "
"down!");
mPreemptingRunnableInfos.Clear();
@ -7140,7 +7148,7 @@ WorkerPrivate::SetThread(WorkerThread* aThread)
if (!mPreStartRunnables.IsEmpty()) {
for (uint32_t index = 0; index < mPreStartRunnables.Length(); index++) {
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
mThread->Dispatch(friendKey, mPreStartRunnables[index])));
mThread->DispatchAnyThread(friendKey, mPreStartRunnables[index].forget())));
}
mPreStartRunnables.Clear();
}
@ -7400,9 +7408,19 @@ NS_INTERFACE_MAP_END
template <class Derived>
NS_IMETHODIMP
WorkerPrivateParent<Derived>::
EventTarget::Dispatch(nsIRunnable* aRunnable, uint32_t aFlags)
EventTarget::DispatchFromScript(nsIRunnable* aRunnable, uint32_t aFlags)
{
nsCOMPtr<nsIRunnable> event(aRunnable);
return Dispatch(event.forget(), aFlags);
}
template <class Derived>
NS_IMETHODIMP
WorkerPrivateParent<Derived>::
EventTarget::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable, uint32_t aFlags)
{
// May be called on any thread!
nsCOMPtr<nsIRunnable> event(aRunnable);
// Workers only support asynchronous dispatch for now.
if (NS_WARN_IF(aFlags != NS_DISPATCH_NORMAL)) {
@ -7419,12 +7437,12 @@ EventTarget::Dispatch(nsIRunnable* aRunnable, uint32_t aFlags)
return NS_ERROR_UNEXPECTED;
}
if (aRunnable) {
workerRunnable = mWorkerPrivate->MaybeWrapAsWorkerRunnable(aRunnable);
if (event) {
workerRunnable = mWorkerPrivate->MaybeWrapAsWorkerRunnable(event.forget());
}
nsresult rv =
mWorkerPrivate->DispatchPrivate(workerRunnable, mNestedEventTarget);
mWorkerPrivate->DispatchPrivate(workerRunnable.forget(), mNestedEventTarget);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

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

@ -233,7 +233,7 @@ private:
ErrorResult& aRv);
nsresult
DispatchPrivate(WorkerRunnable* aRunnable, nsIEventTarget* aSyncLoopTarget);
DispatchPrivate(already_AddRefed<WorkerRunnable>&& aRunnable, nsIEventTarget* aSyncLoopTarget);
public:
virtual JSObject*
@ -258,19 +258,19 @@ public:
}
nsresult
Dispatch(WorkerRunnable* aRunnable)
Dispatch(already_AddRefed<WorkerRunnable>&& aRunnable)
{
return DispatchPrivate(aRunnable, nullptr);
return DispatchPrivate(Move(aRunnable), nullptr);
}
nsresult
DispatchControlRunnable(WorkerControlRunnable* aWorkerControlRunnable);
DispatchControlRunnable(already_AddRefed<WorkerControlRunnable>&& aWorkerControlRunnable);
nsresult
DispatchDebuggerRunnable(WorkerRunnable* aDebuggerRunnable);
DispatchDebuggerRunnable(already_AddRefed<WorkerRunnable>&& aDebuggerRunnable);
already_AddRefed<WorkerRunnable>
MaybeWrapAsWorkerRunnable(nsIRunnable* aRunnable);
MaybeWrapAsWorkerRunnable(already_AddRefed<nsIRunnable>&& aRunnable);
already_AddRefed<nsIEventTarget>
GetEventTarget();

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

@ -136,25 +136,27 @@ WorkerRunnable::Dispatch(JSContext* aCx)
bool
WorkerRunnable::DispatchInternal()
{
nsRefPtr<WorkerRunnable> runnable(this);
if (mBehavior == WorkerThreadModifyBusyCount ||
mBehavior == WorkerThreadUnchangedBusyCount) {
if (IsDebuggerRunnable()) {
return NS_SUCCEEDED(mWorkerPrivate->DispatchDebuggerRunnable(this));
return NS_SUCCEEDED(mWorkerPrivate->DispatchDebuggerRunnable(runnable.forget()));
} else {
return NS_SUCCEEDED(mWorkerPrivate->Dispatch(this));
return NS_SUCCEEDED(mWorkerPrivate->Dispatch(runnable.forget()));
}
}
MOZ_ASSERT(mBehavior == ParentThreadUnchangedBusyCount);
if (WorkerPrivate* parent = mWorkerPrivate->GetParent()) {
return NS_SUCCEEDED(parent->Dispatch(this));
return NS_SUCCEEDED(parent->Dispatch(runnable.forget()));
}
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
MOZ_ASSERT(mainThread);
return NS_SUCCEEDED(mainThread->Dispatch(this, NS_DISPATCH_NORMAL));
return NS_SUCCEEDED(mainThread->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL));
}
void
@ -422,7 +424,8 @@ bool
WorkerSyncRunnable::DispatchInternal()
{
if (mSyncLoopTarget) {
return NS_SUCCEEDED(mSyncLoopTarget->Dispatch(this, NS_DISPATCH_NORMAL));
nsRefPtr<WorkerSyncRunnable> runnable(this);
return NS_SUCCEEDED(mSyncLoopTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL));
}
return WorkerRunnable::DispatchInternal();
@ -482,7 +485,8 @@ StopSyncLoopRunnable::DispatchInternal()
{
MOZ_ASSERT(mSyncLoopTarget);
return NS_SUCCEEDED(mSyncLoopTarget->Dispatch(this, NS_DISPATCH_NORMAL));
nsRefPtr<StopSyncLoopRunnable> runnable(this);
return NS_SUCCEEDED(mSyncLoopTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL));
}
void
@ -518,18 +522,20 @@ WorkerControlRunnable::Cancel()
bool
WorkerControlRunnable::DispatchInternal()
{
nsRefPtr<WorkerControlRunnable> runnable(this);
if (mBehavior == WorkerThreadUnchangedBusyCount) {
return NS_SUCCEEDED(mWorkerPrivate->DispatchControlRunnable(this));
return NS_SUCCEEDED(mWorkerPrivate->DispatchControlRunnable(runnable.forget()));
}
if (WorkerPrivate* parent = mWorkerPrivate->GetParent()) {
return NS_SUCCEEDED(parent->DispatchControlRunnable(this));
return NS_SUCCEEDED(parent->DispatchControlRunnable(runnable.forget()));
}
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
MOZ_ASSERT(mainThread);
return NS_SUCCEEDED(mainThread->Dispatch(this, NS_DISPATCH_NORMAL));
return NS_SUCCEEDED(mainThread->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL));
}
void
@ -560,8 +566,9 @@ WorkerMainThreadRunnable::Dispatch(JSContext* aCx)
AutoSyncLoopHolder syncLoop(mWorkerPrivate);
mSyncLoopTarget = syncLoop.EventTarget();
nsRefPtr<WorkerMainThreadRunnable> runnable(this);
if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
if (NS_FAILED(NS_DispatchToMainThread(runnable.forget(), NS_DISPATCH_NORMAL))) {
JS_ReportError(aCx, "Failed to dispatch to main thread!");
return false;
}

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

@ -139,11 +139,13 @@ WorkerThread::SetWorker(const WorkerThreadFriendKey& /* aKey */,
nsresult
WorkerThread::DispatchPrimaryRunnable(const WorkerThreadFriendKey& /* aKey */,
nsIRunnable* aRunnable)
already_AddRefed<nsIRunnable>&& aRunnable)
{
nsCOMPtr<nsIRunnable> runnable(aRunnable);
#ifdef DEBUG
MOZ_ASSERT(PR_GetCurrentThread() != mThread);
MOZ_ASSERT(aRunnable);
MOZ_ASSERT(runnable);
{
MutexAutoLock lock(mLock);
@ -152,7 +154,7 @@ WorkerThread::DispatchPrimaryRunnable(const WorkerThreadFriendKey& /* aKey */,
}
#endif
nsresult rv = nsThread::Dispatch(aRunnable, NS_DISPATCH_NORMAL);
nsresult rv = nsThread::Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -161,8 +163,8 @@ WorkerThread::DispatchPrimaryRunnable(const WorkerThreadFriendKey& /* aKey */,
}
nsresult
WorkerThread::Dispatch(const WorkerThreadFriendKey& /* aKey */,
WorkerRunnable* aWorkerRunnable)
WorkerThread::DispatchAnyThread(const WorkerThreadFriendKey& /* aKey */,
already_AddRefed<WorkerRunnable>&& aWorkerRunnable)
{
// May be called on any thread!
@ -181,8 +183,9 @@ WorkerThread::Dispatch(const WorkerThreadFriendKey& /* aKey */,
}
}
#endif
nsCOMPtr<nsIRunnable> runnable(aWorkerRunnable);
nsresult rv = nsThread::Dispatch(aWorkerRunnable, NS_DISPATCH_NORMAL);
nsresult rv = nsThread::Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -197,9 +200,17 @@ WorkerThread::Dispatch(const WorkerThreadFriendKey& /* aKey */,
NS_IMPL_ISUPPORTS_INHERITED0(WorkerThread, nsThread)
NS_IMETHODIMP
WorkerThread::Dispatch(nsIRunnable* aRunnable, uint32_t aFlags)
WorkerThread::DispatchFromScript(nsIRunnable* aRunnable, uint32_t aFlags)
{
nsCOMPtr<nsIRunnable> runnable(aRunnable);
return Dispatch(runnable.forget(), aFlags);
}
NS_IMETHODIMP
WorkerThread::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable, uint32_t aFlags)
{
// May be called on any thread!
nsCOMPtr<nsIRunnable> runnable(aRunnable); // in case we exit early
// Workers only support asynchronous dispatch.
if (NS_WARN_IF(aFlags != NS_DISPATCH_NORMAL)) {
@ -209,8 +220,8 @@ WorkerThread::Dispatch(nsIRunnable* aRunnable, uint32_t aFlags)
const bool onWorkerThread = PR_GetCurrentThread() == mThread;
#ifdef DEBUG
if (aRunnable && !onWorkerThread) {
nsCOMPtr<nsICancelableRunnable> cancelable = do_QueryInterface(aRunnable);
if (runnable && !onWorkerThread) {
nsCOMPtr<nsICancelableRunnable> cancelable = do_QueryInterface(runnable);
{
MutexAutoLock lock(mLock);
@ -245,18 +256,14 @@ WorkerThread::Dispatch(nsIRunnable* aRunnable, uint32_t aFlags)
}
}
nsIRunnable* runnableToDispatch;
nsRefPtr<WorkerRunnable> workerRunnable;
if (aRunnable && onWorkerThread) {
workerRunnable = workerPrivate->MaybeWrapAsWorkerRunnable(aRunnable);
runnableToDispatch = workerRunnable;
nsresult rv;
if (runnable && onWorkerThread) {
nsRefPtr<WorkerRunnable> workerRunnable = workerPrivate->MaybeWrapAsWorkerRunnable(runnable.forget());
rv = nsThread::Dispatch(workerRunnable.forget(), NS_DISPATCH_NORMAL);
} else {
runnableToDispatch = aRunnable;
rv = nsThread::Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
}
nsresult rv = nsThread::Dispatch(runnableToDispatch, NS_DISPATCH_NORMAL);
if (!onWorkerThread && workerPrivate) {
// We need to wake the worker thread if we're not already on the right
// thread and the dispatch succeeded.

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

@ -66,11 +66,11 @@ public:
nsresult
DispatchPrimaryRunnable(const WorkerThreadFriendKey& aKey,
nsIRunnable* aRunnable);
already_AddRefed<nsIRunnable>&& aRunnable);
nsresult
Dispatch(const WorkerThreadFriendKey& aKey,
WorkerRunnable* aWorkerRunnable);
DispatchAnyThread(const WorkerThreadFriendKey& aKey,
already_AddRefed<WorkerRunnable>&& aWorkerRunnable);
uint32_t
RecursionDepth(const WorkerThreadFriendKey& aKey) const;
@ -84,7 +84,10 @@ private:
// This should only be called by consumers that have an
// nsIEventTarget/nsIThread pointer.
NS_IMETHOD
Dispatch(nsIRunnable* aRunnable, uint32_t aFlags) override;
Dispatch(already_AddRefed<nsIRunnable>&& aRunnable, uint32_t aFlags) override;
NS_IMETHOD
DispatchFromScript(nsIRunnable* aRunnable, uint32_t aFlags) override;
};
} // namespace workers

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

@ -66,7 +66,6 @@ FontInfoLoadCompleteEvent::Run()
loader->FinalizeLoader(mFontInfo);
mFontInfo = nullptr;
return NS_OK;
}
@ -81,7 +80,6 @@ AsyncFontInfoLoader::Run()
// post a completion event that transfer the data to the fontlist
NS_DispatchToMainThread(mCompleteEvent);
mFontInfo = nullptr;
return NS_OK;
}
@ -140,23 +138,27 @@ gfxFontInfoLoader::StartLoader(uint32_t aDelay, uint32_t aInterval)
InitLoader();
// start async load
mState = stateAsyncLoad;
nsresult rv = NS_NewNamedThread("Font Loader",
getter_AddRefs(mFontLoaderThread),
nullptr);
if (NS_FAILED(rv)) {
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
mState = stateAsyncLoad;
nsCOMPtr<nsIRunnable> loadEvent = new AsyncFontInfoLoader(mFontInfo);
mFontLoaderThread->Dispatch(loadEvent, NS_DISPATCH_NORMAL);
mFontLoaderThread->Dispatch(loadEvent.forget(), NS_DISPATCH_NORMAL);
}
void
gfxFontInfoLoader::FinalizeLoader(FontInfoData *aFontInfo)
{
// avoid loading data if loader has already been canceled
// Avoid loading data if loader has already been canceled.
// This should mean that CancelLoader() ran and the Load
// thread has already Shutdown(), and likely before processing
// the Shutdown event it handled the load event and sent back
// our Completion event, thus we end up here.
if (mState != stateAsyncLoad) {
return;
}
@ -187,8 +189,11 @@ gfxFontInfoLoader::CancelLoader()
mTimer = nullptr;
}
if (mFontLoaderThread) {
mFontLoaderThread->Shutdown();
mFontLoaderThread = nullptr;
// NOTE: Shutdown() runs the event loop, and we can get timer events
// ensure that we can't try to do this twice!
nsCOMPtr<nsIThread> temp;
temp.swap(mFontLoaderThread);
temp->Shutdown();
}
RemoveShutdownObserver();
CleanupLoader();

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

@ -179,34 +179,41 @@ public:
}
};
bool
nsresult
Bridge(const PrivateIPDLInterface&,
MessageChannel* aParentChannel, ProcessId aParentPid,
MessageChannel* aChildChannel, ProcessId aChildPid,
ProtocolId aProtocol, ProtocolId aChildProtocol)
{
if (!aParentPid || !aChildPid) {
return false;
return NS_ERROR_INVALID_ARG;
}
TransportDescriptor parentSide, childSide;
if (!CreateTransport(aParentPid, &parentSide, &childSide)) {
return false;
nsresult rv;
if (NS_FAILED(rv = CreateTransport(aParentPid, &parentSide, &childSide))) {
return rv;
}
if (!aParentChannel->Send(new ChannelOpened(parentSide,
aChildPid,
aProtocol,
IPC::Message::PRIORITY_URGENT)) ||
!aChildChannel->Send(new ChannelOpened(childSide,
aParentPid,
aChildProtocol,
IPC::Message::PRIORITY_URGENT))) {
IPC::Message::PRIORITY_URGENT))) {
CloseDescriptor(parentSide);
CloseDescriptor(childSide);
return false;
return NS_ERROR_BRIDGE_OPEN_PARENT;
}
return true;
if (!aChildChannel->Send(new ChannelOpened(childSide,
aParentPid,
aChildProtocol,
IPC::Message::PRIORITY_URGENT))) {
CloseDescriptor(parentSide);
CloseDescriptor(childSide);
return NS_ERROR_BRIDGE_OPEN_CHILD;
}
return NS_OK;
}
bool
@ -224,7 +231,7 @@ Open(const PrivateIPDLInterface&,
}
TransportDescriptor parentSide, childSide;
if (!CreateTransport(parentId, &parentSide, &childSide)) {
if (NS_FAILED(CreateTransport(parentId, &parentSide, &childSide))) {
return false;
}

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

@ -295,7 +295,7 @@ FatalError(const char* aProtocolName, const char* aMsg,
struct PrivateIPDLInterface {};
bool
nsresult
Bridge(const PrivateIPDLInterface&,
MessageChannel*, base::ProcessId, MessageChannel*, base::ProcessId,
ProtocolId, ProtocolId);

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

@ -24,8 +24,9 @@ class FileDescriptor;
typedef IPC::Channel Transport;
bool CreateTransport(base::ProcessId aProcIdOne,
TransportDescriptor* aOne, TransportDescriptor* aTwo);
nsresult CreateTransport(base::ProcessId aProcIdOne,
TransportDescriptor* aOne,
TransportDescriptor* aTwo);
Transport* OpenDescriptor(const TransportDescriptor& aTd,
Transport::Mode aMode);

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

@ -21,9 +21,10 @@ using base::ProcessHandle;
namespace mozilla {
namespace ipc {
bool
CreateTransport(base::ProcessId /*unused*/,
TransportDescriptor* aOne, TransportDescriptor* aTwo)
nsresult
CreateTransport(base::ProcessId aProcIdOne,
TransportDescriptor* aOne,
TransportDescriptor* aTwo)
{
wstring id = IPC::Channel::GenerateVerifiedChannelID(std::wstring());
// Use MODE_SERVER to force creation of the socketpair
@ -32,7 +33,7 @@ CreateTransport(base::ProcessId /*unused*/,
int fd2, dontcare;
t.GetClientFileDescriptorMapping(&fd2, &dontcare);
if (fd1 < 0 || fd2 < 0) {
return false;
return NS_ERROR_TRANSPORT_INIT;
}
// The Transport closes these fds when it goes out of scope, so we
@ -40,12 +41,12 @@ CreateTransport(base::ProcessId /*unused*/,
fd1 = dup(fd1);
fd2 = dup(fd2);
if (fd1 < 0 || fd2 < 0) {
return false;
return NS_ERROR_DUPLICATE_HANDLE;
}
aOne->mFd = base::FileDescriptor(fd1, true/*close after sending*/);
aTwo->mFd = base::FileDescriptor(fd2, true/*close after sending*/);
return true;
return NS_OK;
}
Transport*

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

@ -18,16 +18,17 @@ using base::ProcessHandle;
namespace mozilla {
namespace ipc {
bool
nsresult
CreateTransport(base::ProcessId aProcIdOne,
TransportDescriptor* aOne, TransportDescriptor* aTwo)
TransportDescriptor* aOne,
TransportDescriptor* aTwo)
{
wstring id = IPC::Channel::GenerateVerifiedChannelID(std::wstring());
// Use MODE_SERVER to force creation of the pipe
Transport t(id, Transport::MODE_SERVER, nullptr);
HANDLE serverPipe = t.GetServerPipeHandle();
if (!serverPipe) {
return false;
return NS_ERROR_TRANSPORT_INIT;
}
// NB: we create the server pipe immediately, instead of just
@ -39,13 +40,13 @@ CreateTransport(base::ProcessId aProcIdOne,
DWORD access = 0;
DWORD options = DUPLICATE_SAME_ACCESS;
if (!DuplicateHandle(serverPipe, aProcIdOne, &serverDup, access, options)) {
return false;
return NS_ERROR_DUPLICATE_HANDLE;
}
aOne->mPipeName = aTwo->mPipeName = id;
aOne->mServerPipe = serverDup;
aTwo->mServerPipe = INVALID_HANDLE_VALUE;
return true;
return NS_OK;
}
Transport*

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

@ -331,6 +331,7 @@ Type.BOOL = Type('bool')
Type.INT = Type('int')
Type.INT32 = Type('int32_t')
Type.INTPTR = Type('intptr_t')
Type.NSRESULT = Type('nsresult')
Type.UINT32 = Type('uint32_t')
Type.UINT32PTR = Type('uint32_t', ptr=1)
Type.SIZE = Type('size_t')

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

@ -1680,7 +1680,7 @@ class _GenerateProtocolCode(ipdl.ast.Visitor):
'Bridge',
params=[ Decl(parentHandleType, parentvar.name),
Decl(childHandleType, childvar.name) ],
ret=Type.BOOL))
ret=Type.NSRESULT))
bridgefunc.addstmt(StmtReturn(ExprCall(
ExprVar('mozilla::ipc::Bridge'),
args=[ _backstagePass(),

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

@ -0,0 +1,91 @@
var asmdiv2 = (function(m) {
"use asm"
function f(x) {
x = x|0;
var z = 0;
z = ((x>>>0) / 2)>>>0;
return z|0;
}
return f;
})()
var plaindiv2 = function(x) {
x = x|0;
var z = 0;
z = ((x>>>0) / 2)>>>0;
return z|0;
}
var k2 = 0xf0000000;
assertEq(asmdiv2(k2), 0x78000000);
assertEq(plaindiv2(k2), 0x78000000);
var asmdiv3 = (function(m) {
"use asm"
function f(x) {
x = x|0;
var z = 0;
z = ((x>>>0) / 3)>>>0;
return z|0;
}
return f;
})()
var plaindiv3 = function(x) {
x = x|0;
var z = 0;
z = ((x>>>0) / 3)>>>0;
return z|0;
}
var k3 = 3<<30;
assertEq(asmdiv3(k3), 1<<30);
assertEq(plaindiv3(k3), 1<<30);
var asmdiv7 = (function(m) {
"use asm"
function f(x) {
x = x|0;
var z = 0;
z = ((x>>>0) / 7)>>>0;
return z|0;
}
return f;
})()
var plaindiv7 = function(x) {
x = x|0;
var z = 0;
z = ((x>>>0) / 7)>>>0;
return z|0;
}
var k7 = (1<<29)*7 + 4;
assertEq(asmdiv7(k7), 1<<29);
assertEq(plaindiv7(k7), 1<<29);
var asmmod3 = (function(m) {
"use asm"
function f(x) {
x = x|0;
var z = 0;
z = ((x>>>0) % 3)>>>0;
return z|0;
}
return f;
})()
var plainmod3 = function(x) {
x = x|0;
var z = 0;
z = ((x>>>0) % 3)>>>0;
return z|0;
}
var kmod = (3<<30) + 2;
assertEq(asmmod3(kmod), 2);
assertEq(plainmod3(kmod), 2);

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

@ -6386,6 +6386,16 @@ class MDiv : public MBinaryArithInstruction
}
bool canBeNegativeDividend() const {
// "Dividend" is an ambiguous concept for unsigned truncated
// division, because of the truncation procedure:
// ((x>>>0)/2)|0, for example, gets transformed in
// MDiv::truncate into a node with lhs representing x (not
// x>>>0) and rhs representing the constant 2; in other words,
// the MIR node corresponds to "cast operands to unsigned and
// divide" operation. In this case, is the dividend x or is it
// x>>>0? In order to resolve such ambiguities, we disallow
// the usage of this method for unsigned division.
MOZ_ASSERT(!unsigned_);
return canBeNegativeDividend_;
}
@ -6469,6 +6479,7 @@ class MMod : public MBinaryArithInstruction
bool canBeNegativeDividend() const {
MOZ_ASSERT(specialization_ == MIRType_Int32);
MOZ_ASSERT(!unsigned_);
return canBeNegativeDividend_;
}

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

@ -1574,45 +1574,56 @@ CodeGeneratorShared::addCacheLocations(const CacheLocationList& locs, size_t* nu
}
ReciprocalMulConstants
CodeGeneratorShared::computeDivisionConstants(int d) {
// In what follows, d is positive and is not a power of 2.
MOZ_ASSERT(d > 0 && (d & (d - 1)) != 0);
CodeGeneratorShared::computeDivisionConstants(uint32_t d, int maxLog) {
MOZ_ASSERT(maxLog >= 2 && maxLog <= 32);
// In what follows, 0 < d < 2^maxLog and d is not a power of 2.
MOZ_ASSERT(d < (uint64_t(1) << maxLog) && (d & (d - 1)) != 0);
// Speeding up division by non power-of-2 constants is possible by
// calculating, during compilation, a value M such that high-order
// bits of M*n correspond to the result of the division. Formally,
// we compute values 0 <= M < 2^32 and 0 <= s < 31 such that
// (M * n) >> (32 + s) = floor(n/d) if n >= 0
// (M * n) >> (32 + s) = ceil(n/d) - 1 if n < 0.
// bits of M*n correspond to the result of the division of n by d.
// No value of M can serve this purpose for arbitrarily big values
// of n but, for optimizing integer division, we're just concerned
// with values of n whose absolute value is bounded (by fitting in
// an integer type, say). With this in mind, we'll find a constant
// M as above that works for -2^maxLog <= n < 2^maxLog; maxLog can
// then be 31 for signed division or 32 for unsigned division.
//
// The original presentation of this technique appears in Hacker's
// Delight, a book by Henry S. Warren, Jr.. A proof of correctness
// for our version follows.
// Define p = 32 + s, M = ceil(2^p/d), and assume that s satisfies
// M - 2^p/d <= 2^(s+1)/d. (1)
// (Observe that s = FloorLog32(d) satisfies this, because in this
// case d <= 2^(s+1) and so the RHS of (1) is at least one). Then,
// for our version follows; we'll denote maxLog by L in the proof,
// for conciseness.
//
// a) If s <= FloorLog32(d), then M <= 2^32 - 1.
// Proof: Indeed, M is monotone in s and, for s = FloorLog32(d),
// the inequalities 2^31 > d >= 2^s + 1 readily imply
// 2^p / d = 2^p/(d - 1) * (d - 1)/d
// <= 2^32 * (1 - 1/d) < 2 * (2^31 - 1) = 2^32 - 2.
// Formally, for |d| < 2^L, we'll compute two magic values M and s
// in the ranges 0 <= M < 2^(L+1) and 0 <= s <= L such that
// (M * n) >> (32 + s) = floor(n/d) if 0 <= n < 2^L
// (M * n) >> (32 + s) = ceil(n/d) - 1 if -2^L <= n < 0.
//
// Define p = 32 + s, M = ceil(2^p/d), and assume that s satisfies
// M - 2^p/d <= 2^(p-L)/d. (1)
// (Observe that p = CeilLog32(d) + L satisfies this, as the right
// side of (1) is at least one in this case). Then,
//
// a) If p <= CeilLog32(d) + L, then M < 2^(L+1) - 1.
// Proof: Indeed, M is monotone in p and, for p equal to the above
// value, the bounds 2^L > d >= 2^(p-L-1) + 1 readily imply that
// 2^p / d < 2^p/(d - 1) * (d - 1)/d
// <= 2^(L+1) * (1 - 1/d) < 2^(L+1) - 2.
// The claim follows by applying the ceiling function.
//
// b) For any 0 <= n < 2^31, floor(Mn/2^p) = floor(n/d).
// b) For any 0 <= n < 2^L, floor(Mn/2^p) = floor(n/d).
// Proof: Put x = floor(Mn/2^p); it's the unique integer for which
// Mn/2^p - 1 < x <= Mn/2^p. (2)
// Using M >= 2^p/d on the LHS and (1) on the RHS, we get
// n/d - 1 < x <= n/d + n/(2^31 d) < n/d + 1/d.
// n/d - 1 < x <= n/d + n/(2^L d) < n/d + 1/d.
// Since x is an integer, it's not in the interval (n/d, (n+1)/d),
// and so n/d - 1 < x <= n/d, which implies x = floor(n/d).
//
// c) For any -2^31 <= n < 0, floor(Mn/2^p) + 1 = ceil(n/d).
// c) For any -2^L <= n < 0, floor(Mn/2^p) + 1 = ceil(n/d).
// Proof: The proof is similar. Equation (2) holds as above. Using
// M > 2^p/d (d isn't a power of 2) on the RHS and (1) on the LHS,
// n/d + n/(2^31 d) - 1 < x < n/d.
// Using n >= -2^31 and summing 1,
// n/d + n/(2^L d) - 1 < x < n/d.
// Using n >= -2^L and summing 1,
// n/d - 1/d < x + 1 < n/d + 1.
// Since x + 1 is an integer, this implies n/d <= x + 1 < n/d + 1.
// In other words, x + 1 = ceil(n/d).
@ -1620,27 +1631,30 @@ CodeGeneratorShared::computeDivisionConstants(int d) {
// Condition (1) isn't necessary for the existence of M and s with
// the properties above. Hacker's Delight provides a slightly less
// restrictive condition when d >= 196611, at the cost of a 3-page
// proof of correctness.
// proof of correctness, for the case L = 31.
//
// Note that, since d*M - 2^p = d - (2^p)%d, (1) can be written as
// 2^(s+1) >= d - (2^p)%d.
// We now compute the least s with this property...
// 2^(p-L) >= d - (2^p)%d.
// In order to avoid overflow in the (2^p) % d calculation, we can
// compute it as (2^p-1) % d + 1, where 2^p-1 can then be computed
// without overflow as UINT64_MAX >> (64-p).
int32_t shift = 0;
while ((int64_t(1) << (shift+1)) + (int64_t(1) << (shift+32)) % d < d)
shift++;
// We now compute the least p >= 32 with the property above...
int32_t p = 32;
while ((uint64_t(1) << (p-maxLog)) + (UINT64_MAX >> (64-p)) % d + 1 < d)
p++;
// ...and the corresponding M. This may not fit in a signed 32-bit
// integer; we will compute (M - 2^32) * n + (2^32 * n) instead of
// M * n if this is the case (cf. item (a) above).
// ...and the corresponding M. For either the signed (L=31) or the
// unsigned (L=32) case, this value can be too large (cf. item a).
// Codegen can still multiply by M by multiplying by (M - 2^L) and
// adjusting the value afterwards, if this is the case.
ReciprocalMulConstants rmc;
rmc.multiplier = int32_t((int64_t(1) << (shift+32))/d + 1);
rmc.shiftAmount = shift;
rmc.multiplier = (UINT64_MAX >> (64-p))/d + 1;
rmc.shiftAmount = p - 32;
return rmc;
}
#ifdef JS_TRACE_LOGGING
void

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

@ -45,7 +45,7 @@ struct PatchableBackedgeInfo
};
struct ReciprocalMulConstants {
int32_t multiplier;
int64_t multiplier;
int32_t shiftAmount;
};
@ -447,7 +447,7 @@ class CodeGeneratorShared : public LElementVisitor
void addCache(LInstruction* lir, size_t cacheIndex);
size_t addCacheLocations(const CacheLocationList& locs, size_t* numLocs);
ReciprocalMulConstants computeDivisionConstants(int d);
ReciprocalMulConstants computeDivisionConstants(uint32_t d, int maxLog);
protected:
void addOutOfLineCode(OutOfLineCode* code, const MInstruction* mir);

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

@ -22,6 +22,7 @@
_(AsmJSLoadFuncPtr) \
_(SimdValueInt32x4) \
_(SimdValueFloat32x4) \
_(UDivOrMod)
_(UDivOrMod) \
_(UDivOrModConstant)
#endif /* jit_x64_LOpcodes_x64_h */

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

@ -1357,6 +1357,9 @@ class AssemblerX86Shared : public AssemblerShared
void imull(Register multiplier) {
masm.imull_r(multiplier.encoding());
}
void umull(Register multiplier) {
masm.mull_r(multiplier.encoding());
}
void imull(Imm32 imm, Register dest) {
masm.imull_ir(imm.value, dest.encoding(), dest.encoding());
}

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

@ -1319,6 +1319,12 @@ public:
}
#endif
void mull_r(RegisterID multiplier)
{
spew("mull %s", GPReg32Name(multiplier));
m_formatter.oneByteOp(OP_GROUP3_Ev, multiplier, GROUP3_OP_MUL);
}
void idivl_r(RegisterID divisor)
{
spew("idivl %s", GPReg32Name(divisor));

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

@ -1005,6 +1005,82 @@ CodeGeneratorX86Shared::visitUDivOrMod(LUDivOrMod* ins)
}
}
void
CodeGeneratorX86Shared::visitUDivOrModConstant(LUDivOrModConstant *ins) {
Register lhs = ToRegister(ins->numerator());
Register output = ToRegister(ins->output());
uint32_t d = ins->denominator();
// This emits the division answer into edx or the modulus answer into eax.
MOZ_ASSERT(output == eax || output == edx);
MOZ_ASSERT(lhs != eax && lhs != edx);
bool isDiv = (output == edx);
if (d == 0) {
if (ins->mir()->isTruncated())
masm.xorl(output, output);
else
bailout(ins->snapshot());
return;
}
// The denominator isn't a power of 2 (see LDivPowTwoI and LModPowTwoI).
MOZ_ASSERT((d & (d - 1)) != 0);
ReciprocalMulConstants rmc = computeDivisionConstants(d, /* maxLog = */ 32);
// We first compute (M * n) >> 32, where M = rmc.multiplier.
masm.movl(Imm32(rmc.multiplier), eax);
masm.umull(lhs);
if (rmc.multiplier > UINT32_MAX) {
// M >= 2^32 and shift == 0 is impossible, as d >= 2 implies that
// ((M * n) >> (32 + shift)) >= n > floor(n/d) whenever n >= d, contradicting
// the proof of correctness in computeDivisionConstants.
MOZ_ASSERT(rmc.shiftAmount > 0);
MOZ_ASSERT(rmc.multiplier < (int64_t(1) << 33));
// We actually computed edx = ((uint32_t(M) * n) >> 32) instead. Since
// (M * n) >> (32 + shift) is the same as (edx + n) >> shift, we can
// correct for the overflow. This case is a bit trickier than the signed
// case, though, as the (edx + n) addition itself can overflow; however,
// note that (edx + n) >> shift == (((n - edx) >> 1) + edx) >> (shift - 1),
// which is overflow-free. See Hacker's Delight, section 10-8 for details.
// Compute (n - edx) >> 1 into eax.
masm.movl(lhs, eax);
masm.subl(edx, eax);
masm.shrl(Imm32(1), eax);
// Finish the computation.
masm.addl(eax, edx);
masm.shrl(Imm32(rmc.shiftAmount - 1), edx);
} else {
masm.shrl(Imm32(rmc.shiftAmount), edx);
}
// We now have the truncated division value in edx. If we're
// computing a modulus or checking whether the division resulted
// in an integer, we need to multiply the obtained value by d and
// finish the computation/check.
if (!isDiv) {
masm.imull(Imm32(d), edx, edx);
masm.movl(lhs, eax);
masm.subl(edx, eax);
// The final result of the modulus op, just computed above by the
// sub instruction, can be a number in the range [2^31, 2^32). If
// this is the case and the modulus is not truncated, we must bail
// out.
if (!ins->mir()->isTruncated())
bailoutIf(Assembler::Signed, ins->snapshot());
} else if (!ins->mir()->isTruncated()) {
masm.imull(Imm32(d), edx, eax);
masm.cmpl(lhs, eax);
bailoutIf(Assembler::NotEqual, ins->snapshot());
}
}
void
CodeGeneratorX86Shared::visitMulNegativeZeroCheck(MulNegativeZeroCheck* ool)
{
@ -1050,21 +1126,26 @@ CodeGeneratorX86Shared::visitDivPowTwoI(LDivPowTwoI* ins)
bailoutIf(Assembler::NonZero, ins->snapshot());
}
// Adjust the value so that shifting produces a correctly rounded result
// when the numerator is negative. See 10-1 "Signed Division by a Known
// Power of 2" in Henry S. Warren, Jr.'s Hacker's Delight.
if (mir->canBeNegativeDividend()) {
Register lhsCopy = ToRegister(ins->numeratorCopy());
MOZ_ASSERT(lhsCopy != lhs);
if (shift > 1)
masm.sarl(Imm32(31), lhs);
masm.shrl(Imm32(32 - shift), lhs);
masm.addl(lhsCopy, lhs);
}
if (mir->isUnsigned()) {
masm.shrl(Imm32(shift), lhs);
} else {
// Adjust the value so that shifting produces a correctly
// rounded result when the numerator is negative. See 10-1
// "Signed Division by a Known Power of 2" in Henry
// S. Warren, Jr.'s Hacker's Delight.
if (mir->canBeNegativeDividend()) {
Register lhsCopy = ToRegister(ins->numeratorCopy());
MOZ_ASSERT(lhsCopy != lhs);
if (shift > 1)
masm.sarl(Imm32(31), lhs);
masm.shrl(Imm32(32 - shift), lhs);
masm.addl(lhsCopy, lhs);
}
masm.sarl(Imm32(shift), lhs);
masm.sarl(Imm32(shift), lhs);
if (negativeDivisor)
masm.negl(lhs);
if (negativeDivisor)
masm.negl(lhs);
}
} else if (shift == 0 && negativeDivisor) {
// INT32_MIN / -1 overflows.
masm.negl(lhs);
@ -1090,17 +1171,23 @@ CodeGeneratorX86Shared::visitDivOrModConstantI(LDivOrModConstantI* ins) {
// We will first divide by Abs(d), and negate the answer if d is negative.
// If desired, this can be avoided by generalizing computeDivisionConstants.
ReciprocalMulConstants rmc = computeDivisionConstants(Abs(d));
ReciprocalMulConstants rmc = computeDivisionConstants(Abs(d), /* maxLog = */ 31);
// As explained in the comments of computeDivisionConstants, we first compute
// X >> (32 + shift), where X is either (rmc.multiplier * n) if the multiplier
// is non-negative or (rmc.multiplier * n) + (2^32 * n) otherwise. This is the
// desired division result if n is non-negative, and is one less than the result
// otherwise.
// We first compute (M * n) >> 32, where M = rmc.multiplier.
masm.movl(Imm32(rmc.multiplier), eax);
masm.imull(lhs);
if (rmc.multiplier < 0)
if (rmc.multiplier > INT32_MAX) {
MOZ_ASSERT(rmc.multiplier < (int64_t(1) << 32));
// We actually computed edx = ((int32_t(M) * n) >> 32) instead. Since
// (M * n) >> 32 is the same as (edx + n), we can correct for the overflow.
// (edx + n) can't overflow, as n and edx have opposite signs because int32_t(M)
// is negative.
masm.addl(lhs, edx);
}
// (M * n) >> (32 + shift) is the truncated division answer if n is non-negative,
// as proved in the comments of computeDivisionConstants. We must add 1 later if n is
// negative to get the right answer in all cases.
masm.sarl(Imm32(rmc.shiftAmount), edx);
// We'll subtract -1 instead of adding 1, because (n < 0 ? -1 : 0) can be
@ -1242,7 +1329,7 @@ CodeGeneratorX86Shared::visitModPowTwoI(LModPowTwoI* ins)
Label negative;
if (ins->mir()->canBeNegativeDividend()) {
if (!ins->mir()->isUnsigned() && ins->mir()->canBeNegativeDividend()) {
// Switch based on sign of the lhs.
// Positive numbers are just a bitmask
masm.branchTest32(Assembler::Signed, lhs, lhs, &negative);
@ -1250,7 +1337,7 @@ CodeGeneratorX86Shared::visitModPowTwoI(LModPowTwoI* ins)
masm.andl(Imm32((uint32_t(1) << shift) - 1), lhs);
if (ins->mir()->canBeNegativeDividend()) {
if (!ins->mir()->isUnsigned() && ins->mir()->canBeNegativeDividend()) {
Label done;
masm.jump(&done);

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

@ -242,6 +242,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
virtual void visitGuardClass(LGuardClass* guard);
virtual void visitEffectiveAddress(LEffectiveAddress* ins);
virtual void visitUDivOrMod(LUDivOrMod* ins);
virtual void visitUDivOrModConstant(LUDivOrModConstant *ins);
virtual void visitAsmJSPassStackArg(LAsmJSPassStackArg* ins);
virtual void visitMemoryBarrier(LMemoryBarrier* ins);

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

@ -289,6 +289,7 @@ enum GroupOpcodeID {
GROUP3_OP_TEST = 0,
GROUP3_OP_NOT = 2,
GROUP3_OP_NEG = 3,
GROUP3_OP_MUL = 4,
GROUP3_OP_IMUL = 5,
GROUP3_OP_DIV = 6,
GROUP3_OP_IDIV = 7,

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

@ -163,6 +163,37 @@ class LUDivOrMod : public LBinaryMath<1>
}
};
class LUDivOrModConstant : public LInstructionHelper<1, 1, 1>
{
const uint32_t denominator_;
public:
LIR_HEADER(UDivOrModConstant)
LUDivOrModConstant(const LAllocation &lhs, uint32_t denominator, const LDefinition& temp)
: denominator_(denominator)
{
setOperand(0, lhs);
setTemp(0, temp);
}
const LAllocation *numerator() {
return getOperand(0);
}
uint32_t denominator() const {
return denominator_;
}
MBinaryArithInstruction *mir() const {
MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
return static_cast<MBinaryArithInstruction *>(mir_);
}
bool canBeNegativeDividend() const {
if (mir_->isMod())
return mir_->toMod()->canBeNegativeDividend();
return mir_->toDiv()->canBeNegativeDividend();
}
};
class LModPowTwoI : public LInstructionHelper<1,1,0>
{
const int32_t shift_;

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

@ -274,6 +274,26 @@ LIRGeneratorX86Shared::visitAsmJSNeg(MAsmJSNeg* ins)
void
LIRGeneratorX86Shared::lowerUDiv(MDiv* div)
{
if (div->rhs()->isConstant()) {
uint32_t rhs = div->rhs()->toConstant()->value().toInt32();
int32_t shift = FloorLog2(rhs);
LAllocation lhs = useRegisterAtStart(div->lhs());
if (rhs != 0 && uint32_t(1) << shift == rhs) {
LDivPowTwoI* lir = new(alloc()) LDivPowTwoI(lhs, lhs, shift, false);
if (div->fallible())
assignSnapshot(lir, Bailout_DoubleOutput);
defineReuseInput(lir, div, 0);
} else {
LUDivOrModConstant* lir = new(alloc()) LUDivOrModConstant(useRegister(div->lhs()),
rhs, tempFixed(eax));
if (div->fallible())
assignSnapshot(lir, Bailout_DoubleOutput);
defineFixed(lir, div, LAllocation(AnyRegister(edx)));
}
return;
}
LUDivOrMod* lir = new(alloc()) LUDivOrMod(useRegister(div->lhs()),
useRegister(div->rhs()),
tempFixed(edx));
@ -285,6 +305,25 @@ LIRGeneratorX86Shared::lowerUDiv(MDiv* div)
void
LIRGeneratorX86Shared::lowerUMod(MMod* mod)
{
if (mod->rhs()->isConstant()) {
uint32_t rhs = mod->rhs()->toConstant()->value().toInt32();
int32_t shift = FloorLog2(rhs);
if (rhs != 0 && uint32_t(1) << shift == rhs) {
LModPowTwoI* lir = new(alloc()) LModPowTwoI(useRegisterAtStart(mod->lhs()), shift);
if (mod->fallible())
assignSnapshot(lir, Bailout_DoubleOutput);
defineReuseInput(lir, mod, 0);
} else {
LUDivOrModConstant* lir = new(alloc()) LUDivOrModConstant(useRegister(mod->lhs()),
rhs, tempFixed(edx));
if (mod->fallible())
assignSnapshot(lir, Bailout_DoubleOutput);
defineFixed(lir, mod, LAllocation(AnyRegister(eax)));
}
return;
}
LUDivOrMod* lir = new(alloc()) LUDivOrMod(useRegister(mod->lhs()),
useRegister(mod->rhs()),
tempFixed(eax));

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

@ -23,6 +23,7 @@
_(AsmJSLoadFuncPtr) \
_(SimdValueInt32x4) \
_(SimdValueFloat32x4) \
_(UDivOrMod)
_(UDivOrMod) \
_(UDivOrModConstant)
#endif /* jit_x86_LOpcodes_x86_h */

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

@ -291,7 +291,7 @@ SandboxFetch(JSContext* cx, JS::HandleObject scope, const CallArgs& args)
FetchRequest(global, Constify(request), Constify(options), rv);
rv.WouldReportJSException();
if (rv.Failed()) {
return ThrowMethodFailedWithDetails(cx, rv, "Sandbox", "fetch");
return ThrowMethodFailed(cx, rv);
}
if (!GetOrCreateDOMReflector(cx, scope, response, args.rval())) {
return false;

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

@ -1202,13 +1202,9 @@ public:
uint32_t flags = imgIContainer::FLAG_SYNC_DECODE;
nsImageFrame* f = static_cast<nsImageFrame*>(mFrame);
EventStates state = f->GetContent()->AsElement()->State();
DrawResult result =
f->DisplayAltFeedback(*aCtx,
mVisibleRect,
IMAGE_OK(state, true)
? nsImageFrame::gIconLoad->mLoadingImage
: nsImageFrame::gIconLoad->mBrokenImage,
ToReferenceFrame(),
flags);
@ -1221,13 +1217,15 @@ public:
DrawResult
nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
imgIRequest* aRequest,
nsPoint aPt,
uint32_t aFlags)
{
// We should definitely have a gIconLoad here.
MOZ_ASSERT(gIconLoad, "How did we succeed in Init then?");
// Whether we draw the broken or loading icon.
bool isLoading = IMAGE_OK(GetContent()->AsElement()->State(), true);
// Calculate the inner area
nsRect inner = GetInnerArea() + aPt;
@ -1247,10 +1245,12 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
}
// Paint the border
nsRecessedBorder recessedBorder(borderEdgeWidth, PresContext());
nsCSSRendering::PaintBorderWithStyleBorder(PresContext(), aRenderingContext,
this, inner, inner,
recessedBorder, mStyleContext);
if (!isLoading || gIconLoad->mPrefShowLoadingPlaceholder) {
nsRecessedBorder recessedBorder(borderEdgeWidth, PresContext());
nsCSSRendering::PaintBorderWithStyleBorder(PresContext(), aRenderingContext,
this, inner, inner,
recessedBorder, mStyleContext);
}
// Adjust the inner rect to account for the one pixel recessed border,
// and a six pixel padding on each edge
@ -1271,15 +1271,20 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
DrawResult result = DrawResult::NOT_READY;
// Check if we should display image placeholders
if (!gIconLoad->mPrefShowPlaceholders) {
if (!gIconLoad->mPrefShowPlaceholders ||
(isLoading && !gIconLoad->mPrefShowLoadingPlaceholder)) {
result = DrawResult::SUCCESS;
} else {
nscoord size = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE);
imgIRequest* request = isLoading
? nsImageFrame::gIconLoad->mLoadingImage
: nsImageFrame::gIconLoad->mBrokenImage;
// If we weren't previously displaying an icon, register ourselves
// as an observer for load and animation updates and flag that we're
// doing so now.
if (aRequest && !mDisplayingIcon) {
if (request && !mDisplayingIcon) {
gIconLoad->AddIconObserver(this);
mDisplayingIcon = true;
}
@ -1290,11 +1295,11 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
// If the icon in question is loaded, draw it.
uint32_t imageStatus = 0;
if (aRequest)
aRequest->GetImageStatus(&imageStatus);
if (request)
request->GetImageStatus(&imageStatus);
if (imageStatus & imgIRequest::STATUS_LOAD_COMPLETE) {
nsCOMPtr<imgIContainer> imgCon;
aRequest->GetImage(getter_AddRefs(imgCon));
request->GetImage(getter_AddRefs(imgCon));
MOZ_ASSERT(imgCon, "Load complete, but no image container?");
nsRect dest(flushRight ? inner.XMost() - size : inner.x,
inner.y, size, size);
@ -2192,6 +2197,7 @@ NS_IMPL_ISUPPORTS(nsImageFrame::IconLoad, nsIObserver,
static const char* kIconLoadPrefs[] = {
"browser.display.force_inline_alttext",
"browser.display.show_image_placeholders",
"browser.display.show_loading_image_placeholder",
nullptr
};
@ -2244,6 +2250,9 @@ void nsImageFrame::IconLoad::GetPrefs()
mPrefShowPlaceholders =
Preferences::GetBool("browser.display.show_image_placeholders", true);
mPrefShowLoadingPlaceholder =
Preferences::GetBool("browser.display.show_loading_image_placeholder", true);
}
NS_IMETHODIMP

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

@ -145,7 +145,6 @@ public:
DrawResult DisplayAltFeedback(nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
imgIRequest* aRequest,
nsPoint aPt,
uint32_t aFlags);
@ -364,6 +363,7 @@ private:
nsRefPtr<imgRequestProxy> mBrokenImage;
bool mPrefForceInlineAltText;
bool mPrefShowPlaceholders;
bool mPrefShowLoadingPlaceholder;
};
public:

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

@ -8897,7 +8897,7 @@ nsRuleNode::SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
const nsCSSValueList* cur = aValue->GetListValue();
uint8_t sizingBox = NS_STYLE_CLIP_SHAPE_SIZING_NOBOX;
nsStyleBasicShape* basicShape = nullptr;
nsRefPtr<nsStyleBasicShape> basicShape;
for (unsigned i = 0; i < 2; ++i) {
if (!cur) {
break;

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

@ -50,6 +50,23 @@ addAsyncAnimTest(function *() {
"at 300ms");
done_div();
});
addAsyncAnimTest(function *() {
var [ div, cs ] = new_div("animation: anim 10s 1 linear forwards");
var animation = div.getAnimations()[0];
advance_clock(300);
yield waitForPaints();
animation.playbackRate = 0;
yield waitForPaintsFlushed();
omta_is(div, "transform", { tx: 3 }, RunningOn.MainThread,
"animation with zero playback rate should stay in the " +
"same position and be running on the main thread");
done_div();
});
</script>
</body>
</html>

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

@ -62,7 +62,7 @@ GMPGetAPI(const char* aApiName, void* aHostAPI, void** aPluginAPI)
*aPluginAPI = new ClearKeySessionManager();
}
#if defined(ENABLE_WMF)
if (!strcmp(aApiName, GMP_API_AUDIO_DECODER) &&
else if (!strcmp(aApiName, GMP_API_AUDIO_DECODER) &&
wmf::EnsureLibs()) {
*aPluginAPI = new AudioDecoder(static_cast<GMPAudioHost*>(aHostAPI));
} else if (!strcmp(aApiName, GMP_API_VIDEO_DECODER) &&

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

@ -44,7 +44,7 @@ RunOnThreadInternal(nsIEventTarget *thread, nsIRunnable *runnable, uint32_t flag
return rv;
}
if (!on) {
return thread->Dispatch(runnable_ref, flags);
return thread->Dispatch(runnable_ref.forget(), flags);
}
}
return runnable_ref->Run();

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

@ -202,6 +202,12 @@ public class FxAccountStatusActivity extends LocaleAwareFragmentActivity {
boolean enabled = !AppConstants.MOZILLA_OFFICIAL || AppConstants.NIGHTLY_BUILD || AppConstants.DEBUG_BUILD;
if (!enabled) {
menu.removeItem(R.id.enable_debug_mode);
} else {
final MenuItem debugModeItem = menu.findItem(R.id.enable_debug_mode);
if (debugModeItem != null) {
// Update checked state based on internal flag.
menu.findItem(R.id.enable_debug_mode).setChecked(FxAccountUtils.LOG_PERSONAL_INFORMATION);
}
}
return super.onCreateOptionsMenu(menu);
};

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

@ -208,7 +208,10 @@ pref("browser.display.force_inline_alttext", false); // true = force ALT text fo
// 1 = use external leading only when font provides,
// 2 = add extra leading both internal leading and external leading are zero
pref("browser.display.normal_lineheight_calc_control", 2);
pref("browser.display.show_image_placeholders", true); // true = show image placeholders while image is loaded and when image is broken
// enable showing image placeholders while image is loading or when image is broken
pref("browser.display.show_image_placeholders", true);
// if browser.display.show_image_placeholders is true then this controls whether the loading image placeholder and border is shown or not
pref("browser.display.show_loading_image_placeholder", false);
// min font device pixel size at which to turn on high quality
pref("browser.display.auto_quality_min_font_size", 20);
pref("browser.anchor_color", "#0000EE");

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

@ -154,13 +154,21 @@ nsSocketTransportService::GetThreadSafely()
}
NS_IMETHODIMP
nsSocketTransportService::Dispatch(nsIRunnable *event, uint32_t flags)
nsSocketTransportService::DispatchFromScript(nsIRunnable *event, uint32_t flags)
{
SOCKET_LOG(("STS dispatch [%p]\n", event));
nsCOMPtr<nsIRunnable> event_ref(event);
return Dispatch(event_ref.forget(), flags);
}
NS_IMETHODIMP
nsSocketTransportService::Dispatch(already_AddRefed<nsIRunnable>&& event, uint32_t flags)
{
nsCOMPtr<nsIRunnable> event_ref(event);
SOCKET_LOG(("STS dispatch [%p]\n", event_ref.get()));
nsCOMPtr<nsIThread> thread = GetThreadSafely();
nsresult rv;
rv = thread ? thread->Dispatch(event, flags) : NS_ERROR_NOT_INITIALIZED;
rv = thread ? thread->Dispatch(event_ref.forget(), flags) : NS_ERROR_NOT_INITIALIZED;
if (rv == NS_ERROR_UNEXPECTED) {
// Thread is no longer accepting events. We must have just shut it
// down on the main thread. Pretend we never saw it.

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

@ -81,6 +81,10 @@ public:
NS_DECL_NSITHREADOBSERVER
NS_DECL_NSIRUNNABLE
NS_DECL_NSIOBSERVER
// missing from NS_DECL_NSIEVENTTARGET because MSVC
nsresult Dispatch(nsIRunnable* aEvent, uint32_t aFlags) {
return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
}
nsSocketTransportService();

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

@ -504,8 +504,16 @@ NS_IMPL_ISUPPORTS(nsStreamTransportService,
nsIObserver)
NS_IMETHODIMP
nsStreamTransportService::Dispatch(nsIRunnable *task, uint32_t flags)
nsStreamTransportService::DispatchFromScript(nsIRunnable *task, uint32_t flags)
{
nsCOMPtr<nsIRunnable> event(task);
return Dispatch(event.forget(), flags);
}
NS_IMETHODIMP
nsStreamTransportService::Dispatch(already_AddRefed<nsIRunnable>&& task, uint32_t flags)
{
nsCOMPtr<nsIRunnable> event(task); // so it gets released on failure paths
nsCOMPtr<nsIThreadPool> pool;
{
mozilla::MutexAutoLock lock(mShutdownLock);
@ -515,7 +523,7 @@ nsStreamTransportService::Dispatch(nsIRunnable *task, uint32_t flags)
pool = mPool;
}
NS_ENSURE_TRUE(pool, NS_ERROR_NOT_INITIALIZED);
return pool->Dispatch(task, flags);
return pool->Dispatch(event.forget(), flags);
}
NS_IMETHODIMP

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

@ -21,6 +21,10 @@ public:
NS_DECL_NSISTREAMTRANSPORTSERVICE
NS_DECL_NSIEVENTTARGET
NS_DECL_NSIOBSERVER
// missing from NS_DECL_NSIEVENTTARGET because MSVC
nsresult Dispatch(nsIRunnable* aEvent, uint32_t aFlags) {
return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
}
nsresult Init();

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

@ -254,7 +254,8 @@ nsEffectiveTLDService::GetBaseDomainInternal(nsCString &aHostname,
const char *currDomain = aHostname.get();
const char *nextDot = strchr(currDomain, '.');
const char *end = currDomain + aHostname.Length();
const char *eTLD = currDomain;
// Default value of *eTLD is currDomain as set in the while loop below
const char *eTLD = nullptr;
while (1) {
// sanity check the string we're about to look up: it should not begin with
// a '.'; this would mean the hostname began with a '.' or had an

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

@ -475,9 +475,9 @@ DataChannelConnection::StartDefer()
{
nsresult rv;
if (!NS_IsMainThread()) {
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::START_DEFER,
this, (DataChannel *) nullptr));
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::START_DEFER,
this, (DataChannel *) nullptr)));
return;
}
@ -614,9 +614,9 @@ DataChannelConnection::CompleteConnect(TransportFlow *flow, TransportLayer::Stat
}
}
// Note: currently this doesn't actually notify the application
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CONNECTION,
this));
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CONNECTION,
this)));
return;
}
@ -712,7 +712,7 @@ DataChannelConnection::SctpDtlsOutput(void *addr, void *buffer, size_t length,
peer->mSTS->Dispatch(WrapRunnable(
nsRefPtr<DataChannelConnection>(peer),
&DataChannelConnection::SendPacket, data, length, true),
NS_DISPATCH_NORMAL);
NS_DISPATCH_NORMAL);
res = 0; // cheat! Packets can always be dropped later anyways
}
return res;
@ -773,9 +773,9 @@ DataChannelConnection::Listen(unsigned short port)
// Notify Connection open
// XXX We need to make sure connection sticks around until the message is delivered
LOG(("%s: sending ON_CONNECTION for %p", __FUNCTION__, this));
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CONNECTION,
this, (DataChannel *) nullptr));
this, (DataChannel *) nullptr)));
return true;
}
@ -851,9 +851,9 @@ DataChannelConnection::Connect(const char *addr, unsigned short port)
// Notify Connection open
// XXX We need to make sure connection sticks around until the message is delivered
LOG(("%s: sending ON_CONNECTION for %p", __FUNCTION__, this));
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CONNECTION,
this, (DataChannel *) nullptr));
this, (DataChannel *) nullptr)));
return true;
}
#endif
@ -1052,9 +1052,9 @@ DataChannelConnection::SendDeferredMessages()
channel->mState = OPEN;
channel->mReady = true;
LOG(("%s: sending ON_CHANNEL_OPEN for %p", __FUNCTION__, channel.get()));
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CHANNEL_OPEN, this,
channel));
channel)));
sent = true;
} else {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
@ -1064,9 +1064,9 @@ DataChannelConnection::SendDeferredMessages()
mStreams[channel->mStream] = nullptr;
channel->mState = CLOSED;
// Don't need to reset; we didn't open it
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this,
channel));
channel)));
}
}
}
@ -1232,9 +1232,9 @@ DataChannelConnection::HandleOpenRequestMessage(const struct rtcweb_datachannel_
LOG(("%s: sending ON_CHANNEL_CREATED for %s/%s: %u (state %u)", __FUNCTION__,
channel->mLabel.get(), channel->mProtocol.get(), stream, channel->mState));
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CHANNEL_CREATED,
this, channel));
this, channel)));
LOG(("%s: deferring sending ON_CHANNEL_OPEN for %p", __FUNCTION__, channel.get()));
@ -1462,9 +1462,9 @@ DataChannelConnection::HandleAssociationChangeEvent(const struct sctp_assoc_chan
SetEvenOdd();
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CONNECTION,
this));
this)));
LOG(("DTLS connect() succeeded! Entering connected mode"));
// Open any streams pending...
@ -1479,18 +1479,18 @@ DataChannelConnection::HandleAssociationChangeEvent(const struct sctp_assoc_chan
case SCTP_COMM_LOST:
LOG(("Association change: SCTP_COMM_LOST"));
// This association is toast, so also close all the channels -- from mainthread!
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_DISCONNECTED,
this));
this)));
break;
case SCTP_RESTART:
LOG(("Association change: SCTP_RESTART"));
break;
case SCTP_SHUTDOWN_COMP:
LOG(("Association change: SCTP_SHUTDOWN_COMP"));
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_DISCONNECTED,
this));
this)));
break;
case SCTP_CANT_STR_ASSOC:
LOG(("Association change: SCTP_CANT_STR_ASSOC"));
@ -1753,9 +1753,9 @@ DataChannelConnection::HandleStreamResetEvent(const struct sctp_stream_reset_eve
// Mark the stream for reset (the reset is sent below)
ResetOutgoingStream(channel->mStream);
}
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this,
channel));
channel)));
mStreams[channel->mStream] = nullptr;
LOG(("Disconnected DataChannel %p from connection %p",
@ -1846,9 +1846,9 @@ DataChannelConnection::HandleStreamChangeEvent(const struct sctp_stream_change_e
(strchg->strchange_flags & SCTP_STREAM_CHANGE_FAILED)) {
/* XXX: Signal to the other end. */
channel->mState = CLOSED;
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this,
channel));
channel)));
// maybe fire onError (bug 843625)
} else {
stream = FindFreeStream();
@ -2129,9 +2129,9 @@ DataChannelConnection::OpenFinish(already_AddRefed<DataChannel>&& aChannel)
if (channel->mFlags & DATA_CHANNEL_FLAGS_FINISH_OPEN) {
// We already returned the channel to the app.
NS_ERROR("Failed to send open request");
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this,
channel));
channel)));
}
// If we haven't returned the channel yet, it will get destroyed when we exit
// this function.
@ -2149,9 +2149,9 @@ DataChannelConnection::OpenFinish(already_AddRefed<DataChannel>&& aChannel)
channel->mReady = true;
// FIX? Move into DOMDataChannel? I don't think we can send it yet here
LOG(("%s: sending ON_CHANNEL_OPEN for %p", __FUNCTION__, channel.get()));
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CHANNEL_OPEN, this,
channel));
channel)));
return channel.forget();
@ -2160,9 +2160,9 @@ request_error_cleanup:
if (channel->mFlags & DATA_CHANNEL_FLAGS_FINISH_OPEN) {
// We already returned the channel to the app.
NS_ERROR("Failed to request more streams");
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this,
channel));
channel)));
return channel.forget();
}
// we'll be destroying the channel, but it never really got set up
@ -2329,8 +2329,7 @@ DataChannelConnection::SendBlob(uint16_t stream, nsIInputStream *aBlob)
}
}
nsCOMPtr<nsIRunnable> runnable = new ReadBlobRunnable(this, stream, aBlob);
mInternalIOThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
mInternalIOThread->Dispatch(do_AddRef(new ReadBlobRunnable(this, stream, aBlob)), NS_DISPATCH_NORMAL);
return 0;
}
@ -2577,9 +2576,9 @@ DataChannel::AppReady()
mReady = true;
if (mState == WAITING_TO_OPEN) {
mState = OPEN;
NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
NS_DispatchToMainThread(do_AddRef(new DataChannelOnMessageAvailable(
DataChannelOnMessageAvailable::ON_CHANNEL_OPEN, mConnection,
this));
this)));
for (uint32_t i = 0; i < mQueuedMessages.Length(); ++i) {
nsCOMPtr<nsIRunnable> runnable = mQueuedMessages[i];
MOZ_ASSERT(runnable);

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

@ -494,6 +494,7 @@ class RecursiveMakeBackend(CommonBackend):
backend_file.write('GENERATED_FILES += %s\n' % obj.output)
if obj.script:
backend_file.write("""{output}: {script}{inputs}
\t$(REPORT_BUILD)
\t$(call py_action,file_generate,{script} {method} {output}{inputs})
""".format(output=obj.output,

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

@ -377,10 +377,12 @@ class TestRecursiveMakeBackend(BackendTester):
expected = [
'GENERATED_FILES += bar.c',
'bar.c: %s/generate-bar.py' % env.topsrcdir,
'$(REPORT_BUILD)',
'$(call py_action,file_generate,%s/generate-bar.py baz bar.c)' % env.topsrcdir,
'',
'GENERATED_FILES += foo.c',
'foo.c: %s/generate-foo.py %s/foo-data' % (env.topsrcdir, env.topsrcdir),
'$(REPORT_BUILD)',
'$(call py_action,file_generate,%s/generate-foo.py main foo.c %s/foo-data)' % (env.topsrcdir, env.topsrcdir),
'',
'GENERATED_FILES += quux.c',

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

@ -108,7 +108,10 @@ void Finalize(JSFreeOp *fop, JSObject *objSelf)
// Notify observers. Since we are executed during garbage-collection,
// we need to dispatch the notification to the main thread.
(void)NS_DispatchToMainThread(event);
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
if (mainThread) {
mainThread->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
}
// We may fail at dispatching to the main thread if we arrive too late
// during shutdown. In that case, there is not much we can do.
}

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

@ -203,8 +203,7 @@
<method name="print">
<body>
<![CDATA[
let contentWindow = this.mPPBrowser.contentWindowAsCPOW;
PrintUtils.print(contentWindow, this.mPPBrowser);
PrintUtils.printWindow(this.mPPBrowser.outerWindowID, this.mPPBrowser);
]]>
</body>
</method>

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

@ -30,18 +30,14 @@
* Messages sent:
*
* Printing:Print
* This message is sent to kick off a print job for a particular content
* window (which is passed along with the message). We also pass print
* settings with this message - though bug 1088070 will have us gather
* those settings from the content process instead.
* Kick off a print job for a nsIDOMWindow, passing the outer window ID as
* windowID.
*
* Printing:Preview:Enter
* This message is sent to put content into print preview mode. We pass
* the content window of the browser we're showing the preview of, and
* the target of the message is the browser that we'll be showing the
* preview in. We also pass print settings in this message, but
* bug 1088070 will have us gather those settings from the content process
* instead.
* preview in.
*
* Printing:Preview:Exit
* This message is sent to take content out of print preview mode.
@ -95,59 +91,58 @@ var PrintUtils = {
},
/**
* Starts printing the contents of aWindow.
* Starts the process of printing the contents of a window.
*
* @param aWindow
* An nsIDOMWindow to initiate the printing of. If the chrome window
* is not running with remote tabs, this defaults to window.content if
* omitted. If running with remote tabs, the caller must pass in the
* content window to be printed. This function throws if that invariant
* is violated.
* @param aBrowser (optional for non-remote browsers)
* The remote <xul:browser> that contains aWindow. This argument is
* not necessary if aWindow came from a non-remote browser, but is
* strictly required otherwise. This function will throw if aWindow
* comes from a remote browser and aBrowser is not provided. This
* browser must have its type attribute set to "content",
* "content-targetable", or "content-primary".
* @param aWindowID
* The outer window ID of the nsIDOMWindow to print.
* @param aBrowser
* The <xul:browser> that the nsIDOMWindow for aWindowID belongs to.
*/
print: function (aWindow, aBrowser)
printWindow: function (aWindowID, aBrowser)
{
if (!aWindow) {
// If we're using remote browsers, chances are that window.content will
// not be defined.
if (this.usingRemoteTabs) {
throw new Error("Windows running with remote tabs must explicitly pass " +
"a content window to PrintUtils.print.");
}
// Otherwise, we should have access to window.content.
aWindow = window.content;
let mm = aBrowser.messageManager;
mm.sendAsyncMessage("Printing:Print", {
windowID: aWindowID,
});
},
/**
* Deprecated.
*
* Starts the process of printing the contents of window.content.
*
*/
print: function ()
{
if (gBrowser) {
return this.printWindow(gBrowser.selectedBrowser.outerWindowID,
gBrowser.selectedBrowser);
}
if (Components.utils.isCrossProcessWrapper(aWindow)) {
if (!aBrowser) {
throw new Error("PrintUtils.print expects a remote browser passed as " +
"an argument if the content window is a CPOW.");
}
} else {
// For content windows coming from non-remote browsers, the browser can
// be resolved as the chromeEventHandler.
aBrowser = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell)
.chromeEventHandler;
if (this.usingRemoteTabs) {
throw new Error("PrintUtils.print cannot be run in windows running with " +
"remote tabs. Use PrintUtils.printWindow instead.");
}
if (!aBrowser) {
let domWindow = window.content;
let ifReq = domWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
let browser = ifReq.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell)
.chromeEventHandler;
if (!browser) {
throw new Error("PrintUtils.print could not resolve content window " +
"to a browser.");
}
let mm = aBrowser.messageManager;
let windowID = ifReq.getInterface(Components.interfaces.nsIDOMWindowUtils)
.outerWindowID;
mm.sendAsyncMessage("Printing:Print", null, {
contentWindow: aWindow,
});
let Deprecated = Components.utils.import("resource://gre/modules/Deprecated.jsm", {}).Deprecated;
let msg = "PrintUtils.print is now deprecated. Please use PrintUtils.printWindow.";
let url = "https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Printing";
Deprecated.warning(msg, url);
this.printWindow(windowID, browser);
},
/**
@ -410,9 +405,8 @@ var PrintUtils = {
// listener.
let ppBrowser = this._listener.getPrintPreviewBrowser();
let mm = ppBrowser.messageManager;
mm.sendAsyncMessage("Printing:Preview:Enter", null, {
contentWindow: this._sourceBrowser.contentWindowAsCPOW ||
this._sourceBrowser.contentWindow,
mm.sendAsyncMessage("Printing:Preview:Enter", {
windowID: this._sourceBrowser.outerWindowID,
});
if (this._webProgressPP.value) {

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

@ -7,6 +7,10 @@ support-files =
[test_lookup_system_principal.html]
[test_classified_annotations.html]
tags = trackingprotection
[test_allowlisted_annotations.html]
tags = trackingprotection
[test_privatebrowsing_trackingprotection.html]
tags = trackingprotection
[test_trackingprotection_bug1157081.html]
tags = trackingprotection

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

@ -39,7 +39,7 @@
<stringbundle id="viewSourceBundle" src="chrome://global/locale/viewSource.properties"/>
<command id="cmd_savePage" oncommand="ViewSourceSavePage();"/>
<command id="cmd_print" oncommand="PrintUtils.print();"/>
<command id="cmd_print" oncommand="PrintUtils.printWindow(gBrowser.outerWindowID, gBrowser);"/>
<command id="cmd_printpreview" oncommand="PrintUtils.printPreview(PrintPreviewListener);"/>
<command id="cmd_pagesetup" oncommand="PrintUtils.showPageSetup();"/>
<command id="cmd_close" oncommand="window.close();"/>

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

@ -39,7 +39,7 @@
<stringbundle id="viewSourceBundle" src="chrome://global/locale/viewSource.properties"/>
<command id="cmd_savePage" oncommand="ViewSourceSavePage();"/>
<command id="cmd_print" oncommand="PrintUtils.print(gBrowser.contentWindowAsCPOW, gBrowser);"/>
<command id="cmd_print" oncommand="PrintUtils.printWindow(gBrowser.outerWindowID, gBrowser);"/>
<command id="cmd_printpreview" oncommand="PrintUtils.printPreview(PrintPreviewListener);"/>
<command id="cmd_pagesetup" oncommand="PrintUtils.showPageSetup();"/>
<command id="cmd_close" oncommand="window.close();"/>

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

@ -392,7 +392,7 @@ let Printing = {
let data = message.data;
switch(message.name) {
case "Printing:Preview:Enter": {
this.enterPrintPreview(objects.contentWindow);
this.enterPrintPreview(Services.wm.getOuterWindowWithId(data.windowID));
break;
}
@ -412,7 +412,7 @@ let Printing = {
}
case "Printing:Print": {
this.print(objects.contentWindow);
this.print(Services.wm.getOuterWindowWithId(data.windowID));
break;
}
}
@ -691,3 +691,39 @@ addMessageListener("WebChannelMessageToContent", function (e) {
Cu.reportError("WebChannel message failed. No message data.");
}
});
let MediaPlaybackListener = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
init() {
Services.obs.addObserver(this, "media-playback", false);
addMessageListener("MediaPlaybackMute", this);
addEventListener("unload", () => {
MediaPlaybackListener.uninit();
});
},
uninit() {
Services.obs.removeObserver(this, "media-playback");
removeMessageListener("MediaPlaybackMute", this);
},
observe(subject, topic, data) {
if (topic === "media-playback") {
if (subject && subject.top == global.content) {
let name = "MediaPlayback:";
name += (data === "active") ? "Start" : "Stop";
sendAsyncMessage(name);
}
}
},
receiveMessage(msg) {
if (msg.name == "MediaPlaybackMute") {
let utils = global.content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
utils.audioMuted = msg.data.type === "mute";
}
},
};
MediaPlaybackListener.init();

Двоичные данные
toolkit/content/tests/browser/audio.ogg Normal file

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

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

@ -36,4 +36,10 @@ skip-if = !e10s || !crashreporter
support-files =
file_redirect.html
file_redirect_to.html
[browser_bug1170531.js]
[browser_bug1170531.js]
[browser_mediaPlayback.js]
support-files =
file_mediaPlayback.html
file_mediaPlaybackFrame.html
audio.ogg
[browser_mute.js]

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

@ -0,0 +1,36 @@
const PAGE = "https://example.com/browser/toolkit/content/tests/browser/file_mediaPlayback.html";
const FRAME = "https://example.com/browser/toolkit/content/tests/browser/file_mediaPlaybackFrame.html";
function wait_for_event(browser, event) {
return BrowserTestUtils.waitForEvent(browser, event, false, (event) => {
is(event.originalTarget, browser, "Event must be dispatched to correct browser.");
return true;
});
}
function* test_on_browser(url, browser) {
browser.loadURI(url);
yield wait_for_event(browser, "DOMMediaPlaybackStarted");
yield wait_for_event(browser, "DOMMediaPlaybackStopped");
}
add_task(function*() {
yield new Promise((resolve) => {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]},
resolve);
});
});
add_task(function* test_page() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: "about:blank",
}, test_on_browser.bind(undefined, PAGE));
});
add_task(function* test_frame() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: "about:blank",
}, test_on_browser.bind(undefined, FRAME));
});

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

@ -0,0 +1,23 @@
const PAGE = "data:text/html,page";
function* test_on_browser(browser) {
ok(!browser.audioMuted, "Audio should not be muted by default");
browser.mute();
ok(browser.audioMuted, "Audio should be muted now");
browser.unmute();
ok(!browser.audioMuted, "Audio should be unmuted now");
}
add_task(function*() {
yield new Promise((resolve) => {
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]},
resolve);
});
});
add_task(function*() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: PAGE,
}, test_on_browser);
});

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

@ -0,0 +1,13 @@
<!DOCTYPE html>
<script type="text/javascript">
var audio = new Audio();
audio.oncanplay = function() {
audio.oncanplay = null;
audio.onplaying = function() {
audio.onplaying = null;
audio.pause();
};
audio.play();
};
audio.src = "audio.ogg";
</script>

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

@ -0,0 +1,2 @@
<!DOCTYPE html>
<iframe src="file_mediaPlayback.html"></iframe>

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

@ -641,7 +641,7 @@
<method name="updateBlockedPopups">
<body>
<![CDATA[
var event = document.createEvent("Events");
let event = document.createEvent("Events");
event.initEvent("DOMUpdatePageReport", true, true);
this.dispatchEvent(event);
]]>
@ -663,6 +663,51 @@
onget="return this.blockedPopups;"
readonly="true"/>
<method name="mediaPlaybackStarted">
<body>
<![CDATA[
let event = document.createEvent("Events");
event.initEvent("DOMMediaPlaybackStarted", true, true);
this.dispatchEvent(event);
]]>
</body>
</method>
<method name="mediaPlaybackStopped">
<body>
<![CDATA[
let event = document.createEvent("Events");
event.initEvent("DOMMediaPlaybackStopped", true, true);
this.dispatchEvent(event);
]]>
</body>
</method>
<field name="_audioMuted">false</field>
<property name="audioMuted"
onget="return this._audioMuted;"
readonly="true"/>
<method name="mute">
<body>
<![CDATA[
this._audioMuted = true;
this.messageManager.sendAsyncMessage("MediaPlaybackMute",
{type: "mute"});
]]>
</body>
</method>
<method name="unmute">
<body>
<![CDATA[
this._audioMuted = false;
this.messageManager.sendAsyncMessage("MediaPlaybackMute",
{type: "unmute"});
]]>
</body>
</method>
<property name="securityUI">
<getter>
<![CDATA[
@ -813,6 +858,8 @@
this.messageManager.addMessageListener("PopupBlocking:UpdateBlockedPopups", this);
this.messageManager.addMessageListener("Autoscroll:Start", this);
this.messageManager.addMessageListener("Autoscroll:Cancel", this);
this.messageManager.addMessageListener("MediaPlayback:Start", this);
this.messageManager.addMessageListener("MediaPlayback:Stop", this);
}
]]>
</constructor>
@ -899,6 +946,12 @@
case "Autoscroll:Cancel":
this._autoScrollPopup.hidePopup();
break;
case "MediaPlayback:Start":
this.mediaPlaybackStarted();
break;
case "MediaPlayback:Stop":
this.mediaPlaybackStopped();
break;
}
]]></body>
</method>

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