Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2015-05-05 12:15:21 +02:00
Родитель 1e817a57be 0d950f5c81
Коммит 7976b9d3b3
152 изменённых файлов: 1858 добавлений и 897 удалений

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

@ -22,5 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please # changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more. # don't change CLOBBER for WebIDL changes any more.
Bug 1159082 - Renaming *Readonly animation interfaces to *ReadOnly causes Bug 1128037 needed a clobber to properly build on OS X
build bustage on case-insensitive filesystems.

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

@ -1132,6 +1132,10 @@ pref("dom.requestSync.enabled", true);
// Resample touch events on b2g // Resample touch events on b2g
pref("gfx.touch.resample", true); 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 // mulet apparently loads firefox.js as well as b2g.js, so we have to explicitly
// disable serviceworkers here to get them disabled in mulet. // disable serviceworkers here to get them disabled in mulet.
pref("dom.serviceWorkers.enabled", false); pref("dom.serviceWorkers.enabled", false);

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26"> <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </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="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <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="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>

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

@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <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="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/> <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26"> <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </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="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33"> <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </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="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <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="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/> <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"> <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </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="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -17,7 +17,7 @@
</project> </project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <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="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/> <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>

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

@ -1,9 +1,9 @@
{ {
"git": { "git": {
"git_revision": "70077825aab2c7a79611befb40a5fe7e610d5443", "git_revision": "e1773d6d1014c997be4b5c4233bba3ee073b8d7b",
"remote": "https://git.mozilla.org/releases/gaia.git", "remote": "https://git.mozilla.org/releases/gaia.git",
"branch": "" "branch": ""
}, },
"revision": "536698903e2c4c12a3ff6c6d83f70278fab7311d", "revision": "172680469094791e563268fa7d074fee9e0105ab",
"repo_path": "integration/gaia-central" "repo_path": "integration/gaia-central"
} }

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

@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <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="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/> <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33"> <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </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="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -13,8 +13,7 @@ var gPluginHandler = {
"PluginContent:HideNotificationBar", "PluginContent:HideNotificationBar",
"PluginContent:ShowInstallNotification", "PluginContent:ShowInstallNotification",
"PluginContent:InstallSinglePlugin", "PluginContent:InstallSinglePlugin",
"PluginContent:ShowNPAPIPluginCrashedNotification", "PluginContent:ShowPluginCrashedNotification",
"PluginContent:ShowGMPCrashedNotification",
"PluginContent:SubmitReport", "PluginContent:SubmitReport",
"PluginContent:LinkClickCallback", "PluginContent:LinkClickCallback",
], ],
@ -62,15 +61,9 @@ var gPluginHandler = {
case "PluginContent:InstallSinglePlugin": case "PluginContent:InstallSinglePlugin":
this.installSinglePlugin(msg.data.pluginInfo); this.installSinglePlugin(msg.data.pluginInfo);
break; break;
case "PluginContent:ShowNPAPIPluginCrashedNotification": case "PluginContent:ShowPluginCrashedNotification":
this.showNPAPIPluginCrashedNotification(msg.target, msg.data.message, this.showPluginCrashedNotification(msg.target, msg.data.messageString,
msg.data.runID); msg.data.pluginID);
break;
case "PluginContent:ShowGMPCrashedNotification":
this.showGMPCrashedNotification(msg.target,
msg.data.messageString,
msg.data.pluginDumpID,
msg.data.browserDumpID);
break; break;
case "PluginContent:SubmitReport": case "PluginContent:SubmitReport":
if (AppConstants.MOZ_CRASHREPORTER) { if (AppConstants.MOZ_CRASHREPORTER) {
@ -498,63 +491,32 @@ var gPluginHandler = {
{ pluginName, runID, state }); { 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, * Shows a plugin-crashed notification bar for a browser that has had an
* since the latter are not yet working for e10s. These will be unified * invisiable NPAPI plugin crash, or a GMP plugin crash.
* 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.
* *
* @param browser * @param browser
* The browser that contains the crashing plugin. * The browser to show the notification for.
* @param messageString * @param messageString
* The message to display in the notification. * The string to put in the notification bar
* @param crashReportCallback * @param pluginID
* Optional. Pass a function to submit a crash report for this plugin * The unique-per-process identifier for the NPAPI plugin or GMP.
* crash if a report exists. If no function is passed, the Submit Report * For a GMP, this is the pluginID. For NPAPI plugins (where "pluginID"
* button will not be added. * 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. // If there's already an existing notification bar, don't do anything.
let notificationBox = gBrowser.getNotificationBox(browser); let notificationBox = gBrowser.getNotificationBox(browser);
let notification = notificationBox.getNotificationWithValue("plugin-crashed"); let notification = notificationBox.getNotificationWithValue("plugin-crashed");
if (notification) if (notification) {
return; return;
}
// Configure the notification bar // Configure the notification bar
let priority = notificationBox.PRIORITY_WARNING_MEDIUM; let priority = notificationBox.PRIORITY_WARNING_MEDIUM;
let iconURL = "chrome://mozapps/skin/plugins/notifyPluginCrashed.png"; let iconURL = "chrome://mozapps/skin/plugins/notifyPluginCrashed.png";
let reloadLabel = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.label"); let reloadLabel = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.label");
let reloadKey = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.accesskey"); let reloadKey = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.accesskey");
let submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label");
let submitKey = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey");
let buttons = [{ let buttons = [{
label: reloadLabel, label: reloadLabel,
@ -563,12 +525,17 @@ var gPluginHandler = {
callback: function() { browser.reload(); }, 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 = { let submitButton = {
label: submitLabel, label: submitLabel,
accessKey: submitKey, accessKey: submitKey,
popup: null, popup: null,
callback: crashReportCallback, callback: () => {
PluginCrashReporter.submitCrashReport(pluginID);
},
}; };
buttons.push(submitButton); buttons.push(submitButton);
@ -585,11 +552,9 @@ var gPluginHandler = {
let crashurl = formatURL("app.support.baseURL", true); let crashurl = formatURL("app.support.baseURL", true);
crashurl += "plugin-crashed-notificationbar"; crashurl += "plugin-crashed-notificationbar";
link.href = crashurl; link.href = crashurl;
let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText"); let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
description.appendChild(link); description.appendChild(link);
}, },
}; };
gPluginHandler.init(); gPluginHandler.init();

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

@ -1,6 +1,5 @@
/** /**
* Test that plugin crash submissions still work properly after * Test that the notification bar for crashed GMPs works.
* click-to-play activation.
*/ */
add_task(function*() { add_task(function*() {
yield BrowserTestUtils.withNewTab({ yield BrowserTestUtils.withNewTab({
@ -9,9 +8,8 @@ add_task(function*() {
}, function* (browser) { }, function* (browser) {
yield ContentTask.spawn(browser, null, function* () { yield ContentTask.spawn(browser, null, function* () {
const GMP_CRASH_EVENT = { const GMP_CRASH_EVENT = {
pluginID: 1,
pluginName: "GlobalTestPlugin", pluginName: "GlobalTestPlugin",
pluginDumpID: "1234",
browserDumpID: "5678",
submittedCrashReport: false, submittedCrashReport: false,
bubbles: true, bubbles: true,
cancelable: 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 # 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/. # 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 ${GetParameters} $0
${GetOptions} "$0" "/UAC:" $1 ${GetOptions} "$0" "/UAC:" $1
${If} ${Errors} ${If} ${Errors}
StrCpy $1 "0" Exec "$\"$INSTDIR\${FileMainEXE}$\""
StrCpy $2 "0"
${If} $1 == "1"
Exec "$\"$INSTDIR\${FileMainEXE}$\""
${EndIf}
${Else} ${Else}
GetFunctionAddress $0 LaunchAppFromElevatedProcess GetFunctionAddress $0 LaunchAppFromElevatedProcess
UAC::ExecCodeSegment $0 UAC::ExecCodeSegment $0
@ -816,12 +812,7 @@ Function LaunchAppFromElevatedProcess
; Set our current working directory to the application's install directory ; 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. ; otherwise the 7-Zip temp directory will be in use and won't be deleted.
SetOutPath "$1" SetOutPath "$1"
StrCpy $2 "0" Exec "$\"$0$\""
StrCpy $3 "0"
${If} $2 == "1"
; Launch into desktop
Exec "$\"$0$\""
${EndIf}
FunctionEnd FunctionEnd
################################################################################ ################################################################################

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

@ -114,27 +114,68 @@ this.PluginCrashReporter = {
this.crashReports = new Map(); this.crashReports = new Map();
Services.obs.addObserver(this, "plugin-crashed", false); 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) { observe(subject, topic, data) {
if (topic != "plugin-crashed") { switch(topic) {
return; 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; let runID = propertyBag.getPropertyAsUint32("runID");
if (!(propertyBag instanceof Ci.nsIPropertyBag2) || let pluginDumpID = propertyBag.getPropertyAsAString("pluginDumpID");
!(propertyBag instanceof Ci.nsIWritablePropertyBag2) || let browserDumpID = propertyBag.getPropertyAsAString("browserDumpID");
!propertyBag.hasKey("runID") || if (pluginDumpID) {
!propertyBag.hasKey("pluginName")) { this.crashReports.set(runID, { pluginDumpID, browserDumpID });
Cu.reportError("PluginCrashReporter can not read plugin information."); }
return; 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 pluginID = propertyBag.getPropertyAsUint32("pluginID");
let pluginDumpID = propertyBag.getPropertyAsAString("pluginDumpID"); let pluginDumpID = propertyBag.getPropertyAsAString("pluginDumpID");
let browserDumpID = propertyBag.getPropertyAsAString("browserDumpID"); if (pluginDumpID) {
if (pluginDumpID) { this.crashReports.set(pluginID, { pluginDumpID });
this.crashReports.set(runID, { pluginDumpID, browserDumpID }); }
// 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) { hasCrashReport(runID) {
return this.crashReports.has(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 // If another plugin on the page was large enough to show our UI, we don't
// want to show a notification bar. // want to show a notification bar.
if (!doc.mozNoPluginCrashedNotification) { if (!doc.mozNoPluginCrashedNotification) {
this.global.sendAsyncMessage("PluginContent:ShowNPAPIPluginCrashedNotification", this.global.sendAsyncMessage("PluginContent:ShowPluginCrashedNotification",
{ message, runID }); { messageString: message, pluginID: runID });
// Remove the notification when the page is reloaded. // Remove the notification when the page is reloaded.
doc.defaultView.top.addEventListener("unload", event => { doc.defaultView.top.addEventListener("unload", event => {
this.hideNotificationBar("plugin-crashed"); 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) { GMPCrashed: function(aEvent) {
let target = aEvent.target; let target = aEvent.target;
let submittedReport = aEvent.submittedCrashReport;
let pluginName = aEvent.pluginName; let pluginName = aEvent.pluginName;
let pluginDumpID = aEvent.pluginDumpID;
let browserDumpID = aEvent.browserDumpID;
let gmpPlugin = aEvent.gmpPlugin; let gmpPlugin = aEvent.gmpPlugin;
let pluginID = aEvent.pluginID;
let doc = target.document; let doc = target.document;
if (!gmpPlugin || !doc) { if (!gmpPlugin || !doc) {
@ -1079,11 +1073,8 @@ PluginContent.prototype = {
gNavigatorBundle.formatStringFromName("crashedpluginsMessage.title", gNavigatorBundle.formatStringFromName("crashedpluginsMessage.title",
[pluginName], 1); [pluginName], 1);
this.global.sendAsyncMessage("PluginContent:ShowGMPCrashedNotification", { this.global.sendAsyncMessage("PluginContent:ShowPluginCrashedNotification",
messageString: messageString, { messageString, pluginID });
pluginDumpID: pluginDumpID,
browserDumpID: browserDumpID,
});
// Remove the notification when the page is reloaded. // Remove the notification when the page is reloaded.
doc.defaultView.top.addEventListener("unload", event => { 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) 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 Register Chrome
=============== ===============

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

@ -279,8 +279,9 @@ class RemoteAutomation(Automation):
self.procName = app self.procName = app
print "Robocop process name: "+self.procName print "Robocop process name: "+self.procName
# Setting timeout at 1 hour since on a remote device this takes much longer # Setting timeout at 1 hour since on a remote device this takes much longer.
self.timeout = 3600 # 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 # The benefit of the following sleep is unclear; it was formerly 15 seconds
time.sleep(1) time.sleep(1)

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

@ -3577,7 +3577,7 @@ MOZ_ARG_WITH_BOOL(system-nss,
_USE_SYSTEM_NSS=1 ) _USE_SYSTEM_NSS=1 )
if test -n "$_USE_SYSTEM_NSS"; then 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 fi
if test -n "$MOZ_NATIVE_NSS"; then if test -n "$MOZ_NATIVE_NSS"; then

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

@ -355,6 +355,23 @@ let Activities = {
calleeApp.appStatus !== Ci.nsIPrincipal.APP_STATUS_CERTIFIED) { calleeApp.appStatus !== Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
return false; 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, return ActivitiesServiceFilter.match(aMsg.options.data,
aResult.description.filters); aResult.description.filters);
}; };

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

@ -69,6 +69,22 @@ ActivityProxy.prototype = {
return; 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:FireSuccess", this);
cpmm.addMessageListener("Activity:FireError", this); cpmm.addMessageListener("Activity:FireError", this);

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

@ -8,6 +8,8 @@ DIRS += ['interfaces']
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini'] XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
MOCHITEST_CHROME_MANIFESTS += ['tests/mochi/mochitest.ini']
EXPORTS.mozilla.dom += [ EXPORTS.mozilla.dom += [
'Activity.h', '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/WindowBinding.h"
#include "mozilla/dom/ElementBinding.h" #include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/VRDevice.h" #include "mozilla/dom/VRDevice.h"
#include "nsComputedDOMStyle.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
@ -385,7 +386,7 @@ Element::GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult)
IsHTMLElement(nsGkAtoms::object) || IsHTMLElement(nsGkAtoms::object) ||
IsHTMLElement(nsGkAtoms::embed) || IsHTMLElement(nsGkAtoms::embed) ||
IsHTMLElement(nsGkAtoms::applet)); IsHTMLElement(nsGkAtoms::applet));
nsIPresShell *shell = aDocument->GetShell(); nsCOMPtr<nsIPresShell> shell = aDocument->GetShell();
if (!shell || GetPrimaryFrame() || !isXULorPluginElement) { if (!shell || GetPrimaryFrame() || !isXULorPluginElement) {
*aResult = nullptr; *aResult = nullptr;
@ -393,11 +394,8 @@ Element::GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult)
} }
// Get the computed -moz-binding directly from the style context // Get the computed -moz-binding directly from the style context
nsPresContext *pctx = shell->GetPresContext(); nsRefPtr<nsStyleContext> sc =
NS_ENSURE_TRUE(pctx, false); nsComputedDOMStyle::GetStyleContextForElementNoFlush(this, nullptr, shell);
nsRefPtr<nsStyleContext> sc = pctx->StyleSet()->ResolveStyleFor(this,
nullptr);
NS_ENSURE_TRUE(sc, false); NS_ENSURE_TRUE(sc, false);
*aResult = sc->StyleDisplay()->mBinding; *aResult = sc->StyleDisplay()->mBinding;

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

@ -10398,7 +10398,7 @@ class CGDOMJSProxyHandler_getOwnPropDescriptor(ClassMethod):
$*{getIndexed} $*{getIndexed}
JS::Rooted<JSObject*> expando(cx); JS::Rooted<JSObject*> expando(cx);
if (!isXray && (expando = GetExpandoObject(proxy))) { if (!isXray && (expando = GetExpandoObject(proxy))) {
if (!JS_GetPropertyDescriptorById(cx, expando, id, desc)) { if (!JS_GetOwnPropertyDescriptorById(cx, expando, id, desc)) {
return false; return false;
} }
if (desc.object()) { 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 // Make sure to ignore our named properties when checking for own
// property descriptors for a set. // property descriptors for a set.
JS::Rooted<JSPropertyDescriptor> desc(cx); JS::Rooted<JSPropertyDescriptor> ownDesc(cx);
if (!getOwnPropDescriptor(cx, proxy, id, /* ignoreNamedProps = */ true, if (!getOwnPropDescriptor(cx, proxy, id, /* ignoreNamedProps = */ true,
&desc)) { &ownDesc)) {
return false; return false;
} }
if (!desc.object()) { return js::SetPropertyIgnoringNamedGetter(cx, proxy, id, v, receiver, ownDesc, result);
// 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);
} }
bool bool

3
dom/cache/TypeUtils.cpp поставляемый
Просмотреть файл

@ -400,7 +400,8 @@ TypeUtils::ProcessURL(nsAString& aUrl, bool* aSchemeValidOut,
if (aSchemeValidOut) { if (aSchemeValidOut) {
nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen)); nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
*aSchemeValidOut = scheme.LowerCaseEqualsLiteral("http") || *aSchemeValidOut = scheme.LowerCaseEqualsLiteral("http") ||
scheme.LowerCaseEqualsLiteral("https"); scheme.LowerCaseEqualsLiteral("https") ||
scheme.LowerCaseEqualsLiteral("app");
} }
uint32_t queryPos; uint32_t queryPos;

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

@ -290,10 +290,7 @@ void MediaDecoder::Pause()
void MediaDecoder::SetVolume(double aVolume) void MediaDecoder::SetVolume(double aVolume)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
mInitialVolume = aVolume; mVolume = aVolume;
if (mDecoderStateMachine) {
mDecoderStateMachine->SetVolume(aVolume);
}
} }
void MediaDecoder::ConnectDecodedStreamToOutputStream(OutputStreamData* aStream) void MediaDecoder::ConnectDecodedStreamToOutputStream(OutputStreamData* aStream)
@ -538,7 +535,7 @@ void MediaDecoder::AddOutputStream(ProcessedMediaStream* aStream,
{ {
ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
if (mDecoderStateMachine) { if (mDecoderStateMachine) {
mDecoderStateMachine->SetAudioCaptured(); mDecoderStateMachine->DispatchAudioCaptured();
} }
if (!GetDecodedStream()) { if (!GetDecodedStream()) {
int64_t t = mDecoderStateMachine ? int64_t t = mDecoderStateMachine ?
@ -602,9 +599,9 @@ MediaDecoder::MediaDecoder() :
mDecoderPosition(0), mDecoderPosition(0),
mPlaybackPosition(0), mPlaybackPosition(0),
mCurrentTime(0.0), mCurrentTime(0.0),
mInitialVolume(0.0), mVolume(AbstractThread::MainThread(), 0.0, "MediaDecoder::mVolume (Canonical)"),
mInitialPlaybackRate(1.0), mPlaybackRate(AbstractThread::MainThread(), 1.0, "MediaDecoder::mPlaybackRate (Canonical)"),
mInitialPreservesPitch(true), mPreservesPitch(AbstractThread::MainThread(), true, "MediaDecoder::mPreservesPitch (Canonical)"),
mDuration(-1), mDuration(-1),
mMediaSeekable(true), mMediaSeekable(true),
mSameOriginMedia(false), mSameOriginMedia(false),
@ -750,21 +747,23 @@ void MediaDecoder::SetStateMachineParameters()
{ {
ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mDecoderStateMachine->SetDuration(mDuration); mDecoderStateMachine->SetDuration(mDuration);
mDecoderStateMachine->SetVolume(mInitialVolume);
if (GetDecodedStream()) { if (GetDecodedStream()) {
mDecoderStateMachine->SetAudioCaptured(); mDecoderStateMachine->DispatchAudioCaptured();
} }
SetPlaybackRate(mInitialPlaybackRate);
mDecoderStateMachine->SetPreservesPitch(mInitialPreservesPitch);
if (mMinimizePreroll) { if (mMinimizePreroll) {
mDecoderStateMachine->SetMinimizePrerollUntilPlaybackStarts(); mDecoderStateMachine->DispatchMinimizePrerollUntilPlaybackStarts();
} }
} }
void MediaDecoder::SetMinimizePrerollUntilPlaybackStarts() void MediaDecoder::SetMinimizePrerollUntilPlaybackStarts()
{ {
DECODER_LOG("SetMinimizePrerollUntilPlaybackStarts()");
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
mMinimizePreroll = true; 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() nsresult MediaDecoder::ScheduleStateMachineThread()
@ -1550,11 +1549,10 @@ bool MediaDecoder::OnStateMachineTaskQueue() const
void MediaDecoder::SetPlaybackRate(double aPlaybackRate) void MediaDecoder::SetPlaybackRate(double aPlaybackRate)
{ {
if (aPlaybackRate == 0.0) { mPlaybackRate = aPlaybackRate;
if (mPlaybackRate == 0.0) {
mPausedForPlaybackRateNull = true; mPausedForPlaybackRateNull = true;
mInitialPlaybackRate = aPlaybackRate;
Pause(); Pause();
return;
} else if (mPausedForPlaybackRateNull) { } else if (mPausedForPlaybackRateNull) {
// Play() uses mPausedForPlaybackRateNull value, so must reset it first // Play() uses mPausedForPlaybackRateNull value, so must reset it first
mPausedForPlaybackRateNull = false; mPausedForPlaybackRateNull = false;
@ -1564,21 +1562,11 @@ void MediaDecoder::SetPlaybackRate(double aPlaybackRate)
Play(); Play();
} }
} }
if (mDecoderStateMachine) {
mDecoderStateMachine->SetPlaybackRate(aPlaybackRate);
} else {
mInitialPlaybackRate = aPlaybackRate;
}
} }
void MediaDecoder::SetPreservesPitch(bool aPreservesPitch) void MediaDecoder::SetPreservesPitch(bool aPreservesPitch)
{ {
if (mDecoderStateMachine) { mPreservesPitch = aPreservesPitch;
mDecoderStateMachine->SetPreservesPitch(aPreservesPitch);
} else {
mInitialPreservesPitch = aPreservesPitch;
}
} }
bool MediaDecoder::OnDecodeTaskQueue() const { bool MediaDecoder::OnDecodeTaskQueue() const {

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

@ -1079,14 +1079,22 @@ protected:
// It is read and written from the main thread only. // It is read and written from the main thread only.
double mCurrentTime; double mCurrentTime;
// Volume that playback should start at. 0.0 = muted. 1.0 = full // Volume of playback. 0.0 = muted. 1.0 = full volume.
// volume. Readable/Writeable from the main thread. Canonical<double> mVolume;
double mInitialVolume; public:
AbstractCanonical<double>* CanonicalVolume() { return &mVolume; }
protected:
// PlaybackRate and pitch preservation status we should start at. // PlaybackRate and pitch preservation status we should start at.
// Readable/Writeable from the main thread. Canonical<double> mPlaybackRate;
double mInitialPlaybackRate; public:
bool mInitialPreservesPitch; 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. // Duration of the media resource. Set to -1 if unknown.
// Set when the metadata is loaded. Accessed on the main thread // Set when the metadata is loaded. Accessed on the main thread

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

@ -226,9 +226,10 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mDecodedAudioEndTime(-1), mDecodedAudioEndTime(-1),
mVideoFrameEndTime(-1), mVideoFrameEndTime(-1),
mDecodedVideoEndTime(-1), mDecodedVideoEndTime(-1),
mVolume(1.0), mVolume(mTaskQueue, 1.0, "MediaDecoderStateMachine::mVolume (Mirror)"),
mPlaybackRate(1.0), mPlaybackRate(1.0),
mPreservesPitch(true), mLogicalPlaybackRate(mTaskQueue, 1.0, "MediaDecoderStateMachine::mLogicalPlaybackRate (Mirror)"),
mPreservesPitch(mTaskQueue, true, "MediaDecoderStateMachine::mPreservesPitch (Mirror)"),
mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS), mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS),
mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS), mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS),
mQuickBufferingLowDataThresholdUsecs(detail::QUICK_BUFFERING_LOW_DATA_USECS), mQuickBufferingLowDataThresholdUsecs(detail::QUICK_BUFFERING_LOW_DATA_USECS),
@ -307,13 +308,21 @@ MediaDecoderStateMachine::InitializationTask()
// Connect mirrors. // Connect mirrors.
mPlayState.Connect(mDecoder->CanonicalPlayState()); mPlayState.Connect(mDecoder->CanonicalPlayState());
mNextPlayState.Connect(mDecoder->CanonicalNextPlayState()); mNextPlayState.Connect(mDecoder->CanonicalNextPlayState());
mVolume.Connect(mDecoder->CanonicalVolume());
mLogicalPlaybackRate.Connect(mDecoder->CanonicalPlaybackRate());
mPreservesPitch.Connect(mDecoder->CanonicalPreservesPitch());
// Initialize watchers. // Initialize watchers.
mWatchManager.Watch(mState, &MediaDecoderStateMachine::UpdateNextFrameStatus); mWatchManager.Watch(mState, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mAudioCompleted, &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() { bool MediaDecoderStateMachine::HasFutureAudio() {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
NS_ASSERTION(HasAudio(), "Should only call HasFutureAudio() when we have audio"); NS_ASSERTION(HasAudio(), "Should only call HasFutureAudio() when we have audio");
// We've got audio ready to play if: // We've got audio ready to play if:
@ -328,6 +337,7 @@ bool MediaDecoderStateMachine::HasFutureAudio() {
} }
bool MediaDecoderStateMachine::HaveNextFrameData() { bool MediaDecoderStateMachine::HaveNextFrameData() {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
return (!HasAudio() || HasFutureAudio()) && return (!HasAudio() || HasFutureAudio()) &&
(!HasVideo() || VideoQueue().GetSize() > 0); (!HasVideo() || VideoQueue().GetSize() > 0);
@ -567,6 +577,7 @@ void MediaDecoderStateMachine::SendStreamData()
MediaDecoderStateMachine::WakeDecoderRunnable* MediaDecoderStateMachine::WakeDecoderRunnable*
MediaDecoderStateMachine::GetWakeDecoderRunnable() MediaDecoderStateMachine::GetWakeDecoderRunnable()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
if (!mPendingWakeDecoder.get()) { if (!mPendingWakeDecoder.get()) {
@ -577,6 +588,7 @@ MediaDecoderStateMachine::GetWakeDecoderRunnable()
bool MediaDecoderStateMachine::HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs) bool MediaDecoderStateMachine::HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs)
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
if (AudioQueue().GetSize() == 0 || if (AudioQueue().GetSize() == 0 ||
@ -604,6 +616,7 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs)
bool MediaDecoderStateMachine::HaveEnoughDecodedVideo() bool MediaDecoderStateMachine::HaveEnoughDecodedVideo()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
if (static_cast<uint32_t>(VideoQueue().GetSize()) < GetAmpleVideoFrames() * mPlaybackRate) { if (static_cast<uint32_t>(VideoQueue().GetSize()) < GetAmpleVideoFrames() * mPlaybackRate) {
@ -628,6 +641,7 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedVideo()
bool bool
MediaDecoderStateMachine::NeedToDecodeVideo() MediaDecoderStateMachine::NeedToDecodeVideo()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
return IsVideoDecoding() && return IsVideoDecoding() &&
((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) || ((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
@ -639,6 +653,7 @@ MediaDecoderStateMachine::NeedToDecodeVideo()
bool bool
MediaDecoderStateMachine::NeedToSkipToNextKeyframe() MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
if (mState == DECODER_STATE_DECODING_FIRSTFRAME) { if (mState == DECODER_STATE_DECODING_FIRSTFRAME) {
return false; return false;
@ -688,6 +703,7 @@ MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
bool bool
MediaDecoderStateMachine::NeedToDecodeAudio() MediaDecoderStateMachine::NeedToDecodeAudio()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
SAMPLE_LOG("NeedToDecodeAudio() isDec=%d decToTar=%d minPrl=%d seek=%d enufAud=%d", SAMPLE_LOG("NeedToDecodeAudio() isDec=%d decToTar=%d minPrl=%d seek=%d enufAud=%d",
IsAudioDecoding(), mDecodeToSeekTarget, mMinimizePreroll, IsAudioDecoding(), mDecodeToSeekTarget, mMinimizePreroll,
@ -706,6 +722,7 @@ MediaDecoderStateMachine::NeedToDecodeAudio()
bool bool
MediaDecoderStateMachine::IsAudioSeekComplete() MediaDecoderStateMachine::IsAudioSeekComplete()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
SAMPLE_LOG("IsAudioSeekComplete() curTarVal=%d mAudDis=%d aqFin=%d aqSz=%d", SAMPLE_LOG("IsAudioSeekComplete() curTarVal=%d mAudDis=%d aqFin=%d aqSz=%d",
mCurrentSeek.Exists(), mDropAudioUntilNextDiscontinuity, AudioQueue().IsFinished(), AudioQueue().GetSize()); mCurrentSeek.Exists(), mDropAudioUntilNextDiscontinuity, AudioQueue().IsFinished(), AudioQueue().GetSize());
@ -719,6 +736,7 @@ MediaDecoderStateMachine::IsAudioSeekComplete()
bool bool
MediaDecoderStateMachine::IsVideoSeekComplete() MediaDecoderStateMachine::IsVideoSeekComplete()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
SAMPLE_LOG("IsVideoSeekComplete() curTarVal=%d mVidDis=%d vqFin=%d vqSz=%d", SAMPLE_LOG("IsVideoSeekComplete() curTarVal=%d mVidDis=%d vqFin=%d vqSz=%d",
mCurrentSeek.Exists(), mDropVideoUntilNextDiscontinuity, VideoQueue().IsFinished(), VideoQueue().GetSize()); mCurrentSeek.Exists(), mDropVideoUntilNextDiscontinuity, VideoQueue().IsFinished(), VideoQueue().GetSize());
@ -1143,6 +1161,7 @@ MediaDecoderStateMachine::CheckIfSeekComplete()
bool bool
MediaDecoderStateMachine::IsAudioDecoding() MediaDecoderStateMachine::IsAudioDecoding()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
return HasAudio() && !AudioQueue().IsFinished(); return HasAudio() && !AudioQueue().IsFinished();
} }
@ -1150,6 +1169,7 @@ MediaDecoderStateMachine::IsAudioDecoding()
bool bool
MediaDecoderStateMachine::IsVideoDecoding() MediaDecoderStateMachine::IsVideoDecoding()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
return HasVideo() && !VideoQueue().IsFinished(); return HasVideo() && !VideoQueue().IsFinished();
} }
@ -1343,27 +1363,15 @@ void MediaDecoderStateMachine::SetState(State aState)
mSentPlaybackEndedEvent = false; 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()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mVolume = volume;
if (mAudioSink) { if (mAudioSink) {
mAudioSink->SetVolume(mVolume); 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 double MediaDecoderStateMachine::GetCurrentTime() const
{ {
return static_cast<double>(mCurrentFrameTime) / static_cast<double>(USECS_PER_S); return static_cast<double>(mCurrentFrameTime) / static_cast<double>(USECS_PER_S);
@ -1753,6 +1761,7 @@ void MediaDecoderStateMachine::StopAudioThread()
nsresult nsresult
MediaDecoderStateMachine::EnqueueDecodeFirstFrameTask() MediaDecoderStateMachine::EnqueueDecodeFirstFrameTask()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME); MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME);
@ -2041,6 +2050,7 @@ MediaDecoderStateMachine::StartAudioThread()
int64_t MediaDecoderStateMachine::AudioDecodedUsecs() int64_t MediaDecoderStateMachine::AudioDecodedUsecs()
{ {
MOZ_ASSERT(OnTaskQueue());
NS_ASSERTION(HasAudio(), NS_ASSERTION(HasAudio(),
"Should only call AudioDecodedUsecs() when we have audio"); "Should only call AudioDecodedUsecs() when we have audio");
// The amount of audio we have decoded is the amount of audio data we've // 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) bool MediaDecoderStateMachine::HasLowDecodedData(int64_t aAudioUsecs)
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
MOZ_ASSERT(mReader->UseBufferingHeuristics()); MOZ_ASSERT(mReader->UseBufferingHeuristics());
// We consider ourselves low on decoded data if we're low on audio, // 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() bool MediaDecoderStateMachine::OutOfDecodedAudio()
{ {
MOZ_ASSERT(OnTaskQueue());
return IsAudioDecoding() && !AudioQueue().IsFinished() && return IsAudioDecoding() && !AudioQueue().IsFinished() &&
AudioQueue().GetSize() == 0 && AudioQueue().GetSize() == 0 &&
(!mAudioSink || !mAudioSink->HasUnplayedFrames()); (!mAudioSink || !mAudioSink->HasUnplayedFrames());
@ -2078,11 +2090,13 @@ bool MediaDecoderStateMachine::OutOfDecodedAudio()
bool MediaDecoderStateMachine::HasLowUndecodedData() bool MediaDecoderStateMachine::HasLowUndecodedData()
{ {
MOZ_ASSERT(OnTaskQueue());
return HasLowUndecodedData(mLowDataThresholdUsecs); return HasLowUndecodedData(mLowDataThresholdUsecs);
} }
bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs) bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs)
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
NS_ASSERTION(mState > DECODER_STATE_DECODING_FIRSTFRAME, NS_ASSERTION(mState > DECODER_STATE_DECODING_FIRSTFRAME,
"Must have loaded first frame for GetBuffered() to work"); "Must have loaded first frame for GetBuffered() to work");
@ -2146,9 +2160,9 @@ MediaDecoderStateMachine::DecodeError()
void void
MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata) MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
{ {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(mState == DECODER_STATE_DECODING_METADATA); MOZ_ASSERT(mState == DECODER_STATE_DECODING_METADATA);
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mMetadataRequest.Complete(); mMetadataRequest.Complete();
mDecoder->SetMediaSeekable(mReader->IsMediaSeekable()); mDecoder->SetMediaSeekable(mReader->IsMediaSeekable());
@ -2186,9 +2200,9 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
void void
MediaDecoderStateMachine::OnMetadataNotRead(ReadMetadataFailureReason aReason) MediaDecoderStateMachine::OnMetadataNotRead(ReadMetadataFailureReason aReason)
{ {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(mState == DECODER_STATE_DECODING_METADATA); MOZ_ASSERT(mState == DECODER_STATE_DECODING_METADATA);
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mMetadataRequest.Complete(); mMetadataRequest.Complete();
if (aReason == ReadMetadataFailureReason::WAITING_FOR_RESOURCES) { if (aReason == ReadMetadataFailureReason::WAITING_FOR_RESOURCES) {
@ -2299,8 +2313,8 @@ MediaDecoderStateMachine::DecodeFirstFrame()
nsresult nsresult
MediaDecoderStateMachine::FinishDecodeFirstFrame() MediaDecoderStateMachine::FinishDecodeFirstFrame()
{ {
AssertCurrentThreadInMonitor();
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
DECODER_LOG("FinishDecodeFirstFrame"); DECODER_LOG("FinishDecodeFirstFrame");
if (IsShutdown()) { if (IsShutdown()) {
@ -2375,8 +2389,8 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
void void
MediaDecoderStateMachine::OnSeekCompleted(int64_t aTime) MediaDecoderStateMachine::OnSeekCompleted(int64_t aTime)
{ {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mSeekRequest.Complete(); mSeekRequest.Complete();
// We must decode the first samples of active streams, so we can determine // We must decode the first samples of active streams, so we can determine
@ -2389,8 +2403,8 @@ MediaDecoderStateMachine::OnSeekCompleted(int64_t aTime)
void void
MediaDecoderStateMachine::OnSeekFailed(nsresult aResult) MediaDecoderStateMachine::OnSeekFailed(nsresult aResult)
{ {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mSeekRequest.Complete(); mSeekRequest.Complete();
MOZ_ASSERT(NS_FAILED(aResult), "Cancels should also disconnect mSeekRequest"); MOZ_ASSERT(NS_FAILED(aResult), "Cancels should also disconnect mSeekRequest");
DecodeError(); DecodeError();
@ -2527,6 +2541,9 @@ MediaDecoderStateMachine::FinishShutdown()
// Disconnect canonicals and mirrors before shutting down our task queue. // Disconnect canonicals and mirrors before shutting down our task queue.
mPlayState.DisconnectIfConnected(); mPlayState.DisconnectIfConnected();
mNextPlayState.DisconnectIfConnected(); mNextPlayState.DisconnectIfConnected();
mVolume.DisconnectIfConnected();
mLogicalPlaybackRate.DisconnectIfConnected();
mPreservesPitch.DisconnectIfConnected();
mNextFrameStatus.DisconnectAll(); mNextFrameStatus.DisconnectAll();
// Shut down the watch manager before shutting down our task queue. // Shut down the watch manager before shutting down our task queue.
@ -2838,6 +2855,7 @@ void MediaDecoderStateMachine::RenderVideoFrame(VideoData* aData,
void MediaDecoderStateMachine::ResyncAudioClock() void MediaDecoderStateMachine::ResyncAudioClock()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
if (IsPlaying()) { if (IsPlaying()) {
SetPlayStartTime(TimeStamp::Now()); SetPlayStartTime(TimeStamp::Now());
@ -2848,6 +2866,7 @@ void MediaDecoderStateMachine::ResyncAudioClock()
int64_t int64_t
MediaDecoderStateMachine::GetAudioClock() const MediaDecoderStateMachine::GetAudioClock() const
{ {
MOZ_ASSERT(OnTaskQueue());
// We must hold the decoder monitor while using the audio stream off the // 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 // audio sink to ensure that it doesn't get destroyed on the audio sink
// while we're using it. // while we're using it.
@ -2874,6 +2893,7 @@ int64_t MediaDecoderStateMachine::GetVideoStreamPosition() const
int64_t MediaDecoderStateMachine::GetClock() const int64_t MediaDecoderStateMachine::GetClock() const
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
// Determine the clock time. If we've got audio, and we've not reached // Determine the clock time. If we've got audio, and we've not reached
@ -3053,6 +3073,7 @@ void MediaDecoderStateMachine::AdvanceFrame()
nsresult nsresult
MediaDecoderStateMachine::DropVideoUpToSeekTarget(VideoData* aSample) MediaDecoderStateMachine::DropVideoUpToSeekTarget(VideoData* aSample)
{ {
MOZ_ASSERT(OnTaskQueue());
nsRefPtr<VideoData> video(aSample); nsRefPtr<VideoData> video(aSample);
MOZ_ASSERT(video); MOZ_ASSERT(video);
DECODER_LOG("DropVideoUpToSeekTarget() frame [%lld, %lld] dup=%d", DECODER_LOG("DropVideoUpToSeekTarget() frame [%lld, %lld] dup=%d",
@ -3104,6 +3125,7 @@ MediaDecoderStateMachine::DropVideoUpToSeekTarget(VideoData* aSample)
nsresult nsresult
MediaDecoderStateMachine::DropAudioUpToSeekTarget(AudioData* aSample) MediaDecoderStateMachine::DropAudioUpToSeekTarget(AudioData* aSample)
{ {
MOZ_ASSERT(OnTaskQueue());
nsRefPtr<AudioData> audio(aSample); nsRefPtr<AudioData> audio(aSample);
MOZ_ASSERT(audio && MOZ_ASSERT(audio &&
mCurrentSeek.Exists() && mCurrentSeek.Exists() &&
@ -3199,7 +3221,8 @@ void MediaDecoderStateMachine::SetStartTime(int64_t aStartTimeUsecs)
DECODER_LOG("Set media start time to %lld", mStartTime); DECODER_LOG("Set media start time to %lld", mStartTime);
} }
void MediaDecoderStateMachine::UpdateNextFrameStatus() { void MediaDecoderStateMachine::UpdateNextFrameStatus()
{
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
@ -3228,6 +3251,7 @@ void MediaDecoderStateMachine::UpdateNextFrameStatus() {
bool MediaDecoderStateMachine::JustExitedQuickBuffering() bool MediaDecoderStateMachine::JustExitedQuickBuffering()
{ {
MOZ_ASSERT(OnTaskQueue());
return !mDecodeStartTime.IsNull() && return !mDecodeStartTime.IsNull() &&
mQuickBuffering && mQuickBuffering &&
(TimeStamp::Now() - mDecodeStartTime) < TimeDuration::FromMicroseconds(QUICK_BUFFER_THRESHOLD_USECS); (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()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
DispatchAudioDecodeTaskIfNeeded(); DispatchAudioDecodeTaskIfNeeded();
DispatchVideoDecodeTaskIfNeeded(); DispatchVideoDecodeTaskIfNeeded();
@ -3353,14 +3379,14 @@ bool MediaDecoderStateMachine::IsStateMachineScheduled() const
return mDispatchedStateMachine || mDelayedScheduler.IsScheduled(); return mDispatchedStateMachine || mDelayedScheduler.IsScheduled();
} }
void MediaDecoderStateMachine::SetPlaybackRate(double aPlaybackRate) void
MediaDecoderStateMachine::LogicalPlaybackRateChanged()
{ {
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); MOZ_ASSERT(OnTaskQueue());
NS_ASSERTION(aPlaybackRate != 0,
"PlaybackRate == 0 should be handled before this function.");
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mPlaybackRate == aPlaybackRate) { if (mLogicalPlaybackRate == 0) {
// This case is handled in MediaDecoder by pausing playback.
return; return;
} }
@ -3374,31 +3400,22 @@ void MediaDecoderStateMachine::SetPlaybackRate(double aPlaybackRate)
SetPlayStartTime(TimeStamp::Now()); SetPlayStartTime(TimeStamp::Now());
} }
mPlaybackRate = aPlaybackRate; mPlaybackRate = mLogicalPlaybackRate;
if (mAudioSink) { if (mAudioSink) {
mAudioSink->SetPlaybackRate(mPlaybackRate); 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()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mPreservesPitch = aPreservesPitch;
if (mAudioSink) { if (mAudioSink) {
mAudioSink->SetPreservesPitch(mPreservesPitch); mAudioSink->SetPreservesPitch(mPreservesPitch);
} }
} }
void
MediaDecoderStateMachine::SetMinimizePrerollUntilPlaybackStarts()
{
AssertCurrentThreadInMonitor();
DECODER_LOG("SetMinimizePrerollUntilPlaybackStarts()");
mMinimizePreroll = true;
}
bool MediaDecoderStateMachine::IsShutdown() bool MediaDecoderStateMachine::IsShutdown()
{ {
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
@ -3471,6 +3488,7 @@ void MediaDecoderStateMachine::OnAudioSinkError()
uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
return (mReader->IsAsync() && mReader->VideoIsHardwareAccelerated()) return (mReader->IsAsync() && mReader->VideoIsHardwareAccelerated())
? std::max<uint32_t>(sVideoQueueHWAccelSize, MIN_VIDEO_QUEUE_SIZE) ? std::max<uint32_t>(sVideoQueueHWAccelSize, MIN_VIDEO_QUEUE_SIZE)

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

@ -152,10 +152,20 @@ public:
return mState; return mState;
} }
// Set the audio volume. The decoder monitor must be obtained before void DispatchAudioCaptured()
// calling this. {
void SetVolume(double aVolume); nsRefPtr<MediaDecoderStateMachine> self = this;
void SetAudioCaptured(); 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. // Check if the decoder needs to become dormant state.
bool IsDormantNeeded(); bool IsDormantNeeded();
@ -309,9 +319,6 @@ public:
return mReader->GetBuffered(aBuffered); return mReader->GetBuffered(aBuffered);
} }
void SetPlaybackRate(double aPlaybackRate);
void SetPreservesPitch(bool aPreservesPitch);
size_t SizeOfVideoQueue() { size_t SizeOfVideoQueue() {
if (mReader) { if (mReader) {
return mReader->SizeOfVideoQueueInBytes(); return mReader->SizeOfVideoQueueInBytes();
@ -392,7 +399,21 @@ public:
// the state machine is free to return to prerolling normally. Note // the state machine is free to return to prerolling normally. Note
// "prerolling" in this context refers to when we decode and buffer decoded // "prerolling" in this context refers to when we decode and buffer decoded
// samples in advance of when they're needed for playback. // 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 OnAudioDecoded(AudioData* aSample);
void OnVideoDecoded(VideoData* aSample); void OnVideoDecoded(VideoData* aSample);
@ -447,6 +468,9 @@ protected:
already_AddRefed<AudioData> PopAudio(); already_AddRefed<AudioData> PopAudio();
already_AddRefed<VideoData> PopVideo(); already_AddRefed<VideoData> PopVideo();
void VolumeChanged();
void LogicalPlaybackRateChanged();
void PreservesPitchChanged();
class WakeDecoderRunnable : public nsRunnable { class WakeDecoderRunnable : public nsRunnable {
public: public:
@ -1009,17 +1033,19 @@ protected:
// on decoded video data. // on decoded video data.
int64_t mDecodedVideoEndTime; int64_t mDecodedVideoEndTime;
// Volume of playback. 0.0 = muted. 1.0 = full volume. Read/Written // Volume of playback. 0.0 = muted. 1.0 = full volume.
// from the state machine and main threads. Synchronised via decoder Mirror<double> mVolume;
// monitor.
double mVolume;
// Playback rate. 1.0 : normal speed, 0.5 : two times slower. Synchronized via // Playback rate. 1.0 : normal speed, 0.5 : two times slower.
// decoder monitor. //
// 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; double mPlaybackRate;
Mirror<double> mLogicalPlaybackRate;
// Pitch preservation for the playback rate. Synchronized via decoder monitor. // Pitch preservation for the playback rate.
bool mPreservesPitch; Mirror<bool> mPreservesPitch;
// Time at which we started decoding. Synchronised via decoder monitor. // Time at which we started decoding. Synchronised via decoder monitor.
TimeStamp mDecodeStartTime; TimeStamp mDecodeStartTime;
@ -1080,12 +1106,14 @@ protected:
bool DonePrerollingAudio() bool DonePrerollingAudio()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
return !IsAudioDecoding() || GetDecodedAudioDuration() >= AudioPrerollUsecs() * mPlaybackRate; return !IsAudioDecoding() || GetDecodedAudioDuration() >= AudioPrerollUsecs() * mPlaybackRate;
} }
bool DonePrerollingVideo() bool DonePrerollingVideo()
{ {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
return !IsVideoDecoding() || return !IsVideoDecoding() ||
static_cast<uint32_t>(VideoQueue().GetSize()) >= VideoPrerollFrames() * mPlaybackRate; 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-about-to-go-offline", true);
Services.obs.addObserver(this, "network:offline-status-changed", true); Services.obs.addObserver(this, "network:offline-status-changed", true);
Services.obs.addObserver(this, "gmp-plugin-crash", 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 = { GlobalPCList.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsIMessageListener,
Ci.nsISupportsWeakReference, Ci.nsISupportsWeakReference,
Ci.IPeerConnectionManager]), Ci.IPeerConnectionManager]),
classID: PC_MANAGER_CID, classID: PC_MANAGER_CID,
@ -93,6 +98,31 @@ GlobalPCList.prototype = {
return this._list[winID] ? true : false; 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) { observe: function(subject, topic, data) {
let cleanupPcRef = function(pcref) { let cleanupPcRef = function(pcref) {
let pc = pcref.get(); 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") { if (topic == "inner-window-destroyed") {
let winID = subject.QueryInterface(Ci.nsISupportsPRUint64).data; let winID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
cleanupWinId(this._list, winID); cleanupWinId(this._list, winID);
@ -162,17 +181,11 @@ GlobalPCList.prototype = {
} }
} }
} else if (topic == "gmp-plugin-crash") { } else if (topic == "gmp-plugin-crash") {
// a plugin crashed; if it's associated with any of our PCs, fire an if (subject instanceof Ci.nsIWritablePropertyBag2) {
// event to the DOM window let pluginID = subject.getPropertyAsUint32("pluginID");
let sep = data.indexOf(' '); let pluginName = subject.getPropertyAsAString("pluginName");
let pluginId = data.slice(0, sep); let data = { pluginID, pluginName };
let rest = data.slice(sep+1); this.handleGMPCrash(data);
// 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);
} }
} }
}, },

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

@ -377,22 +377,23 @@ MediaKeys::Init(ErrorResult& aRv)
class CrashHandler : public gmp::GeckoMediaPluginService::PluginCrashCallback class CrashHandler : public gmp::GeckoMediaPluginService::PluginCrashCallback
{ {
public: public:
CrashHandler(const nsACString& aPluginId, CrashHandler(const uint32_t aPluginId,
nsPIDOMWindow* aParentWindow, nsPIDOMWindow* aParentWindow,
nsIDocument* aDocument) nsIDocument* aDocument)
: gmp::GeckoMediaPluginService::PluginCrashCallback(aPluginId) : gmp::GeckoMediaPluginService::PluginCrashCallback(aPluginId)
, mPluginId(aPluginId)
, mParentWindowWeakPtr(do_GetWeakReference(aParentWindow)) , mParentWindowWeakPtr(do_GetWeakReference(aParentWindow))
, mDocumentWeakPtr(do_GetWeakReference(aDocument)) , mDocumentWeakPtr(do_GetWeakReference(aDocument))
{ {
} }
virtual void Run(const nsACString& aPluginName, const nsAString& aPluginDumpId) override virtual void Run(const nsACString& aPluginName) override
{ {
PluginCrashedEventInit init; PluginCrashedEventInit init;
init.mPluginID = mPluginId;
init.mBubbles = true; init.mBubbles = true;
init.mCancelable = true; init.mCancelable = true;
init.mGmpPlugin = true; init.mGmpPlugin = true;
init.mPluginDumpID = aPluginDumpId;
CopyUTF8toUTF16(aPluginName, init.mPluginName); CopyUTF8toUTF16(aPluginName, init.mPluginName);
init.mSubmittedCrashReport = false; init.mSubmittedCrashReport = false;
@ -445,12 +446,13 @@ private:
return true; return true;
} }
uint32_t mPluginId;
nsWeakPtr mParentWindowWeakPtr; nsWeakPtr mParentWindowWeakPtr;
nsWeakPtr mDocumentWeakPtr; nsWeakPtr mDocumentWeakPtr;
}; };
void 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)); nsRefPtr<Promise> promise(RetrievePromise(aId));
if (!promise) { if (!promise) {
@ -468,7 +470,7 @@ MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const nsACStri
mKeySystem, mKeySystem,
MediaKeySystemStatus::Cdm_created); MediaKeySystemStatus::Cdm_created);
if (!aPluginId.IsEmpty()) { if (aPluginId) {
// Prepare plugin crash reporter. // Prepare plugin crash reporter.
nsRefPtr<gmp::GeckoMediaPluginService> service = nsRefPtr<gmp::GeckoMediaPluginService> service =
gmp::GeckoMediaPluginService::GetGeckoMediaPluginService(); gmp::GeckoMediaPluginService::GetGeckoMediaPluginService();
@ -483,8 +485,8 @@ MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const nsACStri
return; return;
} }
service->AddPluginCrashCallback(new CrashHandler(aPluginId, mParent, doc)); service->AddPluginCrashCallback(new CrashHandler(aPluginId, mParent, doc));
EME_LOG("MediaKeys[%p]::OnCDMCreated() registered crash handler for pluginId '%s'", EME_LOG("MediaKeys[%p]::OnCDMCreated() registered crash handler for pluginId '%i'",
this, aPluginId.Data()); this, aPluginId);
} }
} }

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

@ -81,7 +81,7 @@ public:
// Called once a Init() operation succeeds. // Called once a Init() operation succeeds.
void OnCDMCreated(PromiseId aId, 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 // Called once the CDM generates a sessionId while servicing a
// MediaKeySession.generateRequest() or MediaKeySession.load() call, // MediaKeySession.generateRequest() or MediaKeySession.load() call,

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

@ -51,11 +51,11 @@ public:
{ {
return mDisplayName; return mDisplayName;
} }
void SetPluginId(const nsCString& aPluginId) void SetPluginId(const uint32_t aPluginId)
{ {
mPluginId = aPluginId; mPluginId = aPluginId;
} }
const nsCString& GetPluginId() const uint32_t GetPluginId()
{ {
return mPluginId; return mPluginId;
} }
@ -92,7 +92,7 @@ private:
nsCOMPtr<nsIThread> mGMPThread; nsCOMPtr<nsIThread> mGMPThread;
nsRefPtr<GMPParent> mParent; nsRefPtr<GMPParent> mParent;
nsCString mDisplayName; nsCString mDisplayName;
nsCString mPluginId; uint32_t mPluginId;
}; };
} // namespace gmp } // namespace gmp

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

@ -29,7 +29,7 @@ GMPDecryptorParent::~GMPDecryptorParent()
{ {
} }
const nsACString& const uint32_t
GMPDecryptorParent::GetPluginId() const GMPDecryptorParent::GetPluginId() const
{ {
return mPluginId; return mPluginId;

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

@ -29,7 +29,7 @@ public:
// GMPDecryptorProxy // GMPDecryptorProxy
virtual const nsACString& GetPluginId() const override; virtual const uint32_t GetPluginId() const override;
virtual nsresult Init(GMPDecryptorProxyCallback* aCallback) override; virtual nsresult Init(GMPDecryptorProxyCallback* aCallback) override;
@ -113,7 +113,7 @@ private:
bool mShuttingDown; bool mShuttingDown;
bool mActorDestroyed; bool mActorDestroyed;
nsRefPtr<GMPContentParent> mPlugin; nsRefPtr<GMPContentParent> mPlugin;
nsCString mPluginId; uint32_t mPluginId;
GMPDecryptorProxyCallback* mCallback; GMPDecryptorProxyCallback* mCallback;
#ifdef DEBUG #ifdef DEBUG
nsIThread* const mGMPThread; nsIThread* const mGMPThread;

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

@ -59,7 +59,7 @@ class GMPDecryptorProxy {
public: public:
~GMPDecryptorProxy() {} ~GMPDecryptorProxy() {}
virtual const nsACString& GetPluginId() const = 0; virtual const uint32_t GetPluginId() const = 0;
virtual nsresult Init(GMPDecryptorProxyCallback* aCallback) = 0; virtual nsresult Init(GMPDecryptorProxyCallback* aCallback) = 0;

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

@ -13,7 +13,9 @@
#include "nsCharSeparatedTokenizer.h" #include "nsCharSeparatedTokenizer.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsIRunnable.h" #include "nsIRunnable.h"
#include "nsIWritablePropertyBag2.h"
#include "mozIGeckoMediaPluginService.h" #include "mozIGeckoMediaPluginService.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/SyncRunnable.h" #include "mozilla/SyncRunnable.h"
#include "mozilla/unused.h" #include "mozilla/unused.h"
#include "nsIObserverService.h" #include "nsIObserverService.h"
@ -25,6 +27,7 @@
#include "mozilla/dom/CrashReporterParent.h" #include "mozilla/dom/CrashReporterParent.h"
using mozilla::dom::CrashReporterParent; using mozilla::dom::CrashReporterParent;
using mozilla::ipc::GeckoChildProcessHost;
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
using CrashReporter::AnnotationTable; using CrashReporter::AnnotationTable;
@ -64,9 +67,7 @@ GMPParent::GMPParent()
#endif #endif
{ {
LOGD("GMPParent ctor"); LOGD("GMPParent ctor");
// Use the parent address to identify it. mPluginId = GeckoChildProcessHost::GetUniqueID();
// We could use any unique-to-the-parent value.
mPluginId.AppendInt(reinterpret_cast<uint64_t>(this));
} }
GMPParent::~GMPParent() GMPParent::~GMPParent()
@ -499,23 +500,22 @@ GMPParent::GetCrashID(nsString& aResult)
} }
static void 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(); nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) { nsCOMPtr<nsIWritablePropertyBag2> propbag =
nsString id; do_CreateInstance("@mozilla.org/hash-property-bag;1");
AppendUTF8toUTF16(aPluginId, id); if (obs && propbag) {
id.Append(NS_LITERAL_STRING(" ")); propbag->SetPropertyAsUint32(NS_LITERAL_STRING("pluginID"), aPluginID);
AppendUTF8toUTF16(aPluginName, id); propbag->SetPropertyAsACString(NS_LITERAL_STRING("pluginName"), aPluginName);
id.Append(NS_LITERAL_STRING(" ")); propbag->SetPropertyAsAString(NS_LITERAL_STRING("pluginDumpID"), aPluginDumpID);
id.Append(aPluginDumpId); obs->NotifyObservers(propbag, "gmp-plugin-crash", nullptr);
obs->NotifyObservers(nullptr, "gmp-plugin-crash", id.Data());
} }
nsRefPtr<gmp::GeckoMediaPluginService> service = nsRefPtr<gmp::GeckoMediaPluginService> service =
gmp::GeckoMediaPluginService::GetGeckoMediaPluginService(); gmp::GeckoMediaPluginService::GetGeckoMediaPluginService();
if (service) { if (service) {
service->RunPluginCrashCallbacks(aPluginId, aPluginName, aPluginDumpId); service->RunPluginCrashCallbacks(aPluginID, aPluginName);
} }
} }
#endif #endif
@ -820,7 +820,7 @@ GMPParent::GetVersion() const
return mVersion; return mVersion;
} }
const nsCString& const uint32_t
GMPParent::GetPluginId() const GMPParent::GetPluginId() const
{ {
return mPluginId; return mPluginId;

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

@ -123,7 +123,7 @@ public:
const nsCString& GetDisplayName() const; const nsCString& GetDisplayName() const;
const nsCString& GetVersion() 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. // Returns true if a plugin can be or is being used across multiple NodeIds.
bool CanBeSharedCrossNodeIds() const; bool CanBeSharedCrossNodeIds() const;
@ -192,7 +192,7 @@ private:
nsCString mDisplayName; // name of plugin displayed to users nsCString mDisplayName; // name of plugin displayed to users
nsCString mDescription; // description of plugin for display to users nsCString mDescription; // description of plugin for display to users
nsCString mVersion; nsCString mVersion;
nsCString mPluginId; uint32_t mPluginId;
nsTArray<nsAutoPtr<GMPCapability>> mCapabilities; nsTArray<nsAutoPtr<GMPCapability>> mCapabilities;
GMPProcessParent* mProcess; GMPProcessParent* mProcess;
bool mDeleteProcessOnlyOnUnload; bool mDeleteProcessOnlyOnUnload;

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

@ -165,9 +165,8 @@ GeckoMediaPluginService::RemoveObsoletePluginCrashCallbacks()
for (size_t i = mPluginCrashCallbacks.Length(); i != 0; --i) { for (size_t i = mPluginCrashCallbacks.Length(); i != 0; --i) {
nsRefPtr<PluginCrashCallback>& callback = mPluginCrashCallbacks[i - 1]; nsRefPtr<PluginCrashCallback>& callback = mPluginCrashCallbacks[i - 1];
if (!callback->IsStillValid()) { if (!callback->IsStillValid()) {
LOGD(("%s::%s - Removing obsolete callback for pluginId %s", LOGD(("%s::%s - Removing obsolete callback for pluginId %i",
__CLASS__, __FUNCTION__, __CLASS__, __FUNCTION__, callback->PluginId()));
PromiseFlatCString(callback->PluginId()).get()));
mPluginCrashCallbacks.RemoveElementAt(i - 1); mPluginCrashCallbacks.RemoveElementAt(i - 1);
} }
} }
@ -182,7 +181,7 @@ GeckoMediaPluginService::AddPluginCrashCallback(
} }
void void
GeckoMediaPluginService::RemovePluginCrashCallbacks(const nsACString& aPluginId) GeckoMediaPluginService::RemovePluginCrashCallbacks(const uint32_t aPluginId)
{ {
RemoveObsoletePluginCrashCallbacks(); RemoveObsoletePluginCrashCallbacks();
for (size_t i = mPluginCrashCallbacks.Length(); i != 0; --i) { for (size_t i = mPluginCrashCallbacks.Length(); i != 0; --i) {
@ -194,24 +193,22 @@ GeckoMediaPluginService::RemovePluginCrashCallbacks(const nsACString& aPluginId)
} }
void void
GeckoMediaPluginService::RunPluginCrashCallbacks(const nsACString& aPluginId, GeckoMediaPluginService::RunPluginCrashCallbacks(const uint32_t aPluginId,
const nsACString& aPluginName, const nsACString& aPluginName)
const nsAString& aPluginDumpId)
{ {
MOZ_ASSERT(NS_IsMainThread()); 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) { for (size_t i = mPluginCrashCallbacks.Length(); i != 0; --i) {
nsRefPtr<PluginCrashCallback>& callback = mPluginCrashCallbacks[i - 1]; nsRefPtr<PluginCrashCallback>& callback = mPluginCrashCallbacks[i - 1];
const nsACString& callbackPluginId = callback->PluginId(); const uint32_t callbackPluginId = callback->PluginId();
if (!callback->IsStillValid()) { if (!callback->IsStillValid()) {
LOGD(("%s::%s(%s) - Removing obsolete callback for pluginId %s", LOGD(("%s::%s(%i) - Removing obsolete callback for pluginId %i",
__CLASS__, __FUNCTION__, aPluginId.Data(), __CLASS__, __FUNCTION__, aPluginId, callback->PluginId()));
PromiseFlatCString(callback->PluginId()).get()));
mPluginCrashCallbacks.RemoveElementAt(i - 1); mPluginCrashCallbacks.RemoveElementAt(i - 1);
} else if (callbackPluginId == aPluginId) { } else if (callbackPluginId == aPluginId) {
LOGD(("%s::%s(%s) - Running #%u", LOGD(("%s::%s(%i) - Running #%u",
__CLASS__, __FUNCTION__, aPluginId.Data(), i - 1)); __CLASS__, __FUNCTION__, aPluginId, i - 1));
callback->Run(aPluginName, aPluginDumpId); callback->Run(aPluginName);
mPluginCrashCallbacks.RemoveElementAt(i - 1); mPluginCrashCallbacks.RemoveElementAt(i - 1);
} }
} }

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

@ -66,13 +66,13 @@ public:
public: public:
NS_INLINE_DECL_REFCOUNTING(PluginCrashCallback) NS_INLINE_DECL_REFCOUNTING(PluginCrashCallback)
PluginCrashCallback(const nsACString& aPluginId) PluginCrashCallback(const uint32_t aPluginId)
: mPluginId(aPluginId) : mPluginId(aPluginId)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
} }
const nsACString& PluginId() const { return mPluginId; } const uint32_t PluginId() const { return mPluginId; }
virtual void Run(const nsACString& aPluginName, const nsAString& aPluginDumpId) = 0; virtual void Run(const nsACString& aPluginName) = 0;
virtual bool IsStillValid() = 0; // False if callback has become useless. virtual bool IsStillValid() = 0; // False if callback has become useless.
protected: protected:
virtual ~PluginCrashCallback() virtual ~PluginCrashCallback()
@ -80,14 +80,13 @@ public:
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
} }
private: private:
const nsCString mPluginId; const uint32_t mPluginId;
}; };
void RemoveObsoletePluginCrashCallbacks(); // Called from add/remove/run. void RemoveObsoletePluginCrashCallbacks(); // Called from add/remove/run.
void AddPluginCrashCallback(nsRefPtr<PluginCrashCallback> aPluginCrashCallback); void AddPluginCrashCallback(nsRefPtr<PluginCrashCallback> aPluginCrashCallback);
void RemovePluginCrashCallbacks(const nsACString& aPluginId); void RemovePluginCrashCallbacks(const uint32_t aPluginId);
void RunPluginCrashCallbacks(const nsACString& aPluginId, void RunPluginCrashCallbacks(const uint32_t aPluginId,
const nsACString& aPluginName, const nsACString& aPluginName);
const nsAString& aPluginDumpId);
protected: protected:
GeckoMediaPluginService(); GeckoMediaPluginService();

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

@ -82,7 +82,7 @@ public:
base::ProcessId otherProcess; base::ProcessId otherProcess;
nsCString displayName; nsCString displayName;
nsCString pluginId; uint32_t pluginId;
bool ok = aGMPServiceChild->SendLoadGMP(mNodeId, mAPI, mTags, bool ok = aGMPServiceChild->SendLoadGMP(mNodeId, mAPI, mTags,
alreadyBridgedTo, &otherProcess, alreadyBridgedTo, &otherProcess,
&displayName, &pluginId); &displayName, &pluginId);

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

@ -1435,7 +1435,7 @@ GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId,
nsTArray<ProcessId>&& aAlreadyBridgedTo, nsTArray<ProcessId>&& aAlreadyBridgedTo,
ProcessId* aId, ProcessId* aId,
nsCString* aDisplayName, nsCString* aDisplayName,
nsCString* aPluginId) uint32_t* aPluginId)
{ {
nsRefPtr<GMPParent> gmp = mService->SelectPluginForAPI(aNodeId, aAPI, aTags); nsRefPtr<GMPParent> gmp = mService->SelectPluginForAPI(aNodeId, aAPI, aTags);

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

@ -193,7 +193,7 @@ public:
nsTArray<ProcessId>&& aAlreadyBridgedTo, nsTArray<ProcessId>&& aAlreadyBridgedTo,
base::ProcessId* aID, base::ProcessId* aID,
nsCString* aDisplayName, nsCString* aDisplayName,
nsCString* aPluginId) override; uint32_t* aPluginId) override;
virtual bool RecvGetGMPNodeId(const nsString& aOrigin, virtual bool RecvGetGMPNodeId(const nsString& aOrigin,
const nsString& aTopLevelOrigin, const nsString& aTopLevelOrigin,
const bool& aInPrivateBrowsing, const bool& aInPrivateBrowsing,

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

@ -216,6 +216,12 @@ GMPVideoEncoderParent::SetPeriodicKeyFrames(bool aEnable)
return GMPNoErr; return GMPNoErr;
} }
const uint32_t
GMPVideoEncoderParent::ParentID()
{
return mPlugin ? mPlugin->GetPluginId() : 0;
}
// Note: Consider keeping ActorDestroy sync'd up when making changes here. // Note: Consider keeping ActorDestroy sync'd up when making changes here.
void void
GMPVideoEncoderParent::Shutdown() GMPVideoEncoderParent::Shutdown()

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

@ -45,7 +45,7 @@ public:
virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) override; virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) override;
virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) override; virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) override;
virtual GMPErr SetPeriodicKeyFrames(bool aEnable) 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 // GMPSharedMemManager
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) override 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 SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0;
virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0; virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0;
virtual GMPErr SetPeriodicKeyFrames(bool aEnable) = 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 // Call to tell GMP/plugin the consumer will no longer use this
// interface/codec. // interface/codec.

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

@ -17,7 +17,7 @@ sync protocol PGMPService
parent: parent:
sync LoadGMP(nsCString nodeId, nsCString api, nsCString[] tags, sync LoadGMP(nsCString nodeId, nsCString api, nsCString[] tags,
ProcessId[] alreadyBridgedTo) ProcessId[] alreadyBridgedTo)
returns (ProcessId id, nsCString displayName, nsCString pluginId); returns (ProcessId id, nsCString displayName, uint32_t pluginId);
sync GetGMPNodeId(nsString origin, nsString topLevelOrigin, sync GetGMPNodeId(nsString origin, nsString topLevelOrigin,
bool inPrivateBrowsing) bool inPrivateBrowsing)
returns (nsCString id); returns (nsCString id);

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

@ -52,8 +52,8 @@ MediaOmxCommonDecoder::SetPlatformCanOffloadAudio(bool aCanOffloadAudio)
bool bool
MediaOmxCommonDecoder::CheckDecoderCanOffloadAudio() MediaOmxCommonDecoder::CheckDecoderCanOffloadAudio()
{ {
return (mCanOffloadAudio && !mFallbackToStateMachine && !mOutputStreams.Length() && return (mCanOffloadAudio && !mFallbackToStateMachine &&
mInitialPlaybackRate == 1.0); !mOutputStreams.Length() && mPlaybackRate == 1.0);
} }
void void

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

@ -15,6 +15,7 @@
#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PCrashReporterParent.h" #include "mozilla/dom/PCrashReporterParent.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/MessageChannel.h" #include "mozilla/ipc/MessageChannel.h"
#include "mozilla/plugins/BrowserStreamParent.h" #include "mozilla/plugins/BrowserStreamParent.h"
#include "mozilla/plugins/PluginAsyncSurrogate.h" #include "mozilla/plugins/PluginAsyncSurrogate.h"
@ -58,6 +59,7 @@ using base::KillProcess;
using mozilla::PluginLibrary; using mozilla::PluginLibrary;
using mozilla::ipc::MessageChannel; using mozilla::ipc::MessageChannel;
using mozilla::ipc::GeckoChildProcessHost;
using mozilla::dom::PCrashReporterParent; using mozilla::dom::PCrashReporterParent;
using mozilla::dom::CrashReporterParent; using mozilla::dom::CrashReporterParent;
@ -658,10 +660,6 @@ PluginModuleContentParent::~PluginModuleContentParent()
Preferences::UnregisterCallback(TimeoutChanged, kContentTimeoutPref, this); 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; bool PluginModuleChromeParent::sInstantiated = false;
PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId) PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId)
@ -693,7 +691,7 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32
{ {
NS_ASSERTION(mSubprocess, "Out of memory!"); NS_ASSERTION(mSubprocess, "Out of memory!");
sInstantiated = true; sInstantiated = true;
mRunID = sNextRunID++; mRunID = GeckoChildProcessHost::GetUniqueID();
#ifdef MOZ_ENABLE_PROFILER_SPS #ifdef MOZ_ENABLE_PROFILER_SPS
InitPluginProfiling(); InitPluginProfiling();

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

@ -557,7 +557,6 @@ private:
dom::ContentParent* mContentParent; dom::ContentParent* mContentParent;
nsCOMPtr<nsIObserver> mOfflineObserver; nsCOMPtr<nsIObserver> mOfflineObserver;
bool mIsBlocklisted; bool mIsBlocklisted;
static uint32_t sNextRunID;
static bool sInstantiated; static bool sInstantiated;
}; };

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

@ -63,7 +63,7 @@ interface PeerConnectionImpl {
void close(); void close();
/* Notify DOM window if this plugin crash is ours. */ /* 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 */ /* Attributes */
[Constant] [Constant]

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

@ -7,6 +7,7 @@
[Constructor(DOMString type, optional PluginCrashedEventInit eventInitDict), ChromeOnly] [Constructor(DOMString type, optional PluginCrashedEventInit eventInitDict), ChromeOnly]
interface PluginCrashedEvent : Event interface PluginCrashedEvent : Event
{ {
readonly attribute unsigned long pluginID;
readonly attribute DOMString pluginDumpID; readonly attribute DOMString pluginDumpID;
readonly attribute DOMString pluginName; readonly attribute DOMString pluginName;
readonly attribute DOMString? browserDumpID; readonly attribute DOMString? browserDumpID;
@ -17,6 +18,7 @@ interface PluginCrashedEvent : Event
dictionary PluginCrashedEventInit : EventInit dictionary PluginCrashedEventInit : EventInit
{ {
unsigned long pluginID = 0;
DOMString pluginDumpID = ""; DOMString pluginDumpID = "";
DOMString pluginName = ""; DOMString pluginName = "";
DOMString? browserDumpID = null; DOMString? browserDumpID = null;

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

@ -208,6 +208,8 @@ private:
const char* aPathPrefix, const char* aPathPrefix,
const ImageMemoryCounter& aCounter) const ImageMemoryCounter& aCounter)
{ {
nsresult rv;
nsAutoCString pathPrefix(NS_LITERAL_CSTRING("explicit/")); nsAutoCString pathPrefix(NS_LITERAL_CSTRING("explicit/"));
pathPrefix.Append(aPathPrefix); pathPrefix.Append(aPathPrefix);
pathPrefix.Append(aCounter.Type() == imgIContainer::TYPE_RASTER pathPrefix.Append(aCounter.Type() == imgIContainer::TYPE_RASTER
@ -228,7 +230,13 @@ private:
pathPrefix.Append(")/"); 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, static nsresult ReportSurfaces(nsIHandleReportCallback* aHandleReport,
@ -332,10 +340,7 @@ private:
{ {
nsresult rv; nsresult rv;
rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix, rv = ReportSourceValue(aHandleReport, aData, aPathPrefix, aCounter);
"source",
"Raster image source data and vector image documents.",
aCounter.Source());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix, rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix,
@ -353,6 +358,21 @@ private:
return NS_OK; 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, static nsresult ReportValue(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, nsISupports* aData,
int32_t aKind, int32_t aKind,

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

@ -254,6 +254,17 @@ uint32_t GeckoChildProcessHost::GetSupportedArchitecturesForProcessType(GeckoPro
return base::GetCurrentProcessArchitecture(); 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 void
GeckoChildProcessHost::PrepareLaunch() GeckoChildProcessHost::PrepareLaunch()
{ {

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

@ -47,6 +47,8 @@ public:
static uint32_t GetSupportedArchitecturesForProcessType(GeckoProcessType type); static uint32_t GetSupportedArchitecturesForProcessType(GeckoProcessType type);
static uint32_t GetUniqueID();
// Block until the IPC channel for our subprocess is initialized, // Block until the IPC channel for our subprocess is initialized,
// but no longer. The child process may or may not have been // but no longer. The child process may or may not have been
// created when this method returns. // created when this method returns.
@ -196,6 +198,8 @@ private:
// //
// FIXME/cjones: this strongly indicates bad design. Shame on us. // FIXME/cjones: this strongly indicates bad design. Shame on us.
std::queue<IPC::Message> mQueue; std::queue<IPC::Message> mQueue;
static uint32_t sNextUniqueID;
}; };
#ifdef MOZ_NUWA_PROCESS #ifdef MOZ_NUWA_PROCESS

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

@ -591,7 +591,7 @@ struct JSClass {
#define JSCLASS_IS_PROXY (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4)) #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. // Reserved for embeddings.
#define JSCLASS_USERBIT2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6)) #define JSCLASS_USERBIT2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6))

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

@ -225,7 +225,7 @@ struct GCSizes
macro(_, _, marker) \ macro(_, _, marker) \
macro(_, _, nurseryCommitted) \ macro(_, _, nurseryCommitted) \
macro(_, _, nurseryDecommitted) \ macro(_, _, nurseryDecommitted) \
macro(_, _, nurseryHugeSlots) \ macro(_, _, nurseryMallocedBuffers) \
macro(_, _, storeBufferVals) \ macro(_, _, storeBufferVals) \
macro(_, _, storeBufferCells) \ macro(_, _, storeBufferCells) \
macro(_, _, storeBufferSlots) \ macro(_, _, storeBufferSlots) \

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

@ -105,10 +105,14 @@ elif [ "$OSTYPE" = "linux-gnu" ]; then
fi fi
fi fi
elif [ "$OSTYPE" = "msys" ]; then elif [ "$OSTYPE" = "msys" ]; then
USE_64BIT=false case "$platform" in
if [ "$platform" = "win64" ]; then win64*)
USE_64BIT=true USE_64BIT=true
fi ;;
*)
USE_64BIT=false
;;
esac
MAKE=${MAKE:-mozmake} MAKE=${MAKE:-mozmake}
source "$ABSDIR/winbuildenv.sh" source "$ABSDIR/winbuildenv.sh"
fi fi
@ -117,6 +121,9 @@ MAKE=${MAKE:-make}
if $USE_64BIT; then if $USE_64BIT; then
NSPR64="--enable-64bit" NSPR64="--enable-64bit"
if [ "$OSTYPE" = "msys" ]; then
CONFIGURE_ARGS="$CONFIGURE_ARGS --target=x86_64-pc-mingw32 --host=x86_64-pc-mingw32"
fi
else else
NSPR64="" NSPR64=""
if [ "$OSTYPE" != "msys" ]; then if [ "$OSTYPE" != "msys" ]; then
@ -169,8 +176,14 @@ elif [[ "$VARIANT" = "compacting" ]]; then
esac esac
fi fi
if [[ "$VARIANT" = "warnaserr" ]]; then if [[ "$VARIANT" = "warnaserr" ||
"$VARIANT" = "warnaserrdebug" ||
"$VARIANT" = "plain" ]]; then
export JSTESTS_EXTRA_ARGS=--tbpl export JSTESTS_EXTRA_ARGS=--tbpl
elif [[ "$VARIANT" = "arm-sim" ||
"$VARIANT" = "rootanalysis" ||
"$VARIANT" = "plaindebug" ]]; then
export JSTESTS_EXTRA_ARGS=--tbpl-debug
fi fi
$COMMAND_PREFIX $MAKE check || exit 1 $COMMAND_PREFIX $MAKE check || exit 1

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

@ -14,9 +14,11 @@
#include "js/TracingAPI.h" #include "js/TracingAPI.h"
#include "vm/Runtime.h" #include "vm/Runtime.h"
namespace js {
template <typename T> template <typename T>
MOZ_ALWAYS_INLINE bool MOZ_ALWAYS_INLINE bool
js::Nursery::getForwardedPointer(T** ref) Nursery::getForwardedPointer(T** ref)
{ {
MOZ_ASSERT(ref); MOZ_ASSERT(ref);
MOZ_ASSERT(isInside((void*)*ref)); MOZ_ASSERT(isInside((void*)*ref));
@ -28,4 +30,47 @@ js::Nursery::getForwardedPointer(T** ref)
return true; 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 */ #endif /* gc_Nursery_inl_h */

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

@ -37,16 +37,16 @@ using mozilla::ArrayLength;
using mozilla::PodCopy; using mozilla::PodCopy;
using mozilla::PodZero; using mozilla::PodZero;
struct js::Nursery::FreeHugeSlotsTask : public GCParallelTask struct js::Nursery::FreeMallocedBuffersTask : public GCParallelTask
{ {
explicit FreeHugeSlotsTask(FreeOp* fop) : fop_(fop) {} explicit FreeMallocedBuffersTask(FreeOp* fop) : fop_(fop) {}
bool init() { return slots_.init(); } bool init() { return buffers_.init(); }
void transferSlotsToFree(HugeSlotsSet& slotsToFree); void transferBuffersToFree(MallocedBuffersSet& buffersToFree);
~FreeHugeSlotsTask() override { join(); } ~FreeMallocedBuffersTask() override { join(); }
private: private:
FreeOp* fop_; FreeOp* fop_;
HugeSlotsSet slots_; MallocedBuffersSet buffers_;
virtual void run() override; virtual void run() override;
}; };
@ -61,15 +61,15 @@ js::Nursery::init(uint32_t maxNurseryBytes)
if (numNurseryChunks_ == 0) if (numNurseryChunks_ == 0)
return true; return true;
if (!hugeSlots.init()) if (!mallocedBuffers.init())
return false; return false;
void* heap = MapAlignedPages(nurserySize(), Alignment); void* heap = MapAlignedPages(nurserySize(), Alignment);
if (!heap) if (!heap)
return false; return false;
freeHugeSlotsTask = js_new<FreeHugeSlotsTask>(runtime()->defaultFreeOp()); freeMallocedBuffersTask = js_new<FreeMallocedBuffersTask>(runtime()->defaultFreeOp());
if (!freeHugeSlotsTask || !freeHugeSlotsTask->init()) if (!freeMallocedBuffersTask || !freeMallocedBuffersTask->init())
return false; return false;
heapStart_ = uintptr_t(heap); heapStart_ = uintptr_t(heap);
@ -100,7 +100,7 @@ js::Nursery::~Nursery()
if (start()) if (start())
UnmapPages((void*)start(), nurserySize()); UnmapPages((void*)start(), nurserySize());
js_delete(freeHugeSlotsTask); js_delete(freeMallocedBuffersTask);
} }
void void
@ -175,38 +175,19 @@ js::Nursery::leaveZealMode() {
} }
#endif // JS_GC_ZEAL #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* JSObject*
js::Nursery::allocateObject(JSContext* cx, size_t size, size_t numDynamic, const js::Class* clasp) 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. */ /* Ensure there's enough space to replace the contents with a RelocationOverlay. */
MOZ_ASSERT(size >= sizeof(RelocationOverlay)); MOZ_ASSERT(size >= sizeof(RelocationOverlay));
verifyFinalizerList();
/* If we have a finalizer, get space for the list entry. */ /*
ListItem* listEntry = nullptr; * Classes with JSCLASS_SKIP_NURSERY_FINALIZE will not have their finalizer
if (clasp->finalize) { * called if they are nursery allocated and not promoted to the tenured
listEntry = static_cast<ListItem*>(allocate(sizeof(ListItem))); * heap. The finalizers for these classes must do nothing except free data
if (!listEntry) * which was allocated via Nursery::allocateBuffer.
return nullptr; */
} MOZ_ASSERT_IF(clasp->finalize, clasp->flags & JSCLASS_SKIP_NURSERY_FINALIZE);
/* Make the object allocation. */ /* Make the object allocation. */
JSObject* obj = static_cast<JSObject*>(allocate(size)); 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. */ /* If we want external slots, add them. */
HeapSlot* slots = nullptr; HeapSlot* slots = nullptr;
if (numDynamic) { if (numDynamic) {
/* Try to allocate in the nursery first. */ slots = static_cast<HeapSlot*>(allocateBuffer(cx->zone(), numDynamic * sizeof(HeapSlot)));
if (numDynamic <= MaxNurserySlots) if (!slots) {
slots = static_cast<HeapSlot*>(allocate(numDynamic * sizeof(HeapSlot))); /*
* It is safe to leave the allocated object uninitialized, since we
/* If we are out of space or too large, use the malloc heap. */ * do not visit unallocated things in the nursery.
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)
return nullptr; return nullptr;
}
} }
/* Always initialize the slots field to match the JIT behavior. */ /* Always initialize the slots field to match the JIT behavior. */
obj->setInitialSlotsMaybeNonNative(slots); 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); TraceNurseryAlloc(obj, size);
return obj; return obj;
} }
@ -264,89 +234,72 @@ js::Nursery::allocate(size_t size)
return thing; return thing;
} }
/* Internally, this function is used to allocate elements as well as slots. */ void*
HeapSlot* js::Nursery::allocateBuffer(Zone* zone, uint32_t nbytes)
js::Nursery::allocateSlots(JSObject* obj, uint32_t nslots) {
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(obj);
MOZ_ASSERT(nslots > 0); MOZ_ASSERT(nbytes > 0);
if (!IsInsideNursery(obj)) if (!IsInsideNursery(obj))
return obj->zone()->pod_malloc<HeapSlot>(nslots); return obj->zone()->pod_malloc<uint8_t>(nbytes);
return allocateBuffer(obj->zone(), nbytes);
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);
} }
ObjectElements* void*
js::Nursery::allocateElements(JSObject* obj, uint32_t nelems) js::Nursery::reallocateBuffer(JSObject* obj, void* oldBuffer,
{ uint32_t oldBytes, uint32_t newBytes)
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)
{ {
if (!IsInsideNursery(obj)) 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)) { if (!isInside(oldBuffer)) {
HeapSlot* newSlots = obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount); void* newBuffer = obj->zone()->pod_realloc<uint8_t>((uint8_t*)oldBuffer, oldBytes, newBytes);
if (newSlots && oldSlots != newSlots) { if (newBuffer && oldBytes != newBytes) {
hugeSlots.remove(oldSlots); removeMallocedBuffer(oldBuffer);
/* If this put fails, we will only leak the slots. */ /* 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. */ /* The nursery cannot make use of the returned slots data. */
if (newCount < oldCount) if (newBytes < oldBytes)
return oldSlots; return oldBuffer;
HeapSlot* newSlots = allocateSlots(obj, newCount); void* newBuffer = allocateBuffer(obj->zone(), newBytes);
if (newSlots) if (newBuffer)
PodCopy(newSlots, oldSlots, oldCount); PodCopy((uint8_t*)newBuffer, (uint8_t*)oldBuffer, oldBytes);
return newSlots; return newBuffer;
}
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 void
js::Nursery::freeSlots(HeapSlot* slots) js::Nursery::freeBuffer(void* buffer)
{ {
if (!isInside(slots)) { if (!isInside(buffer)) {
hugeSlots.remove(slots); removeMallocedBuffer(buffer);
js_free(slots); 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 js {
namespace gc { namespace gc {
@ -691,8 +644,15 @@ js::Nursery::moveObjectToTenured(MinorCollectionTracer* trc,
} }
} }
if (src->is<InlineTypedObject>()) if (src->is<InlineTypedObject>()) {
InlineTypedObject::objectMovedDuringMinorGC(trc, dst, src); 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; return tenuredSize;
} }
@ -705,7 +665,7 @@ js::Nursery::moveSlotsToTenured(NativeObject* dst, NativeObject* src, AllocKind
return 0; return 0;
if (!isInside(src->slots_)) { if (!isInside(src->slots_)) {
hugeSlots.remove(src->slots_); removeMallocedBuffer(src->slots_);
return 0; 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. */ /* TODO Bug 874151: Prefer to put element data inline if we have space. */
if (!isInside(srcHeader)) { if (!isInside(srcHeader)) {
MOZ_ASSERT(src->elements_ == dst->elements_); MOZ_ASSERT(src->elements_ == dst->elements_);
hugeSlots.remove(reinterpret_cast<HeapSlot*>(srcHeader)); removeMallocedBuffer(srcHeader);
return 0; return 0;
} }
@ -879,13 +839,9 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
TIME_END(updateJitActivations); TIME_END(updateJitActivations);
// Sweep. // Sweep.
TIME_START(runFinalizers); TIME_START(freeMallocedBuffers);
runFinalizers(); freeMallocedBuffers();
TIME_END(runFinalizers); TIME_END(freeMallocedBuffers);
TIME_START(freeHugeSlots);
freeHugeSlots();
TIME_END(freeHugeSlots);
TIME_START(sweep); TIME_START(sweep);
sweep(); sweep();
@ -947,7 +903,7 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
#define FMT " %6" PRIu64 #define FMT " %6" PRIu64
fprintf(stderr, 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), js::gcstats::ExplainReason(reason),
promotionRate * 100, promotionRate * 100,
numActiveChunks_, numActiveChunks_,
@ -966,8 +922,7 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
TIME_TOTAL(collectToFP), TIME_TOTAL(collectToFP),
TIME_TOTAL(sweepArrayBufferViewList), TIME_TOTAL(sweepArrayBufferViewList),
TIME_TOTAL(updateJitActivations), TIME_TOTAL(updateJitActivations),
TIME_TOTAL(runFinalizers), TIME_TOTAL(freeMallocedBuffers),
TIME_TOTAL(freeHugeSlots),
TIME_TOTAL(clearStoreBuffer), TIME_TOTAL(clearStoreBuffer),
TIME_TOTAL(sweep), TIME_TOTAL(sweep),
TIME_TOTAL(resize), TIME_TOTAL(resize),
@ -981,62 +936,47 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
#undef TIME_TOTAL #undef TIME_TOTAL
void 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. // swapping the sets, which also clears the source.
MOZ_ASSERT(!isRunning()); MOZ_ASSERT(!isRunning());
MOZ_ASSERT(slots_.empty()); MOZ_ASSERT(buffers_.empty());
mozilla::Swap(slots_, slotsToFree); mozilla::Swap(buffers_, buffersToFree);
} }
void 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()); fop_->free_(r.front());
slots_.clear(); buffers_.clear();
} }
void void
js::Nursery::freeHugeSlots() js::Nursery::freeMallocedBuffers()
{ {
if (hugeSlots.empty()) if (mallocedBuffers.empty())
return; return;
bool started; bool started;
{ {
AutoLockHelperThreadState lock; AutoLockHelperThreadState lock;
freeHugeSlotsTask->joinWithLockHeld(); freeMallocedBuffersTask->joinWithLockHeld();
freeHugeSlotsTask->transferSlotsToFree(hugeSlots); freeMallocedBuffersTask->transferBuffersToFree(mallocedBuffers);
started = freeHugeSlotsTask->startWithLockHeld(); started = freeMallocedBuffersTask->startWithLockHeld();
} }
if (!started) if (!started)
freeHugeSlotsTask->runFromMainThread(runtime()); freeMallocedBuffersTask->runFromMainThread(runtime());
MOZ_ASSERT(hugeSlots.empty()); MOZ_ASSERT(mallocedBuffers.empty());
} }
void void
js::Nursery::waitBackgroundFreeEnd() js::Nursery::waitBackgroundFreeEnd()
{ {
freeHugeSlotsTask->join(); freeMallocedBuffersTask->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;
} }
void void

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

@ -59,10 +59,9 @@ class Nursery
currentChunk_(0), currentChunk_(0),
numActiveChunks_(0), numActiveChunks_(0),
numNurseryChunks_(0), numNurseryChunks_(0),
finalizers_(nullptr),
profileThreshold_(0), profileThreshold_(0),
enableProfiling_(false), enableProfiling_(false),
freeHugeSlotsTask(nullptr) freeMallocedBuffersTask(nullptr)
{} {}
~Nursery(); ~Nursery();
@ -94,22 +93,21 @@ class Nursery
*/ */
JSObject* allocateObject(JSContext* cx, size_t size, size_t numDynamic, const js::Class* clasp); JSObject* allocateObject(JSContext* cx, size_t size, size_t numDynamic, const js::Class* clasp);
/* Allocate a slots array for the given object. */ /* Allocate a buffer for a given zone, using the nursery if possible. */
HeapSlot* allocateSlots(JSObject* obj, uint32_t nslots); 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. */ /* Resize an existing object buffer. */
HeapSlot* reallocateSlots(JSObject* obj, HeapSlot* oldSlots, void* reallocateBuffer(JSObject* obj, void* oldBuffer,
uint32_t oldCount, uint32_t newCount); uint32_t oldBytes, uint32_t newBytes);
/* Resize an existing elements vector. */ /* Free an object buffer. */
ObjectElements* reallocateElements(JSObject* obj, ObjectElements* oldHeader, void freeBuffer(void* buffer);
uint32_t oldCount, uint32_t newCount);
/* Free a slots array. */
void freeSlots(HeapSlot* slots);
typedef Vector<ObjectGroup*, 0, SystemAllocPolicy> ObjectGroupList; typedef Vector<ObjectGroup*, 0, SystemAllocPolicy> ObjectGroupList;
@ -135,6 +133,11 @@ class Nursery
setForwardingPointer(oldData, newData, direct); setForwardingPointer(oldData, newData, direct);
} }
/* Mark a malloced buffer as no longer needing to be freed. */
void removeMallocedBuffer(void* buffer) {
mallocedBuffers.remove(buffer);
}
void waitBackgroundFreeEnd(); void waitBackgroundFreeEnd();
size_t sizeOfHeapCommitted() const { size_t sizeOfHeapCommitted() const {
@ -143,11 +146,11 @@ class Nursery
size_t sizeOfHeapDecommitted() const { size_t sizeOfHeapDecommitted() const {
return (numNurseryChunks_ - numActiveChunks_) * gc::ChunkSize; return (numNurseryChunks_ - numActiveChunks_) * gc::ChunkSize;
} }
size_t sizeOfHugeSlots(mozilla::MallocSizeOf mallocSizeOf) const { size_t sizeOfMallocedBuffers(mozilla::MallocSizeOf mallocSizeOf) const {
size_t total = 0; 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 += mallocSizeOf(r.front());
total += hugeSlots.sizeOfExcludingThis(mallocSizeOf); total += mallocedBuffers.sizeOfExcludingThis(mallocSizeOf);
return total; return total;
} }
@ -198,31 +201,21 @@ class Nursery
/* Number of chunks allocated for the nursery. */ /* Number of chunks allocated for the nursery. */
int numNurseryChunks_; 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. */ /* Report minor collections taking more than this many us, if enabled. */
int64_t profileThreshold_; int64_t profileThreshold_;
bool enableProfiling_; bool enableProfiling_;
/* /*
* The set of externally malloced slots potentially kept live by objects * The set of externally malloced buffers potentially kept live by objects
* stored in the nursery. Any external slots that do not belong to a * 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. * tenured thing at the end of a minor GC must be freed.
*/ */
typedef HashSet<HeapSlot*, PointerHasher<HeapSlot*, 3>, SystemAllocPolicy> HugeSlotsSet; typedef HashSet<void*, PointerHasher<void*, 3>, SystemAllocPolicy> MallocedBuffersSet;
HugeSlotsSet hugeSlots; MallocedBuffersSet mallocedBuffers;
/* A task structure used to free the huge slots on a background thread. */ /* A task structure used to free the malloced bufers on a background thread. */
struct FreeHugeSlotsTask; struct FreeMallocedBuffersTask;
FreeHugeSlotsTask* freeHugeSlotsTask; FreeMallocedBuffersTask* freeMallocedBuffersTask;
/* /*
* During a collection most hoisted slot and element buffers indicate their * 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; typedef HashMap<void*, void*, PointerHasher<void*, 1>, SystemAllocPolicy> ForwardedBufferMap;
ForwardedBufferMap forwardedBuffers; ForwardedBufferMap forwardedBuffers;
/* The maximum number of slots allowed to reside inline in the nursery. */ /* The maximum number of bytes allowed to reside in nursery buffers. */
static const size_t MaxNurserySlots = 128; static const size_t MaxNurseryBufferSize = 1024;
/* The amount of space in the mapped nursery available to allocations. */ /* The amount of space in the mapped nursery available to allocations. */
static const size_t NurseryChunkUsableSize = gc::ChunkSize - sizeof(gc::ChunkTrailer); static const size_t NurseryChunkUsableSize = gc::ChunkSize - sizeof(gc::ChunkTrailer);
@ -292,9 +285,6 @@ class Nursery
JSRuntime* runtime() const { return runtime_; } 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. */ /* Allocates a new GC thing from the tenured generation during minor GC. */
gc::TenuredCell* allocateFromTenured(JS::Zone* zone, gc::AllocKind thingKind); gc::TenuredCell* allocateFromTenured(JS::Zone* zone, gc::AllocKind thingKind);
@ -302,7 +292,6 @@ class Nursery
/* Common internal allocator function. */ /* Common internal allocator function. */
void* allocate(size_t size); void* allocate(size_t size);
void verifyFinalizerList();
/* /*
* Move the object at |src| in the Nursery to an already-allocated cell * 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, void setElementsForwardingPointer(ObjectElements* oldHeader, ObjectElements* newHeader,
uint32_t nelems); uint32_t nelems);
/* Run finalizers on all finalizable things in the nursery. */
void runFinalizers();
/* Free malloced pointers owned by freed things in the nursery. */ /* 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 * 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); MOZ_ASSERT(initialHeap != gc::TenuredHeap);
// We still need to allocate in the nursery, per the comment in // We still need to allocate in the nursery, per the comment in
// shouldNurseryAllocate; however, we need to insert into hugeSlots, so // shouldNurseryAllocate; however, we need to insert into the
// bail to do the nursery allocation in the interpreter. // mallocedBuffers set, so bail to do the nursery allocation in the
if (nDynamicSlots >= Nursery::MaxNurserySlots) { // interpreter.
if (nDynamicSlots >= Nursery::MaxNurseryBufferSize / sizeof(Value)) {
jump(fail); jump(fail);
return; return;
} }

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

@ -40,7 +40,6 @@ UNIFIED_SOURCES += [
'testGCFinalizeCallback.cpp', 'testGCFinalizeCallback.cpp',
'testGCHeapPostBarriers.cpp', 'testGCHeapPostBarriers.cpp',
'testGCMarking.cpp', 'testGCMarking.cpp',
'testGCNursery.cpp',
'testGCOutOfMemory.cpp', 'testGCOutOfMemory.cpp',
'testGCStoreBufferRemoval.cpp', 'testGCStoreBufferRemoval.cpp',
'testGetPropertyDescriptor.cpp', 'testGetPropertyDescriptor.cpp',

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

@ -3965,6 +3965,16 @@ JSObject::allocKindForTenure(const js::Nursery& nursery) const
return GetGCObjectKindForBytes(UnboxedPlainObject::offsetOfData() + nbytes); 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 // Inlined typed objects are followed by their data, so make sure we copy
// it all over to the new object. // it all over to the new object.
if (is<InlineTypedObject>()) { if (is<InlineTypedObject>()) {

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

@ -1112,7 +1112,7 @@ GetInitialHeap(NewObjectKind newKind, const Class* clasp)
{ {
if (newKind != GenericObject) if (newKind != GenericObject)
return gc::TenuredHeap; 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::TenuredHeap;
return gc::DefaultHeap; return gc::DefaultHeap;
} }

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

@ -267,7 +267,7 @@ JSObject::create(js::ExclusiveContext* cx, js::gc::AllocKind kind, js::gc::Initi
IsBackgroundFinalized(kind)); IsBackgroundFinalized(kind));
MOZ_ASSERT_IF(group->clasp()->finalize, MOZ_ASSERT_IF(group->clasp()->finalize,
heap == js::gc::TenuredHeap || heap == js::gc::TenuredHeap ||
(group->clasp()->flags & JSCLASS_FINALIZE_FROM_NURSERY)); (group->clasp()->flags & JSCLASS_SKIP_NURSERY_FINALIZE));
MOZ_ASSERT_IF(group->hasUnanalyzedPreliminaryObjects(), MOZ_ASSERT_IF(group->hasUnanalyzedPreliminaryObjects(),
heap == js::gc::TenuredHeap); heap == js::gc::TenuredHeap);

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

@ -13,7 +13,7 @@ from copy import copy
from subprocess import list2cmdline, call from subprocess import list2cmdline, call
from lib.results import NullTestOutput 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.results import ResultsSink
from lib.progressbar import ProgressBar from lib.progressbar import ProgressBar
@ -97,6 +97,9 @@ def parse_args():
harness_og.add_option('--tbpl', action='store_true', harness_og.add_option('--tbpl', action='store_true',
help='Runs each test in all configurations tbpl' help='Runs each test in all configurations tbpl'
' tests.') ' 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', harness_og.add_option('-g', '--debug', action='store_true',
help='Run a test in debugger.') help='Run a test in debugger.')
harness_og.add_option('--debugger', default='gdb -q --args', harness_og.add_option('--debugger', default='gdb -q --args',
@ -269,9 +272,9 @@ def load_tests(options, requested_paths, excluded_paths):
sys.exit() sys.exit()
# Create a new test list. Apply each TBPL configuration to every test. # 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 = [] new_test_list = []
flags_list = TBPL_FLAGS flags_list = TBPL_FLAGS if options.tbpl else TBPL_DEBUG_FLAGS
for test in test_list: for test in test_list:
for jitflags in flags_list: for jitflags in flags_list:
tmp_test = copy(test) tmp_test = copy(test)

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

@ -20,6 +20,12 @@ TBPL_FLAGS = [
['--baseline-eager', '--no-fpu'], ['--baseline-eager', '--no-fpu'],
['--no-baseline', '--no-ion'], ['--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): def do_run_cmd(cmd):
l = [None, None] l = [None, None]

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

@ -17,6 +17,7 @@
#include "jsobjinlines.h" #include "jsobjinlines.h"
#include "gc/Nursery-inl.h"
#include "vm/ArrayObject-inl.h" #include "vm/ArrayObject-inl.h"
#include "vm/Shape-inl.h" #include "vm/Shape-inl.h"
@ -24,6 +25,7 @@ using namespace js;
using JS::GenericNaN; using JS::GenericNaN;
using mozilla::DebugOnly; using mozilla::DebugOnly;
using mozilla::PodCopy;
using mozilla::RoundUpPow2; using mozilla::RoundUpPow2;
static const ObjectElements emptyElementsHeader(0, 0); static const ObjectElements emptyElementsHeader(0, 0);
@ -377,31 +379,6 @@ NativeObject::setSlotSpan(ExclusiveContext* cx, uint32_t span)
return true; 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 bool
NativeObject::growSlots(ExclusiveContext* cx, uint32_t oldCount, uint32_t newCount) 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); MOZ_ASSERT(newCount < NELEMENTS_LIMIT);
if (!oldCount) { if (!oldCount) {
slots_ = AllocateSlots(cx, this, newCount); slots_ = AllocateObjectBuffer<HeapSlot>(cx, this, newCount);
if (!slots_) if (!slots_)
return false; return false;
Debug_SetSlotRangeToCrashOnTouch(slots_, newCount); Debug_SetSlotRangeToCrashOnTouch(slots_, newCount);
return true; return true;
} }
HeapSlot* newslots = ReallocateSlots(cx, this, slots_, oldCount, newCount); HeapSlot* newslots = ReallocateObjectBuffer<HeapSlot>(cx, this, slots_, oldCount, newCount);
if (!newslots) if (!newslots)
return false; /* Leave slots at its old size. */ 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. // Note: threads without a JSContext do not have access to GGC nursery allocated things.
if (cx->isJSContext()) if (cx->isJSContext())
return cx->asJSContext()->runtime()->gc.nursery.freeSlots(slots); return cx->asJSContext()->runtime()->gc.nursery.freeBuffer(slots);
js_free(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); 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) if (!newslots)
return; /* Leave slots at its old size. */ return; /* Leave slots at its old size. */
@ -664,31 +641,6 @@ NativeObject::maybeDensifySparseElements(js::ExclusiveContext* cx, HandleNativeO
return ED_OK; 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 // 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: // slot count is usually a power-of-two:
// //
@ -820,19 +772,20 @@ NativeObject::growElements(ExclusiveContext* cx, uint32_t reqCapacity)
uint32_t initlen = getDenseInitializedLength(); uint32_t initlen = getDenseInitializedLength();
ObjectElements* newheader; HeapSlot* oldHeaderSlots = reinterpret_cast<HeapSlot*>(getElementsHeader());
HeapSlot* newHeaderSlots;
if (hasDynamicElements()) { if (hasDynamicElements()) {
newheader = ReallocateElements(cx, this, getElementsHeader(), oldAllocated, newAllocated); newHeaderSlots = ReallocateObjectBuffer<HeapSlot>(cx, this, oldHeaderSlots, oldAllocated, newAllocated);
if (!newheader) if (!newHeaderSlots)
return false; // Leave elements at its old size. return false; // Leave elements at its old size.
} else { } else {
newheader = AllocateElements(cx, this, newAllocated); newHeaderSlots = AllocateObjectBuffer<HeapSlot>(cx, this, newAllocated);
if (!newheader) if (!newHeaderSlots)
return false; // Leave elements at its old size. return false; // Leave elements at its old size.
js_memcpy(newheader, getElementsHeader(), PodCopy(newHeaderSlots, oldHeaderSlots, ObjectElements::VALUES_PER_HEADER + initlen);
(ObjectElements::VALUES_PER_HEADER + initlen) * sizeof(Value));
} }
ObjectElements* newheader = reinterpret_cast<ObjectElements*>(newHeaderSlots);
newheader->capacity = newCapacity; newheader->capacity = newCapacity;
elements_ = newheader->elements(); elements_ = newheader->elements();
@ -863,13 +816,15 @@ NativeObject::shrinkElements(ExclusiveContext* cx, uint32_t reqCapacity)
MOZ_ASSERT(newAllocated > ObjectElements::VALUES_PER_HEADER); MOZ_ASSERT(newAllocated > ObjectElements::VALUES_PER_HEADER);
uint32_t newCapacity = newAllocated - ObjectElements::VALUES_PER_HEADER; uint32_t newCapacity = newAllocated - ObjectElements::VALUES_PER_HEADER;
ObjectElements* newheader = ReallocateElements(cx, this, getElementsHeader(), HeapSlot* oldHeaderSlots = reinterpret_cast<HeapSlot*>(getElementsHeader());
oldAllocated, newAllocated); HeapSlot* newHeaderSlots = ReallocateObjectBuffer<HeapSlot>(cx, this, oldHeaderSlots,
if (!newheader) { oldAllocated, newAllocated);
if (!newHeaderSlots) {
cx->recoverFromOutOfMemory(); cx->recoverFromOutOfMemory();
return; // Leave elements at its old size. return; // Leave elements at its old size.
} }
ObjectElements* newheader = reinterpret_cast<ObjectElements*>(newHeaderSlots);
newheader->capacity = newCapacity; newheader->capacity = newCapacity;
elements_ = newheader->elements(); elements_ = newheader->elements();
} }
@ -893,9 +848,10 @@ NativeObject::CopyElementsForWrite(ExclusiveContext* cx, NativeObject* obj)
JSObject::writeBarrierPre(obj->getElementsHeader()->ownerObject()); JSObject::writeBarrierPre(obj->getElementsHeader()->ownerObject());
ObjectElements* newheader = AllocateElements(cx, obj, newAllocated); HeapSlot* newHeaderSlots = AllocateObjectBuffer<HeapSlot>(cx, obj, newAllocated);
if (!newheader) if (!newHeaderSlots)
return false; return false;
ObjectElements* newheader = reinterpret_cast<ObjectElements*>(newHeaderSlots);
js_memcpy(newheader, obj->getElementsHeader(), js_memcpy(newheader, obj->getElementsHeader(),
(ObjectElements::VALUES_PER_HEADER + initlen) * sizeof(Value)); (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.marker += gc.marker.sizeOfExcludingThis(mallocSizeOf);
rtSizes->gc.nurseryCommitted += gc.nursery.sizeOfHeapCommitted(); rtSizes->gc.nurseryCommitted += gc.nursery.sizeOfHeapCommitted();
rtSizes->gc.nurseryDecommitted += gc.nursery.sizeOfHeapDecommitted(); 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); gc.storeBuffer.addSizeOfExcludingThis(mallocSizeOf, &rtSizes->gc);
} }

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

@ -11,6 +11,7 @@
#include "jsobjinlines.h" #include "jsobjinlines.h"
#include "gc/Nursery-inl.h"
#include "vm/Shape-inl.h" #include "vm/Shape-inl.h"
using mozilla::ArrayLength; using mozilla::ArrayLength;
@ -1034,16 +1035,18 @@ UnboxedArrayObject::create(ExclusiveContext* cx, HandleObjectGroup group, uint32
size_t capacity = (GetGCKindBytes(allocKind) - offsetOfInlineElements()) / elementSize; size_t capacity = (GetGCKindBytes(allocKind) - offsetOfInlineElements()) / elementSize;
res->setCapacityIndex(exactCapacityIndex(capacity)); res->setCapacityIndex(exactCapacityIndex(capacity));
} else { } 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); res = NewObjectWithGroup<UnboxedArrayObject>(cx, group, gc::AllocKind::OBJECT0, newKind);
if (!res) if (!res)
return nullptr; 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); res->setCapacityIndex(CapacityMatchesLengthIndex);
} }
@ -1145,10 +1148,51 @@ UnboxedArrayObject::objectMoved(JSObject* obj, const JSObject* old)
/* static */ void /* static */ void
UnboxedArrayObject::finalize(FreeOp* fop, JSObject* obj) UnboxedArrayObject::finalize(FreeOp* fop, JSObject* obj)
{ {
MOZ_ASSERT(!IsInsideNursery(obj));
if (!obj->as<UnboxedArrayObject>().hasInlineElements()) if (!obj->as<UnboxedArrayObject>().hasInlineElements())
js_free(obj->as<UnboxedArrayObject>().elements()); 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 // 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 // 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 // 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; uint8_t* newElements;
if (hasInlineElements()) { if (hasInlineElements()) {
newElements = cx->zone()->pod_malloc<uint8_t>(newCapacity * elementSize()); newElements = AllocateObjectBuffer<uint8_t>(cx, this, newCapacity * elementSize());
if (!newElements) if (!newElements)
return false; return false;
js_memcpy(newElements, elements(), initializedLength() * elementSize()); js_memcpy(newElements, elements(), initializedLength() * elementSize());
} else { } else {
newElements = cx->zone()->pod_realloc<uint8_t>(elements(), oldCapacity * elementSize(), newElements = ReallocateObjectBuffer<uint8_t>(cx, this, elements(),
newCapacity * elementSize()); oldCapacity * elementSize(),
newCapacity * elementSize());
if (!newElements) if (!newElements)
return false; return false;
} }
@ -1299,9 +1344,9 @@ UnboxedArrayObject::shrinkElements(ExclusiveContext* cx, size_t cap)
if (newCapacity >= oldCapacity) if (newCapacity >= oldCapacity)
return; return;
uint8_t* newElements = uint8_t* newElements = ReallocateObjectBuffer<uint8_t>(cx, this, elements(),
cx->zone()->pod_realloc<uint8_t>(elements(), oldCapacity * elementSize(), oldCapacity * elementSize(),
newCapacity * elementSize()); newCapacity * elementSize());
if (!newElements) if (!newElements)
return; return;
@ -1496,7 +1541,8 @@ const Class UnboxedArrayObject::class_ = {
"Array", "Array",
Class::NON_NATIVE | Class::NON_NATIVE |
JSCLASS_IMPLEMENTS_BARRIERS | 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, /* addProperty */
nullptr, /* delProperty */ nullptr, /* delProperty */
nullptr, /* getProperty */ nullptr, /* getProperty */

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

@ -399,6 +399,9 @@ class UnboxedArrayObject : public JSObject
static void objectMoved(JSObject* obj, const JSObject* old); static void objectMoved(JSObject* obj, const JSObject* old);
static void finalize(FreeOp* fop, JSObject* obj); static void finalize(FreeOp* fop, JSObject* obj);
static size_t objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src,
gc::AllocKind allocKind);
uint8_t* elements() { uint8_t* elements() {
return elements_; return elements_;
} }

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

@ -945,7 +945,11 @@ xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prin
return NS_ERROR_XPC_UNEXPECTED; return NS_ERROR_XPC_UNEXPECTED;
// Now check what sort of thing we've got in |proto| // 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); const js::Class* unwrappedClass = js::GetObjectClass(unwrappedProto);
if (IS_WN_CLASS(unwrappedClass) || if (IS_WN_CLASS(unwrappedClass) ||
mozilla::dom::IsDOMClass(Jsvalify(unwrappedClass))) { mozilla::dom::IsDOMClass(Jsvalify(unwrappedClass))) {

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

@ -2553,8 +2553,8 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats& rtStats,
KIND_NONHEAP, rtStats.runtime.gc.nurseryCommitted, KIND_NONHEAP, rtStats.runtime.gc.nurseryCommitted,
"Memory being used by the GC's nursery."); "Memory being used by the GC's nursery.");
RREPORT_BYTES(rtPath + NS_LITERAL_CSTRING("runtime/gc/nursery-huge-slots"), RREPORT_BYTES(rtPath + NS_LITERAL_CSTRING("runtime/gc/nursery-malloced-buffers"),
KIND_NONHEAP, rtStats.runtime.gc.nurseryHugeSlots, KIND_NONHEAP, rtStats.runtime.gc.nurseryMallocedBuffers,
"Out-of-line slots and elements belonging to objects in the " "Out-of-line slots and elements belonging to objects in the "
"nursery."); "nursery.");

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

@ -27,6 +27,7 @@
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "nsJSPrincipals.h" #include "nsJSPrincipals.h"
#include "xpcpublic.h" #include "xpcpublic.h"
#include "xpcprivate.h"
#include "BackstagePass.h" #include "BackstagePass.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
@ -632,6 +633,35 @@ SimulateActivityCallback(JSContext* cx, unsigned argc, jsval* vp)
return true; 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[] = { static const JSFunctionSpec glob_functions[] = {
JS_FS("print", Print, 0,0), JS_FS("print", Print, 0,0),
JS_FS("readline", ReadLine, 1,0), JS_FS("readline", ReadLine, 1,0),
@ -652,6 +682,7 @@ static const JSFunctionSpec glob_functions[] = {
JS_FS("btoa", Btoa, 1,0), JS_FS("btoa", Btoa, 1,0),
JS_FS("setInterruptCallback", SetInterruptCallback, 1,0), JS_FS("setInterruptCallback", SetInterruptCallback, 1,0),
JS_FS("simulateActivityCallback", SimulateActivityCallback, 1,0), JS_FS("simulateActivityCallback", SimulateActivityCallback, 1,0),
JS_FS("registerAppManifest", RegisterAppManifest, 1, 0),
JS_FS_END JS_FS_END
}; };
@ -1341,7 +1372,7 @@ XRE_XPCShellMain(int argc, char** argv, char** envp)
printf("Couldn't get manifest file.\n"); printf("Couldn't get manifest file.\n");
return 1; return 1;
} }
XRE_AddManifestLocation(NS_COMPONENT_LOCATION, lf); XRE_AddManifestLocation(NS_APP_LOCATION, lf);
argc -= 2; argc -= 2;
argv += 2; argv += 2;

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

@ -8,8 +8,8 @@ const Ci = Components.interfaces;
function run_test() { function run_test() {
// Load the component manifests. // Load the component manifests.
Components.manager.autoRegister(do_get_file('../components/native/xpctest.manifest')); registerAppManifest(do_get_file('../components/native/xpctest.manifest'));
Components.manager.autoRegister(do_get_file('../components/js/xpctest.manifest')); registerAppManifest(do_get_file('../components/js/xpctest.manifest'));
// Test for each component. // Test for each component.
test_component_readwrite("@mozilla.org/js/xpc/test/native/ObjectReadWrite;1"); 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() { function run_test() {
// Load the component manifests. // Load the component manifests.
Components.manager.autoRegister(do_get_file('../components/native/xpctest.manifest')); registerAppManifest(do_get_file('../components/native/xpctest.manifest'));
Components.manager.autoRegister(do_get_file('../components/js/xpctest.manifest')); registerAppManifest(do_get_file('../components/js/xpctest.manifest'));
// Test for each component. // Test for each component.
test_component("@mozilla.org/js/xpc/test/native/Params;1"); test_component("@mozilla.org/js/xpc/test/native/Params;1");

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

@ -16,8 +16,8 @@ function getConsoleMessages() {
function run_test() { function run_test() {
// Load the component manifests. // Load the component manifests.
Cm.autoRegister(do_get_file('../components/native/xpctest.manifest')); registerAppManifest(do_get_file('../components/native/xpctest.manifest'));
Cm.autoRegister(do_get_file('../components/js/xpctest.manifest')); registerAppManifest(do_get_file('../components/js/xpctest.manifest'));
// and the tests. // and the tests.
test_simple(); test_simple();

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

@ -55,6 +55,7 @@ support-files =
[test_bug1081990.js] [test_bug1081990.js]
[test_bug1110546.js] [test_bug1110546.js]
[test_bug1150771.js] [test_bug1150771.js]
[test_bug1151385.js]
[test_bug_442086.js] [test_bug_442086.js]
[test_callFunctionWithAsyncStack.js] [test_callFunctionWithAsyncStack.js]
[test_file.js] [test_file.js]

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

@ -2688,7 +2688,7 @@ nsCSSFrameConstructor::ConstructRootFrame()
nsContainerFrame::SyncFrameViewProperties(mPresShell->GetPresContext(), viewportFrame, nsContainerFrame::SyncFrameViewProperties(mPresShell->GetPresContext(), viewportFrame,
viewportPseudoStyle, rootView); viewportPseudoStyle, rootView);
nsContainerFrame::SyncWindowProperties(mPresShell->GetPresContext(), viewportFrame, nsContainerFrame::SyncWindowProperties(mPresShell->GetPresContext(), viewportFrame,
rootView); rootView, nullptr, nsContainerFrame::SET_ASYNC);
// Make it an absolute container for fixed-pos elements // Make it an absolute container for fixed-pos elements
viewportFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN); viewportFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);

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

@ -140,8 +140,8 @@ typedef struct CapturingContentInfo {
// d910f009-d209-74c1-6b04-30c83c051c78 // d910f009-d209-74c1-6b04-30c83c051c78
#define NS_IPRESSHELL_IID \ #define NS_IPRESSHELL_IID \
{ 0xd910f009, 0xd209, 0x74c1, \ { 0x025264c6, 0x0b12, 0x4804, \
{ 0x6b, 0x04, 0x30, 0xc8, 0x3c, 0x05, 0x1c, 0x78 } } { 0xa3, 0x3e, 0xb7, 0x73, 0xf2, 0x19, 0x48, 0x90 } }
// debug VerifyReflow flags // debug VerifyReflow flags
#define VERIFY_REFLOW_ON 0x01 #define VERIFY_REFLOW_ON 0x01
@ -1661,6 +1661,8 @@ public:
bool HasPendingReflow() const bool HasPendingReflow() const
{ return mReflowScheduled || mReflowContinueTimer; } { return mReflowScheduled || mReflowContinueTimer; }
void SyncWindowProperties(nsView* aView);
protected: protected:
friend class nsRefreshDriver; friend class nsRefreshDriver;

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

@ -3116,10 +3116,12 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
} }
} }
#if !defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ANDROID_APZ) #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 // 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 // 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()) { if (dom::Element* element = presShell->GetDocument()->GetDocumentElement()) {
id = nsLayoutUtils::FindOrCreateIDFor(element); id = nsLayoutUtils::FindOrCreateIDFor(element);
} }

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

@ -9245,7 +9245,8 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
target->GetView(), target->GetView(),
boundsRelativeToTarget); boundsRelativeToTarget);
nsContainerFrame::SyncWindowProperties(mPresContext, target, nsContainerFrame::SyncWindowProperties(mPresContext, target,
target->GetView(), &rcx); target->GetView(), &rcx,
nsContainerFrame::SET_ASYNC);
target->DidReflow(mPresContext, nullptr, nsDidReflowStatus::FINISHED); target->DidReflow(mPresContext, nullptr, nsDidReflowStatus::FINISHED);
if (target == rootFrame && size.BSize(wm) == NS_UNCONSTRAINEDSIZE) { if (target == rootFrame && size.BSize(wm) == NS_UNCONSTRAINEDSIZE) {
@ -11081,3 +11082,13 @@ PresShell::ResumePainting()
mPaintingIsFrozen = false; mPaintingIsFrozen = false;
GetPresContext()->RefreshDriver()->Thaw(); 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 void
nsContainerFrame::SyncWindowProperties(nsPresContext* aPresContext, nsContainerFrame::SyncWindowProperties(nsPresContext* aPresContext,
nsIFrame* aFrame, nsIFrame* aFrame,
nsView* aView, nsView* aView,
nsRenderingContext* aRC) nsRenderingContext* aRC,
uint32_t aFlags)
{ {
#ifdef MOZ_XUL #ifdef MOZ_XUL
if (!aView || !nsCSSRendering::IsCanvasFrame(aFrame) || !aView->HasWidget()) if (!aView || !nsCSSRendering::IsCanvasFrame(aFrame) || !aView->HasWidget())
return; return;
nsIWidget* windowWidget = GetPresContextContainerWidget(aPresContext); nsCOMPtr<nsIWidget> windowWidget = GetPresContextContainerWidget(aPresContext);
if (!windowWidget || !IsTopLevelWidget(windowWidget)) if (!windowWidget || !IsTopLevelWidget(windowWidget))
return; return;
@ -650,14 +651,27 @@ nsContainerFrame::SyncWindowProperties(nsPresContext* aPresContext,
if (!rootFrame) if (!rootFrame)
return; return;
if (aFlags & SET_ASYNC) {
aView->SetNeedsWindowPropertiesSync();
return;
}
nsRefPtr<nsPresContext> kungFuDeathGrip(aPresContext);
nsWeakFrame weak(rootFrame);
nsTransparencyMode mode = nsLayoutUtils::GetFrameTransparency(aFrame, 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); viewWidget->SetTransparencyMode(mode);
windowWidget->SetWindowShadowStyle(rootFrame->StyleUIReset()->mWindowShadow); windowWidget->SetWindowShadowStyle(shadow);
if (!aRC) if (!aRC)
return; return;
if (!weak.IsAlive()) {
return;
}
nsBoxLayoutState aState(aPresContext, aRC); nsBoxLayoutState aState(aPresContext, aRC);
nsSize minSize = rootFrame->GetMinSize(aState); nsSize minSize = rootFrame->GetMinSize(aState);
nsSize maxSize = rootFrame->GetMaxSize(aState); nsSize maxSize = rootFrame->GetMaxSize(aState);

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