merge autoland to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-09-14 12:07:02 +02:00
Родитель 1019d4f3c1 8cc38b3dfc
Коммит d2c3fe7fd3
246 изменённых файлов: 2926 добавлений и 2447 удалений

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

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1288460 requires another clobber due to bug 1298779.
Bug 1302429 to fix also bustage.

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

@ -1507,3 +1507,14 @@ pref("print.use_simplify_page", true);
// Space separated list of URLS that are allowed to send objects (instead of
// only strings) through webchannels. This list is duplicated in mobile/android/app/mobile.js
pref("webchannel.allowObject.urlWhitelist", "https://accounts.firefox.com https://content.cdn.mozilla.net https://input.mozilla.org https://support.mozilla.org https://install.mozilla.org");
// Whether or not the browser should scan for unsubmitted
// crash reports, and then show a notification for submitting
// those reports.
#ifdef RELEASE_BUILD
pref("browser.crashReports.unsubmittedCheck.enabled", false);
#else
pref("browser.crashReports.unsubmittedCheck.enabled", true);
#endif
pref("browser.crashReports.unsubmittedCheck.autoSubmit", false);

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

@ -777,13 +777,6 @@ html|*#fullscreen-exit-button {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#click-to-play-plugins-notification");
}
#login-fill-notification {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#login-fill-notification");
}
.login-fill-item {
-moz-binding: url("chrome://passwordmgr/content/login.xml#login");
}
.plugin-popupnotification-centeritem {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#plugin-popupnotification-center-item");
@ -1185,10 +1178,6 @@ toolbarpaletteitem[place="palette"][hidden] {
display: none;
}
#login-fill-doorhanger:not([inDetailView]) > #login-fill-clickcapturer {
pointer-events: none;
}
.popup-notification-invalid-input {
box-shadow: 0 0 1.5px 1px red;
}

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

@ -718,8 +718,6 @@
tooltiptext="&urlbar.addonsNotificationAnchor.tooltip;"/>
<image id="indexedDB-notification-icon" class="notification-anchor-icon indexedDB-icon" role="button"
tooltiptext="&urlbar.indexedDBNotificationAnchor.tooltip;"/>
<image id="login-fill-notification-icon" class="notification-anchor-icon login-icon" role="button"
tooltiptext="&urlbar.loginFillNotificationAnchor.tooltip;"/>
<image id="password-notification-icon" class="notification-anchor-icon login-icon" role="button"
tooltiptext="&urlbar.passwordNotificationAnchor.tooltip;"/>
<image id="plugins-notification-icon" class="notification-anchor-icon plugin-icon" role="button"

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

@ -52,22 +52,6 @@
</popupnotificationcontent>
</popupnotification>
<stack id="login-fill-doorhanger" hidden="true">
<vbox id="login-fill-mainview">
<description id="login-fill-testing"
value="Thanks for testing the login fill doorhanger!"/>
<textbox id="login-fill-filter"/>
<richlistbox id="login-fill-list"/>
</vbox>
<vbox id="login-fill-clickcapturer"/>
<vbox id="login-fill-details">
<textbox id="login-fill-username" readonly="true"/>
<textbox id="login-fill-password" type="password" disabled="true"/>
<hbox>
<button id="login-fill-use" label="Use in form"/>
</hbox>
</vbox>
</stack>
<popupnotification id="addon-progress-notification" hidden="true">
<popupnotificationcontent orient="vertical">

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

@ -2478,16 +2478,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
</handlers>
</binding>
<!-- This is the XBL notification definition for the login fill doorhanger,
which is empty because the actual panel is not implemented inside an XBL
binding, but made of elements added to the notification panel. This
allows accessing the full structure while the panel is hidden. -->
<binding id="login-fill-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
<content>
<children/>
</content>
</binding>
<binding id="splitmenu">
<content>
<xul:hbox anonid="menuitem" flex="1"

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

@ -71,6 +71,8 @@ XPCOMUtils.defineLazyServiceGetter(this, "AlertsService", "@mozilla.org/alerts-s
if (AppConstants.MOZ_CRASHREPORTER) {
XPCOMUtils.defineLazyModuleGetter(this, "PluginCrashReporter",
"resource:///modules/ContentCrashHandlers.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UnsubmittedCrashHandler",
"resource:///modules/ContentCrashHandlers.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CrashSubmit",
"resource://gre/modules/CrashSubmit.jsm");
}
@ -714,6 +716,7 @@ BrowserGlue.prototype = {
TabCrashHandler.init();
if (AppConstants.MOZ_CRASHREPORTER) {
PluginCrashReporter.init();
UnsubmittedCrashHandler.init();
}
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
@ -744,64 +747,6 @@ BrowserGlue.prototype = {
}
},
checkForPendingCrashReports: function() {
// We don't process crash reports older than 28 days, so don't bother submitting them
const PENDING_CRASH_REPORT_DAYS = 28;
if (AppConstants.MOZ_CRASHREPORTER) {
let dateLimit = new Date();
dateLimit.setDate(dateLimit.getDate() - PENDING_CRASH_REPORT_DAYS);
CrashSubmit.pendingIDsAsync(dateLimit).then(
function onSuccess(ids) {
let count = ids.length;
if (count) {
let win = RecentWindow.getMostRecentBrowserWindow();
if (!win) {
return;
}
let nb = win.document.getElementById("global-notificationbox");
let notification = nb.getNotificationWithValue("pending-crash-reports");
if (notification) {
return;
}
let buttons = [
{
label: win.gNavigatorBundle.getString("pendingCrashReports.submitAll"),
callback: function() {
ids.forEach(function(id) {
CrashSubmit.submit(id, {extraExtraKeyVals: {"SubmittedFromInfobar": true}});
});
}
},
{
label: win.gNavigatorBundle.getString("pendingCrashReports.ignoreAll"),
callback: function() {
ids.forEach(function(id) {
CrashSubmit.ignore(id);
});
}
},
{
label: win.gNavigatorBundle.getString("pendingCrashReports.viewAll"),
callback: function() {
win.openUILinkIn("about:crashes", "tab");
return true;
}
}
];
nb.appendNotification(PluralForm.get(count,
win.gNavigatorBundle.getString("pendingCrashReports.label")).replace("#1", count),
"pending-crash-reports",
"chrome://browser/skin/tab-crashed.svg",
nb.PRIORITY_INFO_HIGH, buttons);
}
},
function onError(err) {
Cu.reportError(err);
}
);
}
},
_onSafeModeRestart: function BG_onSafeModeRestart() {
// prompt the user to confirm
let strings = gBrowserBundle;
@ -1070,10 +1015,6 @@ BrowserGlue.prototype = {
this._checkForOldBuildUpdates();
if (!AppConstants.RELEASE_BUILD) {
this.checkForPendingCrashReports();
}
CaptivePortalWatcher.init();
AutoCompletePopup.init();

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

@ -60,10 +60,7 @@ var gAdvancedPane = {
setEventListener("submitHealthReportBox", "command",
gAdvancedPane.updateSubmitHealthReport);
}
if (AppConstants.MOZ_CRASHREPORTER) {
setEventListener("submitCrashesBox", "command",
gAdvancedPane.updateSubmitCrashes);
}
setEventListener("connectionSettings", "command",
gAdvancedPane.showConnections);
setEventListener("clearCacheButton", "command",
@ -243,28 +240,6 @@ var gAdvancedPane = {
{
this._setupLearnMoreLink("toolkit.crashreporter.infoURL",
"crashReporterLearnMore");
var checkbox = document.getElementById("submitCrashesBox");
try {
var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"].
getService(Components.interfaces.nsICrashReporter);
checkbox.checked = cr.submitReports;
} catch (e) {
checkbox.style.display = "none";
}
},
/**
*
*/
updateSubmitCrashes: function ()
{
var checkbox = document.getElementById("submitCrashesBox");
try {
var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"].
getService(Components.interfaces.nsICrashReporter);
cr.submitReports = checkbox.checked;
} catch (e) { }
},
/**

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

@ -54,6 +54,13 @@
type="bool"/>
#endif
<!-- Data Choices tab -->
#ifdef MOZ_CRASHREPORTER
<preference id="browser.crashReports.unsubmittedCheck.autoSubmit"
name="browser.crashReports.unsubmittedCheck.autoSubmit"
type="bool"/>
#endif
<!-- Network tab -->
<preference id="browser.cache.disk.capacity"
name="browser.cache.disk.capacity"
@ -229,11 +236,13 @@
#ifdef MOZ_CRASHREPORTER
<groupbox>
<caption>
<checkbox id="submitCrashesBox" label="&enableCrashReporter.label;"
accesskey="&enableCrashReporter.accesskey;"/>
<checkbox id="automaticallySubmitCrashesBox"
preference="browser.crashReports.unsubmittedCheck.autoSubmit"
label="&alwaysSubmitCrashReports.label;"
accesskey="&alwaysSubmitCrashReports.accesskey;"/>
</caption>
<hbox class="indent">
<label flex="1">&crashReporterDesc.label;</label>
<label flex="1">&crashReporterDesc2.label;</label>
<spacer flex="10"/>
<label id="crashReporterLearnMore"
class="text-link">&crashReporterLearnMore.label;</label>

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

@ -29,11 +29,11 @@
"unpack": true
},
{
"version": "Visual Studio 2015 Update 2 / SDK 10.0.10586.0/212",
"size": 332442800,
"digest": "995394a4a515c7cb0f8595f26f5395361a638870dd0bbfcc22193fe1d98a0c47126057d5999cc494f3f3eac5cb49160e79757c468f83ee5797298e286ef6252c",
"version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",
"size": 326656969,
"digest": "babc414ffc0457d27f5a1ed24a8e4873afbe2f1c1a4075469a27c005e1babc3b2a788f643f825efedff95b79686664c67ec4340ed535487168a3482e68559bc7",
"algorithm": "sha512",
"filename": "vs2015u2.zip",
"filename": "vs2015u3.zip",
"unpack": true
}
]

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

@ -30,11 +30,11 @@
"unpack": true
},
{
"version": "Visual Studio 2015 Update 2 / SDK 10.0.10586.0/212",
"size": 332442800,
"digest": "995394a4a515c7cb0f8595f26f5395361a638870dd0bbfcc22193fe1d98a0c47126057d5999cc494f3f3eac5cb49160e79757c468f83ee5797298e286ef6252c",
"version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",
"size": 326656969,
"digest": "babc414ffc0457d27f5a1ed24a8e4873afbe2f1c1a4075469a27c005e1babc3b2a788f643f825efedff95b79686664c67ec4340ed535487168a3482e68559bc7",
"algorithm": "sha512",
"filename": "vs2015u2.zip",
"filename": "vs2015u3.zip",
"unpack": true
}
]

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

@ -211,7 +211,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY urlbar.geolocationNotificationAnchor.tooltip "Open location request panel">
<!ENTITY urlbar.addonsNotificationAnchor.tooltip "Open add-on installation message panel">
<!ENTITY urlbar.indexedDBNotificationAnchor.tooltip "Open offline storage message panel">
<!ENTITY urlbar.loginFillNotificationAnchor.tooltip "Manage your login information">
<!ENTITY urlbar.passwordNotificationAnchor.tooltip "Open save password message panel">
<!ENTITY urlbar.pluginsNotificationAnchor.tooltip "Manage plug-in use">
<!ENTITY urlbar.webNotificationAnchor.tooltip "Change whether you can receive notifications from the site">

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

@ -730,10 +730,10 @@ tabgroups.migration.tabGroupBookmarkFolderName = Bookmarked Tab Groups
# LOCALIZATION NOTE (pendingCrashReports.label): Semi-colon list of plural forms
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
# #1 is the number of pending crash reports
pendingCrashReports.label = You have an unsubmitted crash report;You have #1 unsubmitted crash reports
pendingCrashReports2.label = You have an unsent crash report;You have #1 unsent crash reports
pendingCrashReports.viewAll = View
pendingCrashReports.submitAll = Submit
pendingCrashReports.ignoreAll = Ignore
pendingCrashReports.send = Send
pendingCrashReports.alwaysSend = Always Send
decoder.noCodecs.button = Learn how
decoder.noCodecs.accesskey = L

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

@ -40,10 +40,10 @@
<!ENTITY enableTelemetryData.accesskey "T">
<!ENTITY telemetryLearnMore.label "Learn More">
<!ENTITY crashReporterDesc.label "&brandShortName; submits crash reports to help &vendorShortName; make your browser more stable and secure">
<!ENTITY enableCrashReporter.label "Enable Crash Reporter">
<!ENTITY enableCrashReporter.accesskey "C">
<!ENTITY crashReporterLearnMore.label "Learn More">
<!ENTITY crashReporterDesc2.label "Crash reports help &vendorShortName; fix problems and make your browser more stable and secure">
<!ENTITY alwaysSubmitCrashReports.label "Allow &brandShortName; to send backlogged crash reports on your behalf">
<!ENTITY alwaysSubmitCrashReports.accesskey "c">
<!ENTITY crashReporterLearnMore.label "Learn More">
<!ENTITY networkTab.label "Network">

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

@ -8,7 +8,9 @@ var Cc = Components.classes;
var Ci = Components.interfaces;
var Cu = Components.utils;
this.EXPORTED_SYMBOLS = [ "TabCrashHandler", "PluginCrashReporter" ];
this.EXPORTED_SYMBOLS = [ "TabCrashHandler",
"PluginCrashReporter",
"UnsubmittedCrashHandler" ];
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
@ -21,6 +23,21 @@ XPCOMUtils.defineLazyModuleGetter(this, "RemotePages",
"resource://gre/modules/RemotePageManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
"resource:///modules/sessionstore/SessionStore.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyGetter(this, "gNavigatorBundle", function() {
const url = "chrome://browser/locale/browser.properties";
return Services.strings.createBundle(url);
});
// We don't process crash reports older than 28 days, so don't bother
// submitting them
const PENDING_CRASH_REPORT_DAYS = 28;
this.TabCrashHandler = {
_crashedTabCount: 0,
@ -319,6 +336,204 @@ this.TabCrashHandler = {
},
}
/**
* This component is responsible for scanning the pending
* crash report directory for reports, and (if enabled), to
* prompt the user to submit those reports. It might also
* submit those reports automatically without prompting if
* the user has opted in.
*/
this.UnsubmittedCrashHandler = {
init() {
if (this.initialized) {
return;
}
this.initialized = true;
let pref = "browser.crashReports.unsubmittedCheck.enabled";
let shouldCheck = Services.prefs.getBoolPref(pref);
if (shouldCheck) {
Services.obs.addObserver(this, "browser-delayed-startup-finished",
false);
}
},
observe(subject, topic, data) {
if (topic != "browser-delayed-startup-finished") {
return;
}
Services.obs.removeObserver(this, topic);
this.checkForUnsubmittedCrashReports();
},
/**
* Scans the profile directory for unsubmitted crash reports
* within the past PENDING_CRASH_REPORT_DAYS days. If it
* finds any, it will, if necessary, attempt to open a notification
* bar to prompt the user to submit them.
*
* @returns Promise
* Resolves after it tries to append a notification on
* the most recent browser window. If a notification
* cannot be shown, will resolve anyways.
*/
checkForUnsubmittedCrashReports: Task.async(function*() {
let dateLimit = new Date();
dateLimit.setDate(dateLimit.getDate() - PENDING_CRASH_REPORT_DAYS);
let reportIDs = [];
try {
reportIDs = yield CrashSubmit.pendingIDsAsync(dateLimit);
} catch (e) {
Cu.reportError(e);
return;
}
if (reportIDs.length) {
if (CrashNotificationBar.autoSubmit) {
CrashNotificationBar.submitReports(reportIDs);
} else {
this.showPendingSubmissionsNotification(reportIDs);
}
}
}),
/**
* Given an array of unsubmitted crash report IDs, try to open
* up a notification asking the user to submit them.
*
* @param reportIDs (Array<string>)
* The Array of report IDs to offer the user to send.
*/
showPendingSubmissionsNotification(reportIDs) {
let count = reportIDs.length;
if (!count) {
return;
}
let messageTemplate =
gNavigatorBundle.GetStringFromName("pendingCrashReports2.label");
let message = PluralForm.get(count, messageTemplate).replace("#1", count);
CrashNotificationBar.show({
notificationID: "pending-crash-reports",
message,
reportIDs,
});
},
};
this.CrashNotificationBar = {
/**
* Attempts to show a notification bar to the user in the most
* recent browser window asking them to submit some crash report
* IDs. If a notification cannot be shown (for example, there
* is no browser window), this method exits silently.
*
* The notification will allow the user to submit their crash
* reports. If the user dismissed the notification, the crash
* reports will be marked to be ignored (though they can
* still be manually submitted via about:crashes).
*
* @param JS Object
* An Object with the following properties:
*
* notificationID (string)
* The ID for the notification to be opened.
*
* message (string)
* The message to be displayed in the notification.
*
* reportIDs (Array<string>)
* The array of report IDs to offer to the user.
*/
show({ notificationID, message, reportIDs }) {
let chromeWin = RecentWindow.getMostRecentBrowserWindow();
if (!chromeWin) {
// Can't show a notification in this case. We'll hopefully
// get another opportunity to have the user submit their
// crash reports later.
return;
}
let nb = chromeWin.document.getElementById("global-notificationbox");
let notification = nb.getNotificationWithValue(notificationID);
if (notification) {
return;
}
let buttons = [{
label: gNavigatorBundle.GetStringFromName("pendingCrashReports.send"),
callback: () => {
this.submitReports(reportIDs);
},
},
{
label: gNavigatorBundle.GetStringFromName("pendingCrashReports.alwaysSend"),
callback: () => {
this.autoSubmit = true;
this.submitReports(reportIDs);
},
},
{
label: gNavigatorBundle.GetStringFromName("pendingCrashReports.viewAll"),
callback: function() {
chromeWin.openUILinkIn("about:crashes", "tab");
return true;
},
}];
let eventCallback = (eventType) => {
if (eventType == "dismissed") {
// The user intentionally dismissed the notification,
// which we interpret as meaning that they don't care
// to submit the reports. We'll ignore these particular
// reports going forward.
reportIDs.forEach(function(reportID) {
CrashSubmit.ignore(reportID);
});
}
};
nb.appendNotification(message, notificationID,
"chrome://browser/skin/tab-crashed.svg",
nb.PRIORITY_INFO_HIGH, buttons,
eventCallback);
},
get autoSubmit() {
return Services.prefs
.getBoolPref("browser.crashReports.unsubmittedCheck.autoSubmit");
},
set autoSubmit(val) {
Services.prefs.setBoolPref("browser.crashReports.unsubmittedCheck.autoSubmit",
val);
},
/**
* Attempt to submit reports to the crash report server. Each
* report will have the "SubmittedFromInfobar" extra key set
* to true.
*
* @param reportIDs (Array<string>)
* The array of reportIDs to submit.
*/
submitReports(reportIDs) {
for (let reportID of reportIDs) {
CrashSubmit.submit(reportID, {
extraExtraKeyVals: {
"SubmittedFromInfobar": true,
},
});
}
},
};
this.PluginCrashReporter = {
/**
* Makes the PluginCrashReporter ready to hear about and

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

@ -1745,7 +1745,6 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton:not(:h
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64);
}
%include ../shared/login-doorhanger.inc.css
%include downloads/indicator.css

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

@ -3155,7 +3155,6 @@ menulist.translate-infobar-element > .menulist-dropmarker {
%include ../../../devtools/client/themes/responsivedesign.inc.css
%include ../../../devtools/client/themes/commandline.inc.css
%include ../shared/plugin-doorhanger.inc.css
%include ../shared/login-doorhanger.inc.css
%include downloads/indicator.css

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

@ -1,79 +0,0 @@
#notification-popup[popupid="login-fill"] > .panel-arrowcontainer > .panel-arrowcontent {
/* Since we display a sliding subview that extends to the border, we cannot
* keep the default padding of arrow panels. We use the same padding in the
* individual content views instead. Since we removed the padding, we also
* have to ensure the contents are clipped to the border box. */
padding: 0;
overflow: hidden;
}
#login-fill-mainview,
#login-fill-details {
padding: var(--panel-arrowcontent-padding);
}
#login-fill-doorhanger[inDetailView] > #login-fill-mainview {
transform: translateX(-14px);
}
#login-fill-mainview,
#login-fill-details {
transition: transform 150ms;
}
#login-fill-doorhanger:not([inDetailView]) > #login-fill-details {
transform: translateX(105%);
}
#login-fill-doorhanger:not([inDetailView]) > #login-fill-details:-moz-locale-dir(rtl) {
transform: translateX(-105%);
}
#login-fill-doorhanger[inDetailView] > #login-fill-clickcapturer {
background-color: hsla(210,4%,10%,.1);
}
#login-fill-testing {
color: #b33;
font-weight: bold;
}
#login-fill-list {
border: 1px solid black;
max-height: 20em;
}
.login-fill-item[disabled] {
color: #888;
background-color: #fff;
}
.login-fill-item[disabled][selected] {
background-color: #eef;
}
.login-hostname {
margin: 4px;
font-weight: bold;
}
.login-fill-item.different-hostname > .login-hostname {
color: #888;
font-style: italic;
}
.login-username {
margin: 4px;
color: #888;
}
#login-fill-details {
padding: 4px;
background: var(--panel-arrowcontent-background);
color: var(--panel-arrowcontent-color);
background-clip: padding-box;
border-left: 1px solid hsla(210,4%,10%,.3);
box-shadow: 0 3px 5px hsla(210,4%,10%,.1),
0 0 7px hsla(210,4%,10%,.1);
margin-inline-start: 38px;
}

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

@ -129,11 +129,6 @@
list-style-image: url(chrome://browser/skin/notification-icons.svg#login-detailed);
}
#login-fill-notification-icon {
/* Temporary solution until the capture and fill doorhangers are unified. */
transform: scaleX(-1);
}
.camera-icon,
.popup-notification-icon[popupid="webRTC-shareDevices"] {
list-style-image: url(chrome://browser/skin/notification-icons.svg#camera);

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

@ -2434,7 +2434,6 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton {
}
}
%include ../shared/login-doorhanger.inc.css
%include downloads/indicator.css

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

@ -51,7 +51,7 @@ Once Visual Studio 2015 Community has been installed, from a checkout
of mozilla-central, run something like the following to produce a ZIP
archive::
$ ./mach python build/windows_toolchain.py create-zip vs2015u2
$ ./mach python build/windows_toolchain.py create-zip vs2015u3
The produced archive will be the argument to ``create-zip`` + ``.zip``.

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

@ -274,9 +274,11 @@ def get_compiler_info(compiler, language):
raise FatalCheckError(
'Unknown compiler or compiler not supported.')
# Metadata emitted by preprocessors such as GCC with LANG=ja_JP.utf-8 may
# have non-ASCII characters. Treat the output as bytearray.
data = {}
for line in result.splitlines():
if line.startswith('%'):
if line.startswith(b'%'):
k, _, v = line.partition(' ')
k = k.lstrip('%')
data[k] = v.replace(' ', '').lstrip('"').rstrip('"')

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

@ -1,6 +1,6 @@
if [ -z "${VSPATH}" ]; then
TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
VSPATH="$(cd ${TOOLTOOL_DIR} && pwd)/vs2015u2"
VSPATH="$(cd ${TOOLTOOL_DIR} && pwd)/vs2015u3"
fi
VSWINPATH="$(cd ${VSPATH} && pwd -W)"
@ -12,8 +12,8 @@ export WIN_UCRT_REDIST_DIR="${VSPATH}/SDK/Redist/ucrt/DLLs/x86"
export PATH="${VSPATH}/VC/bin/amd64_x86:${VSPATH}/VC/bin/amd64:${VSPATH}/VC/bin:${VSPATH}/SDK/bin/x86:${VSPATH}/SDK/bin/x64:${VSPATH}/DIA SDK/bin:${PATH}"
export PATH="${VSPATH}/VC/redist/x86/Microsoft.VC140.CRT:${VSPATH}/VC/redist/x64/Microsoft.VC140.CRT:${VSPATH}/SDK/Redist/ucrt/DLLs/x86:${VSPATH}/SDK/Redist/ucrt/DLLs/x64:${PATH}"
export INCLUDE="${VSPATH}/VC/include:${VSPATH}/VC/atlmfc/include:${VSPATH}/SDK/Include/10.0.10586.0/ucrt:${VSPATH}/SDK/Include/10.0.10586.0/shared:${VSPATH}/SDK/Include/10.0.10586.0/um:${VSPATH}/SDK/Include/10.0.10586.0/winrt:${VSPATH}/DIA SDK/include"
export LIB="${VSPATH}/VC/lib:${VSPATH}/VC/atlmfc/lib:${VSPATH}/SDK/lib/10.0.10586.0/ucrt/x86:${VSPATH}/SDK/lib/10.0.10586.0/um/x86:${VSPATH}/DIA SDK/lib"
export INCLUDE="${VSPATH}/VC/include:${VSPATH}/VC/atlmfc/include:${VSPATH}/SDK/Include/10.0.14393.0/ucrt:${VSPATH}/SDK/Include/10.0.14393.0/shared:${VSPATH}/SDK/Include/10.0.14393.0/um:${VSPATH}/SDK/Include/10.0.14393.0/winrt:${VSPATH}/DIA SDK/include"
export LIB="${VSPATH}/VC/lib:${VSPATH}/VC/atlmfc/lib:${VSPATH}/SDK/lib/10.0.14393.0/ucrt/x86:${VSPATH}/SDK/lib/10.0.14393.0/um/x86:${VSPATH}/DIA SDK/lib"
. $topsrcdir/build/mozconfig.vs-common

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

@ -1,6 +1,6 @@
if [ -z "${VSPATH}" ]; then
TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
VSPATH="$(cd ${TOOLTOOL_DIR} && pwd)/vs2015u2"
VSPATH="$(cd ${TOOLTOOL_DIR} && pwd)/vs2015u3"
fi
VSWINPATH="$(cd ${VSPATH} && pwd -W)"
@ -11,8 +11,8 @@ export WIN_UCRT_REDIST_DIR="${VSPATH}/SDK/Redist/ucrt/DLLs/x64"
export PATH="${VSPATH}/VC/bin/amd64:${VSPATH}/VC/bin:${VSPATH}/SDK/bin/x64:${VSPATH}/VC/redist/x64/Microsoft.VC140.CRT:${VSPATH}/SDK/Redist/ucrt/DLLs/x64:${VSPATH}/DIA SDK/bin/amd64:${PATH}"
export INCLUDE="${VSPATH}/VC/include:${VSPATH}/VC/atlmfc/include:${VSPATH}/SDK/Include/10.0.10586.0/ucrt:${VSPATH}/SDK/Include/10.0.10586.0/shared:${VSPATH}/SDK/Include/10.0.10586.0/um:${VSPATH}/SDK/Include/10.0.10586.0/winrt:${VSPATH}/DIA SDK/include"
export LIB="${VSPATH}/VC/lib/amd64:${VSPATH}/VC/atlmfc/lib/amd64:${VSPATH}/SDK/lib/10.0.10586.0/ucrt/x64:${VSPATH}/SDK/lib/10.0.10586.0/um/x64:${VSPATH}/DIA SDK/lib/amd64"
export INCLUDE="${VSPATH}/VC/include:${VSPATH}/VC/atlmfc/include:${VSPATH}/SDK/Include/10.0.14393.0/ucrt:${VSPATH}/SDK/Include/10.0.14393.0/shared:${VSPATH}/SDK/Include/10.0.14393.0/um:${VSPATH}/SDK/Include/10.0.14393.0/winrt:${VSPATH}/DIA SDK/include"
export LIB="${VSPATH}/VC/lib/amd64:${VSPATH}/VC/atlmfc/lib/amd64:${VSPATH}/SDK/lib/10.0.14393.0/ucrt/x64:${VSPATH}/SDK/lib/10.0.14393.0/um/x64:${VSPATH}/DIA SDK/lib/amd64"
. $topsrcdir/build/mozconfig.vs-common

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

@ -84,7 +84,7 @@ VS_PATTERNS = [
},
]
SDK_RELEASE = '10.0.10586.0'
SDK_RELEASE = '10.0.14393.0'
# Files from the Windows 10 SDK to install.
SDK_PATTERNS = [

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

@ -59,7 +59,11 @@
#pragma warning( push )
#pragma warning( disable : 4275 4530 )
#ifdef __clang__
#include_next <${HEADER}>
#else
#include <${HEADER_PATH}>
#endif
#pragma warning( pop )

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

@ -82,11 +82,11 @@ function addTab(url, win, backgroundTab = false) {
}
let linkedBrowser = tab.linkedBrowser;
linkedBrowser.addEventListener("load", function onLoad() {
linkedBrowser.removeEventListener("load", onLoad, true);
info("Tab added and finished loading: " + url);
done(tab);
}, true);
BrowserTestUtils.browserLoaded(linkedBrowser)
.then(function () {
info("Tab added and finished loading: " + url);
done(tab);
});
});
}

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

@ -81,11 +81,11 @@ function addTab(aUrl, aWindow) {
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
let linkedBrowser = tab.linkedBrowser;
linkedBrowser.addEventListener("load", function onLoad() {
linkedBrowser.removeEventListener("load", onLoad, true);
info("Tab added and finished loading: " + aUrl);
deferred.resolve(tab);
}, true);
BrowserTestUtils.browserLoaded(linkedBrowser)
.then(function () {
info("Tab added and finished loading: " + aUrl);
deferred.resolve(tab);
});
return deferred.promise;
}

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

@ -91,11 +91,11 @@ this.addTab = function addTab(aUrl, aWindow) {
info("Loading frame script with url " + FRAME_SCRIPT_URL + ".");
linkedBrowser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false);
linkedBrowser.addEventListener("load", function onLoad() {
linkedBrowser.removeEventListener("load", onLoad, true);
info("Tab added and finished loading: " + aUrl);
deferred.resolve(tab);
}, true);
BrowserTestUtils.browserLoaded(linkedBrowser)
.then(function () {
info("Tab added and finished loading: " + aUrl);
deferred.resolve(tab);
});
return deferred.promise;
};

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

@ -5,7 +5,9 @@
// Tests that the keybindings for opening and closing the inspector work as expected
// Can probably make this a shared test that tests all of the tools global keybindings
const TEST_URL = "data:text/html,<html><head><title>Test for the " +
"highlighter keybindings</title></head><body>" +
"<h1>Keybindings!</h1></body></html>"
function test()
{
waitForExplicitFinish();
@ -15,17 +17,11 @@ function test()
let inspector;
let keysetMap = { };
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
addTab(TEST_URL).then(function () {
doc = content.document;
node = doc.querySelector("h1");
waitForFocus(setupKeyBindingsTest);
}, true);
content.location = "data:text/html,<html><head><title>Test for the " +
"highlighter keybindings</title></head><body>" +
"<h1>Keybindings!</h1></body></html>";
});
function buildDevtoolsKeysetMap(keyset) {
[].forEach.call(keyset.querySelectorAll("key"), function (key) {

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

@ -3,28 +3,25 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_URL = "data:text/html,test custom host";
function test() {
let {Toolbox} = require("devtools/client/framework/toolbox");
let toolbox, iframe, target, tab;
gBrowser.selectedTab = gBrowser.addTab();
target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox, iframe, target;
window.addEventListener("message", onMessage);
iframe = document.createElement("iframe");
document.documentElement.appendChild(iframe);
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
addTab(TEST_URL).then(function (tab) {
target = TargetFactory.forTab(tab);
let options = {customIframe: iframe};
gDevTools.showToolbox(target, null, Toolbox.HostType.CUSTOM, options)
.then(testCustomHost, console.error)
.then(null, console.error);
}, true);
content.location = "data:text/html,test custom host";
});
function onMessage(event) {
info("onMessage: " + event.data);
@ -50,7 +47,7 @@ function test() {
// toolbox.destroy() returns a singleton promise that ensures
// everything is cleaned up before proceeding.
toolbox.destroy().then(() => {
toolbox = iframe = target = tab = null;
toolbox = iframe = target = null;
finish();
});
}

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

@ -3,19 +3,16 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_URL = "data:text/html,test for dynamically registering and unregistering tools";
var toolbox;
function test()
{
gBrowser.selectedTab = gBrowser.addTab();
let target = TargetFactory.forTab(gBrowser.selectedTab);
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
addTab(TEST_URL).then(tab => {
let target = TargetFactory.forTab(tab);
gDevTools.showToolbox(target).then(testRegister);
}, true);
content.location = "data:text/html,test for dynamically registering and unregistering tools";
});
}
function testRegister(aToolbox)

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

@ -6,23 +6,19 @@
/* import-globals-from shared-head.js */
"use strict";
const TEST_URL = "data:text/html;charset=utf8,test for dynamically " +
"registering and unregistering tools";
var doc = null, toolbox = null, panelWin = null, modifiedPrefs = [];
function test() {
gBrowser.selectedTab = gBrowser.addTab();
let target = TargetFactory.forTab(gBrowser.selectedTab);
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
addTab(TEST_URL).then(tab => {
let target = TargetFactory.forTab(tab);
gDevTools.showToolbox(target)
.then(testSelectTool)
.then(testToggleToolboxButtons)
.then(testPrefsAreRespectedWhenReopeningToolbox)
.then(cleanup, errorHandler);
}, true);
content.location = "data:text/html;charset=utf8,test for dynamically " +
"registering and unregistering tools";
});
}
function testPrefsAreRespectedWhenReopeningToolbox() {

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

@ -8,15 +8,10 @@
const TEST_URI = URL_ROOT + "browser_toolbox_options_disable_js.html";
function test() {
gBrowser.selectedTab = gBrowser.addTab();
let target = TargetFactory.forTab(gBrowser.selectedTab);
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
addTab(TEST_URI).then(tab => {
let target = TargetFactory.forTab(tab);
gDevTools.showToolbox(target).then(testSelectTool);
}, true);
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, TEST_URI);
});
}
function testSelectTool(toolbox) {

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

@ -31,19 +31,15 @@ function test() {
}
function init() {
let tab = gBrowser.selectedTab = gBrowser.addTab();
let target = TargetFactory.forTab(gBrowser.selectedTab);
let linkedBrowser = tab.linkedBrowser;
addTab(TEST_URI).then(tab => {
let target = TargetFactory.forTab(tab);
let linkedBrowser = tab.linkedBrowser;
linkedBrowser.messageManager.loadFrameScript(COMMON_FRAME_SCRIPT_URL, false);
linkedBrowser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false);
linkedBrowser.messageManager.loadFrameScript(COMMON_FRAME_SCRIPT_URL, false);
linkedBrowser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false);
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
gDevTools.showToolbox(target).then(testSelectTool);
}, true);
content.location = TEST_URI;
});
}
function testSelectTool(aToolbox) {

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

@ -3,23 +3,20 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_URL = "data:text/html,test for opening toolbox in different hosts";
var {Toolbox} = require("devtools/client/framework/toolbox");
var toolbox, target, tab1, tab2;
var toolbox, tab1, tab2;
function test() {
gBrowser.selectedTab = tab1 = gBrowser.addTab();
tab2 = gBrowser.addTab();
target = TargetFactory.forTab(gBrowser.selectedTab);
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
addTab(TEST_URL).then(tab => {
tab2 = gBrowser.addTab();
let target = TargetFactory.forTab(tab);
gDevTools.showToolbox(target)
.then(testBottomHost, console.error)
.then(null, console.error);
}, true);
content.location = "data:text/html,test for opening toolbox in different hosts";
});
}
function testBottomHost(aToolbox) {
@ -73,7 +70,7 @@ function cleanup() {
Services.prefs.setCharPref("devtools.toolbox.host", Toolbox.HostType.BOTTOM);
toolbox.destroy().then(function () {
toolbox = target = null;
toolbox = null;
gBrowser.removeCurrentTab();
gBrowser.removeCurrentTab();
finish();

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

@ -3,25 +3,19 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
gBrowser.selectedTab = gBrowser.addTab();
let target = TargetFactory.forTab(gBrowser.selectedTab);
const TEST_URL = "data:text/html,test for toolbox being ready";
const onLoad = Task.async(function* (evt) {
gBrowser.selectedBrowser.removeEventListener("load", onLoad);
add_task(function* () {
let tab = yield addTab(TEST_URL);
let target = TargetFactory.forTab(tab);
const toolbox = yield gDevTools.showToolbox(target, "webconsole");
ok(toolbox.isReady, "toolbox isReady is set");
ok(toolbox.threadClient, "toolbox has a thread client");
const toolbox = yield gDevTools.showToolbox(target, "webconsole");
ok(toolbox.isReady, "toolbox isReady is set");
ok(toolbox.threadClient, "toolbox has a thread client");
const toolbox2 = yield gDevTools.showToolbox(toolbox.target, toolbox.toolId);
is(toolbox2, toolbox, "same toolbox");
const toolbox2 = yield gDevTools.showToolbox(toolbox.target, toolbox.toolId);
is(toolbox2, toolbox, "same toolbox");
yield toolbox.destroy();
gBrowser.removeCurrentTab();
finish();
});
gBrowser.selectedBrowser.addEventListener("load", onLoad, true);
content.location = "data:text/html,test for toolbox being ready";
}
yield toolbox.destroy();
gBrowser.removeCurrentTab();
});

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

@ -30,17 +30,14 @@ function test() {
function openTabs() {
// Open two tabs, select the second
gTab1 = gBrowser.addTab(TAB_URL_1);
gTab1.linkedBrowser.addEventListener("load", function onLoad1(evt) {
gTab1.linkedBrowser.removeEventListener("load", onLoad1);
gTab2 = gBrowser.selectedTab = gBrowser.addTab(TAB_URL_2);
gTab2.linkedBrowser.addEventListener("load", function onLoad2(evt) {
gTab2.linkedBrowser.removeEventListener("load", onLoad2);
addTab(TAB_URL_1).then(tab1 => {
gTab1 = tab1;
addTab(TAB_URL_2).then(tab2 => {
gTab2 = tab2;
connect();
}, true);
}, true);
});
});
}
function connect() {

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

@ -91,12 +91,10 @@ function reloadTab(tabX) {
let def = defer();
let browser = gBrowser.selectedBrowser;
// once() doesn't work here so we use a standard handler instead.
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
BrowserTestUtils.browserLoaded(browser).then(function () {
info("Reloaded tab " + tabX.title);
def.resolve();
}, true);
});
info("Reloading tab " + tabX.title);
let mm = getFrameScript();

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

@ -113,7 +113,7 @@ var addTab = Task.async(function* (url) {
info("Adding a new tab with URL: " + url);
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
yield once(gBrowser.selectedBrowser, "load", true);
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
info("Tab added and finished loading");
@ -142,7 +142,7 @@ var removeTab = Task.async(function* (tab) {
*/
var refreshTab = Task.async(function*(tab) {
info("Refreshing tab.");
const finished = once(gBrowser.selectedBrowser, "load", true);
const finished = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
gBrowser.reloadTab(gBrowser.selectedTab);
yield finished;
info("Tab finished refreshing.");
@ -291,9 +291,7 @@ function waitForTick() {
* @return A promise that resolves when the time is passed
*/
function wait(ms) {
let def = defer();
content.setTimeout(def.resolve, ms);
return def.promise;
return new promise(resolve => setTimeout(resolve, ms));
}
/**

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

@ -52,7 +52,7 @@ add_task(function* () {
EventUtils.synthesizeMouse(searchField, 2, 2,
{type: "contextmenu", button: 2}, win);
yield onContextMenuPopup;
yield waitForClipboard(() => cmdCopy.click(), TEST_INPUT);
yield waitForClipboardPromise(() => cmdCopy.click(), TEST_INPUT);
searchContextMenu.hidePopup();
yield onContextMenuHidden;

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

@ -62,7 +62,7 @@ function* checkCopySelection(view) {
"font-variant-caps: small-caps;[\\r\\n]*";
try {
yield waitForClipboard(() => fireCopyEvent(props[0]),
yield waitForClipboardPromise(() => fireCopyEvent(props[0]),
() => checkClipboardData(expectedPattern));
} catch (e) {
failedClipboard(expectedPattern);
@ -84,7 +84,7 @@ function* checkSelectAll(view) {
"font-variant-caps: small-caps;[\\r\\n]*";
try {
yield waitForClipboard(() => fireCopyEvent(prop),
yield waitForClipboardPromise(() => fireCopyEvent(prop),
() => checkClipboardData(expectedPattern));
} catch (e) {
failedClipboard(expectedPattern);

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

@ -25,7 +25,7 @@ add_task(function* () {
let onTabOpened = once(gBrowser.tabContainer, "TabOpen");
inspector.onFollowLink();
let {target: tab} = yield onTabOpened;
yield waitForTabLoad(tab);
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
ok(true, "A new tab opened");
is(tab.linkedBrowser.currentURI.spec, URL_ROOT + "doc_markup_tooltip.png",
@ -67,16 +67,3 @@ add_task(function* () {
is(inspector.selection.nodeFront.tagName.toLowerCase(), "output",
"The <output> node is still selected");
});
function waitForTabLoad(tab) {
let def = defer();
tab.addEventListener("load", function onLoad(e) {
// Skip load event for about:blank
if (tab.linkedBrowser.currentURI.spec === "about:blank") {
return;
}
tab.removeEventListener("load", onLoad);
def.resolve();
});
return def.promise;
}

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

@ -58,19 +58,6 @@ add_task(function* () {
yield followLinkNoNewNode(linkEl, true, inspector);
});
function waitForTabLoad(tab) {
let def = defer();
tab.addEventListener("load", function onLoad() {
// Skip load event for about:blank
if (tab.linkedBrowser.currentURI.spec === "about:blank") {
return;
}
tab.removeEventListener("load", onLoad);
def.resolve();
});
return def.promise;
}
function performMouseDown(linkEl, metactrl) {
let evt = linkEl.ownerDocument.createEvent("MouseEvents");
@ -95,7 +82,7 @@ function* followLinkWaitForTab(linkEl, isMetaClick, expectedTabURI) {
let onTabOpened = once(gBrowser.tabContainer, "TabOpen");
performMouseDown(linkEl, isMetaClick);
let {target} = yield onTabOpened;
yield waitForTabLoad(target);
yield BrowserTestUtils.browserLoaded(target.linkedBrowser);
ok(true, "A new tab opened");
is(target.linkedBrowser.currentURI.spec, expectedTabURI,
"The URL for the new tab is correct");

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

@ -271,18 +271,6 @@ function searchUsingSelectorSearch(selector, inspector) {
EventUtils.sendKey("return", inspector.panelWin);
}
/**
* This shouldn't be used in the tests, but is useful when writing new tests or
* debugging existing tests in order to introduce delays in the test steps
* @param {Number} ms The time to wait
* @return A promise that resolves when the time is passed
*/
function wait(ms) {
let def = defer();
setTimeout(def.resolve, ms);
return def.promise;
}
/**
* Check to see if the inspector menu items for editing are disabled.
* Things like Edit As HTML, Delete Node, etc.

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

@ -267,7 +267,7 @@ function* checkCopyStyle(view, node, menuItemLabel, expectedPattern, visible) {
visible.copyRule);
try {
yield waitForClipboard(() => menuItem.click(),
yield waitForClipboardPromise(() => menuItem.click(),
() => checkClipboardData(expectedPattern));
} catch (e) {
failedClipboard(expectedPattern);

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

@ -51,7 +51,7 @@ add_task(function* () {
EventUtils.synthesizeMouse(searchField, 2, 2,
{type: "contextmenu", button: 2}, win);
yield onContextMenuPopup;
yield waitForClipboard(() => cmdCopy.click(), TEST_INPUT);
yield waitForClipboardPromise(() => cmdCopy.click(), TEST_INPUT);
searchContextMenu.hidePopup();
yield onContextMenuHidden;

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

@ -75,7 +75,7 @@ function* checkCopySelection(view) {
"Copy menu item is displayed as expected");
try {
yield waitForClipboard(() => menuitemCopy.click(),
yield waitForClipboardPromise(() => menuitemCopy.click(),
() => checkClipboardData(expectedPattern));
} catch (e) {
failedClipboard(expectedPattern);
@ -109,7 +109,7 @@ function* checkSelectAll(view) {
"Copy menu item is displayed as expected");
try {
yield waitForClipboard(() => menuitemCopy.click(),
yield waitForClipboardPromise(() => menuitemCopy.click(),
() => checkClipboardData(expectedPattern));
} catch (e) {
failedClipboard(expectedPattern);
@ -137,7 +137,7 @@ function* checkCopyEditorValue(view) {
"Copy menu item is displayed as expected");
try {
yield waitForClipboard(() => menuitemCopy.click(),
yield waitForClipboardPromise(() => menuitemCopy.click(),
() => checkClipboardData(expectedPattern));
} catch (e) {
failedClipboard(expectedPattern);

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

@ -39,7 +39,7 @@ function* testCopyToClipboard(inspector, view) {
ok(menuitemCopyColor.visible, "Copy color is visible");
yield waitForClipboard(() => menuitemCopyColor.click(),
yield waitForClipboardPromise(() => menuitemCopyColor.click(),
"#123ABC");
EventUtils.synthesizeKey("VK_ESCAPE", { });

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

@ -87,12 +87,12 @@ function* testCopyUrlToClipboard({view, inspector}, type, selector, expected) {
if (type == "data-uri") {
info("Click Copy Data URI and wait for clipboard");
yield waitForClipboard(() => {
yield waitForClipboardPromise(() => {
return menuitemCopyImageDataUrl.click();
}, expected);
} else {
info("Click Copy URL and wait for clipboard");
yield waitForClipboard(() => {
yield waitForClipboardPromise(() => {
return menuitemCopyUrl.click();
}, expected);
}

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

@ -23,7 +23,7 @@ add_task(function* () {
info("Make sure to wait until the eyedropper is done taking a screenshot of the page");
yield waitForElementAttributeSet("root", "drawn", helper);
yield waitForClipboard(() => {
yield waitForClipboardPromise(() => {
info("Activate the eyedropper so the background color is copied");
EventUtils.synthesizeKey("VK_RETURN", {});
}, "#FF0000");

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

@ -34,7 +34,7 @@ function* setSelectionNodeFront(node, inspector) {
function* checkClipboard(expectedText, node) {
try {
yield waitForClipboard(() => fireCopyEvent(node), expectedText);
yield waitForClipboardPromise(() => fireCopyEvent(node), expectedText);
ok(true, "Clipboard successfully filled with : " + expectedText);
} catch (e) {
ok(false, "Clipboard could not be filled with the expected text : " +

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

@ -44,6 +44,6 @@ add_task(function* () {
let item = allMenuItems.find(i => i.id === id);
ok(item, "The popup has a " + desc + " menu item.");
yield waitForClipboard(() => item.click(), text);
yield waitForClipboardPromise(() => item.click(), text);
}
});

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

@ -50,7 +50,7 @@ add_task(function* () {
EventUtils.synthesizeMouse(searchBox, 2, 2,
{type: "contextmenu", button: 2}, win);
yield onContextMenuPopup;
yield waitForClipboard(() => cmdCopy.click(), TEST_INPUT);
yield waitForClipboardPromise(() => cmdCopy.click(), TEST_INPUT);
searchContextMenu.hidePopup();
yield onContextMenuHidden;

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

@ -618,23 +618,6 @@ function waitForStyleEditor(toolbox, href) {
return def.promise;
}
/**
* @see SimpleTest.waitForClipboard
*
* @param {Function} setup
* Function to execute before checking for the
* clipboard content
* @param {String|Function} expected
* An expected string or validator function
* @return a promise that resolves when the expected string has been found or
* the validator function has returned true, rejects otherwise.
*/
function waitForClipboard(setup, expected) {
let def = defer();
SimpleTest.waitForClipboard(expected, setup, def.resolve, def.reject);
return def.promise;
}
/**
* Checks if document's active element is within the given element.
* @param {HTMLDocument} doc document with active element in question
@ -662,8 +645,7 @@ var waitForTab = Task.async(function* () {
info("Waiting for a tab to open");
yield once(gBrowser.tabContainer, "TabOpen");
let tab = gBrowser.selectedTab;
let browser = tab.linkedBrowser;
yield once(browser, "load", true);
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
info("The tab load completed");
return tab;
});

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

@ -57,15 +57,13 @@ function addTab(url) {
info("Adding a new tab with URL: '" + url + "'");
let def = promise.defer();
let tab = gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(function () {
info("URL '" + url + "' loading complete");
waitForFocus(() => {
def.resolve(tab);
}, content);
}, true);
content.location = url;
});
return def.promise;
}

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

@ -195,18 +195,12 @@ var addTab = Task.async(function* (url) {
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
let browser = tab.linkedBrowser;
yield once(browser, "load", true);
yield BrowserTestUtils.browserLoaded(browser);
info("URL '" + url + "' loading complete");
return tab;
});
function wait(ms) {
let def = promise.defer();
setTimeout(def.resolve, ms);
return def.promise;
}
/**
* Waits for the next load to complete in the current browser.
*

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

@ -76,11 +76,10 @@ function addTab(aUrl, aWindow) {
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
let linkedBrowser = tab.linkedBrowser;
linkedBrowser.addEventListener("load", function onLoad() {
linkedBrowser.removeEventListener("load", onLoad, true);
BrowserTestUtils.browserLoaded(linkedBrowser).then(function () {
info("Tab added and finished loading: " + aUrl);
deferred.resolve(tab);
}, true);
});
return deferred.promise;
}

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

@ -12,14 +12,7 @@ function test() {
requestLongerTimeout(3);
waitForExplicitFinish();
let tab = gBrowser.addTab();
gBrowser.selectedTab = tab;
let browser = gBrowser.getBrowserForTab(tab);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
runCodeMirrorTest(browser);
}, true);
browser.loadURI(URI);
addTab(URI).then(function (tab) {
runCodeMirrorTest(tab.linkedBrowser);
});
}

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

@ -79,13 +79,10 @@ let inspector;
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
addTab(TEST_URI).then(function () {
doc = content.document;
runTests();
}, true);
content.location = TEST_URI;
});
}
function runTests() {

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

@ -11,14 +11,7 @@ function test() {
requestLongerTimeout(4);
waitForExplicitFinish();
let tab = gBrowser.addTab();
gBrowser.selectedTab = tab;
let browser = gBrowser.getBrowserForTab(tab);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
runCodeMirrorTest(browser);
}, true);
browser.loadURI(URI);
addTab(URI).then(function (tab) {
runCodeMirrorTest(tab.linkedBrowser);
});
}

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

@ -22,18 +22,16 @@ SimpleTest.registerCleanupFunction(() => {
function addTab(url, callback) {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
content.location = url;
gBrowser.selectedTab = gBrowser.addTab(url);
let tab = gBrowser.selectedTab;
let browser = gBrowser.getBrowserForTab(tab);
function onTabLoad() {
browser.removeEventListener("load", onTabLoad, true);
callback(browser, tab, browser.contentDocument);
}
browser.addEventListener("load", onTabLoad, true);
return BrowserTestUtils.browserLoaded(browser).then(function () {
if (typeof(callback) == "function") {
callback(browser, tab, browser.contentDocument);
}
return tab;
});
}
function promiseTab(url) {

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

@ -29,11 +29,11 @@ var addTab = function (url, win) {
let targetBrowser = targetWindow.gBrowser;
let tab = targetBrowser.selectedTab = targetBrowser.addTab(url);
targetBrowser.selectedBrowser.addEventListener("load", function onload() {
targetBrowser.selectedBrowser.removeEventListener("load", onload, true);
info("URL '" + url + "' loading complete");
def.resolve(tab);
}, true);
BrowserTestUtils.browserLoaded(targetBrowser.selectedBrowser)
.then(function () {
info("URL '" + url + "' loading complete");
def.resolve(tab);
});
return def.promise;
};

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

@ -73,11 +73,10 @@ function addTab(aUrl, aWindow) {
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
let linkedBrowser = tab.linkedBrowser;
linkedBrowser.addEventListener("load", function onLoad() {
linkedBrowser.removeEventListener("load", onLoad, true);
BrowserTestUtils.browserLoaded(linkedBrowser).then(function () {
info("Tab added and finished loading: " + aUrl);
deferred.resolve(tab);
}, true);
});
return deferred.promise;
}

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

@ -167,11 +167,10 @@ function addTab(aUrl, aWindow) {
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
let linkedBrowser = tab.linkedBrowser;
linkedBrowser.addEventListener("load", function onLoad() {
linkedBrowser.removeEventListener("load", onLoad, true);
BrowserTestUtils.browserLoaded(linkedBrowser).then(function () {
info("Tab added and finished loading: " + aUrl);
deferred.resolve(tab);
}, true);
});
return deferred.promise;
}

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

@ -65,7 +65,7 @@ add_task(function* () {
is(mouseDownHandled, 1, "The mousedown event was handled once before navigation");
info("Navigating to a new page");
let loaded = once(gBrowser.selectedBrowser, "load", true);
let loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
content.location = TEST_URL_2;
yield loaded;
doc = gBrowser.selectedBrowser.contentWindow.document;

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

@ -33,7 +33,7 @@ waitForExplicitFinish();
var addTab = Task.async(function* (url) {
info(`Adding a new tab with URL: ${url}`);
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
yield once(gBrowser.selectedBrowser, "load", true);
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
info(`Tab added and URL ${url} loaded`);

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

@ -18,14 +18,6 @@ test(function(t) {
assert_equals(animation.id, 'anim', 'animation.id reflects the value set');
}, 'Animation.id for CSS Animations');
test(function(t) {
var div = addDiv(t);
var animation = div.animate({}, 100 * MS_PER_SEC);
assert_equals(animation.id, '', 'id for CSS Animation is initially empty');
animation.id = 'anim'
assert_equals(animation.id, 'anim', 'animation.id reflects the value set');
}, 'Animation.id for CSS Animations');
done();
</script>
</body>

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

@ -5,7 +5,7 @@
<script>
'use strict';
async_test(function(t) {
promise_test(function(t) {
var div = addDiv(t, { style: 'margin-left: 0px' });
flushComputedStyle(div);
@ -14,17 +14,16 @@ async_test(function(t) {
flushComputedStyle(div);
var animation = div.getAnimations()[0];
animation.ready.then(waitForFrame).then(t.step_func(function() {
return animation.ready.then(waitForFrame).then(function() {
assert_not_equals(getComputedStyle(div).marginLeft, '1000px',
'transform style is animated before cancelling');
animation.cancel();
assert_equals(getComputedStyle(div).marginLeft, div.style.marginLeft,
'transform style is no longer animated after cancelling');
t.done();
}));
});
}, 'Animated style is cleared after cancelling a running CSS transition');
async_test(function(t) {
promise_test(function(t) {
var div = addDiv(t, { style: 'margin-left: 0px' });
flushComputedStyle(div);
@ -32,24 +31,22 @@ async_test(function(t) {
div.style.marginLeft = '1000px';
flushComputedStyle(div);
div.addEventListener('transitionend', t.step_func(function() {
div.addEventListener('transitionend', function() {
assert_unreached('Got unexpected end event on cancelled transition');
}));
});
var animation = div.getAnimations()[0];
animation.ready.then(t.step_func(function() {
return animation.ready.then(function() {
// Seek to just before the end then cancel
animation.currentTime = 99.9 * 1000;
animation.cancel();
// Then wait a couple of frames and check that no event was dispatched
return waitForAnimationFrames(2);
})).then(t.step_func(function() {
t.done();
}));
});
}, 'Cancelled CSS transitions do not dispatch events');
async_test(function(t) {
promise_test(function(t) {
var div = addDiv(t, { style: 'margin-left: 0px' });
flushComputedStyle(div);
@ -58,7 +55,7 @@ async_test(function(t) {
flushComputedStyle(div);
var animation = div.getAnimations()[0];
animation.ready.then(t.step_func(function() {
return animation.ready.then(function() {
animation.cancel();
assert_equals(getComputedStyle(div).marginLeft, '1000px',
'margin-left style is not animated after cancelling');
@ -66,14 +63,13 @@ async_test(function(t) {
assert_equals(getComputedStyle(div).marginLeft, '0px',
'margin-left style is animated after re-starting transition');
return animation.ready;
})).then(t.step_func(function() {
}).then(function() {
assert_equals(animation.playState, 'running',
'Transition succeeds in running after being re-started');
t.done();
}));
});
}, 'After cancelling a transition, it can still be re-used');
async_test(function(t) {
promise_test(function(t) {
var div = addDiv(t, { style: 'margin-left: 0px' });
flushComputedStyle(div);
@ -82,7 +78,7 @@ async_test(function(t) {
flushComputedStyle(div);
var animation = div.getAnimations()[0];
animation.ready.then(t.step_func(function() {
return animation.ready.then(function() {
animation.finish();
animation.cancel();
assert_equals(getComputedStyle(div).marginLeft, '1000px',
@ -91,11 +87,10 @@ async_test(function(t) {
assert_equals(getComputedStyle(div).marginLeft, '0px',
'margin-left style is animated after re-starting transition');
return animation.ready;
})).then(t.step_func(function() {
}).then(function() {
assert_equals(animation.playState, 'running',
'Transition succeeds in running after being re-started');
t.done();
}));
});
}, 'After cancelling a finished transition, it can still be re-used');
test(function(t) {
@ -123,6 +118,20 @@ test(function(t) {
}, 'After cancelling a transition, updating transition properties doesn\'t make'
+ ' it live again');
test(function(t) {
var div = addDiv(t, { style: 'margin-left: 0px' });
flushComputedStyle(div);
div.style.transition = 'margin-left 100s';
div.style.marginLeft = '1000px';
flushComputedStyle(div);
var animation = div.getAnimations()[0];
div.style.display = 'none';
assert_equals(animation.playState, 'idle');
assert_equals(getComputedStyle(div).marginLeft, '1000px');
}, 'Setting display:none on an element cancels its transitions');
done();
</script>
</body>

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

@ -84,7 +84,7 @@ skip-if = android_version == '18' #Android 4.3 aws only; bug 1030942
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
[test_webgl_compressed_texture_es3.html]
[test_webgl_disjoint_timer_query.html]
fail-if = (os == 'win' && (os_version == '6.1' || os_version == '6.2'))
fail-if = (os == 'win' && (os_version == '6.1' || os_version == '6.2' || os_version == '10.0'))
[test_webgl_force_enable.html]
[test_webgl_request_context.html]
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests

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

@ -4341,7 +4341,7 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
}
if (mIsEncrypted) {
if (!mMediaSource && Preferences::GetBool("media.eme.mse-only", true)) {
DecodeError();
DecodeError(NS_ERROR_DOM_MEDIA_FATAL_ERR);
return;
}
@ -4416,7 +4416,7 @@ void HTMLMediaElement::NetworkError()
Error(nsIDOMMediaError::MEDIA_ERR_NETWORK);
}
void HTMLMediaElement::DecodeError()
void HTMLMediaElement::DecodeError(const MediaResult& aError)
{
nsAutoString src;
GetCurrentSrc(src);
@ -4440,7 +4440,7 @@ void HTMLMediaElement::DecodeError()
NS_WARNING("Should know the source we were loading from!");
}
} else {
Error(nsIDOMMediaError::MEDIA_ERR_DECODE);
Error(nsIDOMMediaError::MEDIA_ERR_DECODE, aError);
}
}
@ -4454,7 +4454,8 @@ void HTMLMediaElement::LoadAborted()
Error(nsIDOMMediaError::MEDIA_ERR_ABORTED);
}
void HTMLMediaElement::Error(uint16_t aErrorCode)
void HTMLMediaElement::Error(uint16_t aErrorCode,
const MediaResult& aErrorDetails)
{
NS_ASSERTION(aErrorCode == nsIDOMMediaError::MEDIA_ERR_DECODE ||
aErrorCode == nsIDOMMediaError::MEDIA_ERR_NETWORK ||
@ -4467,8 +4468,12 @@ void HTMLMediaElement::Error(uint16_t aErrorCode)
if (mError) {
return;
}
nsCString message;
if (NS_FAILED(aErrorDetails)) {
message = aErrorDetails.Description();
}
mError = new MediaError(this, aErrorCode, message);
mError = new MediaError(this, aErrorCode);
DispatchAsyncEvent(NS_LITERAL_STRING("error"));
if (mReadyState == nsIDOMHTMLMediaElement::HAVE_NOTHING) {
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY);

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

@ -179,7 +179,7 @@ public:
// Called by the video decoder object, on the main thread, when the
// resource has a decode error during metadata loading or decoding.
virtual void DecodeError() final override;
virtual void DecodeError(const MediaResult& aError) final override;
// Return true if error attribute is not null.
virtual bool HasError() const final override;
@ -1116,7 +1116,7 @@ protected:
* Resets the media element for an error condition as per aErrorCode.
* aErrorCode must be one of nsIDOMHTMLMediaError codes.
*/
void Error(uint16_t aErrorCode);
void Error(uint16_t aErrorCode, const MediaResult& aErrorDetails = NS_OK);
/**
* Returns the URL spec of the currentSrc.

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

@ -21,9 +21,11 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaError)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMediaError)
NS_INTERFACE_MAP_END
MediaError::MediaError(HTMLMediaElement* aParent, uint16_t aCode)
MediaError::MediaError(HTMLMediaElement* aParent, uint16_t aCode,
const nsACString& aMessage)
: mParent(aParent)
, mCode(aCode)
, mMessage(aMessage)
{
}
@ -35,6 +37,12 @@ NS_IMETHODIMP MediaError::GetCode(uint16_t* aCode)
return NS_OK;
}
NS_IMETHODIMP MediaError::GetMessage(nsAString& aResult)
{
CopyUTF8toUTF16(mMessage, aResult);
return NS_OK;
}
JSObject*
MediaError::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{

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

@ -22,7 +22,8 @@ class MediaError final : public nsIDOMMediaError,
~MediaError() {}
public:
MediaError(HTMLMediaElement* aParent, uint16_t aCode);
MediaError(HTMLMediaElement* aParent, uint16_t aCode,
const nsACString& aMessage = nsCString());
// nsISupports
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -48,6 +49,8 @@ private:
// Error code
const uint16_t mCode;
// Error details;
const nsCString mMessage;
};
} // namespace dom

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

@ -12,11 +12,11 @@ interface nsIDOMMediaError : nsISupports
the user agent at the user's requet */
const unsigned short MEDIA_ERR_ABORTED = 1;
/* A network error of some description caused the
/* A network error of some description caused the
user agent to stop downloading the media resource */
const unsigned short MEDIA_ERR_NETWORK = 2;
/* An error of some description occurred while decoding
/* An error of some description occurred while decoding
the media resource */
const unsigned short MEDIA_ERR_DECODE = 3;
@ -24,4 +24,6 @@ interface nsIDOMMediaError : nsISupports
const unsigned short MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
readonly attribute unsigned short code;
readonly attribute DOMString message;
};

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

@ -1312,6 +1312,16 @@ StartMacOSContentSandbox()
MOZ_CRASH("Failed to get NS_OS_TEMP_DIR path");
}
nsCOMPtr<nsIFile> profileDir;
ContentChild::GetSingleton()->GetProfileDir(getter_AddRefs(profileDir));
nsCString profileDirPath;
if (profileDir) {
rv = profileDir->GetNativePath(profileDirPath);
if (NS_FAILED(rv) || profileDirPath.IsEmpty()) {
MOZ_CRASH("Failed to get profile path");
}
}
MacSandboxInfo info;
info.type = MacSandboxType_Content;
info.level = info.level = sandboxLevel;
@ -1320,6 +1330,13 @@ StartMacOSContentSandbox()
info.appDir.assign(appDir.get());
info.appTempDir.assign(tempDirPath.get());
if (profileDir) {
info.hasSandboxedProfile = true;
info.profileDir.assign(profileDirPath.get());
} else {
info.hasSandboxedProfile = false;
}
std::string err;
if (!mozilla::StartMacSandbox(info, err)) {
NS_WARNING(err.c_str());

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

@ -21,6 +21,9 @@
#include "nsWeakPtr.h"
#include "nsIWindowProvider.h"
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
#include "nsIFile.h"
#endif
struct ChromePackage;
class nsIObserver;
@ -114,6 +117,19 @@ public:
void GetProcessName(nsACString& aName) const;
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
void GetProfileDir(nsIFile** aProfileDir) const
{
*aProfileDir = mProfileDir;
NS_IF_ADDREF(*aProfileDir);
}
void SetProfileDir(nsIFile* aProfileDir)
{
mProfileDir = aProfileDir;
}
#endif
bool IsAlive() const;
bool IsShuttingDown() const;
@ -681,6 +697,10 @@ private:
nsCOMPtr<nsIDomainPolicy> mPolicy;
nsCOMPtr<nsITimer> mForceKillTimer;
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
nsCOMPtr<nsIFile> mProfileDir;
#endif
// Hashtable to keep track of the pending GetFilesHelper objects.
// This GetFilesHelperChild objects are removed when RecvGetFilesResponse is
// received.

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

@ -114,6 +114,21 @@ ContentProcess::SetAppDir(const nsACString& aPath)
mXREEmbed.SetAppDir(aPath);
}
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
void
ContentProcess::SetProfile(const nsACString& aProfile)
{
bool flag;
nsresult rv =
XRE_GetFileFromPath(aProfile.BeginReading(), getter_AddRefs(mProfileDir));
if (NS_FAILED(rv) ||
NS_FAILED(mProfileDir->Exists(&flag)) || !flag) {
NS_WARNING("Invalid profile directory passed to content process.");
mProfileDir = nullptr;
}
}
#endif
bool
ContentProcess::Init()
{
@ -124,6 +139,10 @@ ContentProcess::Init()
mContent.InitXPCOM();
mContent.InitGraphicsDeviceData();
#if (defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
mContent.SetProfileDir(mProfileDir);
#endif
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
SetUpSandboxEnvironment();
#endif

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

@ -39,9 +39,18 @@ public:
void SetAppDir(const nsACString& aPath);
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
void SetProfile(const nsACString& aProfile);
#endif
private:
ContentChild mContent;
mozilla::ipc::ScopedXREEmbed mXREEmbed;
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
nsCOMPtr<nsIFile> mProfileDir;
#endif
#if defined(XP_WIN)
// This object initializes and configures COM.
mozilla::mscom::MainThreadRuntime mCOMRuntime;

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

@ -318,7 +318,7 @@ ADTSDemuxer::Init()
ADTSLOG("Init() failure: waiting for data");
return InitPromise::CreateAndReject(
DemuxerFailureReason::DEMUXER_ERROR, __func__);
NS_ERROR_DOM_MEDIA_METADATA_ERR, __func__);
}
ADTSLOG("Init() successful");
@ -515,10 +515,7 @@ ADTSTrackDemuxer::GetSamples(int32_t aNumSamples)
aNumSamples, mOffset, mNumParsedFrames, mFrameIndex, mTotalFrameLen,
mSamplesPerFrame, mSamplesPerSecond, mChannels);
if (!aNumSamples) {
return SamplesPromise::CreateAndReject(
DemuxerFailureReason::DEMUXER_ERROR, __func__);
}
MOZ_ASSERT(aNumSamples);
RefPtr<SamplesHolder> frames = new SamplesHolder();
@ -540,7 +537,7 @@ ADTSTrackDemuxer::GetSamples(int32_t aNumSamples)
if (frames->mSamples.IsEmpty()) {
return SamplesPromise::CreateAndReject(
DemuxerFailureReason::END_OF_STREAM, __func__);
NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
}
return SamplesPromise::CreateAndResolve(frames, __func__);
@ -562,7 +559,7 @@ ADTSTrackDemuxer::SkipToNextRandomAccessPoint(media::TimeUnit aTimeThreshold)
{
// Will not be called for audio-only resources.
return SkipAccessPointPromise::CreateAndReject(
SkipFailureHolder(DemuxerFailureReason::DEMUXER_ERROR, 0), __func__);
SkipFailureHolder(NS_ERROR_DOM_MEDIA_DEMUXER_ERR, 0), __func__);
}
int64_t

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

@ -61,7 +61,7 @@ AccurateSeekTask::Discard()
AssertOwnerThread();
// Disconnect MDSM.
RejectIfExist(__func__);
RejectIfExist(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
// Disconnect MediaDecoderReaderWrapper.
mSeekRequest.DisconnectIfExists();
@ -120,7 +120,7 @@ AccurateSeekTask::DropAudioUpToSeekTarget(MediaData* aSample)
CheckedInt64 sampleDuration = FramesToUsecs(audio->mFrames, mAudioRate);
if (!sampleDuration.isValid()) {
return NS_ERROR_FAILURE;
return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
}
if (audio->mTime + sampleDuration.value() <= mTarget.GetTime().ToMicroseconds()) {
@ -154,7 +154,7 @@ AccurateSeekTask::DropAudioUpToSeekTarget(MediaData* aSample)
CheckedInt64 framesToPrune =
UsecsToFrames(mTarget.GetTime().ToMicroseconds() - audio->mTime, mAudioRate);
if (!framesToPrune.isValid()) {
return NS_ERROR_FAILURE;
return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
}
if (framesToPrune.value() > audio->mFrames) {
// We've messed up somehow. Don't try to trim frames, the |frames|
@ -174,7 +174,7 @@ AccurateSeekTask::DropAudioUpToSeekTarget(MediaData* aSample)
frames * channels * sizeof(AudioDataValue));
CheckedInt64 duration = FramesToUsecs(frames, mAudioRate);
if (!duration.isValid()) {
return NS_ERROR_FAILURE;
return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
}
RefPtr<AudioData> data(new AudioData(audio->mOffset,
mTarget.GetTime().ToMicroseconds(),
@ -260,7 +260,7 @@ AccurateSeekTask::OnSeekRejected(nsresult aResult)
mSeekRequest.Complete();
MOZ_ASSERT(NS_FAILED(aResult), "Cancels should also disconnect mSeekRequest");
RejectIfExist(__func__);
RejectIfExist(aResult, __func__);
}
void
@ -308,10 +308,13 @@ AccurateSeekTask::OnAudioDecoded(MediaData* aAudioSample)
// Non-precise seek; we can stop the seek at the first sample.
mSeekedAudioData = audio;
mDoneAudioSeeking = true;
} else if (NS_FAILED(DropAudioUpToSeekTarget(audio))) {
CancelCallbacks();
RejectIfExist(__func__);
return;
} else {
nsresult rv = DropAudioUpToSeekTarget(audio);
if (NS_FAILED(rv)) {
CancelCallbacks();
RejectIfExist(rv, __func__);
return;
}
}
if (!mDoneAudioSeeking) {
@ -323,33 +326,26 @@ AccurateSeekTask::OnAudioDecoded(MediaData* aAudioSample)
void
AccurateSeekTask::OnNotDecoded(MediaData::Type aType,
MediaDecoderReader::NotDecodedReason aReason)
const MediaResult& aError)
{
AssertOwnerThread();
MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished");
SAMPLE_LOG("OnNotDecoded type=%d reason=%u", aType, aReason);
SAMPLE_LOG("OnNotDecoded type=%d reason=%u", aType, aError.Code());
// Ignore pending requests from video-only seek.
if (aType == MediaData::AUDIO_DATA && mTarget.IsVideoOnly()) {
return;
}
if (aReason == MediaDecoderReader::DECODE_ERROR) {
// If this is a decode error, delegate to the generic error path.
CancelCallbacks();
RejectIfExist(__func__);
return;
}
// If the decoder is waiting for data, we tell it to call us back when the
// data arrives.
if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
if (aError == NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
mReader->WaitForData(aType);
return;
}
if (aReason == MediaDecoderReader::CANCELED) {
if (aError == NS_ERROR_DOM_MEDIA_CANCELED) {
if (aType == MediaData::AUDIO_DATA) {
RequestAudioData();
} else {
@ -358,7 +354,7 @@ AccurateSeekTask::OnNotDecoded(MediaData::Type aType,
return;
}
if (aReason == MediaDecoderReader::END_OF_STREAM) {
if (aError == NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
if (aType == MediaData::AUDIO_DATA) {
mIsAudioQueueFinished = true;
mDoneAudioSeeking = true;
@ -372,7 +368,12 @@ AccurateSeekTask::OnNotDecoded(MediaData::Type aType,
}
}
MaybeFinishSeek();
return;
}
// This is a decode error, delegate to the generic error path.
CancelCallbacks();
RejectIfExist(aError, __func__);
}
void
@ -395,10 +396,13 @@ AccurateSeekTask::OnVideoDecoded(MediaData* aVideoSample)
// Non-precise seek. We can stop the seek at the first sample.
mSeekedVideoData = video;
mDoneVideoSeeking = true;
} else if (NS_FAILED(DropVideoUpToSeekTarget(video.get()))) {
CancelCallbacks();
RejectIfExist(__func__);
return;
} else {
nsresult rv = DropVideoUpToSeekTarget(video.get());
if (NS_FAILED(rv)) {
CancelCallbacks();
RejectIfExist(rv, __func__);
return;
}
}
if (!mDoneVideoSeeking) {
@ -419,7 +423,7 @@ AccurateSeekTask::SetCallbacks()
OnAudioDecoded(aData.as<MediaData*>());
} else {
OnNotDecoded(MediaData::AUDIO_DATA,
aData.as<MediaDecoderReader::NotDecodedReason>());
aData.as<MediaResult>());
}
});
@ -430,7 +434,7 @@ AccurateSeekTask::SetCallbacks()
OnVideoDecoded(Get<0>(aData.as<Type>()));
} else {
OnNotDecoded(MediaData::VIDEO_DATA,
aData.as<MediaDecoderReader::NotDecodedReason>());
aData.as<MediaResult>());
}
});

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

@ -50,7 +50,7 @@ private:
void OnVideoDecoded(MediaData* aVideoSample);
void OnNotDecoded(MediaData::Type, MediaDecoderReader::NotDecodedReason);
void OnNotDecoded(MediaData::Type, const MediaResult&);
void SetCallbacks();

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

@ -169,7 +169,7 @@ BenchmarkPlayback::DemuxSamples()
}
DemuxNextSample();
},
[this, ref](DemuxerFailureReason aReason) { MainThreadShutdown(); });
[this, ref](const MediaResult& aError) { MainThreadShutdown(); });
}
void
@ -190,9 +190,9 @@ BenchmarkPlayback::DemuxNextSample()
Dispatch(NS_NewRunnableFunction([this, ref]() { DemuxNextSample(); }));
}
},
[this, ref](DemuxerFailureReason aReason) {
switch (aReason) {
case DemuxerFailureReason::END_OF_STREAM:
[this, ref](const MediaResult& aError) {
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
InitDecoder(Move(*mTrackDemuxer->GetInfo()));
break;
default:
@ -218,7 +218,7 @@ BenchmarkPlayback::InitDecoder(TrackInfo&& aInfo)
[this, ref](TrackInfo::TrackType aTrackType) {
InputExhausted();
},
[this, ref](MediaDataDecoder::DecoderFailureReason aReason) {
[this, ref](MediaResult aError) {
MainThreadShutdown();
});
}
@ -281,7 +281,7 @@ BenchmarkPlayback::Output(MediaData* aData)
}
void
BenchmarkPlayback::Error(MediaDataDecoderError aError)
BenchmarkPlayback::Error(const MediaResult& aError)
{
RefPtr<Benchmark> ref(mMainThreadState);
Dispatch(NS_NewRunnableFunction([this, ref]() { MainThreadShutdown(); }));

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

@ -32,7 +32,7 @@ class BenchmarkPlayback : public QueueObject, private MediaDataDecoderCallback
// MediaDataDecoderCallback
// Those methods are called on the MediaDataDecoder's task queue.
void Output(MediaData* aData) override;
void Error(MediaDataDecoderError aError) override;
void Error(const MediaResult& aError) override;
void InputExhausted() override;
void DrainComplete() override;
bool OnReaderTaskQueue() override;

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

@ -55,7 +55,7 @@ MP3Demuxer::Init() {
MP3LOG("MP3Demuxer::Init() failure: waiting for data");
return InitPromise::CreateAndReject(
DemuxerFailureReason::DEMUXER_ERROR, __func__);
NS_ERROR_DOM_MEDIA_METADATA_ERR, __func__);
}
MP3LOG("MP3Demuxer::Init() successful");
@ -276,7 +276,7 @@ MP3TrackDemuxer::GetSamples(int32_t aNumSamples) {
if (!aNumSamples) {
return SamplesPromise::CreateAndReject(
DemuxerFailureReason::DEMUXER_ERROR, __func__);
NS_ERROR_DOM_MEDIA_DEMUXER_ERR, __func__);
}
RefPtr<SamplesHolder> frames = new SamplesHolder();
@ -300,7 +300,7 @@ MP3TrackDemuxer::GetSamples(int32_t aNumSamples) {
if (frames->mSamples.IsEmpty()) {
return SamplesPromise::CreateAndReject(
DemuxerFailureReason::END_OF_STREAM, __func__);
NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
}
return SamplesPromise::CreateAndResolve(frames, __func__);
}
@ -317,7 +317,7 @@ RefPtr<MP3TrackDemuxer::SkipAccessPointPromise>
MP3TrackDemuxer::SkipToNextRandomAccessPoint(TimeUnit aTimeThreshold) {
// Will not be called for audio-only resources.
return SkipAccessPointPromise::CreateAndReject(
SkipFailureHolder(DemuxerFailureReason::DEMUXER_ERROR, 0), __func__);
SkipFailureHolder(NS_ERROR_DOM_MEDIA_DEMUXER_ERR, 0), __func__);
}
int64_t

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

@ -12,6 +12,7 @@
#include "MediaData.h"
#include "MediaInfo.h"
#include "MediaResult.h"
#include "TimeUnits.h"
#include "nsISupportsImpl.h"
#include "mozilla/RefPtr.h"
@ -22,16 +23,6 @@ namespace mozilla {
class MediaTrackDemuxer;
class TrackMetadataHolder;
enum class DemuxerFailureReason : int8_t
{
WAITING_FOR_DATA,
END_OF_STREAM,
DEMUXER_ERROR,
CANCELED,
SHUTDOWN,
};
// Allows reading the media data: to retrieve the metadata and demux samples.
// MediaDataDemuxer isn't designed to be thread safe.
// When used by the MediaFormatDecoder, care is taken to ensure that the demuxer
@ -41,7 +32,7 @@ class MediaDataDemuxer
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDataDemuxer)
typedef MozPromise<nsresult, DemuxerFailureReason, /* IsExclusive = */ true> InitPromise;
typedef MozPromise<nsresult, MediaResult, /* IsExclusive = */ true> InitPromise;
// Initializes the demuxer. Other methods cannot be called unless
// initialization has completed and succeeded.
@ -120,16 +111,16 @@ public:
class SkipFailureHolder {
public:
SkipFailureHolder(DemuxerFailureReason aFailure, uint32_t aSkipped)
SkipFailureHolder(const MediaResult& aFailure, uint32_t aSkipped)
: mFailure(aFailure)
, mSkipped(aSkipped)
{}
DemuxerFailureReason mFailure;
MediaResult mFailure;
uint32_t mSkipped;
};
typedef MozPromise<media::TimeUnit, DemuxerFailureReason, /* IsExclusive = */ true> SeekPromise;
typedef MozPromise<RefPtr<SamplesHolder>, DemuxerFailureReason, /* IsExclusive = */ true> SamplesPromise;
typedef MozPromise<media::TimeUnit, MediaResult, /* IsExclusive = */ true> SeekPromise;
typedef MozPromise<RefPtr<SamplesHolder>, MediaResult, /* IsExclusive = */ true> SamplesPromise;
typedef MozPromise<uint32_t, SkipFailureHolder, /* IsExclusive = */ true> SkipAccessPointPromise;
// Returns the TrackInfo (a.k.a Track Description) for this track.

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

@ -198,7 +198,7 @@ MediaDecoder::ResourceCallback::NotifyDecodeError()
RefPtr<ResourceCallback> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
if (self->mDecoder) {
self->mDecoder->DecodeError();
self->mDecoder->DecodeError(NS_ERROR_DOM_MEDIA_FATAL_ERR);
}
});
AbstractThread::MainThread()->Dispatch(r.forget());
@ -607,6 +607,7 @@ MediaDecoder::Shutdown()
mMetadataLoadedListener.Disconnect();
mFirstFrameLoadedListener.Disconnect();
mOnPlaybackEvent.Disconnect();
mOnPlaybackErrorEvent.Disconnect();
mOnMediaNotSeekable.Disconnect();
mDecoderStateMachine->BeginShutdown()
@ -661,9 +662,6 @@ MediaDecoder::OnPlaybackEvent(MediaEventType aEvent)
case MediaEventType::SeekStarted:
SeekingStarted();
break;
case MediaEventType::DecodeError:
DecodeError();
break;
case MediaEventType::Invalidate:
Invalidate();
break;
@ -676,6 +674,12 @@ MediaDecoder::OnPlaybackEvent(MediaEventType aEvent)
}
}
void
MediaDecoder::OnPlaybackErrorEvent(const MediaResult& aError)
{
DecodeError(aError);
}
void
MediaDecoder::FinishShutdown()
{
@ -749,6 +753,8 @@ MediaDecoder::SetStateMachineParameters()
mOnPlaybackEvent = mDecoderStateMachine->OnPlaybackEvent().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::OnPlaybackEvent);
mOnPlaybackErrorEvent = mDecoderStateMachine->OnPlaybackErrorEvent().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::OnPlaybackErrorEvent);
mOnMediaNotSeekable = mDecoderStateMachine->OnMediaNotSeekable().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::OnMediaNotSeekable);
}
@ -1006,11 +1012,11 @@ MediaDecoder::NetworkError()
}
void
MediaDecoder::DecodeError()
MediaDecoder::DecodeError(const MediaResult& aError)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsShutdown());
mOwner->DecodeError();
mOwner->DecodeError(aError);
MOZ_ASSERT(IsShutdown());
}

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

@ -436,7 +436,7 @@ private:
int64_t GetDownloadPosition();
// Notifies the element that decoding has failed.
void DecodeError();
void DecodeError(const MediaResult& aError);
// Indicate whether the media is same-origin with the element.
void UpdateSameOriginStatus(bool aSameOrigin);
@ -592,6 +592,7 @@ private:
DataArrivedEvent() override { return &mDataArrivedEvent; }
void OnPlaybackEvent(MediaEventType aEvent);
void OnPlaybackErrorEvent(const MediaResult& aError);
void OnMediaNotSeekable()
{
@ -731,6 +732,7 @@ protected:
MediaEventListener mFirstFrameLoadedListener;
MediaEventListener mOnPlaybackEvent;
MediaEventListener mOnPlaybackErrorEvent;
MediaEventListener mOnMediaNotSeekable;
protected:

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

@ -11,6 +11,7 @@
namespace mozilla {
class VideoFrameContainer;
class MediaResult;
namespace dom {
class HTMLMediaElement;
@ -67,7 +68,7 @@ public:
// resource has a decode error during metadata loading or decoding.
// The decoder owner should call Shutdown() on the decoder and drop the
// reference to the decoder to prevent further calls into the decoder.
virtual void DecodeError() = 0;
virtual void DecodeError(const MediaResult& aError) = 0;
// Return true if media element error attribute is not null.
virtual bool HasError() const = 0;

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

@ -289,12 +289,12 @@ nsresult MediaDecoderReader::ResetDecode(TrackSet aTracks)
{
if (aTracks.contains(TrackInfo::kVideoTrack)) {
VideoQueue().Reset();
mBaseVideoPromise.RejectIfExists(CANCELED, __func__);
mBaseVideoPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
if (aTracks.contains(TrackInfo::kAudioTrack)) {
AudioQueue().Reset();
mBaseAudioPromise.RejectIfExists(CANCELED, __func__);
mBaseAudioPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
return NS_OK;
@ -323,7 +323,7 @@ MediaDecoderReader::DecodeToFirstVideoData()
p->Resolve(self->VideoQueue().PeekFront(), __func__);
}, [p] () {
// We don't have a way to differentiate EOS, error, and shutdown here. :-(
p->Reject(END_OF_STREAM, __func__);
p->Reject(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
});
return p.forget();
@ -360,8 +360,6 @@ MediaDecoderReader::GetBuffered()
RefPtr<MediaDecoderReader::MetadataPromise>
MediaDecoderReader::AsyncReadMetadata()
{
typedef ReadMetadataFailureReason Reason;
MOZ_ASSERT(OnTaskQueue());
DECODER_LOG("MediaDecoderReader::AsyncReadMetadata");
@ -374,7 +372,7 @@ MediaDecoderReader::AsyncReadMetadata()
// error.
if (NS_FAILED(rv) || !metadata->mInfo.HasValidMedia()) {
DECODER_WARN("ReadMetadata failed, rv=%x HasValidMedia=%d", rv, metadata->mInfo.HasValidMedia());
return MetadataPromise::CreateAndReject(Reason::METADATA_ERROR, __func__);
return MetadataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_METADATA_ERR, __func__);
}
// Success!
@ -456,7 +454,7 @@ MediaDecoderReader::RequestVideoData(bool aSkipToNextKeyframe,
RefPtr<VideoData> v = VideoQueue().PopFront();
mBaseVideoPromise.Resolve(v, __func__);
} else if (VideoQueue().IsFinished()) {
mBaseVideoPromise.Reject(END_OF_STREAM, __func__);
mBaseVideoPromise.Reject(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
} else {
MOZ_ASSERT(false, "Dropping this promise on the floor");
}
@ -488,7 +486,9 @@ MediaDecoderReader::RequestAudioData()
RefPtr<AudioData> a = AudioQueue().PopFront();
mBaseAudioPromise.Resolve(a, __func__);
} else if (AudioQueue().IsFinished()) {
mBaseAudioPromise.Reject(mHitAudioDecodeError ? DECODE_ERROR : END_OF_STREAM, __func__);
mBaseAudioPromise.Reject(mHitAudioDecodeError
? NS_ERROR_DOM_MEDIA_FATAL_ERR
: NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
mHitAudioDecodeError = false;
} else {
MOZ_ASSERT(false, "Dropping this promise on the floor");
@ -503,8 +503,8 @@ MediaDecoderReader::Shutdown()
MOZ_ASSERT(OnTaskQueue());
mShutdown = true;
mBaseAudioPromise.RejectIfExists(END_OF_STREAM, __func__);
mBaseVideoPromise.RejectIfExists(END_OF_STREAM, __func__);
mBaseAudioPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
mBaseVideoPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
mDataArrivedListener.DisconnectIfExists();

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

@ -13,6 +13,7 @@
#include "AbstractMediaDecoder.h"
#include "MediaInfo.h"
#include "MediaData.h"
#include "MediaResult.h"
#include "MediaMetadataManager.h"
#include "MediaQueue.h"
#include "MediaTimer.h"
@ -50,11 +51,6 @@ private:
virtual ~MetadataHolder() {}
};
enum class ReadMetadataFailureReason : int8_t
{
METADATA_ERROR
};
// Encapsulates the decoding and reading of media data. Reading can either
// synchronous and done on the calling "decode" thread, or asynchronous and
// performed on a background thread, with the result being returned by
@ -68,19 +64,12 @@ class MediaDecoderReader {
static const bool IsExclusive = true;
public:
enum NotDecodedReason {
END_OF_STREAM,
DECODE_ERROR,
WAITING_FOR_DATA,
CANCELED
};
using TrackSet = EnumSet<TrackInfo::TrackType>;
using MetadataPromise =
MozPromise<RefPtr<MetadataHolder>, ReadMetadataFailureReason, IsExclusive>;
MozPromise<RefPtr<MetadataHolder>, MediaResult, IsExclusive>;
using MediaDataPromise =
MozPromise<RefPtr<MediaData>, NotDecodedReason, IsExclusive>;
MozPromise<RefPtr<MediaData>, MediaResult, IsExclusive>;
using SeekPromise = MozPromise<media::TimeUnit, nsresult, IsExclusive>;
// Note that, conceptually, WaitForData makes sense in a non-exclusive sense.

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

@ -76,22 +76,22 @@ public:
p->Resolve(data, __func__);
},
[p] () {
p->Reject(MediaDecoderReader::CANCELED, __func__);
p->Reject(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
});
return p.forget();
}
template<MediaData::Type SampleType>
void FirstSampleRejected(MediaDecoderReader::NotDecodedReason aReason)
void FirstSampleRejected(const MediaResult& aError)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
if (aReason == MediaDecoderReader::DECODE_ERROR) {
mHaveStartTimePromise.RejectIfExists(false, __func__);
} else if (aReason == MediaDecoderReader::END_OF_STREAM) {
if (aError == NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
LOG("StartTimeRendezvous=%p SampleType(%d) Has no samples.",
this, SampleType);
MaybeSetChannelStartTime<SampleType>(INT64_MAX);
} else if (aError != NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
mHaveStartTimePromise.RejectIfExists(false, __func__);
}
}
@ -200,9 +200,9 @@ MediaDecoderReaderWrapper::RequestAudioData()
aAudioSample->AdjustForStartTime(self->StartTime().ToMicroseconds());
self->mAudioCallback.Notify(AsVariant(aAudioSample));
},
[self] (MediaDecoderReader::NotDecodedReason aReason) {
[self] (const MediaResult& aError) {
self->mAudioDataRequest.Complete();
self->mAudioCallback.Notify(AsVariant(aReason));
self->mAudioCallback.Notify(AsVariant(aError));
}));
}
@ -240,9 +240,9 @@ MediaDecoderReaderWrapper::RequestVideoData(bool aSkipToNextKeyframe,
aVideoSample->AdjustForStartTime(self->StartTime().ToMicroseconds());
self->mVideoCallback.Notify(AsVariant(MakeTuple(aVideoSample, videoDecodeStartTime)));
},
[self] (MediaDecoderReader::NotDecodedReason aReason) {
[self] (const MediaResult& aError) {
self->mVideoDataRequest.Complete();
self->mVideoCallback.Notify(AsVariant(aReason));
self->mVideoCallback.Notify(AsVariant(aError));
}));
}

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

@ -21,8 +21,8 @@ class StartTimeRendezvous;
typedef MozPromise<bool, bool, /* isExclusive = */ false> HaveStartTimePromise;
typedef Variant<MediaData*, MediaDecoderReader::NotDecodedReason> AudioCallbackData;
typedef Variant<Tuple<MediaData*, TimeStamp>, MediaDecoderReader::NotDecodedReason> VideoCallbackData;
typedef Variant<MediaData*, MediaResult> AudioCallbackData;
typedef Variant<Tuple<MediaData*, TimeStamp>, MediaResult> VideoCallbackData;
typedef Variant<MediaData::Type, WaitForDataRejectValue> WaitCallbackData;
/**

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

@ -263,8 +263,8 @@ public:
[this] (MetadataHolder* aMetadata) {
OnMetadataRead(aMetadata);
},
[this] (ReadMetadataFailureReason aReason) {
OnMetadataNotRead(aReason);
[this] (const MediaResult& aError) {
OnMetadataNotRead(aError);
}));
}
@ -355,11 +355,11 @@ private:
SetState(DECODER_STATE_DECODING_FIRSTFRAME);
}
void OnMetadataNotRead(ReadMetadataFailureReason aReason)
void OnMetadataNotRead(const MediaResult& aError)
{
mMetadataRequest.Complete();
SWARN("Decode metadata failed, shutting down decoder");
mMaster->DecodeError();
mMaster->DecodeError(aError);
}
MozPromiseRequestHolder<MediaDecoderReader::MetadataPromise> mMetadataRequest;
@ -979,12 +979,12 @@ MediaDecoderStateMachine::OnVideoPopped(const RefPtr<MediaData>& aSample)
void
MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
MediaDecoderReader::NotDecodedReason aReason)
const MediaResult& aError)
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(mState != DECODER_STATE_SEEKING);
SAMPLE_LOG("OnNotDecoded (aType=%u, aReason=%u)", aType, aReason);
SAMPLE_LOG("OnNotDecoded (aType=%u, aError=%u)", aType, aError.Code());
bool isAudio = aType == MediaData::AUDIO_DATA;
MOZ_ASSERT_IF(!isAudio, aType == MediaData::VIDEO_DATA);
@ -993,15 +993,9 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
return;
}
// If this is a decode error, delegate to the generic error path.
if (aReason == MediaDecoderReader::DECODE_ERROR) {
DecodeError();
return;
}
// If the decoder is waiting for data, we tell it to call us back when the
// data arrives.
if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
if (aError == NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
MOZ_ASSERT(mReader->IsWaitForDataSupported(),
"Readers that send WAITING_FOR_DATA need to implement WaitForData");
mReader->WaitForData(aType);
@ -1017,7 +1011,7 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
return;
}
if (aReason == MediaDecoderReader::CANCELED) {
if (aError == NS_ERROR_DOM_MEDIA_CANCELED) {
if (isAudio) {
EnsureAudioDecodeTaskQueued();
} else {
@ -1026,9 +1020,14 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
return;
}
// If this is a decode error, delegate to the generic error path.
if (aError != NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
DecodeError(aError);
return;
}
// This is an EOS. Finish off the queue, and then handle things based on our
// state.
MOZ_ASSERT(aReason == MediaDecoderReader::END_OF_STREAM);
if (isAudio) {
AudioQueue().Finish();
StopPrerollingAudio();
@ -1219,7 +1218,7 @@ MediaDecoderStateMachine::SetMediaDecoderReaderWrapperCallback()
if (aData.is<MediaData*>()) {
OnAudioDecoded(aData.as<MediaData*>());
} else {
OnNotDecoded(MediaData::AUDIO_DATA, aData.as<MediaDecoderReader::NotDecodedReason>());
OnNotDecoded(MediaData::AUDIO_DATA, aData.as<MediaResult>());
}
});
@ -1230,7 +1229,7 @@ MediaDecoderStateMachine::SetMediaDecoderReaderWrapperCallback()
auto&& v = aData.as<Type>();
OnVideoDecoded(Get<0>(v), Get<1>(v));
} else {
OnNotDecoded(MediaData::VIDEO_DATA, aData.as<MediaDecoderReader::NotDecodedReason>());
OnNotDecoded(MediaData::VIDEO_DATA, aData.as<MediaResult>());
}
});
@ -2083,7 +2082,7 @@ MediaDecoderStateMachine::OnSeekTaskRejected(SeekTaskRejectValue aValue)
StopPrerollingVideo();
}
DecodeError();
DecodeError(aValue.mError);
DiscardSeekTaskIfExist();
}
@ -2292,13 +2291,13 @@ bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs)
}
void
MediaDecoderStateMachine::DecodeError()
MediaDecoderStateMachine::DecodeError(const MediaResult& aError)
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(!IsShutdown());
DECODER_WARN("Decode error");
// Notify the decode error and MediaDecoder will shut down MDSM.
mOnPlaybackEvent.Notify(MediaEventType::DecodeError);
mOnPlaybackErrorEvent.Notify(aError);
}
void
@ -2919,7 +2918,7 @@ MediaDecoderStateMachine::OnMediaSinkVideoError()
if (HasAudio()) {
return;
}
DecodeError();
DecodeError(MediaResult(NS_ERROR_DOM_MEDIA_MEDIASINK_ERR, __func__));
}
void MediaDecoderStateMachine::OnMediaSinkAudioComplete()
@ -2950,7 +2949,7 @@ void MediaDecoderStateMachine::OnMediaSinkAudioError()
// Otherwise notify media decoder/element about this error for it makes
// no sense to play an audio-only file without sound output.
DecodeError();
DecodeError(MediaResult(NS_ERROR_DOM_MEDIA_MEDIASINK_ERR, __func__));
}
#ifdef MOZ_EME

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

@ -119,7 +119,6 @@ enum class MediaEventType : int8_t {
PlaybackStopped,
PlaybackEnded,
SeekStarted,
DecodeError,
Invalidate,
EnterVideoSuspend,
ExitVideoSuspend
@ -245,6 +244,8 @@ public:
MediaEventSource<MediaEventType>&
OnPlaybackEvent() { return mOnPlaybackEvent; }
MediaEventSource<MediaResult>&
OnPlaybackErrorEvent() { return mOnPlaybackErrorEvent; }
size_t SizeOfVideoQueue() const;
@ -344,7 +345,7 @@ private:
// Need to figure out a suitable API name for this case.
void OnAudioDecoded(MediaData* aAudioSample);
void OnVideoDecoded(MediaData* aVideoSample, TimeStamp aDecodeStartTime);
void OnNotDecoded(MediaData::Type aType, MediaDecoderReader::NotDecodedReason aReason);
void OnNotDecoded(MediaData::Type aType, const MediaResult& aError);
// Resets all state related to decoding and playback, emptying all buffers
// and aborting all pending operations on the decode task queue.
@ -481,7 +482,7 @@ protected:
// event to the media element. This begins shutting down the decoder.
// The decoder monitor must be held. This is only called on the
// decode thread.
void DecodeError();
void DecodeError(const MediaResult& aError);
// Dispatches a LoadedMetadataEvent.
// This is threadsafe and can be called on any thread.
@ -892,6 +893,7 @@ private:
MediaDecoderEventVisibility> mFirstFrameLoadedEvent;
MediaEventProducer<MediaEventType> mOnPlaybackEvent;
MediaEventProducer<MediaResult> mOnPlaybackErrorEvent;
// True if audio is offloading.
// Playback will not start when audio is offloading.

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

@ -93,14 +93,14 @@ MediaFormatReader::Shutdown()
MOZ_ASSERT(OnTaskQueue());
mDemuxerInitRequest.DisconnectIfExists();
mMetadataPromise.RejectIfExists(ReadMetadataFailureReason::METADATA_ERROR, __func__);
mSeekPromise.RejectIfExists(NS_ERROR_FAILURE, __func__);
mMetadataPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
mSeekPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
mSkipRequest.DisconnectIfExists();
if (mAudio.mDecoder) {
Reset(TrackInfo::kAudioTrack);
if (mAudio.HasPromise()) {
mAudio.RejectPromise(CANCELED, __func__);
mAudio.RejectPromise(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
mAudio.ShutdownDecoder();
}
@ -119,7 +119,7 @@ MediaFormatReader::Shutdown()
if (mVideo.mDecoder) {
Reset(TrackInfo::kVideoTrack);
if (mVideo.HasPromise()) {
mVideo.RejectPromise(CANCELED, __func__);
mVideo.RejectPromise(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
mVideo.ShutdownDecoder();
}
@ -283,7 +283,7 @@ MediaFormatReader::OnDemuxerInitDone(nsresult)
// We currently only handle the first video track.
mVideo.mTrackDemuxer = mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
if (!mVideo.mTrackDemuxer) {
mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
mMetadataPromise.Reject(NS_ERROR_DOM_MEDIA_METADATA_ERR, __func__);
return;
}
@ -292,7 +292,7 @@ MediaFormatReader::OnDemuxerInitDone(nsresult)
if (videoActive) {
if (platform && !platform->SupportsMimeType(videoInfo->mMimeType, nullptr)) {
// We have no decoder for this track. Error.
mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
mMetadataPromise.Reject(NS_ERROR_DOM_MEDIA_METADATA_ERR, __func__);
return;
}
mInfo.mVideo = *videoInfo->GetAsVideoInfo();
@ -312,7 +312,7 @@ MediaFormatReader::OnDemuxerInitDone(nsresult)
if (audioActive) {
mAudio.mTrackDemuxer = mDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0);
if (!mAudio.mTrackDemuxer) {
mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
mMetadataPromise.Reject(NS_ERROR_DOM_MEDIA_METADATA_ERR, __func__);
return;
}
@ -364,7 +364,7 @@ MediaFormatReader::OnDemuxerInitDone(nsresult)
mDemuxer->IsSeekableOnlyInBufferedRanges();
if (!videoActive && !audioActive) {
mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
mMetadataPromise.Reject(NS_ERROR_DOM_MEDIA_METADATA_ERR, __func__);
return;
}
@ -376,13 +376,13 @@ MediaFormatReader::OnDemuxerInitDone(nsresult)
}
void
MediaFormatReader::OnDemuxerInitFailed(DemuxerFailureReason aFailure)
MediaFormatReader::OnDemuxerInitFailed(const MediaResult& aError)
{
mDemuxerInitRequest.Complete();
mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
mMetadataPromise.Reject(aError, __func__);
}
bool
MediaResult
MediaFormatReader::EnsureDecoderCreated(TrackType aTrack)
{
MOZ_ASSERT(OnTaskQueue());
@ -391,19 +391,17 @@ MediaFormatReader::EnsureDecoderCreated(TrackType aTrack)
auto& decoder = GetDecoderData(aTrack);
if (decoder.mDecoder) {
return true;
return NS_OK;
}
if (!mPlatform) {
mPlatform = new PDMFactory();
NS_ENSURE_TRUE(mPlatform, false);
if (IsEncrypted()) {
#ifdef MOZ_EME
MOZ_ASSERT(mCDMProxy);
mPlatform->SetCDMProxy(mCDMProxy);
#else
// EME not supported.
return false;
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, "EME not supported");
#endif
}
}
@ -443,10 +441,10 @@ MediaFormatReader::EnsureDecoderCreated(TrackType aTrack)
}
if (decoder.mDecoder ) {
decoder.mDescription = decoder.mDecoder->GetDescriptionName();
} else {
decoder.mDescription = "error creating decoder";
return NS_OK;
}
return decoder.mDecoder != nullptr;
decoder.mDescription = "error creating decoder";
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, "error creating decoder");
}
bool
@ -479,11 +477,11 @@ MediaFormatReader::EnsureDecoderInitialized(TrackType aTrack)
self->SetVideoDecodeThreshold();
self->ScheduleUpdate(aTrack);
},
[self, aTrack] (MediaDataDecoder::DecoderFailureReason aResult) {
[self, aTrack] (MediaResult aError) {
auto& decoder = self->GetDecoderData(aTrack);
decoder.mInitPromise.Complete();
decoder.ShutdownDecoder();
self->NotifyError(aTrack);
self->NotifyError(aTrack, aError);
}));
return false;
}
@ -534,21 +532,21 @@ MediaFormatReader::RequestVideoData(bool aSkipToNextKeyframe,
if (!HasVideo()) {
LOG("called with no video track");
return MediaDataPromise::CreateAndReject(DECODE_ERROR, __func__);
return MediaDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
}
if (IsSeeking()) {
LOG("called mid-seek. Rejecting.");
return MediaDataPromise::CreateAndReject(CANCELED, __func__);
return MediaDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
if (mShutdown) {
NS_WARNING("RequestVideoData on shutdown MediaFormatReader!");
return MediaDataPromise::CreateAndReject(CANCELED, __func__);
return MediaDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
if (IsSuspended()) {
return MediaDataPromise::CreateAndReject(CANCELED, __func__);
return MediaDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
media::TimeUnit timeThreshold{media::TimeUnit::FromMicroseconds(aTimeThreshold)};
@ -568,37 +566,33 @@ MediaFormatReader::RequestVideoData(bool aSkipToNextKeyframe,
}
void
MediaFormatReader::OnDemuxFailed(TrackType aTrack, DemuxerFailureReason aFailure)
MediaFormatReader::OnDemuxFailed(TrackType aTrack, const MediaResult& aError)
{
MOZ_ASSERT(OnTaskQueue());
LOG("Failed to demux %s, failure:%d",
aTrack == TrackType::kVideoTrack ? "video" : "audio", aFailure);
LOG("Failed to demux %s, failure:%u",
aTrack == TrackType::kVideoTrack ? "video" : "audio", aError.Code());
auto& decoder = GetDecoderData(aTrack);
decoder.mDemuxRequest.Complete();
switch (aFailure) {
case DemuxerFailureReason::END_OF_STREAM:
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
if (!decoder.mWaitingForData) {
decoder.mNeedDraining = true;
}
NotifyEndOfStream(aTrack);
break;
case DemuxerFailureReason::DEMUXER_ERROR:
NotifyError(aTrack);
break;
case DemuxerFailureReason::WAITING_FOR_DATA:
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
if (!decoder.mWaitingForData) {
decoder.mNeedDraining = true;
}
NotifyWaitingForData(aTrack);
break;
case DemuxerFailureReason::CANCELED: MOZ_FALLTHROUGH;
case DemuxerFailureReason::SHUTDOWN:
case NS_ERROR_DOM_MEDIA_CANCELED:
if (decoder.HasPromise()) {
decoder.RejectPromise(CANCELED, __func__);
decoder.RejectPromise(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
break;
default:
MOZ_ASSERT(false);
NotifyError(aTrack, aError);
break;
}
}
@ -638,21 +632,21 @@ MediaFormatReader::RequestAudioData()
if (!HasAudio()) {
LOG("called with no audio track");
return MediaDataPromise::CreateAndReject(DECODE_ERROR, __func__);
return MediaDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
}
if (IsSuspended()) {
return MediaDataPromise::CreateAndReject(CANCELED, __func__);
return MediaDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
if (IsSeeking()) {
LOG("called mid-seek. Rejecting.");
return MediaDataPromise::CreateAndReject(CANCELED, __func__);
return MediaDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
if (mShutdown) {
NS_WARNING("RequestAudioData on shutdown MediaFormatReader!");
return MediaDataPromise::CreateAndReject(CANCELED, __func__);
return MediaDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
RefPtr<MediaDataPromise> p = mAudio.EnsurePromise(__func__);
@ -723,7 +717,7 @@ MediaFormatReader::NotifyDrainComplete(TrackType aTrack)
}
void
MediaFormatReader::NotifyError(TrackType aTrack, MediaDataDecoderError aError)
MediaFormatReader::NotifyError(TrackType aTrack, const MediaResult& aError)
{
MOZ_ASSERT(OnTaskQueue());
LOGV("%s Decoding error", TrackTypeToStr(aTrack));
@ -938,9 +932,10 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
return;
}
if (!EnsureDecoderCreated(aTrack)) {
MediaResult rv = EnsureDecoderCreated(aTrack);
if (NS_FAILED(rv)) {
NS_WARNING("Error constructing decoders");
NotifyError(aTrack);
NotifyError(aTrack, rv);
return;
}
@ -1052,24 +1047,23 @@ MediaFormatReader::InternalSeek(TrackType aTrack, const InternalSeekTarget& aTar
self->SetVideoDecodeThreshold();
self->ScheduleUpdate(aTrack);
},
[self, aTrack] (DemuxerFailureReason aResult) {
[self, aTrack] (const MediaResult& aError) {
auto& decoder = self->GetDecoderData(aTrack);
decoder.mSeekRequest.Complete();
switch (aResult) {
case DemuxerFailureReason::WAITING_FOR_DATA:
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
self->NotifyWaitingForData(aTrack);
break;
case DemuxerFailureReason::END_OF_STREAM:
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
decoder.mTimeThreshold.reset();
self->NotifyEndOfStream(aTrack);
break;
case DemuxerFailureReason::CANCELED: MOZ_FALLTHROUGH;
case DemuxerFailureReason::SHUTDOWN:
case NS_ERROR_DOM_MEDIA_CANCELED:
decoder.mTimeThreshold.reset();
break;
default:
decoder.mTimeThreshold.reset();
self->NotifyError(aTrack);
self->NotifyError(aTrack, aError);
break;
}
}));
@ -1205,7 +1199,7 @@ MediaFormatReader::Update(TrackType aTrack)
}
} else if (decoder.HasFatalError()) {
LOG("Rejecting %s promise: DECODE_ERROR", TrackTypeToStr(aTrack));
decoder.RejectPromise(DECODE_ERROR, __func__);
decoder.RejectPromise(decoder.mError.ref(), __func__);
return;
} else if (decoder.mDrainComplete) {
bool wasDraining = decoder.mDraining;
@ -1213,7 +1207,7 @@ MediaFormatReader::Update(TrackType aTrack)
decoder.mDraining = false;
if (decoder.mDemuxEOS) {
LOG("Rejecting %s promise: EOS", TrackTypeToStr(aTrack));
decoder.RejectPromise(END_OF_STREAM, __func__);
decoder.RejectPromise(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
} else if (decoder.mWaitingForData) {
if (wasDraining && decoder.mLastSampleTime &&
!decoder.mNextStreamSourceID) {
@ -1226,7 +1220,7 @@ MediaFormatReader::Update(TrackType aTrack)
}
if (!decoder.mReceivedNewData) {
LOG("Rejecting %s promise: WAITING_FOR_DATA", TrackTypeToStr(aTrack));
decoder.RejectPromise(WAITING_FOR_DATA, __func__);
decoder.RejectPromise(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA, __func__);
}
}
// Now that draining has completed, we check if we have received
@ -1243,7 +1237,7 @@ MediaFormatReader::Update(TrackType aTrack)
// There is no more samples left to be decoded and we are already in
// EOS state. We can immediately reject the data promise.
LOG("Rejecting %s promise: EOS", TrackTypeToStr(aTrack));
decoder.RejectPromise(END_OF_STREAM, __func__);
decoder.RejectPromise(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
}
}
@ -1252,14 +1246,13 @@ MediaFormatReader::Update(TrackType aTrack)
return;
}
if (decoder.mError &&
decoder.mError.ref() == MediaDataDecoderError::DECODE_ERROR) {
if (decoder.mError && !decoder.HasFatalError()) {
decoder.mDecodePending = false;
decoder.mError.reset();
if (++decoder.mNumOfConsecutiveError > decoder.mMaxConsecutiveError) {
NotifyError(aTrack);
NotifyError(aTrack, decoder.mError.ref());
return;
}
decoder.mError.reset();
LOG("%s decoded error count %d", TrackTypeToStr(aTrack),
decoder.mNumOfConsecutiveError);
media::TimeUnit nextKeyframe;
@ -1398,7 +1391,7 @@ MediaFormatReader::ResetDecode(TrackSet aTracks)
mVideo.ResetDemuxer();
Reset(TrackInfo::kVideoTrack);
if (mVideo.HasPromise()) {
mVideo.RejectPromise(CANCELED, __func__);
mVideo.RejectPromise(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
}
@ -1406,7 +1399,7 @@ MediaFormatReader::ResetDecode(TrackSet aTracks)
mAudio.ResetDemuxer();
Reset(TrackInfo::kAudioTrack);
if (mAudio.HasPromise()) {
mAudio.RejectPromise(CANCELED, __func__);
mAudio.RejectPromise(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
}
@ -1418,7 +1411,7 @@ MediaFormatReader::Output(TrackType aTrack, MediaData* aSample)
{
if (!aSample) {
NS_WARNING("MediaFormatReader::Output() passed a null sample");
Error(aTrack);
Error(aTrack, MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__));
return;
}
@ -1451,10 +1444,10 @@ MediaFormatReader::InputExhausted(TrackType aTrack)
}
void
MediaFormatReader::Error(TrackType aTrack, MediaDataDecoderError aError)
MediaFormatReader::Error(TrackType aTrack, const MediaResult& aError)
{
RefPtr<nsIRunnable> task =
NewRunnableMethod<TrackType, MediaDataDecoderError>(
NewRunnableMethod<TrackType, MediaResult>(
this, &MediaFormatReader::NotifyError, aTrack, aError);
OwnerThread()->Dispatch(task.forget());
}
@ -1567,9 +1560,9 @@ MediaFormatReader::OnVideoSkipFailed(MediaTrackDemuxer::SkipFailureHolder aFailu
LOG("Skipping failed, skipped %u frames", aFailure.mSkipped);
mSkipRequest.Complete();
switch (aFailure.mFailure) {
case DemuxerFailureReason::END_OF_STREAM: MOZ_FALLTHROUGH;
case DemuxerFailureReason::WAITING_FOR_DATA:
switch (aFailure.mFailure.Code()) {
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
// Some frames may have been output by the decoder since we initiated the
// videoskip process and we know they would be late.
DropDecodedSamples(TrackInfo::kVideoTrack);
@ -1577,14 +1570,13 @@ MediaFormatReader::OnVideoSkipFailed(MediaTrackDemuxer::SkipFailureHolder aFailu
// normally.
ScheduleUpdate(TrackInfo::kVideoTrack);
break;
case DemuxerFailureReason::CANCELED: MOZ_FALLTHROUGH;
case DemuxerFailureReason::SHUTDOWN:
case NS_ERROR_DOM_MEDIA_CANCELED:
if (mVideo.HasPromise()) {
mVideo.RejectPromise(CANCELED, __func__);
mVideo.RejectPromise(aFailure.mFailure, __func__);
}
break;
default:
NotifyError(TrackType::kVideoTrack);
NotifyError(TrackType::kVideoTrack, aFailure.mFailure);
break;
}
}
@ -1696,17 +1688,17 @@ MediaFormatReader::AttemptSeek()
}
void
MediaFormatReader::OnSeekFailed(TrackType aTrack, DemuxerFailureReason aResult)
MediaFormatReader::OnSeekFailed(TrackType aTrack, const MediaResult& aError)
{
MOZ_ASSERT(OnTaskQueue());
LOGV("%s failure:%d", TrackTypeToStr(aTrack), aResult);
LOGV("%s failure:%u", TrackTypeToStr(aTrack), aError.Code());
if (aTrack == TrackType::kVideoTrack) {
mVideo.mSeekRequest.Complete();
} else {
mAudio.mSeekRequest.Complete();
}
if (aResult == DemuxerFailureReason::WAITING_FOR_DATA) {
if (aError == NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
if (HasVideo() && aTrack == TrackType::kAudioTrack &&
mFallbackSeekTime.isSome() &&
mPendingSeekTime.ref() != mFallbackSeekTime.ref()) {
@ -1740,7 +1732,7 @@ MediaFormatReader::OnSeekFailed(TrackType aTrack, DemuxerFailureReason aResult)
}
MOZ_ASSERT(!mVideo.mSeekRequest.Exists() && !mAudio.mSeekRequest.Exists());
mPendingSeekTime.reset();
mSeekPromise.Reject(NS_ERROR_FAILURE, __func__);
mSeekPromise.Reject(aError, __func__);
}
void
@ -1781,10 +1773,10 @@ MediaFormatReader::OnVideoSeekCompleted(media::TimeUnit aTime)
}
void
MediaFormatReader::OnVideoSeekFailed(DemuxerFailureReason aFailure)
MediaFormatReader::OnVideoSeekFailed(const MediaResult& aError)
{
mPreviousDecodedKeyframeTime_us = sNoPreviousDecodedKeyframe;
OnSeekFailed(TrackType::kVideoTrack, aFailure);
OnSeekFailed(TrackType::kVideoTrack, aError);
}
void
@ -1848,9 +1840,9 @@ MediaFormatReader::OnAudioSeekCompleted(media::TimeUnit aTime)
}
void
MediaFormatReader::OnAudioSeekFailed(DemuxerFailureReason aFailure)
MediaFormatReader::OnAudioSeekFailed(const MediaResult& aError)
{
OnSeekFailed(TrackType::kAudioTrack, aFailure);
OnSeekFailed(TrackType::kAudioTrack, aError);
}
media::TimeIntervals

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

@ -117,7 +117,7 @@ private:
void NotifyDemuxer();
void ReturnOutput(MediaData* aData, TrackType aTrack);
bool EnsureDecoderCreated(TrackType aTrack);
MediaResult EnsureDecoderCreated(TrackType aTrack);
bool EnsureDecoderInitialized(TrackType aTrack);
// Enqueues a task to call Update(aTrack) on the decoder task queue.
@ -166,7 +166,7 @@ private:
void NotifyNewOutput(TrackType aTrack, MediaData* aSample);
void NotifyInputExhausted(TrackType aTrack);
void NotifyDrainComplete(TrackType aTrack);
void NotifyError(TrackType aTrack, MediaDataDecoderError aError = MediaDataDecoderError::FATAL_ERROR);
void NotifyError(TrackType aTrack, const MediaResult& aError);
void NotifyWaitingForData(TrackType aTrack);
void NotifyEndOfStream(TrackType aTrack);
@ -179,7 +179,7 @@ private:
// functions.
void Output(TrackType aType, MediaData* aSample);
void InputExhausted(TrackType aTrack);
void Error(TrackType aTrack, MediaDataDecoderError aError = MediaDataDecoderError::FATAL_ERROR);
void Error(TrackType aTrack, const MediaResult& aError);
void Reset(TrackType aTrack);
void DrainComplete(TrackType aTrack);
void DropDecodedSamples(TrackType aTrack);
@ -206,7 +206,7 @@ private:
void InputExhausted() override {
mReader->InputExhausted(mType);
}
void Error(MediaDataDecoderError aError) override {
void Error(const MediaResult& aError) override {
mReader->Error(mType, aError);
}
void DrainComplete() override {
@ -327,10 +327,10 @@ private:
uint32_t mNumOfConsecutiveError;
uint32_t mMaxConsecutiveError;
Maybe<MediaDataDecoderError> mError;
Maybe<MediaResult> mError;
bool HasFatalError() const
{
return mError.isSome() && mError.ref() == MediaDataDecoderError::FATAL_ERROR;
return mError.isSome() && mError.ref() != NS_ERROR_DOM_MEDIA_DECODE_ERR;
}
// If set, all decoded samples prior mTimeThreshold will be dropped.
@ -354,7 +354,7 @@ private:
virtual bool HasPromise() const = 0;
virtual RefPtr<MediaDataPromise> EnsurePromise(const char* aMethodName) = 0;
virtual void ResolvePromise(MediaData* aData, const char* aMethodName) = 0;
virtual void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
virtual void RejectPromise(const MediaResult& aError,
const char* aMethodName) = 0;
// Clear track demuxer related data.
@ -462,11 +462,11 @@ private:
mHasPromise = false;
}
void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
void RejectPromise(const MediaResult& aError,
const char* aMethodName) override
{
MOZ_ASSERT(mOwner->OnTaskQueue());
mPromise.Reject(aReason, aMethodName);
mPromise.Reject(aError, aMethodName);
mHasPromise = false;
}
@ -487,22 +487,22 @@ private:
RefPtr<MediaDataDemuxer> mDemuxer;
bool mDemuxerInitDone;
void OnDemuxerInitDone(nsresult);
void OnDemuxerInitFailed(DemuxerFailureReason aFailure);
void OnDemuxerInitFailed(const MediaResult& aError);
MozPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest;
void OnDemuxFailed(TrackType aTrack, DemuxerFailureReason aFailure);
void OnDemuxFailed(TrackType aTrack, const MediaResult& aError);
void DoDemuxVideo();
void OnVideoDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples);
void OnVideoDemuxFailed(DemuxerFailureReason aFailure)
void OnVideoDemuxFailed(const MediaResult& aError)
{
OnDemuxFailed(TrackType::kVideoTrack, aFailure);
OnDemuxFailed(TrackType::kVideoTrack, aError);
}
void DoDemuxAudio();
void OnAudioDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples);
void OnAudioDemuxFailed(DemuxerFailureReason aFailure)
void OnAudioDemuxFailed(const MediaResult& aError)
{
OnDemuxFailed(TrackType::kAudioTrack, aFailure);
OnDemuxFailed(TrackType::kAudioTrack, aError);
}
void SkipVideoDemuxToNextKeyFrame(media::TimeUnit aTimeThreshold);
@ -550,15 +550,15 @@ private:
}
void ScheduleSeek();
void AttemptSeek();
void OnSeekFailed(TrackType aTrack, DemuxerFailureReason aFailure);
void OnSeekFailed(TrackType aTrack, const MediaResult& aError);
void DoVideoSeek();
void OnVideoSeekCompleted(media::TimeUnit aTime);
void OnVideoSeekFailed(DemuxerFailureReason aFailure);
void OnVideoSeekFailed(const MediaResult& aError);
bool mSeekScheduled;
void DoAudioSeek();
void OnAudioSeekCompleted(media::TimeUnit aTime);
void OnAudioSeekFailed(DemuxerFailureReason aFailure);
void OnAudioSeekFailed(const MediaResult& aError);
// The SeekTarget that was last given to Seek()
SeekTarget mOriginalSeekTarget;
// Temporary seek information while we wait for the data

60
dom/media/MediaResult.h Normal file
Просмотреть файл

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef MediaResult_h_
#define MediaResult_h_
#include "nsError.h"
#include "nsPrintfCString.h"
// MediaResult can be used interchangeably with nsresult.
// It allows to store extra information such as where the error occurred.
// While nsresult is typically passed by value; due to its potential size, using
// MediaResult const references is recommended.
namespace mozilla {
class MediaResult
{
public:
MOZ_IMPLICIT MediaResult(nsresult aResult)
: mCode(aResult)
{
}
MediaResult(nsresult aResult, const nsACString& aMessage)
: mCode(aResult)
, mMessage(aMessage)
{
}
MediaResult(nsresult aResult, const char* aMessage)
: mCode(aResult)
, mMessage(aMessage)
{
}
MediaResult(const MediaResult& aOther) = default;
MediaResult(MediaResult&& aOther) = default;
MediaResult& operator=(const MediaResult& aOther) = default;
MediaResult& operator=(MediaResult&& aOther) = default;
nsresult Code() const { return mCode; }
const nsCString& Message() const { return mMessage; }
// Interoperations with nsresult.
bool operator==(nsresult aResult) const { return aResult == mCode; }
bool operator!=(nsresult aResult) const { return aResult != mCode; }
operator nsresult () const { return mCode; }
nsCString Description() const
{
return nsPrintfCString("0x%08x: %s", mCode, mMessage.get());
}
private:
nsresult mCode;
nsCString mMessage;
};
} // namespace mozilla
#endif // MediaResult_h_

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

@ -53,7 +53,7 @@ NextFrameSeekTask::Discard()
AssertOwnerThread();
// Disconnect MDSM.
RejectIfExist(__func__);
RejectIfExist(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
// Disconnect MediaDecoderReader.
CancelCallbacks();
@ -183,12 +183,12 @@ NextFrameSeekTask::OnAudioDecoded(MediaData* aAudioSample)
}
void
NextFrameSeekTask::OnAudioNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
NextFrameSeekTask::OnAudioNotDecoded(const MediaResult& aError)
{
AssertOwnerThread();
MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished");
SAMPLE_LOG("OnAudioNotDecoded (aReason=%u)", aReason);
SAMPLE_LOG("OnAudioNotDecoded (aError=%u)", aError.Code());
// We don't really handle audio deocde error here. Let MDSM to trigger further
// audio decoding tasks if it needs to play audio, and MDSM will then receive
@ -224,36 +224,36 @@ NextFrameSeekTask::OnVideoDecoded(MediaData* aVideoSample)
}
void
NextFrameSeekTask::OnVideoNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
NextFrameSeekTask::OnVideoNotDecoded(const MediaResult& aError)
{
AssertOwnerThread();
MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished");
SAMPLE_LOG("OnVideoNotDecoded (aReason=%u)", aReason);
SAMPLE_LOG("OnVideoNotDecoded (aError=%u)", aError.Code());
if (aReason == MediaDecoderReader::END_OF_STREAM) {
if (aError == NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
mIsVideoQueueFinished = true;
}
// Video seek not finished.
if (NeedMoreVideo()) {
switch (aReason) {
case MediaDecoderReader::DECODE_ERROR:
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
mReader->WaitForData(MediaData::VIDEO_DATA);
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
RequestVideoData();
break;
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
MOZ_ASSERT(false, "Shouldn't want more data for ended video.");
break;
default:
// We might lose the audio sample after canceling the callbacks.
// However it doesn't really matter because MDSM is gonna shut down
// when seek fails.
CancelCallbacks();
// Reject the promise since we can't finish video seek anyway.
RejectIfExist(__func__);
break;
case MediaDecoderReader::WAITING_FOR_DATA:
mReader->WaitForData(MediaData::VIDEO_DATA);
break;
case MediaDecoderReader::CANCELED:
RequestVideoData();
break;
case MediaDecoderReader::END_OF_STREAM:
MOZ_ASSERT(false, "Shouldn't want more data for ended video.");
RejectIfExist(aError, __func__);
break;
}
return;
@ -274,7 +274,7 @@ NextFrameSeekTask::SetCallbacks()
if (aData.is<MediaData*>()) {
OnAudioDecoded(aData.as<MediaData*>());
} else {
OnAudioNotDecoded(aData.as<MediaDecoderReader::NotDecodedReason>());
OnAudioNotDecoded(aData.as<MediaResult>());
}
});
@ -284,7 +284,7 @@ NextFrameSeekTask::SetCallbacks()
if (aData.is<Type>()) {
OnVideoDecoded(Get<0>(aData.as<Type>()));
} else {
OnVideoNotDecoded(aData.as<MediaDecoderReader::NotDecodedReason>());
OnVideoNotDecoded(aData.as<MediaResult>());
}
});
@ -303,7 +303,7 @@ NextFrameSeekTask::SetCallbacks()
} else {
// Reject if we can't finish video seeking.
CancelCallbacks();
RejectIfExist(__func__);
RejectIfExist(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
return;
}

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

@ -57,11 +57,11 @@ private:
void OnAudioDecoded(MediaData* aAudioSample);
void OnAudioNotDecoded(MediaDecoderReader::NotDecodedReason aReason);
void OnAudioNotDecoded(const MediaResult& aError);
void OnVideoDecoded(MediaData* aVideoSample);
void OnVideoNotDecoded(MediaDecoderReader::NotDecodedReason aReason);
void OnVideoNotDecoded(const MediaResult& aError);
void SetCallbacks();

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