This commit is contained in:
Ryan VanderMeulen 2016-09-01 12:15:35 -04:00
Родитель 3e2ab4cb31 37b200a0c5
Коммит d9f7626454
188 изменённых файлов: 1254 добавлений и 1243 удалений

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

@ -64,10 +64,8 @@ XPCOMUtils.defineLazyServiceGetter(Services, 'captivePortalDetector',
'@mozilla.org/toolkit/captive-detector;1',
'nsICaptivePortalDetector');
if (AppConstants.MOZ_SAFE_BROWSING) {
XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
"resource://gre/modules/SafeBrowsing.jsm");
}
XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
"resource://gre/modules/SafeBrowsing.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SafeMode",
"resource://gre/modules/SafeMode.jsm");
@ -434,11 +432,9 @@ var shell = {
ppmm.addMessageListener("mail-handler", this);
ppmm.addMessageListener("file-picker", this);
if (AppConstants.MOZ_SAFE_BROWSING) {
setTimeout(function() {
SafeBrowsing.init();
}, 5000);
}
setTimeout(function() {
SafeBrowsing.init();
}, 5000);
},
stop: function shell_stop() {

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

@ -17,8 +17,6 @@ MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
# MOZ_APP_DISPLAYNAME is set by branding/configure.sh
MOZ_SAFE_BROWSING=1
MOZ_NO_SMART_CARDS=1
MOZ_APP_STATIC_INI=1
MOZ_NO_EV_CERTS=1

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

@ -24,7 +24,6 @@ MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
# MOZ_APP_DISPLAYNAME is set by branding/configure.sh
MOZ_SAFE_BROWSING=1
MOZ_CAPTIVEDETECT=1
MOZ_NO_SMART_CARDS=1

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

@ -13,10 +13,8 @@
%customizeToolbarDTD;
<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
%placesDTD;
#ifdef MOZ_SAFE_BROWSING
<!ENTITY % safebrowsingDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd">
%safebrowsingDTD;
#endif
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
%aboutHomeDTD;
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">

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

@ -2,9 +2,6 @@
* 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/. */
// Note: this file is not shipped (through jar.mn)
// if MOZ_SAFE_BROWSING is not defined.
var gSafeBrowsing = {
setReportPhishingMenu: function() {

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

@ -763,7 +763,7 @@ html|*#fullscreen-exit-button {
-moz-user-focus: normal;
}
.blocked-permission-icon:not([showing]),
#blocked-permissions-container > .blocked-permission-icon:not([showing]),
.notification-anchor-icon:not([showing]) {
display: none;
}

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

@ -57,10 +57,8 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
["webrtcUI", "resource:///modules/webrtcUI.jsm", ]
].forEach(([name, resource]) => XPCOMUtils.defineLazyModuleGetter(this, name, resource));
if (AppConstants.MOZ_SAFE_BROWSING) {
XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
"resource://gre/modules/SafeBrowsing.jsm");
}
XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
"resource://gre/modules/SafeBrowsing.jsm");
if (AppConstants.MOZ_CRASHREPORTER) {
XPCOMUtils.defineLazyModuleGetter(this, "PluginCrashReporter",
@ -1146,10 +1144,8 @@ var gBrowserInit = {
}
}
if (AppConstants.MOZ_SAFE_BROWSING) {
// Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
setTimeout(function() { SafeBrowsing.init(); }, 2000);
}
// Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
setTimeout(function() { SafeBrowsing.init(); }, 2000);
Services.obs.addObserver(gIdentityHandler, "perm-changed", false);
Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
@ -7377,7 +7373,7 @@ var gIdentityHandler = {
let img = document.createElement("image");
let classes = "identity-popup-permission-icon " + aPermission.id + "-icon";
if (aPermission.state == SitePermissions.BLOCK)
classes += " blocked";
classes += " blocked-permission-icon";
if (aPermission.inUse)
classes += " in-use";
img.setAttribute("class", classes);

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

@ -23,9 +23,7 @@
<script type="application/javascript" src="chrome://browser/content/browser-places.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-plugins.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-refreshblocker.js"/>
#ifdef MOZ_SAFE_BROWSING
<script type="application/javascript" src="chrome://browser/content/browser-safebrowsing.js"/>
#endif
<script type="application/javascript" src="chrome://browser/content/browser-sidebar.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-social.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-syncui.js"/>

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

@ -695,8 +695,11 @@ nsContextMenu.prototype = {
this.target.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
if (request && (request.imageStatus & request.STATUS_SIZE_AVAILABLE))
this.onLoadedImage = true;
if (request && (request.imageStatus & request.STATUS_LOAD_COMPLETE))
if (request &&
(request.imageStatus & request.STATUS_LOAD_COMPLETE) &&
!(request.imageStatus & request.STATUS_ERROR)) {
this.onCompletedImage = true;
}
this.mediaURL = this.target.currentURI.spec;

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

@ -742,8 +742,9 @@ function openTourPage()
function buildHelpMenu()
{
// Enable/disable the "Report Web Forgery" menu item.
if (typeof gSafeBrowsing != "undefined" && AppConstants.MOZ_SAFE_BROWSING)
if (typeof gSafeBrowsing != "undefined") {
gSafeBrowsing.setReportPhishingMenu();
}
}
function isElementVisible(aElement)

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

@ -87,9 +87,7 @@ browser.jar:
content/browser/browser-places.js (content/browser-places.js)
content/browser/browser-plugins.js (content/browser-plugins.js)
content/browser/browser-refreshblocker.js (content/browser-refreshblocker.js)
#ifdef MOZ_SAFE_BROWSING
content/browser/browser-safebrowsing.js (content/browser-safebrowsing.js)
#endif
content/browser/browser-sidebar.js (content/browser-sidebar.js)
content/browser/browser-social.js (content/browser-social.js)
content/browser/browser-syncui.js (content/browser-syncui.js)
@ -191,10 +189,8 @@ browser.jar:
# the following files are browser-specific overrides
* content/browser/license.html (/toolkit/content/license.html)
% override chrome://global/content/license.html chrome://browser/content/license.html
#ifdef MOZ_SAFE_BROWSING
content/browser/report-phishing-overlay.xul (content/report-phishing-overlay.xul)
content/browser/blockedSite.xhtml (content/blockedSite.xhtml)
% overlay chrome://browser/content/browser.xul chrome://browser/content/report-phishing-overlay.xul
#endif
% override chrome://global/content/netError.xhtml chrome://browser/content/aboutNetError.xhtml

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

@ -35,13 +35,11 @@ struct RedirEntry {
URI_SAFE_FOR_UNTRUSTED_CONTENT.
*/
static RedirEntry kRedirMap[] = {
#ifdef MOZ_SAFE_BROWSING
{ "blocked", "chrome://browser/content/blockedSite.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
#endif
{ "certerror", "chrome://browser/content/aboutNetError.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::URI_CAN_LOAD_IN_CHILD |

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

@ -85,9 +85,7 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
{ NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
#endif
{ NS_FEEDSNIFFER_CONTRACTID, &kNS_FEEDSNIFFER_CID },
#ifdef MOZ_SAFE_BROWSING
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "blocked", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#endif
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "certerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "socialerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "providerdirectory", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },

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

@ -50,6 +50,7 @@ EXTRA_JS_MODULES += [
]
BROWSER_CHROME_MANIFESTS += [
'safebrowsing/content/test/browser.ini',
'tests/browser/browser.ini'
]
@ -57,9 +58,6 @@ XPCSHELL_TESTS_MANIFESTS += [
'tests/unit/xpcshell.ini'
]
if CONFIG['MOZ_SAFE_BROWSING']:
BROWSER_CHROME_MANIFESTS += ['safebrowsing/content/test/browser.ini']
with Files('safebrowsing/*'):
BUG_COMPONENT = ('Toolkit', 'Phishing Protection')

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

@ -32,7 +32,6 @@ fi
# Enable building ./signmar and running libmar signature tests
MOZ_ENABLE_SIGNMAR=1
MOZ_SAFE_BROWSING=1
MOZ_APP_VERSION=$FIREFOX_VERSION
MOZ_APP_VERSION_DISPLAY=$FIREFOX_VERSION_DISPLAY
MOZ_EXTENSIONS_DEFAULT=" gio"

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

@ -596,13 +596,11 @@
@RESPATH@/modules/*
; Safe Browsing
#ifdef MOZ_URL_CLASSIFIER
@RESPATH@/components/nsURLClassifier.manifest
@RESPATH@/components/nsUrlClassifierHashCompleter.js
@RESPATH@/components/nsUrlClassifierListManager.js
@RESPATH@/components/nsUrlClassifierLib.js
@RESPATH@/components/url-classifier.xpt
#endif
; Private Browsing
@RESPATH@/components/privatebrowsing.xpt

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

@ -53,10 +53,8 @@
locale/browser/places/bookmarkProperties.properties (%chrome/browser/places/bookmarkProperties.properties)
locale/browser/preferences/selectBookmark.dtd (%chrome/browser/preferences/selectBookmark.dtd)
locale/browser/places/moveBookmarks.dtd (%chrome/browser/places/moveBookmarks.dtd)
#ifdef MOZ_SAFE_BROWSING
locale/browser/safebrowsing/phishing-afterload-warning-message.dtd (%chrome/browser/safebrowsing/phishing-afterload-warning-message.dtd)
locale/browser/safebrowsing/report-phishing.dtd (%chrome/browser/safebrowsing/report-phishing.dtd)
#endif
locale/browser/feeds/subscribe.dtd (%chrome/browser/feeds/subscribe.dtd)
locale/browser/feeds/subscribe.properties (%chrome/browser/feeds/subscribe.properties)
locale/browser/migration/migration.dtd (%chrome/browser/migration/migration.dtd)

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

@ -221,8 +221,8 @@ fi
])
dnl Configure an Android SDK.
dnl Arg 1: target SDK version, like 22.
dnl Arg 2: build tools version, like 22.0.1.
dnl Arg 1: target SDK version, like 23.
dnl Arg 2: list of build-tools versions, like "23.0.3 23.0.1".
AC_DEFUN([MOZ_ANDROID_SDK],
[
@ -254,12 +254,21 @@ case "$target" in
fi
AC_MSG_RESULT([$android_sdk])
android_build_tools="$android_sdk_root"/build-tools/$2
AC_MSG_CHECKING([for Android build-tools version $2])
if test -d "$android_build_tools" -a -f "$android_build_tools/aapt"; then
AC_MSG_RESULT([$android_build_tools])
else
AC_MSG_ERROR([You must install the Android build-tools version $2. Try |mach bootstrap|. (Looked for $android_build_tools)])
AC_MSG_CHECKING([for Android build-tools])
android_build_tools_base="$android_sdk_root"/build-tools
android_build_tools_version=""
versions=($2)
for version in $versions; do
android_build_tools="$android_build_tools_base"/$version
if test -d "$android_build_tools" -a -f "$android_build_tools/aapt"; then
android_build_tools_version=$version
AC_MSG_RESULT([$android_build_tools])
break
fi
done
if test "$android_build_tools_version" == ""; then
version=$(echo $versions | cut -d" " -f1)
AC_MSG_ERROR([You must install the Android build-tools version $version. Try |mach bootstrap|. (Looked for "$android_build_tools_base"/$version)])
fi
MOZ_PATH_PROG(ZIPALIGN, zipalign, :, [$android_build_tools])
@ -309,7 +318,7 @@ case "$target" in
ANDROID_SDK="${android_sdk}"
ANDROID_SDK_ROOT="${android_sdk_root}"
ANDROID_TOOLS="${android_tools}"
ANDROID_BUILD_TOOLS_VERSION="$2"
ANDROID_BUILD_TOOLS_VERSION="$android_build_tools_version"
AC_DEFINE_UNQUOTED(ANDROID_TARGET_SDK,$ANDROID_TARGET_SDK)
AC_SUBST(ANDROID_TARGET_SDK)
AC_SUBST(ANDROID_SDK_ROOT)

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

@ -13,4 +13,7 @@ DevToolsModules(
'panel.js'
)
BROWSER_CHROME_MANIFESTS += ['test/mochitest/browser.ini']
BROWSER_CHROME_MANIFESTS += [
'new/test/mochitest/browser.ini',
'test/mochitest/browser.ini'
]

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

@ -0,0 +1,5 @@
[DEFAULT]
tags = devtools
subsuite = devtools
[browser_dbg_stub.js]

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

@ -0,0 +1,7 @@
add_task(function*() {
ok(true,
"This is a stub so that we can run the new debugger tests " +
"by copying them in here. This will go away once we land " +
"the initial suite of new tests");
});

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

@ -182,14 +182,28 @@ Tools.jsdebugger = {
}
};
if (Services.prefs.getBoolPref("devtools.debugger.new-debugger-frontend")) {
const NewDebuggerPanel = require("devtools/client/debugger/new/panel").DebuggerPanel;
function switchDebugger() {
if (Services.prefs.getBoolPref("devtools.debugger.new-debugger-frontend")) {
const NewDebuggerPanel = require("devtools/client/debugger/new/panel").DebuggerPanel;
Tools.jsdebugger.url = "chrome://devtools/content/debugger/new/index.html";
Tools.jsdebugger.build = function (iframeWindow, toolbox) {
return new NewDebuggerPanel(iframeWindow, toolbox);
};
Tools.jsdebugger.url = "chrome://devtools/content/debugger/new/index.html";
Tools.jsdebugger.build = function (iframeWindow, toolbox) {
return new NewDebuggerPanel(iframeWindow, toolbox);
};
} else {
Tools.jsdebugger.url = "chrome://devtools/content/debugger/debugger.xul";
Tools.jsdebugger.build = function (iframeWindow, toolbox) {
return new DebuggerPanel(iframeWindow, toolbox);
};
}
}
switchDebugger();
Services.prefs.addObserver(
"devtools.debugger.new-debugger-frontend",
{ observe: switchDebugger },
false
);
Tools.styleEditor = {
id: "styleeditor",

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

@ -176,7 +176,8 @@ module.exports = createClass({
if (functionDisplayName) {
elements.push(
dom.span({ className: "frame-link-function-display-name" },
functionDisplayName)
functionDisplayName),
" "
);
}
}
@ -236,7 +237,7 @@ module.exports = createClass({
elements.push(sourceEl);
if (showHost && host) {
elements.push(dom.span({ className: "frame-link-host" }, host));
elements.push(" ", dom.span({ className: "frame-link-host" }, host));
}
return dom.span(attributes, ...elements);

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

@ -42,12 +42,12 @@ const StackTrace = createClass({
let frames = [];
stacktrace.forEach(s => {
if (s.asyncCause) {
frames.push(AsyncFrame({
frames.push("\t", AsyncFrame({
asyncCause: s.asyncCause
}));
}), "\n");
}
frames.push(Frame({
frames.push("\t", Frame({
frame: {
functionDisplayName: s.functionName,
source: s.filename.split(" -> ").pop(),
@ -58,7 +58,7 @@ const StackTrace = createClass({
showAnonymousFunctionName: true,
showFullSourceUrl: true,
onClick: onViewSourceInDebugger
}));
}), "\n");
});
return dom.div({ className: "stack-trace" }, frames);

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

@ -45,7 +45,9 @@ window.onload = function() {
let traceEl = trace.getDOMNode();
ok(traceEl, "Rendered StackTrace has an element");
let frameEls = traceEl.childNodes;
// Get the child nodes and filter out the text-only whitespace ones
let frameEls = Array.from(traceEl.childNodes)
.filter(n => n.className.includes("frame"));
ok(frameEls, "Rendered StackTrace has frames");
is(frameEls.length, 3, "StackTrace has 3 frames");
@ -76,6 +78,14 @@ window.onload = function() {
shouldLink: true,
tooltip: "View source in Debugger → http://myfile.com/loadee.js:10",
});
// Check the tabs and newlines in the stack trace textContent
let traceText = traceEl.textContent;
let traceLines = traceText.split("\n");
ok(traceLines.length > 0, "There are newlines in the stack trace text");
is(traceLines.pop(), "", "There is a newline at the end of the stack trace text");
is(traceLines.length, 3, "The stack trace text has 3 lines");
ok(traceLines.every(l => l[0] == "\t"), "Every stack trace line starts with tab");
});
}
</script>

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

@ -935,8 +935,6 @@ Messages.Simple.prototype = extend(Messages.BaseMessage.prototype, {
this.element.appendChild(body);
this.element.appendChild(this.document.createTextNode("\n"));
this.element.clipboardText = this.element.textContent;
if (this.private) {
@ -993,12 +991,16 @@ Messages.Simple.prototype = extend(Messages.BaseMessage.prototype, {
let location = this._renderLocation();
if (repeatNode) {
bodyFlex.appendChild(this.document.createTextNode(" "));
bodyFlex.appendChild(repeatNode);
}
if (location) {
bodyFlex.appendChild(this.document.createTextNode(" "));
bodyFlex.appendChild(location);
}
bodyFlex.appendChild(this.document.createTextNode("\n"));
if (this.stack) {
this._attachment = new Widgets.Stacktrace(this, this.stack).render().element;
}

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

@ -3,67 +3,95 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/* globals goDoCommand */
"use strict";
// Test copying of the entire console message when right-clicked
// with no other text selected. See Bug 1100562.
function test() {
add_task(function* () {
let hud;
let outputNode;
let contextMenu;
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-console.html";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/test/test-console.html";
Task.spawn(runner).then(finishTest);
const { tab, browser } = yield loadTab(TEST_URI);
hud = yield openConsole(tab);
outputNode = hud.outputNode;
contextMenu = hud.iframeWindow.document.getElementById("output-contextmenu");
function* runner() {
const {tab} = yield loadTab(TEST_URI);
hud = yield openConsole(tab);
outputNode = hud.outputNode;
contextMenu = hud.iframeWindow.document.getElementById("output-contextmenu");
registerCleanupFunction(() => {
hud = outputNode = contextMenu = null;
});
registerCleanupFunction(() => {
hud = outputNode = contextMenu = null;
});
hud.jsterm.clearOutput();
hud.jsterm.clearOutput();
content.console.log("bug 1100562");
yield ContentTask.spawn(browser, {}, function* () {
let button = content.document.getElementById("testTrace");
button.click();
});
let [results] = yield waitForMessages({
webconsole: hud,
messages: [{
let results = yield waitForMessages({
webconsole: hud,
messages: [
{
text: "bug 1100562",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
}]
});
lines: 1,
},
{
name: "console.trace output",
consoleTrace: true,
lines: 3,
},
]
});
outputNode.focus();
let message = [...results.matched][0];
outputNode.focus();
yield waitForContextMenu(contextMenu, message, copyFromPopup,
testContextMenuCopy);
for (let result of results) {
let message = [...result.matched][0];
function copyFromPopup() {
yield waitForContextMenu(contextMenu, message, () => {
let copyItem = contextMenu.querySelector("#cMenu_copy");
copyItem.doCommand();
let controller = top.document.commandDispatcher
.getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
}
});
function testContextMenuCopy() {
waitForClipboard((str) => {
return message.textContent.trim() == str.trim();
}, () => {
goDoCommand("cmd_copy");
}, () => {}, () => {}
);
}
let clipboardText;
yield closeConsole(tab);
yield waitForClipboardPromise(
() => goDoCommand("cmd_copy"),
(str) => {
clipboardText = str;
return message.textContent == clipboardText;
}
);
ok(clipboardText, "Clipboard text was found and saved");
let lines = clipboardText.split("\n");
ok(lines.length > 0, "There is at least one newline in the message");
is(lines.pop(), "", "There is a newline at the end");
is(lines.length, result.lines, `There are ${result.lines} lines in the message`);
// Test the first line for "timestamp message repeat file:line"
let firstLine = lines.shift();
ok(/^[\d:.]+ .+ \d+ .+:\d+$/.test(firstLine),
"The message's first line has the right format");
// Test the remaining lines (stack trace) for "TABfunctionName sourceURL:line:col"
for (let line of lines) {
ok(/^\t.+ .+:\d+:\d+$/.test(line), "The stack trace line has the right format");
}
}
}
yield closeConsole(tab);
yield finishTest();
});

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

@ -13,6 +13,12 @@
console.log(str);
}
}
function testTrace() {
console.log("bug 1100562");
console.trace();
}
console.info("INLINE SCRIPT:");
test();
console.warn("I'm warning you, he will eat up all yr bacon.");
@ -22,6 +28,7 @@
<body>
<h1 id="header">Heads Up Display Demo</h1>
<button onclick="test();">Log stuff about Dolske</button>
<button id="testTrace" onclick="testTrace();">Log stuff with stacktrace</button>
<div id="myDiv"></div>
</body>
</html>

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

@ -6,6 +6,24 @@
const parsePropertiesFile = require("devtools/shared/node-properties/node-properties");
const { sprintf } = require("devtools/shared/sprintfjs/sprintf");
const propertiesMap = {};
/**
* Memoized getter for properties files that ensures a given url is only required and
* parsed once.
*
* @param {String} url
* The URL of the properties file to parse.
* @return {Object} parsed properties mapped in an object.
*/
function getProperties(url) {
if (!propertiesMap[url]) {
propertiesMap[url] = parsePropertiesFile(require(`raw!${url}`));
}
return propertiesMap[url];
}
/**
* Localization convenience methods.
*
@ -17,14 +35,6 @@ function LocalizationHelper(stringBundleName) {
}
LocalizationHelper.prototype = {
get properties() {
if (!this._properties) {
this._properties = parsePropertiesFile(require(`raw!${this.stringBundleName}`));
}
return this._properties;
},
/**
* L10N shortcut function.
*
@ -32,8 +42,9 @@ LocalizationHelper.prototype = {
* @return string
*/
getStr: function (name) {
if (name in this.properties) {
return this.properties[name];
let properties = getProperties(this.stringBundleName);
if (name in properties) {
return properties[name];
}
throw new Error("No localization found for [" + name + "]");
@ -103,6 +114,63 @@ LocalizationHelper.prototype = {
}
};
function getPropertiesForNode(node) {
let bundleEl = node.closest("[data-localization-bundle]");
if (!bundleEl) {
return null;
}
let propertiesUrl = bundleEl.getAttribute("data-localization-bundle");
return getProperties(propertiesUrl);
}
/**
* Translate existing markup annotated with data-localization attributes.
*
* How to use data-localization in markup:
*
* <div data-localization="content=myContent;title=myTitle"/>
*
* The data-localization attribute identifies an element as being localizable.
* The content of the attribute is semi-colon separated list of descriptors.
* - "title=myTitle" means the "title" attribute should be replaced with the localized
* string corresponding to the key "myTitle".
* - "content=myContent" means the text content of the node should be replaced by the
* string corresponding to "myContent"
*
* How to define the localization bundle in markup:
*
* <div data-localization-bundle="url/to/my.properties">
* [...]
* <div data-localization="content=myContent;title=myTitle"/>
*
* Set the data-localization-bundle on an ancestor of the nodes that should be localized.
*
* @param {Element} root
* The root node to use for the localization
*/
function localizeMarkup(root) {
let elements = root.querySelectorAll("[data-localization]");
for (let element of elements) {
let properties = getPropertiesForNode(element);
if (!properties) {
continue;
}
let attributes = element.getAttribute("data-localization").split(";");
for (let attribute of attributes) {
let [name, value] = attribute.trim().split("=");
if (name === "content") {
element.textContent = properties[value];
} else {
element.setAttribute(name, properties[value]);
}
}
element.removeAttribute("data-localization");
}
}
const sharedL10N = new LocalizationHelper("devtools-shared/locale/shared.properties");
const ELLIPSIS = sharedL10N.getStr("ellipsis");
@ -140,5 +208,6 @@ function MultiLocalizationHelper(...stringBundleNames) {
}
exports.LocalizationHelper = LocalizationHelper;
exports.localizeMarkup = localizeMarkup;
exports.MultiLocalizationHelper = MultiLocalizationHelper;
exports.ELLIPSIS = ELLIPSIS;

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

@ -5,3 +5,4 @@ support-files =
../../../server/tests/browser/head.js
[browser_async_storage.js]
[browser_l10n_localizeMarkup.js]

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

@ -0,0 +1,54 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Tests that the markup localization works properly.
const { localizeMarkup, LocalizationHelper } = require("devtools/shared/l10n");
add_task(function* () {
info("Check that the strings used for this test are still valid");
let INSPECTOR_L10N = new LocalizationHelper("devtools/locale/inspector.properties");
let TOOLBOX_L10N = new LocalizationHelper("devtools/locale/toolbox.properties");
let str1 = INSPECTOR_L10N.getStr("inspector.label");
let str2 = INSPECTOR_L10N.getStr("inspector.commandkey");
let str3 = TOOLBOX_L10N.getStr("toolbox.defaultTitle");
ok(str1 && str2 && str3, "If this failed, strings should be updated in the test");
info("Create the test markup");
let div = document.createElement("div");
div.innerHTML =
`<div data-localization-bundle="devtools/locale/inspector.properties">
<div id="d0" data-localization="content=inspector.someInvalidKey"></div>
<div id="d1" data-localization="content=inspector.label">Text will disappear</div>
<div id="d2" data-localization="content=inspector.label;title=inspector.commandkey">
</div>
<!-- keep the following data-localization on two separate lines -->
<div id="d3" data-localization="content=inspector.label;
title=inspector.commandkey"></div>
<div id="d4" data-localization="aria-label=inspector.label">Some content</div>
<div data-localization-bundle="devtools/locale/toolbox.properties">
<div id="d5" data-localization="content=toolbox.defaultTitle"></div>
</div>
</div>
`;
info("Use localization helper to localize the test markup");
localizeMarkup(div);
let div1 = div.querySelector("#d1");
let div2 = div.querySelector("#d2");
let div3 = div.querySelector("#d3");
let div4 = div.querySelector("#d4");
let div5 = div.querySelector("#d5");
is(div1.innerHTML, str1, "The content of #d1 is localized");
is(div2.innerHTML, str1, "The content of #d2 is localized");
is(div2.getAttribute("title"), str2, "The title of #d2 is localized");
is(div3.innerHTML, str1, "The content of #d3 is localized");
is(div3.getAttribute("title"), str2, "The title of #d3 is localized");
is(div4.innerHTML, "Some content", "The content of #d4 is not replaced");
is(div4.getAttribute("aria-label"), str1, "The aria-label of #d4 is localized");
is(div5.innerHTML, str3, "The content of #d5 is localized with another bundle");
});

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

@ -143,10 +143,14 @@ AnimationEffectReadOnly::GetComputedTimingAt(
StickyTimeDuration activeTime;
StickyTimeDuration beforeActiveBoundary =
std::min(StickyTimeDuration(aTiming.mDelay), result.mEndTime);
std::max(std::min(StickyTimeDuration(aTiming.mDelay), result.mEndTime),
zeroDuration);
StickyTimeDuration activeAfterBoundary =
std::min(StickyTimeDuration(aTiming.mDelay + result.mActiveDuration),
result.mEndTime);
std::max(std::min(StickyTimeDuration(aTiming.mDelay +
result.mActiveDuration),
result.mEndTime),
zeroDuration);
if (localTime > activeAfterBoundary ||
(aPlaybackRate >= 0 && localTime == activeAfterBoundary)) {
@ -155,9 +159,10 @@ AnimationEffectReadOnly::GetComputedTimingAt(
// The animation isn't active or filling at this time.
return result;
}
activeTime = std::max(std::min(result.mActiveDuration,
result.mActiveDuration + aTiming.mEndDelay),
zeroDuration);
activeTime =
std::max(std::min(StickyTimeDuration(localTime - aTiming.mDelay),
result.mActiveDuration),
zeroDuration);
} else if (localTime < beforeActiveBoundary ||
(aPlaybackRate < 0 && localTime == beforeActiveBoundary)) {
result.mPhase = ComputedTiming::AnimationPhase::Before;
@ -165,7 +170,8 @@ AnimationEffectReadOnly::GetComputedTimingAt(
// The animation isn't active or filling at this time.
return result;
}
// activeTime is zero
activeTime = std::max(StickyTimeDuration(localTime - aTiming.mDelay),
zeroDuration);
} else {
MOZ_ASSERT(result.mActiveDuration != zeroDuration,
"How can we be in the middle of a zero-duration interval?");

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

@ -114,7 +114,8 @@ struct TimingParams
StickyTimeDuration EndTime() const
{
return mDelay + ActiveDuration() + mEndDelay;
return std::max(mDelay + ActiveDuration() + mEndDelay,
StickyTimeDuration());
}
bool operator==(const TimingParams& aOther) const;

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

@ -192,7 +192,7 @@ test(function(t) {
// undefined value.
var div = addDiv(t, {style: 'animation: moveAnimation 10s -100s forwards'});
var effect = div.getAnimations()[0].effect;
assert_equals(effect.getComputedTiming().endTime, -90 * MS_PER_SEC,
assert_equals(effect.getComputedTiming().endTime, 0,
'Initial value of endTime');
}, 'endTime of an animation that finishes before its startTime');

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

@ -279,7 +279,7 @@ public:
/**
* This listener observes the first video frame to arrive with a non-empty size,
* and calls HTMLMediaElement::ReceivedMediaStreamInitialSize() with that size.
* and calls HTMLMediaElement::UpdateInitialMediaSize() with that size.
*/
class HTMLMediaElement::StreamSizeListener : public DirectMediaStreamTrackListener {
public:
@ -287,13 +287,17 @@ public:
mElement(aElement),
mInitialSizeFound(false)
{}
void Forget() { mElement = nullptr; }
void ReceivedSize(gfx::IntSize aSize)
{
MOZ_ASSERT(NS_IsMainThread());
if (!mElement) {
return;
}
RefPtr<HTMLMediaElement> deathGrip = mElement;
mElement->UpdateInitialMediaSize(aSize);
}
@ -302,18 +306,27 @@ public:
StreamTime aTrackOffset,
const MediaSegment& aMedia) override
{
if (mInitialSizeFound || aMedia.GetType() != MediaSegment::VIDEO) {
if (mInitialSizeFound) {
return;
}
if (aMedia.GetType() != MediaSegment::VIDEO) {
MOZ_ASSERT(false, "Should only lock on to a video track");
return;
}
const VideoSegment& video = static_cast<const VideoSegment&>(aMedia);
for (VideoSegment::ConstChunkIterator c(video); !c.IsEnded(); c.Next()) {
if (c->mFrame.GetIntrinsicSize() != gfx::IntSize(0,0)) {
mInitialSizeFound = true;
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod<gfx::IntSize>(
this, &StreamSizeListener::ReceivedSize,
c->mFrame.GetIntrinsicSize());
aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
NewRunnableMethod<gfx::IntSize>(this, &StreamSizeListener::ReceivedSize,
c->mFrame.GetIntrinsicSize());
// This is fine to dispatch straight to main thread (instead of via
// ...AfterStreamUpdate()) since it reflects state of the element,
// not the stream. Events reflecting stream or track state should be
// dispatched so their order is preserved.
NS_DispatchToMainThread(event.forget());
return;
}
}
@ -323,7 +336,9 @@ private:
// These fields may only be accessed on the main thread
HTMLMediaElement* mElement;
// These fields may only be accessed on the MSG thread
// These fields may only be accessed on the MSG's appending thread.
// (this is a direct listener so we get called by whoever is producing
// this track's data)
bool mInitialSizeFound;
};
@ -2575,16 +2590,21 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
mAudioCaptured = true;
}
if (mDecoder) {
out->mCapturingDecoder = true;
mDecoder->AddOutputStream(out->mStream->GetInputStream()->AsProcessedStream(),
aFinishWhenEnded);
} else if (mSrcStream) {
out->mCapturingMediaStream = true;
}
if (mReadyState == HAVE_NOTHING) {
// Do not expose the tracks directly before we have metadata.
// Do not expose the tracks until we have metadata.
RefPtr<DOMMediaStream> result = out->mStream;
return result.forget();
}
if (mDecoder) {
out->mCapturingDecoder = true;
mDecoder->AddOutputStream(out->mStream->GetInputStream()->AsProcessedStream(),
aFinishWhenEnded);
if (HasAudio()) {
TrackID audioTrackId = mMediaInfo.mAudio.mTrackId;
RefPtr<MediaStreamTrackSource> trackSource =
@ -2610,22 +2630,6 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
}
if (mSrcStream) {
out->mCapturingMediaStream = true;
MediaStream* inputStream = out->mStream->GetInputStream();
if (!inputStream) {
NS_ERROR("No input stream");
RefPtr<DOMMediaStream> result = out->mStream;
return result.forget();
}
ProcessedMediaStream* processedInputStream =
inputStream->AsProcessedStream();
if (!processedInputStream) {
NS_ERROR("Input stream not a ProcessedMediaStream");
RefPtr<DOMMediaStream> result = out->mStream;
return result.forget();
}
for (size_t i = 0; i < AudioTracks()->Length(); ++i) {
AudioTrack* t = (*AudioTracks())[i];
if (t->Enabled()) {

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

@ -2554,7 +2554,7 @@ TabParent::GetAuthPrompt(uint32_t aPromptReason, const nsIID& iid,
nsCOMPtr<nsILoginManagerPrompter> prompter = do_QueryInterface(prompt);
if (prompter) {
nsCOMPtr<nsIDOMElement> browser = do_QueryInterface(mFrameElement);
prompter->SetE10sData(browser, nullptr);
prompter->SetBrowser(browser);
}
*aResult = prompt.forget().take();

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

@ -242,7 +242,6 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mQuickBuffering(false),
mMinimizePreroll(false),
mDecodeThreadWaiting(false),
mDecodingFirstFrame(true),
mSentLoadedMetadataEvent(false),
mSentFirstFrameLoadedEvent(false),
mSentPlaybackEndedEvent(false),
@ -488,7 +487,7 @@ MediaDecoderStateMachine::NeedToDecodeVideo()
IsVideoDecoding(), mMinimizePreroll, HaveEnoughDecodedVideo());
return IsVideoDecoding() &&
mState != DECODER_STATE_SEEKING &&
((IsDecodingFirstFrame() && VideoQueue().GetSize() == 0) ||
((!mSentFirstFrameLoadedEvent && VideoQueue().GetSize() == 0) ||
(!mMinimizePreroll && !HaveEnoughDecodedVideo()));
}
@ -496,7 +495,8 @@ bool
MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
{
MOZ_ASSERT(OnTaskQueue());
if (IsDecodingFirstFrame()) {
// Don't skip when we're still decoding first frames.
if (!mSentFirstFrameLoadedEvent) {
return false;
}
MOZ_ASSERT(mState == DECODER_STATE_DECODING ||
@ -557,7 +557,7 @@ MediaDecoderStateMachine::NeedToDecodeAudio()
return IsAudioDecoding() &&
mState != DECODER_STATE_SEEKING &&
((IsDecodingFirstFrame() && AudioQueue().GetSize() == 0) ||
((!mSentFirstFrameLoadedEvent && AudioQueue().GetSize() == 0) ||
(!mMinimizePreroll && !HaveEnoughDecodedAudio()));
}
@ -733,7 +733,7 @@ bool
MediaDecoderStateMachine::MaybeFinishDecodeFirstFrame()
{
MOZ_ASSERT(OnTaskQueue());
if (!IsDecodingFirstFrame() ||
if (mSentFirstFrameLoadedEvent ||
(IsAudioDecoding() && AudioQueue().GetSize() == 0) ||
(IsVideoDecoding() && VideoQueue().GetSize() == 0)) {
return false;
@ -790,7 +790,7 @@ MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample,
return;
}
TimeDuration decodeTime = TimeStamp::Now() - aDecodeStartTime;
if (!IsDecodingFirstFrame() &&
if (mSentFirstFrameLoadedEvent &&
THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > mLowAudioThresholdUsecs &&
!HasLowUndecodedData())
{
@ -1077,7 +1077,6 @@ MediaDecoderStateMachine::EnterState(State aState)
MOZ_ASSERT(OnTaskQueue());
switch (aState) {
case DECODER_STATE_DECODING_METADATA:
mDecodingFirstFrame = true;
ReadMetadata();
break;
case DECODER_STATE_DORMANT:
@ -1260,19 +1259,11 @@ MediaDecoderStateMachine::StartDecoding()
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(mState == DECODER_STATE_DECODING);
if (mDecodingFirstFrame && mSentFirstFrameLoadedEvent) {
// We're resuming from dormant state, so we don't need to request
// the first samples in order to determine the media start time,
// we have the start time from last time we loaded.
// FinishDecodeFirstFrame will be launched upon completion of the seek when
// we have data ready to play.
MOZ_ASSERT(mQueuedSeek.Exists() && mSentFirstFrameLoadedEvent,
"Return from dormant must have queued seek");
if (mQueuedSeek.Exists()) {
InitiateSeek(Move(mQueuedSeek));
return;
}
// Handle the pending seek now if we've decoded first frames. Otherwise it
// will be handled after decoding first frames.
if (mSentFirstFrameLoadedEvent && mQueuedSeek.Exists()) {
InitiateSeek(Move(mQueuedSeek));
return;
}
if (CheckIfDecodeComplete()) {
@ -1511,8 +1502,12 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget)
MOZ_ASSERT(mState > DECODER_STATE_DECODING_METADATA,
"We should have got duration already");
if (mState < DECODER_STATE_DECODING ||
(IsDecodingFirstFrame() && !mReader->ForceZeroStartTime())) {
// Can't seek until the start time is known.
bool hasStartTime = mSentFirstFrameLoadedEvent || mReader->ForceZeroStartTime();
// Can't seek when state is WAIT_FOR_CDM or DORMANT.
bool stateAllowed = mState >= DECODER_STATE_DECODING;
if (!stateAllowed || !hasStartTime) {
DECODER_LOG("Seek() Not Enough Data to continue at this stage, queuing seek");
mQueuedSeek.RejectIfExists(__func__);
mQueuedSeek.mTarget = aTarget;
@ -1906,8 +1901,8 @@ bool MediaDecoderStateMachine::HasLowUndecodedData()
bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs)
{
MOZ_ASSERT(OnTaskQueue());
NS_ASSERTION(mState >= DECODER_STATE_DECODING && !IsDecodingFirstFrame(),
"Must have loaded first frame for mBuffered to be valid");
MOZ_ASSERT(mState >= DECODER_STATE_DECODING && mSentFirstFrameLoadedEvent,
"Must have loaded first frame for mBuffered to be valid");
// If we don't have a duration, mBuffered is probably not going to have
// a useful buffered range. Return false here so that we don't get stuck in
@ -2074,12 +2069,6 @@ MediaDecoderStateMachine::EnqueueFirstFrameLoadedEvent()
[]() { MOZ_CRASH("Should not reach"); }));
}
bool
MediaDecoderStateMachine::IsDecodingFirstFrame()
{
return mState == DECODER_STATE_DECODING && mDecodingFirstFrame;
}
void
MediaDecoderStateMachine::FinishDecodeFirstFrame()
{
@ -2106,9 +2095,8 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
// If we didn't have duration and/or start time before, we should now.
EnqueueLoadedMetadataEvent();
}
EnqueueFirstFrameLoadedEvent();
mDecodingFirstFrame = false;
EnqueueFirstFrameLoadedEvent();
}
void
@ -2173,9 +2161,11 @@ MediaDecoderStateMachine::SeekCompleted()
// SeekTask::Discard() will ask MediaDecoderReaderWrapper to discard media
// data requests.
if (mDecodingFirstFrame) {
// We were resuming from dormant, or initiated a seek early.
// We can fire loadeddata now.
// Notify FirstFrameLoaded now if we haven't since we've decoded some data
// for readyState to transition to HAVE_CURRENT_DATA and fire 'loadeddata'.
if (!mSentFirstFrameLoadedEvent) {
// Only MSE can start seeking before finishing decoding first frames.
MOZ_ASSERT(mReader->ForceZeroStartTime());
FinishDecodeFirstFrame();
}
@ -2273,9 +2263,8 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
return NS_OK;
case DECODER_STATE_DECODING: {
if (IsDecodingFirstFrame()) {
// We haven't completed decoding our first frames, we can't start
// playback yet.
// Can't start playback until having decoded first frames.
if (!mSentFirstFrameLoadedEvent) {
return NS_OK;
}
if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING && IsPlaying())
@ -2492,7 +2481,7 @@ void MediaDecoderStateMachine::UpdateNextFrameStatus()
MediaDecoderOwner::NextFrameStatus status;
const char* statusString;
if (mState <= DECODER_STATE_WAIT_FOR_CDM || IsDecodingFirstFrame()) {
if (mState < DECODER_STATE_DECODING || !mSentFirstFrameLoadedEvent) {
status = MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
statusString = "NEXT_FRAME_UNAVAILABLE";
} else if (IsBuffering()) {
@ -2830,12 +2819,12 @@ MediaDecoderStateMachine::DumpDebugInfo()
mMediaSink->DumpDebugInfo();
DUMP_LOG(
"GetMediaTime=%lld GetClock=%lld mMediaSink=%p "
"mState=%s mPlayState=%d mDecodingFirstFrame=%d IsPlaying=%d "
"mState=%s mPlayState=%d mSentFirstFrameLoadedEvent=%d IsPlaying=%d "
"mAudioStatus=%s mVideoStatus=%s mDecodedAudioEndTime=%lld mDecodedVideoEndTime=%lld "
"mIsAudioPrerolling=%d mIsVideoPrerolling=%d "
"mAudioCompleted=%d mVideoCompleted=%d",
GetMediaTime(), mMediaSink->IsStarted() ? GetClock() : -1, mMediaSink.get(),
ToStateStr(), mPlayState.Ref(), mDecodingFirstFrame, IsPlaying(),
ToStateStr(), mPlayState.Ref(), mSentFirstFrameLoadedEvent, IsPlaying(),
AudioRequestStatus(), VideoRequestStatus(), mDecodedAudioEndTime, mDecodedVideoEndTime,
mIsAudioPrerolling, mIsVideoPrerolling, mAudioCompleted.Ref(), mVideoCompleted.Ref());
});

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

@ -567,8 +567,7 @@ protected:
// If there are any queued seek, will change state to DECODER_STATE_SEEKING
// and return true.
bool MaybeFinishDecodeFirstFrame();
// Return true if we are currently decoding the first frames.
bool IsDecodingFirstFrame();
void FinishDecodeFirstFrame();
// Completes the seek operation, moves onto the next appropriate state.
@ -885,18 +884,14 @@ private:
// Track our request to update the buffered ranges
MozPromiseRequestHolder<MediaDecoderReader::BufferedUpdatePromise> mBufferedUpdateRequest;
// True if we need to call FinishDecodeFirstFrame() upon frame decoding
// succeeding.
bool mDecodingFirstFrame;
// True if we are back from DECODER_STATE_DORMANT state and
// LoadedMetadataEvent was already sent.
bool mSentLoadedMetadataEvent;
// True if we are back from DECODER_STATE_DORMANT state and
// FirstFrameLoadedEvent was already sent, then we can skip
// SetStartTime because the mStartTime already set before. Also we don't need
// to decode any audio/video since the MediaDecoder will trigger a seek
// operation soon.
// True if we've decoded first frames (thus having the start time) and
// notified the FirstFrameLoaded event. Note we can't initiate seek until the
// start time is known which happens when the first frames are decoded or we
// are playing an MSE stream (the start time is always assumed 0).
bool mSentFirstFrameLoadedEvent;
bool mSentPlaybackEndedEvent;

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

@ -62,9 +62,9 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
VideoFrameContainer* aVideoFrameContainer,
layers::LayersBackend aLayersBackend)
: MediaDecoderReader(aDecoder)
, mAudio(this, MediaData::AUDIO_DATA, Preferences::GetUint("media.audio-decode-ahead", 2),
, mAudio(this, MediaData::AUDIO_DATA,
Preferences::GetUint("media.audio-max-decode-error", 3))
, mVideo(this, MediaData::VIDEO_DATA, Preferences::GetUint("media.video-decode-ahead", 2),
, mVideo(this, MediaData::VIDEO_DATA,
Preferences::GetUint("media.video-max-decode-error", 2))
, mDemuxer(aDemuxer)
, mDemuxerInitDone(false)
@ -562,7 +562,7 @@ MediaFormatReader::RequestVideoData(bool aSkipToNextKeyframe,
}
RefPtr<MediaDataPromise> p = mVideo.EnsurePromise(__func__);
NotifyDecodingRequested(TrackInfo::kVideoTrack);
ScheduleUpdate(TrackInfo::kVideoTrack);
return p;
}
@ -606,7 +606,6 @@ MediaFormatReader::OnDemuxFailed(TrackType aTrack, DemuxerFailureReason aFailure
void
MediaFormatReader::DoDemuxVideo()
{
// TODO Use DecodeAhead value rather than 1.
mVideo.mDemuxRequest.Begin(mVideo.mTrackDemuxer->GetSamples(1)
->Then(OwnerThread(), __func__, this,
&MediaFormatReader::OnVideoDemuxCompleted,
@ -657,7 +656,7 @@ MediaFormatReader::RequestAudioData()
}
RefPtr<MediaDataPromise> p = mAudio.EnsurePromise(__func__);
NotifyDecodingRequested(TrackInfo::kAudioTrack);
ScheduleUpdate(TrackInfo::kAudioTrack);
return p;
}
@ -665,7 +664,6 @@ MediaFormatReader::RequestAudioData()
void
MediaFormatReader::DoDemuxAudio()
{
// TODO Use DecodeAhead value rather than 1.
mAudio.mDemuxRequest.Begin(mAudio.mTrackDemuxer->GetSamples(1)
->Then(OwnerThread(), __func__, this,
&MediaFormatReader::OnAudioDemuxCompleted,
@ -706,7 +704,7 @@ MediaFormatReader::NotifyInputExhausted(TrackType aTrack)
MOZ_ASSERT(OnTaskQueue());
LOGV("Decoder has requested more %s data", TrackTypeToStr(aTrack));
auto& decoder = GetDecoderData(aTrack);
decoder.mInputExhausted = true;
decoder.mDecodePending = false;
ScheduleUpdate(aTrack);
}
@ -755,33 +753,21 @@ MediaFormatReader::NotifyEndOfStream(TrackType aTrack)
ScheduleUpdate(aTrack);
}
void
MediaFormatReader::NotifyDecodingRequested(TrackType aTrack)
{
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
decoder.mDecodingRequested = true;
ScheduleUpdate(aTrack);
}
bool
MediaFormatReader::NeedInput(DecoderData& aDecoder)
{
// We try to keep a few more compressed samples input than decoded samples
// have been output, provided the state machine has requested we send it a
// decoded sample. To account for H.264 streams which may require a longer
// run of input than we input, decoders fire an "input exhausted" callback,
// which overrides our "few more samples" threshold.
// To account for H.264 streams which may require a longer
// run of input than we input, decoders fire an "input exhausted" callback.
// The decoder will not be fed a new raw sample until InputExhausted
// has been called.
return
(aDecoder.HasPromise() || aDecoder.mTimeThreshold.isSome()) &&
!aDecoder.HasPendingDrain() &&
!aDecoder.HasFatalError() &&
aDecoder.mDecodingRequested &&
!aDecoder.mDemuxRequest.Exists() &&
!aDecoder.mOutput.Length() &&
!aDecoder.HasInternalSeekPending() &&
aDecoder.mOutput.Length() <= aDecoder.mDecodeAhead &&
(aDecoder.mInputExhausted || !aDecoder.mQueuedSamples.IsEmpty() ||
aDecoder.mTimeThreshold.isSome() ||
aDecoder.mNumSamplesInput - aDecoder.mNumSamplesOutput <= aDecoder.mDecodeAhead);
!aDecoder.mDecodePending;
}
void
@ -932,6 +918,7 @@ MediaFormatReader::DecodeDemuxedSamples(TrackType aTrack,
LOG("Unable to pass frame to decoder");
return false;
}
decoder.mDecodePending = true;
return true;
}
@ -1007,7 +994,7 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
decoder.ShutdownDecoder();
if (sample->mKeyframe) {
decoder.mQueuedSamples.AppendElements(Move(samples));
NotifyDecodingRequested(aTrack);
ScheduleUpdate(aTrack);
} else {
TimeInterval time =
TimeInterval(TimeUnit::FromMicroseconds(sample->mTime),
@ -1045,9 +1032,6 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
}
samplesPending = true;
}
// We have serviced the decoder's request for more data.
decoder.mInputExhausted = false;
}
void
@ -1071,7 +1055,7 @@ MediaFormatReader::InternalSeek(TrackType aTrack, const InternalSeekTarget& aTar
"Seek promise must be disconnected when timethreshold is reset");
decoder.mTimeThreshold.ref().mHasSeeked = true;
self->SetVideoDecodeThreshold();
self->NotifyDecodingRequested(aTrack);
self->ScheduleUpdate(aTrack);
},
[self, aTrack] (DemuxerFailureReason aResult) {
auto& decoder = self->GetDecoderData(aTrack);
@ -1275,6 +1259,7 @@ MediaFormatReader::Update(TrackType aTrack)
if (decoder.mError &&
decoder.mError.ref() == MediaDataDecoderError::DECODE_ERROR) {
decoder.mDecodePending = false;
decoder.mError.reset();
if (++decoder.mNumOfConsecutiveError > decoder.mMaxConsecutiveError) {
NotifyError(aTrack);
@ -1292,11 +1277,11 @@ MediaFormatReader::Update(TrackType aTrack)
bool needInput = NeedInput(decoder);
LOGV("Update(%s) ni=%d no=%d ie=%d, in:%llu out:%llu qs=%u pending:%u waiting:%d ahead:%d sid:%u",
TrackTypeToStr(aTrack), needInput, needOutput, decoder.mInputExhausted,
LOGV("Update(%s) ni=%d no=%d ie=%d, in:%llu out:%llu qs=%u pending:%u waiting:%d promise:%d sid:%u",
TrackTypeToStr(aTrack), needInput, needOutput, decoder.mDecodePending,
decoder.mNumSamplesInput, decoder.mNumSamplesOutput,
uint32_t(size_t(decoder.mSizeOfQueue)), uint32_t(decoder.mOutput.Length()),
decoder.mWaitingForData, !decoder.HasPromise(), decoder.mLastStreamSourceID);
decoder.mWaitingForData, decoder.HasPromise(), decoder.mLastStreamSourceID);
if (decoder.mWaitingForData &&
(!decoder.mTimeThreshold || decoder.mTimeThreshold.ref().mWaiting)) {
@ -1577,7 +1562,7 @@ MediaFormatReader::OnVideoSkipCompleted(uint32_t aSkipped)
VideoSkipReset(aSkipped);
NotifyDecodingRequested(TrackInfo::kVideoTrack);
ScheduleUpdate(TrackInfo::kVideoTrack);
}
void
@ -1595,7 +1580,7 @@ MediaFormatReader::OnVideoSkipFailed(MediaTrackDemuxer::SkipFailureHolder aFailu
DropDecodedSamples(TrackInfo::kVideoTrack);
// We can't complete the skip operation, will just service a video frame
// normally.
NotifyDecodingRequested(TrackInfo::kVideoTrack);
ScheduleUpdate(TrackInfo::kVideoTrack);
break;
case DemuxerFailureReason::CANCELED: MOZ_FALLTHROUGH;
case DemuxerFailureReason::SHUTDOWN:
@ -2013,12 +1998,11 @@ MediaFormatReader::GetMozDebugReaderData(nsAString& aString)
result += nsPrintfCString("audio frames decoded: %lld\n",
mAudio.mNumSamplesOutputTotal);
if (HasAudio()) {
result += nsPrintfCString("audio state: ni=%d no=%d ie=%d demuxr:%d demuxq:%d decoder:%d tt:%f tths:%d in:%llu out:%llu qs=%u pending:%u waiting:%d sid:%u\n",
result += nsPrintfCString("audio state: ni=%d no=%d ie=%d demuxr:%d demuxq:%d tt:%f tths:%d in:%llu out:%llu qs=%u pending:%u waiting:%d sid:%u\n",
NeedInput(mAudio), mAudio.HasPromise(),
mAudio.mInputExhausted,
mAudio.mDecodePending,
mAudio.mDemuxRequest.Exists(),
int(mAudio.mQueuedSamples.Length()),
mAudio.mDecodingRequested,
mAudio.mTimeThreshold
? mAudio.mTimeThreshold.ref().Time().ToSeconds()
: -1.0,
@ -2037,12 +2021,11 @@ MediaFormatReader::GetMozDebugReaderData(nsAString& aString)
mVideo.mNumSamplesOutputTotal,
mVideo.mNumSamplesSkippedTotal);
if (HasVideo()) {
result += nsPrintfCString("video state: ni=%d no=%d ie=%d demuxr:%d demuxq:%d decoder:%d tt:%f tths:%d in:%llu out:%llu qs=%u pending:%u waiting:%d sid:%u\n",
result += nsPrintfCString("video state: ni=%d no=%d ie=%d demuxr:%d demuxq:%d tt:%f tths:%d in:%llu out:%llu qs=%u pending:%u waiting:%d sid:%u\n",
NeedInput(mVideo), mVideo.HasPromise(),
mVideo.mInputExhausted,
mVideo.mDecodePending,
mVideo.mDemuxRequest.Exists(),
int(mVideo.mQueuedSamples.Length()),
mVideo.mDecodingRequested,
mVideo.mTimeThreshold
? mVideo.mTimeThreshold.ref().Time().ToSeconds()
: -1.0,
@ -2080,7 +2063,7 @@ MediaFormatReader::SetBlankDecode(TrackType aTrack, bool aIsBlankDecode)
decoder.mIsBlankDecode = aIsBlankDecode;
decoder.Flush();
decoder.ShutdownDecoder();
NotifyDecodingRequested(TrackInfo::kVideoTrack); // Calls ScheduleUpdate().
ScheduleUpdate(TrackInfo::kVideoTrack);
return;
}

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

@ -169,7 +169,6 @@ private:
void NotifyError(TrackType aTrack, MediaDataDecoderError aError = MediaDataDecoderError::FATAL_ERROR);
void NotifyWaitingForData(TrackType aTrack);
void NotifyEndOfStream(TrackType aTrack);
void NotifyDecodingRequested(TrackType aTrack);
void ExtractCryptoInitData(nsTArray<uint8_t>& aInitData);
@ -231,21 +230,18 @@ private:
struct DecoderData {
DecoderData(MediaFormatReader* aOwner,
MediaData::Type aType,
uint32_t aDecodeAhead,
uint32_t aNumOfMaxError)
: mOwner(aOwner)
, mType(aType)
, mMonitor("DecoderData")
, mDescription("shutdown")
, mDecodeAhead(aDecodeAhead)
, mUpdateScheduled(false)
, mDemuxEOS(false)
, mWaitingForData(false)
, mReceivedNewData(false)
, mDecoderInitialized(false)
, mDecodingRequested(false)
, mOutputRequested(false)
, mInputExhausted(false)
, mDecodePending(false)
, mNeedDraining(false)
, mDraining(false)
, mDrainComplete(false)
@ -288,7 +284,6 @@ private:
}
// Only accessed from reader's task queue.
uint32_t mDecodeAhead;
bool mUpdateScheduled;
bool mDemuxEOS;
bool mWaitingForData;
@ -312,11 +307,14 @@ private:
MozPromiseRequestHolder<MediaDataDecoder::InitPromise> mInitPromise;
// False when decoder is created. True when decoder Init() promise is resolved.
bool mDecoderInitialized;
// Set when decoding can proceed. It is reset when a decoding promise is
// rejected or prior a seek operation.
bool mDecodingRequested;
bool mOutputRequested;
bool mInputExhausted;
// Set to true once the MediaDataDecoder has been fed a compressed sample.
// No more sample will be passed to the decoder while true.
// mDecodePending is reset when:
// 1- The decoder returns a sample
// 2- The decoder calls InputExhausted
// 3- The decoder is Flushed or Reset.
bool mDecodePending;
bool mNeedDraining;
bool mDraining;
bool mDrainComplete;
@ -376,9 +374,8 @@ private:
if (mDecoder) {
mDecoder->Flush();
}
mDecodingRequested = false;
mOutputRequested = false;
mInputExhausted = false;
mDecodePending = false;
mOutput.Clear();
mNumSamplesInput = 0;
mNumSamplesOutput = 0;
@ -397,10 +394,9 @@ private:
mDemuxEOS = false;
mWaitingForData = false;
mQueuedSamples.Clear();
mDecodingRequested = false;
mOutputRequested = false;
mInputExhausted = false;
mNeedDraining = false;
mDecodePending = false;
mDraining = false;
mDrainComplete = false;
mTimeThreshold.reset();
@ -441,9 +437,8 @@ private:
public:
DecoderDataWithPromise(MediaFormatReader* aOwner,
MediaData::Type aType,
uint32_t aDecodeAhead,
uint32_t aNumOfMaxError)
: DecoderData(aOwner, aType, aDecodeAhead, aNumOfMaxError)
: DecoderData(aOwner, aType, aNumOfMaxError)
, mHasPromise(false)
{}
@ -472,7 +467,6 @@ private:
{
MOZ_ASSERT(mOwner->OnTaskQueue());
mPromise.Reject(aReason, aMethodName);
mDecodingRequested = false;
mHasPromise = false;
}

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

@ -1077,6 +1077,25 @@ MediaStreamGraph::NotifyOutputData(AudioDataValue* aBuffer, size_t aFrames,
}
}
void
MediaStreamGraph::AssertOnGraphThreadOrNotRunning() const
{
// either we're on the right thread (and calling CurrentDriver() is safe),
// or we're going to assert anyways, so don't cross-check CurrentDriver
#ifdef DEBUG
MediaStreamGraphImpl const * graph =
static_cast<MediaStreamGraphImpl const *>(this);
// if all the safety checks fail, assert we own the monitor
if (!graph->mDriver->OnThread()) {
if (!(graph->mDetectedNotRunning &&
graph->mLifecycleState > MediaStreamGraphImpl::LIFECYCLE_RUNNING &&
NS_IsMainThread())) {
graph->mMonitor.AssertCurrentThreadOwns();
}
}
#endif
}
bool
MediaStreamGraphImpl::ShouldUpdateMainThread()
{

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

@ -1353,6 +1353,7 @@ public:
*/
virtual void DispatchToMainThreadAfterStreamStateUpdate(already_AddRefed<nsIRunnable> aRunnable)
{
AssertOnGraphThreadOrNotRunning();
*mPendingUpdateRunnables.AppendElement() = aRunnable;
}
@ -1374,6 +1375,8 @@ public:
void NotifyOutputData(AudioDataValue* aBuffer, size_t aFrames,
TrackRate aRate, uint32_t aChannels);
void AssertOnGraphThreadOrNotRunning() const;
protected:
explicit MediaStreamGraph(TrackRate aSampleRate)
: mSampleRate(aSampleRate)

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

@ -202,24 +202,8 @@ public:
nsISupports* aData,
const nsTArray<AudioNodeSizes>& aAudioStreamSizes);
// The following methods run on the graph thread (or possibly the main thread if
// mLifecycleState > LIFECYCLE_RUNNING)
void AssertOnGraphThreadOrNotRunning() const
{
// either we're on the right thread (and calling CurrentDriver() is safe),
// or we're going to assert anyways, so don't cross-check CurrentDriver
#ifdef DEBUG
// if all the safety checks fail, assert we own the monitor
if (!mDriver->OnThread()) {
if (!(mDetectedNotRunning &&
mLifecycleState > LIFECYCLE_RUNNING &&
NS_IsMainThread())) {
mMonitor.AssertCurrentThreadOwns();
}
}
#endif
}
// The following methods run on the graph thread (or possibly the main thread
// if mLifecycleState > LIFECYCLE_RUNNING)
void CollectSizesForMemoryReport(
already_AddRefed<nsIHandleReportCallback> aHandleReport,
already_AddRefed<nsISupports> aHandlerData);

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

@ -132,7 +132,7 @@ FlacFrameParser::DecodeHeaderBlock(const uint8_t* aPacket, size_t aLength)
if (numChannels > FLAC_MAX_CHANNELS) {
return false;
}
uint32_t bps = ((blob >> 38) & BITMASK(5)) + 1;
uint32_t bps = ((blob >> 36) & BITMASK(5)) + 1;
if (bps > 24) {
return false;
}

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

@ -175,6 +175,9 @@ public:
// Denotes that the last input sample has been inserted into the decoder,
// and no more output can be produced unless more input is sent.
// A frame decoding session is completed once InputExhausted has been called.
// MediaDataDecoder::Input will not be called again until InputExhausted has
// been called.
virtual void InputExhausted() = 0;
virtual void DrainComplete() = 0;

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

@ -96,11 +96,7 @@ private:
while (mReorderQueue.Length() > mMaxRefFrames) {
mCallback->Output(mReorderQueue.Pop().get());
}
if (mReorderQueue.Length() <= mMaxRefFrames) {
mCallback->InputExhausted();
}
mCallback->InputExhausted();
}
private:

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

@ -163,12 +163,9 @@ OpusDataDecoder::ProcessDecode(MediaRawData* aSample)
mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
break;
case DecodeError::DECODE_SUCCESS:
mCallback->InputExhausted();
break;
}
if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
}
OpusDataDecoder::DecodeError

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

@ -202,7 +202,7 @@ TheoraDecoder::ProcessDecode(MediaRawData* aSample)
}
if (DoDecode(aSample) == -1) {
mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
} else if (mTaskQueue->IsEmpty()) {
} else {
mCallback->InputExhausted();
}
}

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

@ -192,7 +192,7 @@ VPXDecoder::ProcessDecode(MediaRawData* aSample)
}
if (DoDecode(aSample) == -1) {
mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
} else if (mTaskQueue->IsEmpty()) {
} else {
mCallback->InputExhausted();
}
}

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

@ -143,7 +143,7 @@ VorbisDataDecoder::ProcessDecode(MediaRawData* aSample)
}
if (DoDecode(aSample) == -1) {
mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
} else if (mTaskQueue->IsEmpty()) {
} else {
mCallback->InputExhausted();
}
}

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

@ -68,6 +68,8 @@ WaveDataDecoder::Input(MediaRawData* aSample)
{
if (!DoDecode(aSample)) {
mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
} else {
mCallback->InputExhausted();
}
return NS_OK;
}

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

@ -215,10 +215,7 @@ AppleATDecoder::SubmitSample(MediaRawData* aSample)
}
mQueuedSamples.Clear();
}
if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
mCallback->InputExhausted();
}
nsresult

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

@ -34,11 +34,9 @@ AppleVTDecoder::AppleVTDecoder(const VideoInfo& aConfig,
, mPictureHeight(aConfig.mImage.height)
, mDisplayWidth(aConfig.mDisplay.width)
, mDisplayHeight(aConfig.mDisplay.height)
, mQueuedSamples(0)
, mTaskQueue(aTaskQueue)
, mMaxRefFrames(mp4_demuxer::H264::ComputeMaxRefFrames(aConfig.mExtraData))
, mImageContainer(aImageContainer)
, mInputIncoming(0)
, mIsShutDown(false)
#ifdef MOZ_WIDGET_UIKIT
, mUseSoftwareImages(true)
@ -88,8 +86,6 @@ AppleVTDecoder::Input(MediaRawData* aSample)
aSample->mKeyframe ? " keyframe" : "",
aSample->Size());
mInputIncoming++;
mTaskQueue->Dispatch(NewRunnableMethod<RefPtr<MediaRawData>>(
this, &AppleVTDecoder::ProcessDecode, aSample));
return NS_OK;
@ -104,8 +100,6 @@ AppleVTDecoder::Flush()
NewRunnableMethod(this, &AppleVTDecoder::ProcessFlush);
SyncRunnable::DispatchToThread(mTaskQueue, runnable);
mIsFlushing = false;
// All ProcessDecode() tasks should be done.
MOZ_ASSERT(mInputIncoming == 0);
mSeekTargetThreshold.reset();
@ -142,18 +136,11 @@ AppleVTDecoder::ProcessDecode(MediaRawData* aSample)
{
AssertOnTaskQueueThread();
mInputIncoming--;
if (mIsFlushing) {
return NS_OK;
}
auto rv = DoDecode(aSample);
// Ask for more data.
if (NS_SUCCEEDED(rv) && !mInputIncoming && mQueuedSamples <= mMaxRefFrames) {
LOG("%s task queue empty; requesting more data", GetDescriptionName());
mCallback->InputExhausted();
}
return rv;
}
@ -213,7 +200,6 @@ AppleVTDecoder::DrainReorderedFrames()
while (!mReorderQueue.IsEmpty()) {
mCallback->Output(mReorderQueue.Pop().get());
}
mQueuedSamples = 0;
}
void
@ -223,7 +209,6 @@ AppleVTDecoder::ClearReorderedFrames()
while (!mReorderQueue.IsEmpty()) {
mReorderQueue.Pop();
}
mQueuedSamples = 0;
}
void
@ -288,16 +273,10 @@ AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage,
aFrameRef.is_sync_point ? " keyframe" : ""
);
if (mQueuedSamples > mMaxRefFrames) {
// We had stopped requesting more input because we had received too much at
// the time. We can ask for more once again.
mCallback->InputExhausted();
}
MOZ_ASSERT(mQueuedSamples);
mQueuedSamples--;
if (!aImage) {
// Image was dropped by decoder.
// Image was dropped by decoder or none return yet.
// We need more input to continue.
mCallback->InputExhausted();
return NS_OK;
}
@ -410,9 +389,10 @@ AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage,
// in composition order.
MonitorAutoLock mon(mMonitor);
mReorderQueue.Push(data);
while (mReorderQueue.Length() > mMaxRefFrames) {
if (mReorderQueue.Length() > mMaxRefFrames) {
mCallback->Output(mReorderQueue.Pop().get());
}
mCallback->InputExhausted();
LOG("%llu decoded frames queued",
static_cast<unsigned long long>(mReorderQueue.Length()));
@ -480,8 +460,6 @@ AppleVTDecoder::DoDecode(MediaRawData* aSample)
return NS_ERROR_FAILURE;
}
mQueuedSamples++;
VTDecodeFrameFlags decodeFlags =
kVTDecodeFrame_EnableAsynchronousDecompression;
rv = VTDecompressionSessionDecodeFrame(mSession,

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

@ -90,11 +90,6 @@ private:
const uint32_t mDisplayWidth;
const uint32_t mDisplayHeight;
// Number of times a sample was queued via Input(). Will be decreased upon
// the decoder's callback being invoked.
// This is used to calculate how many frames has been buffered by the decoder.
Atomic<uint32_t> mQueuedSamples;
// Method to set up the decompression session.
nsresult InitializeSession();
nsresult WaitForAsynchronousFrames();
@ -106,9 +101,6 @@ private:
const RefPtr<TaskQueue> mTaskQueue;
const uint32_t mMaxRefFrames;
const RefPtr<layers::ImageContainer> mImageContainer;
// Increased when Input is called, and decreased when ProcessFrame runs.
// Reaching 0 indicates that there's no pending Input.
Atomic<uint32_t> mInputIncoming;
Atomic<bool> mIsShutDown;
const bool mUseSoftwareImages;

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

@ -133,6 +133,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample)
int64_t samplePosition = aSample->mOffset;
media::TimeUnit pts = media::TimeUnit::FromMicroseconds(aSample->mTime);
bool didOutput = false;
while (packet.size > 0) {
int decoded;
@ -181,6 +182,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample)
numChannels,
samplingRate);
mCallback->Output(data);
didOutput = true;
pts += duration;
if (!pts.IsValid()) {
NS_WARNING("Invalid count of accumulated audio samples");
@ -192,7 +194,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample)
samplePosition += bytesConsumed;
}
return DecodeResult::DECODE_FRAME;
return didOutput ? DecodeResult::DECODE_FRAME : DecodeResult::DECODE_NO_FRAME;
}
void

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

@ -117,10 +117,12 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessDecode(MediaRawData* aSample)
case DecodeResult::FATAL_ERROR:
mCallback->Error(MediaDataDecoderError::FATAL_ERROR);
break;
case DecodeResult::DECODE_NO_FRAME:
case DecodeResult::DECODE_FRAME:
mCallback->InputExhausted();
break;
default:
if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
break;
}
}

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

@ -149,9 +149,7 @@ WMFMediaDataDecoder::ProcessOutput()
mCallback->Output(output);
}
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
mCallback->InputExhausted();
} else if (FAILED(hr)) {
NS_WARNING("WMFMediaDataDecoder failed to output data");
mCallback->Error(MediaDataDecoderError::DECODE_ERROR);

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

@ -15,9 +15,16 @@ from external_media_tests.utils import verbose_until
class YouTubePuppeteer(VideoPuppeteer):
"""
Wrapper around a YouTube #movie_player element.
Wrapper around a YouTube .html5-video-player element.
Partial reference: https://developers.google.com/youtube/js_api_reference.
Can be used with youtube videos or youtube videos at embedded URLS. E.g.
both https://www.youtube.com/watch?v=AbAACm1IQE0 and
https://www.youtube.com/embed/AbAACm1IQE0 should work.
Using an embedded video has the advantage of not auto-playing more videos
while a test is running.
Partial reference: https://developers.google.com/youtube/iframe_api_reference.
This reference is useful for site-specific features such as interacting
with ads, or accessing YouTube's debug data.
"""
@ -37,14 +44,16 @@ class YouTubePuppeteer(VideoPuppeteer):
self.player = None
super(YouTubePuppeteer,
self).__init__(marionette, url,
video_selector='#movie_player video',
video_selector='.html5-video-player video',
**kwargs)
wait = Wait(self.marionette, timeout=30)
with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
verbose_until(wait, self,
expected.element_present(By.ID, 'movie_player'))
self.player = self.marionette.find_element(By.ID, 'movie_player')
self.marionette.execute_script("log('#movie_player "
expected.element_present(By.CLASS_NAME,
'html5-video-player'))
self.player = self.marionette.find_element(By.CLASS_NAME,
'html5-video-player')
self.marionette.execute_script("log('.html5-video-player "
"element obtained');")
# When an ad is playing, self.player_duration indicates the duration
# of the spliced-in ad stream, not the duration of the main video, so
@ -117,7 +126,7 @@ class YouTubePuppeteer(VideoPuppeteer):
def execute_yt_script(self, script):
"""
Execute JS script in content context with access to video element and
YouTube #movie_player element.
YouTube .html5-video-player element.
:param script: script to be executed.
@ -131,7 +140,7 @@ class YouTubePuppeteer(VideoPuppeteer):
@property
def playback_quality(self):
"""
Please see https://developers.google.com/youtube/js_api_reference#Playback_quality
Please see https://developers.google.com/youtube/iframe_api_reference#Playback_quality
for valid values.
:return: A string with a valid value returned via YouTube.
@ -176,7 +185,7 @@ class YouTubePuppeteer(VideoPuppeteer):
"""
:return: The YouTube state of the video. See
https://developers.google.com/youtube/js_api_reference#getPlayerState
https://developers.google.com/youtube/iframe_api_reference#getPlayerState
for valid values.
"""
state = self.execute_yt_script('return arguments[1].'
@ -188,7 +197,7 @@ class YouTubePuppeteer(VideoPuppeteer):
"""
This and the following properties are based on the
player.getPlayerState() call
(https://developers.google.com/youtube/js_api_reference#Playback_status)
(https://developers.google.com/youtube/iframe_api_reference#Playback_status)
:return: True if the video has not yet started.
"""
@ -240,7 +249,7 @@ class YouTubePuppeteer(VideoPuppeteer):
Get state of current ad.
:return: Returns one of the constants listed in
https://developers.google.com/youtube/js_api_reference#Playback_status
https://developers.google.com/youtube/iframe_api_reference#Playback_status
for an ad.
"""
@ -350,7 +359,7 @@ class YouTubePuppeteer(VideoPuppeteer):
# no ad playing
return False
if self.ad_skippable:
selector = '#movie_player .videoAdUiSkipContainer'
selector = '.html5-video-player .videoAdUiSkipContainer'
wait = Wait(self.marionette, timeout=30)
try:
with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
@ -378,7 +387,7 @@ class YouTubePuppeteer(VideoPuppeteer):
if (self.ad_playing and self.video_src.startswith('mediasource') and
self.duration):
return self.duration
selector = '#movie_player .videoAdUiAttribution'
selector = '.html5-media-player .videoAdUiAttribution'
wait = Wait(self.marionette, timeout=5)
try:
with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
@ -464,7 +473,7 @@ class YouTubePuppeteer(VideoPuppeteer):
player_state = self._yt_player_state_name[self.player_state]
ad_state = self._yt_player_state_name[self.ad_state]
messages += [
'#movie_player: {',
'.html5-media-player: {',
'\tvideo id: {0},'.format(self.movie_id),
'\tvideo_title: {0}'.format(self.movie_title),
'\tcurrent_state: {0},'.format(player_state),
@ -475,7 +484,7 @@ class YouTubePuppeteer(VideoPuppeteer):
'}'
]
else:
messages += ['\t#movie_player: None']
messages += ['\t.html5-media-player: None']
return '\n'.join(messages)

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

@ -1,9 +1,9 @@
# short videos; no ads; max 5 minutes
# short videos; no ads; embedded; max 5 minutes
# 0:12
[https://youtu.be/AbAACm1IQE0]
[https://youtube.com/embed/AbAACm1IQE0?autoplay=1]
# 2:18
[https://www.youtube.com/watch?v=yOQQCoxs8-k]
[https://youtube.com/embed/yOQQCoxs8-k?autoplay=1]
# 0:08
[https://www.youtube.com/watch?v=1visYpIREUM]
[https://youtube.com/embed/1visYpIREUM?autoplay=1]
# 2:09
[https://www.youtube.com/watch?v=rjmuKV9BTkE]
[https://youtube.com/embed/rjmuKV9BTkE?autoplay=1]

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

@ -1,14 +1,5 @@
# all long videos; < 12 hours total
# 2:18:00
[http://youtu.be/FLX64H5FYa8]
# 1:00:00
[https://www.youtube.com/watch?v=AYYDshv8C4g]
# 1:10:00
[https://www.youtube.com/watch?v=V0Vy4kYAPDk]
# 1:47:00
[https://www.youtube.com/watch?v=bFtGE2C7Pxs]
# shutdownhang | WaitForSingleObjectEx | WaitForSingleObject | PR_Wait | nsThread::ProcessNextEvent(bool, bool*) | NS_ProcessNextEvent(nsIThread*, bool) | mozilla::MediaShutdownManager::Shutdown()
# 1:43:00
[https://www.youtube.com/watch?v=BXMtXpmpXPU]
# a couple of very long videos, < 12 hours total
# 6:00:00 - can't embed due to copyright
[https://www.youtube.com/watch?v=5N8sUccRiTA]
# 2:09:00
[https://www.youtube.com/embed/b6q5N16dje4?autoplay=1]

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

@ -1,9 +0,0 @@
# a couple of very long videos, < 12 hours total
# 6:00:00
[https://www.youtube.com/watch?v=5N8sUccRiTA]
# 2:27:00
[https://www.youtube.com/watch?v=NAVrm3wjzq8]
# 58:50
[https://www.youtube.com/watch?v=uP1BBw3IYco]
# 2:09:00
[https://www.youtube.com/watch?v=b6q5N16dje4]

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

@ -1,3 +1,6 @@
# It appears these are not currently used by tests. They are left here as they
# reference failure scenarios. If tese are fixed that can be removed.
# videos from crashes, < 12 hours
# hang | NtUserMessageCall | SendMessageW

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

@ -1,3 +1,6 @@
# It appears these are not currently used by tests. They are left here as they
# reference failure scenarios. If tese are fixed that can be removed.
# Total time: about 12-13 hours + unskippable ads
#Request url: https://crash-stats.mozilla.com/api/SuperSearchUnredacted/?product=Firefox&url=%24https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D&url=%21~list&url=%21~index&_results_number=50&platform=Windows&version=37.0&date=%3E2015-03-26

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

@ -1,15 +0,0 @@
# very long test; 96-100 hours?
# 00:3:26
[https://www.youtube.com/watch?v=7RMQksXpQSk]
# nyan cat 10 hours
[http://youtu.be/9bZkp7q19f0]
# 4:54:00
[https://www.youtube.com/watch?v=jWlKjw3LBDk]
# 3:00:01
[https://www.youtube.com/watch?v=ub9JUDS_6i8]
# 10 hours rick roll
[https://www.youtube.com/watch?v=BROWqjuTM0g]
# 24 hours
[https://www.youtube.com/watch?v=FvHiLLkPhQE]
# 2 hours
[https://www.youtube.com/watch?v=VmOuW5zTt9w

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

@ -1,18 +1,18 @@
# mix of shorter/longer videos with/without ads, < 60 min
# 4:59
[http://youtu.be/pWI8RB2dmfU]
# 4:59 - can't embed
[https://www.youtube.com/watch?v=pWI8RB2dmfU]
# 0:46 ad at start
[http://youtu.be/6SFp1z7uA6g]
[https://www.youtube.com/embed/6SFp1z7uA6g?autoplay=1]
# 0:58 ad at start
[http://youtu.be/Aebs62bX0dA]
[https://www.youtube.com/embed/Aebs62bX0dA?autoplay=1]
# 1:43 ad
[https://www.youtube.com/watch?v=l5ODwR6FPRQ]
# 8:00 ad
[https://www.youtube.com/embed/l5ODwR6FPRQ?autoplay=1]
# 8:00 ad - can't embed
[https://www.youtube.com/watch?v=KlyXNRrsk4A]
# video with ad in beginning and in the middle 20:00
# https://bugzilla.mozilla.org/show_bug.cgi?id=1176815
[https://www.youtube.com/watch?v=cht9Xq9suGg]
[https://www.youtube.com/embed/cht9Xq9suGg?autoplay=1]
# 1:35 ad
[https://www.youtube.com/watch?v=orybDrUj4vA]
# 3:02 - ad
[https://youtu.be/tDDVAErOI5U]
[https://www.youtube.com/embed/orybDrUj4vA?autoplay=1]
# 3:02 ad
[https://www.youtube.com/embed/tDDVAErOI5U?autoplay=1]

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

@ -1,6 +0,0 @@
# a few longer videos, < 60 min total
# 0:30:00 no ad
[https://www.youtube.com/watch?v=-qXxNPvqHtQ]
# 0:20:00
[http://youtu.be/Fu2DcHzokew]

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

@ -1,11 +0,0 @@
# a few longer videos, < 120 min total
# video with ad in the middle
# 21:00
[https://www.youtube.com/watch?v=cht9Xq9suGg]
# 16:00
[https://www.youtube.com/watch?v=6Lm9EHhbJAY]
# 20:00
[https://www.youtube.com/watch?v=8XQ1onjXJK0]
# 59:06
[https://www.youtube.com/watch?v=kmpiY5kssU4]

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

@ -1,5 +0,0 @@
# 00:12
[https://youtu.be/AbAACm1IQE0]
# longer video with ads; < 15 min total
# 13:40
[https://www.youtube.com/watch?v=87uo2TPrsl8]

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

@ -1,5 +0,0 @@
# 1-2 longer videos with ads; < 15 minutes total
[https://www.youtube.com/watch?v=v678Em6qyzk]
[https://www.youtube.com/watch?v=l8XOZJkozfI]

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

@ -1,3 +1,6 @@
# It appears these are not currently used by tests. They are left here as they
# reference failure scenarios. If tese are fixed that can be removed.
# crash-data videos, < 15 minutes total
# hang | NtUserMessageCall | SendMessageW

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

@ -46,6 +46,7 @@
#if defined(MOZ_X11)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "X11UndefineNone.h"
#endif
#endif

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

@ -2610,7 +2610,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
#ifdef MOZ_WIDGET_GTK
Window root = GDK_ROOT_WINDOW();
#else
Window root = None; // Could XQueryTree, but this is not important.
Window root = X11None; // Could XQueryTree, but this is not important.
#endif
switch (anEvent.mMessage) {
@ -2628,7 +2628,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
event.y_root = rootPoint.y;
event.state = XInputEventState(mouseEvent);
// information lost
event.subwindow = None;
event.subwindow = X11None;
event.mode = -1;
event.detail = NotifyDetailNone;
event.same_screen = True;
@ -2647,7 +2647,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
event.y_root = rootPoint.y;
event.state = XInputEventState(mouseEvent);
// information lost
event.subwindow = None;
event.subwindow = X11None;
event.is_hint = NotifyNormal;
event.same_screen = True;
}
@ -2678,7 +2678,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
break;
}
// information lost:
event.subwindow = None;
event.subwindow = X11None;
event.same_screen = True;
}
break;
@ -2722,7 +2722,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
// Information that could be obtained from pluginEvent but we may not
// want to promise to provide:
event.subwindow = None;
event.subwindow = X11None;
event.x = 0;
event.y = 0;
event.x_root = -1;
@ -2764,7 +2764,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
XAnyEvent& event = pluginEvent.xany;
event.display = widget ?
static_cast<Display*>(widget->GetNativeData(NS_NATIVE_DISPLAY)) : nullptr;
event.window = None; // not a real window
event.window = X11None; // not a real window
// information lost:
event.serial = 0;
event.send_event = False;

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

@ -217,7 +217,7 @@ nsresult nsPluginNativeWindowGtk::CreateXEmbedWindow(bool aEnableXtFocus) {
GdkVisual* gdkVisual = gdk_drawable_get_visual(gdkWindow);
mWsInfo.depth = gdkVisual->depth;
#else
mWsInfo.colormap = None;
mWsInfo.colormap = X11None;
GdkVisual* gdkVisual = gdk_window_get_visual(gdkWindow);
mWsInfo.depth = gdk_visual_get_depth(gdkVisual);
#endif

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

@ -1282,7 +1282,7 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
}
}
if (aWindow.visualID != None
if (aWindow.visualID != X11None
&& gtk_check_version(2, 12, 10) != nullptr) { // older
// Workaround for a bug in Gtk+ (prior to 2.12.10) where deleting
// a foreign GdkColormap will also free the XColormap.

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

@ -81,7 +81,7 @@ pluginInstanceInit(InstanceData* instanceData)
instanceData->platformData->display = nullptr;
instanceData->platformData->visual = nullptr;
instanceData->platformData->colormap = None;
instanceData->platformData->colormap = X11None;
instanceData->platformData->plug = nullptr;
return NPERR_NO_ERROR;
@ -97,7 +97,7 @@ pluginInstanceShutdown(InstanceData* instanceData)
if (instanceData->hasWidget) {
Window window = reinterpret_cast<XID>(instanceData->window.window);
if (window != None) {
if (window != X11None) {
// This window XID should still be valid.
// See bug 429604 and bug 454756.
XWindowAttributes attributes;

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

@ -11,6 +11,7 @@
#ifdef MOZ_X11
#include <X11/extensions/Xrender.h>
#include <X11/Xlib.h>
#include "X11UndefineNone.h"
#endif
struct _cairo;
@ -87,7 +88,7 @@ public:
BorrowedXlibDrawable()
: mDT(nullptr),
mDisplay(nullptr),
mDrawable(None),
mDrawable(X11None),
mScreen(nullptr),
mVisual(nullptr),
mXRenderFormat(nullptr)
@ -96,7 +97,7 @@ public:
explicit BorrowedXlibDrawable(DrawTarget *aDT)
: mDT(nullptr),
mDisplay(nullptr),
mDrawable(None),
mDrawable(X11None),
mScreen(nullptr),
mVisual(nullptr),
mXRenderFormat(nullptr)

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

@ -2163,7 +2163,7 @@ DrawTargetCairo::Draw3DTransformedSurface(SourceSurface* aSurface, const Matrix4
0, nullptr);
XRenderComposite(display, PictOpSrc,
srcPict, None, dstPict,
srcPict, X11None, dstPict,
0, 0, 0, 0, 0, 0,
xformBounds.width, xformBounds.height);
@ -2313,7 +2313,7 @@ BorrowedXlibDrawable::Init(DrawTarget* aDT)
MOZ_ASSERT(aDT, "Caller should check for nullptr");
MOZ_ASSERT(!mDT, "Can't initialize twice!");
mDT = aDT;
mDrawable = None;
mDrawable = X11None;
#ifdef CAIRO_HAS_XLIB_SURFACE
if (aDT->GetBackendType() != BackendType::CAIRO ||
@ -2356,7 +2356,7 @@ BorrowedXlibDrawable::Finish()
cairo_surface_t* surf = cairo_get_group_target(cairoDT->mContext);
cairo_surface_mark_dirty(surf);
if (mDrawable) {
mDrawable = None;
mDrawable = X11None;
}
}
#endif

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

@ -11,6 +11,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "X11UndefineNone.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/StaticPtr.h"
@ -308,13 +309,13 @@ GLXPixmap
GLXLibrary::CreatePixmap(gfxASurface* aSurface)
{
if (!SupportsTextureFromPixmap(aSurface)) {
return None;
return X11None;
}
gfxXlibSurface* xs = static_cast<gfxXlibSurface*>(aSurface);
const XRenderPictFormat* format = xs->XRenderFormat();
if (!format || format->type != PictTypeDirect) {
return None;
return X11None;
}
const XRenderDirectFormat& direct = format->direct;
int alphaSize = FloorLog2(direct.alphaMask + 1);
@ -327,7 +328,7 @@ GLXLibrary::CreatePixmap(gfxASurface* aSurface)
(alphaSize ? LOCAL_GLX_BIND_TO_TEXTURE_RGBA_EXT
: LOCAL_GLX_BIND_TO_TEXTURE_RGB_EXT), True,
LOCAL_GLX_RENDER_TYPE, LOCAL_GLX_RGBA_BIT,
None };
X11None };
int numConfigs = 0;
Display* display = xs->XDisplay();
@ -351,7 +352,7 @@ GLXLibrary::CreatePixmap(gfxASurface* aSurface)
~(redMask | greenMask | blueMask) != -1UL << format->depth;
for (int i = 0; i < numConfigs; i++) {
int id = None;
int id = X11None;
sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &id);
Visual* visual;
int depth;
@ -424,14 +425,14 @@ GLXLibrary::CreatePixmap(gfxASurface* aSurface)
// caller should deal with this situation.
NS_WARN_IF_FALSE(format->depth == 8,
"[GLX] Couldn't find a FBConfig matching Pixmap format");
return None;
return X11None;
}
int pixmapAttribs[] = { LOCAL_GLX_TEXTURE_TARGET_EXT, LOCAL_GLX_TEXTURE_2D_EXT,
LOCAL_GLX_TEXTURE_FORMAT_EXT,
(alphaSize ? LOCAL_GLX_TEXTURE_FORMAT_RGBA_EXT
: LOCAL_GLX_TEXTURE_FORMAT_RGB_EXT),
None};
X11None};
GLXPixmap glxpixmap = xCreatePixmap(display,
cfgs[matchIndex],
@ -900,7 +901,7 @@ GLContextGLX::~GLContextGLX()
#ifdef DEBUG
bool success =
#endif
mGLX->xMakeCurrent(mDisplay, None, nullptr);
mGLX->xMakeCurrent(mDisplay, X11None, nullptr);
MOZ_ASSERT(success,
"glXMakeCurrent failed to release GL context before we call "
"glXDestroyContext!");
@ -1242,7 +1243,7 @@ GLContextGLX::FindFBConfigForWindow(Display* display, int screen, Window window,
#endif
for (int i = 0; i < numConfigs; i++) {
int visid = None;
int visid = X11None;
sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid);
if (!visid) {
continue;

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

@ -11,6 +11,7 @@
#include <X11/extensions/Xrender.h> // for XRenderPictFormat, etc
#include <X11/extensions/render.h> // for PictFormat
#include "cairo-xlib.h"
#include "X11UndefineNone.h"
#include <stdint.h> // for uint32_t
#include "GLDefs.h" // for GLenum
#include "gfxPlatform.h" // for gfxPlatform
@ -65,7 +66,7 @@ SurfaceDescriptorX11::SurfaceDescriptorX11(gfxXlibSurface* aSurf,
bool aForwardGLX)
: mId(aSurf->XDrawable())
, mSize(aSurf->GetSize())
, mGLXPixmap(None)
, mGLXPixmap(X11None)
{
const XRenderPictFormat *pictFormat = aSurf->XRenderFormat();
if (pictFormat) {
@ -86,7 +87,7 @@ SurfaceDescriptorX11::SurfaceDescriptorX11(Drawable aDrawable, XID aFormatID,
: mId(aDrawable)
, mFormat(aFormatID)
, mSize(aSize)
, mGLXPixmap(None)
, mGLXPixmap(X11None)
{ }
already_AddRefed<gfxXlibSurface>

27
gfx/src/X11UndefineNone.h Normal file
Просмотреть файл

@ -0,0 +1,27 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 MOZILLA_GFX_X11UNDEFINENONE_H_
#define MOZILLA_GFX_X11UNDEFINENONE_H_
// The header <X11/X.h> defines "None" as a macro that expands to "0L".
// This is terrible because many enumerations have an enumerator named "None".
// To work around this, we undefine the macro "None", and define a replacement
// macro named "X11None".
// Include this header after including X11 headers, where necessary.
#ifdef None
# undef None
# define X11None 0L
// <X11/X.h> also defines "RevertToNone" as a macro that expands to "(int)None".
// Since we are undefining "None", that stops working. To keep it working,
// we undefine "RevertToNone" and redefine it in terms of "X11None".
# ifdef RevertToNone
# undef RevertToNone
# define RevertToNone (int)X11None
# endif
#endif
#endif /* MOZILLA_GFX_X11UNDEFINENONE_H_ */

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

@ -29,7 +29,7 @@ FindVisualAndDepth(Display* aDisplay, VisualID aVisualID,
}
}
NS_ASSERTION(aVisualID == None, "VisualID not on Screen.");
NS_ASSERTION(aVisualID == X11None, "VisualID not on Screen.");
*aVisual = nullptr;
*aDepth = 0;
return;

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

@ -13,6 +13,7 @@
#if defined(MOZ_WIDGET_GTK)
# include <gdk/gdk.h>
# include <gdk/gdkx.h>
# include "X11UndefineNone.h"
#else
# error Unknown toolkit
#endif

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

@ -39,6 +39,7 @@ EXPORTS += [
'nsTransform2D.h',
'PingPongRegion.h',
'RegionBuilder.h',
'X11UndefineNone.h'
]
EXPORTS.mozilla += [

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

@ -25,7 +25,7 @@ using namespace mozilla::gfx;
gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual)
: mPixmapTaken(false), mDisplay(dpy), mDrawable(drawable)
#if defined(GL_PROVIDER_GLX)
, mGLXPixmap(None)
, mGLXPixmap(X11None)
#endif
{
const gfx::IntSize size = DoSizeQuery();
@ -36,7 +36,7 @@ gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual)
gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual, const gfx::IntSize& size)
: mPixmapTaken(false), mDisplay(dpy), mDrawable(drawable)
#if defined(GL_PROVIDER_GLX)
, mGLXPixmap(None)
, mGLXPixmap(X11None)
#endif
{
NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
@ -51,7 +51,7 @@ gfxXlibSurface::gfxXlibSurface(Screen *screen, Drawable drawable, XRenderPictFor
: mPixmapTaken(false), mDisplay(DisplayOfScreen(screen)),
mDrawable(drawable)
#if defined(GL_PROVIDER_GLX)
, mGLXPixmap(None)
, mGLXPixmap(X11None)
#endif
{
NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
@ -67,7 +67,7 @@ gfxXlibSurface::gfxXlibSurface(Screen *screen, Drawable drawable, XRenderPictFor
gfxXlibSurface::gfxXlibSurface(cairo_surface_t *csurf)
: mPixmapTaken(false)
#if defined(GL_PROVIDER_GLX)
, mGLXPixmap(None)
, mGLXPixmap(X11None)
#endif
{
NS_PRECONDITION(cairo_surface_status(csurf) == 0,
@ -97,9 +97,9 @@ CreatePixmap(Screen *screen, const gfx::IntSize& size, unsigned int depth,
Drawable relatedDrawable)
{
if (!Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT))
return None;
return X11None;
if (relatedDrawable == None) {
if (relatedDrawable == X11None) {
relatedDrawable = RootWindowOfScreen(screen);
}
Display *dpy = DisplayOfScreen(screen);
@ -274,7 +274,7 @@ gfxXlibSurface::Finish()
#if defined(GL_PROVIDER_GLX)
if (mPixmapTaken && mGLXPixmap) {
gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap);
mGLXPixmap = None;
mGLXPixmap = X11None;
}
#endif
gfxASurface::Finish();

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

@ -10,6 +10,7 @@
#include <X11/extensions/Xrender.h>
#include <X11/Xlib.h>
#include "X11UndefineNone.h"
#if defined(GL_PROVIDER_GLX)
#include "GLXLibrary.h"
@ -46,13 +47,13 @@ public:
// |screen| (if specified).
static already_AddRefed<gfxXlibSurface>
Create(Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size,
Drawable relatedDrawable = None);
Drawable relatedDrawable = X11None);
static cairo_surface_t *
CreateCairoSurface(Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size,
Drawable relatedDrawable = None);
Drawable relatedDrawable = X11None);
static already_AddRefed<gfxXlibSurface>
Create(Screen* screen, XRenderPictFormat *format, const mozilla::gfx::IntSize& size,
Drawable relatedDrawable = None);
Drawable relatedDrawable = X11None);
virtual ~gfxXlibSurface();

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

@ -482,7 +482,9 @@ void
ServoStyleSet::StyleNewSubtree(nsIContent* aContent)
{
MOZ_ASSERT(aContent->IsDirtyForServo());
Servo_RestyleSubtree(aContent, mRawSet.get());
if (aContent->IsElement() || aContent->IsNodeOfType(nsINode::eTEXT)) {
Servo_RestyleSubtree(aContent, mRawSet.get());
}
ClearDirtyBits(aContent);
}

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

@ -763,7 +763,7 @@ class IceTestPeer : public sigslot::has_slots<> {
remote->GetCandidates(i);
for (size_t j=0; j<candidates.size(); ++j) {
std::cerr << name_ << " Candidate: " + candidates[j] << std::endl;
std::cerr << name_ << " Adding remote candidate: " + candidates[j] << std::endl;
}
res = aStream->ParseAttributes(candidates);
ASSERT_TRUE(NS_SUCCEEDED(res));

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

@ -181,7 +181,8 @@ int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair
static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg)
{
int r,_status;
nr_ice_cand_pair *pair=cb_arg,*orig_pair;
nr_ice_cand_pair *pair=cb_arg;
nr_ice_cand_pair *actual_pair=0;
nr_ice_candidate *cand=0;
nr_stun_message *sres;
nr_transport_addr *request_src;
@ -256,14 +257,17 @@ static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg)
cand=TAILQ_FIRST(&pair->local->component->candidates);
while(cand){
if(!nr_transport_addr_cmp(&cand->addr,&pair->stun_client->results.ice_binding_response.mapped_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
if(!nr_transport_addr_cmp(&cand->addr,&pair->stun_client->results.ice_binding_response.mapped_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL)) {
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): found pre-existing local candidate of type %d for mapped address %s", pair->pctx->label,cand->type,cand->addr.as_string);
assert(cand->type != HOST);
break;
}
cand=TAILQ_NEXT(cand,entry_comp);
}
/* OK, nothing found, must be peer reflexive */
if(!cand) {
/* OK, nothing found, must be a new peer reflexive */
if (pair->pctx->ctx->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY) {
/* Any STUN response with a reflexive address in it is unwanted
when we'll send on relay only. Bail since cand is used below. */
@ -277,27 +281,31 @@ static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg)
ABORT(r);
cand->state=NR_ICE_CAND_STATE_INITIALIZED;
TAILQ_INSERT_TAIL(&pair->local->component->candidates,cand,entry_comp);
} else {
/* Check if we have a pair for this candidate already. */
if(r=nr_ice_media_stream_find_pair(pair->remote->stream, cand, pair->remote, &actual_pair)) {
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): no pair exists for %s and %s", pair->pctx->label,cand->addr.as_string, pair->remote->addr.as_string);
}
}
/* Note: we stomp the existing pair! */
orig_pair=pair;
if(r=nr_ice_candidate_pair_create(pair->pctx,cand,pair->remote,
&pair))
ABORT(r);
if(!actual_pair) {
if(r=nr_ice_candidate_pair_create(pair->pctx,cand,pair->remote, &actual_pair))
ABORT(r);
nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_SUCCEEDED);
if(r=nr_ice_component_insert_pair(actual_pair->remote->component,actual_pair))
ABORT(r);
if(r=nr_ice_component_insert_pair(pair->remote->component,pair))
ABORT(r);
/* If the original pair was nominated, make us nominated too. */
if(pair->peer_nominated)
actual_pair->peer_nominated=1;
/* If the original pair was nominated, make us nominated,
since we replace him*/
if(orig_pair->peer_nominated)
pair->peer_nominated=1;
/* Now mark the orig pair failed */
nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED);
}
/* Now mark the orig pair failed */
nr_ice_candidate_pair_set_state(orig_pair->pctx,orig_pair,NR_ICE_PAIR_STATE_FAILED);
assert(actual_pair);
nr_ice_candidate_pair_set_state(actual_pair->pctx,actual_pair,NR_ICE_PAIR_STATE_SUCCEEDED);
pair=actual_pair;
}

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

@ -913,3 +913,21 @@ void nr_ice_media_stream_role_change(nr_ice_media_stream *stream)
}
}
int nr_ice_media_stream_find_pair(nr_ice_media_stream *str, nr_ice_candidate *lcand, nr_ice_candidate *rcand, nr_ice_cand_pair **pair)
{
nr_ice_cand_pair_head *head = &str->check_list;
nr_ice_cand_pair *c1;
c1=TAILQ_FIRST(head);
while(c1){
if(c1->local == lcand &&
c1->remote == rcand) {
*pair=c1;
return(0);
}
c1=TAILQ_NEXT(c1,check_queue_entry);
}
return(R_NOT_FOUND);
}

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

@ -92,6 +92,7 @@ int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int compone
int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, UCHAR *data, int len);
int nr_ice_media_stream_get_active(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_ice_candidate **local, nr_ice_candidate **remote);
int nr_ice_media_stream_find_component(nr_ice_media_stream *str, int comp_id, nr_ice_component **compp);
int nr_ice_media_stream_find_pair(nr_ice_media_stream *str, nr_ice_candidate *local, nr_ice_candidate *remote, nr_ice_cand_pair **pair);
int nr_ice_media_stream_addrs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_transport_addr *local, nr_transport_addr *remote);
int
nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *attr);

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

@ -12,7 +12,6 @@ import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.JSONUtils;
import org.mozilla.gecko.util.NativeEventListener;
import org.mozilla.gecko.util.NativeJSObject;
import org.mozilla.gecko.util.WebActivityMapper;
import org.mozilla.gecko.widget.ExternalIntentDuringPrivateBrowsingPromptFragment;
import org.json.JSONArray;
@ -48,7 +47,6 @@ public final class IntentHelper implements GeckoEventListener,
"Intent:GetHandlers",
"Intent:Open",
"Intent:OpenForResult",
"WebActivity:Open"
};
private static final String[] NATIVE_EVENTS = {
@ -416,8 +414,6 @@ public final class IntentHelper implements GeckoEventListener,
open(message);
} else if (event.equals("Intent:OpenForResult")) {
openForResult(message);
} else if (event.equals("WebActivity:Open")) {
openWebActivity(message);
}
} catch (JSONException e) {
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
@ -572,11 +568,6 @@ public final class IntentHelper implements GeckoEventListener,
return UNKNOWN_PROTOCOL_URI_PREFIX + encodedUri;
}
private void openWebActivity(JSONObject message) throws JSONException {
final Intent intent = WebActivityMapper.getIntentForWebActivity(message.getJSONObject("activity"));
ActivityHandlerHelper.startIntentForActivity(activity, intent, new ResultHandler(message));
}
private static class ResultHandler implements ActivityResultHandler {
private final JSONObject message;

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

@ -139,7 +139,6 @@ gujar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x for x in
'util/UIAsyncTask.java',
'util/UUIDUtil.java',
'util/WeakReferenceHandler.java',
'util/WebActivityMapper.java',
'util/WindowUtils.java',
]]
gujar.extra_jars = [

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

@ -57,10 +57,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerParent",
XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
if (AppConstants.MOZ_SAFE_BROWSING) {
XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
"resource://gre/modules/SafeBrowsing.jsm");
}
XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
"resource://gre/modules/SafeBrowsing.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
"resource://gre/modules/BrowserUtils.jsm");
@ -549,10 +547,8 @@ var BrowserApp = {
InitLater(() => Services.search.init(), Services, "search");
InitLater(() => DownloadNotifications.init(), window, "DownloadNotifications");
if (AppConstants.MOZ_SAFE_BROWSING) {
// Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
InitLater(() => SafeBrowsing.init(), window, "SafeBrowsing");
}
// Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
InitLater(() => SafeBrowsing.init(), window, "SafeBrowsing");
InitLater(() => Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager));
InitLater(() => LoginManagerParent.init(), window, "LoginManagerParent");

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

@ -1,31 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict"
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Messaging.jsm");
function ActivitiesGlue() { }
ActivitiesGlue.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIActivityUIGlue]),
classID: Components.ID("{e4deb5f6-d5e3-4fce-bc53-901dd9951c48}"),
// Ignore aActivities results on Android, go straight to Android intents.
chooseActivity: function ap_chooseActivity(aOptions, aActivities, aCallback) {
Messaging.sendRequestForResult({
type: "WebActivity:Open",
activity: { name: aOptions.name, data: aOptions.data }
}).then((result) => {
aCallback.handleEvent(Ci.nsIActivityUIGlueCallback.NATIVE_ACTIVITY, result);
});
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ActivitiesGlue]);

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

@ -105,18 +105,23 @@ LoginManagerPrompter.prototype = {
*
*/
init : function (aWindow, aFactory) {
this._window = aWindow;
this._chromeWindow = this._getChromeWindow(aWindow).wrappedJSObject;
this._factory = aFactory || null;
this._browser = null;
var prefBranch = Services.prefs.getBranch("signon.");
this._debug = prefBranch.getBoolPref("debug");
this.log("===== initialized =====");
},
setE10sData : function (aBrowser, aOpener) {
throw new Error("This should be filled in when Android is multiprocess");
set browser(aBrowser) {
this._browser = aBrowser;
},
// setting this attribute is ignored because Android does not consider
// opener windows when displaying login notifications
set opener(aOpener) { },
/*
* promptToSavePassword
*
@ -140,10 +145,7 @@ LoginManagerPrompter.prototype = {
* Password string used in creating a doorhanger action
*/
_showLoginNotification : function (aBody, aButtons, aUsername, aPassword) {
let notifyWin = this._window.top;
let chromeWin = this._getChromeWindow(notifyWin).wrappedJSObject;
let browser = chromeWin.BrowserApp.getBrowserForWindow(notifyWin);
let tabID = chromeWin.BrowserApp.getTabForBrowser(browser).id;
let tabID = this._chromeWindow.BrowserApp.getTabForBrowser(this._browser).id;
let actionText = {
text: aUsername,
@ -334,6 +336,8 @@ LoginManagerPrompter.prototype = {
* Given a content DOM window, returns the chrome window it's in.
*/
_getChromeWindow: function (aWindow) {
if (aWindow instanceof Ci.nsIDOMChromeWindow)
return aWindow;
var chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
@ -350,8 +354,7 @@ LoginManagerPrompter.prototype = {
_getNativeWindow : function () {
let nativeWindow = null;
try {
let notifyWin = this._window.top;
let chromeWin = this._getChromeWindow(notifyWin).wrappedJSObject;
let chromeWin = this._chromeWindow;
if (chromeWin.NativeWindow) {
nativeWindow = chromeWin.NativeWindow;
} else {

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

@ -14,9 +14,7 @@ contract @mozilla.org/network/protocol/about;1?what=privatebrowsing {322ba47e-70
#ifdef MOZ_SERVICES_HEALTHREPORT
contract @mozilla.org/network/protocol/about;1?what=healthreport {322ba47e-7047-4f71-aebf-cb7d69325cd9}
#endif
#ifdef MOZ_SAFE_BROWSING
contract @mozilla.org/network/protocol/about;1?what=blocked {322ba47e-7047-4f71-aebf-cb7d69325cd9}
#endif
contract @mozilla.org/network/protocol/about;1?what=accounts {322ba47e-7047-4f71-aebf-cb7d69325cd9}
contract @mozilla.org/network/protocol/about;1?what=logins {322ba47e-7047-4f71-aebf-cb7d69325cd9}
@ -117,10 +115,6 @@ category update-timer Snippets @mozilla.org/snippets;1,getService,snippets-updat
component {430b987f-bb9f-46a3-99a5-241749220b29} ColorPicker.js
contract @mozilla.org/colorpicker;1 {430b987f-bb9f-46a3-99a5-241749220b29}
# AndroidActivitiesGlue.js
component {e4deb5f6-d5e3-4fce-bc53-901dd9951c48} AndroidActivitiesGlue.js
contract @mozilla.org/dom/activities/ui-glue;1 {e4deb5f6-d5e3-4fce-bc53-901dd9951c48}
# PersistentNotificationHandler.js
component {75390fe7-f8a3-423a-b3b1-258d7eabed40} PersistentNotificationHandler.js
contract @mozilla.org/persistent-notification-handler;1 {75390fe7-f8a3-423a-b3b1-258d7eabed40}

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

@ -18,7 +18,7 @@ let dataURI = "iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAC4klEQVRYhdWXLWzbQ
let image = atob(dataURI);
const IMAGE_ARRAYBUFFER = Uint8Array.from(image, byte => byte.charCodeAt(0)).buffer;
function backgroundScript() {
function background() {
browser.test.assertTrue("pageAction" in browser, "Namespace 'pageAction' exists in browser");
browser.test.assertTrue("show" in browser.pageAction, "API method 'show' exists in browser.pageAction");
@ -46,7 +46,7 @@ function backgroundScript() {
add_task(function* test_contentscript() {
let extension = ExtensionTestUtils.loadExtension({
background: "(" + backgroundScript.toString() + ")()",
background,
manifest: {
"name": "PageAction Extension",
"page_action": {

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

@ -21,7 +21,7 @@ let image = atob(dataURI);
const IMAGE_ARRAYBUFFER = Uint8Array.from(image, byte => byte.charCodeAt(0)).buffer;
add_task(function* test_contentscript() {
function backgroundScript() {
function background() {
// TODO: Use the Tabs API to obtain the tab ids for showing pageActions.
let tabId = 1;
let onClickedListenerEnabled = false;
@ -71,7 +71,7 @@ add_task(function* test_contentscript() {
}
let extension = ExtensionTestUtils.loadExtension({
background: `(${backgroundScript}())`,
background,
manifest: {
"name": "PageAction Extension",
"page_action": {
@ -83,11 +83,11 @@ add_task(function* test_contentscript() {
},
},
files: {
"default.html": `<html><head><meta charset="utf-8"><script src="popup.js"></${"script"}></head></html>`,
"default.html": `<html><head><meta charset="utf-8"><script src="popup.js"><\/script></head></html>`,
"extension.png": IMAGE_ARRAYBUFFER,
"a.html": `<html><head><meta charset="utf-8"><script src="popup.js"></${"script"}></head></html>`,
"b.html": `<html><head><meta charset="utf-8"><script src="popup.js"></${"script"}></head></html>`,
"popup.js": `(${popupScript})()`,
"a.html": `<html><head><meta charset="utf-8"><script src="popup.js"><\/script></head></html>`,
"b.html": `<html><head><meta charset="utf-8"><script src="popup.js"><\/script></head></html>`,
"popup.js": popupScript,
},
});

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

@ -13,7 +13,6 @@ XPIDL_MODULE = 'MobileComponents'
EXTRA_COMPONENTS += [
'AboutRedirector.js',
'AddonUpdateService.js',
'AndroidActivitiesGlue.js',
'BlocklistPrompt.js',
'BrowserCLH.js',
'ColorPicker.js',

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