зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to fx-team
This commit is contained in:
Коммит
7976b9d3b3
3
CLOBBER
3
CLOBBER
|
@ -22,5 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1159082 - Renaming *Readonly animation interfaces to *ReadOnly causes
|
||||
build bustage on case-insensitive filesystems.
|
||||
Bug 1128037 needed a clobber to properly build on OS X
|
||||
|
|
|
@ -1132,6 +1132,10 @@ pref("dom.requestSync.enabled", true);
|
|||
// Resample touch events on b2g
|
||||
pref("gfx.touch.resample", true);
|
||||
|
||||
// Comma separated list of activity names that can only be provided by
|
||||
// the system app in dev mode.
|
||||
pref("dom.activities.developer_mode_only", "import-app");
|
||||
|
||||
// mulet apparently loads firefox.js as well as b2g.js, so we have to explicitly
|
||||
// disable serviceworkers here to get them disabled in mulet.
|
||||
pref("dom.serviceWorkers.enabled", false);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="70077825aab2c7a79611befb40a5fe7e610d5443"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e1773d6d1014c997be4b5c4233bba3ee073b8d7b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="70077825aab2c7a79611befb40a5fe7e610d5443"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e1773d6d1014c997be4b5c4233bba3ee073b8d7b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="70077825aab2c7a79611befb40a5fe7e610d5443"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e1773d6d1014c997be4b5c4233bba3ee073b8d7b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="70077825aab2c7a79611befb40a5fe7e610d5443"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e1773d6d1014c997be4b5c4233bba3ee073b8d7b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="70077825aab2c7a79611befb40a5fe7e610d5443"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e1773d6d1014c997be4b5c4233bba3ee073b8d7b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="70077825aab2c7a79611befb40a5fe7e610d5443"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e1773d6d1014c997be4b5c4233bba3ee073b8d7b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="70077825aab2c7a79611befb40a5fe7e610d5443"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e1773d6d1014c997be4b5c4233bba3ee073b8d7b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="70077825aab2c7a79611befb40a5fe7e610d5443"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e1773d6d1014c997be4b5c4233bba3ee073b8d7b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "70077825aab2c7a79611befb40a5fe7e610d5443",
|
||||
"git_revision": "e1773d6d1014c997be4b5c4233bba3ee073b8d7b",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "536698903e2c4c12a3ff6c6d83f70278fab7311d",
|
||||
"revision": "172680469094791e563268fa7d074fee9e0105ab",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="70077825aab2c7a79611befb40a5fe7e610d5443"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e1773d6d1014c997be4b5c4233bba3ee073b8d7b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="70077825aab2c7a79611befb40a5fe7e610d5443"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e1773d6d1014c997be4b5c4233bba3ee073b8d7b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -13,8 +13,7 @@ var gPluginHandler = {
|
|||
"PluginContent:HideNotificationBar",
|
||||
"PluginContent:ShowInstallNotification",
|
||||
"PluginContent:InstallSinglePlugin",
|
||||
"PluginContent:ShowNPAPIPluginCrashedNotification",
|
||||
"PluginContent:ShowGMPCrashedNotification",
|
||||
"PluginContent:ShowPluginCrashedNotification",
|
||||
"PluginContent:SubmitReport",
|
||||
"PluginContent:LinkClickCallback",
|
||||
],
|
||||
|
@ -62,15 +61,9 @@ var gPluginHandler = {
|
|||
case "PluginContent:InstallSinglePlugin":
|
||||
this.installSinglePlugin(msg.data.pluginInfo);
|
||||
break;
|
||||
case "PluginContent:ShowNPAPIPluginCrashedNotification":
|
||||
this.showNPAPIPluginCrashedNotification(msg.target, msg.data.message,
|
||||
msg.data.runID);
|
||||
break;
|
||||
case "PluginContent:ShowGMPCrashedNotification":
|
||||
this.showGMPCrashedNotification(msg.target,
|
||||
msg.data.messageString,
|
||||
msg.data.pluginDumpID,
|
||||
msg.data.browserDumpID);
|
||||
case "PluginContent:ShowPluginCrashedNotification":
|
||||
this.showPluginCrashedNotification(msg.target, msg.data.messageString,
|
||||
msg.data.pluginID);
|
||||
break;
|
||||
case "PluginContent:SubmitReport":
|
||||
if (AppConstants.MOZ_CRASHREPORTER) {
|
||||
|
@ -498,63 +491,32 @@ var gPluginHandler = {
|
|||
{ pluginName, runID, state });
|
||||
},
|
||||
|
||||
showNPAPIPluginCrashedNotification: function (browser, messageString, runID) {
|
||||
let crashReportCallback;
|
||||
|
||||
if (AppConstants.MOZ_CRASHREPORTER &&
|
||||
PluginCrashReporter.hasCrashReport(runID)) {
|
||||
crashReportCallback = () => {
|
||||
PluginCrashReporter.submitCrashReport(runID);
|
||||
};
|
||||
}
|
||||
|
||||
this._showPluginCrashedNotification(browser, messageString, crashReportCallback);
|
||||
},
|
||||
|
||||
/**
|
||||
* For now, GMP crashes are handled separately from NPAPI plugin crashes,
|
||||
* since the latter are not yet working for e10s. These will be unified
|
||||
* once e10s support is added for GMP crash reporting in bug 1146955.
|
||||
*/
|
||||
showGMPCrashedNotification: function (browser, messageString,
|
||||
pluginDumpID, browserDumpID) {
|
||||
let crashReportCallback;
|
||||
|
||||
if (AppConstants.MOZ_CRASHREPORTER && pluginDumpID) {
|
||||
crashReportCallback = () => {
|
||||
PluginCrashReporter.submitGMPCrashReport(pluginDumpID, browserDumpID);
|
||||
};
|
||||
}
|
||||
|
||||
this._showPluginCrashedNotification(browser, messageString, crashReportCallback);
|
||||
},
|
||||
|
||||
/**
|
||||
* A helper function for showing the plugin crashed notification bar.
|
||||
* Shows a plugin-crashed notification bar for a browser that has had an
|
||||
* invisiable NPAPI plugin crash, or a GMP plugin crash.
|
||||
*
|
||||
* @param browser
|
||||
* The browser that contains the crashing plugin.
|
||||
* The browser to show the notification for.
|
||||
* @param messageString
|
||||
* The message to display in the notification.
|
||||
* @param crashReportCallback
|
||||
* Optional. Pass a function to submit a crash report for this plugin
|
||||
* crash if a report exists. If no function is passed, the Submit Report
|
||||
* button will not be added.
|
||||
* The string to put in the notification bar
|
||||
* @param pluginID
|
||||
* The unique-per-process identifier for the NPAPI plugin or GMP.
|
||||
* For a GMP, this is the pluginID. For NPAPI plugins (where "pluginID"
|
||||
* means something different), this is the runID.
|
||||
*/
|
||||
_showPluginCrashedNotification: function (browser, messageString, crashReportCallback) {
|
||||
showPluginCrashedNotification: function (browser, messageString, pluginID) {
|
||||
// If there's already an existing notification bar, don't do anything.
|
||||
let notificationBox = gBrowser.getNotificationBox(browser);
|
||||
let notification = notificationBox.getNotificationWithValue("plugin-crashed");
|
||||
if (notification)
|
||||
if (notification) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure the notification bar
|
||||
let priority = notificationBox.PRIORITY_WARNING_MEDIUM;
|
||||
let iconURL = "chrome://mozapps/skin/plugins/notifyPluginCrashed.png";
|
||||
let reloadLabel = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.label");
|
||||
let reloadKey = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.accesskey");
|
||||
let submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label");
|
||||
let submitKey = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey");
|
||||
|
||||
let buttons = [{
|
||||
label: reloadLabel,
|
||||
|
@ -563,12 +525,17 @@ var gPluginHandler = {
|
|||
callback: function() { browser.reload(); },
|
||||
}];
|
||||
|
||||
if (AppConstants.MOZ_CRASHREPORTER && crashReportCallback) {
|
||||
if (AppConstants.MOZ_CRASHREPORTER &&
|
||||
PluginCrashReporter.hasCrashReport(pluginID)) {
|
||||
let submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label");
|
||||
let submitKey = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey");
|
||||
let submitButton = {
|
||||
label: submitLabel,
|
||||
accessKey: submitKey,
|
||||
popup: null,
|
||||
callback: crashReportCallback,
|
||||
callback: () => {
|
||||
PluginCrashReporter.submitCrashReport(pluginID);
|
||||
},
|
||||
};
|
||||
|
||||
buttons.push(submitButton);
|
||||
|
@ -585,11 +552,9 @@ var gPluginHandler = {
|
|||
let crashurl = formatURL("app.support.baseURL", true);
|
||||
crashurl += "plugin-crashed-notificationbar";
|
||||
link.href = crashurl;
|
||||
|
||||
let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
|
||||
description.appendChild(link);
|
||||
},
|
||||
};
|
||||
|
||||
gPluginHandler.init();
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/**
|
||||
* Test that plugin crash submissions still work properly after
|
||||
* click-to-play activation.
|
||||
* Test that the notification bar for crashed GMPs works.
|
||||
*/
|
||||
add_task(function*() {
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
|
@ -9,9 +8,8 @@ add_task(function*() {
|
|||
}, function* (browser) {
|
||||
yield ContentTask.spawn(browser, null, function* () {
|
||||
const GMP_CRASH_EVENT = {
|
||||
pluginID: 1,
|
||||
pluginName: "GlobalTestPlugin",
|
||||
pluginDumpID: "1234",
|
||||
browserDumpID: "5678",
|
||||
submittedCrashReport: false,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
# 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/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
exclude_files = \
|
||||
test \
|
||||
README.mozilla \
|
||||
$(NULL)
|
||||
|
||||
$(FINAL_TARGET)/chrome/pdfjs.manifest: $(GLOBAL_DEPS)
|
||||
printf 'manifest pdfjs/chrome.manifest' > $@
|
||||
|
||||
libs:: $(FINAL_TARGET)/chrome/pdfjs.manifest
|
||||
$(PYTHON) $(topsrcdir)/config/nsinstall.py \
|
||||
$(srcdir)/pdfjs \
|
||||
$(foreach exclude,$(exclude_files), -X $(srcdir)/pdfjs/$(exclude)) \
|
||||
$(FINAL_TARGET)/chrome
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest 'manifest chrome/pdfjs.manifest')
|
||||
|
||||
ifdef NIGHTLY_BUILD
|
||||
$(FINAL_TARGET)/chrome/shumway.manifest: $(GLOBAL_DEPS)
|
||||
printf 'manifest shumway/chrome.manifest' > $@
|
||||
|
||||
libs:: $(FINAL_TARGET)/chrome/shumway.manifest
|
||||
$(PYTHON) $(topsrcdir)/config/nsinstall.py \
|
||||
$(srcdir)/shumway \
|
||||
$(foreach exclude,$(exclude_files), -X $(srcdir)/shumway/$(exclude)) \
|
||||
$(FINAL_TARGET)/chrome
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest 'manifest chrome/shumway.manifest')
|
||||
endif
|
|
@ -4,4 +4,7 @@
|
|||
# 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/.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['pdfjs/test/browser.ini']
|
||||
DIRS += [
|
||||
'pdfjs',
|
||||
'shumway',
|
||||
]
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
pdfjs.jar:
|
||||
% resource pdf.js %content/
|
||||
content/ (content/*)
|
|
@ -0,0 +1,9 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
|
@ -0,0 +1,5 @@
|
|||
shumway.jar:
|
||||
% content shumway %chrome/
|
||||
% resource shumway %content/
|
||||
chrome/ (chrome/*)
|
||||
content/ (content/*)
|
|
@ -0,0 +1,7 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
|
@ -795,11 +795,7 @@ Function LaunchApp
|
|||
${GetParameters} $0
|
||||
${GetOptions} "$0" "/UAC:" $1
|
||||
${If} ${Errors}
|
||||
StrCpy $1 "0"
|
||||
StrCpy $2 "0"
|
||||
${If} $1 == "1"
|
||||
Exec "$\"$INSTDIR\${FileMainEXE}$\""
|
||||
${EndIf}
|
||||
Exec "$\"$INSTDIR\${FileMainEXE}$\""
|
||||
${Else}
|
||||
GetFunctionAddress $0 LaunchAppFromElevatedProcess
|
||||
UAC::ExecCodeSegment $0
|
||||
|
@ -816,12 +812,7 @@ Function LaunchAppFromElevatedProcess
|
|||
; Set our current working directory to the application's install directory
|
||||
; otherwise the 7-Zip temp directory will be in use and won't be deleted.
|
||||
SetOutPath "$1"
|
||||
StrCpy $2 "0"
|
||||
StrCpy $3 "0"
|
||||
${If} $2 == "1"
|
||||
; Launch into desktop
|
||||
Exec "$\"$0$\""
|
||||
${EndIf}
|
||||
Exec "$\"$0$\""
|
||||
FunctionEnd
|
||||
|
||||
################################################################################
|
||||
|
|
|
@ -114,27 +114,68 @@ this.PluginCrashReporter = {
|
|||
this.crashReports = new Map();
|
||||
|
||||
Services.obs.addObserver(this, "plugin-crashed", false);
|
||||
Services.obs.addObserver(this, "gmp-plugin-crash", false);
|
||||
Services.obs.addObserver(this, "profile-after-change", false);
|
||||
},
|
||||
|
||||
uninit() {
|
||||
Services.obs.removeObserver(this, "plugin-crashed", false);
|
||||
Services.obs.removeObserver(this, "gmp-plugin-crash", false);
|
||||
Services.obs.removeObserver(this, "profile-after-change", false);
|
||||
this.initialized = false;
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
if (topic != "plugin-crashed") {
|
||||
return;
|
||||
}
|
||||
switch(topic) {
|
||||
case "plugin-crashed": {
|
||||
let propertyBag = subject;
|
||||
if (!(propertyBag instanceof Ci.nsIPropertyBag2) ||
|
||||
!(propertyBag instanceof Ci.nsIWritablePropertyBag2) ||
|
||||
!propertyBag.hasKey("runID") ||
|
||||
!propertyBag.hasKey("pluginDumpID")) {
|
||||
Cu.reportError("PluginCrashReporter can not read plugin information.");
|
||||
return;
|
||||
}
|
||||
|
||||
let propertyBag = subject;
|
||||
if (!(propertyBag instanceof Ci.nsIPropertyBag2) ||
|
||||
!(propertyBag instanceof Ci.nsIWritablePropertyBag2) ||
|
||||
!propertyBag.hasKey("runID") ||
|
||||
!propertyBag.hasKey("pluginName")) {
|
||||
Cu.reportError("PluginCrashReporter can not read plugin information.");
|
||||
return;
|
||||
}
|
||||
let runID = propertyBag.getPropertyAsUint32("runID");
|
||||
let pluginDumpID = propertyBag.getPropertyAsAString("pluginDumpID");
|
||||
let browserDumpID = propertyBag.getPropertyAsAString("browserDumpID");
|
||||
if (pluginDumpID) {
|
||||
this.crashReports.set(runID, { pluginDumpID, browserDumpID });
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "gmp-plugin-crash": {
|
||||
let propertyBag = subject;
|
||||
if (!(propertyBag instanceof Ci.nsIWritablePropertyBag2) ||
|
||||
!propertyBag.hasKey("pluginID") ||
|
||||
!propertyBag.hasKey("pluginDumpID") ||
|
||||
!propertyBag.hasKey("pluginName")) {
|
||||
Cu.reportError("PluginCrashReporter can not read plugin information.");
|
||||
return;
|
||||
}
|
||||
|
||||
let runID = propertyBag.getPropertyAsUint32("runID");
|
||||
let pluginDumpID = propertyBag.getPropertyAsAString("pluginDumpID");
|
||||
let browserDumpID = propertyBag.getPropertyAsAString("browserDumpID");
|
||||
if (pluginDumpID) {
|
||||
this.crashReports.set(runID, { pluginDumpID, browserDumpID });
|
||||
let pluginID = propertyBag.getPropertyAsUint32("pluginID");
|
||||
let pluginDumpID = propertyBag.getPropertyAsAString("pluginDumpID");
|
||||
if (pluginDumpID) {
|
||||
this.crashReports.set(pluginID, { pluginDumpID });
|
||||
}
|
||||
|
||||
// Only the parent process gets the gmp-plugin-crash observer
|
||||
// notification, so we need to inform any content processes that
|
||||
// the GMP has crashed.
|
||||
if (Cc["@mozilla.org/parentprocessmessagemanager;1"]) {
|
||||
let pluginName = propertyBag.getPropertyAsAString("pluginName");
|
||||
let mm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
|
||||
.getService(Ci.nsIMessageListenerManager);
|
||||
mm.broadcastAsyncMessage("gmp-plugin-crash",
|
||||
{ pluginName, pluginID });
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "profile-after-change":
|
||||
this.uninit();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -194,14 +235,4 @@ this.PluginCrashReporter = {
|
|||
hasCrashReport(runID) {
|
||||
return this.crashReports.has(runID);
|
||||
},
|
||||
|
||||
/**
|
||||
* Deprecated mechanism for sending crash reports for GMPs. This
|
||||
* should be removed when bug 1146955 is fixed.
|
||||
*/
|
||||
submitGMPCrashReport(pluginDumpID, browserDumpID) {
|
||||
CrashSubmit.submit(pluginDumpID, { recordSubmission: true });
|
||||
if (browserDumpID)
|
||||
CrashSubmit.submit(browserDumpID);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1031,8 +1031,8 @@ PluginContent.prototype = {
|
|||
// If another plugin on the page was large enough to show our UI, we don't
|
||||
// want to show a notification bar.
|
||||
if (!doc.mozNoPluginCrashedNotification) {
|
||||
this.global.sendAsyncMessage("PluginContent:ShowNPAPIPluginCrashedNotification",
|
||||
{ message, runID });
|
||||
this.global.sendAsyncMessage("PluginContent:ShowPluginCrashedNotification",
|
||||
{ messageString: message, pluginID: runID });
|
||||
// Remove the notification when the page is reloaded.
|
||||
doc.defaultView.top.addEventListener("unload", event => {
|
||||
this.hideNotificationBar("plugin-crashed");
|
||||
|
@ -1057,17 +1057,11 @@ PluginContent.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Currently, GMP crash events are only handled in the non-e10s case.
|
||||
* e10s support for GMP crash events is being tracked in bug 1146955.
|
||||
*/
|
||||
GMPCrashed: function(aEvent) {
|
||||
let target = aEvent.target;
|
||||
let submittedReport = aEvent.submittedCrashReport;
|
||||
let pluginName = aEvent.pluginName;
|
||||
let pluginDumpID = aEvent.pluginDumpID;
|
||||
let browserDumpID = aEvent.browserDumpID;
|
||||
let gmpPlugin = aEvent.gmpPlugin;
|
||||
let pluginID = aEvent.pluginID;
|
||||
let doc = target.document;
|
||||
|
||||
if (!gmpPlugin || !doc) {
|
||||
|
@ -1079,11 +1073,8 @@ PluginContent.prototype = {
|
|||
gNavigatorBundle.formatStringFromName("crashedpluginsMessage.title",
|
||||
[pluginName], 1);
|
||||
|
||||
this.global.sendAsyncMessage("PluginContent:ShowGMPCrashedNotification", {
|
||||
messageString: messageString,
|
||||
pluginDumpID: pluginDumpID,
|
||||
browserDumpID: browserDumpID,
|
||||
});
|
||||
this.global.sendAsyncMessage("PluginContent:ShowPluginCrashedNotification",
|
||||
{ messageString, pluginID });
|
||||
|
||||
// Remove the notification when the page is reloaded.
|
||||
doc.defaultView.top.addEventListener("unload", event => {
|
||||
|
|
|
@ -59,6 +59,15 @@ file from the alternate localization source tree
|
|||
|
||||
locale/path/localized.dtd (%localized/path/localized.dtd)
|
||||
|
||||
The source tree location can also use wildcards, in which case the path in
|
||||
jar is expected to be a base directory. Paths before the wildcard are not
|
||||
made part of the destination path::
|
||||
|
||||
path/in/jar/ (source/tree/location/*.xul)
|
||||
|
||||
The above will install all xul files under ``source/tree/location`` as
|
||||
``path/in/jar/*.xul``.
|
||||
|
||||
Register Chrome
|
||||
===============
|
||||
|
||||
|
|
|
@ -279,8 +279,9 @@ class RemoteAutomation(Automation):
|
|||
self.procName = app
|
||||
print "Robocop process name: "+self.procName
|
||||
|
||||
# Setting timeout at 1 hour since on a remote device this takes much longer
|
||||
self.timeout = 3600
|
||||
# Setting timeout at 1 hour since on a remote device this takes much longer.
|
||||
# Temporarily increased to 75 minutes because no more chunks can be created.
|
||||
self.timeout = 4500
|
||||
# The benefit of the following sleep is unclear; it was formerly 15 seconds
|
||||
time.sleep(1)
|
||||
|
||||
|
|
|
@ -3577,7 +3577,7 @@ MOZ_ARG_WITH_BOOL(system-nss,
|
|||
_USE_SYSTEM_NSS=1 )
|
||||
|
||||
if test -n "$_USE_SYSTEM_NSS"; then
|
||||
AM_PATH_NSS(3.18, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
|
||||
AM_PATH_NSS(3.19, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_NATIVE_NSS"; then
|
||||
|
|
|
@ -355,6 +355,23 @@ let Activities = {
|
|||
calleeApp.appStatus !== Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the activity is in the developer mode activity list, only let the
|
||||
// system app be a provider.
|
||||
let isSystemApp = false;
|
||||
let isDevModeActivity = false;
|
||||
try {
|
||||
isSystemApp =
|
||||
aResult.manifest == Services.prefs.getCharPref("b2g.system_manifest_url");
|
||||
isDevModeActivity =
|
||||
Services.prefs.getCharPref("dom.activities.developer_mode_only")
|
||||
.split(",").indexOf(aMsg.options.name) !== -1;
|
||||
} catch(e) {}
|
||||
|
||||
if (isDevModeActivity && !isSystemApp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ActivitiesServiceFilter.match(aMsg.options.data,
|
||||
aResult.description.filters);
|
||||
};
|
||||
|
|
|
@ -69,6 +69,22 @@ ActivityProxy.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Check the activities that are restricted to be used in dev mode.
|
||||
let devMode = false;
|
||||
let isDevModeActivity = false;
|
||||
try {
|
||||
devMode = Services.prefs.getBoolPref("dom.apps.developer_mode");
|
||||
isDevModeActivity =
|
||||
Services.prefs.getCharPref("dom.activities.developer_mode_only")
|
||||
.split(",").indexOf(aOptions.name) !== -1;
|
||||
|
||||
} catch(e) {}
|
||||
if (isDevModeActivity && !devMode) {
|
||||
Services.DOMRequest.fireErrorAsync(this.activity, "SecurityError");
|
||||
Services.obs.notifyObservers(null, "Activity:Error", null);
|
||||
return;
|
||||
}
|
||||
|
||||
cpmm.addMessageListener("Activity:FireSuccess", this);
|
||||
cpmm.addMessageListener("Activity:FireError", this);
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ DIRS += ['interfaces']
|
|||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['tests/mochi/mochitest.ini']
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Activity.h',
|
||||
]
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "Random app",
|
||||
"activities": {
|
||||
"import-app": { "blob": { "required": true } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Content-Type: application/manifest+json
|
|
@ -0,0 +1,9 @@
|
|||
[DEFAULT]
|
||||
skip-if = e10s
|
||||
support-files =
|
||||
system.webapp
|
||||
system.webapp^headers^
|
||||
manifest.webapp
|
||||
manifest.webapp^headers^
|
||||
|
||||
[test_dev_mode_activity.html]
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "System app",
|
||||
"activities": {
|
||||
"import-app": { "blob": { "required": true } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Content-Type: application/manifest+json
|
|
@ -0,0 +1,290 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id={1123846}
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug {1123846}</title>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/chrome-harness.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={1123846}">Mozilla Bug {1123846}</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
|
||||
/**
|
||||
* Tests the developer mode activities that can only be provided by the
|
||||
* system app.
|
||||
*
|
||||
* We test the following:
|
||||
* 1) No dev mode, no system app installed (failure).
|
||||
* 2) No dev mode, system app installed (failure).
|
||||
* 3) No dev mode, system app and other app installed (failure).
|
||||
* 4) Dev mode, system app and other app installed (success, only system app returned).
|
||||
*/
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
var gRootUrl = "http://test/chrome/dom/activities/tests/mochi/";
|
||||
var gGenerator = runTest();
|
||||
|
||||
function go() {
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ "type": "webapps-manage", "allow": 1, "context": document },
|
||||
{ "type": "browser", "allow": 1, "context": document },
|
||||
{ "type": "embed-apps", "allow": 1, "context": document }],
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{'set': [["dom.mozBrowserFramesEnabled", true],
|
||||
["dom.sysmsg.enabled", true],
|
||||
["dom.apps.developer_mode", false],
|
||||
["dom.activities.developer_mode_only", "import-app"]]},
|
||||
continueTest) });
|
||||
}
|
||||
|
||||
function cbError(aEvent) {
|
||||
ok(false, "Error callback invoked " +
|
||||
aEvent.target.error.name + " " + aEvent.target.error.message);
|
||||
finish();
|
||||
}
|
||||
|
||||
function unexpectedSuccess(aMsg) {
|
||||
return function() {
|
||||
ok(false, "Should not have succeeded: " + aMsg);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var systemAppUrl = gRootUrl + "system.webapp";
|
||||
var otherAppUrl = gRootUrl + "manifest.webapp";
|
||||
|
||||
function installApp(aUrl) {
|
||||
var request = navigator.mozApps.install(aUrl, { });
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
return request;
|
||||
}
|
||||
|
||||
function installSystemApp() {
|
||||
return installApp(systemAppUrl);
|
||||
}
|
||||
|
||||
function installOtherApp() {
|
||||
return installApp(otherAppUrl);
|
||||
}
|
||||
|
||||
function uninstall(aApp) {
|
||||
info("Uninstalling " + (aApp ? aApp.manifestURL : "NO APP!!"));
|
||||
var request = navigator.mozApps.mgmt.uninstall(aApp);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
}
|
||||
|
||||
function registerComponent(aObject, aDescription, aContract) {
|
||||
var uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator);
|
||||
var cid = uuidGenerator.generateUUID();
|
||||
|
||||
info("Registering " + cid);
|
||||
|
||||
var componentManager =
|
||||
Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
componentManager.registerFactory(cid, aDescription, aContract, aObject);
|
||||
|
||||
// Keep the id on the object so we can unregister later.
|
||||
aObject.cid = cid;
|
||||
}
|
||||
|
||||
function unregisterComponent(aObject) {
|
||||
info("Unregistering " + aObject.cid);
|
||||
var componentManager =
|
||||
Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
componentManager.unregisterFactory(aObject.cid, aObject);
|
||||
}
|
||||
|
||||
var ActivityGlue = {
|
||||
// nsISupports implementation.
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsIFactory) ||
|
||||
iid.equals(Ci.nsIActivityUIGlue)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
// nsIFactory implementation.
|
||||
createInstance: function(outer, iid) {
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
// nsIActivityUIGlue implementation.
|
||||
chooseActivity: function(aOptions, aActivities, aCallback) {
|
||||
aCallback.handleEvent(Ci.nsIActivityUIGlueCallback.WEBAPPS_ACTIVITY,
|
||||
aActivities.length == 1 ? 0 : -1);
|
||||
}
|
||||
};
|
||||
|
||||
var SystemMessageGlue = {
|
||||
// nsISupports implementation.
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsIFactory) ||
|
||||
iid.equals(Ci.nsISystemMessageGlue)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
// nsIFactory implementation.
|
||||
createInstance: function(outer, iid) {
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
// nsISystemMessageGlue implementation.
|
||||
openApp(pageURL, manifestURL, type, target, showApp, onlyShowApp, extra) {
|
||||
// We should only try to open a page in the sytem app.
|
||||
is(manifestURL, systemAppUrl, "Opening a page in the system app.");
|
||||
}
|
||||
};
|
||||
|
||||
registerComponent(ActivityGlue,
|
||||
"Activity Glue",
|
||||
"@mozilla.org/dom/activities/ui-glue;1");
|
||||
|
||||
registerComponent(SystemMessageGlue,
|
||||
"System Message Glue",
|
||||
"@mozilla.org/dom/messages/system-message-glue;1");
|
||||
|
||||
function finish() {
|
||||
unregisterComponent(ActivityGlue);
|
||||
unregisterComponent(SystemMessageGlue);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function continueTest() {
|
||||
try {
|
||||
gGenerator.next();
|
||||
} catch (e if e instanceof StopIteration) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test exporting and importing hosted and packaged apps.
|
||||
*/
|
||||
function runTest() {
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
// Check how many apps we are starting with.
|
||||
var request = navigator.mozApps.mgmt.getAll();
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
yield undefined;
|
||||
var initialAppsCount = request.result.length;
|
||||
info("Starting with " + initialAppsCount + " apps installed.");
|
||||
|
||||
// 1) No dev mode, no system app installed (failure).
|
||||
var activity = new MozActivity({ name: "import-app" });
|
||||
activity.onerror = function() {
|
||||
ok(true, "1) No dev mode, no system app installed");
|
||||
continueTest();
|
||||
}
|
||||
activity.onsuccess = unexpectedSuccess("1) No dev mode, no system app installed");
|
||||
yield undefined;
|
||||
|
||||
|
||||
// 2) No dev mode, system app installed (failure).
|
||||
// Configure the system app manifest url.
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{'set': [["b2g.system_manifest_url", systemAppUrl]]},
|
||||
continueTest);
|
||||
yield undefined;
|
||||
|
||||
// Install the system app.
|
||||
request = installSystemApp();
|
||||
yield undefined;
|
||||
var systemApp = request.result;
|
||||
ok(systemApp, "systemApp is non-null");
|
||||
|
||||
activity = new MozActivity({ name: "import-app" });
|
||||
activity.onerror = function() {
|
||||
ok(true, "2) No dev mode, system app installed");
|
||||
continueTest();
|
||||
}
|
||||
activity.onsuccess = unexpectedSuccess("2) No dev mode, system app installed");
|
||||
yield undefined;
|
||||
|
||||
// 3) No dev mode, system app and other app installed (failure).
|
||||
request = installOtherApp();
|
||||
yield undefined;
|
||||
var otherApp = request.result;
|
||||
ok(otherApp, "otherApp is non-null");
|
||||
|
||||
activity = new MozActivity({ name: "import-app" });
|
||||
activity.onerror = function() {
|
||||
ok(true, "3) No dev mode, system app and other app installed");
|
||||
continueTest();
|
||||
}
|
||||
activity.onsuccess = unexpectedSuccess("3) No dev mode, system app and other app installed");
|
||||
yield undefined;
|
||||
|
||||
// 4) Dev mode, no system app installed.
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{'set': [["dom.apps.developer_mode", true]]},
|
||||
continueTest);
|
||||
yield undefined;
|
||||
|
||||
activity = new MozActivity({ name: "import-app" });
|
||||
activity.onsuccess = function() {
|
||||
ok(true, "4) Dev mode, system app and other app installed");
|
||||
continueTest();
|
||||
}
|
||||
activity.onerror = function(aError) {
|
||||
ok(false, "Got error: " + aError.name);
|
||||
finish();
|
||||
}
|
||||
yield undefined;
|
||||
|
||||
// Cleanup
|
||||
uninstall(systemApp);
|
||||
yield undefined;
|
||||
|
||||
uninstall(otherApp);
|
||||
yield undefined;
|
||||
|
||||
// Check that we restored the app registry.
|
||||
request = navigator.mozApps.mgmt.getAll();
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
yield undefined;
|
||||
|
||||
is(request.result.length, initialAppsCount, "All apps are uninstalled.");
|
||||
}
|
||||
|
||||
addLoadEvent(go);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -139,6 +139,7 @@
|
|||
#include "mozilla/dom/WindowBinding.h"
|
||||
#include "mozilla/dom/ElementBinding.h"
|
||||
#include "mozilla/dom/VRDevice.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -385,7 +386,7 @@ Element::GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult)
|
|||
IsHTMLElement(nsGkAtoms::object) ||
|
||||
IsHTMLElement(nsGkAtoms::embed) ||
|
||||
IsHTMLElement(nsGkAtoms::applet));
|
||||
nsIPresShell *shell = aDocument->GetShell();
|
||||
nsCOMPtr<nsIPresShell> shell = aDocument->GetShell();
|
||||
if (!shell || GetPrimaryFrame() || !isXULorPluginElement) {
|
||||
*aResult = nullptr;
|
||||
|
||||
|
@ -393,11 +394,8 @@ Element::GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult)
|
|||
}
|
||||
|
||||
// Get the computed -moz-binding directly from the style context
|
||||
nsPresContext *pctx = shell->GetPresContext();
|
||||
NS_ENSURE_TRUE(pctx, false);
|
||||
|
||||
nsRefPtr<nsStyleContext> sc = pctx->StyleSet()->ResolveStyleFor(this,
|
||||
nullptr);
|
||||
nsRefPtr<nsStyleContext> sc =
|
||||
nsComputedDOMStyle::GetStyleContextForElementNoFlush(this, nullptr, shell);
|
||||
NS_ENSURE_TRUE(sc, false);
|
||||
|
||||
*aResult = sc->StyleDisplay()->mBinding;
|
||||
|
|
|
@ -10398,7 +10398,7 @@ class CGDOMJSProxyHandler_getOwnPropDescriptor(ClassMethod):
|
|||
$*{getIndexed}
|
||||
JS::Rooted<JSObject*> expando(cx);
|
||||
if (!isXray && (expando = GetExpandoObject(proxy))) {
|
||||
if (!JS_GetPropertyDescriptorById(cx, expando, id, desc)) {
|
||||
if (!JS_GetOwnPropertyDescriptorById(cx, expando, id, desc)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.object()) {
|
||||
|
|
|
@ -210,25 +210,12 @@ DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<jsid> id,
|
|||
|
||||
// Make sure to ignore our named properties when checking for own
|
||||
// property descriptors for a set.
|
||||
JS::Rooted<JSPropertyDescriptor> desc(cx);
|
||||
JS::Rooted<JSPropertyDescriptor> ownDesc(cx);
|
||||
if (!getOwnPropDescriptor(cx, proxy, id, /* ignoreNamedProps = */ true,
|
||||
&desc)) {
|
||||
&ownDesc)) {
|
||||
return false;
|
||||
}
|
||||
if (!desc.object()) {
|
||||
// Don't just use getPropertyDescriptor, unlike BaseProxyHandler::set,
|
||||
// because that would call getOwnPropertyDescriptor on ourselves. Instead,
|
||||
// directly delegate to the proto, if any.
|
||||
JS::Rooted<JSObject*> proto(cx);
|
||||
if (!js::GetObjectProto(cx, proxy, &proto)) {
|
||||
return false;
|
||||
}
|
||||
if (proto && !JS_GetPropertyDescriptorById(cx, proto, id, &desc)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return js::SetPropertyIgnoringNamedGetter(cx, proxy, id, v, receiver, desc, result);
|
||||
return js::SetPropertyIgnoringNamedGetter(cx, proxy, id, v, receiver, ownDesc, result);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -400,7 +400,8 @@ TypeUtils::ProcessURL(nsAString& aUrl, bool* aSchemeValidOut,
|
|||
if (aSchemeValidOut) {
|
||||
nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
|
||||
*aSchemeValidOut = scheme.LowerCaseEqualsLiteral("http") ||
|
||||
scheme.LowerCaseEqualsLiteral("https");
|
||||
scheme.LowerCaseEqualsLiteral("https") ||
|
||||
scheme.LowerCaseEqualsLiteral("app");
|
||||
}
|
||||
|
||||
uint32_t queryPos;
|
||||
|
|
|
@ -290,10 +290,7 @@ void MediaDecoder::Pause()
|
|||
void MediaDecoder::SetVolume(double aVolume)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mInitialVolume = aVolume;
|
||||
if (mDecoderStateMachine) {
|
||||
mDecoderStateMachine->SetVolume(aVolume);
|
||||
}
|
||||
mVolume = aVolume;
|
||||
}
|
||||
|
||||
void MediaDecoder::ConnectDecodedStreamToOutputStream(OutputStreamData* aStream)
|
||||
|
@ -538,7 +535,7 @@ void MediaDecoder::AddOutputStream(ProcessedMediaStream* aStream,
|
|||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
if (mDecoderStateMachine) {
|
||||
mDecoderStateMachine->SetAudioCaptured();
|
||||
mDecoderStateMachine->DispatchAudioCaptured();
|
||||
}
|
||||
if (!GetDecodedStream()) {
|
||||
int64_t t = mDecoderStateMachine ?
|
||||
|
@ -602,9 +599,9 @@ MediaDecoder::MediaDecoder() :
|
|||
mDecoderPosition(0),
|
||||
mPlaybackPosition(0),
|
||||
mCurrentTime(0.0),
|
||||
mInitialVolume(0.0),
|
||||
mInitialPlaybackRate(1.0),
|
||||
mInitialPreservesPitch(true),
|
||||
mVolume(AbstractThread::MainThread(), 0.0, "MediaDecoder::mVolume (Canonical)"),
|
||||
mPlaybackRate(AbstractThread::MainThread(), 1.0, "MediaDecoder::mPlaybackRate (Canonical)"),
|
||||
mPreservesPitch(AbstractThread::MainThread(), true, "MediaDecoder::mPreservesPitch (Canonical)"),
|
||||
mDuration(-1),
|
||||
mMediaSeekable(true),
|
||||
mSameOriginMedia(false),
|
||||
|
@ -750,21 +747,23 @@ void MediaDecoder::SetStateMachineParameters()
|
|||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
mDecoderStateMachine->SetDuration(mDuration);
|
||||
mDecoderStateMachine->SetVolume(mInitialVolume);
|
||||
if (GetDecodedStream()) {
|
||||
mDecoderStateMachine->SetAudioCaptured();
|
||||
mDecoderStateMachine->DispatchAudioCaptured();
|
||||
}
|
||||
SetPlaybackRate(mInitialPlaybackRate);
|
||||
mDecoderStateMachine->SetPreservesPitch(mInitialPreservesPitch);
|
||||
if (mMinimizePreroll) {
|
||||
mDecoderStateMachine->SetMinimizePrerollUntilPlaybackStarts();
|
||||
mDecoderStateMachine->DispatchMinimizePrerollUntilPlaybackStarts();
|
||||
}
|
||||
}
|
||||
|
||||
void MediaDecoder::SetMinimizePrerollUntilPlaybackStarts()
|
||||
{
|
||||
DECODER_LOG("SetMinimizePrerollUntilPlaybackStarts()");
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mMinimizePreroll = true;
|
||||
|
||||
// This needs to be called before we init the state machine, otherwise it will
|
||||
// have no effect.
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mDecoderStateMachine);
|
||||
}
|
||||
|
||||
nsresult MediaDecoder::ScheduleStateMachineThread()
|
||||
|
@ -1550,11 +1549,10 @@ bool MediaDecoder::OnStateMachineTaskQueue() const
|
|||
|
||||
void MediaDecoder::SetPlaybackRate(double aPlaybackRate)
|
||||
{
|
||||
if (aPlaybackRate == 0.0) {
|
||||
mPlaybackRate = aPlaybackRate;
|
||||
if (mPlaybackRate == 0.0) {
|
||||
mPausedForPlaybackRateNull = true;
|
||||
mInitialPlaybackRate = aPlaybackRate;
|
||||
Pause();
|
||||
return;
|
||||
} else if (mPausedForPlaybackRateNull) {
|
||||
// Play() uses mPausedForPlaybackRateNull value, so must reset it first
|
||||
mPausedForPlaybackRateNull = false;
|
||||
|
@ -1564,21 +1562,11 @@ void MediaDecoder::SetPlaybackRate(double aPlaybackRate)
|
|||
Play();
|
||||
}
|
||||
}
|
||||
|
||||
if (mDecoderStateMachine) {
|
||||
mDecoderStateMachine->SetPlaybackRate(aPlaybackRate);
|
||||
} else {
|
||||
mInitialPlaybackRate = aPlaybackRate;
|
||||
}
|
||||
}
|
||||
|
||||
void MediaDecoder::SetPreservesPitch(bool aPreservesPitch)
|
||||
{
|
||||
if (mDecoderStateMachine) {
|
||||
mDecoderStateMachine->SetPreservesPitch(aPreservesPitch);
|
||||
} else {
|
||||
mInitialPreservesPitch = aPreservesPitch;
|
||||
}
|
||||
mPreservesPitch = aPreservesPitch;
|
||||
}
|
||||
|
||||
bool MediaDecoder::OnDecodeTaskQueue() const {
|
||||
|
|
|
@ -1079,14 +1079,22 @@ protected:
|
|||
// It is read and written from the main thread only.
|
||||
double mCurrentTime;
|
||||
|
||||
// Volume that playback should start at. 0.0 = muted. 1.0 = full
|
||||
// volume. Readable/Writeable from the main thread.
|
||||
double mInitialVolume;
|
||||
// Volume of playback. 0.0 = muted. 1.0 = full volume.
|
||||
Canonical<double> mVolume;
|
||||
public:
|
||||
AbstractCanonical<double>* CanonicalVolume() { return &mVolume; }
|
||||
protected:
|
||||
|
||||
// PlaybackRate and pitch preservation status we should start at.
|
||||
// Readable/Writeable from the main thread.
|
||||
double mInitialPlaybackRate;
|
||||
bool mInitialPreservesPitch;
|
||||
Canonical<double> mPlaybackRate;
|
||||
public:
|
||||
AbstractCanonical<double>* CanonicalPlaybackRate() { return &mPlaybackRate; }
|
||||
protected:
|
||||
|
||||
Canonical<bool> mPreservesPitch;
|
||||
public:
|
||||
AbstractCanonical<bool>* CanonicalPreservesPitch() { return &mPreservesPitch; }
|
||||
protected:
|
||||
|
||||
// Duration of the media resource. Set to -1 if unknown.
|
||||
// Set when the metadata is loaded. Accessed on the main thread
|
||||
|
|
|
@ -226,9 +226,10 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
|||
mDecodedAudioEndTime(-1),
|
||||
mVideoFrameEndTime(-1),
|
||||
mDecodedVideoEndTime(-1),
|
||||
mVolume(1.0),
|
||||
mVolume(mTaskQueue, 1.0, "MediaDecoderStateMachine::mVolume (Mirror)"),
|
||||
mPlaybackRate(1.0),
|
||||
mPreservesPitch(true),
|
||||
mLogicalPlaybackRate(mTaskQueue, 1.0, "MediaDecoderStateMachine::mLogicalPlaybackRate (Mirror)"),
|
||||
mPreservesPitch(mTaskQueue, true, "MediaDecoderStateMachine::mPreservesPitch (Mirror)"),
|
||||
mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS),
|
||||
mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS),
|
||||
mQuickBufferingLowDataThresholdUsecs(detail::QUICK_BUFFERING_LOW_DATA_USECS),
|
||||
|
@ -307,13 +308,21 @@ MediaDecoderStateMachine::InitializationTask()
|
|||
// Connect mirrors.
|
||||
mPlayState.Connect(mDecoder->CanonicalPlayState());
|
||||
mNextPlayState.Connect(mDecoder->CanonicalNextPlayState());
|
||||
mVolume.Connect(mDecoder->CanonicalVolume());
|
||||
mLogicalPlaybackRate.Connect(mDecoder->CanonicalPlaybackRate());
|
||||
mPreservesPitch.Connect(mDecoder->CanonicalPreservesPitch());
|
||||
|
||||
// Initialize watchers.
|
||||
mWatchManager.Watch(mState, &MediaDecoderStateMachine::UpdateNextFrameStatus);
|
||||
mWatchManager.Watch(mAudioCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus);
|
||||
mWatchManager.Watch(mVolume, &MediaDecoderStateMachine::VolumeChanged);
|
||||
mWatchManager.Watch(mLogicalPlaybackRate, &MediaDecoderStateMachine::LogicalPlaybackRateChanged);
|
||||
mWatchManager.Watch(mPreservesPitch, &MediaDecoderStateMachine::PreservesPitchChanged);
|
||||
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::HasFutureAudio() {
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
NS_ASSERTION(HasAudio(), "Should only call HasFutureAudio() when we have audio");
|
||||
// We've got audio ready to play if:
|
||||
|
@ -328,6 +337,7 @@ bool MediaDecoderStateMachine::HasFutureAudio() {
|
|||
}
|
||||
|
||||
bool MediaDecoderStateMachine::HaveNextFrameData() {
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
return (!HasAudio() || HasFutureAudio()) &&
|
||||
(!HasVideo() || VideoQueue().GetSize() > 0);
|
||||
|
@ -567,6 +577,7 @@ void MediaDecoderStateMachine::SendStreamData()
|
|||
MediaDecoderStateMachine::WakeDecoderRunnable*
|
||||
MediaDecoderStateMachine::GetWakeDecoderRunnable()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
|
||||
if (!mPendingWakeDecoder.get()) {
|
||||
|
@ -577,6 +588,7 @@ MediaDecoderStateMachine::GetWakeDecoderRunnable()
|
|||
|
||||
bool MediaDecoderStateMachine::HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
|
||||
if (AudioQueue().GetSize() == 0 ||
|
||||
|
@ -604,6 +616,7 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs)
|
|||
|
||||
bool MediaDecoderStateMachine::HaveEnoughDecodedVideo()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
|
||||
if (static_cast<uint32_t>(VideoQueue().GetSize()) < GetAmpleVideoFrames() * mPlaybackRate) {
|
||||
|
@ -628,6 +641,7 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedVideo()
|
|||
bool
|
||||
MediaDecoderStateMachine::NeedToDecodeVideo()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
return IsVideoDecoding() &&
|
||||
((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
|
||||
|
@ -639,6 +653,7 @@ MediaDecoderStateMachine::NeedToDecodeVideo()
|
|||
bool
|
||||
MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
if (mState == DECODER_STATE_DECODING_FIRSTFRAME) {
|
||||
return false;
|
||||
|
@ -688,6 +703,7 @@ MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
|
|||
bool
|
||||
MediaDecoderStateMachine::NeedToDecodeAudio()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
SAMPLE_LOG("NeedToDecodeAudio() isDec=%d decToTar=%d minPrl=%d seek=%d enufAud=%d",
|
||||
IsAudioDecoding(), mDecodeToSeekTarget, mMinimizePreroll,
|
||||
|
@ -706,6 +722,7 @@ MediaDecoderStateMachine::NeedToDecodeAudio()
|
|||
bool
|
||||
MediaDecoderStateMachine::IsAudioSeekComplete()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
SAMPLE_LOG("IsAudioSeekComplete() curTarVal=%d mAudDis=%d aqFin=%d aqSz=%d",
|
||||
mCurrentSeek.Exists(), mDropAudioUntilNextDiscontinuity, AudioQueue().IsFinished(), AudioQueue().GetSize());
|
||||
|
@ -719,6 +736,7 @@ MediaDecoderStateMachine::IsAudioSeekComplete()
|
|||
bool
|
||||
MediaDecoderStateMachine::IsVideoSeekComplete()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
SAMPLE_LOG("IsVideoSeekComplete() curTarVal=%d mVidDis=%d vqFin=%d vqSz=%d",
|
||||
mCurrentSeek.Exists(), mDropVideoUntilNextDiscontinuity, VideoQueue().IsFinished(), VideoQueue().GetSize());
|
||||
|
@ -1143,6 +1161,7 @@ MediaDecoderStateMachine::CheckIfSeekComplete()
|
|||
bool
|
||||
MediaDecoderStateMachine::IsAudioDecoding()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
return HasAudio() && !AudioQueue().IsFinished();
|
||||
}
|
||||
|
@ -1150,6 +1169,7 @@ MediaDecoderStateMachine::IsAudioDecoding()
|
|||
bool
|
||||
MediaDecoderStateMachine::IsVideoDecoding()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
return HasVideo() && !VideoQueue().IsFinished();
|
||||
}
|
||||
|
@ -1343,27 +1363,15 @@ void MediaDecoderStateMachine::SetState(State aState)
|
|||
mSentPlaybackEndedEvent = false;
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::SetVolume(double volume)
|
||||
void MediaDecoderStateMachine::VolumeChanged()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mVolume = volume;
|
||||
if (mAudioSink) {
|
||||
mAudioSink->SetVolume(mVolume);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::SetAudioCaptured()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
AssertCurrentThreadInMonitor();
|
||||
if (!mAudioCaptured) {
|
||||
mAudioCaptured = true;
|
||||
// Schedule the state machine to send stream data as soon as possible.
|
||||
ScheduleStateMachine();
|
||||
}
|
||||
}
|
||||
|
||||
double MediaDecoderStateMachine::GetCurrentTime() const
|
||||
{
|
||||
return static_cast<double>(mCurrentFrameTime) / static_cast<double>(USECS_PER_S);
|
||||
|
@ -1753,6 +1761,7 @@ void MediaDecoderStateMachine::StopAudioThread()
|
|||
nsresult
|
||||
MediaDecoderStateMachine::EnqueueDecodeFirstFrameTask()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME);
|
||||
|
||||
|
@ -2041,6 +2050,7 @@ MediaDecoderStateMachine::StartAudioThread()
|
|||
|
||||
int64_t MediaDecoderStateMachine::AudioDecodedUsecs()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
NS_ASSERTION(HasAudio(),
|
||||
"Should only call AudioDecodedUsecs() when we have audio");
|
||||
// The amount of audio we have decoded is the amount of audio data we've
|
||||
|
@ -2058,6 +2068,7 @@ int64_t MediaDecoderStateMachine::AudioDecodedUsecs()
|
|||
|
||||
bool MediaDecoderStateMachine::HasLowDecodedData(int64_t aAudioUsecs)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
MOZ_ASSERT(mReader->UseBufferingHeuristics());
|
||||
// We consider ourselves low on decoded data if we're low on audio,
|
||||
|
@ -2071,6 +2082,7 @@ bool MediaDecoderStateMachine::HasLowDecodedData(int64_t aAudioUsecs)
|
|||
|
||||
bool MediaDecoderStateMachine::OutOfDecodedAudio()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
return IsAudioDecoding() && !AudioQueue().IsFinished() &&
|
||||
AudioQueue().GetSize() == 0 &&
|
||||
(!mAudioSink || !mAudioSink->HasUnplayedFrames());
|
||||
|
@ -2078,11 +2090,13 @@ bool MediaDecoderStateMachine::OutOfDecodedAudio()
|
|||
|
||||
bool MediaDecoderStateMachine::HasLowUndecodedData()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
return HasLowUndecodedData(mLowDataThresholdUsecs);
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
NS_ASSERTION(mState > DECODER_STATE_DECODING_FIRSTFRAME,
|
||||
"Must have loaded first frame for GetBuffered() to work");
|
||||
|
@ -2146,9 +2160,9 @@ MediaDecoderStateMachine::DecodeError()
|
|||
void
|
||||
MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
MOZ_ASSERT(mState == DECODER_STATE_DECODING_METADATA);
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mMetadataRequest.Complete();
|
||||
|
||||
mDecoder->SetMediaSeekable(mReader->IsMediaSeekable());
|
||||
|
@ -2186,9 +2200,9 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
|
|||
void
|
||||
MediaDecoderStateMachine::OnMetadataNotRead(ReadMetadataFailureReason aReason)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
MOZ_ASSERT(mState == DECODER_STATE_DECODING_METADATA);
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mMetadataRequest.Complete();
|
||||
|
||||
if (aReason == ReadMetadataFailureReason::WAITING_FOR_RESOURCES) {
|
||||
|
@ -2299,8 +2313,8 @@ MediaDecoderStateMachine::DecodeFirstFrame()
|
|||
nsresult
|
||||
MediaDecoderStateMachine::FinishDecodeFirstFrame()
|
||||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
DECODER_LOG("FinishDecodeFirstFrame");
|
||||
|
||||
if (IsShutdown()) {
|
||||
|
@ -2375,8 +2389,8 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
|
|||
void
|
||||
MediaDecoderStateMachine::OnSeekCompleted(int64_t aTime)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mSeekRequest.Complete();
|
||||
|
||||
// We must decode the first samples of active streams, so we can determine
|
||||
|
@ -2389,8 +2403,8 @@ MediaDecoderStateMachine::OnSeekCompleted(int64_t aTime)
|
|||
void
|
||||
MediaDecoderStateMachine::OnSeekFailed(nsresult aResult)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mSeekRequest.Complete();
|
||||
MOZ_ASSERT(NS_FAILED(aResult), "Cancels should also disconnect mSeekRequest");
|
||||
DecodeError();
|
||||
|
@ -2527,6 +2541,9 @@ MediaDecoderStateMachine::FinishShutdown()
|
|||
// Disconnect canonicals and mirrors before shutting down our task queue.
|
||||
mPlayState.DisconnectIfConnected();
|
||||
mNextPlayState.DisconnectIfConnected();
|
||||
mVolume.DisconnectIfConnected();
|
||||
mLogicalPlaybackRate.DisconnectIfConnected();
|
||||
mPreservesPitch.DisconnectIfConnected();
|
||||
mNextFrameStatus.DisconnectAll();
|
||||
|
||||
// Shut down the watch manager before shutting down our task queue.
|
||||
|
@ -2838,6 +2855,7 @@ void MediaDecoderStateMachine::RenderVideoFrame(VideoData* aData,
|
|||
|
||||
void MediaDecoderStateMachine::ResyncAudioClock()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
if (IsPlaying()) {
|
||||
SetPlayStartTime(TimeStamp::Now());
|
||||
|
@ -2848,6 +2866,7 @@ void MediaDecoderStateMachine::ResyncAudioClock()
|
|||
int64_t
|
||||
MediaDecoderStateMachine::GetAudioClock() const
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
// We must hold the decoder monitor while using the audio stream off the
|
||||
// audio sink to ensure that it doesn't get destroyed on the audio sink
|
||||
// while we're using it.
|
||||
|
@ -2874,6 +2893,7 @@ int64_t MediaDecoderStateMachine::GetVideoStreamPosition() const
|
|||
|
||||
int64_t MediaDecoderStateMachine::GetClock() const
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
|
||||
// Determine the clock time. If we've got audio, and we've not reached
|
||||
|
@ -3053,6 +3073,7 @@ void MediaDecoderStateMachine::AdvanceFrame()
|
|||
nsresult
|
||||
MediaDecoderStateMachine::DropVideoUpToSeekTarget(VideoData* aSample)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
nsRefPtr<VideoData> video(aSample);
|
||||
MOZ_ASSERT(video);
|
||||
DECODER_LOG("DropVideoUpToSeekTarget() frame [%lld, %lld] dup=%d",
|
||||
|
@ -3104,6 +3125,7 @@ MediaDecoderStateMachine::DropVideoUpToSeekTarget(VideoData* aSample)
|
|||
nsresult
|
||||
MediaDecoderStateMachine::DropAudioUpToSeekTarget(AudioData* aSample)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
nsRefPtr<AudioData> audio(aSample);
|
||||
MOZ_ASSERT(audio &&
|
||||
mCurrentSeek.Exists() &&
|
||||
|
@ -3199,7 +3221,8 @@ void MediaDecoderStateMachine::SetStartTime(int64_t aStartTimeUsecs)
|
|||
DECODER_LOG("Set media start time to %lld", mStartTime);
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::UpdateNextFrameStatus() {
|
||||
void MediaDecoderStateMachine::UpdateNextFrameStatus()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
|
||||
|
@ -3228,6 +3251,7 @@ void MediaDecoderStateMachine::UpdateNextFrameStatus() {
|
|||
|
||||
bool MediaDecoderStateMachine::JustExitedQuickBuffering()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
return !mDecodeStartTime.IsNull() &&
|
||||
mQuickBuffering &&
|
||||
(TimeStamp::Now() - mDecodeStartTime) < TimeDuration::FromMicroseconds(QUICK_BUFFER_THRESHOLD_USECS);
|
||||
|
@ -3285,7 +3309,9 @@ void MediaDecoderStateMachine::SetPlayStartTime(const TimeStamp& aTimeStamp)
|
|||
}
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::ScheduleStateMachineWithLockAndWakeDecoder() {
|
||||
void MediaDecoderStateMachine::ScheduleStateMachineWithLockAndWakeDecoder()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
DispatchAudioDecodeTaskIfNeeded();
|
||||
DispatchVideoDecodeTaskIfNeeded();
|
||||
|
@ -3353,14 +3379,14 @@ bool MediaDecoderStateMachine::IsStateMachineScheduled() const
|
|||
return mDispatchedStateMachine || mDelayedScheduler.IsScheduled();
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::SetPlaybackRate(double aPlaybackRate)
|
||||
void
|
||||
MediaDecoderStateMachine::LogicalPlaybackRateChanged()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
NS_ASSERTION(aPlaybackRate != 0,
|
||||
"PlaybackRate == 0 should be handled before this function.");
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
|
||||
if (mPlaybackRate == aPlaybackRate) {
|
||||
if (mLogicalPlaybackRate == 0) {
|
||||
// This case is handled in MediaDecoder by pausing playback.
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3374,31 +3400,22 @@ void MediaDecoderStateMachine::SetPlaybackRate(double aPlaybackRate)
|
|||
SetPlayStartTime(TimeStamp::Now());
|
||||
}
|
||||
|
||||
mPlaybackRate = aPlaybackRate;
|
||||
mPlaybackRate = mLogicalPlaybackRate;
|
||||
if (mAudioSink) {
|
||||
mAudioSink->SetPlaybackRate(mPlaybackRate);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::SetPreservesPitch(bool aPreservesPitch)
|
||||
void MediaDecoderStateMachine::PreservesPitchChanged()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
|
||||
mPreservesPitch = aPreservesPitch;
|
||||
if (mAudioSink) {
|
||||
mAudioSink->SetPreservesPitch(mPreservesPitch);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::SetMinimizePrerollUntilPlaybackStarts()
|
||||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
DECODER_LOG("SetMinimizePrerollUntilPlaybackStarts()");
|
||||
mMinimizePreroll = true;
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::IsShutdown()
|
||||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
|
@ -3471,6 +3488,7 @@ void MediaDecoderStateMachine::OnAudioSinkError()
|
|||
|
||||
uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
return (mReader->IsAsync() && mReader->VideoIsHardwareAccelerated())
|
||||
? std::max<uint32_t>(sVideoQueueHWAccelSize, MIN_VIDEO_QUEUE_SIZE)
|
||||
|
|
|
@ -152,10 +152,20 @@ public:
|
|||
return mState;
|
||||
}
|
||||
|
||||
// Set the audio volume. The decoder monitor must be obtained before
|
||||
// calling this.
|
||||
void SetVolume(double aVolume);
|
||||
void SetAudioCaptured();
|
||||
void DispatchAudioCaptured()
|
||||
{
|
||||
nsRefPtr<MediaDecoderStateMachine> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void
|
||||
{
|
||||
MOZ_ASSERT(self->OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
if (!self->mAudioCaptured) {
|
||||
self->mAudioCaptured = true;
|
||||
self->ScheduleStateMachine();
|
||||
}
|
||||
});
|
||||
TaskQueue()->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
// Check if the decoder needs to become dormant state.
|
||||
bool IsDormantNeeded();
|
||||
|
@ -309,9 +319,6 @@ public:
|
|||
return mReader->GetBuffered(aBuffered);
|
||||
}
|
||||
|
||||
void SetPlaybackRate(double aPlaybackRate);
|
||||
void SetPreservesPitch(bool aPreservesPitch);
|
||||
|
||||
size_t SizeOfVideoQueue() {
|
||||
if (mReader) {
|
||||
return mReader->SizeOfVideoQueueInBytes();
|
||||
|
@ -392,7 +399,21 @@ public:
|
|||
// the state machine is free to return to prerolling normally. Note
|
||||
// "prerolling" in this context refers to when we decode and buffer decoded
|
||||
// samples in advance of when they're needed for playback.
|
||||
void SetMinimizePrerollUntilPlaybackStarts();
|
||||
void DispatchMinimizePrerollUntilPlaybackStarts()
|
||||
{
|
||||
nsRefPtr<MediaDecoderStateMachine> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void
|
||||
{
|
||||
MOZ_ASSERT(self->OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
self->mMinimizePreroll = true;
|
||||
|
||||
// Make sure that this arrives before playback starts, otherwise this won't
|
||||
// have the intended effect.
|
||||
MOZ_DIAGNOSTIC_ASSERT(self->mPlayState == MediaDecoder::PLAY_STATE_LOADING);
|
||||
});
|
||||
TaskQueue()->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
void OnAudioDecoded(AudioData* aSample);
|
||||
void OnVideoDecoded(VideoData* aSample);
|
||||
|
@ -447,6 +468,9 @@ protected:
|
|||
already_AddRefed<AudioData> PopAudio();
|
||||
already_AddRefed<VideoData> PopVideo();
|
||||
|
||||
void VolumeChanged();
|
||||
void LogicalPlaybackRateChanged();
|
||||
void PreservesPitchChanged();
|
||||
|
||||
class WakeDecoderRunnable : public nsRunnable {
|
||||
public:
|
||||
|
@ -1009,17 +1033,19 @@ protected:
|
|||
// on decoded video data.
|
||||
int64_t mDecodedVideoEndTime;
|
||||
|
||||
// Volume of playback. 0.0 = muted. 1.0 = full volume. Read/Written
|
||||
// from the state machine and main threads. Synchronised via decoder
|
||||
// monitor.
|
||||
double mVolume;
|
||||
// Volume of playback. 0.0 = muted. 1.0 = full volume.
|
||||
Mirror<double> mVolume;
|
||||
|
||||
// Playback rate. 1.0 : normal speed, 0.5 : two times slower. Synchronized via
|
||||
// decoder monitor.
|
||||
// Playback rate. 1.0 : normal speed, 0.5 : two times slower.
|
||||
//
|
||||
// The separation between mPlaybackRate and mLogicalPlaybackRate is a kludge
|
||||
// to preserve existing fragile logic while converting this setup to state-
|
||||
// mirroring. Some hero should clean this up.
|
||||
double mPlaybackRate;
|
||||
Mirror<double> mLogicalPlaybackRate;
|
||||
|
||||
// Pitch preservation for the playback rate. Synchronized via decoder monitor.
|
||||
bool mPreservesPitch;
|
||||
// Pitch preservation for the playback rate.
|
||||
Mirror<bool> mPreservesPitch;
|
||||
|
||||
// Time at which we started decoding. Synchronised via decoder monitor.
|
||||
TimeStamp mDecodeStartTime;
|
||||
|
@ -1080,12 +1106,14 @@ protected:
|
|||
|
||||
bool DonePrerollingAudio()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
return !IsAudioDecoding() || GetDecodedAudioDuration() >= AudioPrerollUsecs() * mPlaybackRate;
|
||||
}
|
||||
|
||||
bool DonePrerollingVideo()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
return !IsVideoDecoding() ||
|
||||
static_cast<uint32_t>(VideoQueue().GetSize()) >= VideoPrerollFrames() * mPlaybackRate;
|
||||
|
|
|
@ -45,9 +45,14 @@ function GlobalPCList() {
|
|||
Services.obs.addObserver(this, "network:offline-about-to-go-offline", true);
|
||||
Services.obs.addObserver(this, "network:offline-status-changed", true);
|
||||
Services.obs.addObserver(this, "gmp-plugin-crash", true);
|
||||
if (Cc["@mozilla.org/childprocessmessagemanager;1"]) {
|
||||
let mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
|
||||
mm.addMessageListener("gmp-plugin-crash", this);
|
||||
}
|
||||
}
|
||||
GlobalPCList.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsIMessageListener,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.IPeerConnectionManager]),
|
||||
classID: PC_MANAGER_CID,
|
||||
|
@ -93,6 +98,31 @@ GlobalPCList.prototype = {
|
|||
return this._list[winID] ? true : false;
|
||||
},
|
||||
|
||||
handleGMPCrash: function(data) {
|
||||
let broadcastPluginCrash = function(list, winID, pluginID, pluginName) {
|
||||
if (list.hasOwnProperty(winID)) {
|
||||
list[winID].forEach(function(pcref) {
|
||||
let pc = pcref.get();
|
||||
if (pc) {
|
||||
pc._pc.pluginCrash(pluginID, pluginName);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// a plugin crashed; if it's associated with any of our PCs, fire an
|
||||
// event to the DOM window
|
||||
for (let winId in this._list) {
|
||||
broadcastPluginCrash(this._list, winId, data.pluginID, data.pluginName);
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function(message) {
|
||||
if (message.name == "gmp-plugin-crash") {
|
||||
this.handleGMPCrash(message.data);
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
let cleanupPcRef = function(pcref) {
|
||||
let pc = pcref.get();
|
||||
|
@ -110,17 +140,6 @@ GlobalPCList.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
let broadcastPluginCrash = function(list, winID, pluginID, name, crashReportID) {
|
||||
if (list.hasOwnProperty(winID)) {
|
||||
list[winID].forEach(function(pcref) {
|
||||
let pc = pcref.get();
|
||||
if (pc) {
|
||||
pc._pc.pluginCrash(pluginID, name, crashReportID);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (topic == "inner-window-destroyed") {
|
||||
let winID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
cleanupWinId(this._list, winID);
|
||||
|
@ -162,17 +181,11 @@ GlobalPCList.prototype = {
|
|||
}
|
||||
}
|
||||
} else if (topic == "gmp-plugin-crash") {
|
||||
// a plugin crashed; if it's associated with any of our PCs, fire an
|
||||
// event to the DOM window
|
||||
let sep = data.indexOf(' ');
|
||||
let pluginId = data.slice(0, sep);
|
||||
let rest = data.slice(sep+1);
|
||||
// This presumes no spaces in the name!
|
||||
sep = rest.indexOf(' ');
|
||||
let name = rest.slice(0, sep);
|
||||
let crashId = rest.slice(sep+1);
|
||||
for (let winId in this._list) {
|
||||
broadcastPluginCrash(this._list, winId, pluginId, name, crashId);
|
||||
if (subject instanceof Ci.nsIWritablePropertyBag2) {
|
||||
let pluginID = subject.getPropertyAsUint32("pluginID");
|
||||
let pluginName = subject.getPropertyAsAString("pluginName");
|
||||
let data = { pluginID, pluginName };
|
||||
this.handleGMPCrash(data);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -377,22 +377,23 @@ MediaKeys::Init(ErrorResult& aRv)
|
|||
class CrashHandler : public gmp::GeckoMediaPluginService::PluginCrashCallback
|
||||
{
|
||||
public:
|
||||
CrashHandler(const nsACString& aPluginId,
|
||||
CrashHandler(const uint32_t aPluginId,
|
||||
nsPIDOMWindow* aParentWindow,
|
||||
nsIDocument* aDocument)
|
||||
: gmp::GeckoMediaPluginService::PluginCrashCallback(aPluginId)
|
||||
, mPluginId(aPluginId)
|
||||
, mParentWindowWeakPtr(do_GetWeakReference(aParentWindow))
|
||||
, mDocumentWeakPtr(do_GetWeakReference(aDocument))
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Run(const nsACString& aPluginName, const nsAString& aPluginDumpId) override
|
||||
virtual void Run(const nsACString& aPluginName) override
|
||||
{
|
||||
PluginCrashedEventInit init;
|
||||
init.mPluginID = mPluginId;
|
||||
init.mBubbles = true;
|
||||
init.mCancelable = true;
|
||||
init.mGmpPlugin = true;
|
||||
init.mPluginDumpID = aPluginDumpId;
|
||||
CopyUTF8toUTF16(aPluginName, init.mPluginName);
|
||||
init.mSubmittedCrashReport = false;
|
||||
|
||||
|
@ -445,12 +446,13 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
uint32_t mPluginId;
|
||||
nsWeakPtr mParentWindowWeakPtr;
|
||||
nsWeakPtr mDocumentWeakPtr;
|
||||
};
|
||||
|
||||
void
|
||||
MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const nsACString& aPluginId)
|
||||
MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const uint32_t aPluginId)
|
||||
{
|
||||
nsRefPtr<Promise> promise(RetrievePromise(aId));
|
||||
if (!promise) {
|
||||
|
@ -468,7 +470,7 @@ MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const nsACStri
|
|||
mKeySystem,
|
||||
MediaKeySystemStatus::Cdm_created);
|
||||
|
||||
if (!aPluginId.IsEmpty()) {
|
||||
if (aPluginId) {
|
||||
// Prepare plugin crash reporter.
|
||||
nsRefPtr<gmp::GeckoMediaPluginService> service =
|
||||
gmp::GeckoMediaPluginService::GetGeckoMediaPluginService();
|
||||
|
@ -483,8 +485,8 @@ MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const nsACStri
|
|||
return;
|
||||
}
|
||||
service->AddPluginCrashCallback(new CrashHandler(aPluginId, mParent, doc));
|
||||
EME_LOG("MediaKeys[%p]::OnCDMCreated() registered crash handler for pluginId '%s'",
|
||||
this, aPluginId.Data());
|
||||
EME_LOG("MediaKeys[%p]::OnCDMCreated() registered crash handler for pluginId '%i'",
|
||||
this, aPluginId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ public:
|
|||
|
||||
// Called once a Init() operation succeeds.
|
||||
void OnCDMCreated(PromiseId aId,
|
||||
const nsACString& aNodeId, const nsACString& aPluginId);
|
||||
const nsACString& aNodeId, const uint32_t aPluginId);
|
||||
|
||||
// Called once the CDM generates a sessionId while servicing a
|
||||
// MediaKeySession.generateRequest() or MediaKeySession.load() call,
|
||||
|
|
|
@ -51,11 +51,11 @@ public:
|
|||
{
|
||||
return mDisplayName;
|
||||
}
|
||||
void SetPluginId(const nsCString& aPluginId)
|
||||
void SetPluginId(const uint32_t aPluginId)
|
||||
{
|
||||
mPluginId = aPluginId;
|
||||
}
|
||||
const nsCString& GetPluginId()
|
||||
const uint32_t GetPluginId()
|
||||
{
|
||||
return mPluginId;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ private:
|
|||
nsCOMPtr<nsIThread> mGMPThread;
|
||||
nsRefPtr<GMPParent> mParent;
|
||||
nsCString mDisplayName;
|
||||
nsCString mPluginId;
|
||||
uint32_t mPluginId;
|
||||
};
|
||||
|
||||
} // namespace gmp
|
||||
|
|
|
@ -29,7 +29,7 @@ GMPDecryptorParent::~GMPDecryptorParent()
|
|||
{
|
||||
}
|
||||
|
||||
const nsACString&
|
||||
const uint32_t
|
||||
GMPDecryptorParent::GetPluginId() const
|
||||
{
|
||||
return mPluginId;
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
|
||||
// GMPDecryptorProxy
|
||||
|
||||
virtual const nsACString& GetPluginId() const override;
|
||||
virtual const uint32_t GetPluginId() const override;
|
||||
|
||||
virtual nsresult Init(GMPDecryptorProxyCallback* aCallback) override;
|
||||
|
||||
|
@ -113,7 +113,7 @@ private:
|
|||
bool mShuttingDown;
|
||||
bool mActorDestroyed;
|
||||
nsRefPtr<GMPContentParent> mPlugin;
|
||||
nsCString mPluginId;
|
||||
uint32_t mPluginId;
|
||||
GMPDecryptorProxyCallback* mCallback;
|
||||
#ifdef DEBUG
|
||||
nsIThread* const mGMPThread;
|
||||
|
|
|
@ -59,7 +59,7 @@ class GMPDecryptorProxy {
|
|||
public:
|
||||
~GMPDecryptorProxy() {}
|
||||
|
||||
virtual const nsACString& GetPluginId() const = 0;
|
||||
virtual const uint32_t GetPluginId() const = 0;
|
||||
|
||||
virtual nsresult Init(GMPDecryptorProxyCallback* aCallback) = 0;
|
||||
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIWritablePropertyBag2.h"
|
||||
#include "mozIGeckoMediaPluginService.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
@ -25,6 +27,7 @@
|
|||
|
||||
#include "mozilla/dom/CrashReporterParent.h"
|
||||
using mozilla::dom::CrashReporterParent;
|
||||
using mozilla::ipc::GeckoChildProcessHost;
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
using CrashReporter::AnnotationTable;
|
||||
|
@ -64,9 +67,7 @@ GMPParent::GMPParent()
|
|||
#endif
|
||||
{
|
||||
LOGD("GMPParent ctor");
|
||||
// Use the parent address to identify it.
|
||||
// We could use any unique-to-the-parent value.
|
||||
mPluginId.AppendInt(reinterpret_cast<uint64_t>(this));
|
||||
mPluginId = GeckoChildProcessHost::GetUniqueID();
|
||||
}
|
||||
|
||||
GMPParent::~GMPParent()
|
||||
|
@ -499,23 +500,22 @@ GMPParent::GetCrashID(nsString& aResult)
|
|||
}
|
||||
|
||||
static void
|
||||
GMPNotifyObservers(const nsACString& aPluginId, const nsACString& aPluginName, const nsAString& aPluginDumpId)
|
||||
GMPNotifyObservers(const uint32_t aPluginID, const nsACString& aPluginName, const nsAString& aPluginDumpID)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
nsString id;
|
||||
AppendUTF8toUTF16(aPluginId, id);
|
||||
id.Append(NS_LITERAL_STRING(" "));
|
||||
AppendUTF8toUTF16(aPluginName, id);
|
||||
id.Append(NS_LITERAL_STRING(" "));
|
||||
id.Append(aPluginDumpId);
|
||||
obs->NotifyObservers(nullptr, "gmp-plugin-crash", id.Data());
|
||||
nsCOMPtr<nsIWritablePropertyBag2> propbag =
|
||||
do_CreateInstance("@mozilla.org/hash-property-bag;1");
|
||||
if (obs && propbag) {
|
||||
propbag->SetPropertyAsUint32(NS_LITERAL_STRING("pluginID"), aPluginID);
|
||||
propbag->SetPropertyAsACString(NS_LITERAL_STRING("pluginName"), aPluginName);
|
||||
propbag->SetPropertyAsAString(NS_LITERAL_STRING("pluginDumpID"), aPluginDumpID);
|
||||
obs->NotifyObservers(propbag, "gmp-plugin-crash", nullptr);
|
||||
}
|
||||
|
||||
nsRefPtr<gmp::GeckoMediaPluginService> service =
|
||||
gmp::GeckoMediaPluginService::GetGeckoMediaPluginService();
|
||||
if (service) {
|
||||
service->RunPluginCrashCallbacks(aPluginId, aPluginName, aPluginDumpId);
|
||||
service->RunPluginCrashCallbacks(aPluginID, aPluginName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -820,7 +820,7 @@ GMPParent::GetVersion() const
|
|||
return mVersion;
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
const uint32_t
|
||||
GMPParent::GetPluginId() const
|
||||
{
|
||||
return mPluginId;
|
||||
|
|
|
@ -123,7 +123,7 @@ public:
|
|||
|
||||
const nsCString& GetDisplayName() const;
|
||||
const nsCString& GetVersion() const;
|
||||
const nsCString& GetPluginId() const;
|
||||
const uint32_t GetPluginId() const;
|
||||
|
||||
// Returns true if a plugin can be or is being used across multiple NodeIds.
|
||||
bool CanBeSharedCrossNodeIds() const;
|
||||
|
@ -192,7 +192,7 @@ private:
|
|||
nsCString mDisplayName; // name of plugin displayed to users
|
||||
nsCString mDescription; // description of plugin for display to users
|
||||
nsCString mVersion;
|
||||
nsCString mPluginId;
|
||||
uint32_t mPluginId;
|
||||
nsTArray<nsAutoPtr<GMPCapability>> mCapabilities;
|
||||
GMPProcessParent* mProcess;
|
||||
bool mDeleteProcessOnlyOnUnload;
|
||||
|
|
|
@ -165,9 +165,8 @@ GeckoMediaPluginService::RemoveObsoletePluginCrashCallbacks()
|
|||
for (size_t i = mPluginCrashCallbacks.Length(); i != 0; --i) {
|
||||
nsRefPtr<PluginCrashCallback>& callback = mPluginCrashCallbacks[i - 1];
|
||||
if (!callback->IsStillValid()) {
|
||||
LOGD(("%s::%s - Removing obsolete callback for pluginId %s",
|
||||
__CLASS__, __FUNCTION__,
|
||||
PromiseFlatCString(callback->PluginId()).get()));
|
||||
LOGD(("%s::%s - Removing obsolete callback for pluginId %i",
|
||||
__CLASS__, __FUNCTION__, callback->PluginId()));
|
||||
mPluginCrashCallbacks.RemoveElementAt(i - 1);
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +181,7 @@ GeckoMediaPluginService::AddPluginCrashCallback(
|
|||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginService::RemovePluginCrashCallbacks(const nsACString& aPluginId)
|
||||
GeckoMediaPluginService::RemovePluginCrashCallbacks(const uint32_t aPluginId)
|
||||
{
|
||||
RemoveObsoletePluginCrashCallbacks();
|
||||
for (size_t i = mPluginCrashCallbacks.Length(); i != 0; --i) {
|
||||
|
@ -194,24 +193,22 @@ GeckoMediaPluginService::RemovePluginCrashCallbacks(const nsACString& aPluginId)
|
|||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginService::RunPluginCrashCallbacks(const nsACString& aPluginId,
|
||||
const nsACString& aPluginName,
|
||||
const nsAString& aPluginDumpId)
|
||||
GeckoMediaPluginService::RunPluginCrashCallbacks(const uint32_t aPluginId,
|
||||
const nsACString& aPluginName)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
LOGD(("%s::%s(%s)", __CLASS__, __FUNCTION__, aPluginId.Data()));
|
||||
LOGD(("%s::%s(%i)", __CLASS__, __FUNCTION__, aPluginId));
|
||||
for (size_t i = mPluginCrashCallbacks.Length(); i != 0; --i) {
|
||||
nsRefPtr<PluginCrashCallback>& callback = mPluginCrashCallbacks[i - 1];
|
||||
const nsACString& callbackPluginId = callback->PluginId();
|
||||
const uint32_t callbackPluginId = callback->PluginId();
|
||||
if (!callback->IsStillValid()) {
|
||||
LOGD(("%s::%s(%s) - Removing obsolete callback for pluginId %s",
|
||||
__CLASS__, __FUNCTION__, aPluginId.Data(),
|
||||
PromiseFlatCString(callback->PluginId()).get()));
|
||||
LOGD(("%s::%s(%i) - Removing obsolete callback for pluginId %i",
|
||||
__CLASS__, __FUNCTION__, aPluginId, callback->PluginId()));
|
||||
mPluginCrashCallbacks.RemoveElementAt(i - 1);
|
||||
} else if (callbackPluginId == aPluginId) {
|
||||
LOGD(("%s::%s(%s) - Running #%u",
|
||||
__CLASS__, __FUNCTION__, aPluginId.Data(), i - 1));
|
||||
callback->Run(aPluginName, aPluginDumpId);
|
||||
LOGD(("%s::%s(%i) - Running #%u",
|
||||
__CLASS__, __FUNCTION__, aPluginId, i - 1));
|
||||
callback->Run(aPluginName);
|
||||
mPluginCrashCallbacks.RemoveElementAt(i - 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,13 +66,13 @@ public:
|
|||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(PluginCrashCallback)
|
||||
|
||||
PluginCrashCallback(const nsACString& aPluginId)
|
||||
PluginCrashCallback(const uint32_t aPluginId)
|
||||
: mPluginId(aPluginId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
const nsACString& PluginId() const { return mPluginId; }
|
||||
virtual void Run(const nsACString& aPluginName, const nsAString& aPluginDumpId) = 0;
|
||||
const uint32_t PluginId() const { return mPluginId; }
|
||||
virtual void Run(const nsACString& aPluginName) = 0;
|
||||
virtual bool IsStillValid() = 0; // False if callback has become useless.
|
||||
protected:
|
||||
virtual ~PluginCrashCallback()
|
||||
|
@ -80,14 +80,13 @@ public:
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
private:
|
||||
const nsCString mPluginId;
|
||||
const uint32_t mPluginId;
|
||||
};
|
||||
void RemoveObsoletePluginCrashCallbacks(); // Called from add/remove/run.
|
||||
void AddPluginCrashCallback(nsRefPtr<PluginCrashCallback> aPluginCrashCallback);
|
||||
void RemovePluginCrashCallbacks(const nsACString& aPluginId);
|
||||
void RunPluginCrashCallbacks(const nsACString& aPluginId,
|
||||
const nsACString& aPluginName,
|
||||
const nsAString& aPluginDumpId);
|
||||
void RemovePluginCrashCallbacks(const uint32_t aPluginId);
|
||||
void RunPluginCrashCallbacks(const uint32_t aPluginId,
|
||||
const nsACString& aPluginName);
|
||||
|
||||
protected:
|
||||
GeckoMediaPluginService();
|
||||
|
|
|
@ -82,7 +82,7 @@ public:
|
|||
|
||||
base::ProcessId otherProcess;
|
||||
nsCString displayName;
|
||||
nsCString pluginId;
|
||||
uint32_t pluginId;
|
||||
bool ok = aGMPServiceChild->SendLoadGMP(mNodeId, mAPI, mTags,
|
||||
alreadyBridgedTo, &otherProcess,
|
||||
&displayName, &pluginId);
|
||||
|
|
|
@ -1435,7 +1435,7 @@ GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId,
|
|||
nsTArray<ProcessId>&& aAlreadyBridgedTo,
|
||||
ProcessId* aId,
|
||||
nsCString* aDisplayName,
|
||||
nsCString* aPluginId)
|
||||
uint32_t* aPluginId)
|
||||
{
|
||||
nsRefPtr<GMPParent> gmp = mService->SelectPluginForAPI(aNodeId, aAPI, aTags);
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ public:
|
|||
nsTArray<ProcessId>&& aAlreadyBridgedTo,
|
||||
base::ProcessId* aID,
|
||||
nsCString* aDisplayName,
|
||||
nsCString* aPluginId) override;
|
||||
uint32_t* aPluginId) override;
|
||||
virtual bool RecvGetGMPNodeId(const nsString& aOrigin,
|
||||
const nsString& aTopLevelOrigin,
|
||||
const bool& aInPrivateBrowsing,
|
||||
|
|
|
@ -216,6 +216,12 @@ GMPVideoEncoderParent::SetPeriodicKeyFrames(bool aEnable)
|
|||
return GMPNoErr;
|
||||
}
|
||||
|
||||
const uint32_t
|
||||
GMPVideoEncoderParent::ParentID()
|
||||
{
|
||||
return mPlugin ? mPlugin->GetPluginId() : 0;
|
||||
}
|
||||
|
||||
// Note: Consider keeping ActorDestroy sync'd up when making changes here.
|
||||
void
|
||||
GMPVideoEncoderParent::Shutdown()
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) override;
|
||||
virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) override;
|
||||
virtual GMPErr SetPeriodicKeyFrames(bool aEnable) override;
|
||||
virtual const uint64_t ParentID() override { return reinterpret_cast<uint64_t>(mPlugin.get()); }
|
||||
virtual const uint32_t ParentID() override;
|
||||
|
||||
// GMPSharedMemManager
|
||||
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) override
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0;
|
||||
virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0;
|
||||
virtual GMPErr SetPeriodicKeyFrames(bool aEnable) = 0;
|
||||
virtual const uint64_t ParentID() = 0;
|
||||
virtual const uint32_t ParentID() = 0;
|
||||
|
||||
// Call to tell GMP/plugin the consumer will no longer use this
|
||||
// interface/codec.
|
||||
|
|
|
@ -17,7 +17,7 @@ sync protocol PGMPService
|
|||
parent:
|
||||
sync LoadGMP(nsCString nodeId, nsCString api, nsCString[] tags,
|
||||
ProcessId[] alreadyBridgedTo)
|
||||
returns (ProcessId id, nsCString displayName, nsCString pluginId);
|
||||
returns (ProcessId id, nsCString displayName, uint32_t pluginId);
|
||||
sync GetGMPNodeId(nsString origin, nsString topLevelOrigin,
|
||||
bool inPrivateBrowsing)
|
||||
returns (nsCString id);
|
||||
|
|
|
@ -52,8 +52,8 @@ MediaOmxCommonDecoder::SetPlatformCanOffloadAudio(bool aCanOffloadAudio)
|
|||
bool
|
||||
MediaOmxCommonDecoder::CheckDecoderCanOffloadAudio()
|
||||
{
|
||||
return (mCanOffloadAudio && !mFallbackToStateMachine && !mOutputStreams.Length() &&
|
||||
mInitialPlaybackRate == 1.0);
|
||||
return (mCanOffloadAudio && !mFallbackToStateMachine &&
|
||||
!mOutputStreams.Length() && mPlaybackRate == 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/PCrashReporterParent.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/ipc/MessageChannel.h"
|
||||
#include "mozilla/plugins/BrowserStreamParent.h"
|
||||
#include "mozilla/plugins/PluginAsyncSurrogate.h"
|
||||
|
@ -58,6 +59,7 @@ using base::KillProcess;
|
|||
|
||||
using mozilla::PluginLibrary;
|
||||
using mozilla::ipc::MessageChannel;
|
||||
using mozilla::ipc::GeckoChildProcessHost;
|
||||
using mozilla::dom::PCrashReporterParent;
|
||||
using mozilla::dom::CrashReporterParent;
|
||||
|
||||
|
@ -658,10 +660,6 @@ PluginModuleContentParent::~PluginModuleContentParent()
|
|||
Preferences::UnregisterCallback(TimeoutChanged, kContentTimeoutPref, this);
|
||||
}
|
||||
|
||||
// We start the Run IDs at 1 so that we can use 0 as a way of detecting
|
||||
// errors in retrieving the run ID.
|
||||
uint32_t PluginModuleChromeParent::sNextRunID = 1;
|
||||
|
||||
bool PluginModuleChromeParent::sInstantiated = false;
|
||||
|
||||
PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId)
|
||||
|
@ -693,7 +691,7 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32
|
|||
{
|
||||
NS_ASSERTION(mSubprocess, "Out of memory!");
|
||||
sInstantiated = true;
|
||||
mRunID = sNextRunID++;
|
||||
mRunID = GeckoChildProcessHost::GetUniqueID();
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
InitPluginProfiling();
|
||||
|
|
|
@ -557,7 +557,6 @@ private:
|
|||
dom::ContentParent* mContentParent;
|
||||
nsCOMPtr<nsIObserver> mOfflineObserver;
|
||||
bool mIsBlocklisted;
|
||||
static uint32_t sNextRunID;
|
||||
static bool sInstantiated;
|
||||
};
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ interface PeerConnectionImpl {
|
|||
void close();
|
||||
|
||||
/* Notify DOM window if this plugin crash is ours. */
|
||||
boolean pluginCrash(unsigned long long pluginId, DOMString name, DOMString pluginDumpID);
|
||||
boolean pluginCrash(unsigned long long pluginId, DOMString name);
|
||||
|
||||
/* Attributes */
|
||||
[Constant]
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[Constructor(DOMString type, optional PluginCrashedEventInit eventInitDict), ChromeOnly]
|
||||
interface PluginCrashedEvent : Event
|
||||
{
|
||||
readonly attribute unsigned long pluginID;
|
||||
readonly attribute DOMString pluginDumpID;
|
||||
readonly attribute DOMString pluginName;
|
||||
readonly attribute DOMString? browserDumpID;
|
||||
|
@ -17,6 +18,7 @@ interface PluginCrashedEvent : Event
|
|||
|
||||
dictionary PluginCrashedEventInit : EventInit
|
||||
{
|
||||
unsigned long pluginID = 0;
|
||||
DOMString pluginDumpID = "";
|
||||
DOMString pluginName = "";
|
||||
DOMString? browserDumpID = null;
|
||||
|
|
|
@ -208,6 +208,8 @@ private:
|
|||
const char* aPathPrefix,
|
||||
const ImageMemoryCounter& aCounter)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString pathPrefix(NS_LITERAL_CSTRING("explicit/"));
|
||||
pathPrefix.Append(aPathPrefix);
|
||||
pathPrefix.Append(aCounter.Type() == imgIContainer::TYPE_RASTER
|
||||
|
@ -228,7 +230,13 @@ private:
|
|||
|
||||
pathPrefix.Append(")/");
|
||||
|
||||
return ReportSurfaces(aHandleReport, aData, pathPrefix, aCounter);
|
||||
rv = ReportSurfaces(aHandleReport, aData, pathPrefix, aCounter);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = ReportSourceValue(aHandleReport, aData, pathPrefix, aCounter.Values());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult ReportSurfaces(nsIHandleReportCallback* aHandleReport,
|
||||
|
@ -332,10 +340,7 @@ private:
|
|||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix,
|
||||
"source",
|
||||
"Raster image source data and vector image documents.",
|
||||
aCounter.Source());
|
||||
rv = ReportSourceValue(aHandleReport, aData, aPathPrefix, aCounter);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix,
|
||||
|
@ -353,6 +358,21 @@ private:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult ReportSourceValue(nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aData,
|
||||
const nsACString& aPathPrefix,
|
||||
const MemoryCounter& aCounter)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix,
|
||||
"source",
|
||||
"Raster image source data and vector image documents.",
|
||||
aCounter.Source());
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static nsresult ReportValue(nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aData,
|
||||
int32_t aKind,
|
||||
|
|
|
@ -254,6 +254,17 @@ uint32_t GeckoChildProcessHost::GetSupportedArchitecturesForProcessType(GeckoPro
|
|||
return base::GetCurrentProcessArchitecture();
|
||||
}
|
||||
|
||||
// We start the unique IDs at 1 so that 0 can be used to mean that
|
||||
// a component has no unique ID assigned to it.
|
||||
uint32_t GeckoChildProcessHost::sNextUniqueID = 1;
|
||||
|
||||
/* static */
|
||||
uint32_t
|
||||
GeckoChildProcessHost::GetUniqueID()
|
||||
{
|
||||
return sNextUniqueID++;
|
||||
}
|
||||
|
||||
void
|
||||
GeckoChildProcessHost::PrepareLaunch()
|
||||
{
|
||||
|
|
|
@ -47,6 +47,8 @@ public:
|
|||
|
||||
static uint32_t GetSupportedArchitecturesForProcessType(GeckoProcessType type);
|
||||
|
||||
static uint32_t GetUniqueID();
|
||||
|
||||
// Block until the IPC channel for our subprocess is initialized,
|
||||
// but no longer. The child process may or may not have been
|
||||
// created when this method returns.
|
||||
|
@ -196,6 +198,8 @@ private:
|
|||
//
|
||||
// FIXME/cjones: this strongly indicates bad design. Shame on us.
|
||||
std::queue<IPC::Message> mQueue;
|
||||
|
||||
static uint32_t sNextUniqueID;
|
||||
};
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
|
|
|
@ -591,7 +591,7 @@ struct JSClass {
|
|||
|
||||
#define JSCLASS_IS_PROXY (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
|
||||
|
||||
#define JSCLASS_FINALIZE_FROM_NURSERY (1<<(JSCLASS_HIGH_FLAGS_SHIFT+5))
|
||||
#define JSCLASS_SKIP_NURSERY_FINALIZE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+5))
|
||||
|
||||
// Reserved for embeddings.
|
||||
#define JSCLASS_USERBIT2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6))
|
||||
|
|
|
@ -225,7 +225,7 @@ struct GCSizes
|
|||
macro(_, _, marker) \
|
||||
macro(_, _, nurseryCommitted) \
|
||||
macro(_, _, nurseryDecommitted) \
|
||||
macro(_, _, nurseryHugeSlots) \
|
||||
macro(_, _, nurseryMallocedBuffers) \
|
||||
macro(_, _, storeBufferVals) \
|
||||
macro(_, _, storeBufferCells) \
|
||||
macro(_, _, storeBufferSlots) \
|
||||
|
|
|
@ -105,10 +105,14 @@ elif [ "$OSTYPE" = "linux-gnu" ]; then
|
|||
fi
|
||||
fi
|
||||
elif [ "$OSTYPE" = "msys" ]; then
|
||||
USE_64BIT=false
|
||||
if [ "$platform" = "win64" ]; then
|
||||
USE_64BIT=true
|
||||
fi
|
||||
case "$platform" in
|
||||
win64*)
|
||||
USE_64BIT=true
|
||||
;;
|
||||
*)
|
||||
USE_64BIT=false
|
||||
;;
|
||||
esac
|
||||
MAKE=${MAKE:-mozmake}
|
||||
source "$ABSDIR/winbuildenv.sh"
|
||||
fi
|
||||
|
@ -117,6 +121,9 @@ MAKE=${MAKE:-make}
|
|||
|
||||
if $USE_64BIT; then
|
||||
NSPR64="--enable-64bit"
|
||||
if [ "$OSTYPE" = "msys" ]; then
|
||||
CONFIGURE_ARGS="$CONFIGURE_ARGS --target=x86_64-pc-mingw32 --host=x86_64-pc-mingw32"
|
||||
fi
|
||||
else
|
||||
NSPR64=""
|
||||
if [ "$OSTYPE" != "msys" ]; then
|
||||
|
@ -169,8 +176,14 @@ elif [[ "$VARIANT" = "compacting" ]]; then
|
|||
esac
|
||||
fi
|
||||
|
||||
if [[ "$VARIANT" = "warnaserr" ]]; then
|
||||
if [[ "$VARIANT" = "warnaserr" ||
|
||||
"$VARIANT" = "warnaserrdebug" ||
|
||||
"$VARIANT" = "plain" ]]; then
|
||||
export JSTESTS_EXTRA_ARGS=--tbpl
|
||||
elif [[ "$VARIANT" = "arm-sim" ||
|
||||
"$VARIANT" = "rootanalysis" ||
|
||||
"$VARIANT" = "plaindebug" ]]; then
|
||||
export JSTESTS_EXTRA_ARGS=--tbpl-debug
|
||||
fi
|
||||
|
||||
$COMMAND_PREFIX $MAKE check || exit 1
|
||||
|
|
|
@ -14,9 +14,11 @@
|
|||
#include "js/TracingAPI.h"
|
||||
#include "vm/Runtime.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
template <typename T>
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
js::Nursery::getForwardedPointer(T** ref)
|
||||
Nursery::getForwardedPointer(T** ref)
|
||||
{
|
||||
MOZ_ASSERT(ref);
|
||||
MOZ_ASSERT(isInside((void*)*ref));
|
||||
|
@ -28,4 +30,47 @@ js::Nursery::getForwardedPointer(T** ref)
|
|||
return true;
|
||||
}
|
||||
|
||||
// The allocation methods below will not run the garbage collector. If the
|
||||
// nursery cannot accomodate the allocation, the malloc heap will be used
|
||||
// instead.
|
||||
|
||||
template <typename T>
|
||||
static inline T*
|
||||
AllocateObjectBuffer(ExclusiveContext* cx, uint32_t count)
|
||||
{
|
||||
if (cx->isJSContext()) {
|
||||
Nursery& nursery = cx->asJSContext()->runtime()->gc.nursery;
|
||||
return static_cast<T*>(nursery.allocateBuffer(cx->zone(), count * sizeof(T)));
|
||||
}
|
||||
return cx->zone()->pod_malloc<T>(count);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T*
|
||||
AllocateObjectBuffer(ExclusiveContext* cx, JSObject* obj, uint32_t count)
|
||||
{
|
||||
if (cx->isJSContext()) {
|
||||
Nursery& nursery = cx->asJSContext()->runtime()->gc.nursery;
|
||||
return static_cast<T*>(nursery.allocateBuffer(obj, count * sizeof(T)));
|
||||
}
|
||||
return obj->zone()->pod_malloc<T>(count);
|
||||
}
|
||||
|
||||
// If this returns null then the old buffer will be left alone.
|
||||
template <typename T>
|
||||
static inline T*
|
||||
ReallocateObjectBuffer(ExclusiveContext* cx, JSObject* obj, T* oldBuffer,
|
||||
uint32_t oldCount, uint32_t newCount)
|
||||
{
|
||||
if (cx->isJSContext()) {
|
||||
Nursery& nursery = cx->asJSContext()->runtime()->gc.nursery;
|
||||
return static_cast<T*>(nursery.reallocateBuffer(obj, oldBuffer,
|
||||
oldCount * sizeof(T),
|
||||
newCount * sizeof(T)));
|
||||
}
|
||||
return obj->zone()->pod_realloc<T>(oldBuffer, oldCount, newCount);
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* gc_Nursery_inl_h */
|
||||
|
|
|
@ -37,16 +37,16 @@ using mozilla::ArrayLength;
|
|||
using mozilla::PodCopy;
|
||||
using mozilla::PodZero;
|
||||
|
||||
struct js::Nursery::FreeHugeSlotsTask : public GCParallelTask
|
||||
struct js::Nursery::FreeMallocedBuffersTask : public GCParallelTask
|
||||
{
|
||||
explicit FreeHugeSlotsTask(FreeOp* fop) : fop_(fop) {}
|
||||
bool init() { return slots_.init(); }
|
||||
void transferSlotsToFree(HugeSlotsSet& slotsToFree);
|
||||
~FreeHugeSlotsTask() override { join(); }
|
||||
explicit FreeMallocedBuffersTask(FreeOp* fop) : fop_(fop) {}
|
||||
bool init() { return buffers_.init(); }
|
||||
void transferBuffersToFree(MallocedBuffersSet& buffersToFree);
|
||||
~FreeMallocedBuffersTask() override { join(); }
|
||||
|
||||
private:
|
||||
FreeOp* fop_;
|
||||
HugeSlotsSet slots_;
|
||||
MallocedBuffersSet buffers_;
|
||||
|
||||
virtual void run() override;
|
||||
};
|
||||
|
@ -61,15 +61,15 @@ js::Nursery::init(uint32_t maxNurseryBytes)
|
|||
if (numNurseryChunks_ == 0)
|
||||
return true;
|
||||
|
||||
if (!hugeSlots.init())
|
||||
if (!mallocedBuffers.init())
|
||||
return false;
|
||||
|
||||
void* heap = MapAlignedPages(nurserySize(), Alignment);
|
||||
if (!heap)
|
||||
return false;
|
||||
|
||||
freeHugeSlotsTask = js_new<FreeHugeSlotsTask>(runtime()->defaultFreeOp());
|
||||
if (!freeHugeSlotsTask || !freeHugeSlotsTask->init())
|
||||
freeMallocedBuffersTask = js_new<FreeMallocedBuffersTask>(runtime()->defaultFreeOp());
|
||||
if (!freeMallocedBuffersTask || !freeMallocedBuffersTask->init())
|
||||
return false;
|
||||
|
||||
heapStart_ = uintptr_t(heap);
|
||||
|
@ -100,7 +100,7 @@ js::Nursery::~Nursery()
|
|||
if (start())
|
||||
UnmapPages((void*)start(), nurserySize());
|
||||
|
||||
js_delete(freeHugeSlotsTask);
|
||||
js_delete(freeMallocedBuffersTask);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -175,38 +175,19 @@ js::Nursery::leaveZealMode() {
|
|||
}
|
||||
#endif // JS_GC_ZEAL
|
||||
|
||||
void
|
||||
js::Nursery::verifyFinalizerList()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (ListItem* current = finalizers_; current; current = current->next()) {
|
||||
JSObject* obj = current->get();
|
||||
RelocationOverlay* overlay = RelocationOverlay::fromCell(obj);
|
||||
if (overlay->isForwarded())
|
||||
obj = static_cast<JSObject*>(overlay->forwardingAddress());
|
||||
MOZ_ASSERT(obj);
|
||||
MOZ_ASSERT(obj->group());
|
||||
MOZ_ASSERT(obj->group()->clasp());
|
||||
MOZ_ASSERT(obj->group()->clasp()->finalize);
|
||||
MOZ_ASSERT(obj->group()->clasp()->flags & JSCLASS_FINALIZE_FROM_NURSERY);
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::Nursery::allocateObject(JSContext* cx, size_t size, size_t numDynamic, const js::Class* clasp)
|
||||
{
|
||||
/* Ensure there's enough space to replace the contents with a RelocationOverlay. */
|
||||
MOZ_ASSERT(size >= sizeof(RelocationOverlay));
|
||||
verifyFinalizerList();
|
||||
|
||||
/* If we have a finalizer, get space for the list entry. */
|
||||
ListItem* listEntry = nullptr;
|
||||
if (clasp->finalize) {
|
||||
listEntry = static_cast<ListItem*>(allocate(sizeof(ListItem)));
|
||||
if (!listEntry)
|
||||
return nullptr;
|
||||
}
|
||||
/*
|
||||
* Classes with JSCLASS_SKIP_NURSERY_FINALIZE will not have their finalizer
|
||||
* called if they are nursery allocated and not promoted to the tenured
|
||||
* heap. The finalizers for these classes must do nothing except free data
|
||||
* which was allocated via Nursery::allocateBuffer.
|
||||
*/
|
||||
MOZ_ASSERT_IF(clasp->finalize, clasp->flags & JSCLASS_SKIP_NURSERY_FINALIZE);
|
||||
|
||||
/* Make the object allocation. */
|
||||
JSObject* obj = static_cast<JSObject*>(allocate(size));
|
||||
|
@ -216,30 +197,19 @@ js::Nursery::allocateObject(JSContext* cx, size_t size, size_t numDynamic, const
|
|||
/* If we want external slots, add them. */
|
||||
HeapSlot* slots = nullptr;
|
||||
if (numDynamic) {
|
||||
/* Try to allocate in the nursery first. */
|
||||
if (numDynamic <= MaxNurserySlots)
|
||||
slots = static_cast<HeapSlot*>(allocate(numDynamic * sizeof(HeapSlot)));
|
||||
|
||||
/* If we are out of space or too large, use the malloc heap. */
|
||||
if (!slots)
|
||||
slots = allocateHugeSlots(cx->zone(), numDynamic);
|
||||
|
||||
/* It is safe to leave the allocated object uninitialized, since we do
|
||||
* not visit unallocated things. */
|
||||
if (!slots)
|
||||
slots = static_cast<HeapSlot*>(allocateBuffer(cx->zone(), numDynamic * sizeof(HeapSlot)));
|
||||
if (!slots) {
|
||||
/*
|
||||
* It is safe to leave the allocated object uninitialized, since we
|
||||
* do not visit unallocated things in the nursery.
|
||||
*/
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Always initialize the slots field to match the JIT behavior. */
|
||||
obj->setInitialSlotsMaybeNonNative(slots);
|
||||
|
||||
/* If we have a finalizer, link it into the finalizer list. */
|
||||
if (clasp->finalize) {
|
||||
MOZ_ASSERT(listEntry);
|
||||
new (listEntry) ListItem(finalizers_, obj);
|
||||
finalizers_ = listEntry;
|
||||
}
|
||||
|
||||
TraceNurseryAlloc(obj, size);
|
||||
return obj;
|
||||
}
|
||||
|
@ -264,89 +234,72 @@ js::Nursery::allocate(size_t size)
|
|||
return thing;
|
||||
}
|
||||
|
||||
/* Internally, this function is used to allocate elements as well as slots. */
|
||||
HeapSlot*
|
||||
js::Nursery::allocateSlots(JSObject* obj, uint32_t nslots)
|
||||
void*
|
||||
js::Nursery::allocateBuffer(Zone* zone, uint32_t nbytes)
|
||||
{
|
||||
MOZ_ASSERT(nbytes > 0);
|
||||
|
||||
if (nbytes <= MaxNurseryBufferSize) {
|
||||
void* buffer = allocate(nbytes);
|
||||
if (buffer)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void* buffer = zone->pod_malloc<uint8_t>(nbytes);
|
||||
if (buffer) {
|
||||
/* If this put fails, we will only leak the slots. */
|
||||
(void)mallocedBuffers.put(buffer);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void*
|
||||
js::Nursery::allocateBuffer(JSObject* obj, uint32_t nbytes)
|
||||
{
|
||||
MOZ_ASSERT(obj);
|
||||
MOZ_ASSERT(nslots > 0);
|
||||
MOZ_ASSERT(nbytes > 0);
|
||||
|
||||
if (!IsInsideNursery(obj))
|
||||
return obj->zone()->pod_malloc<HeapSlot>(nslots);
|
||||
|
||||
if (nslots > MaxNurserySlots)
|
||||
return allocateHugeSlots(obj->zone(), nslots);
|
||||
|
||||
size_t size = sizeof(HeapSlot) * nslots;
|
||||
HeapSlot* slots = static_cast<HeapSlot*>(allocate(size));
|
||||
if (slots)
|
||||
return slots;
|
||||
|
||||
return allocateHugeSlots(obj->zone(), nslots);
|
||||
return obj->zone()->pod_malloc<uint8_t>(nbytes);
|
||||
return allocateBuffer(obj->zone(), nbytes);
|
||||
}
|
||||
|
||||
ObjectElements*
|
||||
js::Nursery::allocateElements(JSObject* obj, uint32_t nelems)
|
||||
{
|
||||
MOZ_ASSERT(nelems >= ObjectElements::VALUES_PER_HEADER);
|
||||
return reinterpret_cast<ObjectElements*>(allocateSlots(obj, nelems));
|
||||
}
|
||||
|
||||
HeapSlot*
|
||||
js::Nursery::reallocateSlots(JSObject* obj, HeapSlot* oldSlots,
|
||||
uint32_t oldCount, uint32_t newCount)
|
||||
void*
|
||||
js::Nursery::reallocateBuffer(JSObject* obj, void* oldBuffer,
|
||||
uint32_t oldBytes, uint32_t newBytes)
|
||||
{
|
||||
if (!IsInsideNursery(obj))
|
||||
return obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
|
||||
return obj->zone()->pod_realloc<uint8_t>((uint8_t*)oldBuffer, oldBytes, newBytes);
|
||||
|
||||
if (!isInside(oldSlots)) {
|
||||
HeapSlot* newSlots = obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
|
||||
if (newSlots && oldSlots != newSlots) {
|
||||
hugeSlots.remove(oldSlots);
|
||||
if (!isInside(oldBuffer)) {
|
||||
void* newBuffer = obj->zone()->pod_realloc<uint8_t>((uint8_t*)oldBuffer, oldBytes, newBytes);
|
||||
if (newBuffer && oldBytes != newBytes) {
|
||||
removeMallocedBuffer(oldBuffer);
|
||||
/* If this put fails, we will only leak the slots. */
|
||||
(void)hugeSlots.put(newSlots);
|
||||
(void)mallocedBuffers.put(newBuffer);
|
||||
}
|
||||
return newSlots;
|
||||
return newBuffer;
|
||||
}
|
||||
|
||||
/* The nursery cannot make use of the returned slots data. */
|
||||
if (newCount < oldCount)
|
||||
return oldSlots;
|
||||
if (newBytes < oldBytes)
|
||||
return oldBuffer;
|
||||
|
||||
HeapSlot* newSlots = allocateSlots(obj, newCount);
|
||||
if (newSlots)
|
||||
PodCopy(newSlots, oldSlots, oldCount);
|
||||
return newSlots;
|
||||
}
|
||||
|
||||
ObjectElements*
|
||||
js::Nursery::reallocateElements(JSObject* obj, ObjectElements* oldHeader,
|
||||
uint32_t oldCount, uint32_t newCount)
|
||||
{
|
||||
HeapSlot* slots = reallocateSlots(obj, reinterpret_cast<HeapSlot*>(oldHeader),
|
||||
oldCount, newCount);
|
||||
return reinterpret_cast<ObjectElements*>(slots);
|
||||
void* newBuffer = allocateBuffer(obj->zone(), newBytes);
|
||||
if (newBuffer)
|
||||
PodCopy((uint8_t*)newBuffer, (uint8_t*)oldBuffer, oldBytes);
|
||||
return newBuffer;
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::freeSlots(HeapSlot* slots)
|
||||
js::Nursery::freeBuffer(void* buffer)
|
||||
{
|
||||
if (!isInside(slots)) {
|
||||
hugeSlots.remove(slots);
|
||||
js_free(slots);
|
||||
if (!isInside(buffer)) {
|
||||
removeMallocedBuffer(buffer);
|
||||
js_free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
HeapSlot*
|
||||
js::Nursery::allocateHugeSlots(JS::Zone* zone, size_t nslots)
|
||||
{
|
||||
HeapSlot* slots = zone->pod_malloc<HeapSlot>(nslots);
|
||||
/* If this put fails, we will only leak the slots. */
|
||||
if (slots)
|
||||
(void)hugeSlots.put(slots);
|
||||
return slots;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
|
@ -691,8 +644,15 @@ js::Nursery::moveObjectToTenured(MinorCollectionTracer* trc,
|
|||
}
|
||||
}
|
||||
|
||||
if (src->is<InlineTypedObject>())
|
||||
if (src->is<InlineTypedObject>()) {
|
||||
InlineTypedObject::objectMovedDuringMinorGC(trc, dst, src);
|
||||
} else if (src->is<UnboxedArrayObject>()) {
|
||||
tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(trc, dst, src, dstKind);
|
||||
} else {
|
||||
// Objects with JSCLASS_SKIP_NURSERY_FINALIZE need to be handled above
|
||||
// to ensure any additional nursery buffers they hold are moved.
|
||||
MOZ_ASSERT(!(src->getClass()->flags & JSCLASS_SKIP_NURSERY_FINALIZE));
|
||||
}
|
||||
|
||||
return tenuredSize;
|
||||
}
|
||||
|
@ -705,7 +665,7 @@ js::Nursery::moveSlotsToTenured(NativeObject* dst, NativeObject* src, AllocKind
|
|||
return 0;
|
||||
|
||||
if (!isInside(src->slots_)) {
|
||||
hugeSlots.remove(src->slots_);
|
||||
removeMallocedBuffer(src->slots_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -732,7 +692,7 @@ js::Nursery::moveElementsToTenured(NativeObject* dst, NativeObject* src, AllocKi
|
|||
/* TODO Bug 874151: Prefer to put element data inline if we have space. */
|
||||
if (!isInside(srcHeader)) {
|
||||
MOZ_ASSERT(src->elements_ == dst->elements_);
|
||||
hugeSlots.remove(reinterpret_cast<HeapSlot*>(srcHeader));
|
||||
removeMallocedBuffer(srcHeader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -879,13 +839,9 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
|
|||
TIME_END(updateJitActivations);
|
||||
|
||||
// Sweep.
|
||||
TIME_START(runFinalizers);
|
||||
runFinalizers();
|
||||
TIME_END(runFinalizers);
|
||||
|
||||
TIME_START(freeHugeSlots);
|
||||
freeHugeSlots();
|
||||
TIME_END(freeHugeSlots);
|
||||
TIME_START(freeMallocedBuffers);
|
||||
freeMallocedBuffers();
|
||||
TIME_END(freeMallocedBuffers);
|
||||
|
||||
TIME_START(sweep);
|
||||
sweep();
|
||||
|
@ -947,7 +903,7 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
|
|||
|
||||
#define FMT " %6" PRIu64
|
||||
fprintf(stderr,
|
||||
"MinorGC: %20s %5.1f%% %4d" FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT "\n",
|
||||
"MinorGC: %20s %5.1f%% %4d" FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT "\n",
|
||||
js::gcstats::ExplainReason(reason),
|
||||
promotionRate * 100,
|
||||
numActiveChunks_,
|
||||
|
@ -966,8 +922,7 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
|
|||
TIME_TOTAL(collectToFP),
|
||||
TIME_TOTAL(sweepArrayBufferViewList),
|
||||
TIME_TOTAL(updateJitActivations),
|
||||
TIME_TOTAL(runFinalizers),
|
||||
TIME_TOTAL(freeHugeSlots),
|
||||
TIME_TOTAL(freeMallocedBuffers),
|
||||
TIME_TOTAL(clearStoreBuffer),
|
||||
TIME_TOTAL(sweep),
|
||||
TIME_TOTAL(resize),
|
||||
|
@ -981,62 +936,47 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
|
|||
#undef TIME_TOTAL
|
||||
|
||||
void
|
||||
js::Nursery::FreeHugeSlotsTask::transferSlotsToFree(HugeSlotsSet& slotsToFree)
|
||||
js::Nursery::FreeMallocedBuffersTask::transferBuffersToFree(MallocedBuffersSet& buffersToFree)
|
||||
{
|
||||
// Transfer the contents of the source set to the task's slots_ member by
|
||||
// Transfer the contents of the source set to the task's buffers_ member by
|
||||
// swapping the sets, which also clears the source.
|
||||
MOZ_ASSERT(!isRunning());
|
||||
MOZ_ASSERT(slots_.empty());
|
||||
mozilla::Swap(slots_, slotsToFree);
|
||||
MOZ_ASSERT(buffers_.empty());
|
||||
mozilla::Swap(buffers_, buffersToFree);
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::FreeHugeSlotsTask::run()
|
||||
js::Nursery::FreeMallocedBuffersTask::run()
|
||||
{
|
||||
for (HugeSlotsSet::Range r = slots_.all(); !r.empty(); r.popFront())
|
||||
for (MallocedBuffersSet::Range r = buffers_.all(); !r.empty(); r.popFront())
|
||||
fop_->free_(r.front());
|
||||
slots_.clear();
|
||||
buffers_.clear();
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::freeHugeSlots()
|
||||
js::Nursery::freeMallocedBuffers()
|
||||
{
|
||||
if (hugeSlots.empty())
|
||||
if (mallocedBuffers.empty())
|
||||
return;
|
||||
|
||||
bool started;
|
||||
{
|
||||
AutoLockHelperThreadState lock;
|
||||
freeHugeSlotsTask->joinWithLockHeld();
|
||||
freeHugeSlotsTask->transferSlotsToFree(hugeSlots);
|
||||
started = freeHugeSlotsTask->startWithLockHeld();
|
||||
freeMallocedBuffersTask->joinWithLockHeld();
|
||||
freeMallocedBuffersTask->transferBuffersToFree(mallocedBuffers);
|
||||
started = freeMallocedBuffersTask->startWithLockHeld();
|
||||
}
|
||||
|
||||
if (!started)
|
||||
freeHugeSlotsTask->runFromMainThread(runtime());
|
||||
freeMallocedBuffersTask->runFromMainThread(runtime());
|
||||
|
||||
MOZ_ASSERT(hugeSlots.empty());
|
||||
MOZ_ASSERT(mallocedBuffers.empty());
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::waitBackgroundFreeEnd()
|
||||
{
|
||||
freeHugeSlotsTask->join();
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::runFinalizers()
|
||||
{
|
||||
verifyFinalizerList();
|
||||
|
||||
FreeOp* fop = runtime()->defaultFreeOp();
|
||||
for (ListItem* current = finalizers_; current; current = current->next()) {
|
||||
JSObject* obj = current->get();
|
||||
RelocationOverlay* overlay = RelocationOverlay::fromCell(obj);
|
||||
if (!overlay->isForwarded())
|
||||
obj->getClass()->finalize(fop, obj);
|
||||
}
|
||||
finalizers_ = nullptr;
|
||||
freeMallocedBuffersTask->join();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -59,10 +59,9 @@ class Nursery
|
|||
currentChunk_(0),
|
||||
numActiveChunks_(0),
|
||||
numNurseryChunks_(0),
|
||||
finalizers_(nullptr),
|
||||
profileThreshold_(0),
|
||||
enableProfiling_(false),
|
||||
freeHugeSlotsTask(nullptr)
|
||||
freeMallocedBuffersTask(nullptr)
|
||||
{}
|
||||
~Nursery();
|
||||
|
||||
|
@ -94,22 +93,21 @@ class Nursery
|
|||
*/
|
||||
JSObject* allocateObject(JSContext* cx, size_t size, size_t numDynamic, const js::Class* clasp);
|
||||
|
||||
/* Allocate a slots array for the given object. */
|
||||
HeapSlot* allocateSlots(JSObject* obj, uint32_t nslots);
|
||||
/* Allocate a buffer for a given zone, using the nursery if possible. */
|
||||
void* allocateBuffer(Zone* zone, uint32_t nbytes);
|
||||
|
||||
/* Allocate an elements vector for the given object. */
|
||||
ObjectElements* allocateElements(JSObject* obj, uint32_t nelems);
|
||||
/*
|
||||
* Allocate a buffer for a given object, using the nursery if possible and
|
||||
* obj is in the nursery.
|
||||
*/
|
||||
void* allocateBuffer(JSObject* obj, uint32_t nbytes);
|
||||
|
||||
/* Resize an existing slots array. */
|
||||
HeapSlot* reallocateSlots(JSObject* obj, HeapSlot* oldSlots,
|
||||
uint32_t oldCount, uint32_t newCount);
|
||||
/* Resize an existing object buffer. */
|
||||
void* reallocateBuffer(JSObject* obj, void* oldBuffer,
|
||||
uint32_t oldBytes, uint32_t newBytes);
|
||||
|
||||
/* Resize an existing elements vector. */
|
||||
ObjectElements* reallocateElements(JSObject* obj, ObjectElements* oldHeader,
|
||||
uint32_t oldCount, uint32_t newCount);
|
||||
|
||||
/* Free a slots array. */
|
||||
void freeSlots(HeapSlot* slots);
|
||||
/* Free an object buffer. */
|
||||
void freeBuffer(void* buffer);
|
||||
|
||||
typedef Vector<ObjectGroup*, 0, SystemAllocPolicy> ObjectGroupList;
|
||||
|
||||
|
@ -135,6 +133,11 @@ class Nursery
|
|||
setForwardingPointer(oldData, newData, direct);
|
||||
}
|
||||
|
||||
/* Mark a malloced buffer as no longer needing to be freed. */
|
||||
void removeMallocedBuffer(void* buffer) {
|
||||
mallocedBuffers.remove(buffer);
|
||||
}
|
||||
|
||||
void waitBackgroundFreeEnd();
|
||||
|
||||
size_t sizeOfHeapCommitted() const {
|
||||
|
@ -143,11 +146,11 @@ class Nursery
|
|||
size_t sizeOfHeapDecommitted() const {
|
||||
return (numNurseryChunks_ - numActiveChunks_) * gc::ChunkSize;
|
||||
}
|
||||
size_t sizeOfHugeSlots(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
size_t sizeOfMallocedBuffers(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
size_t total = 0;
|
||||
for (HugeSlotsSet::Range r = hugeSlots.all(); !r.empty(); r.popFront())
|
||||
for (MallocedBuffersSet::Range r = mallocedBuffers.all(); !r.empty(); r.popFront())
|
||||
total += mallocSizeOf(r.front());
|
||||
total += hugeSlots.sizeOfExcludingThis(mallocSizeOf);
|
||||
total += mallocedBuffers.sizeOfExcludingThis(mallocSizeOf);
|
||||
return total;
|
||||
}
|
||||
|
||||
|
@ -198,31 +201,21 @@ class Nursery
|
|||
/* Number of chunks allocated for the nursery. */
|
||||
int numNurseryChunks_;
|
||||
|
||||
/* Keep track of objects that need finalization. */
|
||||
class ListItem {
|
||||
ListItem* next_;
|
||||
JSObject* object_;
|
||||
public:
|
||||
ListItem(ListItem* tail, JSObject* obj) : next_(tail), object_(obj) {}
|
||||
ListItem* next() const { return next_; }
|
||||
JSObject* get() { return object_; }
|
||||
} *finalizers_;
|
||||
|
||||
/* Report minor collections taking more than this many us, if enabled. */
|
||||
int64_t profileThreshold_;
|
||||
bool enableProfiling_;
|
||||
|
||||
/*
|
||||
* The set of externally malloced slots potentially kept live by objects
|
||||
* stored in the nursery. Any external slots that do not belong to a
|
||||
* The set of externally malloced buffers potentially kept live by objects
|
||||
* stored in the nursery. Any external buffers that do not belong to a
|
||||
* tenured thing at the end of a minor GC must be freed.
|
||||
*/
|
||||
typedef HashSet<HeapSlot*, PointerHasher<HeapSlot*, 3>, SystemAllocPolicy> HugeSlotsSet;
|
||||
HugeSlotsSet hugeSlots;
|
||||
typedef HashSet<void*, PointerHasher<void*, 3>, SystemAllocPolicy> MallocedBuffersSet;
|
||||
MallocedBuffersSet mallocedBuffers;
|
||||
|
||||
/* A task structure used to free the huge slots on a background thread. */
|
||||
struct FreeHugeSlotsTask;
|
||||
FreeHugeSlotsTask* freeHugeSlotsTask;
|
||||
/* A task structure used to free the malloced bufers on a background thread. */
|
||||
struct FreeMallocedBuffersTask;
|
||||
FreeMallocedBuffersTask* freeMallocedBuffersTask;
|
||||
|
||||
/*
|
||||
* During a collection most hoisted slot and element buffers indicate their
|
||||
|
@ -234,8 +227,8 @@ class Nursery
|
|||
typedef HashMap<void*, void*, PointerHasher<void*, 1>, SystemAllocPolicy> ForwardedBufferMap;
|
||||
ForwardedBufferMap forwardedBuffers;
|
||||
|
||||
/* The maximum number of slots allowed to reside inline in the nursery. */
|
||||
static const size_t MaxNurserySlots = 128;
|
||||
/* The maximum number of bytes allowed to reside in nursery buffers. */
|
||||
static const size_t MaxNurseryBufferSize = 1024;
|
||||
|
||||
/* The amount of space in the mapped nursery available to allocations. */
|
||||
static const size_t NurseryChunkUsableSize = gc::ChunkSize - sizeof(gc::ChunkTrailer);
|
||||
|
@ -292,9 +285,6 @@ class Nursery
|
|||
|
||||
JSRuntime* runtime() const { return runtime_; }
|
||||
|
||||
/* Allocates and registers external slots with the nursery. */
|
||||
HeapSlot* allocateHugeSlots(JS::Zone* zone, size_t nslots);
|
||||
|
||||
/* Allocates a new GC thing from the tenured generation during minor GC. */
|
||||
gc::TenuredCell* allocateFromTenured(JS::Zone* zone, gc::AllocKind thingKind);
|
||||
|
||||
|
@ -302,7 +292,6 @@ class Nursery
|
|||
|
||||
/* Common internal allocator function. */
|
||||
void* allocate(size_t size);
|
||||
void verifyFinalizerList();
|
||||
|
||||
/*
|
||||
* Move the object at |src| in the Nursery to an already-allocated cell
|
||||
|
@ -329,11 +318,8 @@ class Nursery
|
|||
void setElementsForwardingPointer(ObjectElements* oldHeader, ObjectElements* newHeader,
|
||||
uint32_t nelems);
|
||||
|
||||
/* Run finalizers on all finalizable things in the nursery. */
|
||||
void runFinalizers();
|
||||
|
||||
/* Free malloced pointers owned by freed things in the nursery. */
|
||||
void freeHugeSlots();
|
||||
void freeMallocedBuffers();
|
||||
|
||||
/*
|
||||
* Frees all non-live nursery-allocated things at the end of a minor
|
||||
|
|
|
@ -1085,9 +1085,10 @@ MacroAssembler::nurseryAllocate(Register result, Register temp, gc::AllocKind al
|
|||
MOZ_ASSERT(initialHeap != gc::TenuredHeap);
|
||||
|
||||
// We still need to allocate in the nursery, per the comment in
|
||||
// shouldNurseryAllocate; however, we need to insert into hugeSlots, so
|
||||
// bail to do the nursery allocation in the interpreter.
|
||||
if (nDynamicSlots >= Nursery::MaxNurserySlots) {
|
||||
// shouldNurseryAllocate; however, we need to insert into the
|
||||
// mallocedBuffers set, so bail to do the nursery allocation in the
|
||||
// interpreter.
|
||||
if (nDynamicSlots >= Nursery::MaxNurseryBufferSize / sizeof(Value)) {
|
||||
jump(fail);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ UNIFIED_SOURCES += [
|
|||
'testGCFinalizeCallback.cpp',
|
||||
'testGCHeapPostBarriers.cpp',
|
||||
'testGCMarking.cpp',
|
||||
'testGCNursery.cpp',
|
||||
'testGCOutOfMemory.cpp',
|
||||
'testGCStoreBufferRemoval.cpp',
|
||||
'testGetPropertyDescriptor.cpp',
|
||||
|
|
|
@ -3965,6 +3965,16 @@ JSObject::allocKindForTenure(const js::Nursery& nursery) const
|
|||
return GetGCObjectKindForBytes(UnboxedPlainObject::offsetOfData() + nbytes);
|
||||
}
|
||||
|
||||
// Unboxed arrays use inline data if their size is small enough.
|
||||
if (is<UnboxedArrayObject>()) {
|
||||
const UnboxedArrayObject* nobj = &as<UnboxedArrayObject>();
|
||||
size_t nbytes = UnboxedArrayObject::offsetOfInlineElements() +
|
||||
nobj->capacity() * nobj->elementSize();
|
||||
if (nbytes <= JSObject::MAX_BYTE_SIZE)
|
||||
return GetGCObjectKindForBytes(nbytes);
|
||||
return AllocKind::OBJECT0;
|
||||
}
|
||||
|
||||
// Inlined typed objects are followed by their data, so make sure we copy
|
||||
// it all over to the new object.
|
||||
if (is<InlineTypedObject>()) {
|
||||
|
|
|
@ -1112,7 +1112,7 @@ GetInitialHeap(NewObjectKind newKind, const Class* clasp)
|
|||
{
|
||||
if (newKind != GenericObject)
|
||||
return gc::TenuredHeap;
|
||||
if (clasp->finalize && !(clasp->flags & JSCLASS_FINALIZE_FROM_NURSERY))
|
||||
if (clasp->finalize && !(clasp->flags & JSCLASS_SKIP_NURSERY_FINALIZE))
|
||||
return gc::TenuredHeap;
|
||||
return gc::DefaultHeap;
|
||||
}
|
||||
|
|
|
@ -267,7 +267,7 @@ JSObject::create(js::ExclusiveContext* cx, js::gc::AllocKind kind, js::gc::Initi
|
|||
IsBackgroundFinalized(kind));
|
||||
MOZ_ASSERT_IF(group->clasp()->finalize,
|
||||
heap == js::gc::TenuredHeap ||
|
||||
(group->clasp()->flags & JSCLASS_FINALIZE_FROM_NURSERY));
|
||||
(group->clasp()->flags & JSCLASS_SKIP_NURSERY_FINALIZE));
|
||||
MOZ_ASSERT_IF(group->hasUnanalyzedPreliminaryObjects(),
|
||||
heap == js::gc::TenuredHeap);
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ from copy import copy
|
|||
from subprocess import list2cmdline, call
|
||||
|
||||
from lib.results import NullTestOutput
|
||||
from lib.tests import TestCase, TBPL_FLAGS
|
||||
from lib.tests import TestCase, TBPL_FLAGS, TBPL_DEBUG_FLAGS
|
||||
from lib.results import ResultsSink
|
||||
from lib.progressbar import ProgressBar
|
||||
|
||||
|
@ -97,6 +97,9 @@ def parse_args():
|
|||
harness_og.add_option('--tbpl', action='store_true',
|
||||
help='Runs each test in all configurations tbpl'
|
||||
' tests.')
|
||||
harness_og.add_option('--tbpl-debug', action='store_true',
|
||||
help='Runs each test in some faster configurations'
|
||||
' tbpl tests.')
|
||||
harness_og.add_option('-g', '--debug', action='store_true',
|
||||
help='Run a test in debugger.')
|
||||
harness_og.add_option('--debugger', default='gdb -q --args',
|
||||
|
@ -269,9 +272,9 @@ def load_tests(options, requested_paths, excluded_paths):
|
|||
sys.exit()
|
||||
|
||||
# Create a new test list. Apply each TBPL configuration to every test.
|
||||
if options.tbpl:
|
||||
if options.tbpl or options.tbpl_debug:
|
||||
new_test_list = []
|
||||
flags_list = TBPL_FLAGS
|
||||
flags_list = TBPL_FLAGS if options.tbpl else TBPL_DEBUG_FLAGS
|
||||
for test in test_list:
|
||||
for jitflags in flags_list:
|
||||
tmp_test = copy(test)
|
||||
|
|
|
@ -20,6 +20,12 @@ TBPL_FLAGS = [
|
|||
['--baseline-eager', '--no-fpu'],
|
||||
['--no-baseline', '--no-ion'],
|
||||
]
|
||||
# Run reduced variants on debug builds, since they take longer time.
|
||||
TBPL_DEBUG_FLAGS = [
|
||||
[], # no flags, normal baseline and ion
|
||||
['--ion-eager', '--ion-offthread-compile=off'], # implies --baseline-eager
|
||||
['--baseline-eager'],
|
||||
]
|
||||
|
||||
def do_run_cmd(cmd):
|
||||
l = [None, None]
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "gc/Nursery-inl.h"
|
||||
#include "vm/ArrayObject-inl.h"
|
||||
#include "vm/Shape-inl.h"
|
||||
|
||||
|
@ -24,6 +25,7 @@ using namespace js;
|
|||
|
||||
using JS::GenericNaN;
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::PodCopy;
|
||||
using mozilla::RoundUpPow2;
|
||||
|
||||
static const ObjectElements emptyElementsHeader(0, 0);
|
||||
|
@ -377,31 +379,6 @@ NativeObject::setSlotSpan(ExclusiveContext* cx, uint32_t span)
|
|||
return true;
|
||||
}
|
||||
|
||||
// This will not run the garbage collector. If a nursery cannot accomodate the slot array
|
||||
// an attempt will be made to place the array in the tenured area.
|
||||
static HeapSlot*
|
||||
AllocateSlots(ExclusiveContext* cx, JSObject* obj, uint32_t nslots)
|
||||
{
|
||||
if (cx->isJSContext())
|
||||
return cx->asJSContext()->runtime()->gc.nursery.allocateSlots(obj, nslots);
|
||||
return obj->zone()->pod_malloc<HeapSlot>(nslots);
|
||||
}
|
||||
|
||||
// This will not run the garbage collector. If a nursery cannot accomodate the slot array
|
||||
// an attempt will be made to place the array in the tenured area.
|
||||
//
|
||||
// If this returns null then the old slots will be left alone.
|
||||
static HeapSlot*
|
||||
ReallocateSlots(ExclusiveContext* cx, JSObject* obj, HeapSlot* oldSlots,
|
||||
uint32_t oldCount, uint32_t newCount)
|
||||
{
|
||||
if (cx->isJSContext()) {
|
||||
return cx->asJSContext()->runtime()->gc.nursery.reallocateSlots(obj, oldSlots,
|
||||
oldCount, newCount);
|
||||
}
|
||||
return obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
|
||||
}
|
||||
|
||||
bool
|
||||
NativeObject::growSlots(ExclusiveContext* cx, uint32_t oldCount, uint32_t newCount)
|
||||
{
|
||||
|
@ -417,14 +394,14 @@ NativeObject::growSlots(ExclusiveContext* cx, uint32_t oldCount, uint32_t newCou
|
|||
MOZ_ASSERT(newCount < NELEMENTS_LIMIT);
|
||||
|
||||
if (!oldCount) {
|
||||
slots_ = AllocateSlots(cx, this, newCount);
|
||||
slots_ = AllocateObjectBuffer<HeapSlot>(cx, this, newCount);
|
||||
if (!slots_)
|
||||
return false;
|
||||
Debug_SetSlotRangeToCrashOnTouch(slots_, newCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
HeapSlot* newslots = ReallocateSlots(cx, this, slots_, oldCount, newCount);
|
||||
HeapSlot* newslots = ReallocateObjectBuffer<HeapSlot>(cx, this, slots_, oldCount, newCount);
|
||||
if (!newslots)
|
||||
return false; /* Leave slots at its old size. */
|
||||
|
||||
|
@ -440,7 +417,7 @@ FreeSlots(ExclusiveContext* cx, HeapSlot* slots)
|
|||
{
|
||||
// Note: threads without a JSContext do not have access to GGC nursery allocated things.
|
||||
if (cx->isJSContext())
|
||||
return cx->asJSContext()->runtime()->gc.nursery.freeSlots(slots);
|
||||
return cx->asJSContext()->runtime()->gc.nursery.freeBuffer(slots);
|
||||
js_free(slots);
|
||||
}
|
||||
|
||||
|
@ -457,7 +434,7 @@ NativeObject::shrinkSlots(ExclusiveContext* cx, uint32_t oldCount, uint32_t newC
|
|||
|
||||
MOZ_ASSERT_IF(!is<ArrayObject>(), newCount >= SLOT_CAPACITY_MIN);
|
||||
|
||||
HeapSlot* newslots = ReallocateSlots(cx, this, slots_, oldCount, newCount);
|
||||
HeapSlot* newslots = ReallocateObjectBuffer<HeapSlot>(cx, this, slots_, oldCount, newCount);
|
||||
if (!newslots)
|
||||
return; /* Leave slots at its old size. */
|
||||
|
||||
|
@ -664,31 +641,6 @@ NativeObject::maybeDensifySparseElements(js::ExclusiveContext* cx, HandleNativeO
|
|||
return ED_OK;
|
||||
}
|
||||
|
||||
// This will not run the garbage collector. If a nursery cannot accomodate the element array
|
||||
// an attempt will be made to place the array in the tenured area.
|
||||
static ObjectElements*
|
||||
AllocateElements(ExclusiveContext* cx, JSObject* obj, uint32_t nelems)
|
||||
{
|
||||
if (cx->isJSContext())
|
||||
return cx->asJSContext()->runtime()->gc.nursery.allocateElements(obj, nelems);
|
||||
return reinterpret_cast<js::ObjectElements*>(obj->zone()->pod_malloc<HeapSlot>(nelems));
|
||||
}
|
||||
|
||||
// This will not run the garbage collector. If a nursery cannot accomodate the element array
|
||||
// an attempt will be made to place the array in the tenured area.
|
||||
static ObjectElements*
|
||||
ReallocateElements(ExclusiveContext* cx, JSObject* obj, ObjectElements* oldHeader,
|
||||
uint32_t oldCount, uint32_t newCount)
|
||||
{
|
||||
if (cx->isJSContext()) {
|
||||
return cx->asJSContext()->runtime()->gc.nursery.reallocateElements(obj, oldHeader,
|
||||
oldCount, newCount);
|
||||
}
|
||||
return reinterpret_cast<js::ObjectElements*>(
|
||||
obj->zone()->pod_realloc<HeapSlot>(reinterpret_cast<HeapSlot*>(oldHeader),
|
||||
oldCount, newCount));
|
||||
}
|
||||
|
||||
// Round up |reqAllocated| to a good size. Up to 1 Mebi (i.e. 1,048,576) the
|
||||
// slot count is usually a power-of-two:
|
||||
//
|
||||
|
@ -820,19 +772,20 @@ NativeObject::growElements(ExclusiveContext* cx, uint32_t reqCapacity)
|
|||
|
||||
uint32_t initlen = getDenseInitializedLength();
|
||||
|
||||
ObjectElements* newheader;
|
||||
HeapSlot* oldHeaderSlots = reinterpret_cast<HeapSlot*>(getElementsHeader());
|
||||
HeapSlot* newHeaderSlots;
|
||||
if (hasDynamicElements()) {
|
||||
newheader = ReallocateElements(cx, this, getElementsHeader(), oldAllocated, newAllocated);
|
||||
if (!newheader)
|
||||
newHeaderSlots = ReallocateObjectBuffer<HeapSlot>(cx, this, oldHeaderSlots, oldAllocated, newAllocated);
|
||||
if (!newHeaderSlots)
|
||||
return false; // Leave elements at its old size.
|
||||
} else {
|
||||
newheader = AllocateElements(cx, this, newAllocated);
|
||||
if (!newheader)
|
||||
newHeaderSlots = AllocateObjectBuffer<HeapSlot>(cx, this, newAllocated);
|
||||
if (!newHeaderSlots)
|
||||
return false; // Leave elements at its old size.
|
||||
js_memcpy(newheader, getElementsHeader(),
|
||||
(ObjectElements::VALUES_PER_HEADER + initlen) * sizeof(Value));
|
||||
PodCopy(newHeaderSlots, oldHeaderSlots, ObjectElements::VALUES_PER_HEADER + initlen);
|
||||
}
|
||||
|
||||
ObjectElements* newheader = reinterpret_cast<ObjectElements*>(newHeaderSlots);
|
||||
newheader->capacity = newCapacity;
|
||||
elements_ = newheader->elements();
|
||||
|
||||
|
@ -863,13 +816,15 @@ NativeObject::shrinkElements(ExclusiveContext* cx, uint32_t reqCapacity)
|
|||
MOZ_ASSERT(newAllocated > ObjectElements::VALUES_PER_HEADER);
|
||||
uint32_t newCapacity = newAllocated - ObjectElements::VALUES_PER_HEADER;
|
||||
|
||||
ObjectElements* newheader = ReallocateElements(cx, this, getElementsHeader(),
|
||||
oldAllocated, newAllocated);
|
||||
if (!newheader) {
|
||||
HeapSlot* oldHeaderSlots = reinterpret_cast<HeapSlot*>(getElementsHeader());
|
||||
HeapSlot* newHeaderSlots = ReallocateObjectBuffer<HeapSlot>(cx, this, oldHeaderSlots,
|
||||
oldAllocated, newAllocated);
|
||||
if (!newHeaderSlots) {
|
||||
cx->recoverFromOutOfMemory();
|
||||
return; // Leave elements at its old size.
|
||||
}
|
||||
|
||||
ObjectElements* newheader = reinterpret_cast<ObjectElements*>(newHeaderSlots);
|
||||
newheader->capacity = newCapacity;
|
||||
elements_ = newheader->elements();
|
||||
}
|
||||
|
@ -893,9 +848,10 @@ NativeObject::CopyElementsForWrite(ExclusiveContext* cx, NativeObject* obj)
|
|||
|
||||
JSObject::writeBarrierPre(obj->getElementsHeader()->ownerObject());
|
||||
|
||||
ObjectElements* newheader = AllocateElements(cx, obj, newAllocated);
|
||||
if (!newheader)
|
||||
HeapSlot* newHeaderSlots = AllocateObjectBuffer<HeapSlot>(cx, obj, newAllocated);
|
||||
if (!newHeaderSlots)
|
||||
return false;
|
||||
ObjectElements* newheader = reinterpret_cast<ObjectElements*>(newHeaderSlots);
|
||||
js_memcpy(newheader, obj->getElementsHeader(),
|
||||
(ObjectElements::VALUES_PER_HEADER + initlen) * sizeof(Value));
|
||||
|
||||
|
|
|
@ -521,7 +521,7 @@ JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::Runtim
|
|||
rtSizes->gc.marker += gc.marker.sizeOfExcludingThis(mallocSizeOf);
|
||||
rtSizes->gc.nurseryCommitted += gc.nursery.sizeOfHeapCommitted();
|
||||
rtSizes->gc.nurseryDecommitted += gc.nursery.sizeOfHeapDecommitted();
|
||||
rtSizes->gc.nurseryHugeSlots += gc.nursery.sizeOfHugeSlots(mallocSizeOf);
|
||||
rtSizes->gc.nurseryMallocedBuffers += gc.nursery.sizeOfMallocedBuffers(mallocSizeOf);
|
||||
gc.storeBuffer.addSizeOfExcludingThis(mallocSizeOf, &rtSizes->gc);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "gc/Nursery-inl.h"
|
||||
#include "vm/Shape-inl.h"
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
|
@ -1034,16 +1035,18 @@ UnboxedArrayObject::create(ExclusiveContext* cx, HandleObjectGroup group, uint32
|
|||
size_t capacity = (GetGCKindBytes(allocKind) - offsetOfInlineElements()) / elementSize;
|
||||
res->setCapacityIndex(exactCapacityIndex(capacity));
|
||||
} else {
|
||||
UniquePtr<uint8_t[], JS::FreePolicy> elements(
|
||||
cx->zone()->pod_malloc<uint8_t>(length * elementSize));
|
||||
if (!elements)
|
||||
return nullptr;
|
||||
|
||||
res = NewObjectWithGroup<UnboxedArrayObject>(cx, group, gc::AllocKind::OBJECT0, newKind);
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
res->elements_ = elements.release();
|
||||
res->elements_ = AllocateObjectBuffer<uint8_t>(cx, res, length * elementSize);
|
||||
if (!res->elements_) {
|
||||
// Make the object safe for GC.
|
||||
res->setInlineElements();
|
||||
res->setInitializedLength(0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
res->setCapacityIndex(CapacityMatchesLengthIndex);
|
||||
}
|
||||
|
||||
|
@ -1145,10 +1148,51 @@ UnboxedArrayObject::objectMoved(JSObject* obj, const JSObject* old)
|
|||
/* static */ void
|
||||
UnboxedArrayObject::finalize(FreeOp* fop, JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(!IsInsideNursery(obj));
|
||||
if (!obj->as<UnboxedArrayObject>().hasInlineElements())
|
||||
js_free(obj->as<UnboxedArrayObject>().elements());
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
UnboxedArrayObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src,
|
||||
gc::AllocKind allocKind)
|
||||
{
|
||||
UnboxedArrayObject* ndst = &dst->as<UnboxedArrayObject>();
|
||||
UnboxedArrayObject* nsrc = &src->as<UnboxedArrayObject>();
|
||||
MOZ_ASSERT(ndst->elements() == nsrc->elements());
|
||||
|
||||
Nursery& nursery = trc->runtime()->gc.nursery;
|
||||
|
||||
if (!nursery.isInside(nsrc->elements())) {
|
||||
nursery.removeMallocedBuffer(nsrc->elements());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Determine if we can use inline data for the target array. If this is
|
||||
// possible, the nursery will have picked an allocation size that is large
|
||||
// enough.
|
||||
size_t nbytes = nsrc->capacity() * nsrc->elementSize();
|
||||
if (offsetOfInlineElements() + nbytes <= GetGCKindBytes(allocKind)) {
|
||||
ndst->setInlineElements();
|
||||
} else {
|
||||
MOZ_ASSERT(allocKind == gc::AllocKind::OBJECT0);
|
||||
|
||||
uint8_t* data = nsrc->zone()->pod_malloc<uint8_t>(nbytes);
|
||||
if (!data)
|
||||
CrashAtUnhandlableOOM("Failed to allocate unboxed array elements while tenuring.");
|
||||
ndst->elements_ = data;
|
||||
}
|
||||
|
||||
PodCopy(ndst->elements(), nsrc->elements(), nsrc->initializedLength() * nsrc->elementSize());
|
||||
|
||||
// Set a forwarding pointer for the element buffers in case they were
|
||||
// preserved on the stack by Ion.
|
||||
bool direct = nsrc->capacity() * nsrc->elementSize() >= sizeof(uintptr_t);
|
||||
nursery.maybeSetForwardingPointer(trc, nsrc->elements(), ndst->elements(), direct);
|
||||
|
||||
return ndst->hasInlineElements() ? 0 : nbytes;
|
||||
}
|
||||
|
||||
// Possible capacities for unboxed arrays. Some of these capacities might seem
|
||||
// a little weird, but were chosen to allow the inline data of objects of each
|
||||
// size to be fully utilized for arrays of the various types on both 32 bit and
|
||||
|
@ -1266,13 +1310,14 @@ UnboxedArrayObject::growElements(ExclusiveContext* cx, size_t cap)
|
|||
|
||||
uint8_t* newElements;
|
||||
if (hasInlineElements()) {
|
||||
newElements = cx->zone()->pod_malloc<uint8_t>(newCapacity * elementSize());
|
||||
newElements = AllocateObjectBuffer<uint8_t>(cx, this, newCapacity * elementSize());
|
||||
if (!newElements)
|
||||
return false;
|
||||
js_memcpy(newElements, elements(), initializedLength() * elementSize());
|
||||
} else {
|
||||
newElements = cx->zone()->pod_realloc<uint8_t>(elements(), oldCapacity * elementSize(),
|
||||
newCapacity * elementSize());
|
||||
newElements = ReallocateObjectBuffer<uint8_t>(cx, this, elements(),
|
||||
oldCapacity * elementSize(),
|
||||
newCapacity * elementSize());
|
||||
if (!newElements)
|
||||
return false;
|
||||
}
|
||||
|
@ -1299,9 +1344,9 @@ UnboxedArrayObject::shrinkElements(ExclusiveContext* cx, size_t cap)
|
|||
if (newCapacity >= oldCapacity)
|
||||
return;
|
||||
|
||||
uint8_t* newElements =
|
||||
cx->zone()->pod_realloc<uint8_t>(elements(), oldCapacity * elementSize(),
|
||||
newCapacity * elementSize());
|
||||
uint8_t* newElements = ReallocateObjectBuffer<uint8_t>(cx, this, elements(),
|
||||
oldCapacity * elementSize(),
|
||||
newCapacity * elementSize());
|
||||
if (!newElements)
|
||||
return;
|
||||
|
||||
|
@ -1496,7 +1541,8 @@ const Class UnboxedArrayObject::class_ = {
|
|||
"Array",
|
||||
Class::NON_NATIVE |
|
||||
JSCLASS_IMPLEMENTS_BARRIERS |
|
||||
0 /* FIXME using this flag can severely hurt performance: JSCLASS_BACKGROUND_FINALIZE */,
|
||||
JSCLASS_SKIP_NURSERY_FINALIZE |
|
||||
JSCLASS_BACKGROUND_FINALIZE,
|
||||
nullptr, /* addProperty */
|
||||
nullptr, /* delProperty */
|
||||
nullptr, /* getProperty */
|
||||
|
|
|
@ -399,6 +399,9 @@ class UnboxedArrayObject : public JSObject
|
|||
static void objectMoved(JSObject* obj, const JSObject* old);
|
||||
static void finalize(FreeOp* fop, JSObject* obj);
|
||||
|
||||
static size_t objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src,
|
||||
gc::AllocKind allocKind);
|
||||
|
||||
uint8_t* elements() {
|
||||
return elements_;
|
||||
}
|
||||
|
|
|
@ -945,7 +945,11 @@ xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prin
|
|||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
|
||||
// Now check what sort of thing we've got in |proto|
|
||||
JSObject* unwrappedProto = js::UncheckedUnwrap(options.proto, false);
|
||||
JSObject* unwrappedProto = js::CheckedUnwrap(options.proto, false);
|
||||
if (!unwrappedProto) {
|
||||
JS_ReportError(cx, "Sandbox must subsume sandboxPrototype");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
const js::Class* unwrappedClass = js::GetObjectClass(unwrappedProto);
|
||||
if (IS_WN_CLASS(unwrappedClass) ||
|
||||
mozilla::dom::IsDOMClass(Jsvalify(unwrappedClass))) {
|
||||
|
|
|
@ -2553,8 +2553,8 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats& rtStats,
|
|||
KIND_NONHEAP, rtStats.runtime.gc.nurseryCommitted,
|
||||
"Memory being used by the GC's nursery.");
|
||||
|
||||
RREPORT_BYTES(rtPath + NS_LITERAL_CSTRING("runtime/gc/nursery-huge-slots"),
|
||||
KIND_NONHEAP, rtStats.runtime.gc.nurseryHugeSlots,
|
||||
RREPORT_BYTES(rtPath + NS_LITERAL_CSTRING("runtime/gc/nursery-malloced-buffers"),
|
||||
KIND_NONHEAP, rtStats.runtime.gc.nurseryMallocedBuffers,
|
||||
"Out-of-line slots and elements belonging to objects in the "
|
||||
"nursery.");
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "nsAutoPtr.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "xpcprivate.h"
|
||||
#include "BackstagePass.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIPrincipal.h"
|
||||
|
@ -632,6 +633,35 @@ SimulateActivityCallback(JSContext* cx, unsigned argc, jsval* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
RegisterAppManifest(JSContext* cx, unsigned argc, jsval* vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
if (args.length() != 1) {
|
||||
JS_ReportError(cx, "Wrong number of arguments");
|
||||
return false;
|
||||
}
|
||||
if (!args[0].isObject()) {
|
||||
JS_ReportError(cx, "Expected object as argument 1 to registerAppManifest");
|
||||
return false;
|
||||
}
|
||||
|
||||
Rooted<JSObject*> arg1(cx, &args[0].toObject());
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = nsXPConnect::XPConnect()->
|
||||
WrapJS(cx, arg1, NS_GET_IID(nsIFile), getter_AddRefs(file));
|
||||
if (NS_FAILED(rv)) {
|
||||
XPCThrower::Throw(rv, cx);
|
||||
return false;
|
||||
}
|
||||
rv = XRE_AddManifestLocation(NS_APP_LOCATION, file);
|
||||
if (NS_FAILED(rv)) {
|
||||
XPCThrower::Throw(rv, cx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static const JSFunctionSpec glob_functions[] = {
|
||||
JS_FS("print", Print, 0,0),
|
||||
JS_FS("readline", ReadLine, 1,0),
|
||||
|
@ -652,6 +682,7 @@ static const JSFunctionSpec glob_functions[] = {
|
|||
JS_FS("btoa", Btoa, 1,0),
|
||||
JS_FS("setInterruptCallback", SetInterruptCallback, 1,0),
|
||||
JS_FS("simulateActivityCallback", SimulateActivityCallback, 1,0),
|
||||
JS_FS("registerAppManifest", RegisterAppManifest, 1, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
@ -1341,7 +1372,7 @@ XRE_XPCShellMain(int argc, char** argv, char** envp)
|
|||
printf("Couldn't get manifest file.\n");
|
||||
return 1;
|
||||
}
|
||||
XRE_AddManifestLocation(NS_COMPONENT_LOCATION, lf);
|
||||
XRE_AddManifestLocation(NS_APP_LOCATION, lf);
|
||||
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
|
|
|
@ -8,8 +8,8 @@ const Ci = Components.interfaces;
|
|||
function run_test() {
|
||||
|
||||
// Load the component manifests.
|
||||
Components.manager.autoRegister(do_get_file('../components/native/xpctest.manifest'));
|
||||
Components.manager.autoRegister(do_get_file('../components/js/xpctest.manifest'));
|
||||
registerAppManifest(do_get_file('../components/native/xpctest.manifest'));
|
||||
registerAppManifest(do_get_file('../components/js/xpctest.manifest'));
|
||||
|
||||
// Test for each component.
|
||||
test_component_readwrite("@mozilla.org/js/xpc/test/native/ObjectReadWrite;1");
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
function run_test()
|
||||
{
|
||||
try {
|
||||
var sandbox = new Components.utils.Sandbox(null, {"sandboxPrototype" : {}});
|
||||
do_check_true(false);
|
||||
} catch (e) {
|
||||
do_check_true(/must subsume sandboxPrototype/.test(e));
|
||||
}
|
||||
}
|
|
@ -8,8 +8,8 @@ const Ci = Components.interfaces;
|
|||
function run_test() {
|
||||
|
||||
// Load the component manifests.
|
||||
Components.manager.autoRegister(do_get_file('../components/native/xpctest.manifest'));
|
||||
Components.manager.autoRegister(do_get_file('../components/js/xpctest.manifest'));
|
||||
registerAppManifest(do_get_file('../components/native/xpctest.manifest'));
|
||||
registerAppManifest(do_get_file('../components/js/xpctest.manifest'));
|
||||
|
||||
// Test for each component.
|
||||
test_component("@mozilla.org/js/xpc/test/native/Params;1");
|
||||
|
|
|
@ -16,8 +16,8 @@ function getConsoleMessages() {
|
|||
|
||||
function run_test() {
|
||||
// Load the component manifests.
|
||||
Cm.autoRegister(do_get_file('../components/native/xpctest.manifest'));
|
||||
Cm.autoRegister(do_get_file('../components/js/xpctest.manifest'));
|
||||
registerAppManifest(do_get_file('../components/native/xpctest.manifest'));
|
||||
registerAppManifest(do_get_file('../components/js/xpctest.manifest'));
|
||||
|
||||
// and the tests.
|
||||
test_simple();
|
||||
|
|
|
@ -55,6 +55,7 @@ support-files =
|
|||
[test_bug1081990.js]
|
||||
[test_bug1110546.js]
|
||||
[test_bug1150771.js]
|
||||
[test_bug1151385.js]
|
||||
[test_bug_442086.js]
|
||||
[test_callFunctionWithAsyncStack.js]
|
||||
[test_file.js]
|
||||
|
|
|
@ -2688,7 +2688,7 @@ nsCSSFrameConstructor::ConstructRootFrame()
|
|||
nsContainerFrame::SyncFrameViewProperties(mPresShell->GetPresContext(), viewportFrame,
|
||||
viewportPseudoStyle, rootView);
|
||||
nsContainerFrame::SyncWindowProperties(mPresShell->GetPresContext(), viewportFrame,
|
||||
rootView);
|
||||
rootView, nullptr, nsContainerFrame::SET_ASYNC);
|
||||
|
||||
// Make it an absolute container for fixed-pos elements
|
||||
viewportFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
||||
|
|
|
@ -140,8 +140,8 @@ typedef struct CapturingContentInfo {
|
|||
|
||||
// d910f009-d209-74c1-6b04-30c83c051c78
|
||||
#define NS_IPRESSHELL_IID \
|
||||
{ 0xd910f009, 0xd209, 0x74c1, \
|
||||
{ 0x6b, 0x04, 0x30, 0xc8, 0x3c, 0x05, 0x1c, 0x78 } }
|
||||
{ 0x025264c6, 0x0b12, 0x4804, \
|
||||
{ 0xa3, 0x3e, 0xb7, 0x73, 0xf2, 0x19, 0x48, 0x90 } }
|
||||
|
||||
// debug VerifyReflow flags
|
||||
#define VERIFY_REFLOW_ON 0x01
|
||||
|
@ -1661,6 +1661,8 @@ public:
|
|||
bool HasPendingReflow() const
|
||||
{ return mReflowScheduled || mReflowContinueTimer; }
|
||||
|
||||
void SyncWindowProperties(nsView* aView);
|
||||
|
||||
protected:
|
||||
friend class nsRefreshDriver;
|
||||
|
||||
|
|
|
@ -3116,10 +3116,12 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
|||
}
|
||||
}
|
||||
#if !defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ANDROID_APZ)
|
||||
else if (presShell->GetDocument() && presShell->GetDocument()->IsRootDisplayDocument()) {
|
||||
else if (presShell->GetDocument() && presShell->GetDocument()->IsRootDisplayDocument()
|
||||
&& !presShell->GetRootScrollFrame()) {
|
||||
// In cases where the root document is a XUL document, we want to take
|
||||
// the ViewID from the root element, as that will be the ViewID of the
|
||||
// root APZC in the tree.
|
||||
// root APZC in the tree. Skip doing this in cases where we know
|
||||
// nsGfxScrollFrame::BuilDisplayList will do it instead.
|
||||
if (dom::Element* element = presShell->GetDocument()->GetDocumentElement()) {
|
||||
id = nsLayoutUtils::FindOrCreateIDFor(element);
|
||||
}
|
||||
|
|
|
@ -9245,7 +9245,8 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
|
|||
target->GetView(),
|
||||
boundsRelativeToTarget);
|
||||
nsContainerFrame::SyncWindowProperties(mPresContext, target,
|
||||
target->GetView(), &rcx);
|
||||
target->GetView(), &rcx,
|
||||
nsContainerFrame::SET_ASYNC);
|
||||
|
||||
target->DidReflow(mPresContext, nullptr, nsDidReflowStatus::FINISHED);
|
||||
if (target == rootFrame && size.BSize(wm) == NS_UNCONSTRAINEDSIZE) {
|
||||
|
@ -11081,3 +11082,13 @@ PresShell::ResumePainting()
|
|||
mPaintingIsFrozen = false;
|
||||
GetPresContext()->RefreshDriver()->Thaw();
|
||||
}
|
||||
|
||||
void
|
||||
nsIPresShell::SyncWindowProperties(nsView* aView)
|
||||
{
|
||||
nsIFrame* frame = aView->GetFrame();
|
||||
if (frame && mPresContext) {
|
||||
nsRenderingContext rcx(CreateReferenceRenderingContext());
|
||||
nsContainerFrame::SyncWindowProperties(mPresContext, frame, aView, &rcx, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -609,14 +609,15 @@ IsTopLevelWidget(nsIWidget* aWidget)
|
|||
void
|
||||
nsContainerFrame::SyncWindowProperties(nsPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
nsView* aView,
|
||||
nsRenderingContext* aRC)
|
||||
nsView* aView,
|
||||
nsRenderingContext* aRC,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
#ifdef MOZ_XUL
|
||||
if (!aView || !nsCSSRendering::IsCanvasFrame(aFrame) || !aView->HasWidget())
|
||||
return;
|
||||
|
||||
nsIWidget* windowWidget = GetPresContextContainerWidget(aPresContext);
|
||||
nsCOMPtr<nsIWidget> windowWidget = GetPresContextContainerWidget(aPresContext);
|
||||
if (!windowWidget || !IsTopLevelWidget(windowWidget))
|
||||
return;
|
||||
|
||||
|
@ -650,14 +651,27 @@ nsContainerFrame::SyncWindowProperties(nsPresContext* aPresContext,
|
|||
if (!rootFrame)
|
||||
return;
|
||||
|
||||
if (aFlags & SET_ASYNC) {
|
||||
aView->SetNeedsWindowPropertiesSync();
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<nsPresContext> kungFuDeathGrip(aPresContext);
|
||||
nsWeakFrame weak(rootFrame);
|
||||
|
||||
nsTransparencyMode mode = nsLayoutUtils::GetFrameTransparency(aFrame, rootFrame);
|
||||
nsIWidget* viewWidget = aView->GetWidget();
|
||||
int32_t shadow = rootFrame->StyleUIReset()->mWindowShadow;
|
||||
nsCOMPtr<nsIWidget> viewWidget = aView->GetWidget();
|
||||
viewWidget->SetTransparencyMode(mode);
|
||||
windowWidget->SetWindowShadowStyle(rootFrame->StyleUIReset()->mWindowShadow);
|
||||
windowWidget->SetWindowShadowStyle(shadow);
|
||||
|
||||
if (!aRC)
|
||||
return;
|
||||
|
||||
|
||||
if (!weak.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsBoxLayoutState aState(aPresContext, aRC);
|
||||
nsSize minSize = rootFrame->GetMinSize(aState);
|
||||
nsSize maxSize = rootFrame->GetMaxSize(aState);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче