@@ -546,7 +546,7 @@ loop.roomViews = (function(mozL10n) {
var urlDescription = url && url.description || "";
var location = url && url.location || "";
- var cx = React.addons.classSet;
+ var cx = classNames;
var availableContext = this.state.availableContext;
return (
diff --git a/browser/components/loop/content/panel.html b/browser/components/loop/content/panel.html
index 71924073861..3ae4cd4f098 100644
--- a/browser/components/loop/content/panel.html
+++ b/browser/components/loop/content/panel.html
@@ -17,6 +17,7 @@
+
diff --git a/browser/components/loop/content/shared/js/textChatView.js b/browser/components/loop/content/shared/js/textChatView.js
index ae6a58ba10b..d0be68cdef9 100644
--- a/browser/components/loop/content/shared/js/textChatView.js
+++ b/browser/components/loop/content/shared/js/textChatView.js
@@ -48,7 +48,7 @@ loop.shared.views.chat = (function(mozL10n) {
},
render: function() {
- var classes = React.addons.classSet({
+ var classes = classNames({
"text-chat-entry": true,
"received": this.props.type === CHAT_MESSAGE_TYPES.RECEIVED,
"sent": this.props.type === CHAT_MESSAGE_TYPES.SENT,
@@ -165,7 +165,7 @@ loop.shared.views.chat = (function(mozL10n) {
/* Keep track of the last printed timestamp. */
var lastTimestamp = 0;
- var entriesClasses = React.addons.classSet({
+ var entriesClasses = classNames({
"text-chat-entries": true
});
@@ -395,7 +395,7 @@ loop.shared.views.chat = (function(mozL10n) {
return item.type === CHAT_MESSAGE_TYPES.SENT;
});
- var textChatViewClasses = React.addons.classSet({
+ var textChatViewClasses = classNames({
"text-chat-view": true,
"text-chat-entries-empty": !messageList.length,
"text-chat-disabled": !this.state.textChatEnabled
diff --git a/browser/components/loop/content/shared/js/textChatView.jsx b/browser/components/loop/content/shared/js/textChatView.jsx
index 2d0a9988122..a2b879c72d4 100644
--- a/browser/components/loop/content/shared/js/textChatView.jsx
+++ b/browser/components/loop/content/shared/js/textChatView.jsx
@@ -48,7 +48,7 @@ loop.shared.views.chat = (function(mozL10n) {
},
render: function() {
- var classes = React.addons.classSet({
+ var classes = classNames({
"text-chat-entry": true,
"received": this.props.type === CHAT_MESSAGE_TYPES.RECEIVED,
"sent": this.props.type === CHAT_MESSAGE_TYPES.SENT,
@@ -165,7 +165,7 @@ loop.shared.views.chat = (function(mozL10n) {
/* Keep track of the last printed timestamp. */
var lastTimestamp = 0;
- var entriesClasses = React.addons.classSet({
+ var entriesClasses = classNames({
"text-chat-entries": true
});
@@ -395,7 +395,7 @@ loop.shared.views.chat = (function(mozL10n) {
return item.type === CHAT_MESSAGE_TYPES.SENT;
});
- var textChatViewClasses = React.addons.classSet({
+ var textChatViewClasses = classNames({
"text-chat-view": true,
"text-chat-entries-empty": !messageList.length,
"text-chat-disabled": !this.state.textChatEnabled
diff --git a/browser/components/loop/content/shared/js/views.js b/browser/components/loop/content/shared/js/views.js
index d2a5262c917..53a90c95367 100644
--- a/browser/components/loop/content/shared/js/views.js
+++ b/browser/components/loop/content/shared/js/views.js
@@ -70,7 +70,7 @@ loop.shared.views = (function(_, mozL10n) {
},
_getClasses: function() {
- var cx = React.addons.classSet;
+ var cx = classNames;
// classes
var classesObj = {
"btn": true,
@@ -170,7 +170,7 @@ loop.shared.views = (function(_, mozL10n) {
return null;
}
- var cx = React.addons.classSet;
+ var cx = classNames;
var isActive = this.props.state === SCREEN_SHARE_STATES.ACTIVE;
var screenShareClasses = cx({
@@ -304,7 +304,7 @@ loop.shared.views = (function(_, mozL10n) {
* Recover the needed info for generating an specific menu Item
*/
getItemInfo: function(menuItem) {
- var cx = React.addons.classSet;
+ var cx = classNames;
switch (menuItem.id) {
case "help":
return {
@@ -362,7 +362,7 @@ loop.shared.views = (function(_, mozL10n) {
return null;
}
- var cx = React.addons.classSet;
+ var cx = classNames;
var settingsDropdownMenuClasses = cx({
"settings-menu": true,
"dropdown-menu": true,
@@ -494,7 +494,7 @@ loop.shared.views = (function(_, mozL10n) {
return null;
}
- var cx = React.addons.classSet;
+ var cx = classNames;
var conversationToolbarCssClasses = cx({
"conversation-toolbar": true,
"idle": this.state.idle
@@ -642,7 +642,7 @@ loop.shared.views = (function(_, mozL10n) {
},
render: function() {
- var cx = React.addons.classSet;
+ var cx = classNames;
var classObject = { button: true, disabled: this.props.disabled };
if (this.props.additionalClass) {
classObject[this.props.additionalClass] = true;
@@ -675,7 +675,7 @@ loop.shared.views = (function(_, mozL10n) {
},
render: function() {
- var cx = React.addons.classSet;
+ var cx = classNames;
var classObject = { "button-group": true };
if (this.props.additionalClass) {
classObject[this.props.additionalClass] = true;
@@ -742,7 +742,7 @@ loop.shared.views = (function(_, mozL10n) {
},
render: function() {
- var cx = React.addons.classSet;
+ var cx = classNames;
var wrapperClasses = {
"checkbox-wrapper": true,
disabled: this.props.disabled
@@ -860,7 +860,7 @@ loop.shared.views = (function(_, mozL10n) {
"shared/img/icons-16x16.svg#globe";
}
- var wrapperClasses = React.addons.classSet({
+ var wrapperClasses = classNames({
"context-wrapper": true,
"clicks-allowed": this.props.allowClick
});
@@ -1076,17 +1076,17 @@ loop.shared.views = (function(_, mozL10n) {
},
render: function() {
- var remoteStreamClasses = React.addons.classSet({
+ var remoteStreamClasses = classNames({
"remote": true,
"focus-stream": !this.props.displayScreenShare
});
- var screenShareStreamClasses = React.addons.classSet({
+ var screenShareStreamClasses = classNames({
"screen": true,
"focus-stream": this.props.displayScreenShare
});
- var mediaWrapperClasses = React.addons.classSet({
+ var mediaWrapperClasses = classNames({
"media-wrapper": true,
"receiving-screen-share": this.props.displayScreenShare,
"showing-local-streams": this.props.localSrcMediaElement ||
diff --git a/browser/components/loop/content/shared/js/views.jsx b/browser/components/loop/content/shared/js/views.jsx
index b90eaebbf3c..5e8965b0a0b 100644
--- a/browser/components/loop/content/shared/js/views.jsx
+++ b/browser/components/loop/content/shared/js/views.jsx
@@ -70,7 +70,7 @@ loop.shared.views = (function(_, mozL10n) {
},
_getClasses: function() {
- var cx = React.addons.classSet;
+ var cx = classNames;
// classes
var classesObj = {
"btn": true,
@@ -170,7 +170,7 @@ loop.shared.views = (function(_, mozL10n) {
return null;
}
- var cx = React.addons.classSet;
+ var cx = classNames;
var isActive = this.props.state === SCREEN_SHARE_STATES.ACTIVE;
var screenShareClasses = cx({
@@ -304,7 +304,7 @@ loop.shared.views = (function(_, mozL10n) {
* Recover the needed info for generating an specific menu Item
*/
getItemInfo: function(menuItem) {
- var cx = React.addons.classSet;
+ var cx = classNames;
switch (menuItem.id) {
case "help":
return {
@@ -362,7 +362,7 @@ loop.shared.views = (function(_, mozL10n) {
return null;
}
- var cx = React.addons.classSet;
+ var cx = classNames;
var settingsDropdownMenuClasses = cx({
"settings-menu": true,
"dropdown-menu": true,
@@ -494,7 +494,7 @@ loop.shared.views = (function(_, mozL10n) {
return null;
}
- var cx = React.addons.classSet;
+ var cx = classNames;
var conversationToolbarCssClasses = cx({
"conversation-toolbar": true,
"idle": this.state.idle
@@ -642,7 +642,7 @@ loop.shared.views = (function(_, mozL10n) {
},
render: function() {
- var cx = React.addons.classSet;
+ var cx = classNames;
var classObject = { button: true, disabled: this.props.disabled };
if (this.props.additionalClass) {
classObject[this.props.additionalClass] = true;
@@ -675,7 +675,7 @@ loop.shared.views = (function(_, mozL10n) {
},
render: function() {
- var cx = React.addons.classSet;
+ var cx = classNames;
var classObject = { "button-group": true };
if (this.props.additionalClass) {
classObject[this.props.additionalClass] = true;
@@ -742,7 +742,7 @@ loop.shared.views = (function(_, mozL10n) {
},
render: function() {
- var cx = React.addons.classSet;
+ var cx = classNames;
var wrapperClasses = {
"checkbox-wrapper": true,
disabled: this.props.disabled
@@ -860,7 +860,7 @@ loop.shared.views = (function(_, mozL10n) {
"shared/img/icons-16x16.svg#globe";
}
- var wrapperClasses = React.addons.classSet({
+ var wrapperClasses = classNames({
"context-wrapper": true,
"clicks-allowed": this.props.allowClick
});
@@ -1076,17 +1076,17 @@ loop.shared.views = (function(_, mozL10n) {
},
render: function() {
- var remoteStreamClasses = React.addons.classSet({
+ var remoteStreamClasses = classNames({
"remote": true,
"focus-stream": !this.props.displayScreenShare
});
- var screenShareStreamClasses = React.addons.classSet({
+ var screenShareStreamClasses = classNames({
"screen": true,
"focus-stream": this.props.displayScreenShare
});
- var mediaWrapperClasses = React.addons.classSet({
+ var mediaWrapperClasses = classNames({
"media-wrapper": true,
"receiving-screen-share": this.props.displayScreenShare,
"showing-local-streams": this.props.localSrcMediaElement ||
diff --git a/browser/components/loop/content/shared/libs/classnames-2.2.0.js b/browser/components/loop/content/shared/libs/classnames-2.2.0.js
new file mode 100644
index 00000000000..0d336d9cb9c
--- /dev/null
+++ b/browser/components/loop/content/shared/libs/classnames-2.2.0.js
@@ -0,0 +1,48 @@
+/*!
+ Copyright (c) 2015 Jed Watson.
+ Licensed under the MIT License (MIT), see
+ http://jedwatson.github.io/classnames
+*/
+/* global define */
+
+(function () {
+ 'use strict';
+
+ var hasOwn = {}.hasOwnProperty;
+
+ function classNames () {
+ var classes = '';
+
+ for (var i = 0; i < arguments.length; i++) {
+ var arg = arguments[i];
+ if (!arg) continue;
+
+ var argType = typeof arg;
+
+ if (argType === 'string' || argType === 'number') {
+ classes += ' ' + arg;
+ } else if (Array.isArray(arg)) {
+ classes += ' ' + classNames.apply(null, arg);
+ } else if (argType === 'object') {
+ for (var key in arg) {
+ if (hasOwn.call(arg, key) && arg[key]) {
+ classes += ' ' + key;
+ }
+ }
+ }
+ }
+
+ return classes.substr(1);
+ }
+
+ if (typeof module !== 'undefined' && module.exports) {
+ module.exports = classNames;
+ } else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
+ // register as 'classnames', consistent with npm package name
+ define('classnames', function () {
+ return classNames;
+ });
+ } else {
+ window.classNames = classNames;
+ }
+}());
diff --git a/browser/components/loop/jar.mn b/browser/components/loop/jar.mn
index 0d06c3f801c..083139a3e15 100644
--- a/browser/components/loop/jar.mn
+++ b/browser/components/loop/jar.mn
@@ -114,6 +114,7 @@ browser.jar:
#endif
content/browser/loop/shared/libs/lodash-3.9.3.js (content/shared/libs/lodash-3.9.3.js)
content/browser/loop/shared/libs/backbone-1.2.1.js (content/shared/libs/backbone-1.2.1.js)
+ content/browser/loop/shared/libs/classnames-2.2.0.js (content/shared/libs/classnames-2.2.0.js)
# Shared sounds
content/browser/loop/shared/sounds/ringtone.ogg (content/shared/sounds/ringtone.ogg)
diff --git a/browser/components/loop/standalone/content/js/standaloneRoomViews.js b/browser/components/loop/standalone/content/js/standaloneRoomViews.js
index ba356a777db..0247f8a8ce9 100644
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js
@@ -80,7 +80,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
mozL10n.get("rooms_room_joined_own_conversation_label") :
mozL10n.get("rooms_room_join_label");
- var buttonClasses = React.addons.classSet({
+ var buttonClasses = classNames({
btn: true,
"btn-info": true,
disabled: this.state.roomState === ROOM_STATES.JOINED
@@ -325,7 +325,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
var isChrome = utils.isChrome(navigator.userAgent);
var isFirefox = utils.isFirefox(navigator.userAgent);
var isOpera = utils.isOpera(navigator.userAgent);
- var promptMediaMessageClasses = React.addons.classSet({
+ var promptMediaMessageClasses = classNames({
"prompt-media-message": true,
"chrome": isChrome,
"firefox": isFirefox,
diff --git a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
index c810d4d7417..077132d241d 100644
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
@@ -80,7 +80,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
mozL10n.get("rooms_room_joined_own_conversation_label") :
mozL10n.get("rooms_room_join_label");
- var buttonClasses = React.addons.classSet({
+ var buttonClasses = classNames({
btn: true,
"btn-info": true,
disabled: this.state.roomState === ROOM_STATES.JOINED
@@ -325,7 +325,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
var isChrome = utils.isChrome(navigator.userAgent);
var isFirefox = utils.isFirefox(navigator.userAgent);
var isOpera = utils.isOpera(navigator.userAgent);
- var promptMediaMessageClasses = React.addons.classSet({
+ var promptMediaMessageClasses = classNames({
"prompt-media-message": true,
"chrome": isChrome,
"firefox": isFirefox,
diff --git a/browser/components/loop/standalone/content/webappEntryPoint.js b/browser/components/loop/standalone/content/webappEntryPoint.js
index 8ff77d65664..d8460530117 100644
--- a/browser/components/loop/standalone/content/webappEntryPoint.js
+++ b/browser/components/loop/standalone/content/webappEntryPoint.js
@@ -38,9 +38,11 @@ if (typeof __PROD__ !== "undefined") {
// pull in the unbuilt version from node_modules
require("expose?React!react");
require("expose?React!react/addons");
+ require("expose?classNames!classnames");
} else {
// our development server setup doesn't yet handle real modules, so for now...
require("shared/libs/react-0.12.2.js");
+ require("shared/libs/classnames-2.2.0.js");
}
diff --git a/browser/components/loop/standalone/package.json b/browser/components/loop/standalone/package.json
index 961a42691ff..0675f6793d2 100644
--- a/browser/components/loop/standalone/package.json
+++ b/browser/components/loop/standalone/package.json
@@ -12,6 +12,7 @@
},
"dependencies": {},
"devDependencies": {
+ "classnames": "2.2.x",
"compression": "1.5.x",
"eslint": "1.6.x",
"eslint-plugin-mozilla": "../../../../testing/eslint-plugin-mozilla",
diff --git a/browser/components/loop/test/desktop-local/index.html b/browser/components/loop/test/desktop-local/index.html
index d2c924ab21a..1b6446ad0f0 100644
--- a/browser/components/loop/test/desktop-local/index.html
+++ b/browser/components/loop/test/desktop-local/index.html
@@ -31,6 +31,7 @@
+
diff --git a/browser/components/loop/test/karma/karma.coverage.desktop.js b/browser/components/loop/test/karma/karma.coverage.desktop.js
index 3ad8a42dd43..8ad6f46eb20 100644
--- a/browser/components/loop/test/karma/karma.coverage.desktop.js
+++ b/browser/components/loop/test/karma/karma.coverage.desktop.js
@@ -12,6 +12,7 @@ module.exports = function(config) {
baseConfig.files = baseConfig.files.concat([
"content/libs/l10n.js",
"content/shared/libs/react-0.12.2.js",
+ "content/shared/libs/classnames-2.2.0.js",
"content/shared/libs/lodash-3.9.3.js",
"content/shared/libs/backbone-1.2.1.js",
"test/shared/vendor/*.js",
diff --git a/browser/components/loop/test/karma/karma.coverage.shared_standalone.js b/browser/components/loop/test/karma/karma.coverage.shared_standalone.js
index 6f6e40454f9..7d511f42b0e 100644
--- a/browser/components/loop/test/karma/karma.coverage.shared_standalone.js
+++ b/browser/components/loop/test/karma/karma.coverage.shared_standalone.js
@@ -14,6 +14,7 @@ module.exports = function(config) {
"content/shared/libs/lodash-3.9.3.js",
"content/shared/libs/backbone-1.2.1.js",
"content/shared/libs/react-0.12.2.js",
+ "content/shared/libs/classnames-2.2.0.js",
"content/shared/libs/sdk.js",
"test/shared/vendor/*.js",
"test/karma/head.js", // Add test fixture container
diff --git a/browser/components/loop/test/shared/index.html b/browser/components/loop/test/shared/index.html
index 969dc7b3724..507d2f183a4 100644
--- a/browser/components/loop/test/shared/index.html
+++ b/browser/components/loop/test/shared/index.html
@@ -30,6 +30,7 @@
+
diff --git a/browser/components/loop/test/standalone/index.html b/browser/components/loop/test/standalone/index.html
index 1094249fd48..00278b91afe 100644
--- a/browser/components/loop/test/standalone/index.html
+++ b/browser/components/loop/test/standalone/index.html
@@ -31,6 +31,7 @@
+
diff --git a/browser/components/loop/ui/index.html b/browser/components/loop/ui/index.html
index ea5f205d146..06bbda26cc6 100644
--- a/browser/components/loop/ui/index.html
+++ b/browser/components/loop/ui/index.html
@@ -28,6 +28,7 @@
+
diff --git a/browser/components/loop/ui/ui-showcase.js b/browser/components/loop/ui/ui-showcase.js
index 95a139092cd..0b21db52cd3 100644
--- a/browser/components/loop/ui/ui-showcase.js
+++ b/browser/components/loop/ui/ui-showcase.js
@@ -556,7 +556,7 @@
width += 2;
}
- var cx = React.addons.classSet;
+ var cx = classNames;
return (
React.createElement("div", {className: "example"},
React.createElement("h3", {id: this.makeId()},
diff --git a/browser/components/loop/ui/ui-showcase.jsx b/browser/components/loop/ui/ui-showcase.jsx
index ddf52e12d34..fe8884d6e61 100644
--- a/browser/components/loop/ui/ui-showcase.jsx
+++ b/browser/components/loop/ui/ui-showcase.jsx
@@ -556,7 +556,7 @@
width += 2;
}
- var cx = React.addons.classSet;
+ var cx = classNames;
return (
diff --git a/build.gradle b/build.gradle
index 7b834f0f0d3..d8ac18b8cdc 100644
--- a/build.gradle
+++ b/build.gradle
@@ -115,7 +115,6 @@ idea {
excludeDirs -= file(topobjdir)
excludeDirs += files(file(topobjdir).listFiles())
excludeDirs -= file("${topobjdir}/gradle")
- excludeDirs -= file("${topobjdir}/mobile")
}
if (!mozconfig.substs.MOZ_INSTALL_TRACKING) {
diff --git a/build/mach_bootstrap.py b/build/mach_bootstrap.py
index 9b24aeb4af4..6d6f6ef453b 100644
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -41,25 +41,6 @@ Note: `{mach} mercurial-setup` does not make any changes without prompting
you first.
'''.strip()
-OLD_MERCURIAL_TOOLS = '''
-*** MERCURIAL CONFIGURATION POTENTIALLY OUT OF DATE ***
-
-mach has detected that it has been a while since you have run
-`{mach} mercurial-setup`.
-
-Having the latest Mercurial tools and configuration should lead to a better,
-more productive experience when working on Mozilla projects.
-
-Please run `{mach} mercurial-setup` now.
-
-Reminder: `{mach} mercurial-setup` does not make any changes without
-prompting you first.
-
-To avoid this message in the future, run `{mach} mercurial-setup` once a month.
-Or, schedule `{mach} mercurial-setup --update-only` to run automatically in
-the background at least once a month.
-'''.strip()
-
MERCURIAL_SETUP_FATAL_INTERVAL = 31 * 24 * 60 * 60
@@ -281,9 +262,6 @@ def bootstrap(topsrcdir, mozilla_dir=None):
if mtime is None:
print(NO_MERCURIAL_SETUP.format(mach=sys.argv[0]), file=sys.stderr)
sys.exit(2)
- elif time.time() - mtime > MERCURIAL_SETUP_FATAL_INTERVAL:
- print(OLD_MERCURIAL_TOOLS.format(mach=sys.argv[0]), file=sys.stderr)
- sys.exit(2)
def populate_context(context, key=None):
if key is None:
diff --git a/chrome/moz.build b/chrome/moz.build
index c4ee0f64f5f..724f39cb32e 100644
--- a/chrome/moz.build
+++ b/chrome/moz.build
@@ -28,11 +28,8 @@ include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
-GENERATED_INCLUDES += [
- '/xpcom',
-]
-
LOCAL_INCLUDES += [
+ '!/xpcom',
'/dom/base',
'/netwerk/base',
'/netwerk/protocol/res',
diff --git a/devtools/client/debugger/test/mochitest/browser.ini b/devtools/client/debugger/test/mochitest/browser.ini
index 3083a63cc8f..267de1c9a57 100644
--- a/devtools/client/debugger/test/mochitest/browser.ini
+++ b/devtools/client/debugger/test/mochitest/browser.ini
@@ -416,7 +416,7 @@ skip-if = e10s && debug
[browser_dbg_search-sources-03.js]
skip-if = e10s && debug
[browser_dbg_search-symbols.js]
-skip-if = e10s && debug
+skip-if = (e10s && debug) || os == "linux" # Bug 1132375
[browser_dbg_searchbox-help-popup-01.js]
skip-if = e10s && debug
[browser_dbg_searchbox-help-popup-02.js]
diff --git a/docshell/base/nsIContentViewer.idl b/docshell/base/nsIContentViewer.idl
index 507a5f41e27..6d53ecd59db 100644
--- a/docshell/base/nsIContentViewer.idl
+++ b/docshell/base/nsIContentViewer.idl
@@ -31,10 +31,9 @@ class nsDOMNavigationTiming;
[ptr] native nsDOMNavigationTimingPtr(nsDOMNavigationTiming);
[ref] native nsIContentViewerTArray(nsTArray >);
-[scriptable, builtinclass, uuid(702e0a92-7d63-490e-b5ee-d247e6bd4588)]
+[scriptable, builtinclass, uuid(fbd04c99-e149-473f-8a68-44f53d82f98b)]
interface nsIContentViewer : nsISupports
{
-
[noscript] void init(in nsIWidgetPtr aParentWidget,
[const] in nsIntRectRef aBounds);
@@ -245,27 +244,6 @@ interface nsIContentViewer : nsISupports
*/
[noscript] void appendSubtree(in nsIContentViewerTArray array);
- /**
- * Set the maximum line width for the document.
- * NOTE: This will generate a reflow!
- *
- * @param maxLineWidth The maximum width of any line boxes on the page,
- * in CSS pixels.
- */
- void changeMaxLineBoxWidth(in int32_t maxLineBoxWidth);
-
- /**
- * Instruct the refresh driver to discontinue painting until further
- * notice.
- */
- void pausePainting();
-
- /**
- * Instruct the refresh driver to resume painting after a previous call to
- * pausePainting().
- */
- void resumePainting();
-
/*
* Render the document as if being viewed on a device with the specified
* media type. This will cause a reflow.
diff --git a/dom/base/DOMException.cpp b/dom/base/DOMException.cpp
index 8c7b480805f..d9af6d6034c 100644
--- a/dom/base/DOMException.cpp
+++ b/dom/base/DOMException.cpp
@@ -87,6 +87,9 @@ enum DOM4ErrorTypeCodeMap {
BtAuthFailureError = 0,
BtRmtDevDownError = 0,
BtAuthRejectedError = 0,
+
+ /* Push API errors */
+ PermissionDeniedError = 0,
};
#define DOM4_MSG_DEF(name, message, nsresult) {(nsresult), name, #name, message},
diff --git a/dom/base/domerr.msg b/dom/base/domerr.msg
index bf6e5b03793..5c8a63d87ae 100644
--- a/dom/base/domerr.msg
+++ b/dom/base/domerr.msg
@@ -151,5 +151,11 @@ DOM4_MSG_DEF(InvalidStateError, "A mutation operation was attempted on a file st
DOM4_MSG_DEF(AbortError, "A request was aborted, for example through a call to FileHandle.abort.", NS_ERROR_DOM_FILEHANDLE_ABORT_ERR)
DOM4_MSG_DEF(QuotaExceededError, "The current file handle exceeded its quota limitations.", NS_ERROR_DOM_FILEHANDLE_QUOTA_ERR)
+/* Push API errors. */
+DOM4_MSG_DEF(InvalidStateError, "Invalid service worker registration.", NS_ERROR_DOM_PUSH_INVALID_REGISTRATION_ERR)
+DOM4_MSG_DEF(PermissionDeniedError, "User denied permission to use the Push API.", NS_ERROR_DOM_PUSH_DENIED_ERR)
+DOM4_MSG_DEF(AbortError, "Error retrieving push subscription.", NS_ERROR_DOM_PUSH_ABORT_ERR)
+DOM4_MSG_DEF(NetworkError, "Push service unreachable.", NS_ERROR_DOM_PUSH_SERVICE_UNREACHABLE)
+
DOM_MSG_DEF(NS_ERROR_DOM_JS_EXCEPTION, "A callback threw an exception")
DOM_MSG_DEF(NS_ERROR_DOM_DOMEXCEPTION, "A DOMException was thrown")
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index 11afb6378c2..a0be3224045 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -386,30 +386,14 @@ CandidatesTraverse(CustomElementHashKey* aKey,
return PL_DHASH_NEXT;
}
-struct CustomDefinitionTraceArgs
-{
- const TraceCallbacks& callbacks;
- void* closure;
-};
-
-static PLDHashOperator
-CustomDefinitionTrace(CustomElementHashKey *aKey,
- CustomElementDefinition *aData,
- void *aArg)
-{
- CustomDefinitionTraceArgs* traceArgs = static_cast(aArg);
- MOZ_ASSERT(aData, "Definition must not be null");
- traceArgs->callbacks.Trace(&aData->mPrototype, "mCustomDefinitions prototype",
- traceArgs->closure);
- return PL_DHASH_NEXT;
-}
-
NS_IMPL_CYCLE_COLLECTION_CLASS(Registry)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Registry)
- CustomDefinitionTraceArgs customDefinitionArgs = { aCallbacks, aClosure };
- tmp->mCustomDefinitions.EnumerateRead(CustomDefinitionTrace,
- &customDefinitionArgs);
+ for (auto iter = tmp->mCustomDefinitions.Iter(); !iter.Done(); iter.Next()) {
+ aCallbacks.Trace(&iter.UserData()->mPrototype,
+ "mCustomDefinitions prototype",
+ aClosure);
+ }
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Registry)
@@ -941,57 +925,16 @@ nsExternalResourceMap::RequestResource(nsIURI* aURI,
return nullptr;
}
-struct
-nsExternalResourceEnumArgs
-{
- nsIDocument::nsSubDocEnumFunc callback;
- void *data;
-};
-
-static PLDHashOperator
-ExternalResourceEnumerator(nsIURI* aKey,
- nsExternalResourceMap::ExternalResource* aData,
- void* aClosure)
-{
- nsExternalResourceEnumArgs* args =
- static_cast(aClosure);
- bool next =
- aData->mDocument ? args->callback(aData->mDocument, args->data) : true;
- return next ? PL_DHASH_NEXT : PL_DHASH_STOP;
-}
-
void
nsExternalResourceMap::EnumerateResources(nsIDocument::nsSubDocEnumFunc aCallback,
void* aData)
{
- nsExternalResourceEnumArgs args = { aCallback, aData };
- mMap.EnumerateRead(ExternalResourceEnumerator, &args);
-}
-
-static PLDHashOperator
-ExternalResourceTraverser(nsIURI* aKey,
- nsExternalResourceMap::ExternalResource* aData,
- void* aClosure)
-{
- nsCycleCollectionTraversalCallback *cb =
- static_cast(aClosure);
-
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
- "mExternalResourceMap.mMap entry"
- "->mDocument");
- cb->NoteXPCOMChild(aData->mDocument);
-
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
- "mExternalResourceMap.mMap entry"
- "->mViewer");
- cb->NoteXPCOMChild(aData->mViewer);
-
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
- "mExternalResourceMap.mMap entry"
- "->mLoadGroup");
- cb->NoteXPCOMChild(aData->mLoadGroup);
-
- return PL_DHASH_NEXT;
+ for (auto iter = mMap.Iter(); !iter.Done(); iter.Next()) {
+ nsExternalResourceMap::ExternalResource* resource = iter.UserData();
+ if (resource->mDocument && !aCallback(resource->mDocument, aData)) {
+ break;
+ }
+ }
}
void
@@ -999,7 +942,24 @@ nsExternalResourceMap::Traverse(nsCycleCollectionTraversalCallback* aCallback) c
{
// mPendingLoads will get cleared out as the requests complete, so
// no need to worry about those here.
- mMap.EnumerateRead(ExternalResourceTraverser, aCallback);
+ for (auto iter = mMap.ConstIter(); !iter.Done(); iter.Next()) {
+ nsExternalResourceMap::ExternalResource* resource = iter.UserData();
+
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback,
+ "mExternalResourceMap.mMap entry"
+ "->mDocument");
+ aCallback->NoteXPCOMChild(resource->mDocument);
+
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback,
+ "mExternalResourceMap.mMap entry"
+ "->mViewer");
+ aCallback->NoteXPCOMChild(resource->mViewer);
+
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback,
+ "mExternalResourceMap.mMap entry"
+ "->mLoadGroup");
+ aCallback->NoteXPCOMChild(resource->mLoadGroup);
+ }
}
static PLDHashOperator
diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp
index 1653edd3c7a..eee2ef1863e 100644
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -121,26 +121,17 @@ nsFrameMessageManager::~nsFrameMessageManager()
}
}
-static PLDHashOperator
-CycleCollectorTraverseListeners(const nsAString& aKey,
- nsAutoTObserverArray* aListeners,
- void* aCb)
-{
- nsCycleCollectionTraversalCallback* cb =
- static_cast (aCb);
- uint32_t count = aListeners->Length();
- for (uint32_t i = 0; i < count; ++i) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "listeners[i] mStrongListener");
- cb->NoteXPCOMChild(aListeners->ElementAt(i).mStrongListener.get());
- }
- return PL_DHASH_NEXT;
-}
-
NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameMessageManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager)
- tmp->mListeners.EnumerateRead(CycleCollectorTraverseListeners,
- static_cast(&cb));
+ for (auto iter = tmp->mListeners.Iter(); !iter.Done(); iter.Next()) {
+ nsAutoTObserverArray* listeners = iter.UserData();
+ uint32_t count = listeners->Length();
+ for (uint32_t i = 0; i < count; ++i) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "listeners[i] mStrongListener");
+ cb.NoteXPCOMChild(listeners->ElementAt(i).mStrongListener.get());
+ }
+ }
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildManagers)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
@@ -419,35 +410,6 @@ nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage,
return NS_OK;
}
-#ifdef DEBUG
-typedef struct
-{
- nsCOMPtr mCanonical;
- nsWeakPtr mWeak;
-} CanonicalCheckerParams;
-
-static PLDHashOperator
-CanonicalChecker(const nsAString& aKey,
- nsAutoTObserverArray* aListeners,
- void* aParams)
-{
- CanonicalCheckerParams* params =
- static_cast (aParams);
-
- uint32_t count = aListeners->Length();
- for (uint32_t i = 0; i < count; i++) {
- if (!aListeners->ElementAt(i).mWeakListener) {
- continue;
- }
- nsCOMPtr otherCanonical =
- do_QueryReferent(aListeners->ElementAt(i).mWeakListener);
- MOZ_ASSERT((params->mCanonical == otherCanonical) ==
- (params->mWeak == aListeners->ElementAt(i).mWeakListener));
- }
- return PL_DHASH_NEXT;
-}
-#endif
-
NS_IMETHODIMP
nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessage,
nsIMessageListener* aListener)
@@ -461,10 +423,17 @@ nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessage,
// this to happen; it will break e.g. RemoveWeakMessageListener. So let's
// check that we're not getting ourselves into that situation.
nsCOMPtr canonical = do_QueryInterface(aListener);
- CanonicalCheckerParams params;
- params.mCanonical = canonical;
- params.mWeak = weak;
- mListeners.EnumerateRead(CanonicalChecker, (void*)¶ms);
+ for (auto iter = mListeners.Iter(); !iter.Done(); iter.Next()) {
+ nsAutoTObserverArray* listeners = iter.UserData();
+ uint32_t count = listeners->Length();
+ for (uint32_t i = 0; i < count; i++) {
+ nsWeakPtr weakListener = listeners->ElementAt(i).mWeakListener;
+ if (weakListener) {
+ nsCOMPtr otherCanonical = do_QueryReferent(weakListener);
+ MOZ_ASSERT((canonical == otherCanonical) == (weak == weakListener));
+ }
+ }
+ }
#endif
nsAutoTObserverArray* listeners =
@@ -1488,55 +1457,45 @@ protected:
NS_IMPL_ISUPPORTS(MessageManagerReporter, nsIMemoryReporter)
-static PLDHashOperator
-CollectMessageListenerData(const nsAString& aKey,
- nsAutoTObserverArray* aListeners,
- void* aData)
-{
- MessageManagerReferentCount* referentCount =
- static_cast(aData);
-
- uint32_t listenerCount = aListeners->Length();
- if (!listenerCount) {
- return PL_DHASH_NEXT;
- }
-
- nsString key(aKey);
- uint32_t oldCount = 0;
- referentCount->mMessageCounter.Get(key, &oldCount);
- uint32_t currentCount = oldCount + listenerCount;
- referentCount->mMessageCounter.Put(key, currentCount);
-
- // Keep track of messages that have a suspiciously large
- // number of referents (symptom of leak).
- if (currentCount == MessageManagerReporter::kSuspectReferentCount) {
- referentCount->mSuspectMessages.AppendElement(key);
- }
-
- for (uint32_t i = 0; i < listenerCount; ++i) {
- const nsMessageListenerInfo& listenerInfo =
- aListeners->ElementAt(i);
- if (listenerInfo.mWeakListener) {
- nsCOMPtr referent =
- do_QueryReferent(listenerInfo.mWeakListener);
- if (referent) {
- referentCount->mWeakAlive++;
- } else {
- referentCount->mWeakDead++;
- }
- } else {
- referentCount->mStrong++;
- }
- }
- return PL_DHASH_NEXT;
-}
-
void
MessageManagerReporter::CountReferents(nsFrameMessageManager* aMessageManager,
MessageManagerReferentCount* aReferentCount)
{
- aMessageManager->mListeners.EnumerateRead(CollectMessageListenerData,
- aReferentCount);
+ for (auto it = aMessageManager->mListeners.Iter(); !it.Done(); it.Next()) {
+ nsAutoTObserverArray* listeners =
+ it.UserData();
+ uint32_t listenerCount = listeners->Length();
+ if (listenerCount == 0) {
+ continue;
+ }
+
+ nsString key(it.Key());
+ uint32_t oldCount = 0;
+ aReferentCount->mMessageCounter.Get(key, &oldCount);
+ uint32_t currentCount = oldCount + listenerCount;
+ aReferentCount->mMessageCounter.Put(key, currentCount);
+
+ // Keep track of messages that have a suspiciously large
+ // number of referents (symptom of leak).
+ if (currentCount == MessageManagerReporter::kSuspectReferentCount) {
+ aReferentCount->mSuspectMessages.AppendElement(key);
+ }
+
+ for (uint32_t i = 0; i < listenerCount; ++i) {
+ const nsMessageListenerInfo& listenerInfo = listeners->ElementAt(i);
+ if (listenerInfo.mWeakListener) {
+ nsCOMPtr referent =
+ do_QueryReferent(listenerInfo.mWeakListener);
+ if (referent) {
+ aReferentCount->mWeakAlive++;
+ } else {
+ aReferentCount->mWeakDead++;
+ }
+ } else {
+ aReferentCount->mStrong++;
+ }
+ }
+ }
// Add referent count in child managers because the listeners
// participate in messages dispatched from parent message manager.
@@ -2182,24 +2141,20 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
return NS_OK;
}
-static PLDHashOperator
-CycleCollectorMarkListeners(const nsAString& aKey,
- nsAutoTObserverArray* aListeners,
- void* aData)
-{
- uint32_t count = aListeners->Length();
- for (uint32_t i = 0; i < count; i++) {
- if (aListeners->ElementAt(i).mStrongListener) {
- xpc_TryUnmarkWrappedGrayObject(aListeners->ElementAt(i).mStrongListener);
- }
- }
- return PL_DHASH_NEXT;
-}
-
bool
nsFrameMessageManager::MarkForCC()
{
- mListeners.EnumerateRead(CycleCollectorMarkListeners, nullptr);
+ for (auto iter = mListeners.Iter(); !iter.Done(); iter.Next()) {
+ nsAutoTObserverArray* listeners = iter.UserData();
+ uint32_t count = listeners->Length();
+ for (uint32_t i = 0; i < count; i++) {
+ nsCOMPtr strongListener =
+ listeners->ElementAt(i).mStrongListener;
+ if (strongListener) {
+ xpc_TryUnmarkWrappedGrayObject(strongListener);
+ }
+ }
+ }
if (mRefCnt.IsPurple()) {
mRefCnt.RemovePurple();
diff --git a/dom/base/test/chrome/cpows_child.js b/dom/base/test/chrome/cpows_child.js
index ff94f771f04..8736375b522 100644
--- a/dom/base/test/chrome/cpows_child.js
+++ b/dom/base/test/chrome/cpows_child.js
@@ -20,6 +20,7 @@ var Cu = Components.utils;
lifetime_test,
cancel_test,
cancel_test2,
+ unsafe_test,
];
function go() {
@@ -337,3 +338,20 @@ function cancel_test2(finish)
if (fin1 && fin2) finish();
});
}
+
+function unsafe_test(finish)
+{
+ if (!is_remote) {
+ // Only run this test when running out-of-process.
+ finish();
+ return;
+ }
+
+ function f() {}
+
+ sendAsyncMessage("cpows:unsafe", null, {f});
+ addMessageListener("cpows:unsafe_done", msg => {
+ sendRpcMessage("cpows:safe", null, {f});
+ addMessageListener("cpows:safe_done", finish);
+ });
+}
diff --git a/dom/base/test/chrome/cpows_parent.xul b/dom/base/test/chrome/cpows_parent.xul
index 66345993671..1e65628536e 100644
--- a/dom/base/test/chrome/cpows_parent.xul
+++ b/dom/base/test/chrome/cpows_parent.xul
@@ -390,6 +390,33 @@
msg.target.messageManager.sendAsyncMessage("cpows:cancel_test2_done");
}
+ function recvUnsafe(msg) {
+ let failed = false;
+
+ const PREF_UNSAFE_FORBIDDEN = "dom.ipc.cpows.forbid-unsafe-from-browser";
+ opener.wrappedJSObject.SpecialPowers.setBoolPref(PREF_UNSAFE_FORBIDDEN, true);
+ try {
+ msg.objects.f();
+ } catch (e if /unsafe CPOW usage forbidden/.test(String(e))) {
+ failed = true;
+ }
+ opener.wrappedJSObject.SpecialPowers.clearUserPref(PREF_UNSAFE_FORBIDDEN);
+ ok(failed, "CPOW should fail when unsafe");
+ msg.target.messageManager.sendAsyncMessage("cpows:unsafe_done");
+ }
+
+ function recvSafe(msg) {
+ const PREF_UNSAFE_FORBIDDEN = "dom.ipc.cpows.forbid-unsafe-from-browser";
+ opener.wrappedJSObject.SpecialPowers.setBoolPref(PREF_UNSAFE_FORBIDDEN, true);
+ try {
+ msg.objects.f();
+ } catch (e if /unsafe CPOW usage forbidden/.test(String(e))) {
+ ok(false, "cpow failed");
+ }
+ opener.wrappedJSObject.SpecialPowers.clearUserPref(PREF_UNSAFE_FORBIDDEN);
+ msg.target.messageManager.sendAsyncMessage("cpows:safe_done");
+ }
+
function run_tests(type) {
info("Running tests: " + type);
var node = document.getElementById('cpowbrowser_' + type);
@@ -429,6 +456,8 @@
mm.addMessageListener("cpows:cancel_test", recvCancelTest);
mm.addMessageListener("cpows:cancel_sync_message", recvCancelSyncMessage);
mm.addMessageListener("cpows:cancel_test2", recvCancelTest2);
+ mm.addMessageListener("cpows:unsafe", recvUnsafe);
+ mm.addMessageListener("cpows:safe", recvSafe);
mm.loadFrameScript("chrome://mochitests/content/chrome/dom/base/test/chrome/cpows_child.js", true);
}
diff --git a/dom/bindings/test/moz.build b/dom/bindings/test/moz.build
index 1b81ad3e6e3..eeadfee342d 100644
--- a/dom/bindings/test/moz.build
+++ b/dom/bindings/test/moz.build
@@ -41,8 +41,8 @@ WEBIDL_EXAMPLE_INTERFACES += [
'TestExampleProxyInterface',
]
-GENERATED_INCLUDES += ['..']
LOCAL_INCLUDES += [
+ '!..',
'/dom/bindings',
'/js/xpconnect/src',
'/js/xpconnect/wrappers',
diff --git a/dom/canvas/WebGLContextDraw.cpp b/dom/canvas/WebGLContextDraw.cpp
index 47afcbf0473..05d9707271e 100644
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -7,6 +7,7 @@
#include "GLContext.h"
#include "mozilla/CheckedInt.h"
+#include "mozilla/UniquePtrExtensions.h"
#include "WebGLBuffer.h"
#include "WebGLContextUtils.h"
#include "WebGLFramebuffer.h"
@@ -580,7 +581,7 @@ WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
GetAndFlushUnderlyingGLErrors();
if (mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray) {
- UniquePtr array(new (fallible) GLfloat[4 * vertexCount]);
+ auto array = MakeUniqueFallible(4 * vertexCount);
if (!array) {
ErrorOutOfMemory("Fake attrib0 array.");
return false;
diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp
index ad3ad3d04ee..34a9ebaaefd 100644
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -52,6 +52,7 @@
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/Endian.h"
#include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtrExtensions.h"
namespace mozilla {
@@ -1622,7 +1623,7 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
uint32_t subrect_byteLength = (subrect_height-1)*subrect_alignedRowSize + subrect_plainRowSize;
// create subrect buffer, call glReadPixels, copy pixels into destination buffer, delete subrect buffer
- UniquePtr subrect_data(new (fallible) GLubyte[subrect_byteLength]);
+ auto subrect_data = MakeUniqueFallible(subrect_byteLength);
if (!subrect_data)
return ErrorOutOfMemory("readPixels: subrect_data");
diff --git a/dom/canvas/test/captureStream_common.js b/dom/canvas/test/captureStream_common.js
index 91be55ed513..6b9b4c66a8f 100644
--- a/dom/canvas/test/captureStream_common.js
+++ b/dom/canvas/test/captureStream_common.js
@@ -25,6 +25,7 @@ function CaptureStreamTestHelper(width, height) {
CaptureStreamTestHelper.prototype = {
/* Predefined colors for use in the methods below. */
black: { data: [0, 0, 0, 255], name: "black" },
+ blackTransparent: { data: [0, 0, 0, 0], name: "blackTransparent" },
green: { data: [0, 255, 0, 255], name: "green" },
red: { data: [255, 0, 0, 255], name: "red" },
@@ -52,55 +53,90 @@ CaptureStreamTestHelper.prototype = {
video.srcObject.requestFrame();
},
- /* Tests the top left pixel of |video| against |refData|. Format [R,G,B,A]. */
- testPixel: function (video, refData, threshold) {
+ /*
+ * Returns the pixel at (|offsetX|, |offsetY|) (from top left corner) of
+ * |video| as an array of the pixel's color channels: [R,G,B,A].
+ */
+ getPixel: function (video, offsetX, offsetY) {
+ offsetX = offsetX || 0; // Set to 0 if not passed in.
+ offsetY = offsetY || 0; // Set to 0 if not passed in.
var ctxout = this.cout.getContext('2d');
ctxout.drawImage(video, 0, 0);
- var pixel = ctxout.getImageData(0, 0, 1, 1).data;
- return pixel.every((val, i) => Math.abs(val - refData[i]) <= threshold);
+ return ctxout.getImageData(offsetX, offsetY, 1, 1).data;
},
/*
- * Returns a promise that resolves when the pixel matches. Use |threshold|
- * for fuzzy matching the color on each channel, in the range [0,255].
+ * Returns true if px lies within the per-channel |threshold| of the
+ * referenced color for all channels. px is on the form of an array of color
+ * channels, [R,G,B,A]. Each channel is in the range [0, 255].
*/
- waitForPixel: function (video, refColor, threshold, infoString) {
+ isPixel: function (px, refColor, threshold) {
+ threshold = threshold || 0; // Default to 0 (exact match) if not passed in.
+ return px.every((ch, i) => Math.abs(ch - refColor.data[i]) <= threshold);
+ },
+
+ /*
+ * Returns true if px lies further away than |threshold| of the
+ * referenced color for any channel. px is on the form of an array of color
+ * channels, [R,G,B,A]. Each channel is in the range [0, 255].
+ */
+ isPixelNot: function (px, refColor, threshold) {
+ if (threshold === undefined) {
+ // Default to 127 (should be sufficiently far away) if not passed in.
+ threshold = 127;
+ }
+ return px.some((ch, i) => Math.abs(ch - refColor.data[i]) > threshold);
+ },
+
+ /*
+ * Returns a promise that resolves when the provided function |test|
+ * returns true.
+ */
+ waitForPixel: function (video, offsetX, offsetY, test, timeout) {
return new Promise(resolve => {
- info("Testing " + video.id + " against [" + refColor.data.join(',') + "]");
+ const startTime = video.currentTime;
CaptureStreamTestHelper2D.prototype.clear.call(this, this.cout);
- video.ontimeupdate = () => {
- if (this.testPixel(video, refColor.data, threshold)) {
- ok(true, video.id + " " + infoString);
- video.ontimeupdate = null;
- resolve();
+ var ontimeupdate = () => {
+ const pixelMatch = test(this.getPixel(video, offsetX, offsetY));
+ if (!pixelMatch &&
+ (!timeout || video.currentTime < startTime + (timeout / 1000.0))) {
+ // No match yet and,
+ // No timeout (waiting indefinitely) or |timeout| has not passed yet.
+ return;
}
+ video.removeEventListener("timeupdate", ontimeupdate);
+ resolve(pixelMatch);
};
+ video.addEventListener("timeupdate", ontimeupdate);
});
},
/*
- * Returns a promise that resolves after |timeout| ms of playback or when a
- * pixel of |video| becomes the color |refData|. The test is failed if the
+ * Returns a promise that resolves when the top left pixel of |video| matches
+ * on all channels. Use |threshold| for fuzzy matching the color on each
+ * channel, in the range [0,255].
+ */
+ waitForPixelColor: function (video, refColor, threshold, infoString) {
+ info("Waiting for video " + video.id + " to match [" +
+ refColor.data.join(',') + "] - " + refColor.name +
+ " (" + infoString + ")");
+ return this.waitForPixel(video, 0, 0,
+ px => this.isPixel(px, refColor, threshold))
+ .then(() => ok(true, video.id + " " + infoString));
+ },
+
+ /*
+ * Returns a promise that resolves after |timeout| ms of playback or when the
+ * top left pixel of |video| becomes |refColor|. The test is failed if the
* timeout is not reached.
*/
- waitForPixelToTimeout: function (video, refColor, threshold, timeout, infoString) {
- return new Promise(resolve => {
- info("Waiting for " + video.id + " to time out after " + timeout +
- "ms against [" + refColor.data.join(',') + "] - " + refColor.name);
- CaptureStreamTestHelper2D.prototype.clear.call(this, this.cout);
- var startTime = video.currentTime;
- video.ontimeupdate = () => {
- if (this.testPixel(video, refColor.data, threshold)) {
- ok(false, video.id + " " + infoString);
- video.ontimeupdate = null;
- resolve();
- } else if (video.currentTime > startTime + (timeout / 1000.0)) {
- ok(true, video.id + " " + infoString);
- video.ontimeupdate = null;
- resolve();
- }
- };
- });
+ waitForPixelColorTimeout: function (video, refColor, threshold, timeout, infoString) {
+ info("Waiting for " + video.id + " to time out after " + timeout +
+ "ms against [" + refColor.data.join(',') + "] - " + refColor.name);
+ return this.waitForPixel(video, 0, 0,
+ px => this.isPixel(px, refColor, threshold),
+ timeout)
+ .then(result => ok(!result, video.id + " " + infoString));
},
/* Create an element of type |type| with id |id| and append it to the body. */
diff --git a/dom/canvas/test/test_capture.html b/dom/canvas/test/test_capture.html
index ec2902b3ac9..69222d75a9e 100644
--- a/dom/canvas/test/test_capture.html
+++ b/dom/canvas/test/test_capture.html
@@ -23,15 +23,21 @@ function checkDrawColorInitialRed() {
vmanual.srcObject = c.captureStream(0);
vrate.srcObject = c.captureStream(10);
- ok(h.testPixel(vauto, [0, 0, 0, 0], 0), "vauto hould not be drawn to before stable state");
- ok(h.testPixel(vrate, [0, 0, 0, 0], 0), "vrate Should not be drawn to before stable state");
- ok(h.testPixel(vmanual, [0, 0, 0, 0], 0), "vmanual Should not be drawn to before stable state");
+ ok(h.isPixel(h.getPixel(vauto), h.blackTransparent, 0),
+ "vauto should not be drawn to before stable state");
+ ok(h.isPixel(h.getPixel(vrate), h.blackTransparent, 0),
+ "vrate should not be drawn to before stable state");
+ ok(h.isPixel(h.getPixel(vmanual), h.blackTransparent, 0),
+ "vmanual should not be drawn to before stable state");
return Promise.resolve()
- .then(() => h.waitForPixel(vauto, h.red, 0, "should become red automatically"))
- .then(() => h.waitForPixel(vrate, h.red, 0, "should become red automatically"))
- .then(() => h.waitForPixel(vmanual, h.red, 0, "should become red when we get" +
- " to stable state (first frame)"));
+ .then(() => h.waitForPixelColor(vauto, h.red, 0,
+ "should become red automatically"))
+ .then(() => h.waitForPixelColor(vrate, h.red, 0,
+ "should become red automatically"))
+ .then(() => h.waitForPixelColor(vmanual, h.red, 0,
+ "should become red when we get" +
+ " to stable state (first frame)"));
}
function checkDrawColorGreen() {
@@ -40,11 +46,15 @@ function checkDrawColorGreen() {
var drawing = h.startDrawing(() => h.drawColor(c, h.green));
return Promise.resolve()
- .then(() => h.waitForPixel(vauto, h.green, 0, "should become green automatically"))
- .then(() => h.waitForPixel(vrate, h.green, 0, "should become green automatically"))
- .then(() => h.waitForPixel(vmanual, h.red, 0, "should still be red"))
+ .then(() => h.waitForPixelColor(vauto, h.green, 0,
+ "should become green automatically"))
+ .then(() => h.waitForPixelColor(vrate, h.green, 0,
+ "should become green automatically"))
+ .then(() => h.waitForPixelColor(vmanual, h.red, 0,
+ "should still be red"))
.then(() => h.requestFrame(vmanual))
- .then(() => h.waitForPixel(vmanual, h.green, 0, "should become green after requstFrame()"))
+ .then(() => h.waitForPixelColor(vmanual, h.green, 0,
+ "should become green after requstFrame()"))
.catch(err => ok(false, "checkDrawColorGreen failed: ", err))
.then(() => drawing.stop());
}
@@ -54,10 +64,12 @@ function checkRequestFrameOrderGuarantee() {
"call results in the expected frame seen in the stream.");
return Promise.resolve()
- .then(() => h.waitForPixel(vmanual, h.green, 0, "should still be green"))
+ .then(() => h.waitForPixelColor(vmanual, h.green, 0,
+ "should still be green"))
.then(() => h.drawColor(c, h.red)) // 1. Draw canvas red
.then(() => h.requestFrame(vmanual)) // 2. Immediately request a frame
- .then(() => h.waitForPixel(vmanual, h.red, 0, "should become red after call order test"))
+ .then(() => h.waitForPixelColor(vmanual, h.red, 0,
+ "should become red after call order test"))
}
function checkDrawImageNotCleanRed() {
@@ -74,11 +86,14 @@ function checkDrawImageNotCleanRed() {
})
.then(() => drawing = h.startDrawing(() => ctx.drawImage(notCleanRed, 0, 0, c.width, c.height)))
.then(() => h.testNotClean(c))
- .then(() => h.waitForPixelToTimeout(vauto, h.red, 0, 1000, "should not become red"))
- .then(() => h.waitForPixelToTimeout(vrate, h.red, 0, 0, "should not become red"))
- .then(() => h.waitForPixel(vmanual, h.green, 0, "should still be green"))
+ .then(() => h.waitForPixelColorTimeout(vauto, h.red, 0, 1000,
+ "should not become red"))
+ .then(() => h.isPixelNot(h.getPixel(vrate), h.red, 250,
+ "should not have become red"))
+ .then(() => h.waitForPixelColor(vmanual, h.green, 0, "should still be green"))
.then(() => h.requestFrame(vmanual))
- .then(() => h.waitForPixelToTimeout(vmanual, h.red, 0, 1000, "should not become red"))
+ .then(() => h.waitForPixelColorTimeout(vmanual, h.red, 0, 1000,
+ "should not become red"))
.catch(err => ok(false, "checkDrawImageNotCleanRed failed: ", err))
.then(() => drawing.stop());
}
diff --git a/dom/canvas/test/webgl-mochitest/test_capture.html b/dom/canvas/test/webgl-mochitest/test_capture.html
index 489d6787236..fc27b35e734 100644
--- a/dom/canvas/test/webgl-mochitest/test_capture.html
+++ b/dom/canvas/test/webgl-mochitest/test_capture.html
@@ -54,14 +54,21 @@ function checkClearColorInitialRed() {
vmanual.srcObject = c.captureStream(0);
vrate.srcObject = c.captureStream(10);
- ok(h.testPixel(vauto, [0, 0, 0, 0], 0), "Should not be drawn to before stable state");
- ok(h.testPixel(vrate, [0, 0, 0, 0], 0), "Should not be drawn to before stable state");
- ok(h.testPixel(vmanual, [0, 0, 0, 0], 0), "Should not be drawn to before stable state");
+ ok(h.isPixel(h.getPixel(vauto), h.blackTransparent, 0,
+ "vauto should not be drawn to before stable state"));
+ ok(h.isPixel(h.getPixel(vrate), h.blackTransparent, 0,
+ "vrate should not be drawn to before stable state"));
+ ok(h.isPixel(h.getPixel(vmanual), h.blackTransparent, 0,
+ "vmanual should not be drawn to before stable state"));
return Promise.resolve()
- .then(() => h.waitForPixel(vauto, h.red, 0, "should become red automatically"))
- .then(() => h.waitForPixel(vrate, h.red, 0, "should become red automatically"))
- .then(() => h.waitForPixel(vmanual, h.red, 0, "should become red when we get to stable state (first frame)"))
+ .then(() => h.waitForPixelColor(vauto, h.red, 0,
+ "should become red automatically"))
+ .then(() => h.waitForPixelColor(vrate, h.red, 0,
+ "should become red automatically"))
+ .then(() => h.waitForPixelColor(vmanual, h.red, 0,
+ "should become red when we get to stable " +
+ "state (first frame)"))
}
function checkDrawColorGreen() {
@@ -69,11 +76,15 @@ function checkDrawColorGreen() {
var drawing = h.startDrawing(h.drawColor.bind(h, c, h.green));
checkGLError('after DrawColor');
return Promise.resolve()
- .then(() => h.waitForPixel(vauto, h.green, 0, "should become green automatically"))
- .then(() => h.waitForPixel(vrate, h.green, 0, "should become green automatically"))
- .then(() => h.waitForPixel(vmanual, h.red, 0, "should still be red"))
+ .then(() => h.waitForPixelColor(vauto, h.green, 0,
+ "should become green automatically"))
+ .then(() => h.waitForPixelColor(vrate, h.green, 0,
+ "should become green automatically"))
+ .then(() => h.waitForPixelColor(vmanual, h.red, 0,
+ "should still be red"))
.then(() => h.requestFrame(vmanual))
- .then(() => h.waitForPixel(vmanual, h.green, 0, "should become green after requstFrame()"))
+ .then(() => h.waitForPixelColor(vmanual, h.green, 0,
+ "should become green after requstFrame()"))
.then(() => drawing.stop());
}
@@ -81,11 +92,15 @@ function checkClearColorRed() {
info("Checking that clearing to red works.");
var drawing = h.startDrawing(h.clearColor.bind(h, c, h.red));
return Promise.resolve()
- .then(() => h.waitForPixel(vauto, h.red, 0, "should become red automatically"))
- .then(() => h.waitForPixel(vrate, h.red, 0, "should become red automatically"))
- .then(() => h.waitForPixel(vmanual, h.green, 0, "should still be green"))
+ .then(() => h.waitForPixelColor(vauto, h.red, 0,
+ "should become red automatically"))
+ .then(() => h.waitForPixelColor(vrate, h.red, 0,
+ "should become red automatically"))
+ .then(() => h.waitForPixelColor(vmanual, h.green, 0,
+ "should still be green"))
.then(() => h.requestFrame(vmanual))
- .then(() => h.waitForPixel(vmanual, h.red, 0, "should become red after requestFrame()"))
+ .then(() => h.waitForPixelColor(vmanual, h.red, 0,
+ "should become red after requestFrame()"))
.then(() => drawing.stop());
}
@@ -93,10 +108,11 @@ function checkRequestFrameOrderGuarantee() {
info("Checking that requestFrame() immediately after a draw " +
"call results in the expected frame seen in the stream.");
return Promise.resolve()
- .then(() => h.waitForPixel(vmanual, h.red, 0, "should still be red"))
+ .then(() => h.waitForPixelColor(vmanual, h.red, 0, "should still be red"))
.then(() => h.drawColor(c, h.green)) // 1. Draw canvas green
.then(() => h.requestFrame(vmanual)) // 2. Immediately request a frame
- .then(() => h.waitForPixel(vmanual, h.green, 0, "should become green after call order test"))
+ .then(() => h.waitForPixelColor(vmanual, h.green, 0,
+ "should become green after call order test"))
}
function finish() {
diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp
index 643bd698427..9643e67c03b 100755
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1910,28 +1910,6 @@ ContentParent::OnChannelError()
PContentParent::OnChannelError();
}
-void
-ContentParent::OnBeginSyncTransaction() {
- if (XRE_IsParentProcess()) {
- nsCOMPtr console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
- JSContext *cx = nsContentUtils::GetCurrentJSContext();
- if (!sDisableUnsafeCPOWWarnings) {
- if (console && cx) {
- nsAutoString filename;
- uint32_t lineno = 0, column = 0;
- nsJSUtils::GetCallingLocation(cx, filename, &lineno, &column);
- nsCOMPtr error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
- error->Init(NS_LITERAL_STRING("unsafe CPOW usage"), filename,
- EmptyString(), lineno, column,
- nsIScriptError::warningFlag, "chrome javascript");
- console->LogMessage(error);
- } else {
- NS_WARNING("Unsafe synchronous IPC message");
- }
- }
- }
-}
-
void
ContentParent::OnChannelConnected(int32_t pid)
{
diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h
index 4797cd07bfd..3000c155003 100644
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -327,8 +327,6 @@ public:
virtual void OnChannelError() override;
- virtual void OnBeginSyncTransaction() override;
-
virtual PCrashReporterParent*
AllocPCrashReporterParent(const NativeThreadId& tid,
const uint32_t& processType) override;
diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp
index 730f669d4f6..eb15ed4f3db 100644
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1415,25 +1415,22 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
RefPtr p = new PledgeSourceSet();
uint32_t id = mOutstandingPledges.Append(*p);
- // Check if the preference for using audio/video loopback devices is
- // enabled. This is currently used for automated media tests only.
- //
- // If present (and we're doing non-exotic cameras and microphones) use them
- // instead of our built-in fake devices, except if fake tracks are requested
- // (a feature of the built-in ones only).
-
nsAdoptingCString audioLoopDev, videoLoopDev;
- if (!aFakeTracks) {
- if (aVideoType == dom::MediaSourceEnum::Camera) {
- audioLoopDev = Preferences::GetCString("media.audio_loopback_dev");
+ if (!aFake) {
+ // Fake stream not requested. The entire device stack is available.
+ // Loop in loopback devices if they are set, and their respective type is
+ // requested. This is currently used for automated media tests only.
+ if (aVideoType == MediaSourceEnum::Camera) {
videoLoopDev = Preferences::GetCString("media.video_loopback_dev");
-
- if (aFake && !audioLoopDev.IsEmpty() && !videoLoopDev.IsEmpty()) {
- aFake = false;
- }
- } else {
- aFake = false;
}
+ if (aAudioType == MediaSourceEnum::Microphone) {
+ audioLoopDev = Preferences::GetCString("media.audio_loopback_dev");
+ }
+ }
+
+ if (!aFake) {
+ // Fake tracks only make sense when we have a fake stream.
+ aFakeTracks = false;
}
MediaManager::PostTask(FROM_HERE, NewTaskFrom([id, aWindowId, audioLoopDev,
diff --git a/dom/media/encoder/moz.build b/dom/media/encoder/moz.build
index 6def7f46985..853b0d6d3b9 100644
--- a/dom/media/encoder/moz.build
+++ b/dom/media/encoder/moz.build
@@ -42,13 +42,16 @@ FINAL_LIBRARY = 'xul'
# These includes are from Android JB, for use of MediaCodec.
LOCAL_INCLUDES += ['/ipc/chromium/src']
-CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/native/opengl/include',
- 'frameworks/native/include',
- 'frameworks/av/include/media',
+
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] > '15':
+ LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+ 'frameworks/av/include/media',
+ 'frameworks/native/include',
+ 'frameworks/native/opengl/include',
+ ]
+
]
-]
include('/ipc/chromium/chromium-config.mozbuild')
diff --git a/dom/media/omx/moz.build b/dom/media/omx/moz.build
index aec361e2071..543cd5e4d46 100644
--- a/dom/media/omx/moz.build
+++ b/dom/media/omx/moz.build
@@ -97,20 +97,26 @@ LOCAL_INCLUDES += [
'/ipc/chromium/src',
]
-CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'dalvik/libnativehelper/include/nativehelper',
- 'frameworks/av/include/media',
- 'frameworks/base/include',
- 'frameworks/base/include/binder',
- 'frameworks/base/include/utils',
- 'frameworks/base/include/media',
- 'frameworks/base/include/media/stagefright/openmax',
- 'frameworks/base/media/libstagefright/include',
- 'frameworks/native/opengl/include',
- 'frameworks/native/include',
- 'hardware/libhardware/include/',
+if CONFIG['ANDROID_VERSION'] == '15':
+ LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+ 'dalvik/libnativehelper/include/nativehelper',
+ 'frameworks/base/include',
+ 'frameworks/base/include/binder',
+ 'frameworks/base/include/media',
+ 'frameworks/base/include/media/stagefright/openmax',
+ 'frameworks/base/include/utils',
+ 'frameworks/base/media/libstagefright/include',
+ 'hardware/libhardware/include',
+ ]
]
+else:
+ LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+ 'frameworks/av/include/media',
+ 'frameworks/native/include',
+ 'frameworks/native/opengl/include',
+ ]
]
if CONFIG['ANDROID_VERSION'] > '15':
diff --git a/dom/media/platforms/gonk/moz.build b/dom/media/platforms/gonk/moz.build
index eb5f2b2c72c..5dbc0a6705c 100644
--- a/dom/media/platforms/gonk/moz.build
+++ b/dom/media/platforms/gonk/moz.build
@@ -33,7 +33,7 @@ if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
FINAL_LIBRARY = 'xul'
-CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
'frameworks/native/opengl/include',]
]
diff --git a/dom/media/systemservices/moz.build b/dom/media/systemservices/moz.build
index 74300776e71..27a5f68ac7c 100644
--- a/dom/media/systemservices/moz.build
+++ b/dom/media/systemservices/moz.build
@@ -40,12 +40,14 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
EXPORTS += ['OSXRunLoopSingleton.h']
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/wilhelm/include',
- 'system/media/wilhelm/include',
+ if CONFIG['ANDROID_VERSION'] >= '17':
+ LOCAL_INCLUDES += [
+ '%' + '%s/frameworks/wilhelm/include' % CONFIG['ANDROID_SOURCE'],
+ ]
+ else:
+ LOCAL_INCLUDES += [
+ '%' + '%s/system/media/wilhelm/include' % CONFIG['ANDROID_SOURCE'],
]
- ]
if CONFIG['_MSC_VER']:
DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__'
diff --git a/dom/media/test/test_mediarecorder_record_canvas_captureStream.html b/dom/media/test/test_mediarecorder_record_canvas_captureStream.html
index 21456b93539..7f440fba9dd 100644
--- a/dom/media/test/test_mediarecorder_record_canvas_captureStream.html
+++ b/dom/media/test/test_mediarecorder_record_canvas_captureStream.html
@@ -56,7 +56,7 @@ function startTest() {
SimpleTest.finish();
};
document.getElementById("content").appendChild(video);
- helper.waitForPixel(video, helper.red, 128, "Should become red")
+ helper.waitForPixelColor(video, helper.red, 128, "Should become red")
.then(SimpleTest.finish);
};
diff --git a/dom/media/tests/mochitest/identity/identityPcTest.js b/dom/media/tests/mochitest/identity/identityPcTest.js
index e5c9d9b423b..e5fcbc5db87 100644
--- a/dom/media/tests/mochitest/identity/identityPcTest.js
+++ b/dom/media/tests/mochitest/identity/identityPcTest.js
@@ -20,7 +20,6 @@ function identityPcTest(remoteOptions) {
}], [remoteOptions || {
audio: true,
video: true,
- fake: true,
peerIdentity: id1
}]);
test.pcLocal.setIdentityProvider('test1.example.com', 'idp.js');
diff --git a/dom/media/tests/mochitest/identity/test_peerConnection_asymmetricIsolation.html b/dom/media/tests/mochitest/identity/test_peerConnection_asymmetricIsolation.html
index 1d686f533f4..5ea0f5c779b 100644
--- a/dom/media/tests/mochitest/identity/test_peerConnection_asymmetricIsolation.html
+++ b/dom/media/tests/mochitest/identity/test_peerConnection_asymmetricIsolation.html
@@ -20,8 +20,7 @@ function theTest() {
// side is isolated anyway.
identityPcTest({
audio: true,
- video: true,
- fake: true
+ video: true
});
}
runNetworkTest(theTest);
diff --git a/dom/media/tests/mochitest/mochitest.ini b/dom/media/tests/mochitest/mochitest.ini
index dc08b192ee9..8aef9ab7306 100644
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -150,6 +150,7 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' &
[test_peerConnection_throwInCallbacks.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_toJSON.html]
+[test_peerConnection_trackDisabling.html]
[test_peerConnection_twoAudioStreams.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' && debug) # b2g (Bug 1059867), android(Bug 1189784, timeouts on 4.3 emulator)
diff --git a/dom/media/tests/mochitest/test_enumerateDevices.html b/dom/media/tests/mochitest/test_enumerateDevices.html
index 06565e26abb..5a160cf4a9b 100644
--- a/dom/media/tests/mochitest/test_enumerateDevices.html
+++ b/dom/media/tests/mochitest/test_enumerateDevices.html
@@ -46,27 +46,24 @@ runTest(() =>
.then(() => mustSucceed("unknown plain deviceId on video",
() => navigator.mediaDevices.getUserMedia({
video: { deviceId: "unknown9qHr8B0JIbcHlbl9xR+jMbZZ8WyoPfpCXPfc=" },
- fake: true,
})))
.then(() => mustSucceed("unknown plain deviceId on audio",
() => navigator.mediaDevices.getUserMedia({
audio: { deviceId: "unknown9qHr8B0JIbcHlbl9xR+jMbZZ8WyoPfpCXPfc=" },
- fake: true,
})))
.then(() => mustFailWith("unknown exact deviceId on video",
"OverconstrainedError", "deviceId",
() => navigator.mediaDevices.getUserMedia({
video: { deviceId: { exact: "unknown9qHr8B0JIbcHlbl9xR+jMbZZ8WyoPfpCXPfc=" } },
- fake: true,
})))
.then(() => mustFailWith("unknown exact deviceId on audio",
"OverconstrainedError", "deviceId",
() => navigator.mediaDevices.getUserMedia({
audio: { deviceId: { exact: "unknown9qHr8B0JIbcHlbl9xR+jMbZZ8WyoPfpCXPfc=" } },
- fake: true,
})))
- // Check the special case of no devices found (these prefs override fake).
- .then(() => pushPrefs(["media.audio_loopback_dev", "none"],
+ // Check the special case of no devices found.
+ .then(() => pushPrefs(["media.navigator.streams.fake", false],
+ ["media.audio_loopback_dev", "none"],
["media.video_loopback_dev", "none"]))
.then(() => navigator.mediaDevices.enumerateDevices())
.then(devices => ok(devices.length === 0, "No devices found")));
diff --git a/dom/media/tests/mochitest/test_getUserMedia_basicTabshare.html b/dom/media/tests/mochitest/test_getUserMedia_basicTabshare.html
index d3d1a0c3755..9753c669b36 100644
--- a/dom/media/tests/mochitest/test_getUserMedia_basicTabshare.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_basicTabshare.html
@@ -25,8 +25,11 @@
var testVideo = createMediaElement('video', 'testVideo');
return Promise.resolve()
- .then(() => getUserMedia({ video: { mediaSource: "browser",
- scrollWithPage: true } }))
+ .then(() => getUserMedia({
+ video: { mediaSource: "browser",
+ scrollWithPage: true },
+ fake: false
+ }))
.then(stream => {
var playback = new LocalMediaStreamPlayback(testVideo, stream);
return playback.playMediaWithDeprecatedStreamStop(false);
@@ -38,7 +41,8 @@
viewportOffsetY: 0,
viewportWidth: 100,
viewportHeight: 100
- }
+ },
+ fake: false
}))
.then(stream => {
var playback = new LocalMediaStreamPlayback(testVideo, stream);
diff --git a/dom/media/tests/mochitest/test_getUserMedia_constraints.html b/dom/media/tests/mochitest/test_getUserMedia_constraints.html
index 88d0d8993ce..9acb61a253a 100644
--- a/dom/media/tests/mochitest/test_getUserMedia_constraints.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_constraints.html
@@ -16,16 +16,13 @@ createHTML({ title: "Test getUserMedia constraints", bug: "882145" });
var tests = [
// Each test here tests a different constraint or codepath.
{ message: "unknown required constraint on video ignored",
- constraints: { video: { somethingUnknown: { exact: 0 } },
- fake: true },
+ constraints: { video: { somethingUnknown: { exact: 0 } } },
error: null },
{ message: "unknown required constraint on audio ignored",
- constraints: { audio: { somethingUnknown: { exact: 0 } },
- fake: true },
+ constraints: { audio: { somethingUnknown: { exact: 0 } } },
error: null },
{ message: "audio overconstrained by facingMode ignored",
- constraints: { audio: { facingMode: { exact: 'left' } },
- fake: true },
+ constraints: { audio: { facingMode: { exact: 'left' } } },
error: null },
{ message: "full screensharing requires permission",
constraints: { video: { mediaSource: 'screen' } },
@@ -51,8 +48,7 @@ var tests = [
constraints: { },
error: "NotSupportedError" },
{ message: "Success-path: optional video facingMode + audio ignoring facingMode",
- constraints: { fake: true,
- audio: { mediaSource: 'microphone',
+ constraints: { audio: { mediaSource: 'microphone',
facingMode: 'left',
foo: 0,
advanced: [{ facingMode: 'environment' },
@@ -66,7 +62,7 @@ var tests = [
{ bar: 0 }] } },
error: null },
{ message: "legacy facingMode ignored",
- constraints: { video: { mandatory: { facingMode: 'left' } }, fake: true },
+ constraints: { video: { mandatory: { facingMode: 'left' } } },
error: null },
];
diff --git a/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html b/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html
index 108e4f83a17..f680beb533b 100644
--- a/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_peerIdentity.html
@@ -13,7 +13,7 @@ createHTML({
});
function theTest() {
function testPeerIdentityConstraint(withConstraint) {
- var config = { audio: true, video: true, fake: true };
+ var config = { audio: true, video: true };
if (withConstraint) {
config.peerIdentity = 'user@example.com';
}
diff --git a/dom/media/tests/mochitest/test_peerConnection_callbacks.html b/dom/media/tests/mochitest/test_peerConnection_callbacks.html
index fb634f1e00e..8bf4b106daf 100644
--- a/dom/media/tests/mochitest/test_peerConnection_callbacks.html
+++ b/dom/media/tests/mochitest/test_peerConnection_callbacks.html
@@ -65,7 +65,7 @@ runNetworkTest(function() {
is(v2.currentTime, 0, "v2.currentTime is zero at outset");
// not testing legacy gUM here
- navigator.mediaDevices.getUserMedia({ fake: true, video: true, audio: true })
+ navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => pc1.addStream(v1.mozSrcObject = stream))
.then(() => pcall(pc1, pc1.createOffer))
.then(offer => pcall(pc1, pc1.setLocalDescription, offer))
diff --git a/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_2d.html b/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_2d.html
index cf82d4e28a7..624d641d11c 100644
--- a/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_2d.html
+++ b/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_2d.html
@@ -39,7 +39,8 @@ runNetworkTest(() => {
ok(!!vremote, "Should have remote video element for pcRemote");
},
function WAIT_FOR_REMOTE_GREEN() {
- return h.waitForPixel(vremote, h.green, 128, "pcRemote's remote should become green");
+ return h.waitForPixelColor(vremote, h.green, 128,
+ "pcRemote's remote should become green");
},
function DRAW_LOCAL_RED() {
// After requesting a frame it will be captured at the time of next render.
@@ -49,7 +50,8 @@ runNetworkTest(() => {
h.drawColor(canvas, h.red);
},
function WAIT_FOR_REMOTE_RED() {
- return h.waitForPixel(vremote, h.red, 128, "pcRemote's remote should become red");
+ return h.waitForPixelColor(vremote, h.red, 128,
+ "pcRemote's remote should become red");
}
]);
test.run();
diff --git a/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_webgl.html b/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_webgl.html
index 3b9377563db..02e4018d459 100644
--- a/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_webgl.html
+++ b/dom/media/tests/mochitest/test_peerConnection_captureStream_canvas_webgl.html
@@ -89,7 +89,8 @@ runNetworkTest(() => {
ok(!!vremote, "Should have remote video element for pcRemote");
},
function WAIT_FOR_REMOTE_GREEN() {
- return h.waitForPixel(vremote, h.green, 128, "pcRemote's remote should become green");
+ return h.waitForPixelColor(vremote, h.green, 128,
+ "pcRemote's remote should become green");
},
function REQUEST_FRAME(test) {
// After requesting a frame it will be captured at the time of next render.
@@ -101,7 +102,8 @@ runNetworkTest(() => {
h.drawColor(canvas, h.red);
},
function WAIT_FOR_REMOTE_RED() {
- return h.waitForPixel(vremote, h.red, 128, "pcRemote's remote should become red");
+ return h.waitForPixelColor(vremote, h.red, 128,
+ "pcRemote's remote should become red");
}
]);
test.run();
diff --git a/dom/media/tests/mochitest/test_peerConnection_promiseSendOnly.html b/dom/media/tests/mochitest/test_peerConnection_promiseSendOnly.html
index 52f0f77e120..41b302e42c1 100644
--- a/dom/media/tests/mochitest/test_peerConnection_promiseSendOnly.html
+++ b/dom/media/tests/mochitest/test_peerConnection_promiseSendOnly.html
@@ -36,7 +36,7 @@
is(v2.currentTime, 0, "v2.currentTime is zero at outset");
- navigator.mediaDevices.getUserMedia({ fake: true, video: true, audio: true })
+ navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => pc1.addStream(v1.srcObject = stream))
.then(() => pc1.createOffer({})) // check that createOffer accepts arg.
.then(offer => pc1.setLocalDescription(offer))
diff --git a/dom/media/tests/mochitest/test_peerConnection_replaceTrack.html b/dom/media/tests/mochitest/test_peerConnection_replaceTrack.html
index 7f3a4d4bd8d..62546311a32 100644
--- a/dom/media/tests/mochitest/test_peerConnection_replaceTrack.html
+++ b/dom/media/tests/mochitest/test_peerConnection_replaceTrack.html
@@ -30,7 +30,7 @@
var newTrack;
var audiotrack;
- return navigator.mediaDevices.getUserMedia({video:true, audio:true, fake:true})
+ return navigator.mediaDevices.getUserMedia({video:true, audio:true})
.then(newStream => {
window.grip = newStream;
newTrack = newStream.getVideoTracks()[0];
@@ -112,7 +112,8 @@
var sourceNode = test.audioCtx.createOscillator();
sourceNode.type = 'sine';
- // We need a frequency not too close to the fake audio track (1kHz).
+ // We need a frequency not too close to the fake audio track
+ // (440Hz for loopback devices, 1kHz for fake tracks).
sourceNode.frequency.value = 2000;
sourceNode.start();
@@ -157,7 +158,7 @@
is(e.name, "InvalidParameterError",
"addTrack existing track should fail");
}
- return navigator.mediaDevices.getUserMedia({video:true, fake: true})
+ return navigator.mediaDevices.getUserMedia({video:true})
.then(differentStream => {
var track = differentStream.getVideoTracks()[0];
try {
diff --git a/dom/media/tests/mochitest/test_peerConnection_replaceVideoThenRenegotiate.html b/dom/media/tests/mochitest/test_peerConnection_replaceVideoThenRenegotiate.html
index 1693e9e78ef..5e36d7a5e02 100644
--- a/dom/media/tests/mochitest/test_peerConnection_replaceVideoThenRenegotiate.html
+++ b/dom/media/tests/mochitest/test_peerConnection_replaceVideoThenRenegotiate.html
@@ -21,7 +21,7 @@
var oldstream = test.pcLocal._pc.getLocalStreams()[0];
var oldtrack = oldstream.getVideoTracks()[0];
var sender = test.pcLocal._pc.getSenders()[0];
- return navigator.mediaDevices.getUserMedia({video:true, fake:true})
+ return navigator.mediaDevices.getUserMedia({video:true})
.then(newstream => {
var newtrack = newstream.getVideoTracks()[0];
return test.pcLocal.senderReplaceTrack(0, newtrack, newstream.id);
diff --git a/dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html b/dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html
index 7c0dec1859b..ad5cb7d868e 100644
--- a/dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html
+++ b/dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html
@@ -48,7 +48,7 @@ runNetworkTest(function () {
pc2 = new RTCPeerConnection();
// Test success callbacks (happy path)
- navigator.mozGetUserMedia({video:true, fake: true}, function(video1) {
+ navigator.mozGetUserMedia({video:true}, function(video1) {
pc1.addStream(video1);
pc1.createOffer(function(offer) {
pc1.setLocalDescription(offer, function() {
diff --git a/dom/media/tests/mochitest/test_peerConnection_trackDisabling.html b/dom/media/tests/mochitest/test_peerConnection_trackDisabling.html
new file mode 100644
index 00000000000..9ab1bbc0efd
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_trackDisabling.html
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/media/webaudio/ConvolverNode.cpp b/dom/media/webaudio/ConvolverNode.cpp
index c13964fdf24..7764617422d 100644
--- a/dom/media/webaudio/ConvolverNode.cpp
+++ b/dom/media/webaudio/ConvolverNode.cpp
@@ -96,7 +96,6 @@ public:
}
mReverb = new WebCore::Reverb(mBuffer, mBufferLength,
- WEBAUDIO_BLOCK_SIZE,
MaxFFTSize, 2, mUseBackgroundThreads,
mNormalize, mSampleRate);
}
@@ -153,7 +152,7 @@ public:
}
aOutput->AllocateChannels(2);
- mReverb->process(&input, aOutput, WEBAUDIO_BLOCK_SIZE);
+ mReverb->process(&input, aOutput);
}
virtual bool IsActive() const override
diff --git a/dom/media/webaudio/blink/DirectConvolver.cpp b/dom/media/webaudio/blink/DirectConvolver.cpp
deleted file mode 100644
index 43461ad37e1..00000000000
--- a/dom/media/webaudio/blink/DirectConvolver.cpp
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (C) 2012 Intel Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "DirectConvolver.h"
-#include "mozilla/PodOperations.h"
-
-using namespace mozilla;
-
-namespace WebCore {
-
-DirectConvolver::DirectConvolver(size_t inputBlockSize)
- : m_inputBlockSize(inputBlockSize)
-{
- m_buffer.SetLength(inputBlockSize * 2);
- PodZero(m_buffer.Elements(), inputBlockSize * 2);
-}
-
-void DirectConvolver::process(const nsTArray* convolutionKernel, const float* sourceP, float* destP, size_t framesToProcess)
-{
- MOZ_ASSERT(framesToProcess == m_inputBlockSize);
- if (framesToProcess != m_inputBlockSize)
- return;
-
- // Only support kernelSize <= m_inputBlockSize
- size_t kernelSize = convolutionKernel->Length();
- MOZ_ASSERT(kernelSize <= m_inputBlockSize);
- if (kernelSize > m_inputBlockSize)
- return;
-
- const float* kernelP = convolutionKernel->Elements();
-
- // Sanity check
- bool isCopyGood = kernelP && sourceP && destP && m_buffer.Elements();
- MOZ_ASSERT(isCopyGood);
- if (!isCopyGood)
- return;
-
- float* inputP = m_buffer.Elements() + m_inputBlockSize;
-
- // Copy samples to 2nd half of input buffer.
- memcpy(inputP, sourceP, sizeof(float) * framesToProcess);
-
- // FIXME: The macro can be further optimized to avoid pipeline stalls. One possibility is to maintain 4 separate sums and change the macro to CONVOLVE_FOUR_SAMPLES.
-#define CONVOLVE_ONE_SAMPLE \
- sum += inputP[i - j] * kernelP[j]; \
- j++;
-
- size_t i = 0;
- while (i < framesToProcess) {
- size_t j = 0;
- float sum = 0;
-
- // FIXME: SSE optimization may be applied here.
- if (kernelSize == 32) {
- CONVOLVE_ONE_SAMPLE // 1
- CONVOLVE_ONE_SAMPLE // 2
- CONVOLVE_ONE_SAMPLE // 3
- CONVOLVE_ONE_SAMPLE // 4
- CONVOLVE_ONE_SAMPLE // 5
- CONVOLVE_ONE_SAMPLE // 6
- CONVOLVE_ONE_SAMPLE // 7
- CONVOLVE_ONE_SAMPLE // 8
- CONVOLVE_ONE_SAMPLE // 9
- CONVOLVE_ONE_SAMPLE // 10
-
- CONVOLVE_ONE_SAMPLE // 11
- CONVOLVE_ONE_SAMPLE // 12
- CONVOLVE_ONE_SAMPLE // 13
- CONVOLVE_ONE_SAMPLE // 14
- CONVOLVE_ONE_SAMPLE // 15
- CONVOLVE_ONE_SAMPLE // 16
- CONVOLVE_ONE_SAMPLE // 17
- CONVOLVE_ONE_SAMPLE // 18
- CONVOLVE_ONE_SAMPLE // 19
- CONVOLVE_ONE_SAMPLE // 20
-
- CONVOLVE_ONE_SAMPLE // 21
- CONVOLVE_ONE_SAMPLE // 22
- CONVOLVE_ONE_SAMPLE // 23
- CONVOLVE_ONE_SAMPLE // 24
- CONVOLVE_ONE_SAMPLE // 25
- CONVOLVE_ONE_SAMPLE // 26
- CONVOLVE_ONE_SAMPLE // 27
- CONVOLVE_ONE_SAMPLE // 28
- CONVOLVE_ONE_SAMPLE // 29
- CONVOLVE_ONE_SAMPLE // 30
-
- CONVOLVE_ONE_SAMPLE // 31
- CONVOLVE_ONE_SAMPLE // 32
-
- } else if (kernelSize == 64) {
- CONVOLVE_ONE_SAMPLE // 1
- CONVOLVE_ONE_SAMPLE // 2
- CONVOLVE_ONE_SAMPLE // 3
- CONVOLVE_ONE_SAMPLE // 4
- CONVOLVE_ONE_SAMPLE // 5
- CONVOLVE_ONE_SAMPLE // 6
- CONVOLVE_ONE_SAMPLE // 7
- CONVOLVE_ONE_SAMPLE // 8
- CONVOLVE_ONE_SAMPLE // 9
- CONVOLVE_ONE_SAMPLE // 10
-
- CONVOLVE_ONE_SAMPLE // 11
- CONVOLVE_ONE_SAMPLE // 12
- CONVOLVE_ONE_SAMPLE // 13
- CONVOLVE_ONE_SAMPLE // 14
- CONVOLVE_ONE_SAMPLE // 15
- CONVOLVE_ONE_SAMPLE // 16
- CONVOLVE_ONE_SAMPLE // 17
- CONVOLVE_ONE_SAMPLE // 18
- CONVOLVE_ONE_SAMPLE // 19
- CONVOLVE_ONE_SAMPLE // 20
-
- CONVOLVE_ONE_SAMPLE // 21
- CONVOLVE_ONE_SAMPLE // 22
- CONVOLVE_ONE_SAMPLE // 23
- CONVOLVE_ONE_SAMPLE // 24
- CONVOLVE_ONE_SAMPLE // 25
- CONVOLVE_ONE_SAMPLE // 26
- CONVOLVE_ONE_SAMPLE // 27
- CONVOLVE_ONE_SAMPLE // 28
- CONVOLVE_ONE_SAMPLE // 29
- CONVOLVE_ONE_SAMPLE // 30
-
- CONVOLVE_ONE_SAMPLE // 31
- CONVOLVE_ONE_SAMPLE // 32
- CONVOLVE_ONE_SAMPLE // 33
- CONVOLVE_ONE_SAMPLE // 34
- CONVOLVE_ONE_SAMPLE // 35
- CONVOLVE_ONE_SAMPLE // 36
- CONVOLVE_ONE_SAMPLE // 37
- CONVOLVE_ONE_SAMPLE // 38
- CONVOLVE_ONE_SAMPLE // 39
- CONVOLVE_ONE_SAMPLE // 40
-
- CONVOLVE_ONE_SAMPLE // 41
- CONVOLVE_ONE_SAMPLE // 42
- CONVOLVE_ONE_SAMPLE // 43
- CONVOLVE_ONE_SAMPLE // 44
- CONVOLVE_ONE_SAMPLE // 45
- CONVOLVE_ONE_SAMPLE // 46
- CONVOLVE_ONE_SAMPLE // 47
- CONVOLVE_ONE_SAMPLE // 48
- CONVOLVE_ONE_SAMPLE // 49
- CONVOLVE_ONE_SAMPLE // 50
-
- CONVOLVE_ONE_SAMPLE // 51
- CONVOLVE_ONE_SAMPLE // 52
- CONVOLVE_ONE_SAMPLE // 53
- CONVOLVE_ONE_SAMPLE // 54
- CONVOLVE_ONE_SAMPLE // 55
- CONVOLVE_ONE_SAMPLE // 56
- CONVOLVE_ONE_SAMPLE // 57
- CONVOLVE_ONE_SAMPLE // 58
- CONVOLVE_ONE_SAMPLE // 59
- CONVOLVE_ONE_SAMPLE // 60
-
- CONVOLVE_ONE_SAMPLE // 61
- CONVOLVE_ONE_SAMPLE // 62
- CONVOLVE_ONE_SAMPLE // 63
- CONVOLVE_ONE_SAMPLE // 64
-
- } else if (kernelSize == 128) {
- CONVOLVE_ONE_SAMPLE // 1
- CONVOLVE_ONE_SAMPLE // 2
- CONVOLVE_ONE_SAMPLE // 3
- CONVOLVE_ONE_SAMPLE // 4
- CONVOLVE_ONE_SAMPLE // 5
- CONVOLVE_ONE_SAMPLE // 6
- CONVOLVE_ONE_SAMPLE // 7
- CONVOLVE_ONE_SAMPLE // 8
- CONVOLVE_ONE_SAMPLE // 9
- CONVOLVE_ONE_SAMPLE // 10
-
- CONVOLVE_ONE_SAMPLE // 11
- CONVOLVE_ONE_SAMPLE // 12
- CONVOLVE_ONE_SAMPLE // 13
- CONVOLVE_ONE_SAMPLE // 14
- CONVOLVE_ONE_SAMPLE // 15
- CONVOLVE_ONE_SAMPLE // 16
- CONVOLVE_ONE_SAMPLE // 17
- CONVOLVE_ONE_SAMPLE // 18
- CONVOLVE_ONE_SAMPLE // 19
- CONVOLVE_ONE_SAMPLE // 20
-
- CONVOLVE_ONE_SAMPLE // 21
- CONVOLVE_ONE_SAMPLE // 22
- CONVOLVE_ONE_SAMPLE // 23
- CONVOLVE_ONE_SAMPLE // 24
- CONVOLVE_ONE_SAMPLE // 25
- CONVOLVE_ONE_SAMPLE // 26
- CONVOLVE_ONE_SAMPLE // 27
- CONVOLVE_ONE_SAMPLE // 28
- CONVOLVE_ONE_SAMPLE // 29
- CONVOLVE_ONE_SAMPLE // 30
-
- CONVOLVE_ONE_SAMPLE // 31
- CONVOLVE_ONE_SAMPLE // 32
- CONVOLVE_ONE_SAMPLE // 33
- CONVOLVE_ONE_SAMPLE // 34
- CONVOLVE_ONE_SAMPLE // 35
- CONVOLVE_ONE_SAMPLE // 36
- CONVOLVE_ONE_SAMPLE // 37
- CONVOLVE_ONE_SAMPLE // 38
- CONVOLVE_ONE_SAMPLE // 39
- CONVOLVE_ONE_SAMPLE // 40
-
- CONVOLVE_ONE_SAMPLE // 41
- CONVOLVE_ONE_SAMPLE // 42
- CONVOLVE_ONE_SAMPLE // 43
- CONVOLVE_ONE_SAMPLE // 44
- CONVOLVE_ONE_SAMPLE // 45
- CONVOLVE_ONE_SAMPLE // 46
- CONVOLVE_ONE_SAMPLE // 47
- CONVOLVE_ONE_SAMPLE // 48
- CONVOLVE_ONE_SAMPLE // 49
- CONVOLVE_ONE_SAMPLE // 50
-
- CONVOLVE_ONE_SAMPLE // 51
- CONVOLVE_ONE_SAMPLE // 52
- CONVOLVE_ONE_SAMPLE // 53
- CONVOLVE_ONE_SAMPLE // 54
- CONVOLVE_ONE_SAMPLE // 55
- CONVOLVE_ONE_SAMPLE // 56
- CONVOLVE_ONE_SAMPLE // 57
- CONVOLVE_ONE_SAMPLE // 58
- CONVOLVE_ONE_SAMPLE // 59
- CONVOLVE_ONE_SAMPLE // 60
-
- CONVOLVE_ONE_SAMPLE // 61
- CONVOLVE_ONE_SAMPLE // 62
- CONVOLVE_ONE_SAMPLE // 63
- CONVOLVE_ONE_SAMPLE // 64
- CONVOLVE_ONE_SAMPLE // 65
- CONVOLVE_ONE_SAMPLE // 66
- CONVOLVE_ONE_SAMPLE // 67
- CONVOLVE_ONE_SAMPLE // 68
- CONVOLVE_ONE_SAMPLE // 69
- CONVOLVE_ONE_SAMPLE // 70
-
- CONVOLVE_ONE_SAMPLE // 71
- CONVOLVE_ONE_SAMPLE // 72
- CONVOLVE_ONE_SAMPLE // 73
- CONVOLVE_ONE_SAMPLE // 74
- CONVOLVE_ONE_SAMPLE // 75
- CONVOLVE_ONE_SAMPLE // 76
- CONVOLVE_ONE_SAMPLE // 77
- CONVOLVE_ONE_SAMPLE // 78
- CONVOLVE_ONE_SAMPLE // 79
- CONVOLVE_ONE_SAMPLE // 80
-
- CONVOLVE_ONE_SAMPLE // 81
- CONVOLVE_ONE_SAMPLE // 82
- CONVOLVE_ONE_SAMPLE // 83
- CONVOLVE_ONE_SAMPLE // 84
- CONVOLVE_ONE_SAMPLE // 85
- CONVOLVE_ONE_SAMPLE // 86
- CONVOLVE_ONE_SAMPLE // 87
- CONVOLVE_ONE_SAMPLE // 88
- CONVOLVE_ONE_SAMPLE // 89
- CONVOLVE_ONE_SAMPLE // 90
-
- CONVOLVE_ONE_SAMPLE // 91
- CONVOLVE_ONE_SAMPLE // 92
- CONVOLVE_ONE_SAMPLE // 93
- CONVOLVE_ONE_SAMPLE // 94
- CONVOLVE_ONE_SAMPLE // 95
- CONVOLVE_ONE_SAMPLE // 96
- CONVOLVE_ONE_SAMPLE // 97
- CONVOLVE_ONE_SAMPLE // 98
- CONVOLVE_ONE_SAMPLE // 99
- CONVOLVE_ONE_SAMPLE // 100
-
- CONVOLVE_ONE_SAMPLE // 101
- CONVOLVE_ONE_SAMPLE // 102
- CONVOLVE_ONE_SAMPLE // 103
- CONVOLVE_ONE_SAMPLE // 104
- CONVOLVE_ONE_SAMPLE // 105
- CONVOLVE_ONE_SAMPLE // 106
- CONVOLVE_ONE_SAMPLE // 107
- CONVOLVE_ONE_SAMPLE // 108
- CONVOLVE_ONE_SAMPLE // 109
- CONVOLVE_ONE_SAMPLE // 110
-
- CONVOLVE_ONE_SAMPLE // 111
- CONVOLVE_ONE_SAMPLE // 112
- CONVOLVE_ONE_SAMPLE // 113
- CONVOLVE_ONE_SAMPLE // 114
- CONVOLVE_ONE_SAMPLE // 115
- CONVOLVE_ONE_SAMPLE // 116
- CONVOLVE_ONE_SAMPLE // 117
- CONVOLVE_ONE_SAMPLE // 118
- CONVOLVE_ONE_SAMPLE // 119
- CONVOLVE_ONE_SAMPLE // 120
-
- CONVOLVE_ONE_SAMPLE // 121
- CONVOLVE_ONE_SAMPLE // 122
- CONVOLVE_ONE_SAMPLE // 123
- CONVOLVE_ONE_SAMPLE // 124
- CONVOLVE_ONE_SAMPLE // 125
- CONVOLVE_ONE_SAMPLE // 126
- CONVOLVE_ONE_SAMPLE // 127
- CONVOLVE_ONE_SAMPLE // 128
- } else {
- while (j < kernelSize) {
- // Non-optimized using actual while loop.
- CONVOLVE_ONE_SAMPLE
- }
- }
- destP[i++] = sum;
- }
-
- // Copy 2nd half of input buffer to 1st half.
- memcpy(m_buffer.Elements(), inputP, sizeof(float) * framesToProcess);
-}
-
-void DirectConvolver::reset()
-{
- PodZero(m_buffer.Elements(), m_buffer.Length());
-}
-
-} // namespace WebCore
diff --git a/dom/media/webaudio/blink/DirectConvolver.h b/dom/media/webaudio/blink/DirectConvolver.h
deleted file mode 100644
index 5732da64968..00000000000
--- a/dom/media/webaudio/blink/DirectConvolver.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2012 Intel Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DirectConvolver_h
-#define DirectConvolver_h
-
-#include "nsTArray.h"
-#include "mozilla/MemoryReporting.h"
-
-namespace WebCore {
-
-class DirectConvolver {
-public:
- explicit DirectConvolver(size_t inputBlockSize);
-
- void process(const nsTArray* convolutionKernel, const float* sourceP, float* destP, size_t framesToProcess);
-
- void reset();
-
- size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
- {
- size_t amount = aMallocSizeOf(this);
- amount += m_buffer.ShallowSizeOfExcludingThis(aMallocSizeOf);
- return amount;
- }
-
-
-private:
- size_t m_inputBlockSize;
-
- nsTArray m_buffer;
-};
-
-} // namespace WebCore
-
-#endif // DirectConvolver_h
diff --git a/dom/media/webaudio/blink/FFTConvolver.cpp b/dom/media/webaudio/blink/FFTConvolver.cpp
index 9d3305c7d1e..8694073ae21 100644
--- a/dom/media/webaudio/blink/FFTConvolver.cpp
+++ b/dom/media/webaudio/blink/FFTConvolver.cpp
@@ -33,10 +33,11 @@ using namespace mozilla;
namespace WebCore {
-FFTConvolver::FFTConvolver(size_t fftSize)
+FFTConvolver::FFTConvolver(size_t fftSize, size_t renderPhase)
: m_frame(fftSize)
- , m_readWriteIndex(0)
+ , m_readWriteIndex(renderPhase % (fftSize / 2))
{
+ MOZ_ASSERT(fftSize >= 2 * WEBAUDIO_BLOCK_SIZE);
m_inputBuffer.SetLength(fftSize);
PodZero(m_inputBuffer.Elements(), fftSize);
m_outputBuffer.SetLength(fftSize);
@@ -60,67 +61,47 @@ size_t FFTConvolver::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) co
return aMallocSizeOf(this) + sizeOfExcludingThis(aMallocSizeOf);
}
-void FFTConvolver::process(FFTBlock* fftKernel, const float* sourceP, float* destP, size_t framesToProcess)
+const float* FFTConvolver::process(FFTBlock* fftKernel, const float* sourceP)
{
size_t halfSize = fftSize() / 2;
- // framesToProcess must be an exact multiple of halfSize,
- // or halfSize is a multiple of framesToProcess when halfSize > framesToProcess.
- bool isGood = !(halfSize % framesToProcess && framesToProcess % halfSize);
- MOZ_ASSERT(isGood);
- if (!isGood)
- return;
+ // WEBAUDIO_BLOCK_SIZE must be an exact multiple of halfSize,
+ // halfSize must be a multiple of WEBAUDIO_BLOCK_SIZE
+ // and > WEBAUDIO_BLOCK_SIZE.
+ MOZ_ASSERT(halfSize % WEBAUDIO_BLOCK_SIZE == 0 &&
+ WEBAUDIO_BLOCK_SIZE <= halfSize);
- size_t numberOfDivisions = halfSize <= framesToProcess ? (framesToProcess / halfSize) : 1;
- size_t divisionSize = numberOfDivisions == 1 ? framesToProcess : halfSize;
+ // Copy samples to input buffer (note contraint above!)
+ float* inputP = m_inputBuffer.Elements();
- for (size_t i = 0; i < numberOfDivisions; ++i, sourceP += divisionSize, destP += divisionSize) {
- // Copy samples to input buffer (note contraint above!)
- float* inputP = m_inputBuffer.Elements();
+ MOZ_ASSERT(sourceP && inputP && m_readWriteIndex + WEBAUDIO_BLOCK_SIZE <= m_inputBuffer.Length());
- // Sanity check
- bool isCopyGood1 = sourceP && inputP && m_readWriteIndex + divisionSize <= m_inputBuffer.Length();
- MOZ_ASSERT(isCopyGood1);
- if (!isCopyGood1)
- return;
+ memcpy(inputP + m_readWriteIndex, sourceP, sizeof(float) * WEBAUDIO_BLOCK_SIZE);
- memcpy(inputP + m_readWriteIndex, sourceP, sizeof(float) * divisionSize);
+ float* outputP = m_outputBuffer.Elements();
+ m_readWriteIndex += WEBAUDIO_BLOCK_SIZE;
- // Copy samples from output buffer
- float* outputP = m_outputBuffer.Elements();
+ // Check if it's time to perform the next FFT
+ if (m_readWriteIndex == halfSize) {
+ // The input buffer is now filled (get frequency-domain version)
+ m_frame.PerformFFT(m_inputBuffer.Elements());
+ m_frame.Multiply(*fftKernel);
+ m_frame.GetInverseWithoutScaling(m_outputBuffer.Elements());
- // Sanity check
- bool isCopyGood2 = destP && outputP && m_readWriteIndex + divisionSize <= m_outputBuffer.Length();
- MOZ_ASSERT(isCopyGood2);
- if (!isCopyGood2)
- return;
+ // Overlap-add 1st half from previous time
+ AudioBufferAddWithScale(m_lastOverlapBuffer.Elements(), 1.0f,
+ m_outputBuffer.Elements(), halfSize);
- memcpy(destP, outputP + m_readWriteIndex, sizeof(float) * divisionSize);
- m_readWriteIndex += divisionSize;
+ // Finally, save 2nd half of result
+ MOZ_ASSERT(m_outputBuffer.Length() == 2 * halfSize && m_lastOverlapBuffer.Length() == halfSize);
- // Check if it's time to perform the next FFT
- if (m_readWriteIndex == halfSize) {
- // The input buffer is now filled (get frequency-domain version)
- m_frame.PerformFFT(m_inputBuffer.Elements());
- m_frame.Multiply(*fftKernel);
- m_frame.GetInverseWithoutScaling(m_outputBuffer.Elements());
+ memcpy(m_lastOverlapBuffer.Elements(), m_outputBuffer.Elements() + halfSize, sizeof(float) * halfSize);
- // Overlap-add 1st half from previous time
- AudioBufferAddWithScale(m_lastOverlapBuffer.Elements(), 1.0f,
- m_outputBuffer.Elements(), halfSize);
-
- // Finally, save 2nd half of result
- bool isCopyGood3 = m_outputBuffer.Length() == 2 * halfSize && m_lastOverlapBuffer.Length() == halfSize;
- MOZ_ASSERT(isCopyGood3);
- if (!isCopyGood3)
- return;
-
- memcpy(m_lastOverlapBuffer.Elements(), m_outputBuffer.Elements() + halfSize, sizeof(float) * halfSize);
-
- // Reset index back to start for next time
- m_readWriteIndex = 0;
- }
+ // Reset index back to start for next time
+ m_readWriteIndex = 0;
}
+
+ return outputP + m_readWriteIndex;
}
void FFTConvolver::reset()
@@ -129,4 +110,10 @@ void FFTConvolver::reset()
m_readWriteIndex = 0;
}
+size_t FFTConvolver::latencyFrames() const
+{
+ return std::max(fftSize()/2, WEBAUDIO_BLOCK_SIZE) -
+ WEBAUDIO_BLOCK_SIZE;
+}
+
} // namespace WebCore
diff --git a/dom/media/webaudio/blink/FFTConvolver.h b/dom/media/webaudio/blink/FFTConvolver.h
index 53cebf8c876..118c6baef5a 100644
--- a/dom/media/webaudio/blink/FFTConvolver.h
+++ b/dom/media/webaudio/blink/FFTConvolver.h
@@ -40,24 +40,29 @@ using mozilla::FFTBlock;
class FFTConvolver {
public:
- // fftSize must be a power of two
- explicit FFTConvolver(size_t fftSize);
+ // |fftSize| must be a power of two.
+ //
+ // |renderPhase| is the initial offset in the initially zero input buffer.
+ // It is coordinated with the other stages, so they don't all do their
+ // FFTs at the same time.
+ explicit FFTConvolver(size_t fftSize, size_t renderPhase = 0);
+ // Process WEBAUDIO_BLOCK_SIZE elements of array |sourceP| and return a
+ // pointer to an output array of the same size.
+ //
// |fftKernel| must be pre-scaled for FFTBlock::GetInverseWithoutScaling().
//
- // For now, with multiple calls to Process(), framesToProcess MUST add up EXACTLY to fftSize / 2
- //
// FIXME: Later, we can do more sophisticated buffering to relax this requirement...
- //
- // The input to output latency is equal to fftSize / 2
- //
- // Processing in-place is allowed...
- void process(FFTBlock* fftKernel, const float* sourceP, float* destP, size_t framesToProcess);
+ const float* process(FFTBlock* fftKernel, const float* sourceP);
void reset();
size_t fftSize() const { return m_frame.FFTSize(); }
+ // The input to output latency is up to fftSize / 2, but alignment of the
+ // FFTs with the blocks reduces this by one block.
+ size_t latencyFrames() const;
+
size_t sizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
diff --git a/dom/media/webaudio/blink/HRTFElevation.cpp b/dom/media/webaudio/blink/HRTFElevation.cpp
index f53943d6c56..c6e04308859 100644
--- a/dom/media/webaudio/blink/HRTFElevation.cpp
+++ b/dom/media/webaudio/blink/HRTFElevation.cpp
@@ -76,19 +76,19 @@ size_t HRTFElevation::fftSizeForSampleRate(float sampleRate)
// This is the size if we were to use all raw response samples.
unsigned resampledLength =
floorf(ResponseFrameSize * sampleRate / rawSampleRate);
- // Keep things semi-sane, with max FFT size of 1024 and minimum of 4.
- // "size |= 3" ensures a minimum of 4 (with the size++ below) and sets the
- // 2 least significant bits for rounding up to the next power of 2 below.
+ // Keep things semi-sane, with max FFT size of 1024.
unsigned size = min(resampledLength, 1023U);
- size |= 3;
+ // Ensure a minimum of 2 * WEBAUDIO_BLOCK_SIZE (with the size++ below) for
+ // FFTConvolver and set the 8 least significant bits for rounding up to
+ // the next power of 2 below.
+ size |= 2 * WEBAUDIO_BLOCK_SIZE - 1;
// Round up to the next power of 2, making the FFT size no more than twice
// the impulse response length. This doubles size for values that are
- // already powers of 2. This works by filling in 7 bits to right of the
+ // already powers of 2. This works by filling in alls bit to right of the
// most significant bit. The most significant bit is no greater than
- // 1 << 9, and the least significant 2 bits were already set above.
+ // 1 << 9, and the least significant 8 bits were already set above, so
+ // there is at most one bit to add.
size |= (size >> 1);
- size |= (size >> 2);
- size |= (size >> 4);
size++;
MOZ_ASSERT((size & (size - 1)) == 0);
diff --git a/dom/media/webaudio/blink/HRTFPanner.cpp b/dom/media/webaudio/blink/HRTFPanner.cpp
index 11c27289419..c97ce47670f 100644
--- a/dom/media/webaudio/blink/HRTFPanner.cpp
+++ b/dom/media/webaudio/blink/HRTFPanner.cpp
@@ -59,11 +59,6 @@ HRTFPanner::HRTFPanner(float sampleRate, already_AddRefed da
{
MOZ_ASSERT(m_databaseLoader);
MOZ_COUNT_CTOR(HRTFPanner);
-
- m_tempL1.SetLength(RenderingQuantum);
- m_tempR1.SetLength(RenderingQuantum);
- m_tempL2.SetLength(RenderingQuantum);
- m_tempR2.SetLength(RenderingQuantum);
}
HRTFPanner::~HRTFPanner()
@@ -81,10 +76,6 @@ size_t HRTFPanner::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) cons
amount += m_convolverL2.sizeOfExcludingThis(aMallocSizeOf);
amount += m_convolverR2.sizeOfExcludingThis(aMallocSizeOf);
amount += m_delayLine.SizeOfExcludingThis(aMallocSizeOf);
- amount += m_tempL1.ShallowSizeOfExcludingThis(aMallocSizeOf);
- amount += m_tempL2.ShallowSizeOfExcludingThis(aMallocSizeOf);
- amount += m_tempR1.ShallowSizeOfExcludingThis(aMallocSizeOf);
- amount += m_tempR2.ShallowSizeOfExcludingThis(aMallocSizeOf);
return amount;
}
@@ -256,23 +247,26 @@ void HRTFPanner::pan(double desiredAzimuth, double elevation, const AudioBlock*
bool needsCrossfading = m_crossfadeIncr;
- // Have the convolvers render directly to the final destination if we're not cross-fading.
- float* convolutionDestinationL1 = needsCrossfading ? m_tempL1.Elements() : destinationL;
- float* convolutionDestinationR1 = needsCrossfading ? m_tempR1.Elements() : destinationR;
- float* convolutionDestinationL2 = needsCrossfading ? m_tempL2.Elements() : destinationL;
- float* convolutionDestinationR2 = needsCrossfading ? m_tempR2.Elements() : destinationR;
+ const float* convolutionDestinationL1;
+ const float* convolutionDestinationR1;
+ const float* convolutionDestinationL2;
+ const float* convolutionDestinationR2;
// Now do the convolutions.
// Note that we avoid doing convolutions on both sets of convolvers if we're not currently cross-fading.
if (m_crossfadeSelection == CrossfadeSelection1 || needsCrossfading) {
- m_convolverL1.process(kernelL1->fftFrame(), destinationL, convolutionDestinationL1, WEBAUDIO_BLOCK_SIZE);
- m_convolverR1.process(kernelR1->fftFrame(), destinationR, convolutionDestinationR1, WEBAUDIO_BLOCK_SIZE);
+ convolutionDestinationL1 =
+ m_convolverL1.process(kernelL1->fftFrame(), destinationL);
+ convolutionDestinationR1 =
+ m_convolverR1.process(kernelR1->fftFrame(), destinationR);
}
if (m_crossfadeSelection == CrossfadeSelection2 || needsCrossfading) {
- m_convolverL2.process(kernelL2->fftFrame(), destinationL, convolutionDestinationL2, WEBAUDIO_BLOCK_SIZE);
- m_convolverR2.process(kernelR2->fftFrame(), destinationR, convolutionDestinationR2, WEBAUDIO_BLOCK_SIZE);
+ convolutionDestinationL2 =
+ m_convolverL2.process(kernelL2->fftFrame(), destinationL);
+ convolutionDestinationR2 =
+ m_convolverR2.process(kernelR2->fftFrame(), destinationR);
}
if (needsCrossfading) {
@@ -298,6 +292,18 @@ void HRTFPanner::pan(double desiredAzimuth, double elevation, const AudioBlock*
m_crossfadeX = 0;
m_crossfadeIncr = 0;
}
+ } else {
+ const float* sourceL;
+ const float* sourceR;
+ if (m_crossfadeSelection == CrossfadeSelection1) {
+ sourceL = convolutionDestinationL1;
+ sourceR = convolutionDestinationR1;
+ } else {
+ sourceL = convolutionDestinationL2;
+ sourceR = convolutionDestinationR2;
+ }
+ PodCopy(destinationL, sourceL, WEBAUDIO_BLOCK_SIZE);
+ PodCopy(destinationR, sourceR, WEBAUDIO_BLOCK_SIZE);
}
}
@@ -307,10 +313,12 @@ int HRTFPanner::maxTailFrames() const
// response, there is additional tail time from the approximations in the
// implementation. Because HRTFPanner is implemented with a DelayKernel
// and a FFTConvolver, the tailTime of the HRTFPanner is the sum of the
- // tailTime of the DelayKernel and the tailTime of the FFTConvolver.
- // The FFTConvolver has a tail time of fftSize(), including latency of
- // fftSize()/2.
- return m_delayLine.MaxDelayTicks() + fftSize();
+ // tailTime of the DelayKernel and the tailTime of the FFTConvolver. The
+ // FFTs of the convolver are fftSize(), half of which is latency, but this
+ // is aligned with blocks and so is reduced by the one block which is
+ // processed immediately.
+ return m_delayLine.MaxDelayTicks() +
+ m_convolverL1.fftSize()/2 + m_convolverL1.latencyFrames();
}
} // namespace WebCore
diff --git a/dom/media/webaudio/blink/Reverb.cpp b/dom/media/webaudio/blink/Reverb.cpp
index a54f92978b4..39f9d59c935 100644
--- a/dom/media/webaudio/blink/Reverb.cpp
+++ b/dom/media/webaudio/blink/Reverb.cpp
@@ -77,7 +77,7 @@ static float calculateNormalizationScale(ThreadSharedFloatArrayBufferList* respo
return scale;
}
-Reverb::Reverb(ThreadSharedFloatArrayBufferList* impulseResponse, size_t impulseResponseBufferLength, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads, bool normalize, float sampleRate)
+Reverb::Reverb(ThreadSharedFloatArrayBufferList* impulseResponse, size_t impulseResponseBufferLength, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads, bool normalize, float sampleRate)
{
float scale = 1;
@@ -101,7 +101,7 @@ Reverb::Reverb(ThreadSharedFloatArrayBufferList* impulseResponse, size_t impulse
}
}
- initialize(irChannels, impulseResponseBufferLength, renderSliceSize,
+ initialize(irChannels, impulseResponseBufferLength,
maxFFTSize, numberOfChannels, useBackgroundThreads);
}
@@ -121,7 +121,7 @@ size_t Reverb::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
void Reverb::initialize(const nsTArray& impulseResponseBuffer,
- size_t impulseResponseBufferLength, size_t renderSliceSize,
+ size_t impulseResponseBufferLength,
size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads)
{
m_impulseResponseLength = impulseResponseBufferLength;
@@ -135,10 +135,10 @@ void Reverb::initialize(const nsTArray& impulseResponseBuffer,
const float* channel = impulseResponseBuffer[i];
size_t length = impulseResponseBufferLength;
- nsAutoPtr convolver(new ReverbConvolver(channel, length, renderSliceSize, maxFFTSize, convolverRenderPhase, useBackgroundThreads));
+ nsAutoPtr convolver(new ReverbConvolver(channel, length, maxFFTSize, convolverRenderPhase, useBackgroundThreads));
m_convolvers.AppendElement(convolver.forget());
- convolverRenderPhase += renderSliceSize;
+ convolverRenderPhase += WEBAUDIO_BLOCK_SIZE;
}
// For "True" stereo processing we allocate a temporary buffer to avoid repeatedly allocating it in the process() method.
@@ -149,12 +149,12 @@ void Reverb::initialize(const nsTArray& impulseResponseBuffer,
}
}
-void Reverb::process(const AudioBlock* sourceBus, AudioBlock* destinationBus, size_t framesToProcess)
+void Reverb::process(const AudioBlock* sourceBus, AudioBlock* destinationBus)
{
// Do a fairly comprehensive sanity check.
// If these conditions are satisfied, all of the source and destination pointers will be valid for the various matrixing cases.
bool isSafeToProcess = sourceBus && destinationBus && sourceBus->ChannelCount() > 0 && destinationBus->mChannelData.Length() > 0
- && framesToProcess <= MaxFrameSize && framesToProcess <= size_t(sourceBus->GetDuration()) && framesToProcess <= size_t(destinationBus->GetDuration());
+ && WEBAUDIO_BLOCK_SIZE <= MaxFrameSize && WEBAUDIO_BLOCK_SIZE <= size_t(sourceBus->GetDuration()) && WEBAUDIO_BLOCK_SIZE <= size_t(destinationBus->GetDuration());
MOZ_ASSERT(isSafeToProcess);
if (!isSafeToProcess)
@@ -175,28 +175,28 @@ void Reverb::process(const AudioBlock* sourceBus, AudioBlock* destinationBus, si
// 2 -> 2 -> 2
const float* sourceBusR = static_cast(sourceBus->mChannelData[1]);
float* destinationChannelR = static_cast(const_cast(destinationBus->mChannelData[1]));
- m_convolvers[0]->process(sourceBusL, sourceBus->GetDuration(), destinationChannelL, destinationBus->GetDuration(), framesToProcess);
- m_convolvers[1]->process(sourceBusR, sourceBus->GetDuration(), destinationChannelR, destinationBus->GetDuration(), framesToProcess);
+ m_convolvers[0]->process(sourceBusL, destinationChannelL);
+ m_convolvers[1]->process(sourceBusR, destinationChannelR);
} else if (numInputChannels == 1 && numOutputChannels == 2 && numReverbChannels == 2) {
// 1 -> 2 -> 2
for (int i = 0; i < 2; ++i) {
float* destinationChannel = static_cast(const_cast(destinationBus->mChannelData[i]));
- m_convolvers[i]->process(sourceBusL, sourceBus->GetDuration(), destinationChannel, destinationBus->GetDuration(), framesToProcess);
+ m_convolvers[i]->process(sourceBusL, destinationChannel);
}
} else if (numInputChannels == 1 && numReverbChannels == 1 && numOutputChannels == 2) {
// 1 -> 1 -> 2
- m_convolvers[0]->process(sourceBusL, sourceBus->GetDuration(), destinationChannelL, destinationBus->GetDuration(), framesToProcess);
+ m_convolvers[0]->process(sourceBusL, destinationChannelL);
// simply copy L -> R
float* destinationChannelR = static_cast(const_cast(destinationBus->mChannelData[1]));
- bool isCopySafe = destinationChannelL && destinationChannelR && size_t(destinationBus->GetDuration()) >= framesToProcess;
+ bool isCopySafe = destinationChannelL && destinationChannelR && size_t(destinationBus->GetDuration()) >= WEBAUDIO_BLOCK_SIZE;
MOZ_ASSERT(isCopySafe);
if (!isCopySafe)
return;
- PodCopy(destinationChannelR, destinationChannelL, framesToProcess);
+ PodCopy(destinationChannelR, destinationChannelL, WEBAUDIO_BLOCK_SIZE);
} else if (numInputChannels == 1 && numReverbChannels == 1 && numOutputChannels == 1) {
// 1 -> 1 -> 1
- m_convolvers[0]->process(sourceBusL, sourceBus->GetDuration(), destinationChannelL, destinationBus->GetDuration(), framesToProcess);
+ m_convolvers[0]->process(sourceBusL, destinationChannelL);
} else if (numInputChannels == 2 && numReverbChannels == 4 && numOutputChannels == 2) {
// 2 -> 4 -> 2 ("True" stereo)
const float* sourceBusR = static_cast(sourceBus->mChannelData[1]);
@@ -206,12 +206,12 @@ void Reverb::process(const AudioBlock* sourceBus, AudioBlock* destinationBus, si
float* tempChannelR = static_cast(const_cast(m_tempBuffer.mChannelData[1]));
// Process left virtual source
- m_convolvers[0]->process(sourceBusL, sourceBus->GetDuration(), destinationChannelL, destinationBus->GetDuration(), framesToProcess);
- m_convolvers[1]->process(sourceBusL, sourceBus->GetDuration(), destinationChannelR, destinationBus->GetDuration(), framesToProcess);
+ m_convolvers[0]->process(sourceBusL, destinationChannelL);
+ m_convolvers[1]->process(sourceBusL, destinationChannelR);
// Process right virtual source
- m_convolvers[2]->process(sourceBusR, sourceBus->GetDuration(), tempChannelL, m_tempBuffer.GetDuration(), framesToProcess);
- m_convolvers[3]->process(sourceBusR, sourceBus->GetDuration(), tempChannelR, m_tempBuffer.GetDuration(), framesToProcess);
+ m_convolvers[2]->process(sourceBusR, tempChannelL);
+ m_convolvers[3]->process(sourceBusR, tempChannelR);
AudioBufferAddWithScale(tempChannelL, 1.0f, destinationChannelL, sourceBus->GetDuration());
AudioBufferAddWithScale(tempChannelR, 1.0f, destinationChannelR, sourceBus->GetDuration());
@@ -224,12 +224,12 @@ void Reverb::process(const AudioBlock* sourceBus, AudioBlock* destinationBus, si
float* tempChannelR = static_cast(const_cast(m_tempBuffer.mChannelData[1]));
// Process left virtual source
- m_convolvers[0]->process(sourceBusL, sourceBus->GetDuration(), destinationChannelL, destinationBus->GetDuration(), framesToProcess);
- m_convolvers[1]->process(sourceBusL, sourceBus->GetDuration(), destinationChannelR, destinationBus->GetDuration(), framesToProcess);
+ m_convolvers[0]->process(sourceBusL, destinationChannelL);
+ m_convolvers[1]->process(sourceBusL, destinationChannelR);
// Process right virtual source
- m_convolvers[2]->process(sourceBusL, sourceBus->GetDuration(), tempChannelL, m_tempBuffer.GetDuration(), framesToProcess);
- m_convolvers[3]->process(sourceBusL, sourceBus->GetDuration(), tempChannelR, m_tempBuffer.GetDuration(), framesToProcess);
+ m_convolvers[2]->process(sourceBusL, tempChannelL);
+ m_convolvers[3]->process(sourceBusL, tempChannelR);
AudioBufferAddWithScale(tempChannelL, 1.0f, destinationChannelL, sourceBus->GetDuration());
AudioBufferAddWithScale(tempChannelR, 1.0f, destinationChannelR, sourceBus->GetDuration());
@@ -240,15 +240,4 @@ void Reverb::process(const AudioBlock* sourceBus, AudioBlock* destinationBus, si
}
}
-void Reverb::reset()
-{
- for (size_t i = 0; i < m_convolvers.Length(); ++i)
- m_convolvers[i]->reset();
-}
-
-size_t Reverb::latencyFrames() const
-{
- return !m_convolvers.IsEmpty() ? m_convolvers[0]->latencyFrames() : 0;
-}
-
} // namespace WebCore
diff --git a/dom/media/webaudio/blink/Reverb.h b/dom/media/webaudio/blink/Reverb.h
index fd4445ec333..35e72283dcd 100644
--- a/dom/media/webaudio/blink/Reverb.h
+++ b/dom/media/webaudio/blink/Reverb.h
@@ -48,18 +48,22 @@ public:
enum { MaxFrameSize = 256 };
// renderSliceSize is a rendering hint, so the FFTs can be optimized to not all occur at the same time (very bad when rendering on a real-time thread).
- Reverb(mozilla::ThreadSharedFloatArrayBufferList* impulseResponseBuffer, size_t impulseResponseBufferLength, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads, bool normalize, float sampleRate);
+ Reverb(mozilla::ThreadSharedFloatArrayBufferList* impulseResponseBuffer,
+ size_t impulseResponseBufferLength, size_t maxFFTSize,
+ size_t numberOfChannels, bool useBackgroundThreads, bool normalize,
+ float sampleRate);
- void process(const mozilla::AudioBlock* sourceBus, mozilla::AudioBlock* destinationBus, size_t framesToProcess);
- void reset();
+ void process(const mozilla::AudioBlock* sourceBus,
+ mozilla::AudioBlock* destinationBus);
size_t impulseResponseLength() const { return m_impulseResponseLength; }
- size_t latencyFrames() const;
size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
private:
- void initialize(const nsTArray& impulseResponseBuffer, size_t impulseResponseBufferLength, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads);
+ void initialize(const nsTArray& impulseResponseBuffer,
+ size_t impulseResponseBufferLength, size_t maxFFTSize,
+ size_t numberOfChannels, bool useBackgroundThreads);
size_t m_impulseResponseLength;
diff --git a/dom/media/webaudio/blink/ReverbAccumulationBuffer.cpp b/dom/media/webaudio/blink/ReverbAccumulationBuffer.cpp
index 6b92e9983e9..18d22289444 100644
--- a/dom/media/webaudio/blink/ReverbAccumulationBuffer.cpp
+++ b/dom/media/webaudio/blink/ReverbAccumulationBuffer.cpp
@@ -76,7 +76,7 @@ void ReverbAccumulationBuffer::updateReadIndex(int* readIndex, size_t numberOfFr
*readIndex = (*readIndex + numberOfFrames) % m_buffer.Length();
}
-int ReverbAccumulationBuffer::accumulate(float* source, size_t numberOfFrames, int* readIndex, size_t delayFrames)
+int ReverbAccumulationBuffer::accumulate(const float* source, size_t numberOfFrames, int* readIndex, size_t delayFrames)
{
size_t bufferLength = m_buffer.Length();
diff --git a/dom/media/webaudio/blink/ReverbAccumulationBuffer.h b/dom/media/webaudio/blink/ReverbAccumulationBuffer.h
index e07e71061ce..97ee94d271d 100644
--- a/dom/media/webaudio/blink/ReverbAccumulationBuffer.h
+++ b/dom/media/webaudio/blink/ReverbAccumulationBuffer.h
@@ -50,7 +50,7 @@ public:
// We need to pass in and update readIndex here, since each ReverbConvolverStage may be running in
// a different thread than the realtime thread calling ReadAndClear() and maintaining m_readIndex
// Returns the writeIndex where the accumulation took place
- int accumulate(float* source, size_t numberOfFrames, int* readIndex, size_t delayFrames);
+ int accumulate(const float* source, size_t numberOfFrames, int* readIndex, size_t delayFrames);
size_t readIndex() const { return m_readIndex; }
void updateReadIndex(int* readIndex, size_t numberOfFrames) const;
diff --git a/dom/media/webaudio/blink/ReverbConvolver.cpp b/dom/media/webaudio/blink/ReverbConvolver.cpp
index 34212864d96..5d386df6a02 100644
--- a/dom/media/webaudio/blink/ReverbConvolver.cpp
+++ b/dom/media/webaudio/blink/ReverbConvolver.cpp
@@ -49,29 +49,32 @@ const int InputBufferSize = 8 * 16384;
// This was found to be a good value on Mac OS X, and may work well on other platforms as well, assuming
// the very rough scheduling latencies are similar on these time-scales. Of course, this code may need to be
// tuned for individual platforms if this assumption is found to be incorrect.
-const size_t RealtimeFrameLimit = 8192 + 4096; // ~278msec @ 44.1KHz
+const size_t RealtimeFrameLimit = 8192 + 4096 // ~278msec @ 44.1KHz
+ - WEBAUDIO_BLOCK_SIZE;
+// First stage will have size MinFFTSize - successive stages will double in
+// size each time until we hit the maximum size.
+const size_t MinFFTSize = 256;
+// If we are using background threads then don't exceed this FFT size for the
+// stages which run in the real-time thread. This avoids having only one or
+// two large stages (size 16384 or so) at the end which take a lot of time
+// every several processing slices. This way we amortize the cost over more
+// processing slices.
+const size_t MaxRealtimeFFTSize = 4096;
-const size_t MinFFTSize = 128;
-const size_t MaxRealtimeFFTSize = 2048;
-
-ReverbConvolver::ReverbConvolver(const float* impulseResponseData, size_t impulseResponseLength, size_t renderSliceSize, size_t maxFFTSize, size_t convolverRenderPhase, bool useBackgroundThreads)
+ReverbConvolver::ReverbConvolver(const float* impulseResponseData,
+ size_t impulseResponseLength,
+ size_t maxFFTSize,
+ size_t convolverRenderPhase,
+ bool useBackgroundThreads)
: m_impulseResponseLength(impulseResponseLength)
- , m_accumulationBuffer(impulseResponseLength + renderSliceSize)
+ , m_accumulationBuffer(impulseResponseLength + WEBAUDIO_BLOCK_SIZE)
, m_inputBuffer(InputBufferSize)
- , m_minFFTSize(MinFFTSize) // First stage will have this size - successive stages will double in size each time
- , m_maxFFTSize(maxFFTSize) // until we hit m_maxFFTSize
, m_backgroundThread("ConvolverWorker")
, m_backgroundThreadCondition(&m_backgroundThreadLock)
, m_useBackgroundThreads(useBackgroundThreads)
, m_wantsToExit(false)
, m_moreInputBuffered(false)
{
- // If we are using background threads then don't exceed this FFT size for the
- // stages which run in the real-time thread. This avoids having only one or two
- // large stages (size 16384 or so) at the end which take a lot of time every several
- // processing slices. This way we amortize the cost over more processing slices.
- m_maxRealtimeFFTSize = MaxRealtimeFFTSize;
-
// For the moment, a good way to know if we have real-time constraint is to check if we're using background threads.
// Otherwise, assume we're being run from a command-line tool.
bool hasRealtimeConstraint = useBackgroundThreads;
@@ -79,12 +82,13 @@ ReverbConvolver::ReverbConvolver(const float* impulseResponseData, size_t impuls
const float* response = impulseResponseData;
size_t totalResponseLength = impulseResponseLength;
- // The total latency is zero because the direct-convolution is used in the leading portion.
+ // The total latency is zero because the first FFT stage is small enough
+ // to return output in the first block.
size_t reverbTotalLatency = 0;
size_t stageOffset = 0;
- int i = 0;
- size_t fftSize = m_minFFTSize;
+ size_t stagePhase = 0;
+ size_t fftSize = MinFFTSize;
while (stageOffset < totalResponseLength) {
size_t stageSize = fftSize / 2;
@@ -94,11 +98,13 @@ ReverbConvolver::ReverbConvolver(const float* impulseResponseData, size_t impuls
stageSize = totalResponseLength - stageOffset;
// This "staggers" the time when each FFT happens so they don't all happen at the same time
- int renderPhase = convolverRenderPhase + i * renderSliceSize;
+ int renderPhase = convolverRenderPhase + stagePhase;
- bool useDirectConvolver = !stageOffset;
-
- nsAutoPtr stage(new ReverbConvolverStage(response, totalResponseLength, reverbTotalLatency, stageOffset, stageSize, fftSize, renderPhase, renderSliceSize, &m_accumulationBuffer, useDirectConvolver));
+ nsAutoPtr stage
+ (new ReverbConvolverStage(response, totalResponseLength,
+ reverbTotalLatency, stageOffset, stageSize,
+ fftSize, renderPhase,
+ &m_accumulationBuffer));
bool isBackgroundStage = false;
@@ -108,18 +114,35 @@ ReverbConvolver::ReverbConvolver(const float* impulseResponseData, size_t impuls
} else
m_stages.AppendElement(stage.forget());
+ // Figure out next FFT size
+ fftSize *= 2;
+
stageOffset += stageSize;
- ++i;
- if (!useDirectConvolver) {
- // Figure out next FFT size
- fftSize *= 2;
+ if (hasRealtimeConstraint && !isBackgroundStage
+ && fftSize > MaxRealtimeFFTSize) {
+ fftSize = MaxRealtimeFFTSize;
+ // Custom phase positions for all but the first of the realtime
+ // stages of largest size. These spread out the work of the
+ // larger realtime stages. None of the FFTs of size 1024, 2048 or
+ // 4096 are performed when processing the same block. The first
+ // MaxRealtimeFFTSize = 4096 stage, at the end of the doubling,
+ // performs its FFT at block 7. The FFTs of size 2048 are
+ // performed in blocks 3 + 8 * n and size 1024 at 1 + 4 * n.
+ const uint32_t phaseLookup[] = { 14, 0, 10, 4 };
+ stagePhase = WEBAUDIO_BLOCK_SIZE *
+ phaseLookup[m_stages.Length() % ArrayLength(phaseLookup)];
+ } else if (fftSize > maxFFTSize) {
+ fftSize = maxFFTSize;
+ // A prime offset spreads out FFTs in a way that all
+ // available phase positions will be used if there are sufficient
+ // stages.
+ stagePhase += 5 * WEBAUDIO_BLOCK_SIZE;
+ } else if (stageSize > WEBAUDIO_BLOCK_SIZE) {
+ // As the stages are doubling in size, the next FFT will occur
+ // mid-way between FFTs for this stage.
+ stagePhase = stageSize - WEBAUDIO_BLOCK_SIZE;
}
-
- if (hasRealtimeConstraint && !isBackgroundStage && fftSize > m_maxRealtimeFFTSize)
- fftSize = m_maxRealtimeFFTSize;
- if (fftSize > m_maxFFTSize)
- fftSize = m_maxFFTSize;
}
// Start up background thread
@@ -199,25 +222,16 @@ void ReverbConvolver::backgroundThreadEntry()
int readIndex;
while ((readIndex = m_backgroundStages[0]->inputReadIndex()) != writeIndex) { // FIXME: do better to detect buffer overrun...
- // The ReverbConvolverStages need to process in amounts which evenly divide half the FFT size
- const int SliceSize = MinFFTSize / 2;
-
// Accumulate contributions from each stage
for (size_t i = 0; i < m_backgroundStages.Length(); ++i)
- m_backgroundStages[i]->processInBackground(this, SliceSize);
+ m_backgroundStages[i]->processInBackground(this);
}
}
}
-void ReverbConvolver::process(const float* sourceChannelData, size_t sourceChannelLength,
- float* destinationChannelData, size_t destinationChannelLength,
- size_t framesToProcess)
+void ReverbConvolver::process(const float* sourceChannelData,
+ float* destinationChannelData)
{
- bool isSafe = sourceChannelData && destinationChannelData && sourceChannelLength >= framesToProcess && destinationChannelLength >= framesToProcess;
- MOZ_ASSERT(isSafe);
- if (!isSafe)
- return;
-
const float* source = sourceChannelData;
float* destination = destinationChannelData;
bool isDataSafe = source && destination;
@@ -226,14 +240,14 @@ void ReverbConvolver::process(const float* sourceChannelData, size_t sourceChann
return;
// Feed input buffer (read by all threads)
- m_inputBuffer.write(source, framesToProcess);
+ m_inputBuffer.write(source, WEBAUDIO_BLOCK_SIZE);
// Accumulate contributions from each stage
for (size_t i = 0; i < m_stages.Length(); ++i)
- m_stages[i]->process(source, framesToProcess);
+ m_stages[i]->process(source);
// Finally read from accumulation buffer
- m_accumulationBuffer.readAndClear(destination, framesToProcess);
+ m_accumulationBuffer.readAndClear(destination, WEBAUDIO_BLOCK_SIZE);
// Now that we've buffered more input, wake up our background thread.
@@ -249,21 +263,4 @@ void ReverbConvolver::process(const float* sourceChannelData, size_t sourceChann
}
}
-void ReverbConvolver::reset()
-{
- for (size_t i = 0; i < m_stages.Length(); ++i)
- m_stages[i]->reset();
-
- for (size_t i = 0; i < m_backgroundStages.Length(); ++i)
- m_backgroundStages[i]->reset();
-
- m_accumulationBuffer.reset();
- m_inputBuffer.reset();
-}
-
-size_t ReverbConvolver::latencyFrames() const
-{
- return 0;
-}
-
} // namespace WebCore
diff --git a/dom/media/webaudio/blink/ReverbConvolver.h b/dom/media/webaudio/blink/ReverbConvolver.h
index 14b2ff2573c..b7eea45b868 100644
--- a/dom/media/webaudio/blink/ReverbConvolver.h
+++ b/dom/media/webaudio/blink/ReverbConvolver.h
@@ -50,13 +50,13 @@ public:
// For certain tweaky de-convolving applications the phase errors add up quickly and lead to non-sensical results with
// larger FFT sizes and single-precision floats. In these cases 2048 is a good size.
// If not doing multi-threaded convolution, then should not go > 8192.
- ReverbConvolver(const float* impulseResponseData, size_t impulseResponseLength, size_t renderSliceSize, size_t maxFFTSize, size_t convolverRenderPhase, bool useBackgroundThreads);
+ ReverbConvolver(const float* impulseResponseData,
+ size_t impulseResponseLength, size_t maxFFTSize,
+ size_t convolverRenderPhase, bool useBackgroundThreads);
~ReverbConvolver();
- void process(const float* sourceChannelData, size_t sourceChannelLength,
- float* destinationChannelData, size_t destinationChannelLength,
- size_t framesToProcess);
- void reset();
+ void process(const float* sourceChannelData,
+ float* destinationChannelData);
size_t impulseResponseLength() const { return m_impulseResponseLength; }
@@ -65,8 +65,6 @@ public:
bool useBackgroundThreads() const { return m_useBackgroundThreads; }
void backgroundThreadEntry();
- size_t latencyFrames() const;
-
size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
private:
nsTArray > m_stages;
@@ -78,13 +76,6 @@ private:
// One or more background threads read from this input buffer which is fed from the realtime thread.
ReverbInputBuffer m_inputBuffer;
- // First stage will be of size m_minFFTSize. Each next stage will be twice as big until we hit m_maxFFTSize.
- size_t m_minFFTSize;
- size_t m_maxFFTSize;
-
- // But don't exceed this size in the real-time thread (if we're doing background processing).
- size_t m_maxRealtimeFFTSize;
-
// Background thread and synchronization
base::Thread m_backgroundThread;
Lock m_backgroundThreadLock;
diff --git a/dom/media/webaudio/blink/ReverbConvolverStage.cpp b/dom/media/webaudio/blink/ReverbConvolverStage.cpp
index fe6a0929cbb..055098e887d 100644
--- a/dom/media/webaudio/blink/ReverbConvolverStage.cpp
+++ b/dom/media/webaudio/blink/ReverbConvolverStage.cpp
@@ -37,54 +37,32 @@ using namespace mozilla;
namespace WebCore {
-ReverbConvolverStage::ReverbConvolverStage(const float* impulseResponse, size_t, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength,
- size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer* accumulationBuffer, bool directMode)
+ReverbConvolverStage::ReverbConvolverStage(const float* impulseResponse, size_t,
+ size_t reverbTotalLatency,
+ size_t stageOffset,
+ size_t stageLength,
+ size_t fftSize, size_t renderPhase,
+ ReverbAccumulationBuffer* accumulationBuffer)
: m_accumulationBuffer(accumulationBuffer)
, m_accumulationReadIndex(0)
, m_inputReadIndex(0)
- , m_directMode(directMode)
{
MOZ_ASSERT(impulseResponse);
MOZ_ASSERT(accumulationBuffer);
- if (!m_directMode) {
- m_fftKernel = new FFTBlock(fftSize);
- m_fftKernel->PadAndMakeScaledDFT(impulseResponse + stageOffset, stageLength);
- m_fftConvolver = new FFTConvolver(fftSize);
- } else {
- m_directKernel.SetLength(fftSize / 2);
- PodCopy(m_directKernel.Elements(), impulseResponse + stageOffset, fftSize / 2);
- m_directConvolver = new DirectConvolver(renderSliceSize);
- }
- m_temporaryBuffer.SetLength(renderSliceSize);
- PodZero(m_temporaryBuffer.Elements(), m_temporaryBuffer.Length());
+ m_fftKernel = new FFTBlock(fftSize);
+ m_fftKernel->PadAndMakeScaledDFT(impulseResponse + stageOffset, stageLength);
+ m_fftConvolver = new FFTConvolver(fftSize, renderPhase);
// The convolution stage at offset stageOffset needs to have a corresponding delay to cancel out the offset.
size_t totalDelay = stageOffset + reverbTotalLatency;
- // But, the FFT convolution itself incurs fftSize / 2 latency, so subtract this out...
- size_t halfSize = fftSize / 2;
- if (!m_directMode) {
- MOZ_ASSERT(totalDelay >= halfSize);
- if (totalDelay >= halfSize)
- totalDelay -= halfSize;
- }
+ // But, the FFT convolution itself incurs latency, so subtract this out...
+ size_t fftLatency = m_fftConvolver->latencyFrames();
+ MOZ_ASSERT(totalDelay >= fftLatency);
+ totalDelay -= fftLatency;
- // We divide up the total delay, into pre and post delay sections so that we can schedule at exactly the moment when the FFT will happen.
- // This is coordinated with the other stages, so they don't all do their FFTs at the same time...
- int maxPreDelayLength = std::min(halfSize, totalDelay);
- m_preDelayLength = totalDelay > 0 ? renderPhase % maxPreDelayLength : 0;
- if (m_preDelayLength > totalDelay)
- m_preDelayLength = 0;
-
- m_postDelayLength = totalDelay - m_preDelayLength;
- m_preReadWriteIndex = 0;
- m_framesProcessed = 0; // total frames processed so far
-
- size_t delayBufferSize = m_preDelayLength < fftSize ? fftSize : m_preDelayLength;
- delayBufferSize = delayBufferSize < renderSliceSize ? renderSliceSize : delayBufferSize;
- m_preDelayBuffer.SetLength(delayBufferSize);
- PodZero(m_preDelayBuffer.Elements(), m_preDelayBuffer.Length());
+ m_postDelayLength = totalDelay;
}
size_t ReverbConvolverStage::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
@@ -99,101 +77,31 @@ size_t ReverbConvolverStage::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSi
amount += m_fftConvolver->sizeOfIncludingThis(aMallocSizeOf);
}
- amount += m_preDelayBuffer.ShallowSizeOfExcludingThis(aMallocSizeOf);
- amount += m_temporaryBuffer.ShallowSizeOfExcludingThis(aMallocSizeOf);
- amount += m_directKernel.ShallowSizeOfExcludingThis(aMallocSizeOf);
-
- if (m_directConvolver) {
- amount += m_directConvolver->sizeOfIncludingThis(aMallocSizeOf);
- }
-
return amount;
}
-void ReverbConvolverStage::processInBackground(ReverbConvolver* convolver, size_t framesToProcess)
+void ReverbConvolverStage::processInBackground(ReverbConvolver* convolver)
{
ReverbInputBuffer* inputBuffer = convolver->inputBuffer();
- float* source = inputBuffer->directReadFrom(&m_inputReadIndex, framesToProcess);
- process(source, framesToProcess);
+ float* source = inputBuffer->directReadFrom(&m_inputReadIndex,
+ WEBAUDIO_BLOCK_SIZE);
+ process(source);
}
-void ReverbConvolverStage::process(const float* source, size_t framesToProcess)
+void ReverbConvolverStage::process(const float* source)
{
MOZ_ASSERT(source);
if (!source)
return;
- // Deal with pre-delay stream : note special handling of zero delay.
+ // Now, run the convolution (into the delay buffer).
+ // An expensive FFT will happen every fftSize / 2 frames.
+ const float* output = m_fftConvolver->process(m_fftKernel, source);
- const float* preDelayedSource;
- float* preDelayedDestination;
- float* temporaryBuffer;
- bool isTemporaryBufferSafe = false;
- if (m_preDelayLength > 0) {
- // Handles both the read case (call to process() ) and the write case (memcpy() )
- bool isPreDelaySafe = m_preReadWriteIndex + framesToProcess <= m_preDelayBuffer.Length();
- MOZ_ASSERT(isPreDelaySafe);
- if (!isPreDelaySafe)
- return;
-
- isTemporaryBufferSafe = framesToProcess <= m_temporaryBuffer.Length();
-
- preDelayedDestination = m_preDelayBuffer.Elements() + m_preReadWriteIndex;
- preDelayedSource = preDelayedDestination;
- temporaryBuffer = m_temporaryBuffer.Elements();
- } else {
- // Zero delay
- preDelayedDestination = 0;
- preDelayedSource = source;
- temporaryBuffer = m_preDelayBuffer.Elements();
-
- isTemporaryBufferSafe = framesToProcess <= m_preDelayBuffer.Length();
- }
-
- MOZ_ASSERT(isTemporaryBufferSafe);
- if (!isTemporaryBufferSafe)
- return;
-
- if (m_framesProcessed < m_preDelayLength) {
- // For the first m_preDelayLength frames don't process the convolver, instead simply buffer in the pre-delay.
- // But while buffering the pre-delay, we still need to update our index.
- m_accumulationBuffer->updateReadIndex(&m_accumulationReadIndex, framesToProcess);
- } else {
- // Now, run the convolution (into the delay buffer).
- // An expensive FFT will happen every fftSize / 2 frames.
- // We process in-place here...
- if (!m_directMode)
- m_fftConvolver->process(m_fftKernel, preDelayedSource, temporaryBuffer, framesToProcess);
- else
- m_directConvolver->process(&m_directKernel, preDelayedSource, temporaryBuffer, framesToProcess);
-
- // Now accumulate into reverb's accumulation buffer.
- m_accumulationBuffer->accumulate(temporaryBuffer, framesToProcess, &m_accumulationReadIndex, m_postDelayLength);
- }
-
- // Finally copy input to pre-delay.
- if (m_preDelayLength > 0) {
- memcpy(preDelayedDestination, source, sizeof(float) * framesToProcess);
- m_preReadWriteIndex += framesToProcess;
-
- MOZ_ASSERT(m_preReadWriteIndex <= m_preDelayLength);
- if (m_preReadWriteIndex >= m_preDelayLength)
- m_preReadWriteIndex = 0;
- }
-
- m_framesProcessed += framesToProcess;
-}
-
-void ReverbConvolverStage::reset()
-{
- if (!m_directMode)
- m_fftConvolver->reset();
- else
- m_directConvolver->reset();
- PodZero(m_preDelayBuffer.Elements(), m_preDelayBuffer.Length());
- m_accumulationReadIndex = 0;
- m_inputReadIndex = 0;
- m_framesProcessed = 0;
+ // Now accumulate into reverb's accumulation buffer.
+ m_accumulationBuffer->accumulate(output, WEBAUDIO_BLOCK_SIZE,
+ &m_accumulationReadIndex,
+ m_postDelayLength);
}
} // namespace WebCore
diff --git a/dom/media/webaudio/blink/ReverbConvolverStage.h b/dom/media/webaudio/blink/ReverbConvolverStage.h
index 73879477bed..3dfe81bbdf1 100644
--- a/dom/media/webaudio/blink/ReverbConvolverStage.h
+++ b/dom/media/webaudio/blink/ReverbConvolverStage.h
@@ -29,7 +29,6 @@
#ifndef ReverbConvolverStage_h
#define ReverbConvolverStage_h
-#include "DirectConvolver.h"
#include "FFTConvolver.h"
#include "nsTArray.h"
@@ -49,14 +48,12 @@ class ReverbConvolverStage {
public:
// renderPhase is useful to know so that we can manipulate the pre versus post delay so that stages will perform
// their heavy work (FFT processing) on different slices to balance the load in a real-time thread.
- ReverbConvolverStage(const float* impulseResponse, size_t responseLength, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength, size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer*, bool directMode = false);
+ ReverbConvolverStage(const float* impulseResponse, size_t responseLength, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength, size_t fftSize, size_t renderPhase, ReverbAccumulationBuffer*);
- // WARNING: framesToProcess must be such that it evenly divides the delay buffer size (stage_offset).
- void process(const float* source, size_t framesToProcess);
+ // |source| must point to an array of WEBAUDIO_BLOCK_SIZE elements.
+ void process(const float* source);
- void processInBackground(ReverbConvolver* convolver, size_t framesToProcess);
-
- void reset();
+ void processInBackground(ReverbConvolver* convolver);
// Useful for background processing
int inputReadIndex() const { return m_inputReadIndex; }
@@ -67,22 +64,13 @@ private:
nsAutoPtr m_fftKernel;
nsAutoPtr m_fftConvolver;
- nsTArray m_preDelayBuffer;
-
ReverbAccumulationBuffer* m_accumulationBuffer;
int m_accumulationReadIndex;
int m_inputReadIndex;
- size_t m_preDelayLength;
size_t m_postDelayLength;
- size_t m_preReadWriteIndex;
- size_t m_framesProcessed;
nsTArray m_temporaryBuffer;
-
- bool m_directMode;
- nsTArray m_directKernel;
- nsAutoPtr m_directConvolver;
};
} // namespace WebCore
diff --git a/dom/media/webaudio/blink/moz.build b/dom/media/webaudio/blink/moz.build
index 196609f03ca..fd622d0749a 100644
--- a/dom/media/webaudio/blink/moz.build
+++ b/dom/media/webaudio/blink/moz.build
@@ -6,7 +6,6 @@
UNIFIED_SOURCES += [
'Biquad.cpp',
- 'DirectConvolver.cpp',
'DynamicsCompressor.cpp',
'DynamicsCompressorKernel.cpp',
'FFTConvolver.cpp',
diff --git a/dom/plugins/test/mochitest/browser.ini b/dom/plugins/test/mochitest/browser.ini
index ea83e339555..076b7e4c5d3 100644
--- a/dom/plugins/test/mochitest/browser.ini
+++ b/dom/plugins/test/mochitest/browser.ini
@@ -12,4 +12,4 @@ skip-if = (!e10s || os != "win")
[browser_tabswitchbetweenplugins.js]
skip-if = (!e10s || os != "win")
[browser_pluginscroll.js]
-skip-if = (!e10s || os != "win")
+skip-if = (true || !e10s || os != "win") # Bug 1213631
diff --git a/dom/push/Push.js b/dom/push/Push.js
index d1e1f3e5a0d..d85611e1805 100644
--- a/dom/push/Push.js
+++ b/dom/push/Push.js
@@ -68,9 +68,12 @@ Push.prototype = {
debug("askPermission");
return this.createPromise((resolve, reject) => {
- function permissionDenied() {
- reject("PermissionDeniedError");
- }
+ let permissionDenied = () => {
+ reject(new this._window.DOMException(
+ "User denied permission to use the Push API",
+ "PermissionDeniedError"
+ ));
+ };
let permission = Ci.nsIPermissionManager.UNKNOWN_ACTION;
try {
@@ -190,7 +193,10 @@ PushEndpointCallback.prototype = {
onPushEndpoint: function(ok, endpoint, keyLen, key) {
let {pushManager} = this;
if (!Components.isSuccessCode(ok)) {
- this.reject("AbortError");
+ this.reject(new pushManager._window.DOMException(
+ "Error retrieving push subscription",
+ "AbortError"
+ ));
return;
}
diff --git a/dom/push/PushManager.cpp b/dom/push/PushManager.cpp
index 5fdbc3707af..5a4044b0cdf 100644
--- a/dom/push/PushManager.cpp
+++ b/dom/push/PushManager.cpp
@@ -426,12 +426,13 @@ public:
do_CreateInstance("@mozilla.org/push/PushClient;1");
if (!client) {
callback->OnUnsubscribe(NS_ERROR_FAILURE, false);
+ return NS_OK;
}
nsCOMPtr principal = mProxy->GetWorkerPrivate()->GetPrincipal();
if (NS_WARN_IF(NS_FAILED(client->Unsubscribe(mScope, principal, callback)))) {
callback->OnUnsubscribe(NS_ERROR_FAILURE, false);
- return NS_ERROR_FAILURE;
+ return NS_OK;
}
return NS_OK;
}
@@ -521,7 +522,7 @@ public:
promise->MaybeResolve(sub);
}
} else {
- promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ promise->MaybeReject(NS_ERROR_DOM_PUSH_ABORT_ERR);
}
mProxy->CleanUp(aCx);
@@ -647,7 +648,7 @@ public:
if (NS_WARN_IF(NS_FAILED(rv))) {
callback->OnPushEndpoint(NS_ERROR_FAILURE, EmptyString(), 0, nullptr);
- return rv;
+ return NS_OK;
}
return NS_OK;
@@ -677,7 +678,7 @@ WorkerPushManager::PerformSubscriptionAction(SubscriptionAction aAction, ErrorRe
RefPtr proxy = PromiseWorkerProxy::Create(worker, p);
if (!proxy) {
- p->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ p->MaybeReject(NS_ERROR_DOM_PUSH_ABORT_ERR);
return p.forget();
}
diff --git a/dom/push/test/test_permissions.html b/dom/push/test/test_permissions.html
index 9ae76f55e39..508978f69c9 100644
--- a/dom/push/test/test_permissions.html
+++ b/dom/push/test/test_permissions.html
@@ -49,7 +49,8 @@ http://creativecommons.org/licenses/publicdomain/
yield registration.pushManager.subscribe();
ok(false, "subscribe() should fail because no permission for push");
} catch (error) {
- ok(true, "subscribe() could not register for push notification");
+ ok(error instanceof DOMException, "Wrong exception type");
+ is(error.name, "PermissionDeniedError", "Wrong exception name");
}
});
diff --git a/dom/svg/SVGSwitchElement.h b/dom/svg/SVGSwitchElement.h
index ce7b7965557..1fbf5fd92ea 100644
--- a/dom/svg/SVGSwitchElement.h
+++ b/dom/svg/SVGSwitchElement.h
@@ -21,7 +21,7 @@ typedef SVGGraphicsElement SVGSwitchElementBase;
class SVGSwitchElement final : public SVGSwitchElementBase
{
- friend class nsSVGSwitchFrame;
+ friend class ::nsSVGSwitchFrame;
protected:
friend nsresult (::NS_NewSVGSwitchElement(nsIContent **aResult,
already_AddRefed&& aNodeInfo));
diff --git a/dom/system/gonk/moz.build b/dom/system/gonk/moz.build
index 3552b6fb1ee..14c2d4e5455 100644
--- a/dom/system/gonk/moz.build
+++ b/dom/system/gonk/moz.build
@@ -66,9 +66,9 @@ UNIFIED_SOURCES += [
]
if CONFIG['ANDROID_VERSION'] >= '17':
- CXXFLAGS += ['-I%s/frameworks/av/media/mtp' % CONFIG['ANDROID_SOURCE']]
+ LOCAL_INCLUDES += ['%' + '%s/frameworks/av/media/mtp' % CONFIG['ANDROID_SOURCE']]
else:
- CXXFLAGS += ['-I%s/frameworks/base/media/mtp' % CONFIG['ANDROID_SOURCE']]
+ LOCAL_INCLUDES += ['%' + '%s/frameworks/base/media/mtp' % CONFIG['ANDROID_SOURCE']]
if CONFIG['ENABLE_TESTS']:
XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell.ini']
diff --git a/gfx/angle/moz.build b/gfx/angle/moz.build
index 479c374f4d9..a13e401542c 100644
--- a/gfx/angle/moz.build
+++ b/gfx/angle/moz.build
@@ -129,7 +129,7 @@ if CONFIG['GNU_CXX']:
]
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
- CXXFLAGS += ['-I\'%s/include/\'' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
+ LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
DEFINES['_HAS_EXCEPTIONS'] = 0
diff --git a/gfx/angle/src/libANGLE/moz.build b/gfx/angle/src/libANGLE/moz.build
index b29440b033c..d38c3de81d6 100644
--- a/gfx/angle/src/libANGLE/moz.build
+++ b/gfx/angle/src/libANGLE/moz.build
@@ -277,7 +277,7 @@ if CONFIG['GNU_CXX']:
]
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
- CXXFLAGS += ['-I\'%s/include/\'' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
+ LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
DEFINES['_HAS_EXCEPTIONS'] = 0
diff --git a/gfx/angle/src/libEGL/moz.build b/gfx/angle/src/libEGL/moz.build
index d4d25ab5784..f4cd9ebffd7 100644
--- a/gfx/angle/src/libEGL/moz.build
+++ b/gfx/angle/src/libEGL/moz.build
@@ -33,7 +33,7 @@ if CONFIG['GNU_CXX']:
]
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
- CXXFLAGS += ['-I\'%s/include/\'' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
+ LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
DEFINES['_HAS_EXCEPTIONS'] = 0
diff --git a/gfx/angle/src/libGLESv2/moz.build b/gfx/angle/src/libGLESv2/moz.build
index 96c840389c2..561b266f484 100644
--- a/gfx/angle/src/libGLESv2/moz.build
+++ b/gfx/angle/src/libGLESv2/moz.build
@@ -39,7 +39,7 @@ if CONFIG['GNU_CXX']:
]
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
- CXXFLAGS += ['-I\'%s/include/\'' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
+ LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
DEFINES['_HAS_EXCEPTIONS'] = 0
diff --git a/gfx/gl/GLUploadHelpers.h b/gfx/gl/GLUploadHelpers.h
index 5ce7875fc24..46db6fe0681 100644
--- a/gfx/gl/GLUploadHelpers.h
+++ b/gfx/gl/GLUploadHelpers.h
@@ -9,8 +9,7 @@
#include "GLDefs.h"
#include "mozilla/gfx/Types.h"
#include "nsPoint.h"
-
-class nsIntRegion;
+#include "nsRegionFwd.h"
namespace mozilla {
diff --git a/gfx/gl/moz.build b/gfx/gl/moz.build
index 6a0b78e62f9..2a10bbf99be 100644
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -86,7 +86,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
UNIFIED_SOURCES += ['SharedSurfaceGralloc.cpp']
EXPORTS += ['SharedSurfaceGralloc.h']
LOCAL_INCLUDES += ['/widget/gonk']
- CXXFLAGS += ['-I%s/%s' % (CONFIG['ANDROID_SOURCE'], 'hardware/libhardware/include')]
+ LOCAL_INCLUDES += ['%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], 'hardware/libhardware/include')]
if gl_provider == 'CGL':
# These files include Mac headers that are unfriendly to unified builds
diff --git a/gfx/layers/Compositor.h b/gfx/layers/Compositor.h
index 5b7d830bfdb..77ebeac5ccb 100644
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -106,7 +106,6 @@
*/
class nsIWidget;
-class nsIntRegion;
namespace mozilla {
namespace gfx {
diff --git a/gfx/layers/ReadbackProcessor.h b/gfx/layers/ReadbackProcessor.h
index 4ca78205ec2..b07f796c32f 100644
--- a/gfx/layers/ReadbackProcessor.h
+++ b/gfx/layers/ReadbackProcessor.h
@@ -8,9 +8,8 @@
#include // for uint64_t
#include "nsRect.h" // for mozilla::gfx::IntRect
+#include "nsRegionFwd.h" // for nsIntRegion
#include "nsTArray.h" // for nsTArray
-
-class nsIntRegion;
namespace mozilla {
namespace layers {
diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp
index ce510f92ad0..20fdcef01d2 100644
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -161,8 +161,14 @@ SetDisplayPortMargins(nsIPresShell* aPresShell,
return;
}
+ bool hadDisplayPort = nsLayoutUtils::GetDisplayPort(aContent);
ScreenMargin margins = aMetrics.GetDisplayPortMargins();
nsLayoutUtils::SetDisplayPortMargins(aContent, aPresShell, margins, 0);
+ if (!hadDisplayPort) {
+ nsLayoutUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
+ aContent->GetPrimaryFrame(), nsLayoutUtils::RepaintMode::Repaint);
+ }
+
CSSRect baseCSS = aMetrics.CalculateCompositedRectInCssPixels();
nsRect base(0, 0,
baseCSS.width * nsPresContext::AppUnitsPerCSSPixel(),
@@ -237,6 +243,7 @@ APZCCallbackHelper::UpdateRootFrame(FrameMetrics& aMetrics)
// adjusts the display port margins, so do it before we set those.
ScrollFrame(content, aMetrics);
+ MOZ_ASSERT(nsLayoutUtils::GetDisplayPort(content));
SetDisplayPortMargins(shell, content, aMetrics);
}
@@ -304,6 +311,8 @@ APZCCallbackHelper::InitializeRootDisplayport(nsIPresShell* aPresShell)
// nsRootBoxFrame::BuildDisplayList.
nsLayoutUtils::SetDisplayPortMargins(content, aPresShell, ScreenMargin(), 0,
nsLayoutUtils::RepaintMode::DoNotRepaint);
+ nsLayoutUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
+ content->GetPrimaryFrame(), nsLayoutUtils::RepaintMode::DoNotRepaint);
}
}
@@ -551,15 +560,6 @@ APZCCallbackHelper::FireSingleTapEvent(const LayoutDevicePoint& aPoint,
DispatchSynthesizedMouseEvent(eMouseUp, time, aPoint, aModifiers, aWidget);
}
-static nsIScrollableFrame*
-GetScrollableAncestorFrame(nsIFrame* aTarget)
-{
- uint32_t flags = nsLayoutUtils::SCROLLABLE_ALWAYS_MATCH_ROOT
- | nsLayoutUtils::SCROLLABLE_ONLY_ASYNC_SCROLLABLE
- | nsLayoutUtils::SCROLLABLE_FIXEDPOS_FINDS_ROOT;
- return nsLayoutUtils::GetNearestScrollableFrame(aTarget, flags);
-}
-
static dom::Element*
GetDisplayportElementFor(nsIScrollableFrame* aScrollableFrame)
{
@@ -610,7 +610,7 @@ PrepareForSetTargetAPZCNotification(nsIWidget* aWidget,
nsIFrame* target =
nsLayoutUtils::GetFrameForPoint(aRootFrame, point, nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME);
nsIScrollableFrame* scrollAncestor = target
- ? GetScrollableAncestorFrame(target)
+ ? nsLayoutUtils::GetAsyncScrollableAncestorFrame(target)
: aRootFrame->PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
// Assuming that if there's no scrollAncestor, there's already a displayPort.
@@ -651,8 +651,17 @@ PrepareForSetTargetAPZCNotification(nsIWidget* aWidget,
}
APZCCH_LOG("%p didn't have a displayport, so setting one...\n", dpElement.get());
- return nsLayoutUtils::CalculateAndSetDisplayPortMargins(
+ bool activated = nsLayoutUtils::CalculateAndSetDisplayPortMargins(
scrollAncestor, nsLayoutUtils::RepaintMode::Repaint);
+ if (!activated) {
+ return false;
+ }
+
+ nsIFrame* frame = do_QueryFrame(scrollAncestor);
+ nsLayoutUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(frame,
+ nsLayoutUtils::RepaintMode::Repaint);
+
+ return true;
}
static void
diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp
index 0c7a1ef0eec..b240c1cf3ce 100644
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -17,8 +17,6 @@
#include "nsPrintfCString.h" // for nsPrintfCString
#include "nsString.h" // for nsAutoCString
-class nsIntRegion;
-
#define BIAS_TIME_MS 1.0
namespace mozilla {
diff --git a/gfx/layers/composite/ImageHost.h b/gfx/layers/composite/ImageHost.h
index e77afa9a006..c710705e647 100644
--- a/gfx/layers/composite/ImageHost.h
+++ b/gfx/layers/composite/ImageHost.h
@@ -20,10 +20,9 @@
#include "mozilla/mozalloc.h" // for operator delete
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsRect.h" // for mozilla::gfx::IntRect
+#include "nsRegionFwd.h" // for nsIntRegion
#include "nscore.h" // for nsACString
-class nsIntRegion;
-
namespace mozilla {
namespace gfx {
class Matrix4x4;
diff --git a/gfx/layers/layerviewer/hide.png b/gfx/layers/layerviewer/hide.png
new file mode 100644
index 00000000000..9a92e2c1b1e
Binary files /dev/null and b/gfx/layers/layerviewer/hide.png differ
diff --git a/gfx/layers/layerviewer/index.html b/gfx/layers/layerviewer/index.html
new file mode 100644
index 00000000000..3ad835df567
--- /dev/null
+++ b/gfx/layers/layerviewer/index.html
@@ -0,0 +1,47 @@
+
+
+
+ GFX Display List & Layer Visualizer
+
+
+
+
+
+
+
GFX Layers dump visualizer:
+ Paste your display list or layers dump into this textarea:
+
+
+
+
+
+ Help: To get a layers dump go to about:config and set layout.display-list.dump;true or layers.dump;true.
+
+
+
diff --git a/gfx/layers/layerviewer/layerTreeView.js b/gfx/layers/layerviewer/layerTreeView.js
new file mode 100644
index 00000000000..e5ecac2511a
--- /dev/null
+++ b/gfx/layers/layerviewer/layerTreeView.js
@@ -0,0 +1,885 @@
+function toFixed(num, fixed) {
+ fixed = fixed || 0;
+ fixed = Math.pow(10, fixed);
+ return Math.floor(num * fixed) / fixed;
+}
+function createElement(name, props) {
+ var el = document.createElement(name);
+
+ for (var key in props) {
+ if (key === "style") {
+ for (var styleName in props.style) {
+ el.style[styleName] = props.style[styleName];
+ }
+ } else {
+ el[key] = props[key];
+ }
+ }
+
+ return el;
+}
+
+function parseDisplayList(lines) {
+ var root = {
+ line: "DisplayListRoot 0",
+ name: "DisplayListRoot",
+ address: "0x0",
+ frame: "Root",
+ children: [],
+ };
+
+ var objectAtIndentation = {
+ "-1": root,
+ };
+
+ for (var i = 0; i < lines.length; i++) {
+ var line = lines[i];
+
+ var layerObject = {
+ line: line,
+ children: [],
+ }
+ if (!root) {
+ root = layerObject;
+ }
+
+ var matches = line.match("(\\s*)(\\w+)\\sp=(\\w+)\\sf=(.*?)\\((.*?)\\)\\s(z=(\\w+)\\s)?(.*?)?( layer=(\\w+))?$");
+ if (!matches) {
+ dump("Failed to match: " + line + "\n");
+ continue;
+ }
+
+ var indentation = Math.floor(matches[1].length / 2);
+ objectAtIndentation[indentation] = layerObject;
+ var parent = objectAtIndentation[indentation - 1];
+ if (parent) {
+ parent.children.push(layerObject);
+ }
+
+ layerObject.name = matches[2];
+ layerObject.address = matches[3]; // Use 0x prefix to be consistent with layer dump
+ layerObject.frame = matches[4];
+ layerObject.contentDescriptor = matches[5];
+ layerObject.z = matches[7];
+ var rest = matches[8];
+ if (matches[10]) { // WrapList don't provide a layer
+ layerObject.layer = matches[10];
+ }
+ layerObject.rest = rest;
+
+ // the content node name doesn't have a prefix, this makes the parsing easier
+ rest = "content" + rest;
+
+ var fields = {};
+ var nesting = 0;
+ var startIndex;
+ var lastSpace = -1;
+ var lastFieldStart = -1;
+ for (var j = 0; j < rest.length; j++) {
+ if (rest.charAt(j) == '(') {
+ nesting++;
+ if (nesting == 1) {
+ startIndex = j;
+ }
+ } else if (rest.charAt(j) == ')') {
+ nesting--;
+ if (nesting == 0) {
+ var name = rest.substring(lastSpace + 1, startIndex);
+ var value = rest.substring(startIndex + 1, j);
+
+ var rectMatches = value.match("^(.*?),(.*?),(.*?),(.*?)$")
+ if (rectMatches) {
+ layerObject[name] = [
+ parseFloat(rectMatches[1]),
+ parseFloat(rectMatches[2]),
+ parseFloat(rectMatches[3]),
+ parseFloat(rectMatches[4]),
+ ];
+ } else {
+ layerObject[name] = value;
+ }
+ }
+ } else if (nesting == 0 && rest.charAt(j) == ' ') {
+ lastSpace = j;
+ }
+ }
+ //dump("FIELDS: " + JSON.stringify(fields) + "\n");
+ }
+ return root;
+}
+
+function trim(s){
+ return ( s || '' ).replace( /^\s+|\s+$/g, '' );
+}
+
+function getDataURI(str) {
+ if (str.indexOf("data:image/png;base64,") == 0) {
+ return str;
+ }
+
+ var matches = str.match("data:image/lz4bgra;base64,([0-9]+),([0-9]+),([0-9]+),(.*)");
+ if (!matches)
+ return null;
+
+ var canvas = document.createElement("canvas");
+ var w = parseInt(matches[1]);
+ var stride = parseInt(matches[2]);
+ var h = parseInt(matches[3]);
+ canvas.width = w;
+ canvas.height = h;
+
+ // TODO handle stride
+
+ var binary_string = window.atob(matches[4]);
+ var len = binary_string.length;
+ var bytes = new Uint8Array(len);
+ var decoded = new Uint8Array(stride * h);
+ for (var i = 0; i < len; i++) {
+ var ascii = binary_string.charCodeAt(i);
+ bytes[i] = ascii;
+ }
+
+ var ctxt = canvas.getContext("2d");
+ var out = ctxt.createImageData(w, h);
+ buffer = LZ4_uncompressChunk(bytes, decoded);
+
+ for (var x = 0; x < w; x++) {
+ for (var y = 0; y < h; y++) {
+ out.data[4 * x + 4 * y * w + 0] = decoded[4 * x + y * stride + 2];
+ out.data[4 * x + 4 * y * w + 1] = decoded[4 * x + y * stride + 1];
+ out.data[4 * x + 4 * y * w + 2] = decoded[4 * x + y * stride + 0];
+ out.data[4 * x + 4 * y * w + 3] = decoded[4 * x + y * stride + 3];
+ }
+ }
+
+ ctxt.putImageData(out, 0, 0);
+ return canvas.toDataURL();
+}
+
+function parseLayers(layersDumpLines) {
+ function parseMatrix2x3(str) {
+ str = trim(str);
+
+ // Something like '[ 1 0; 0 1; 0 158; ]'
+ var matches = str.match("^\\[ (.*?) (.*?); (.*?) (.*?); (.*?) (.*?); \\]$");
+ if (!matches) {
+ return null;
+ }
+
+ var matrix = [
+ [parseFloat(matches[1]), parseFloat(matches[2])],
+ [parseFloat(matches[3]), parseFloat(matches[4])],
+ [parseFloat(matches[5]), parseFloat(matches[6])],
+ ];
+
+ return matrix;
+ }
+ function parseColor(str) {
+ str = trim(str);
+
+ // Something like 'rgba(0, 0, 0, 0)'
+ var colorMatches = str.match("^rgba\\((.*), (.*), (.*), (.*)\\)$");
+ if (!colorMatches) {
+ return null;
+ }
+
+ var color = {
+ r: colorMatches[1],
+ g: colorMatches[2],
+ b: colorMatches[3],
+ a: colorMatches[4],
+ };
+ return color;
+ }
+ function parseFloat_cleo(str) {
+ str = trim(str);
+
+ // Something like 2.000
+ if (parseFloat(str) == str) {
+ return parseFloat(str);
+ }
+
+ return null;
+ }
+ function parseRect2D(str) {
+ str = trim(str);
+
+ // Something like '(x=0, y=0, w=2842, h=158)'
+ var rectMatches = str.match("^\\(x=(.*?), y=(.*?), w=(.*?), h=(.*?)\\)$");
+ if (!rectMatches) {
+ return null;
+ }
+
+ var rect = [
+ parseFloat(rectMatches[1]), parseFloat(rectMatches[2]),
+ parseFloat(rectMatches[3]), parseFloat(rectMatches[4]),
+ ];
+ return rect;
+ }
+ function parseRegion(str) {
+ str = trim(str);
+
+ // Something like '< (x=0, y=0, w=2842, h=158); (x=0, y=1718, w=2842, h=500); >'
+ if (str.charAt(0) != '<' || str.charAt(str.length - 1) != '>') {
+ return null;
+ }
+
+ var region = [];
+ str = trim(str.substring(1, str.length - 1));
+ while (str != "") {
+ var rectMatches = str.match("^\\(x=(.*?), y=(.*?), w=(.*?), h=(.*?)\\);(.*)$");
+ if (!rectMatches) {
+ return null;
+ }
+
+ var rect = [
+ parseFloat(rectMatches[1]), parseFloat(rectMatches[2]),
+ parseFloat(rectMatches[3]), parseFloat(rectMatches[4]),
+ ];
+ str = trim(rectMatches[5]);
+ region.push(rect);
+ }
+ return region;
+ }
+
+ var LAYERS_LINE_REGEX = "(\\s*)(\\w+)\\s\\((\\w+)\\)(.*)";
+
+ var root;
+ var objectAtIndentation = [];
+ for (var i = 0; i < layersDumpLines.length; i++) {
+ // Something like 'ThebesLayerComposite (0x12104cc00) [shadow-visible=< (x=0, y=0, w=1920, h=158); >] [visible=< (x=0, y=0, w=1920, h=158); >] [opaqueContent] [valid=< (x=0, y=0, w=1920, h=2218); >]'
+ var line = layersDumpLines[i].name || layersDumpLines[i];
+
+ var tileMatches = line.match("(\\s*)Tile \\(x=(.*), y=(.*)\\): (.*)");
+ if (tileMatches) {
+ var indentation = Math.floor(matches[1].length / 2);
+ var x = tileMatches[2];
+ var y = tileMatches[3];
+ var dataUri = tileMatches[4];
+ var parent = objectAtIndentation[indentation - 1];
+ var tiles = parent.tiles || {};
+
+ tiles[x] = tiles[x] || {};
+ tiles[x][y] = dataUri;
+
+ parent.tiles = tiles;
+
+ continue;
+ }
+
+ var surfaceMatches = line.match("(\\s*)Surface: (.*)");
+ if (surfaceMatches) {
+ var indentation = Math.floor(matches[1].length / 2);
+ var parent = objectAtIndentation[indentation - 1] || objectAtIndentation[indentation - 2];
+
+ var surfaceURI = surfaceMatches[2];
+ if (parent.surfaceURI != null) {
+ console.log("error: surfaceURI already set for this layer " + parent.line);
+ }
+ parent.surfaceURI = surfaceURI;
+
+ // Look for the buffer-rect offset
+ var contentHostLine = layersDumpLines[i - 2].name || layersDumpLines[i - 2];
+ var matches = contentHostLine.match(LAYERS_LINE_REGEX);
+ if (matches) {
+ var contentHostRest = matches[4];
+ parent.contentHostProp = {};
+ parseProperties(contentHostRest, parent.contentHostProp);
+ }
+
+ continue;
+ }
+
+ var layerObject = {
+ line: line,
+ children: [],
+ }
+ if (!root) {
+ root = layerObject;
+ }
+
+ var matches = line.match(LAYERS_LINE_REGEX);
+ if (!matches) {
+ continue; // Something like a texturehost dump. Safe to ignore
+ }
+
+ if (matches[2].indexOf("TiledContentHost") != -1 ||
+ matches[2].indexOf("GrallocTextureHostOGL") != -1 ||
+ matches[2].indexOf("ContentHost") != -1 ||
+ matches[2].indexOf("ContentClient") != -1 ||
+ matches[2].indexOf("MemoryTextureHost") != -1 ||
+ matches[2].indexOf("ImageHost") != -1) {
+ continue; // We're already pretty good at visualizing these
+ }
+
+ var indentation = Math.floor(matches[1].length / 2);
+ objectAtIndentation[indentation] = layerObject;
+ for (var c = indentation + 1; c < objectAtIndentation.length; c++) {
+ objectAtIndentation[c] = null;
+ }
+ if (indentation > 0) {
+ var parent = objectAtIndentation[indentation - 1];
+ while (!parent) {
+ indentation--;
+ parent = objectAtIndentation[indentation - 1];
+ }
+
+ parent.children.push(layerObject);
+ }
+
+ layerObject.name = matches[2];
+ layerObject.address = matches[3];
+
+ var rest = matches[4];
+
+ function parseProperties(rest, layerObject) {
+ var fields = [];
+ var nesting = 0;
+ var startIndex;
+ for (var j = 0; j < rest.length; j++) {
+ if (rest.charAt(j) == '[') {
+ nesting++;
+ if (nesting == 1) {
+ startIndex = j;
+ }
+ } else if (rest.charAt(j) == ']') {
+ nesting--;
+ if (nesting == 0) {
+ fields.push(rest.substring(startIndex + 1, j));
+ }
+ }
+ }
+
+ for (var j = 0; j < fields.length; j++) {
+ // Something like 'valid=< (x=0, y=0, w=1920, h=2218); >' or 'opaqueContent'
+ var field = fields[j];
+ //dump("FIELD: " + field + "\n");
+ var parts = field.split("=", 2);
+ var fieldName = parts[0];
+ var rest = field.substring(fieldName.length + 1);
+ if (parts.length == 1) {
+ layerObject[fieldName] = "true";
+ layerObject[fieldName].type = "bool";
+ continue;
+ }
+ var float = parseFloat_cleo(rest);
+ if (float) {
+ layerObject[fieldName] = float;
+ layerObject[fieldName].type = "float";
+ continue;
+ }
+ var region = parseRegion(rest);
+ if (region) {
+ layerObject[fieldName] = region;
+ layerObject[fieldName].type = "region";
+ continue;
+ }
+ var rect = parseRect2D(rest);
+ if (rect) {
+ layerObject[fieldName] = rect;
+ layerObject[fieldName].type = "rect2d";
+ continue;
+ }
+ var matrix = parseMatrix2x3(rest);
+ if (matrix) {
+ layerObject[fieldName] = matrix;
+ layerObject[fieldName].type = "matrix2x3";
+ continue;
+ }
+ var color = parseColor(rest);
+ if (color) {
+ layerObject[fieldName] = color;
+ layerObject[fieldName].type = "color";
+ continue;
+ }
+ if (rest[0] == '{' && rest[rest.length - 1] == '}') {
+ var object = {};
+ parseProperties(rest.substring(1, rest.length - 2).trim(), object);
+ layerObject[fieldName] = object;
+ layerObject[fieldName].type = "object";
+ continue;
+ }
+ fieldName = fieldName.split(" ")[0];
+ layerObject[fieldName] = rest[0];
+ layerObject[fieldName].type = "string";
+ }
+ }
+ parseProperties(rest, layerObject);
+
+ if (!layerObject['shadow-transform']) {
+ // No shadow transform = identify
+ layerObject['shadow-transform'] = [[1, 0], [0, 1], [0, 0]];
+ }
+
+ // Compute screenTransformX/screenTransformY
+ // TODO Fully support transforms
+ if (layerObject['shadow-transform'] && layerObject['transform']) {
+ layerObject['screen-transform'] = [layerObject['shadow-transform'][2][0], layerObject['shadow-transform'][2][1]];
+ var currIndentation = indentation - 1;
+ while (currIndentation >= 0) {
+ var transform = objectAtIndentation[currIndentation]['shadow-transform'] || objectAtIndentation[currIndentation]['transform'];
+ if (transform) {
+ layerObject['screen-transform'][0] += transform[2][0];
+ layerObject['screen-transform'][1] += transform[2][1];
+ }
+ currIndentation--;
+ }
+ }
+
+ //dump("Fields: " + JSON.stringify(fields) + "\n");
+ }
+ root.compositeTime = layersDumpLines.compositeTime;
+ //dump("OBJECTS: " + JSON.stringify(root) + "\n");
+ return root;
+}
+function populateLayers(root, displayList, pane, previewParent, hasSeenRoot, contentScale, rootPreviewParent) {
+
+ contentScale = contentScale || 1;
+ rootPreviewParent = rootPreviewParent || previewParent;
+
+ function getDisplayItemForLayer(displayList) {
+ var items = [];
+ if (!displayList) {
+ return items;
+ }
+ if (displayList.layer == root.address) {
+ items.push(displayList);
+ }
+ for (var i = 0; i < displayList.children.length; i++) {
+ var subDisplayItems = getDisplayItemForLayer(displayList.children[i]);
+ for (var j = 0; j < subDisplayItems.length; j++) {
+ items.push(subDisplayItems[j]);
+ }
+ }
+ return items;
+ }
+ var elem = createElement("div", {
+ className: "layerObjectDescription",
+ textContent: root.line,
+ style: {
+ whiteSpace: "pre",
+ },
+ onmouseover: function() {
+ if (this.layerViewport) {
+ this.layerViewport.classList.add("layerHover");
+ }
+ },
+ onmouseout: function() {
+ if (this.layerViewport) {
+ this.layerViewport.classList.remove("layerHover");
+ }
+ },
+ });
+ var icon = createElement("img", {
+ src: "show.png",
+ style: {
+ width: "12px",
+ height: "12px",
+ marginLeft: "4px",
+ marginRight: "4px",
+ cursor: "pointer",
+ },
+ onclick: function() {
+ if (this.layerViewport) {
+ if (this.layerViewport.style.visibility == "hidden") {
+ this.layerViewport.style.visibility = "";
+ this.src = "show.png"
+ } else {
+ this.layerViewport.style.visibility = "hidden";
+ this.src = "hide.png"
+ }
+ }
+ }
+ });
+ elem.insertBefore(icon, elem.firstChild);
+ pane.appendChild(elem);
+
+ if (root["shadow-visible"] || root["visible"]) {
+ var visibleRegion = root["shadow-visible"] || root["visible"];
+ var layerViewport = createElement("div", {
+ id: root.address + "_viewport",
+ style: {
+ position: "absolute",
+ pointerEvents: "none",
+ },
+ });
+ elem.layerViewport = layerViewport;
+ icon.layerViewport = layerViewport;
+ var layerViewportMatrix = [1, 0, 0, 1, 0, 0];
+ if (root["shadow-clip"] || root["clip"]) {
+ var clip = root["shadow-clip"] || root["clip"]
+ var clipElem = createElement("div", {
+ id: root.address + "_clip",
+ style: {
+ left: clip[0]+"px",
+ top: clip[1]+"px",
+ width: clip[2]+"px",
+ height: clip[3]+"px",
+ position: "absolute",
+ overflow: "hidden",
+ pointerEvents: "none",
+ },
+ });
+ layerViewportMatrix[4] += -clip[0];
+ layerViewportMatrix[5] += -clip[1];
+ layerViewport.style.transform = "translate(-" + clip[0] + "px, -" + clip[1] + "px" + ")";
+ }
+ if (root["shadow-transform"] || root["transform"]) {
+ var matrix = root["shadow-transform"] || root["transform"];
+ layerViewportMatrix[0] = matrix[0][0];
+ layerViewportMatrix[1] = matrix[0][1];
+ layerViewportMatrix[2] = matrix[1][0];
+ layerViewportMatrix[3] = matrix[1][1];
+ layerViewportMatrix[4] += matrix[2][0];
+ layerViewportMatrix[5] += matrix[2][1];
+ }
+ layerViewport.style.transform = "matrix(" + layerViewportMatrix[0] + "," + layerViewportMatrix[1] + "," + layerViewportMatrix[2] + "," + layerViewportMatrix[3] + "," + layerViewportMatrix[4] + "," + layerViewportMatrix[5] + ")";
+ if (!hasSeenRoot) {
+ hasSeenRoot = true;
+ layerViewport.style.transform = "scale(" + 1/contentScale + "," + 1/contentScale + ")";
+ }
+ if (clipElem) {
+ previewParent.appendChild(clipElem);
+ clipElem.appendChild(layerViewport);
+ } else {
+ previewParent.appendChild(layerViewport);
+ }
+ previewParent = layerViewport;
+ for (var i = 0; i < visibleRegion.length; i++) {
+ var rect2d = visibleRegion[i];
+ var layerPreview = createElement("div", {
+ id: root.address + "_visible_part" + i + "-" + visibleRegion.length,
+ className: "layerPreview",
+ style: {
+ position: "absolute",
+ left: rect2d[0] + "px",
+ top: rect2d[1] + "px",
+ width: rect2d[2] + "px",
+ height: rect2d[3] + "px",
+ overflow: "hidden",
+ border: "solid 1px black",
+ background: 'url("noise.png"), linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.2))',
+ },
+ });
+ layerViewport.appendChild(layerPreview);
+
+ function isInside(rect1, rect2) {
+ if (rect1[0] + rect1[2] < rect2[0] && rect2[0] + rect2[2] < rect1[0] &&
+ rect1[1] + rect1[3] < rect2[1] && rect2[1] + rect2[3] < rect1[1]) {
+ return true;
+ }
+ return true;
+ }
+
+ var hasImg = false;
+ // Add tile img objects for this part
+ var previewOffset = rect2d;
+
+ if (root.tiles) {
+ hasImg = true;
+ for (var x in root.tiles) {
+ for (var y in root.tiles[x]) {
+ if (isInside(rect2d, [x, y, 512, 512])) {
+ var tileImgElem = createElement("img", {
+ src: getDataURI(root.tiles[x][y]),
+ style: {
+ position: "absolute",
+ left: (x - previewOffset[0]) + "px",
+ top: (y - previewOffset[1]) + "px",
+ pointerEvents: "auto",
+ },
+ });
+ layerPreview.appendChild(tileImgElem);
+ }
+ }
+ }
+ layerPreview.style.background = "";
+ } else if (root.surfaceURI) {
+ hasImg = true;
+ var offsetX = 0;
+ var offsetY = 0;
+ if (root.contentHostProp && root.contentHostProp['buffer-rect']) {
+ offsetX = root.contentHostProp['buffer-rect'][0];
+ offsetY = root.contentHostProp['buffer-rect'][1];
+ }
+ var surfaceImgElem = createElement("img", {
+ src: getDataURI(root.surfaceURI),
+ style: {
+ position: "absolute",
+ left: (offsetX - previewOffset[0]) + "px",
+ top: (offsetY - previewOffset[1]) + "px",
+ pointerEvents: "auto",
+ },
+ });
+ layerPreview.appendChild(surfaceImgElem);
+ layerPreview.style.background = "";
+ } else if (root.color) {
+ hasImg = true;
+ layerPreview.style.background = "rgba(" + root.color.r + ", " + root.color.g + ", " + root.color.b + ", " + root.color.a + ")";
+ }
+
+ if (hasImg || true) {
+ layerPreview.mouseoverElem = elem;
+ layerPreview.onmouseenter = function() {
+ this.mouseoverElem.onmouseover();
+ }
+ layerPreview.onmouseout = function() {
+ this.mouseoverElem.onmouseout();
+ }
+ }
+ }
+
+ var layerDisplayItems = getDisplayItemForLayer(displayList);
+ for (var i = 0; i < layerDisplayItems.length; i++) {
+ var displayItem = layerDisplayItems[i];
+ var displayElem = createElement("div", {
+ className: "layerObjectDescription",
+ textContent: " " + trim(displayItem.line),
+ style: {
+ whiteSpace: "pre",
+ },
+ displayItem: displayItem,
+ layerViewport: layerViewport,
+ onmouseover: function() {
+ if (this.diPreview) {
+ this.diPreview.classList.add("displayHover");
+
+ var description = "";
+ if (this.displayItem.contentDescriptor) {
+ description += "Content: " + this.displayItem.contentDescriptor;
+ } else {
+ description += "Content: Unknown";
+ }
+ description += " Item: " + this.displayItem.name + " (" + this.displayItem.address + ")";
+ description += " Layer: " + root.name + " (" + root.address + ")";
+ if (this.displayItem.frame) {
+ description += " Frame: " + this.displayItem.frame;
+ }
+ if (this.displayItem.layerBounds) {
+ description += " Bounds: [" + toFixed(this.displayItem.layerBounds[0] / 60, 2) + ", " + toFixed(this.displayItem.layerBounds[1] / 60, 2) + ", " + toFixed(this.displayItem.layerBounds[2] / 60, 2) + ", " + toFixed(this.displayItem.layerBounds[3] / 60, 2) + "] (CSS Pixels)";
+ }
+ if (this.displayItem.z) {
+ description += " Z: " + this.displayItem.z;
+ }
+ // At the end
+ if (this.displayItem.rest) {
+ description += " " + this.displayItem.rest;
+ }
+
+ var box = this.diPreview.getBoundingClientRect();
+ var pageBox = document.body.getBoundingClientRect();
+ this.diPreview.tooltip = createElement("div", {
+ className: "csstooltip",
+ innerHTML: description,
+ style: {
+ top: Math.min(box.bottom, document.documentElement.clientHeight - 150) + "px",
+ left: box.left + "px",
+ }
+ });
+
+ document.body.appendChild(this.diPreview.tooltip);
+ }
+ },
+ onmouseout: function() {
+ if (this.diPreview) {
+ this.diPreview.classList.remove("displayHover");
+ document.body.removeChild(this.diPreview.tooltip);
+ }
+ },
+ });
+
+ var icon = createElement("img", {
+ style: {
+ width: "12px",
+ height: "12px",
+ marginLeft: "4px",
+ marginRight: "4px",
+ }
+ });
+ displayElem.insertBefore(icon, displayElem.firstChild);
+ pane.appendChild(displayElem);
+ // bounds doesn't adjust for within the layer. It's not a bad fallback but
+ // will have the wrong offset
+ var rect2d = displayItem.layerBounds || displayItem.bounds;
+ if (rect2d) { // This doesn't place them corectly
+ var appUnitsToPixels = 60 / contentScale;
+ diPreview = createElement("div", {
+ id: "displayitem_" + displayItem.content + "_" + displayItem.address,
+ className: "layerPreview",
+ style: {
+ position: "absolute",
+ left: rect2d[0]/appUnitsToPixels + "px",
+ top: rect2d[1]/appUnitsToPixels + "px",
+ width: rect2d[2]/appUnitsToPixels + "px",
+ height: rect2d[3]/appUnitsToPixels + "px",
+ border: "solid 1px gray",
+ pointerEvents: "auto",
+ },
+ displayElem: displayElem,
+ onmouseover: function() {
+ this.displayElem.onmouseover();
+ },
+ onmouseout: function() {
+ this.displayElem.onmouseout();
+ },
+ });
+
+ layerViewport.appendChild(diPreview);
+ displayElem.diPreview = diPreview;
+ }
+ }
+ }
+
+ for (var i = 0; i < root.children.length; i++) {
+ populateLayers(root.children[i], displayList, pane, previewParent, hasSeenRoot, contentScale, rootPreviewParent);
+ }
+}
+
+// This function takes a stdout snippet and finds the frames
+function parseMultiLineDump(log) {
+ var lines = log.split("\n");
+
+ var container = createElement("div", {
+ style: {
+ height: "100%",
+ position: "relative",
+ },
+ });
+
+ var layerManagerFirstLine = "[a-zA-Z]*LayerManager \\(.*$\n";
+ var nextLineStartWithSpace = "([ \\t].*$\n)*";
+ var layersRegex = "(" + layerManagerFirstLine + nextLineStartWithSpace + ")";
+
+ var startLine = "Painting --- after optimization:\n";
+ var endLine = "Painting --- layer tree:"
+ var displayListRegex = "(" + startLine + "(.*\n)*?" + endLine + ")";
+
+ var regex = new RegExp(layersRegex + "|" + displayListRegex, "gm");
+ var matches = log.match(regex);
+ console.log(matches);
+ window.matches = matches;
+
+ var matchList = createElement("span", {
+ style: {
+ height: "95%",
+ width: "10%",
+ position: "relative",
+ border: "solid black 2px",
+ display: "inline-block",
+ float: "left",
+ overflow: "auto",
+ },
+ });
+ container.appendChild(matchList);
+ var contents = createElement("span", {
+ style: {
+ height: "95%",
+ width: "88%",
+ display: "inline-block",
+ },
+ textContent: "Click on a frame on the left to view the layer tree",
+ });
+ container.appendChild(contents);
+
+ var lastDisplayList = null;
+ var frameID = 1;
+ for (let i = 0; i < matches.length; i++) {
+ var currMatch = matches[i];
+
+ if (currMatch.indexOf(startLine) == 0) {
+ // Display list match
+ var matchLines = matches[i].split("\n")
+ lastDisplayList = parseDisplayList(matchLines);
+ } else {
+ // Layer tree match:
+ let displayList = lastDisplayList;
+ lastDisplayList = null;
+ var currFrameDiv = createElement("a", {
+ style: {
+ padding: "3px",
+ display: "block",
+ },
+ href: "#",
+ textContent: "LayerTree " + (frameID++),
+ onclick: function() {
+ contents.innerHTML = "";
+ var matchLines = matches[i].split("\n")
+ var dumpDiv = parseDump(matchLines, displayList);
+ contents.appendChild(dumpDiv);
+ }
+ });
+ matchList.appendChild(currFrameDiv);
+ }
+ }
+
+ return container;
+}
+
+function parseDump(log, displayList, compositeTitle, compositeTime) {
+ compositeTitle |= "";
+ compositeTime |= 0
+
+ var container = createElement("div", {
+ style: {
+ background: "white",
+ height: "100%",
+ position: "relative",
+ },
+ });
+
+ if (compositeTitle == null && compositeTime == null) {
+ var titleDiv = createElement("div", {
+ className: "treeColumnHeader",
+ style: {
+ width: "100%",
+ },
+ textContent: compositeTitle + (compositeTitle ? " (near " + compositeTime.toFixed(0) + " ms)" : ""),
+ });
+ container.appendChild(titleDiv);
+ }
+
+ var mainDiv = createElement("div", {
+ style: {
+ position: "absolute",
+ top: "16px",
+ left: "0px",
+ right: "0px",
+ bottom: "0px",
+ },
+ });
+ container.appendChild(mainDiv);
+
+ var layerListPane = createElement("div", {
+ style: {
+ cssFloat: "left",
+ height: "100%",
+ width: "300px",
+ overflowY: "scroll",
+ },
+ });
+ mainDiv.appendChild(layerListPane);
+
+ var previewDiv = createElement("div", {
+ style: {
+ position: "absolute",
+ left: "300px",
+ right: "0px",
+ top: "0px",
+ bottom: "0px",
+ overflow: "auto",
+ },
+ });
+ mainDiv.appendChild(previewDiv);
+
+ var root = parseLayers(log);
+ populateLayers(root, displayList, layerListPane, previewDiv);
+ return container;
+}
+
+function tab_showLayersDump(layersDumpLines, compositeTitle, compositeTime) {
+ var container = parseDump(layersDumpLines, compositeTitle, compositeTime);
+
+ gTabWidget.addTab("LayerTree", container);
+ gTabWidget.selectTab("LayerTree");
+}
+
diff --git a/gfx/layers/layerviewer/noise.png b/gfx/layers/layerviewer/noise.png
new file mode 100755
index 00000000000..01d340aaa90
Binary files /dev/null and b/gfx/layers/layerviewer/noise.png differ
diff --git a/gfx/layers/layerviewer/show.png b/gfx/layers/layerviewer/show.png
new file mode 100644
index 00000000000..7038b660c8f
Binary files /dev/null and b/gfx/layers/layerviewer/show.png differ
diff --git a/gfx/layers/layerviewer/tree.css b/gfx/layers/layerviewer/tree.css
new file mode 100644
index 00000000000..6b26d729b5b
--- /dev/null
+++ b/gfx/layers/layerviewer/tree.css
@@ -0,0 +1,36 @@
+html, body {
+ height: 100%;
+ overflow: hidden;
+}
+.layerObjectDescription:hover {
+ background-color: #E8E8E8;
+}
+
+.layerHover > .layerPreview::after {
+ position: absolute;
+ top: 0; right: 0; bottom: 0; left: 0;
+ background-color: inherit;
+ content: "";
+ background-color: rgba(0,0,0,0.2);
+ box-shadow: -2px 2px 0 #FFF;
+}
+
+@keyframes layerHoverAnimation {
+ 0% { transform: scale(1); }
+ 50% { transform: scale(1.2); }
+ 100% { transform: scale(1); }
+}
+
+.displayHover {
+ background: rgba(0, 128, 0, 0.8);
+}
+
+.layerHover > .layerPreview {
+ animation: layerHoverAnimation 200ms;
+ animation-transform-origin: 50% 50%;
+ background: gold !important;
+ box-shadow: 10px 10px 5px #888888;
+ border-color: blue !important;
+ z-index: 10;
+}
+
diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build
index 5853c319b0a..a2a404df4b2 100644
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -228,11 +228,12 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
'opengl/GrallocTextureHost.cpp',
]
LOCAL_INCLUDES += ['/widget/gonk']
- CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'system/core/libsync/include'
- ]
- ]
+ if CONFIG['ANDROID_VERSION'] >= '21':
+ LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+ 'system/core/libsync/include'
+ ]
+ ]
SOURCES += [
'ipc/ShadowLayerUtilsGralloc.cpp',
]
@@ -403,14 +404,21 @@ if CONFIG['MOZ_DEBUG']:
if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
DEFINES['MOZ_ENABLE_D3D10_LAYER'] = True
-CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/base/include/media/stagefright',
- 'frameworks/base/include/media/stagefright/openmax',
- 'frameworks/av/include/media/stagefright',
- 'frameworks/native/include/media/openmax',
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+ if CONFIG['ANDROID_VERSION'] > '17':
+ includes = [
+ 'frameworks/av/include/media/stagefright',
+ 'frameworks/native/include/media/openmax',
+ ]
+ else:
+ includes = [
+ 'frameworks/base/include/media/stagefright',
+ 'frameworks/base/include/media/stagefright/openmax',
+ ]
+
+ LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in includes
]
-]
if CONFIG['ENABLE_TESTS']:
DIRS += ['apz/test/gtest']
diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h
index 92bc5b51756..efdc19a7ce3 100644
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -29,10 +29,9 @@
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsDebug.h" // for NS_WARNING
#include "nsISupportsImpl.h" // for TextureImage::Release, etc
+#include "nsRegionFwd.h" // for nsIntRegion
#include "OGLShaderProgram.h" // for ShaderProgramType, etc
-class nsIntRegion;
-
namespace mozilla {
namespace gfx {
class DataSourceSurface;
diff --git a/gfx/src/RegionTyped.h b/gfx/src/RegionTyped.h
deleted file mode 100644
index dab5481461a..00000000000
--- a/gfx/src/RegionTyped.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* 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_RegionTyped_h
-#define mozilla_RegionTyped_h
-
-#include "nsRegion.h"
-#include "mozilla/gfx/Rect.h"
-
-namespace mozilla {
-
-namespace gfx {
-
-template
-class IntRegionTyped :
- public BaseIntRegion, IntRectTyped, IntPointTyped, IntMarginTyped>
-{
- typedef BaseIntRegion, IntRectTyped, IntPointTyped, IntMarginTyped> Super;
-public:
- // Forward constructors.
- IntRegionTyped() {}
- MOZ_IMPLICIT IntRegionTyped(const IntRectTyped& aRect) : Super(aRect) {}
- IntRegionTyped(const IntRegionTyped& aRegion) : Super(aRegion) {}
- IntRegionTyped(IntRegionTyped&& aRegion) : Super(mozilla::Move(aRegion)) {}
-
- // Assignment operators need to be forwarded as well, otherwise the compiler
- // will declare deleted ones.
- IntRegionTyped& operator=(const IntRegionTyped& aRegion)
- {
- return Super::operator=(aRegion);
- }
- IntRegionTyped& operator=(IntRegionTyped&& aRegion)
- {
- return Super::operator=(mozilla::Move(aRegion));
- }
-
- static IntRegionTyped FromUntyped(const nsIntRegion& aRegion)
- {
- return IntRegionTyped(aRegion.Impl());
- }
-private:
- // This is deliberately private, so calling code uses FromUntyped().
- explicit IntRegionTyped(const nsRegion& aRegion) : Super(aRegion) {}
-};
-
-} // namespace gfx
-
-} // namespace mozilla
-
-
-
-#endif /* mozilla_RegionTyped_h */
diff --git a/gfx/src/moz.build b/gfx/src/moz.build
index 156aa1f7ce9..19879c4b3eb 100644
--- a/gfx/src/moz.build
+++ b/gfx/src/moz.build
@@ -32,6 +32,7 @@ EXPORTS += [
'nsPoint.h',
'nsRect.h',
'nsRegion.h',
+ 'nsRegionFwd.h',
'nsRenderingContext.h',
'nsSize.h',
'nsThemeConstants.h',
@@ -42,10 +43,6 @@ EXPORTS.mozilla += [
'AppUnits.h',
]
-EXPORTS.mozilla.gfx += [
- 'RegionTyped.h',
-]
-
if CONFIG['MOZ_X11']:
EXPORTS.mozilla += ['X11Util.h']
SOURCES += [
diff --git a/gfx/src/nsIScriptableRegion.idl b/gfx/src/nsIScriptableRegion.idl
index 84ee20bf071..1e32fdd1bae 100644
--- a/gfx/src/nsIScriptableRegion.idl
+++ b/gfx/src/nsIScriptableRegion.idl
@@ -7,7 +7,7 @@
#include "nsISupports.idl"
%{C++
-class nsIntRegion;
+#include "nsRegionFwd.h"
%}
native nsIntRegion(nsIntRegion);
diff --git a/gfx/src/nsRegion.h b/gfx/src/nsRegion.h
index 315db6d78e3..0244c842c7a 100644
--- a/gfx/src/nsRegion.h
+++ b/gfx/src/nsRegion.h
@@ -15,11 +15,11 @@
#include "nsPoint.h" // for nsIntPoint, nsPoint
#include "nsRect.h" // for mozilla::gfx::IntRect, nsRect
#include "nsMargin.h" // for nsIntMargin
+#include "nsRegionFwd.h" // for nsIntRegion
#include "nsStringGlue.h" // for nsCString
#include "xpcom-config.h" // for CPP_THROW_NEW
#include "mozilla/Move.h" // for mozilla::Move
-class nsIntRegion;
namespace mozilla {
namespace gfx {
class Matrix4x4;
@@ -821,30 +821,42 @@ private:
}
};
-} // namespace gfx
-} // namespace mozilla
-
-class nsIntRegion : public mozilla::gfx::BaseIntRegion
+template
+class IntRegionTyped :
+ public BaseIntRegion, IntRectTyped, IntPointTyped, IntMarginTyped>
{
+ typedef BaseIntRegion, IntRectTyped, IntPointTyped, IntMarginTyped> Super;
public:
// Forward constructors.
- nsIntRegion() {}
- MOZ_IMPLICIT nsIntRegion(const mozilla::gfx::IntRect& aRect) : BaseIntRegion(aRect) {}
- nsIntRegion(const nsIntRegion& aRegion) : BaseIntRegion(aRegion) {}
- nsIntRegion(nsIntRegion&& aRegion) : BaseIntRegion(mozilla::Move(aRegion)) {}
+ IntRegionTyped() {}
+ MOZ_IMPLICIT IntRegionTyped(const IntRectTyped& aRect) : Super(aRect) {}
+ IntRegionTyped(const IntRegionTyped& aRegion) : Super(aRegion) {}
+ IntRegionTyped(IntRegionTyped&& aRegion) : Super(mozilla::Move(aRegion)) {}
// Assignment operators need to be forwarded as well, otherwise the compiler
// will declare deleted ones.
- nsIntRegion& operator=(const nsIntRegion& aRegion)
+ IntRegionTyped& operator=(const IntRegionTyped& aRegion)
{
- return BaseIntRegion::operator=(aRegion);
+ return Super::operator=(aRegion);
}
- nsIntRegion& operator=(nsIntRegion&& aRegion)
+ IntRegionTyped& operator=(IntRegionTyped&& aRegion)
{
- return BaseIntRegion::operator=(mozilla::Move(aRegion));
+ return Super::operator=(mozilla::Move(aRegion));
}
+
+ static IntRegionTyped FromUntyped(const IntRegionTyped& aRegion)
+ {
+ return IntRegionTyped(aRegion.Impl());
+ }
+private:
+ // This is deliberately private, so calling code uses FromUntyped().
+ explicit IntRegionTyped(const nsRegion& aRegion) : Super(aRegion) {}
};
+} // namespace gfx
+} // namespace mozilla
+
+typedef mozilla::gfx::IntRegion nsIntRegion;
typedef nsIntRegion::RectIterator nsIntRegionRectIterator;
#endif
diff --git a/gfx/src/nsRegionFwd.h b/gfx/src/nsRegionFwd.h
new file mode 100644
index 00000000000..6d5345d1458
--- /dev/null
+++ b/gfx/src/nsRegionFwd.h
@@ -0,0 +1,26 @@
+/* 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 nsRegionFwd_h__
+#define nsRegionFwd_h__
+
+// Forward declare enough things to define the typedef |nsIntRegion|.
+
+namespace mozilla {
+namespace gfx {
+
+struct UnknownUnits;
+
+template
+class IntRegionTyped;
+
+typedef IntRegionTyped IntRegion;
+
+} // namespace gfx
+} // namespace mozilla
+
+typedef mozilla::gfx::IntRegion nsIntRegion;
+
+#endif
diff --git a/gfx/thebes/gfxTypes.h b/gfx/thebes/gfxTypes.h
index 1dad160e60d..64ad9e1ef6d 100644
--- a/gfx/thebes/gfxTypes.h
+++ b/gfx/thebes/gfxTypes.h
@@ -47,24 +47,28 @@ enum class gfxBreakPriority {
/**
* The format for an image surface. For all formats with alpha data, 0
* means transparent, 1 or 255 means fully opaque.
+ *
+ * XXX: it's vital that the values here match the values in cairo_format_t,
+ * otherwise gfxCairoFormatToImageFormat() and gfxImageFormatToCairoFormat()
+ * won't work.
*/
enum class gfxImageFormat {
- ARGB32, ///< ARGB data in native endianness, using premultiplied alpha
- RGB24, ///< xRGB data in native endianness
- A8, ///< Only an alpha channel
- RGB16_565, ///< RGB_565 data in native endianness
+ ARGB32 = 0, ///< ARGB data in native endianness, using premultiplied alpha
+ RGB24 = 1, ///< xRGB data in native endianness
+ A8 = 2, ///< Only an alpha channel
+ RGB16_565 = 4, ///< RGB_565 data in native endianness
Unknown
};
// XXX: temporary
// This works because the gfxImageFormat enum is defined so as to match the
-// _cairo_format enum.
+// cairo_format_t enum.
#define gfxCairoFormatToImageFormat(aFormat) \
((gfxImageFormat)aFormat)
// XXX: temporary
// This works because the gfxImageFormat enum is defined so as to match the
-// _cairo_format enum.
+// cairo_format_t enum.
#define gfxImageFormatToCairoFormat(aFormat) \
((cairo_format_t)aFormat)
diff --git a/gfx/thebes/gfxUtils.cpp b/gfx/thebes/gfxUtils.cpp
index fa992730278..01f4a0a4fbf 100644
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -21,6 +21,7 @@
#include "mozilla/gfx/Logging.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/Vector.h"
#include "nsComponentManagerUtils.h"
#include "nsIClipboardHelper.h"
@@ -1560,7 +1561,7 @@ gfxUtils::GetImageBuffer(gfx::DataSourceSurface* aSurface,
return nullptr;
uint32_t bufferSize = aSurface->GetSize().width * aSurface->GetSize().height * 4;
- UniquePtr imageBuffer(new (fallible) uint8_t[bufferSize]);
+ auto imageBuffer = MakeUniqueFallible(bufferSize);
if (!imageBuffer) {
aSurface->Unmap();
return nullptr;
diff --git a/gfx/thebes/gfxUtils.h b/gfx/thebes/gfxUtils.h
index 97ebd27494e..a90987445b1 100644
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -13,13 +13,13 @@
#include "mozilla/UniquePtr.h"
#include "nsColor.h"
#include "nsPrintfCString.h"
+#include "nsRegionFwd.h"
#include "mozilla/gfx/Rect.h"
class gfxASurface;
class gfxDrawable;
class nsIInputStream;
class nsIGfxInfo;
-class nsIntRegion;
class nsIPresShell;
namespace mozilla {
diff --git a/hal/moz.build b/hal/moz.build
index ba9abffd856..a046bdcd43f 100644
--- a/hal/moz.build
+++ b/hal/moz.build
@@ -174,7 +174,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- CXXFLAGS += ['-I%s/hardware/libhardware_legacy/include' % CONFIG['ANDROID_SOURCE']]
+ LOCAL_INCLUDES += ['%' + '%s/hardware/libhardware_legacy/include' % CONFIG['ANDROID_SOURCE']]
CFLAGS += CONFIG['GLIB_CFLAGS']
CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
diff --git a/image/encoders/bmp/nsBMPEncoder.cpp b/image/encoders/bmp/nsBMPEncoder.cpp
index 8f02ef564bc..4484faa3e41 100644
--- a/image/encoders/bmp/nsBMPEncoder.cpp
+++ b/image/encoders/bmp/nsBMPEncoder.cpp
@@ -5,6 +5,7 @@
#include "nsCRT.h"
#include "mozilla/Endian.h"
+#include "mozilla/UniquePtrExtensions.h"
#include "nsBMPEncoder.h"
#include "prprf.h"
#include "nsString.h"
@@ -187,9 +188,8 @@ nsBMPEncoder::AddImageFrame(const uint8_t* aData,
return NS_ERROR_INVALID_ARG;
}
- UniquePtr row(new (fallible)
- uint8_t[mBMPInfoHeader.width *
- BytesPerPixel(mBMPInfoHeader.bpp)]);
+ auto row = MakeUniqueFallible(mBMPInfoHeader.width *
+ BytesPerPixel(mBMPInfoHeader.bpp));
if (!row) {
return NS_ERROR_OUT_OF_MEMORY;
}
diff --git a/ipc/chromium/chromium-config.mozbuild b/ipc/chromium/chromium-config.mozbuild
index 53bd38348dc..c6f5de45c51 100644
--- a/ipc/chromium/chromium-config.mozbuild
+++ b/ipc/chromium/chromium-config.mozbuild
@@ -5,14 +5,11 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
LOCAL_INCLUDES += [
+ '!/ipc/ipdl/_ipdlheaders',
'/ipc/chromium/src',
'/ipc/glue',
]
-GENERATED_INCLUDES += [
- '/ipc/ipdl/_ipdlheaders',
-]
-
if CONFIG['OS_ARCH'] == 'WINNT':
OS_LIBS += [
'psapi',
diff --git a/ipc/chromium/src/third_party/libeventcommon.mozbuild b/ipc/chromium/src/third_party/libeventcommon.mozbuild
index f5736187bfe..bb8f41bcf40 100644
--- a/ipc/chromium/src/third_party/libeventcommon.mozbuild
+++ b/ipc/chromium/src/third_party/libeventcommon.mozbuild
@@ -31,7 +31,7 @@ else:
if os_posix and not CONFIG['MOZ_NATIVE_LIBEVENT']:
DEFINES['HAVE_CONFIG_H'] = True
LOCAL_INCLUDES += sorted([
- libevent_path_prefix + '/libevent',
- libevent_path_prefix + '/libevent/include',
- libevent_path_prefix + '/libevent/' + libevent_include_suffix,
+ 'libevent',
+ 'libevent/include',
+ 'libevent/' + libevent_include_suffix,
])
diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp
index 6c0271575e3..519cb1618d1 100644
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -101,11 +101,11 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
mPrivileges(aPrivileges),
mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"),
mProcessState(CREATING_CHANNEL),
- mDelegate(nullptr),
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
mEnableSandboxLogging(false),
mSandboxLevel(0),
#endif
+ mDelegate(nullptr),
mChildProcessHandle(0)
#if defined(MOZ_WIDGET_COCOA)
, mChildTask(MACH_PORT_NULL)
diff --git a/ipc/glue/MessageChannel.cpp b/ipc/glue/MessageChannel.cpp
index 1388b6502b9..805489894c5 100644
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -848,9 +848,6 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
AssertWorkerThread();
mMonitor->AssertNotCurrentThreadOwns();
- if (mCurrentTransaction == 0)
- mListener->OnBeginSyncTransaction();
-
#ifdef OS_WIN
SyncStackFrame frame(this, false);
NeuteredWindowRegion neuteredRgn(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION);
diff --git a/ipc/glue/MessageChannel.h b/ipc/glue/MessageChannel.h
index 41143c0594d..b0cc491279a 100644
--- a/ipc/glue/MessageChannel.h
+++ b/ipc/glue/MessageChannel.h
@@ -143,6 +143,7 @@ class MessageChannel : HasResultCodes
return !mCxxStackFrames.empty();
}
+ bool IsInTransaction() const { return mCurrentTransaction != 0; }
void CancelCurrentTransaction();
/**
diff --git a/ipc/glue/MessageLink.h b/ipc/glue/MessageLink.h
index ff6b8b96b87..06632467449 100644
--- a/ipc/glue/MessageLink.h
+++ b/ipc/glue/MessageLink.h
@@ -88,10 +88,6 @@ class MessageListener
virtual void OnExitedCall() {
NS_RUNTIMEABORT("default impl shouldn't be invoked");
}
- /* This callback is called when a sync message is sent that begins a new IPC transaction
- (i.e., when it is not part of an existing sequence of nested messages). */
- virtual void OnBeginSyncTransaction() {
- }
virtual RacyInterruptPolicy MediateInterruptRace(const Message& parent,
const Message& child)
{
diff --git a/js/ipc/JavaScriptChild.h b/js/ipc/JavaScriptChild.h
index 474064b6519..f5eb2daba96 100644
--- a/js/ipc/JavaScriptChild.h
+++ b/js/ipc/JavaScriptChild.h
@@ -25,6 +25,8 @@ class JavaScriptChild : public JavaScriptBase
void drop(JSObject* obj);
+ bool allowMessage(JSContext* cx) override { return true; }
+
protected:
virtual bool isParent() override { return false; }
virtual JSObject* scopeForTargetObjects() override;
diff --git a/js/ipc/JavaScriptParent.cpp b/js/ipc/JavaScriptParent.cpp
index 19d99c9e9a8..fa65efb5706 100644
--- a/js/ipc/JavaScriptParent.cpp
+++ b/js/ipc/JavaScriptParent.cpp
@@ -48,6 +48,54 @@ JavaScriptParent::init()
return true;
}
+static bool
+ForbidUnsafeBrowserCPOWs()
+{
+ static bool result;
+ static bool cached = false;
+ if (!cached) {
+ cached = true;
+ Preferences::AddBoolVarCache(&result, "dom.ipc.cpows.forbid-unsafe-from-browser", false);
+ }
+ return result;
+}
+
+bool
+JavaScriptParent::allowMessage(JSContext* cx)
+{
+ MessageChannel* channel = GetIPCChannel();
+ if (channel->IsInTransaction())
+ return true;
+
+ if (ForbidUnsafeBrowserCPOWs()) {
+ if (JSObject* global = JS::CurrentGlobalOrNull(cx)) {
+ if (!JS::AddonIdOfObject(global)) {
+ JS_ReportError(cx, "unsafe CPOW usage forbidden");
+ return false;
+ }
+ }
+ }
+
+ static bool disableUnsafeCPOWWarnings = PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS");
+ if (!disableUnsafeCPOWWarnings) {
+ nsCOMPtr console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+ if (console && cx) {
+ nsAutoString filename;
+ uint32_t lineno = 0, column = 0;
+ nsJSUtils::GetCallingLocation(cx, filename, &lineno, &column);
+ nsCOMPtr error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
+ error->Init(NS_LITERAL_STRING("unsafe CPOW usage"), filename,
+ EmptyString(), lineno, column,
+ nsIScriptError::warningFlag, "chrome javascript");
+ console->LogMessage(error);
+ } else {
+ NS_WARNING("Unsafe synchronous IPC message");
+ }
+ }
+
+ return true;
+}
+
void
JavaScriptParent::trace(JSTracer* trc)
{
diff --git a/js/ipc/JavaScriptParent.h b/js/ipc/JavaScriptParent.h
index b0fe4025508..aa379c81e7a 100644
--- a/js/ipc/JavaScriptParent.h
+++ b/js/ipc/JavaScriptParent.h
@@ -25,6 +25,8 @@ class JavaScriptParent : public JavaScriptBase
void drop(JSObject* obj);
+ bool allowMessage(JSContext* cx) override;
+
mozilla::ipc::IProtocol*
CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx) override;
diff --git a/js/ipc/WrapperOwner.cpp b/js/ipc/WrapperOwner.cpp
index 3b7646c2055..60093070352 100644
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -150,6 +150,9 @@ const CPOWProxyHandler CPOWProxyHandler::singleton;
JS_ReportError(cx, "cannot use a CPOW whose process is gone"); \
return false; \
} \
+ if (!owner->allowMessage(cx)) { \
+ return false; \
+ } \
{ \
CPOWTimer timer(cx); \
return owner->call args; \
@@ -978,8 +981,9 @@ InstanceOf(JSObject* proxy, const nsID* id, bool* bp)
}
bool
-DOMInstanceOf(JSContext* cx, JSObject* proxy, int prototypeID, int depth, bool* bp)
+DOMInstanceOf(JSContext* cx, JSObject* proxyArg, int prototypeID, int depth, bool* bp)
{
+ RootedObject proxy(cx, proxyArg);
FORWARD(domInstanceOf, (cx, proxy, prototypeID, depth, bp));
}
diff --git a/js/ipc/WrapperOwner.h b/js/ipc/WrapperOwner.h
index 757c8fd2853..2e05d1d2c5d 100644
--- a/js/ipc/WrapperOwner.h
+++ b/js/ipc/WrapperOwner.h
@@ -74,6 +74,8 @@ class WrapperOwner : public virtual JavaScriptShared
bool active() { return !inactive_; }
+ virtual bool allowMessage(JSContext* cx) = 0;
+
void drop(JSObject* obj);
void updatePointer(JSObject* obj, const JSObject* old);
diff --git a/js/src/configure.in b/js/src/configure.in
index de198cbdff3..5e06e09b24f 100644
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -350,7 +350,10 @@ case "$target" in
# that behavior) that it's better to turn it off.
# _CRT_SECURE_NO_WARNINGS disables warnings about using MSVC-specific
# secure CRT functions.
- CXXFLAGS="$CXXFLAGS -wd4345 -wd4351 -wd4800 -D_CRT_SECURE_NO_WARNINGS"
+ # MSVC warning C4819 warns some UTF-8 characters (e.g. copyright sign)
+ # on non-Western system locales even if it is in a comment.
+ CFLAGS="$CFLAGS -wd4819"
+ CXXFLAGS="$CXXFLAGS -wd4345 -wd4351 -wd4800 -wd4819 -D_CRT_SECURE_NO_WARNINGS"
AC_LANG_SAVE
AC_LANG_C
AC_TRY_COMPILE([#include ],
diff --git a/js/src/gdb/moz.build b/js/src/gdb/moz.build
index e385acaafdf..56378f76728 100644
--- a/js/src/gdb/moz.build
+++ b/js/src/gdb/moz.build
@@ -23,8 +23,10 @@ UNIFIED_SOURCES += [
DEFINES['EXPORT_JS_API'] = True
-LOCAL_INCLUDES += ['..']
-GENERATED_INCLUDES += ['..']
+LOCAL_INCLUDES += [
+ '!..',
+ '..',
+]
USE_LIBS += [
'static:js',
diff --git a/js/src/jsapi-tests/moz.build b/js/src/jsapi-tests/moz.build
index 9ad38d24ddb..c62193e2d3a 100644
--- a/js/src/jsapi-tests/moz.build
+++ b/js/src/jsapi-tests/moz.build
@@ -104,8 +104,10 @@ if CONFIG['ENABLE_ION']:
DEFINES['EXPORT_JS_API'] = True
-LOCAL_INCLUDES += ['..']
-GENERATED_INCLUDES += ['..']
+LOCAL_INCLUDES += [
+ '!..',
+ '..',
+]
USE_LIBS += [
'static:js',
diff --git a/js/src/moz.build b/js/src/moz.build
index 146f44e2055..a8f87d8a694 100644
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -541,8 +541,8 @@ if CONFIG['JS_HAS_CTYPES']:
'ctypes/Library.cpp',
]
if not CONFIG['MOZ_NATIVE_FFI']:
- GENERATED_INCLUDES += [
- 'ctypes/libffi/include',
+ LOCAL_INCLUDES += [
+ '!ctypes/libffi/include',
]
if CONFIG['MOZ_VTUNE']:
diff --git a/js/src/shell/moz.build b/js/src/shell/moz.build
index be315c60bbf..bb35df206c3 100644
--- a/js/src/shell/moz.build
+++ b/js/src/shell/moz.build
@@ -24,8 +24,10 @@ if CONFIG['_MSC_VER']:
# for PGO.
NO_PGO = True
-LOCAL_INCLUDES += ['..']
-GENERATED_INCLUDES += ['..']
+LOCAL_INCLUDES += [
+ '!..',
+ '..',
+]
OS_LIBS += CONFIG['EDITLINE_LIBS']
OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
diff --git a/layout/base/Units.h b/layout/base/Units.h
index 13e99709276..f02231ca1c4 100644
--- a/layout/base/Units.h
+++ b/layout/base/Units.h
@@ -10,11 +10,11 @@
#include "mozilla/gfx/Coord.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/gfx/Rect.h"
-#include "mozilla/gfx/RegionTyped.h"
#include "mozilla/gfx/ScaleFactor.h"
#include "mozilla/gfx/ScaleFactors2D.h"
-#include "nsRect.h"
#include "nsMargin.h"
+#include "nsRect.h"
+#include "nsRegion.h"
#include "mozilla/AppUnits.h"
#include "mozilla/TypeTraits.h"
diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp
index 794fb8b8ad3..1ccf4788bfa 100644
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -2832,29 +2832,6 @@ nsDocumentViewer::CallChildren(CallChildFunc aFunc, void* aClosure)
}
}
-struct LineBoxInfo
-{
- nscoord mMaxLineBoxWidth;
-};
-
-static void
-ChangeChildPaintingEnabled(nsIContentViewer* aChild, void* aClosure)
-{
- bool* enablePainting = (bool*) aClosure;
- if (*enablePainting) {
- aChild->ResumePainting();
- } else {
- aChild->PausePainting();
- }
-}
-
-static void
-ChangeChildMaxLineBoxWidth(nsIContentViewer* aChild, void* aClosure)
-{
- struct LineBoxInfo* lbi = (struct LineBoxInfo*) aClosure;
- aChild->ChangeMaxLineBoxWidth(lbi->mMaxLineBoxWidth);
-}
-
struct ZoomInfo
{
float mZoom;
@@ -3284,52 +3261,6 @@ NS_IMETHODIMP nsDocumentViewer::AppendSubtree(nsTArrayPausePainting();
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDocumentViewer::ResumePainting()
-{
- bool enablePaint = true;
- CallChildren(ChangeChildPaintingEnabled, &enablePaint);
-
- nsIPresShell* presShell = GetPresShell();
- if (presShell) {
- presShell->ResumePainting();
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDocumentViewer::ChangeMaxLineBoxWidth(int32_t aMaxLineBoxWidth)
-{
- // Change the max line box width for all children.
- struct LineBoxInfo lbi = { aMaxLineBoxWidth };
- CallChildren(ChangeChildMaxLineBoxWidth, &lbi);
-
- // Now, change our max line box width.
- // Convert to app units, since our input is in CSS pixels.
- nscoord mlbw = nsPresContext::CSSPixelsToAppUnits(aMaxLineBoxWidth);
- nsIPresShell* presShell = GetPresShell();
- if (presShell) {
- presShell->SetMaxLineBoxWidth(mlbw);
- }
-
- return NS_OK;
-}
-
NS_IMETHODIMP
nsDocumentViewer::GetContentSize(int32_t* aWidth, int32_t* aHeight)
{
diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h
index 609bbcaf592..d25009d9b47 100644
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -36,6 +36,7 @@
#include "nsCompatibility.h"
#include "nsFrameManagerBase.h"
#include "nsRect.h"
+#include "nsRegionFwd.h"
#include "mozFlushType.h"
#include "nsWeakReference.h"
#include // for FILE definition
@@ -69,7 +70,6 @@ class nsFrameManager;
class nsILayoutHistoryState;
class nsIReflowCallback;
class nsIDOMNode;
-class nsIntRegion;
class nsIStyleSheet;
class nsCSSFrameConstructor;
class nsISelection;
@@ -140,10 +140,10 @@ typedef struct CapturingContentInfo {
mozilla::StaticRefPtr mContent;
} CapturingContentInfo;
-// b07c5323-3061-4ca9-95ed-84cccbffadac
+// 0ff43c2e-5688-464f-a23f-a3de223df684
#define NS_IPRESSHELL_IID \
-{ 0xb07c5323, 0x3061, 0x4ca9, \
- { 0x95, 0xed, 0x84, 0xcc, 0xcb, 0xff, 0xad, 0xac } }
+{ 0x0ff43c2e, 0x5688, 0x464f, \
+ { 0xa2, 0x3f, 0xa3, 0xde, 0x22, 0x3d, 0xf6, 0x84 } }
// debug VerifyReflow flags
#define VERIFY_REFLOW_ON 0x01
@@ -936,20 +936,6 @@ public:
*/
bool IsPaintingSuppressed() const { return mPaintingSuppressed; }
- /**
- * Pause painting by freezing the refresh driver of this and all parent
- * presentations. This may not have the desired effect if this pres shell
- * has its own refresh driver.
- */
- virtual void PausePainting() = 0;
-
- /**
- * Resume painting by thawing the refresh driver of this and all parent
- * presentations. This may not have the desired effect if this pres shell
- * has its own refresh driver.
- */
- virtual void ResumePainting() = 0;
-
/**
* Unsuppress painting.
*/
@@ -1089,7 +1075,7 @@ public:
* such as the file name in a file upload widget, and we might choose not
* to paint themes.
* set RENDER_IGNORE_VIEWPORT_SCROLLING to ignore
- * clipping/scrolling/scrollbar painting due to scrolling in the viewport
+ * clipping and scrollbar painting due to scrolling in the viewport
* set RENDER_CARET to draw the caret if one would be visible
* (by default the caret is never drawn)
* set RENDER_USE_LAYER_MANAGER to force rendering to go through
@@ -1102,8 +1088,11 @@ public:
* set RENDER_ASYNC_DECODE_IMAGES to avoid having images synchronously
* decoded during rendering.
* (by default images decode synchronously with RenderDocument)
- * set RENDER_DOCUMENT_RELATIVE to interpret |aRect| relative to the
- * document instead of the CSS viewport
+ * set RENDER_DOCUMENT_RELATIVE to render the document as if there has been
+ * no scrolling and interpret |aRect| relative to the document instead of the
+ * CSS viewport. Only considered if RENDER_IGNORE_VIEWPORT_SCROLLING is set
+ * or the document is in ignore viewport scrolling mode
+ * (nsIPresShell::SetIgnoreViewportScrolling/IgnoringViewportScrolling).
* @param aBackgroundColor a background color to render onto
* @param aRenderedContext the gfxContext to render to. We render so that
* one CSS pixel in the source document is rendered to one unit in the current
@@ -1670,32 +1659,6 @@ public:
virtual void ThemeChanged() = 0;
virtual void BackingScaleFactorChanged() = 0;
- nscoord MaxLineBoxWidth() {
- return mMaxLineBoxWidth;
- }
-
- void SetMaxLineBoxWidth(nscoord aMaxLineBoxWidth);
-
- /**
- * Returns whether or not there is a reflow on zoom event pending. A reflow
- * on zoom event is a change to the max line box width, followed by a reflow.
- * This subsequent reflow event should treat all frames as though they resized
- * horizontally (and thus reflow all their descendants), rather than marking
- * all frames dirty from the root. This is the way the pres shell indicates
- * that an hresize reflow should take place during reflow state construction.
- */
- bool IsReflowOnZoomPending() {
- return mReflowOnZoomPending;
- }
-
- /**
- * Clear the flag indicating whether a reflow on zoom event is pending. This
- * is performed at the very end of DoReflow().
- */
- void ClearReflowOnZoomPending() {
- mReflowOnZoomPending = false;
- }
-
/**
* Documents belonging to an invisible DocShell must not be painted ever.
*/
@@ -1829,19 +1792,10 @@ protected:
bool mFontSizeInflationForceEnabled;
bool mFontSizeInflationDisabledInMasterProcess;
bool mFontSizeInflationEnabled;
- bool mPaintingIsFrozen;
// Dirty bit indicating that mFontSizeInflationEnabled needs to be recomputed.
bool mFontSizeInflationEnabledIsDirty;
- // Flag to indicate whether or not there is a reflow on zoom event pending.
- // See IsReflowOnZoomPending() for more information.
- bool mReflowOnZoomPending;
-
- // The maximum width of a line box. Text on a single line that exceeds this
- // width will be wrapped. A value of 0 indicates that no limit is enforced.
- nscoord mMaxLineBoxWidth;
-
// If a document belongs to an invisible DocShell, this flag must be set
// to true, so we can avoid any paint calls for widget related to this
// presshell.
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
index 839e05aca9a..8507f47b9dc 100644
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3127,6 +3127,42 @@ nsLayoutUtils::GetOrMaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder,
return haveDisplayPort;
}
+nsIScrollableFrame*
+nsLayoutUtils::GetAsyncScrollableAncestorFrame(nsIFrame* aTarget)
+{
+ uint32_t flags = nsLayoutUtils::SCROLLABLE_ALWAYS_MATCH_ROOT
+ | nsLayoutUtils::SCROLLABLE_ONLY_ASYNC_SCROLLABLE
+ | nsLayoutUtils::SCROLLABLE_FIXEDPOS_FINDS_ROOT;
+ return nsLayoutUtils::GetNearestScrollableFrame(aTarget, flags);
+}
+
+void
+nsLayoutUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(nsIFrame* aFrame,
+ RepaintMode aRepaintMode)
+{
+ nsIFrame* frame = aFrame;
+ while (frame) {
+ frame = nsLayoutUtils::GetCrossDocParentFrame(frame);
+ if (!frame) {
+ break;
+ }
+ nsIScrollableFrame* scrollAncestor = GetAsyncScrollableAncestorFrame(frame);
+ if (!scrollAncestor) {
+ break;
+ }
+ frame = do_QueryFrame(scrollAncestor);
+ MOZ_ASSERT(frame);
+ MOZ_ASSERT(scrollAncestor->WantAsyncScroll() ||
+ frame->PresContext()->PresShell()->GetRootScrollFrame() == frame);
+ if (nsLayoutUtils::AsyncPanZoomEnabled(frame) &&
+ !nsLayoutUtils::GetDisplayPort(frame->GetContent())) {
+ nsLayoutUtils::SetDisplayPortMargins(
+ frame->GetContent(), frame->PresContext()->PresShell(), ScreenMargin(), 0,
+ aRepaintMode);
+ }
+ }
+}
+
nsresult
nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFrame,
const nsRegion& aDirtyRegion, nscolor aBackstop,
diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h
index 4845b0b95dc..261266a6baa 100644
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1048,9 +1048,11 @@ public:
* to force rendering to use the widget's layer manager for testing
* or speed. PAINT_WIDGET_LAYERS must be set if aRenderingContext is null.
* If PAINT_DOCUMENT_RELATIVE is used, the visible region is interpreted
- * as being relative to the document. (Normally it's relative to the CSS
- * viewport.) PAINT_TO_WINDOW sets painting to window to true on the display
- * list builder even if we can't tell that we are painting to the window.
+ * as being relative to the document (normally it's relative to the CSS
+ * viewport) and the document is painted as if no scrolling has occured.
+ * Only considered if nsIPresShell::IgnoringViewportScrolling is true.
+ * PAINT_TO_WINDOW sets painting to window to true on the display list
+ * builder even if we can't tell that we are painting to the window.
* If PAINT_EXISTING_TRANSACTION is set, then BeginTransaction() has already
* been called on aFrame's widget's layer manager and should not be
* called again.
@@ -2702,6 +2704,15 @@ public:
nsRect aDisplayPortBase,
nsRect* aOutDisplayport);
+ static nsIScrollableFrame* GetAsyncScrollableAncestorFrame(nsIFrame* aTarget);
+
+ /**
+ * Sets a zero margin display port on all proper ancestors of aFrame that
+ * are async scrollable.
+ */
+ static void SetZeroMarginDisplayPortOnAsyncScrollableAncestors(nsIFrame* aFrame,
+ RepaintMode aRepaintMode);
+
static bool IsOutlineStyleAutoEnabled();
static void SetBSizeFromFontMetrics(const nsIFrame* aFrame,
diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp
index d0c8818c803..5020f3e13e9 100644
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -789,8 +789,6 @@ PresShell::PresShell()
mScrollPositionClampingScrollPortSizeSet = false;
- mMaxLineBoxWidth = 0;
-
static bool addedSynthMouseMove = false;
if (!addedSynthMouseMove) {
Preferences::AddBoolVarCache(&sSynthMouseMove,
@@ -804,7 +802,6 @@ PresShell::PresShell()
addedPointerEventEnabled = true;
}
- mPaintingIsFrozen = false;
mHasCSSBackgroundColor = true;
mIsLastChromeOnlyEscapeKeyConsumed = false;
mHasReceivedPaintMessage = false;
@@ -828,13 +825,6 @@ PresShell::~PresShell()
mLastCallbackEventRequest == nullptr,
"post-reflow queues not empty. This means we're leaking");
- // Verify that if painting was frozen, but we're being removed from the tree,
- // that we now re-enable painting on our refresh driver, since it may need to
- // be re-used by another presentation.
- if (mPaintingIsFrozen) {
- mPresContext->RefreshDriver()->Thaw();
- }
-
#ifdef DEBUG
MOZ_ASSERT(mPresArenaAllocCount == 0,
"Some pres arena objects were not freed");
@@ -1869,7 +1859,7 @@ PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight)
DoReflow(rootFrame, true);
}
- DidDoReflow(true, false);
+ DidDoReflow(true);
}
}
@@ -6591,22 +6581,6 @@ PresShell::RecordMouseLocation(WidgetGUIEvent* aEvent)
}
}
-static PLDHashOperator
-FindAnyTarget(const uint32_t& aKey, RefPtr& aData,
- void* aAnyTarget)
-{
- if (aData) {
- dom::EventTarget* target = aData->GetTarget();
- if (target) {
- nsCOMPtr* content =
- static_cast*>(aAnyTarget);
- *content = do_QueryInterface(target);
- return PL_DHASH_STOP;
- }
- }
- return PL_DHASH_NEXT;
-}
-
nsIFrame* GetNearestFrameContainingPresShell(nsIPresShell* aPresShell)
{
nsView* view = aPresShell->GetViewManager()->GetRootView();
@@ -7314,7 +7288,18 @@ PresShell::HandleEvent(nsIFrame* aFrame,
// the capture list
nsCOMPtr anyTarget;
if (TouchManager::gCaptureTouchList->Count() > 0 && touchEvent->touches.Length() > 1) {
- TouchManager::gCaptureTouchList->Enumerate(&FindAnyTarget, &anyTarget);
+ for (auto iter = TouchManager::gCaptureTouchList->Iter();
+ !iter.Done();
+ iter.Next()) {
+ RefPtr& touch = iter.Data();
+ if (touch) {
+ dom::EventTarget* target = touch->GetTarget();
+ if (target) {
+ anyTarget = do_QueryInterface(target);
+ break;
+ }
+ }
+ }
}
for (int32_t i = touchEvent->touches.Length(); i; ) {
@@ -8854,7 +8839,7 @@ PresShell::WillDoReflow()
}
void
-PresShell::DidDoReflow(bool aInterruptible, bool aWasInterrupted)
+PresShell::DidDoReflow(bool aInterruptible)
{
mFrameConstructor->EndUpdate();
@@ -8875,10 +8860,6 @@ PresShell::DidDoReflow(bool aInterruptible, bool aWasInterrupted)
}
mPresContext->NotifyMissingFonts();
-
- if (!aWasInterrupted) {
- ClearReflowOnZoomPending();
- }
}
DOMHighResTimeStamp
@@ -9229,7 +9210,7 @@ PresShell::ProcessReflowCommands(bool aInterruptible)
// Exiting the scriptblocker might have killed us
if (!mIsDestroying) {
- DidDoReflow(aInterruptible, interrupted);
+ DidDoReflow(aInterruptible);
}
// DidDoReflow might have killed us
@@ -10889,39 +10870,6 @@ nsIPresShell::FontSizeInflationEnabled()
return mFontSizeInflationEnabled;
}
-void
-nsIPresShell::SetMaxLineBoxWidth(nscoord aMaxLineBoxWidth)
-{
- NS_ASSERTION(aMaxLineBoxWidth >= 0, "attempting to set max line box width to a negative value");
-
- if (mMaxLineBoxWidth != aMaxLineBoxWidth) {
- mMaxLineBoxWidth = aMaxLineBoxWidth;
- mReflowOnZoomPending = true;
- FrameNeedsReflow(GetRootFrame(), nsIPresShell::eResize,
- NS_FRAME_HAS_DIRTY_CHILDREN);
- }
-}
-
-void
-PresShell::PausePainting()
-{
- if (GetPresContext()->RefreshDriver()->PresContext() != GetPresContext())
- return;
-
- mPaintingIsFrozen = true;
- GetPresContext()->RefreshDriver()->Freeze();
-}
-
-void
-PresShell::ResumePainting()
-{
- if (GetPresContext()->RefreshDriver()->PresContext() != GetPresContext())
- return;
-
- mPaintingIsFrozen = false;
- GetPresContext()->RefreshDriver()->Thaw();
-}
-
void
nsIPresShell::SyncWindowProperties(nsView* aView)
{
diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h
index d099d25bd37..a2a48dfcd59 100644
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -436,10 +436,8 @@ protected:
* Callback handler for whether reflow happened.
*
* @param aInterruptible Whether or not reflow interruption is allowed.
- * @param aWasInterrupted Whether or not the reflow was interrupted earlier.
- *
*/
- void DidDoReflow(bool aInterruptible, bool aWasInterrupted);
+ void DidDoReflow(bool aInterruptible);
// ProcessReflowCommands returns whether we processed all our dirty roots
// without interruptions.
bool ProcessReflowCommands(bool aInterruptible);
@@ -732,9 +730,6 @@ protected:
virtual void ThemeChanged() override { mPresContext->ThemeChanged(); }
virtual void BackingScaleFactorChanged() override { mPresContext->UIResolutionChanged(); }
- virtual void PausePainting() override;
- virtual void ResumePainting() override;
-
void UpdateImageVisibility();
void UpdateActivePointerState(mozilla::WidgetGUIEvent* aEvent);
diff --git a/layout/base/tests/mochitest.ini b/layout/base/tests/mochitest.ini
index 67679e77afa..9a65019a593 100644
--- a/layout/base/tests/mochitest.ini
+++ b/layout/base/tests/mochitest.ini
@@ -199,7 +199,6 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
[test_bug731777.html]
[test_bug761572.html]
[test_bug770106.html]
-[test_maxLineBoxWidth.html]
[test_remote_frame.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_remote_passpointerevents.html]
diff --git a/layout/base/tests/test_maxLineBoxWidth.html b/layout/base/tests/test_maxLineBoxWidth.html
deleted file mode 100644
index d8b0431cacd..00000000000
--- a/layout/base/tests/test_maxLineBoxWidth.html
+++ /dev/null
@@ -1,191 +0,0 @@
-
-
-
-
-
- Test for Bug 780258
-
-
-
-
-
-
-Mozilla Bug 780258
-
-
-
-
-
-
All of this text should be completely contained
- within the blue box.
-
I once knew a man, showed me the sleight of hand.
- In the blink of an eye he danced across the strings.
- He played a song I've never heard; poignant and absurd;
- To this day, it leaves me wondering.
-
Don't let tomorrow find you wishin'.
- Boy, you've got a mission.
- Shake it, rattle, and roll.
- Now, just use your intuition.
- You'll get less competition
- from the clock up on the wall.
-
You are what you are.
- You dream what you dream.
- Play on your blue guitar for me.
-
-
-
This text should not apply the max line box width, since it exists within a constrained height block. This is used for limiting the reflow-on-zoom feature for constrained height blocks, since otherwise they could overflow into an element later in the document, or potentially have their text cut off vertically.
-
-
-
-
-
-
-
diff --git a/layout/build/moz.build b/layout/build/moz.build
index 83318f31b36..6272b01d4a4 100644
--- a/layout/build/moz.build
+++ b/layout/build/moz.build
@@ -85,17 +85,18 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
LOCAL_INCLUDES += [
'/dom/system/gonk',
]
- CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'dalvik/libnativehelper/include/nativehelper',
- 'frameworks/base/include',
- 'frameworks/base/include/binder',
- 'frameworks/base/include/utils',
- 'frameworks/base/include/media',
- 'frameworks/base/include/media/stagefright/openmax',
- 'frameworks/base/media/libstagefright/include',
+ if CONFIG['ANDROID_VERSION'] == '15':
+ LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+ 'dalvik/libnativehelper/include/nativehelper',
+ 'frameworks/base/include',
+ 'frameworks/base/include/binder',
+ 'frameworks/base/include/media',
+ 'frameworks/base/include/media/stagefright/openmax',
+ 'frameworks/base/include/utils',
+ 'frameworks/base/media/libstagefright/include',
+ ]
]
- ]
if CONFIG['MOZ_B2G_FM']:
LOCAL_INCLUDES += [
diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp
index 8b25b2bf15b..08ea83d63d6 100644
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1875,6 +1875,8 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter,
ScreenMargin(),
0,
nsLayoutUtils::RepaintMode::DoNotRepaint);
+ nsLayoutUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
+ mOuter, nsLayoutUtils::RepaintMode::DoNotRepaint);
}
}
@@ -2136,6 +2138,10 @@ ScrollFrameHelper::ScrollToWithOrigin(nsPoint aScrollPosition,
nsLayoutUtils::CalculateAndSetDisplayPortMargins(
mOuter->GetScrollTargetFrame(),
nsLayoutUtils::RepaintMode::DoNotRepaint);
+ nsIFrame* frame = do_QueryFrame(mOuter->GetScrollTargetFrame());
+ nsLayoutUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
+ frame,
+ nsLayoutUtils::RepaintMode::DoNotRepaint);
}
// Schedule a paint to ensure that the frame metrics get updated on
diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp
index 37816b92557..0adacc20dd4 100644
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -514,10 +514,9 @@ void
nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameType)
{
const WritingMode wm = mWritingMode; // just a shorthand
- bool isIResize = (frame->ISize(wm) !=
- ComputedISize() +
- ComputedLogicalBorderPadding().IStartEnd(wm)) ||
- aPresContext->PresShell()->IsReflowOnZoomPending();
+ bool isIResize =
+ frame->ISize(wm) !=
+ ComputedISize() + ComputedLogicalBorderPadding().IStartEnd(wm);
if ((frame->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT) &&
nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp
index 55f958e0e6b..f57c98d52be 100644
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -211,23 +211,6 @@ nsLineLayout::BeginLineReflow(nscoord aICoord, nscoord aBCoord,
psd->mIEnd = aICoord + aISize;
mContainerSize = aContainerSize;
- // If we're in a constrained block-size frame, then we don't allow a
- // max line box width to take effect.
- if (!(LineContainerFrame()->GetStateBits() &
- NS_FRAME_IN_CONSTRAINED_BSIZE)) {
-
- // If the available size is greater than the maximum line box width (if
- // specified), then we need to adjust the line box width to be at the max
- // possible width.
- nscoord maxLineBoxWidth =
- LineContainerFrame()->PresContext()->PresShell()->MaxLineBoxWidth();
-
- if (maxLineBoxWidth > 0 &&
- psd->mIEnd - psd->mIStart > maxLineBoxWidth) {
- psd->mIEnd = psd->mIStart + maxLineBoxWidth;
- }
- }
-
mBStartEdge = aBCoord;
psd->mNoWrap = !mStyleText->WhiteSpaceCanWrapStyle() || mSuppressLineWrap;
diff --git a/layout/style/CSSStyleSheet.cpp b/layout/style/CSSStyleSheet.cpp
index 4bc98188f04..9a71201dfae 100644
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -2332,12 +2332,6 @@ CSSStyleSheet::ReparseSheet(const nsAString& aInput)
return NS_OK;
}
-/* virtual */ nsIURI*
-CSSStyleSheet::GetOriginalURI() const
-{
- return mInner->mOriginalSheetURI;
-}
-
/* virtual */
JSObject*
CSSStyleSheet::WrapObject(JSContext* aCx, JS::Handle aGivenProto)
diff --git a/layout/style/CSSStyleSheet.h b/layout/style/CSSStyleSheet.h
index 1192fc5da1b..4abf42e857c 100644
--- a/layout/style/CSSStyleSheet.h
+++ b/layout/style/CSSStyleSheet.h
@@ -224,7 +224,7 @@ public:
/* Get the URI this sheet was originally loaded from, if any. Can
return null */
- virtual nsIURI* GetOriginalURI() const;
+ nsIURI* GetOriginalURI() const { return mInner->mOriginalSheetURI; }
// nsICSSLoaderObserver interface
NS_IMETHOD StyleSheetLoaded(CSSStyleSheet* aSheet, bool aWasAlternate,
diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp
index e899c6ba37a..26d210daacb 100644
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -437,7 +437,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
SheetLoadData::~SheetLoadData()
{
- NS_IF_RELEASE(mNext);
+ NS_CSS_NS_RELEASE_LIST_MEMBER(SheetLoadData, this, mNext);
}
NS_IMETHODIMP
diff --git a/layout/style/crashtests/1186768-1.xhtml b/layout/style/crashtests/1186768-1.xhtml
new file mode 100644
index 00000000000..22608557df5
--- /dev/null
+++ b/layout/style/crashtests/1186768-1.xhtml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/style/crashtests/1221902.html b/layout/style/crashtests/1221902.html
new file mode 100644
index 00000000000..4186a38b95d
--- /dev/null
+++ b/layout/style/crashtests/1221902.html
@@ -0,0 +1,38002 @@
+
diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list
index d93807c42f9..c541ed9fdf8 100644
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -125,9 +125,11 @@ load 1161366-1.html
load 1163446-1.html
load 1164813-1.html
load 1167782-1.html
+load 1186768-1.xhtml
load 1200568-1.html
load 1206105-1.html
load border-image-visited-link.html
load font-face-truncated-src.html
load large_border_image_width.html
load long-url-list-stack-overflow.html
+load 1221902.html
diff --git a/layout/style/nsCSSValue.h b/layout/style/nsCSSValue.h
index 6648c3423cf..6c27d6e2ccb 100644
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -50,6 +50,18 @@ class CSSStyleSheet;
cur = dlm_next; \
} \
}
+// Ditto, but use NS_RELEASE instead of 'delete' (bug 1221902).
+#define NS_CSS_NS_RELEASE_LIST_MEMBER(type_, ptr_, member_) \
+ { \
+ type_ *cur = (ptr_)->member_; \
+ (ptr_)->member_ = nullptr; \
+ while (cur) { \
+ type_ *dlm_next = cur->member_; \
+ cur->member_ = nullptr; \
+ NS_RELEASE(cur); \
+ cur = dlm_next; \
+ } \
+ }
// Clones a linked list iteratively to avoid blowing up the stack.
// If it fails to clone the entire list then 'to_' is deleted and
diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp
index bdb211208cf..23eb44fea96 100644
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -3846,24 +3846,50 @@ nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext,
&scriptLevelAdjustedUnconstrainedParentSize);
NS_ASSERTION(!aUsedStartStruct || aFont->mScriptUnconstrainedSize == aFont->mSize,
"If we have a start struct, we should have reset everything coming in here");
+
+ // Compute whether we're affected by scriptMinSize *before* calling
+ // SetFontSize, since aParentFont might be the same as aFont. If it
+ // is, calling SetFontSize might throw off our calculation.
+ bool affectedByScriptMinSize =
+ aParentFont->mSize != aParentFont->mScriptUnconstrainedSize ||
+ scriptLevelAdjustedParentSize !=
+ scriptLevelAdjustedUnconstrainedParentSize;
+
SetFontSize(aPresContext, aRuleData, aFont, aParentFont,
&aFont->mSize,
systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize,
aUsedStartStruct, atRoot, aConditions);
- if (aParentFont->mSize == aParentFont->mScriptUnconstrainedSize &&
- scriptLevelAdjustedParentSize == scriptLevelAdjustedUnconstrainedParentSize) {
+ if (!aPresContext->Document()->GetMathMLEnabled()) {
+ MOZ_ASSERT(!affectedByScriptMinSize);
+ // If MathML is not enabled, we don't need to mark this node as
+ // uncacheable. If it becomes enabled, code in
+ // nsMathMLElementFactory will rebuild the rule tree and style data
+ // when MathML is first enabled (see nsMathMLElement::BindToTree).
+ aFont->mScriptUnconstrainedSize = aFont->mSize;
+ } else if (!affectedByScriptMinSize) {
// Fast path: we have not been affected by scriptminsize so we don't
// need to call SetFontSize again to compute the
// scriptminsize-unconstrained size. This is OK even if we have a
// start struct, because if we have a start struct then 'font-size'
// was specified and so scriptminsize has no effect.
aFont->mScriptUnconstrainedSize = aFont->mSize;
+ // It's possible we could, in the future, have a different parent,
+ // which would lead to a different affectedByScriptMinSize.
+ aConditions.SetUncacheable();
} else {
+ // see previous else-if
+ aConditions.SetUncacheable();
+
+ // Use a separate conditions object because it might get a
+ // *different* font-size dependency. We can ignore it because we've
+ // already called SetUncacheable.
+ RuleNodeCacheConditions unconstrainedConditions;
+
SetFontSize(aPresContext, aRuleData, aFont, aParentFont,
&aFont->mScriptUnconstrainedSize,
systemFont, aParentFont->mScriptUnconstrainedSize,
scriptLevelAdjustedUnconstrainedParentSize,
- aUsedStartStruct, atRoot, aConditions);
+ aUsedStartStruct, atRoot, unconstrainedConditions);
}
NS_ASSERTION(aFont->mScriptUnconstrainedSize <= aFont->mSize,
"scriptminsize should never be making things bigger");
diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini
index 40c7148cb1a..fc057db0ca0 100644
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -176,6 +176,7 @@ support-files =
BitPattern.woff
file_font_loading_api_vframe.html
[test_garbage_at_end_of_declarations.html]
+skip-if = (toolkit == 'gonk' && debug) # Bug 1186440
[test_grid_container_shorthands.html]
[test_grid_item_shorthands.html]
[test_grid_shorthand_serialization.html]
diff --git a/layout/svg/nsSVGIntegrationUtils.h b/layout/svg/nsSVGIntegrationUtils.h
index f8781aa83e5..00514e042d8 100644
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -9,13 +9,13 @@
#include "gfxMatrix.h"
#include "gfxRect.h"
#include "nsAutoPtr.h"
+#include "nsRegionFwd.h"
class gfxContext;
class gfxDrawable;
class nsDisplayList;
class nsDisplayListBuilder;
class nsIFrame;
-class nsIntRegion;
struct nsRect;
diff --git a/media/libcubeb/src/moz.build b/media/libcubeb/src/moz.build
index 3a11a25c090..a01a4ced249 100644
--- a/media/libcubeb/src/moz.build
+++ b/media/libcubeb/src/moz.build
@@ -63,12 +63,14 @@ if CONFIG['OS_TARGET'] == 'Android':
FINAL_LIBRARY = 'gkmedias'
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- CFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/wilhelm/include',
- 'system/media/wilhelm/include',
+ if CONFIG['ANDROID_VERSION'] >= '17':
+ LOCAL_INCLUDES += [
+ '%' + '%s/frameworks/wilhelm/include' % CONFIG['ANDROID_SOURCE'],
+ ]
+ else:
+ LOCAL_INCLUDES += [
+ '%' + '%s/system/media/wilhelm/include' % CONFIG['ANDROID_SOURCE'],
]
- ]
CFLAGS += CONFIG['MOZ_ALSA_CFLAGS']
CFLAGS += CONFIG['MOZ_PULSEAUDIO_CFLAGS']
diff --git a/media/omx-plugin/moz.build b/media/omx-plugin/moz.build
index 529bab2077a..12b939effab 100644
--- a/media/omx-plugin/moz.build
+++ b/media/omx-plugin/moz.build
@@ -33,20 +33,22 @@ if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-multichar']
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
- CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'dalvik/libnativehelper/include/nativehelper',
- 'frameworks/base/include/',
- 'frameworks/base/include/binder/',
- 'frameworks/base/include/utils/',
- 'frameworks/base/include/media/',
- 'frameworks/base/include/media/stagefright/openmax',
- 'frameworks/base/media/libstagefright/include',
- 'frameworks/base/native/include',
- 'system/core/include',
- 'hardware/libhardware/include',
- ]
- ]
+ if CONFIG['ANDROID_VERSION'] == '15':
+ LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+ 'dalvik/libnativehelper/include/nativehelper',
+ 'frameworks/base/include/',
+ 'frameworks/base/include/binder/',
+ 'frameworks/base/include/media/',
+ 'frameworks/base/include/media/stagefright/openmax',
+ 'frameworks/base/include/utils/',
+ 'frameworks/base/media/libstagefright/include',
+ 'frameworks/base/native/include',
+ 'hardware/libhardware/include',
+ 'system/core/include',
+ ]
+ ]
+
EXTRA_DSO_LDOPTS += [
'-lutils',
'-lstagefright',
diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
index cc1ba2682e0..05d0ed0038b 100644
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -45,6 +45,7 @@
#include "mozilla/gfx/Point.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/UniquePtr.h"
+#include "mozilla/UniquePtrExtensions.h"
#include "logging.h"
@@ -1179,7 +1180,7 @@ void MediaPipelineTransmit::PipelineListener::ProcessVideoChunk(
int half_height = (size.height + 1) >> 1;
int c_size = half_width * half_height;
int buffer_size = YSIZE(size.width, size.height) + 2 * c_size;
- UniquePtr yuv_scoped(new (fallible) uint8[buffer_size]);
+ auto yuv_scoped = MakeUniqueFallible(buffer_size);
if (!yuv_scoped)
return;
uint8* yuv = yuv_scoped.get();
diff --git a/media/webrtc/signaling/test/common.build b/media/webrtc/signaling/test/common.build
index babf9b6c94a..b3bb19f04b5 100644
--- a/media/webrtc/signaling/test/common.build
+++ b/media/webrtc/signaling/test/common.build
@@ -11,10 +11,8 @@ for var in ('MOZILLA_EXTERNAL_LINKAGE', 'USE_FAKE_MEDIA_STREAMS', 'USE_FAKE_PCOB
'NR_SOCKET_IS_VOID_PTR', 'HAVE_STRDUP'):
DEFINES[var] = True
-GENERATED_INCLUDES += [
- '/dom/bindings',
-]
LOCAL_INCLUDES += [
+ '!/dom/bindings',
'/dom/media/',
'/ipc/chromium/src',
'/media/mtransport',
diff --git a/memory/build/moz.build b/memory/build/moz.build
index efeb9c8e427..3595bc663c7 100644
--- a/memory/build/moz.build
+++ b/memory/build/moz.build
@@ -27,7 +27,7 @@ if CONFIG['MOZ_JEMALLOC4']:
SOURCES += [
'mozjemalloc_compat.c',
]
- GENERATED_INCLUDES += ['../jemalloc/src/include']
+ LOCAL_INCLUDES += ['!../jemalloc/src/include']
if CONFIG['_MSC_VER']:
LOCAL_INCLUDES += ['/memory/jemalloc/src/include/msvc_compat']
if not CONFIG['HAVE_INTTYPES_H']:
diff --git a/memory/jemalloc/moz.build b/memory/jemalloc/moz.build
index ed05a2d1578..55c84c67979 100644
--- a/memory/jemalloc/moz.build
+++ b/memory/jemalloc/moz.build
@@ -69,8 +69,10 @@ if CONFIG['GNU_CC']:
DEFINES['abort'] = 'moz_abort'
-GENERATED_INCLUDES += ['src/include']
-LOCAL_INCLUDES += ['src/include']
+LOCAL_INCLUDES += [
+ '!src/include',
+ 'src/include',
+]
# We allow warnings for third-party code that can be updated from upstream.
ALLOW_COMPILER_WARNINGS = True
diff --git a/memory/mozalloc/moz.build b/memory/mozalloc/moz.build
index 35a3e0c1115..33f599199af 100644
--- a/memory/mozalloc/moz.build
+++ b/memory/mozalloc/moz.build
@@ -36,8 +36,6 @@ FINAL_LIBRARY = 'mozglue'
# The strndup declaration in string.h is in an ifdef __USE_GNU section
DEFINES['_GNU_SOURCE'] = True
-GENERATED_INCLUDES += ['/xpcom']
-
DISABLE_STL_WRAPPING = True
DEFINES['IMPL_MFBT'] = True
@@ -45,7 +43,10 @@ DEFINES['IMPL_MFBT'] = True
if CONFIG['_MSC_VER']:
DIRS += ['staticruntime']
-LOCAL_INCLUDES += ['/memory/build']
+LOCAL_INCLUDES += [
+ '!/xpcom',
+ '/memory/build',
+]
DIST_INSTALL = True
diff --git a/memory/mozalloc/staticruntime/moz.build b/memory/mozalloc/staticruntime/moz.build
index e4efea85278..e0a6b9def6a 100644
--- a/memory/mozalloc/staticruntime/moz.build
+++ b/memory/mozalloc/staticruntime/moz.build
@@ -19,7 +19,7 @@ UNIFIED_SOURCES += [
'../mozalloc_oom.cpp',
]
-GENERATED_INCLUDES += ['/xpcom']
+LOCAL_INCLUDES += ['!/xpcom']
DISABLE_STL_WRAPPING = True
diff --git a/memory/replace/jemalloc/moz.build b/memory/replace/jemalloc/moz.build
index 1918de4763e..7518f245101 100644
--- a/memory/replace/jemalloc/moz.build
+++ b/memory/replace/jemalloc/moz.build
@@ -26,7 +26,7 @@ USE_LIBS += [
DEFINES['MOZ_JEMALLOC4'] = True
DEFINES['MOZ_REPLACE_JEMALLOC'] = True
-GENERATED_INCLUDES += ['../../jemalloc/src/include']
+LOCAL_INCLUDES += ['!../../jemalloc/src/include']
if CONFIG['_MSC_VER']:
LOCAL_INCLUDES += ['/memory/jemalloc/src/include/msvc_compat']
if not CONFIG['HAVE_INTTYPES_H']:
diff --git a/mfbt/UniquePtrExtensions.h b/mfbt/UniquePtrExtensions.h
new file mode 100644
index 00000000000..65b07ed2ee0
--- /dev/null
+++ b/mfbt/UniquePtrExtensions.h
@@ -0,0 +1,42 @@
+/* -*- 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/. */
+
+/* Useful extensions to UniquePtr. */
+
+#ifndef mozilla_UniquePtrExtensions_h
+#define mozilla_UniquePtrExtensions_h
+
+#include "mozilla/fallible.h"
+#include "mozilla/UniquePtr.h"
+
+namespace mozilla {
+
+/**
+ * MakeUniqueFallible works exactly like MakeUnique, except that the memory
+ * allocation performed is done fallibly, i.e. it can return nullptr.
+ */
+template
+typename detail::UniqueSelector::SingleObject
+MakeUniqueFallible(Args&&... aArgs)
+{
+ return UniquePtr(new (fallible) T(Forward(aArgs)...));
+}
+
+template
+typename detail::UniqueSelector::UnknownBound
+MakeUniqueFallible(decltype(sizeof(int)) aN)
+{
+ typedef typename RemoveExtent::Type ArrayType;
+ return UniquePtr(new (fallible) ArrayType[aN]());
+}
+
+template
+typename detail::UniqueSelector::KnownBound
+MakeUniqueFallible(Args&&... aArgs) = delete;
+
+} // namespace mozilla
+
+#endif // mozilla_UniquePtrExtensions_h
diff --git a/mfbt/moz.build b/mfbt/moz.build
index 4678f6d060d..f4ae83fbf40 100644
--- a/mfbt/moz.build
+++ b/mfbt/moz.build
@@ -89,6 +89,7 @@ EXPORTS.mozilla = [
'Types.h',
'TypeTraits.h',
'UniquePtr.h',
+ 'UniquePtrExtensions.h',
'Variant.h',
'Vector.h',
'WeakPtr.h',
diff --git a/mobile/android/base/AndroidManifest.xml b/mobile/android/base/AndroidManifest.xml
new file mode 100644
index 00000000000..decb23df4fd
--- /dev/null
+++ b/mobile/android/base/AndroidManifest.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/mobile/android/base/DataReportingNotification.java b/mobile/android/base/DataReportingNotification.java
index 62fe79cbee3..a4988b190fd 100644
--- a/mobile/android/base/DataReportingNotification.java
+++ b/mobile/android/base/DataReportingNotification.java
@@ -78,7 +78,7 @@ public class DataReportingNotification {
Intent prefIntent = new Intent(GeckoApp.ACTION_LAUNCH_SETTINGS);
prefIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
- GeckoPreferences.setResourceToOpen(prefIntent, "preferences_vendor");
+ GeckoPreferences.setResourceToOpen(prefIntent, "preferences_privacy");
prefIntent.putExtra(ALERT_NAME_DATAREPORTING_NOTIFICATION, true);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, prefIntent, PendingIntent.FLAG_UPDATE_CURRENT);
diff --git a/mobile/android/base/android-services.mozbuild b/mobile/android/base/android-services.mozbuild
index 31be309cdea..84d3361c35f 100644
--- a/mobile/android/base/android-services.mozbuild
+++ b/mobile/android/base/android-services.mozbuild
@@ -850,6 +850,7 @@ sync_java_files = [
'browserid/verifier/BrowserIDVerifierException.java',
'browserid/VerifyingPublicKey.java',
'fxa/AccountLoader.java',
+ 'fxa/activities/CustomColorPreference.java',
'fxa/activities/FxAccountAbstractActivity.java',
'fxa/activities/FxAccountAbstractSetupActivity.java',
'fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java',
diff --git a/mobile/android/base/build.gradle b/mobile/android/base/build.gradle
new file mode 100644
index 00000000000..b6c33de56df
--- /dev/null
+++ b/mobile/android/base/build.gradle
@@ -0,0 +1,131 @@
+buildDir "${topobjdir}/gradle/build/mobile/android/base"
+
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.1"
+
+ defaultConfig {
+ targetSdkVersion 22
+ minSdkVersion 9
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_7
+ targetCompatibility JavaVersion.VERSION_1_7
+ }
+
+ lintOptions {
+ abortOnError false
+ }
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java {
+ srcDir "${topobjdir}/gradle/base/src"
+ exclude 'org/mozilla/gecko/resources/**'
+
+ srcDir "${topsrcdir}/mobile/android/search/java"
+ srcDir "${topsrcdir}/mobile/android/javaaddons/java"
+
+ if (mozconfig.substs.MOZ_ANDROID_MLS_STUMBLER) {
+ srcDir "${topsrcdir}/mobile/android/stumbler/java"
+ }
+
+ if (!mozconfig.substs.MOZ_CRASHREPORTER) {
+ exclude 'org/mozilla/gecko/CrashReporter.java'
+ }
+
+ if (!mozconfig.substs.MOZ_NATIVE_DEVICES) {
+ exclude 'org/mozilla/gecko/ChromeCast.java'
+ exclude 'org/mozilla/gecko/GeckoMediaPlayer.java'
+ exclude 'org/mozilla/gecko/MediaPlayerManager.java'
+ }
+
+ if (mozconfig.substs.MOZ_WEBRTC) {
+ srcDir "${topsrcdir}/media/webrtc/trunk/webrtc/modules/audio_device/android/java/src"
+ srcDir "${topsrcdir}/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src"
+ srcDir "${topsrcdir}/media/webrtc/trunk/webrtc/modules/video_render/android/java/src"
+ }
+
+ if (mozconfig.substs.MOZ_INSTALL_TRACKING) {
+ exclude 'org/mozilla/gecko/adjust/StubAdjustHelper.java'
+ } else {
+ exclude 'org/mozilla/gecko/adjust/AdjustHelper.java'
+ }
+
+ srcDir "${project.buildDir}/generated/source/preprocessed_code" // See syncPreprocessedCode.
+ }
+
+ res {
+ srcDir "${topsrcdir}/${mozconfig.substs.MOZ_BRANDING_DIRECTORY}/res"
+ srcDir "${project.buildDir}/generated/source/preprocessed_resources" // See syncPreprocessedResources.
+ srcDir 'resources'
+ if (mozconfig.substs.MOZ_CRASHREPORTER) {
+ srcDir 'crashreporter/res'
+ }
+ }
+ }
+
+ test {
+ java {
+ srcDir "${topsrcdir}/mobile/android/tests/background/junit4/src"
+ }
+
+ resources {
+ srcDir "${topsrcdir}/mobile/android/tests/background/junit4/resources"
+ }
+ }
+ }
+}
+
+task syncPreprocessedCode(type: Sync, dependsOn: rootProject.generateCodeAndResources) {
+ into("${project.buildDir}/generated/source/preprocessed_code")
+ from("${topobjdir}/mobile/android/base/generated/preprocessed")
+}
+
+task syncPreprocessedResources(type: Sync, dependsOn: rootProject.generateCodeAndResources) {
+ into("${project.buildDir}/generated/source/preprocessed_resources")
+ from("${topobjdir}/mobile/android/base/res")
+}
+
+android.libraryVariants.all { variant ->
+ variant.preBuild.dependsOn syncPreprocessedCode
+ variant.preBuild.dependsOn syncPreprocessedResources
+}
+
+dependencies {
+ compile 'com.android.support:support-v4:23.0.1'
+ compile 'com.android.support:appcompat-v7:23.0.1'
+ compile 'com.android.support:recyclerview-v7:23.0.1'
+ compile 'com.android.support:design:23.0.1'
+
+ if (mozconfig.substs.MOZ_NATIVE_DEVICES) {
+ compile 'com.android.support:mediarouter-v7:23.0.1'
+ compile 'com.google.android.gms:play-services-basement:8.1.0'
+ compile 'com.google.android.gms:play-services-base:8.1.0'
+ compile 'com.google.android.gms:play-services-cast:8.1.0'
+ }
+
+ if (mozconfig.substs.MOZ_ANDROID_GCM) {
+ compile 'com.google.android.gms:play-services-basement:8.1.0'
+ compile 'com.google.android.gms:play-services-base:8.1.0'
+ compile 'com.google.android.gms:play-services-gcm:8.1.0'
+ }
+
+ compile project(':thirdparty')
+
+ testCompile 'junit:junit:4.12'
+ testCompile 'org.robolectric:robolectric:3.0'
+ testCompile 'org.simpleframework:simple-http:4.1.13'
+}
+
+apply plugin: 'idea'
+
+idea {
+ module {
+ excludeDirs += file("${topobjdir}/gradle/base/src/org/mozilla/gecko/resources")
+ }
+}
diff --git a/mobile/android/base/fxa/activities/CustomColorPreference.java b/mobile/android/base/fxa/activities/CustomColorPreference.java
new file mode 100644
index 00000000000..5c4d7f3ccaf
--- /dev/null
+++ b/mobile/android/base/fxa/activities/CustomColorPreference.java
@@ -0,0 +1,52 @@
+/* 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/. */
+
+package org.mozilla.gecko.fxa.activities;
+
+import org.mozilla.gecko.R;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
+
+ /**
+ * This preference is used to define custom colors for both title and summary texts.
+ * Color code #777777 (placeholder_grey) is used as the fallback color for both title and summary.
+ */
+public class CustomColorPreference extends Preference {
+ private int mTitleColor;
+ private int mSummaryColor;
+
+ public CustomColorPreference(Context context) {
+ super(context);
+ }
+
+ public CustomColorPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context, attrs);
+ }
+
+ public CustomColorPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context, attrs);
+ }
+
+ public void init(Context context, AttributeSet attrs) {
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomColorPreference);
+ mTitleColor = a.getColor(R.styleable.CustomColorPreference_titleColor, R.color.placeholder_grey);
+ mSummaryColor = a.getColor(R.styleable.CustomColorPreference_summaryColor, R.color.placeholder_grey);
+ a.recycle();
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ final TextView title = (TextView) view.findViewById(android.R.id.title);
+ final TextView summary = (TextView) view.findViewById(android.R.id.summary);
+ title.setTextColor(mTitleColor);
+ summary.setTextColor(mSummaryColor);
+ }
+}
diff --git a/mobile/android/base/lint.xml b/mobile/android/base/lint.xml
new file mode 100644
index 00000000000..b1cc083dee2
--- /dev/null
+++ b/mobile/android/base/lint.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mobile/android/base/preferences/GeckoPreferenceFragment.java b/mobile/android/base/preferences/GeckoPreferenceFragment.java
index 2ae04fe758a..4551c23eb36 100644
--- a/mobile/android/base/preferences/GeckoPreferenceFragment.java
+++ b/mobile/android/base/preferences/GeckoPreferenceFragment.java
@@ -98,8 +98,8 @@ public class GeckoPreferenceFragment extends PreferenceFragment {
// We need this because we can launch straight into this category
// from the Data Reporting notification.
- if (res == R.xml.preferences_vendor) {
- return getString(R.string.pref_category_vendor);
+ if (res == R.xml.preferences_privacy) {
+ return getString(R.string.pref_category_privacy_short);
}
// from the Awesomescreen with the magnifying glass.
diff --git a/mobile/android/base/resources/values/attrs.xml b/mobile/android/base/resources/values/attrs.xml
index d11a33d17e4..a3cc181449f 100644
--- a/mobile/android/base/resources/values/attrs.xml
+++ b/mobile/android/base/resources/values/attrs.xml
@@ -168,6 +168,11 @@
+
+
+
+
+
diff --git a/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml b/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
index 88b16e27497..59e447ebee7 100644
--- a/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
+++ b/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
@@ -1,6 +1,7 @@
+ xmlns:gecko="http://schemas.android.com/apk/res-auto"
+ android:key="status_screen">
- Cu.reportError("Error adding tab to reading list: " + e));
UITelemetry.addEvent("save.1", "pageaction", null, "reader");
+ Reader._buttonHistogram.add(Reader._buttonHistogramValues.LONG_TAP);
},
},
@@ -247,6 +264,9 @@ var Reader = {
if (browser.isArticle) {
showPageAction("drawable://reader", Strings.reader.GetStringFromName("readerView.enter"));
+ this._buttonHistogram.add(this._buttonHistogramValues.SHOWN);
+ } else {
+ this._buttonHistogram.add(this._buttonHistogramValues.HIDDEN);
}
},
diff --git a/mozglue/android/moz.build b/mozglue/android/moz.build
index 71d87af80af..88cf3701149 100644
--- a/mozglue/android/moz.build
+++ b/mozglue/android/moz.build
@@ -26,8 +26,8 @@ for var in ('ANDROID_PACKAGE_NAME',
if CONFIG['MOZ_FOLD_LIBS']:
DEFINES['MOZ_FOLD_LIBS'] = True
-GENERATED_INCLUDES += ['/build']
LOCAL_INCLUDES += [
+ '!/build',
'../linker',
'/db/sqlite3/src',
'/ipc/chromium/src',
diff --git a/netwerk/build/moz.build b/netwerk/build/moz.build
index e9ca940fa32..a3ba3c7ceac 100644
--- a/netwerk/build/moz.build
+++ b/netwerk/build/moz.build
@@ -73,6 +73,6 @@ if CONFIG['MOZ_RTSP']:
'/netwerk/protocol/rtsp',
]
-GENERATED_INCLUDES += [
- '/netwerk/dns',
+LOCAL_INCLUDES += [
+ '!/netwerk/dns',
]
diff --git a/netwerk/dns/mdns/libmdns/moz.build b/netwerk/dns/mdns/libmdns/moz.build
index 1615f3a070e..2012f423d14 100644
--- a/netwerk/dns/mdns/libmdns/moz.build
+++ b/netwerk/dns/mdns/libmdns/moz.build
@@ -17,8 +17,8 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] >= '16
'nsDNSServiceDiscovery.cpp',
]
- CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+ LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
'external/mdnsresponder/mDNSShared',
]
]
diff --git a/netwerk/dns/moz.build b/netwerk/dns/moz.build
index d1d259e1218..49ed50ef72d 100644
--- a/netwerk/dns/moz.build
+++ b/netwerk/dns/moz.build
@@ -67,7 +67,7 @@ LOCAL_INCLUDES += [
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] > '19':
- CXXFLAGS += ['-I%s/bionic/libc/dns/include' % CONFIG['ANDROID_SOURCE']]
+ LOCAL_INCLUDES += ['%' + '%s/bionic/libc/dns/include' % CONFIG['ANDROID_SOURCE']]
if CONFIG['ENABLE_INTL_API']:
DEFINES['IDNA2008'] = True
diff --git a/netwerk/protocol/rtsp/moz.build b/netwerk/protocol/rtsp/moz.build
index 655507dac8f..13d491cd1d5 100644
--- a/netwerk/protocol/rtsp/moz.build
+++ b/netwerk/protocol/rtsp/moz.build
@@ -66,8 +66,8 @@ for var in ('IMPL_NS_NET', 'FORCE_PR_LOG'):
DEFINES[var] = True
if CONFIG['ANDROID_VERSION'] == '15':
- CXXFLAGS += ['-I%s/frameworks/base/media/libstagefright/mpeg2ts' % CONFIG['ANDROID_SOURCE']]
+ LOCAL_INCLUDES += ['%' + '%s/frameworks/base/media/libstagefright/mpeg2ts' % CONFIG['ANDROID_SOURCE']]
else:
- CXXFLAGS += ['-I%s/frameworks/av/media/libstagefright/mpeg2ts' % CONFIG['ANDROID_SOURCE']]
+ LOCAL_INCLUDES += ['%' + '%s/frameworks/av/media/libstagefright/mpeg2ts' % CONFIG['ANDROID_SOURCE']]
CXXFLAGS += ['-Wno-multichar']
diff --git a/python/mozbuild/mozbuild/backend/recursivemake.py b/python/mozbuild/mozbuild/backend/recursivemake.py
index 33767778b34..ee8962ef0fd 100644
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -24,6 +24,11 @@ from mozpack.manifests import (
)
import mozpack.path as mozpath
+from mozbuild.frontend.context import (
+ Path,
+ SourcePath,
+ ObjDirPath,
+)
from .common import CommonBackend
from ..frontend.data import (
AndroidAssetsDirs,
@@ -42,7 +47,6 @@ from ..frontend.data import (
ExternalLibrary,
FinalTargetFiles,
GeneratedFile,
- GeneratedInclude,
GeneratedSources,
HostDefines,
HostLibrary,
@@ -556,9 +560,6 @@ class RecursiveMakeBackend(CommonBackend):
elif isinstance(obj, LocalInclude):
self._process_local_include(obj.path, backend_file)
- elif isinstance(obj, GeneratedInclude):
- self._process_generated_include(obj.path, backend_file)
-
elif isinstance(obj, PerSourceFlag):
self._process_per_source_flag(obj, backend_file)
@@ -868,6 +869,21 @@ class RecursiveMakeBackend(CommonBackend):
ensureParentDir(mozpath.join(self.environment.topobjdir, 'dist', 'foo'))
+ def _pretty_path(self, path, backend_file):
+ assert isinstance(path, Path)
+ if isinstance(path, SourcePath):
+ if path.full_path.startswith(backend_file.srcdir):
+ return '$(srcdir)' + path.full_path[len(backend_file.srcdir):]
+ if path.full_path.startswith(self.environment.topsrcdir):
+ return '$(topsrcdir)' + path.full_path[len(self.environment.topsrcdir):]
+ elif isinstance(path, ObjDirPath):
+ if path.full_path.startswith(backend_file.objdir):
+ return path.full_path[len(backend_file.objdir) + 1:]
+ if path.full_path.startswith(self.environment.topobjdir):
+ return '$(DEPTH)' + path.full_path[len(self.environment.topobjdir):]
+
+ return path.full_path
+
def _process_unified_sources(self, obj):
backend_file = self._get_backend_file_for(obj)
@@ -1219,18 +1235,11 @@ INSTALL_TARGETS += %(prefix)s
self.backend_input_files |= obj.manifest.manifests
def _process_local_include(self, local_include, backend_file):
- if local_include.startswith('/'):
- path = '$(topsrcdir)'
+ path = self._pretty_path(local_include, backend_file)
+ if ' ' in path:
+ backend_file.write('LOCAL_INCLUDES += -I\'%s\'\n' % path)
else:
- path = '$(srcdir)/'
- backend_file.write('LOCAL_INCLUDES += -I%s%s\n' % (path, local_include))
-
- def _process_generated_include(self, generated_include, backend_file):
- if generated_include.startswith('/'):
- path = self.environment.topobjdir.replace('\\', '/')
- else:
- path = ''
- backend_file.write('LOCAL_INCLUDES += -I%s%s\n' % (path, generated_include))
+ backend_file.write('LOCAL_INCLUDES += -I%s\n' % path)
def _process_per_source_flag(self, per_source_flag, backend_file):
for flag in per_source_flag.flags:
diff --git a/python/mozbuild/mozbuild/backend/visualstudio.py b/python/mozbuild/mozbuild/backend/visualstudio.py
index 51dd2e298b6..11aa573cede 100644
--- a/python/mozbuild/mozbuild/backend/visualstudio.py
+++ b/python/mozbuild/mozbuild/backend/visualstudio.py
@@ -136,13 +136,8 @@ class VisualStudioBackend(CommonBackend):
self._paths_to_defines.setdefault(reldir, {}).update(obj.defines)
elif isinstance(obj, LocalInclude):
- p = obj.path
includes = self._paths_to_includes.setdefault(reldir, [])
-
- if p.startswith('/'):
- includes.append(os.path.join('$(TopSrcDir)', p[1:]))
- else:
- includes.append(os.path.join('$(TopSrcDir)', reldir, p))
+ includes.append(obj.path.full_path)
# Just acknowledge everything.
return True
diff --git a/python/mozbuild/mozbuild/frontend/context.py b/python/mozbuild/mozbuild/frontend/context.py
index 51991237b2e..34fec486b83 100644
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -1077,11 +1077,6 @@ VARIABLES = {
This variable only has an effect when building with MSVC.
""", None),
- 'GENERATED_INCLUDES' : (StrictOrderingOnAppendList, list,
- """Directories generated by the build system to be searched for include
- files by the compiler.
- """, None),
-
'HOST_SOURCES': (ContextDerivedTypedList(SourcePath, StrictOrderingOnAppendList), list,
"""Source code files to compile with the host compiler.
@@ -1169,7 +1164,7 @@ VARIABLES = {
"""List of system libraries for host programs and libraries.
""", None),
- 'LOCAL_INCLUDES': (StrictOrderingOnAppendList, list,
+ 'LOCAL_INCLUDES': (ContextDerivedTypedList(Path, StrictOrderingOnAppendList), list,
"""Additional directories to be searched for include files by the compiler.
""", None),
@@ -2110,6 +2105,16 @@ DEPRECATION_HINTS = {
GENERATED_SOURCES += [ 'foo.cpp']
''',
+
+ 'GENERATED_INCLUDES': '''
+ Please use
+
+ LOCAL_INCLUDES += [ '!foo' ]
+
+ instead of
+
+ GENERATED_INCLUDES += [ 'foo' ]
+ ''',
}
# Make sure that all template variables have a deprecation hint.
diff --git a/python/mozbuild/mozbuild/frontend/data.py b/python/mozbuild/mozbuild/frontend/data.py
index 4352c96db70..358b94c7499 100644
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -648,18 +648,6 @@ class LocalInclude(ContextDerived):
self.path = path
-class GeneratedInclude(ContextDerived):
- """Describes an individual generated include path."""
-
- __slots__ = (
- 'path',
- )
-
- def __init__(self, context, path):
- ContextDerived.__init__(self, context)
-
- self.path = path
-
class PerSourceFlag(ContextDerived):
"""Describes compiler flags specified for individual source files."""
diff --git a/python/mozbuild/mozbuild/frontend/emitter.py b/python/mozbuild/mozbuild/frontend/emitter.py
index 6370fd7e2e2..64b33ba0a6c 100644
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -38,7 +38,6 @@ from .data import (
FinalTargetFiles,
GeneratedEventWebIDLFile,
GeneratedFile,
- GeneratedInclude,
GeneratedSources,
GeneratedWebIDLFile,
ExampleWebIDLInterface,
@@ -659,7 +658,6 @@ class TreeMetadataEmitter(LoggingMixin):
('GENERATED_EVENTS_WEBIDL_FILES', GeneratedEventWebIDLFile),
('GENERATED_WEBIDL_FILES', GeneratedWebIDLFile),
('IPDL_SOURCES', IPDLFile),
- ('GENERATED_INCLUDES', GeneratedInclude),
('PREPROCESSED_TEST_WEBIDL_FILES', PreprocessedTestWebIDLFile),
('PREPROCESSED_WEBIDL_FILES', PreprocessedWebIDLFile),
('TEST_WEBIDL_FILES', TestWebIDLFile),
@@ -671,17 +669,11 @@ class TreeMetadataEmitter(LoggingMixin):
yield klass(context, name)
for local_include in context.get('LOCAL_INCLUDES', []):
- if local_include.startswith('/'):
- path = context.config.topsrcdir
- relative_include = local_include[1:]
- else:
- path = context.srcdir
- relative_include = local_include
-
- actual_include = os.path.join(path, relative_include)
- if not os.path.exists(actual_include):
+ if (not isinstance(local_include, ObjDirPath) and
+ not os.path.exists(local_include.full_path)):
raise SandboxValidationError('Path specified in LOCAL_INCLUDES '
- 'does not exist: %s (resolved to %s)' % (local_include, actual_include), context)
+ 'does not exist: %s (resolved to %s)' % (local_include,
+ local_include.full_path), context)
yield LocalInclude(context, local_include)
final_target_files = context.get('FINAL_TARGET_FILES')
diff --git a/python/mozbuild/mozbuild/frontend/gyp_reader.py b/python/mozbuild/mozbuild/frontend/gyp_reader.py
index 4b29ba6a628..84724d3b72f 100644
--- a/python/mozbuild/mozbuild/frontend/gyp_reader.py
+++ b/python/mozbuild/mozbuild/frontend/gyp_reader.py
@@ -221,10 +221,10 @@ def read_from_gyp(config, path, output, vars, non_unified_sources = set()):
# Add some features to all contexts. Put here in case LOCAL_INCLUDES
# order matters.
context['LOCAL_INCLUDES'] += [
+ '!/ipc/ipdl/_ipdlheaders',
'/ipc/chromium/src',
'/ipc/glue',
]
- context['GENERATED_INCLUDES'] += ['/ipc/ipdl/_ipdlheaders']
# These get set via VC project file settings for normal GYP builds.
if config.substs['OS_TARGET'] == 'WINNT':
context['DEFINES']['UNICODE'] = True
diff --git a/python/mozbuild/mozbuild/test/backend/data/generated_includes/moz.build b/python/mozbuild/mozbuild/test/backend/data/generated_includes/moz.build
index b4c71617b90..876a842eeb3 100644
--- a/python/mozbuild/mozbuild/test/backend/data/generated_includes/moz.build
+++ b/python/mozbuild/mozbuild/test/backend/data/generated_includes/moz.build
@@ -2,4 +2,4 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
-GENERATED_INCLUDES += ['/bar/baz', 'foo']
+LOCAL_INCLUDES += ['!/bar/baz', '!foo']
diff --git a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
index 56ca2ac48bc..ff6767e49f0 100644
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -610,7 +610,7 @@ class TestRecursiveMakeBackend(BackendTester):
lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
expected = [
- 'LOCAL_INCLUDES += -I$(topsrcdir)/bar/baz',
+ 'LOCAL_INCLUDES += -I$(srcdir)/bar/baz',
'LOCAL_INCLUDES += -I$(srcdir)/foo',
]
@@ -627,7 +627,7 @@ class TestRecursiveMakeBackend(BackendTester):
topobjdir = env.topobjdir.replace('\\', '/')
expected = [
- 'LOCAL_INCLUDES += -I%s/bar/baz' % topobjdir,
+ 'LOCAL_INCLUDES += -Ibar/baz',
'LOCAL_INCLUDES += -Ifoo',
]
diff --git a/python/mozbuild/mozbuild/test/frontend/data/generated_includes/moz.build b/python/mozbuild/mozbuild/test/frontend/data/generated_includes/moz.build
index b4c71617b90..876a842eeb3 100644
--- a/python/mozbuild/mozbuild/test/frontend/data/generated_includes/moz.build
+++ b/python/mozbuild/mozbuild/test/frontend/data/generated_includes/moz.build
@@ -2,4 +2,4 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
-GENERATED_INCLUDES += ['/bar/baz', 'foo']
+LOCAL_INCLUDES += ['!/bar/baz', '!foo']
diff --git a/python/mozbuild/mozbuild/test/frontend/test_emitter.py b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
index e46191ad63b..4cd0fd14947 100644
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -18,7 +18,6 @@ from mozbuild.frontend.data import (
DirectoryTraversal,
Exports,
GeneratedFile,
- GeneratedInclude,
GeneratedSources,
HostDefines,
HostSources,
@@ -647,15 +646,33 @@ class TestEmitterBasic(unittest.TestCase):
self.assertEqual(local_includes, expected)
+ local_includes = [o.path.full_path
+ for o in objs if isinstance(o, LocalInclude)]
+ expected = [
+ mozpath.join(reader.config.topsrcdir, 'bar/baz'),
+ mozpath.join(reader.config.topsrcdir, 'foo'),
+ ]
+
+ self.assertEqual(local_includes, expected)
+
def test_generated_includes(self):
"""Test that GENERATED_INCLUDES is emitted correctly."""
reader = self.reader('generated_includes')
objs = self.read_topsrcdir(reader)
- generated_includes = [o.path for o in objs if isinstance(o, GeneratedInclude)]
+ generated_includes = [o.path for o in objs if isinstance(o, LocalInclude)]
expected = [
- '/bar/baz',
- 'foo',
+ '!/bar/baz',
+ '!foo',
+ ]
+
+ self.assertEqual(generated_includes, expected)
+
+ generated_includes = [o.path.full_path
+ for o in objs if isinstance(o, LocalInclude)]
+ expected = [
+ mozpath.join(reader.config.topobjdir, 'bar/baz'),
+ mozpath.join(reader.config.topobjdir, 'foo'),
]
self.assertEqual(generated_includes, expected)
diff --git a/security/manager/pki/moz.build b/security/manager/pki/moz.build
index a29e6ca6785..826c7b4dbbb 100644
--- a/security/manager/pki/moz.build
+++ b/security/manager/pki/moz.build
@@ -19,8 +19,8 @@ UNIFIED_SOURCES += [
'nsPKIModule.cpp',
]
-GENERATED_INCLUDES += [
- '/dist/public/nss',
+LOCAL_INCLUDES += [
+ '!/dist/public/nss',
]
FINAL_LIBRARY = 'xul'
diff --git a/security/manager/ssl/moz.build b/security/manager/ssl/moz.build
index 59a47bca666..66639347aed 100644
--- a/security/manager/ssl/moz.build
+++ b/security/manager/ssl/moz.build
@@ -161,8 +161,8 @@ LOCAL_INCLUDES += [
'/security/pkix/include',
]
-GENERATED_INCLUDES += [
- '/dist/public/nss',
+LOCAL_INCLUDES += [
+ '!/dist/public/nss',
]
if CONFIG['NSS_DISABLE_DBM']:
diff --git a/settings.gradle b/settings.gradle
index f37309b0589..db0e215ef37 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -21,14 +21,32 @@ if (json.substs.MOZ_BUILD_APP != 'mobile/android') {
throw new GradleException("Building with Gradle is only supported for Fennec, i.e., MOZ_BUILD_APP == 'mobile/android'.");
}
+def srcdir = { dst, src ->
+ def d = java.nio.file.Paths.get("${json.topobjdir}/gradle/${dst}")
+ def s = java.nio.file.Paths.get("${json.topsrcdir}/${src}")
+ try {
+ java.nio.file.Files.createDirectories(d.getParent())
+ } catch (java.nio.file.FileAlreadyExistsException e) {
+ // Do nothing.
+ }
+ try {
+ java.nio.file.Files.createSymbolicLink(d, s)
+ } catch (java.nio.file.FileAlreadyExistsException e) {
+ // Do nothing.
+ }
+}
+
+// Since base/ doesn't have the correct package prefix directory structure, we
+// still need to symlink.
+srcdir('base/src/org/mozilla/gecko', 'mobile/android/base')
+
include ':app'
include ':base'
include ':omnijar'
include ':thirdparty'
-def gradleRoot = new File("${json.topobjdir}/mobile/android/gradle")
project(':app').projectDir = new File("${json.topsrcdir}/mobile/android/app")
-project(':base').projectDir = new File(gradleRoot, 'base')
+project(':base').projectDir = new File("${json.topsrcdir}/mobile/android/base")
project(':omnijar').projectDir = new File("${json.topsrcdir}/mobile/android/app/omnijar")
project(':thirdparty').projectDir = new File("${json.topsrcdir}/mobile/android/thirdparty")
diff --git a/testing/specialpowers/content/specialpowersAPI.js b/testing/specialpowers/content/specialpowersAPI.js
index 5347acc57bd..7916a30b020 100644
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -1447,14 +1447,6 @@ SpecialPowersAPI.prototype = {
Services.console.reset();
},
- getMaxLineBoxWidth: function(window) {
- return this._getMUDV(window).maxLineBoxWidth;
- },
-
- setMaxLineBoxWidth: function(window, width) {
- this._getMUDV(window).changeMaxLineBoxWidth(width);
- },
-
getFullZoom: function(window) {
return this._getMUDV(window).fullZoom;
},
diff --git a/testing/talos/talos/output.py b/testing/talos/talos/output.py
index cd3316a61ba..adca9b426c2 100755
--- a/testing/talos/talos/output.py
+++ b/testing/talos/talos/output.py
@@ -517,15 +517,23 @@ class PerfherderOutput(Output):
test.test_config['filters'])
vals.extend([[i['value'], j] for i, j in filtered_results])
for val, page in filtered_results:
+ measurement_metadata = {}
+ if test.test_config.get('lower_is_better') is not None:
+ measurement_metadata['lowerIsBetter'] = test.test_config['lower_is_better']
+ if test.test_config.get('unit'):
+ measurement_metadata['unit'] = test.test_config['unit']
if page == 'NULL':
summary['subtests'][test.name()] = val
+ summary['subtests'][test.name()].update(measurement_metadata)
else:
summary['subtests'][page] = val
-
+ summary['subtests'][page].update(measurement_metadata)
suite_summary = self.construct_results(vals,
testname=test.name())
summary['suite'] = suite_summary
+ if test.test_config.get('lower_is_better') is not None:
+ summary['lowerIsBetter'] = test.test_config['lower_is_better']
test_result['summary'] = summary
for result, values in results.items():
diff --git a/testing/talos/talos/test.py b/testing/talos/talos/test.py
index fc41eac75c7..039622ba8cd 100644
--- a/testing/talos/talos/test.py
+++ b/testing/talos/talos/test.py
@@ -30,6 +30,7 @@ class Test(object):
keys = []
desktop = True
filters = filter.ignore_first.prepare(1) + filter.median.prepare()
+ lower_is_better = True
@classmethod
def name(cls):
@@ -137,6 +138,7 @@ class ts_paint(TsBase):
rss = False
mainthread = False
responsiveness = False
+ unit = 'ms'
@register_test()
@@ -159,6 +161,7 @@ class sessionrestore(TsBase):
reinstall = ['sessionstore.js', 'sessionCheckpoints.json']
# Restore the session
preferences = {'browser.startup.page': 3}
+ unit = 'ms'
@register_test()
@@ -189,6 +192,7 @@ class tpaint(TsBase):
sps_profile_entries = 2000000
tpmozafterpaint = True
filters = filter.ignore_first.prepare(5) + filter.median.prepare()
+ unit = 'ms'
@register_test()
@@ -204,6 +208,7 @@ class tresize(TsBase):
sps_profile_entries = 1000000
tpmozafterpaint = True
filters = filter.ignore_first.prepare(5) + filter.median.prepare()
+ unit = 'ms'
# Media Test
@@ -240,7 +245,8 @@ class PageloaderTest(Test):
'timeout', 'shutdown', 'responsiveness', 'profile_path',
'xperf_providers', 'xperf_user_providers', 'xperf_stackwalk',
'filters', 'preferences', 'extensions', 'setup', 'cleanup',
- 'test_name_extension']
+ 'test_name_extension', 'lower_is_better', 'unit']
+ unit = 'ms'
@register_test()
@@ -386,6 +392,7 @@ class glterrain(PageloaderTest):
'docshell.event_starvation_delay_hint': 1,
'dom.send_after_paint_to_content': False}
filters = filter.ignore_first.prepare(1) + filter.median.prepare()
+ unit = 'frame interval'
@register_test()
@@ -475,6 +482,7 @@ class tp5o_scroll(PageloaderTest):
'docshell.event_starvation_delay_hint': 1,
'dom.send_after_paint_to_content': False}
filters = filter.ignore_first.prepare(1) + filter.median.prepare()
+ unit = '1/FPS'
@register_test()
@@ -494,6 +502,8 @@ class v8_7(PageloaderTest):
tpmozafterpaint = False
preferences = {'dom.send_after_paint_to_content': False}
filters = filter.v8_subtest.prepare()
+ unit = 'score'
+ lower_is_better = False
@register_test()
@@ -527,11 +537,14 @@ class tcanvasmark(PageloaderTest):
tpmozafterpaint = False
preferences = {'dom.send_after_paint_to_content': False}
filters = filter.ignore_first.prepare(1) + filter.median.prepare()
+ unit = 'score'
+ lower_is_better = False
class dromaeo(PageloaderTest):
"""abstract base class for dramaeo tests"""
filters = filter.dromaeo.prepare()
+ lower_is_better = False
@register_test()
diff --git a/toolkit/components/extensions/Extension.jsm b/toolkit/components/extensions/Extension.jsm
index 4e3d75be089..4df110cba30 100644
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -4,7 +4,7 @@
"use strict";
-this.EXPORTED_SYMBOLS = ["Extension"];
+this.EXPORTED_SYMBOLS = ["Extension", "ExtensionData"];
/*
* This file is the main entry point for extensions. When an extension
@@ -33,8 +33,12 @@ XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "OS",
+ "resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Task",
+ "resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/ExtensionManagement.jsm");
@@ -58,6 +62,7 @@ var {
MessageBroker,
Messenger,
injectAPI,
+ extend,
flushJarCache,
} = ExtensionUtils;
@@ -322,13 +327,335 @@ var GlobalManager = {
},
};
+// Represents the data contained in an extension, contained either
+// in a directory or a zip file, which may or may not be installed.
+// This class implements the functionality of the Extension class,
+// primarily related to manifest parsing and localization, which is
+// useful prior to extension installation or initialization.
+//
+// No functionality of this class is guaranteed to work before
+// |readManifest| has been called, and completed.
+this.ExtensionData = function(rootURI)
+{
+ this.rootURI = rootURI;
+
+ this.manifest = null;
+ this.id = null;
+ // Map(locale-name -> message-map)
+ // Contains a key for each loaded locale, each of which is a
+ // JSON-compatible object with a property for each message
+ // in that locale.
+ this.localeMessages = new Map();
+ this.selectedLocale = null;
+ this._promiseLocales = null;
+
+ this.errors = [];
+}
+
+ExtensionData.prototype = {
+ get logger() {
+ let id = this.id || "";
+ return Log.repository.getLogger(LOGGER_ID_BASE + id);
+ },
+
+ // Report an error about the extension's manifest file.
+ manifestError(message) {
+ this.packagingError(`Reading manifest: ${message}`);
+ },
+
+ // Report an error about the extension's general packaging.
+ packagingError(message) {
+ this.errors.push(message);
+ this.logger.error(`Loading extension '${this.id}': ${message}`);
+ },
+
+ // https://developer.chrome.com/extensions/i18n
+ localizeMessage(message, substitutions, locale = this.selectedLocale) {
+ let messages = {};
+ if (this.localeMessages.has(locale)) {
+ messages = this.localeMessages.get(locale);
+ }
+
+ if (message in messages) {
+ let str = messages[message].message;
+
+ if (!substitutions) {
+ substitutions = [];
+ } else if (!Array.isArray(substitutions)) {
+ substitutions = [substitutions];
+ }
+
+ // https://developer.chrome.com/extensions/i18n-messages
+ // |str| may contain substrings of the form $1 or $PLACEHOLDER$.
+ // In the former case, we replace $n with substitutions[n - 1].
+ // In the latter case, we consult the placeholders array.
+ // The placeholder may itself use $n to refer to substitutions.
+ let replacer = (matched, name) => {
+ if (name.length == 1 && name[0] >= '1' && name[0] <= '9') {
+ return substitutions[parseInt(name) - 1];
+ } else {
+ let content = messages[message].placeholders[name].content;
+ if (content[0] == '$') {
+ return replacer(matched, content[1]);
+ } else {
+ return content;
+ }
+ }
+ };
+ return str.replace(/\$([A-Za-z_@]+)\$/, replacer)
+ .replace(/\$([0-9]+)/, replacer)
+ .replace(/\$\$/, "$");
+ }
+
+ // Check for certain pre-defined messages.
+ if (message == "@@extension_id") {
+ if ("uuid" in this) {
+ // Per Chrome, this isn't available before an ID is guaranteed
+ // to have been assigned, namely, in manifest files.
+ // This should only be present in instances of the |Extension|
+ // subclass.
+ return this.uuid;
+ }
+ } else if (message == "@@ui_locale") {
+ return Locale.getLocale();
+ } else if (message == "@@bidi_dir") {
+ return "ltr"; // FIXME
+ }
+
+ Cu.reportError(`Unknown localization message ${message}`);
+ return "??";
+ },
+
+ // Localize a string, replacing all |__MSG_(.*)__| tokens with the
+ // matching string from the current locale, as determined by
+ // |this.selectedLocale|.
+ //
+ // This may not be called before calling either |initLocale| or
+ // |initAllLocales|.
+ localize(str, locale = this.selectedLocale) {
+ if (!str) {
+ return str;
+ }
+
+ return str.replace(/__MSG_([A-Za-z0-9@_]+?)__/g, (matched, message) => {
+ return this.localizeMessage(message, [], locale);
+ });
+ },
+
+ // If a "default_locale" is specified in that manifest, returns it
+ // as a Gecko-compatible locale string. Otherwise, returns null.
+ get defaultLocale() {
+ if ("default_locale" in this.manifest) {
+ return this.normalizeLocaleCode(this.manifest.default_locale);
+ }
+
+ return null;
+ },
+
+ // Normalizes a Chrome-compatible locale code to the appropriate
+ // Gecko-compatible variant. Currently, this means simply
+ // replacing underscores with hyphens.
+ normalizeLocaleCode(locale) {
+ return String.replace(locale, /_/g, "-");
+ },
+
+ readDirectory: Task.async(function* (path) {
+ if (this.rootURI instanceof Ci.nsIFileURL) {
+ let uri = NetUtil.newURI(this.rootURI.resolve("./" + path));
+ let fullPath = uri.QueryInterface(Ci.nsIFileURL).file.path;
+
+ let iter = new OS.File.DirectoryIterator(fullPath);
+ let results = [];
+
+ try {
+ yield iter.forEach(entry => {
+ results.push(entry);
+ });
+ } catch (e) {}
+ iter.close();
+
+ // Always return a list, even if the directory does not exist (or is
+ // not a directory) for symmetry with the ZipReader behavior.
+ return results;
+ }
+
+ if (!(this.rootURI instanceof Ci.nsIJARURI &&
+ this.rootURI.JARFile instanceof Ci.nsIFileURL)) {
+ throw Error("Invalid extension root URL");
+ }
+
+ // FIXME: We need a way to do this without main thread IO.
+
+ let file = this.rootURI.JARFile.file;
+ let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(Ci.nsIZipReader);
+ try {
+ zipReader.open(file);
+
+ let results = [];
+
+ // Normalize the directory path.
+ path = path.replace(/\/\/+/g, "/").replace(/^\/|\/$/g, "") + "/";
+
+ // Escape pattern metacharacters.
+ let pattern = path.replace(/[[\]()?*~|$\\]/g, "\\$&");
+
+ let enumerator = zipReader.findEntries(pattern + "*");
+ while (enumerator.hasMore()) {
+ let name = enumerator.getNext();
+ if (!name.startsWith(path)) {
+ throw new Error("Unexpected ZipReader entry");
+ }
+
+ // The enumerator returns the full path of all entries.
+ // Trim off the leading path, and filter out entries from
+ // subdirectories.
+ name = name.slice(path.length);
+ if (name && !/\/./.test(name)) {
+ results.push({
+ name: name.replace("/", ""),
+ isDir: name.endsWith("/"),
+ });
+ }
+ }
+
+ return results;
+ } finally {
+ zipReader.close();
+ }
+ }),
+
+ readJSON(path) {
+ return new Promise((resolve, reject) => {
+ let uri = this.rootURI.resolve(`./${path}`);
+
+ NetUtil.asyncFetch({uri, loadUsingSystemPrincipal: true}, (inputStream, status) => {
+ if (!Components.isSuccessCode(status)) {
+ reject(new Error(status));
+ return;
+ }
+ try {
+ let text = NetUtil.readInputStreamToString(inputStream, inputStream.available());
+ resolve(JSON.parse(text));
+ } catch (e) {
+ reject(e);
+ }
+ });
+ });
+ },
+
+ // Reads the extension's |manifest.json| file, and stores its
+ // parsed contents in |this.manifest|.
+ readManifest() {
+ return this.readJSON("manifest.json").then(manifest => {
+ this.manifest = manifest;
+
+ try {
+ this.id = this.manifest.applications.gecko.id;
+ } catch (e) {}
+
+ if (typeof this.id != "string") {
+ this.manifestError("Missing required `applications.gecko.id` property");
+ }
+
+ return manifest;
+ });
+ },
+
+ // Reads the locale file for the given Gecko-compatible locale code, and
+ // stores its parsed contents in |this.localeMessages.get(locale)|.
+ readLocaleFile: Task.async(function* (locale) {
+ let locales = yield this.promiseLocales();
+ let dir = locales.get(locale);
+ let file = `_locales/${dir}/messages.json`;
+
+ let messages = {};
+ try {
+ messages = yield this.readJSON(file);
+ } catch (e) {
+ this.packagingError(`Loading locale file ${file}: ${e}`);
+ }
+
+ this.localeMessages.set(locale, messages);
+ return messages;
+ }),
+
+ // Reads the list of locales available in the extension, and returns a
+ // Promise which resolves to a Map upon completion.
+ // Each map key is a Gecko-compatible locale code, and each value is the
+ // "_locales" subdirectory containing that locale:
+ //
+ // Map(gecko-locale-code -> locale-directory-name)
+ promiseLocales() {
+ if (!this._promiseLocales) {
+ this._promiseLocales = Task.spawn(function* () {
+ let locales = new Map();
+
+ let entries = yield this.readDirectory("_locales");
+ for (let file of entries) {
+ if (file.isDir) {
+ let locale = this.normalizeLocaleCode(file.name);
+ locales.set(locale, file.name);
+ }
+ }
+
+ return locales;
+ }.bind(this));
+ }
+
+ return this._promiseLocales;
+ },
+
+ // Reads the locale messages for all locales, and returns a promise which
+ // resolves to a Map of locale messages upon completion. Each key in the map
+ // is a Gecko-compatible locale code, and each value is a locale data object
+ // as returned by |readLocaleFile|.
+ initAllLocales: Task.async(function* () {
+ let locales = yield this.promiseLocales();
+
+ yield Promise.all(Array.from(locales.keys(),
+ locale => this.readLocaleFile(locale)));
+
+ let defaultLocale = this.defaultLocale;
+ if (defaultLocale) {
+ if (!locales.has(defaultLocale)) {
+ this.manifestError('Value for "default_locale" property must correspond to ' +
+ 'a directory in "_locales/". Not found: ' +
+ JSON.stringify(`_locales/${default_locale}/`));
+ }
+ } else if (this.localeMessages.size) {
+ this.manifestError('The "default_locale" property is required when a ' +
+ '"_locales/" directory is present.');
+ }
+
+ return this.localeMessages;
+ }),
+
+ // Reads the locale file for the given Gecko-compatible locale code, or the
+ // default locale if no locale code is given, and sets it as the currently
+ // selected locale on success.
+ //
+ // If no locales are unavailable, resolves to |null|.
+ initLocale: Task.async(function* (locale = this.defaultLocale) {
+ if (locale == null) {
+ return null;
+ }
+
+ let localeData = yield this.readLocaleFile(locale);
+
+ this.selectedLocale = locale;
+ return localeData;
+ }),
+};
+
// We create one instance of this class per extension. |addonData|
// comes directly from bootstrap.js when initializing.
this.Extension = function(addonData)
{
+ ExtensionData.call(this, addonData.resourceURI);
+
let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
let uuid = uuidGenerator.generateUUID().number;
- uuid = uuid.substring(1, uuid.length - 1); // Strip of { and } off the UUID.
+ uuid = uuid.slice(1, -1); // Strip of { and } off the UUID.
this.uuid = uuid;
if (addonData.cleanupFile) {
@@ -341,9 +668,6 @@ this.Extension = function(addonData)
this.id = addonData.id;
this.baseURI = Services.io.newURI("moz-extension://" + uuid, null, null);
this.baseURI.QueryInterface(Ci.nsIURL);
- this.manifest = null;
- this.localeMessages = null;
- this.logger = Log.repository.getLogger(LOGGER_ID_BASE + this.id.replace(/\./g, "-"));
this.principal = this.createPrincipal();
this.views = new Set();
@@ -475,7 +799,7 @@ this.Extension.generate = function(id, data)
});
}
-Extension.prototype = {
+Extension.prototype = extend(Object.create(ExtensionData.prototype), {
on(hook, f) {
return this.emitter.on(hook, f);
},
@@ -505,11 +829,6 @@ Extension.prototype = {
return common == this.baseURI.spec;
},
- // Report an error about the extension's manifest file.
- manifestError(message) {
- this.logger.error(`Loading extension '${this.id}': ${message}`);
- },
-
// Representation of the extension to send to content
// processes. This should include anything the content process might
// need.
@@ -526,147 +845,6 @@ Extension.prototype = {
};
},
- // https://developer.chrome.com/extensions/i18n
- localizeMessage(message, substitutions) {
- if (message in this.localeMessages) {
- let str = this.localeMessages[message].message;
-
- if (!substitutions) {
- substitutions = [];
- }
- if (!Array.isArray(substitutions)) {
- substitutions = [substitutions];
- }
-
- // https://developer.chrome.com/extensions/i18n-messages
- // |str| may contain substrings of the form $1 or $PLACEHOLDER$.
- // In the former case, we replace $n with substitutions[n - 1].
- // In the latter case, we consult the placeholders array.
- // The placeholder may itself use $n to refer to substitutions.
- let replacer = (matched, name) => {
- if (name.length == 1 && name[0] >= '1' && name[0] <= '9') {
- return substitutions[parseInt(name) - 1];
- } else {
- let content = this.localeMessages[message].placeholders[name].content;
- if (content[0] == '$') {
- return replacer(matched, content[1]);
- } else {
- return content;
- }
- }
- };
- return str.replace(/\$([A-Za-z_@]+)\$/, replacer)
- .replace(/\$([0-9]+)/, replacer)
- .replace(/\$\$/, "$");
- }
-
- // Check for certain pre-defined messages.
- if (message == "@@extension_id") {
- return this.id;
- } else if (message == "@@ui_locale") {
- return Locale.getLocale();
- } else if (message == "@@bidi_dir") {
- return "ltr"; // FIXME
- }
-
- Cu.reportError(`Unknown localization message ${message}`);
- return "??";
- },
-
- localize(str) {
- if (!str) {
- return str;
- }
-
- if (str.startsWith("__MSG_") && str.endsWith("__")) {
- let message = str.substring("__MSG_".length, str.length - "__".length);
- return this.localizeMessage(message);
- }
-
- return str;
- },
-
- readJSON(uri) {
- return new Promise((resolve, reject) => {
- NetUtil.asyncFetch({uri, loadUsingSystemPrincipal: true}, (inputStream, status) => {
- if (!Components.isSuccessCode(status)) {
- reject(status);
- return;
- }
- let text = NetUtil.readInputStreamToString(inputStream, inputStream.available());
- try {
- resolve(JSON.parse(text));
- } catch (e) {
- reject(e);
- }
- });
- });
- },
-
- readManifest() {
- let manifestURI = Services.io.newURI("manifest.json", null, this.baseURI);
- return this.readJSON(manifestURI);
- },
-
- readLocaleFile(locale) {
- let dir = locale.replace("-", "_");
- let url = `_locales/${dir}/messages.json`;
- let uri = Services.io.newURI(url, null, this.baseURI);
- return this.readJSON(uri);
- },
-
- readLocaleMessages() {
- let locales = [];
-
- // We need to base this off of this.addonData.resourceURI rather
- // than baseURI since baseURI is a moz-extension URI, which always
- // QIs to nsIFileURL.
- let uri = Services.io.newURI("_locales", null, this.addonData.resourceURI);
- if (uri instanceof Ci.nsIFileURL) {
- let file = uri.file;
- let enumerator;
- try {
- enumerator = file.directoryEntries;
- } catch (e) {
- return {};
- }
- while (enumerator.hasMoreElements()) {
- let file = enumerator.getNext().QueryInterface(Ci.nsIFile);
- locales.push({
- name: file.leafName,
- locales: [file.leafName.replace("_", "-")]
- });
- }
- }
-
- if (uri instanceof Ci.nsIJARURI && uri.JARFile instanceof Ci.nsIFileURL) {
- let file = uri.JARFile.file;
- let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(Ci.nsIZipReader);
- try {
- zipReader.open(file);
- let enumerator = zipReader.findEntries("_locales/*");
- while (enumerator.hasMore()) {
- let name = enumerator.getNext();
- let match = name.match(new RegExp("_locales\/([^/]*)"));
- if (match && match[1]) {
- locales.push({
- name: match[1],
- locales: [match[1].replace("_", "-")]
- });
- }
- }
- } finally {
- zipReader.close();
- }
- }
-
- let locale = Locale.findClosestLocale(locales);
- if (locale) {
- return this.readLocaleFile(locale.name).catch(() => {});
- }
- return {};
- },
-
broadcast(msg, data) {
return new Promise(resolve => {
let count = Services.ppmm.childCount;
@@ -723,6 +901,24 @@ Extension.prototype = {
this.onShutdown.delete(obj);
},
+ // Reads the locale file for the given Gecko-compatible locale code, or if
+ // no locale is given, the available locale closest to the UI locale.
+ // Sets the currently selected locale on success.
+ initLocale: Task.async(function* (locale = undefined) {
+ if (locale === undefined) {
+ let locales = yield this.promiseLocales();
+
+ let localeList = Object.keys(locales).map(locale => {
+ return { name: locale, locales: [locale] };
+ });
+
+ let match = Locale.findClosestLocale(localeList);
+ locale = match ? match.name : this.defaultLocale;
+ }
+
+ return ExtensionData.prototype.initLocale.call(this, locale);
+ }),
+
startup() {
try {
ExtensionManagement.startupExtension(this.uuid, this.addonData.resourceURI, this);
@@ -730,21 +926,20 @@ Extension.prototype = {
return Promise.reject(e);
}
- return Promise.all([this.readManifest(), this.readLocaleMessages()]).then(([manifest, messages]) => {
+ return this.readManifest().then(() => {
+ return this.initLocale();
+ }).then(() => {
if (this.hasShutdown) {
return;
}
GlobalManager.init(this);
- this.manifest = manifest;
- this.localeMessages = messages;
-
Management.emit("startup", this);
- return this.runManifest(manifest);
+ return this.runManifest(this.manifest);
}).catch(e => {
- dump(`Extension error: ${e} ${e.fileName}:${e.lineNumber}\n`);
+ dump(`Extension error: ${e} ${e.filename}:${e.lineNumber}\n`);
Cu.reportError(e);
throw e;
});
@@ -808,5 +1003,5 @@ Extension.prototype = {
get name() {
return this.localize(this.manifest.name);
},
-};
+});
diff --git a/toolkit/components/extensions/ExtensionUtils.jsm b/toolkit/components/extensions/ExtensionUtils.jsm
index c1cb5562f19..c7b7b90bcc2 100644
--- a/toolkit/components/extensions/ExtensionUtils.jsm
+++ b/toolkit/components/extensions/ExtensionUtils.jsm
@@ -64,6 +64,21 @@ function runSafe(context, f, ...args)
return runSafeWithoutClone(f, ...args);
}
+// Extend the object |obj| with the property descriptors of each object in
+// |args|.
+function extend(obj, ...args) {
+ for (let arg of args) {
+ let props = [...Object.getOwnPropertyNames(arg),
+ ...Object.getOwnPropertySymbols(arg)];
+ for (let prop of props) {
+ let descriptor = Object.getOwnPropertyDescriptor(arg, prop);
+ Object.defineProperty(obj, prop, descriptor);
+ }
+ }
+
+ return obj;
+}
+
// Similar to a WeakMap, but returns a particular default value for
// |get| if a key is not present.
function DefaultWeakMap(defaultValue)
@@ -602,5 +617,6 @@ this.ExtensionUtils = {
injectAPI,
MessageBroker,
Messenger,
+ extend,
flushJarCache,
};
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index 54a000329af..f98e94b2e0c 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -9093,6 +9093,7 @@
},
"READER_MODE_SERIALIZE_DOM_MS": {
"expires_in_version": "50",
+ "alert_emails": ["mleibovic@mozilla.com"],
"kind": "exponential",
"high": "5000",
"n_buckets": 15,
@@ -9100,6 +9101,7 @@
},
"READER_MODE_WORKER_PARSE_MS": {
"expires_in_version": "50",
+ "alert_emails": ["mleibovic@mozilla.com"],
"kind": "exponential",
"high": "10000",
"n_buckets": 30,
@@ -9107,6 +9109,7 @@
},
"READER_MODE_DOWNLOAD_MS": {
"expires_in_version": "50",
+ "alert_emails": ["mleibovic@mozilla.com"],
"kind": "exponential",
"low": 50,
"high": "40000",
@@ -9115,16 +9118,25 @@
},
"READER_MODE_PARSE_RESULT" : {
"expires_in_version": "50",
+ "alert_emails": ["mleibovic@mozilla.com"],
"kind": "enumerated",
"n_values": 5,
"description": "The result of trying to parse a document to show in reader view (0=Success, 1=Error too many elements, 2=Error in worker, 3=Error no article)"
},
"READER_MODE_DOWNLOAD_RESULT" : {
"expires_in_version": "50",
+ "alert_emails": ["mleibovic@mozilla.com"],
"kind": "enumerated",
"n_values": 5,
"description": "The result of trying to download a document to show in reader view (0=Success, 1=Error XHR, 2=Error no document)"
},
+ "FENNEC_READER_VIEW_BUTTON" : {
+ "expires_in_version": "50",
+ "alert_emails": ["mleibovic@mozilla.com"],
+ "kind": "enumerated",
+ "n_values": 10,
+ "description": "Bug 1219240: Measures user interaction with the reader view button (0=Button hidden, 1=Button shown, 2=Tap to enter reader view, 3=Tap to exit reader view, 4=Long tap)"
+ },
"PERMISSIONS_SQL_CORRUPTED": {
"expires_in_version": "never",
"kind": "count",
diff --git a/toolkit/content/license.html b/toolkit/content/license.html
index f2aebac3f99..d4bfec7c5c9 100644
--- a/toolkit/content/license.html
+++ b/toolkit/content/license.html
@@ -81,6 +81,7 @@
@@ -2718,6 +2719,36 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
classnames License
+
+
This license applies to the file
+ browser/components/loop/content/shared/libs/classnames-*.js.
+
+
+
+Copyright (c) 2015 Jed Watson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
CodeMirror License
diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
index eb978d7ab70..61316b83741 100644
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -22,6 +22,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "ChromeManifestParser",
"resource://gre/modules/ChromeManifestParser.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
"resource://gre/modules/LightweightThemeManager.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ExtensionData",
+ "resource://gre/modules/Extension.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Locale",
"resource://gre/modules/Locale.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
@@ -828,15 +830,20 @@ function getRDFProperty(aDs, aResource, aProperty) {
/**
* Reads an AddonInternal object from a manifest stream.
*
- * @param aStream
- * An open stream to read the manifest from
+ * @param aUri
+ * A |file:| or |jar:| URL for the manifest
* @return an AddonInternal object
* @throws if the install manifest in the stream is corrupt or could not
* be read
*/
-function loadManifestFromWebManifest(aStream) {
- let decoder = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
- let manifest = decoder.decodeFromStream(aStream, aStream.available());
+var loadManifestFromWebManifest = Task.async(function* loadManifestFromWebManifest(aUri) {
+ // We're passed the URI for the manifest file. Get the URI for its
+ // parent directory.
+ let uri = NetUtil.newURI("./", null, aUri);
+
+ let extension = new ExtensionData(uri);
+
+ let manifest = yield extension.readManifest();
function findProp(obj, current, properties) {
if (properties.length == 0)
@@ -903,30 +910,46 @@ function loadManifestFromWebManifest(aStream) {
addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT;
- addon.defaultLocale = {
- name: getProp("name"),
- description: getOptionalProp("description"),
- creator: null,
- homepageURL: null,
+ function getLocale(aLocale) {
+ let result = {
+ name: extension.localize(getProp("name"), aLocale),
+ description: extension.localize(getOptionalProp("description"), aLocale),
+ creator: null,
+ homepageURL: null,
- developers: null,
- translators: null,
- contributors: null,
+ developers: null,
+ translators: null,
+ contributors: null,
+ locales: [aLocale],
+ };
+ return result;
}
+ // Read the list of available locales, and pre-load messages for
+ // all locales.
+ let locales = yield extension.initAllLocales();
+
+ // If there were any errors loading the extension, bail out now.
+ if (extension.errors.length)
+ throw new Error("Extension is invalid");
+
+ addon.defaultLocale = getLocale(extension.defaultLocale);
+ addon.locales = Array.from(locales.keys(), getLocale);
+
+ delete addon.defaultLocale.locales;
+
addon.targetApplications = [{
id: TOOLKIT_ID,
minVersion: AddonManagerPrivate.webExtensionsMinPlatformVersion,
maxVersion: "*",
}];
- addon.locales = [];
addon.targetPlatforms = [];
addon.userDisabled = false;
addon.softDisabled = addon.blocklistState == Blocklist.STATE_SOFTBLOCKED;
return addon;
-}
+});
/**
* Reads an AddonInternal object from an RDF stream.
@@ -1251,8 +1274,19 @@ var loadManifestFromDir = Task.async(function* loadManifestFromDir(aDir, aInstal
return size;
}
- function loadFromRDF(aFile, aStream) {
- let addon = loadManifestFromRDF(Services.io.newFileURI(aFile), aStream);
+ function loadFromRDF(aUri) {
+ let fis = Cc["@mozilla.org/network/file-input-stream;1"].
+ createInstance(Ci.nsIFileInputStream);
+ fis.init(aUri.file, -1, -1, false);
+ let bis = Cc["@mozilla.org/network/buffered-input-stream;1"].
+ createInstance(Ci.nsIBufferedInputStream);
+ bis.init(fis, 4096);
+ try {
+ var addon = loadManifestFromRDF(aUri, bis);
+ } finally {
+ bis.close();
+ fis.close();
+ }
let iconFile = aDir.clone();
iconFile.append("icon.png");
@@ -1283,32 +1317,21 @@ var loadManifestFromDir = Task.async(function* loadManifestFromDir(aDir, aInstal
"install manifest");
}
- let fis = Cc["@mozilla.org/network/file-input-stream;1"].
- createInstance(Ci.nsIFileInputStream);
- fis.init(file, -1, -1, false);
- let bis = Cc["@mozilla.org/network/buffered-input-stream;1"].
- createInstance(Ci.nsIBufferedInputStream);
- bis.init(fis, 4096);
+ let uri = Services.io.newFileURI(file).QueryInterface(Ci.nsIFileURL);
- try {
- let addon = file.leafName == FILE_WEB_MANIFEST ?
- loadManifestFromWebManifest(bis) :
- loadFromRDF(file, bis);
+ let addon = file.leafName == FILE_WEB_MANIFEST ?
+ yield loadManifestFromWebManifest(uri) :
+ loadFromRDF(uri);
- addon._sourceBundle = aDir.clone();
- addon._installLocation = aInstallLocation;
- addon.size = getFileSize(aDir);
- addon.signedState = yield verifyDirSignedState(aDir, addon);
- addon.appDisabled = !isUsableAddon(addon);
+ addon._sourceBundle = aDir.clone();
+ addon._installLocation = aInstallLocation;
+ addon.size = getFileSize(aDir);
+ addon.signedState = yield verifyDirSignedState(aDir, addon);
+ addon.appDisabled = !isUsableAddon(addon);
- defineSyncGUID(addon);
+ defineSyncGUID(addon);
- return addon;
- }
- finally {
- bis.close();
- fis.close();
- }
+ return addon;
});
/**
@@ -1320,9 +1343,17 @@ var loadManifestFromDir = Task.async(function* loadManifestFromDir(aDir, aInstal
* @throws if the XPI file does not contain a valid install manifest
*/
var loadManifestFromZipReader = Task.async(function* loadManifestFromZipReader(aZipReader, aInstallLocation) {
- function loadFromRDF(aStream) {
- let uri = buildJarURI(aZipReader.file, FILE_RDF_MANIFEST);
- let addon = loadManifestFromRDF(uri, aStream);
+ function loadFromRDF(aUri) {
+ let zis = aZipReader.getInputStream(entry);
+ let bis = Cc["@mozilla.org/network/buffered-input-stream;1"].
+ createInstance(Ci.nsIBufferedInputStream);
+ bis.init(zis, 4096);
+ try {
+ var addon = loadManifestFromRDF(aUri, bis);
+ } finally {
+ bis.close();
+ zis.close();
+ }
if (aZipReader.hasEntry("icon.png")) {
addon.icons[32] = "icon.png";
@@ -1335,7 +1366,7 @@ var loadManifestFromZipReader = Task.async(function* loadManifestFromZipReader(a
// Binary components can only be loaded from unpacked addons.
if (addon.unpack) {
- uri = buildJarURI(aZipReader.file, "chrome.manifest");
+ let uri = buildJarURI(aZipReader.file, "chrome.manifest");
let chromeManifest = ChromeManifestParser.parseSync(uri);
addon.hasBinaryComponents = ChromeManifestParser.hasType(chromeManifest,
"binary-component");
@@ -1352,35 +1383,26 @@ var loadManifestFromZipReader = Task.async(function* loadManifestFromZipReader(a
"install manifest");
}
- let zis = aZipReader.getInputStream(entry);
- let bis = Cc["@mozilla.org/network/buffered-input-stream;1"].
- createInstance(Ci.nsIBufferedInputStream);
- bis.init(zis, 4096);
+ let uri = buildJarURI(aZipReader.file, entry);
- try {
- let addon = entry == FILE_WEB_MANIFEST ?
- loadManifestFromWebManifest(bis) :
- loadFromRDF(bis);
+ let addon = entry == FILE_WEB_MANIFEST ?
+ yield loadManifestFromWebManifest(uri) :
+ loadFromRDF(uri);
- addon._sourceBundle = aZipReader.file;
- addon._installLocation = aInstallLocation;
+ addon._sourceBundle = aZipReader.file;
+ addon._installLocation = aInstallLocation;
- addon.size = 0;
- let entries = aZipReader.findEntries(null);
- while (entries.hasMore())
- addon.size += aZipReader.getEntry(entries.getNext()).realSize;
+ addon.size = 0;
+ let entries = aZipReader.findEntries(null);
+ while (entries.hasMore())
+ addon.size += aZipReader.getEntry(entries.getNext()).realSize;
- addon.signedState = yield verifyZipSignedState(aZipReader.file, addon);
- addon.appDisabled = !isUsableAddon(addon);
+ addon.signedState = yield verifyZipSignedState(aZipReader.file, addon);
+ addon.appDisabled = !isUsableAddon(addon);
- defineSyncGUID(addon);
+ defineSyncGUID(addon);
- return addon;
- }
- finally {
- bis.close();
- zis.close();
- }
+ return addon;
});
/**
diff --git a/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/en/messages.json b/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/en/messages.json
new file mode 100644
index 00000000000..91971760e77
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/en/messages.json
@@ -0,0 +1,10 @@
+{
+ "name": {
+ "message": "foo",
+ "description": "foo"
+ },
+ "desc": {
+ "message": "bar",
+ "description": "bar"
+ }
+}
diff --git a/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/fr/messages.json b/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/fr/messages.json
new file mode 100644
index 00000000000..daeac60bb94
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/addons/webextension_3/_locales/fr/messages.json
@@ -0,0 +1,10 @@
+{
+ "name": {
+ "message": "le foo",
+ "description": "foo"
+ },
+ "desc": {
+ "message": "le bar",
+ "description": "bar"
+ }
+}
diff --git a/toolkit/mozapps/extensions/test/addons/webextension_3/manifest.json b/toolkit/mozapps/extensions/test/addons/webextension_3/manifest.json
new file mode 100644
index 00000000000..d4ccddfea3a
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/addons/webextension_3/manifest.json
@@ -0,0 +1,12 @@
+{
+ "name": "Web Extension __MSG_name__",
+ "description": "Descripton __MSG_desc__ of add-on",
+ "version": "1.0",
+ "manifest_version": 2,
+ "default_locale": "en",
+ "applications": {
+ "gecko": {
+ "id": "webextension3@tests.mozilla.org"
+ }
+ }
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js b/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js
index 0e3d50d4a82..671d033f2a9 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js
@@ -4,6 +4,8 @@
const ID = "webextension1@tests.mozilla.org";
+const PREF_SELECTED_LOCALE = "general.useragent.locale";
+
const profileDir = gProfD.clone();
profileDir.append("extensions");
@@ -142,6 +144,33 @@ add_task(function*() {
yield promiseRestartManager();
});
+add_task(function* test_manifest_localization() {
+ const ID = "webextension3@tests.mozilla.org";
+
+ yield promiseInstallAllFiles([do_get_addon("webextension_3")], true);
+
+ let addon = yield promiseAddonByID(ID);
+
+ equal(addon.name, "Web Extension foo");
+ equal(addon.description, "Descripton bar of add-on");
+
+ Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "fr-FR");
+ yield promiseRestartManager();
+
+ addon = yield promiseAddonByID(ID);
+
+ equal(addon.name, "Web Extension le foo");
+ equal(addon.description, "Descripton le bar of add-on");
+
+ Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "de");
+ yield promiseRestartManager();
+
+ addon = yield promiseAddonByID(ID);
+
+ equal(addon.name, "Web Extension foo");
+ equal(addon.description, "Descripton bar of add-on");
+});
+
// Missing ID should cause a failure
add_task(function*() {
writeWebManifestForExtension({
diff --git a/webapprt/gtk/moz.build b/webapprt/gtk/moz.build
index 61faeac5a8a..f9b7c40be5d 100644
--- a/webapprt/gtk/moz.build
+++ b/webapprt/gtk/moz.build
@@ -12,8 +12,8 @@ SOURCES += [
'webapprt.cpp',
]
-GENERATED_INCLUDES += ['/build']
LOCAL_INCLUDES += [
+ '!/build',
'/toolkit/xre',
'/xpcom/base',
'/xpcom/build',
diff --git a/webapprt/mac/moz.build b/webapprt/mac/moz.build
index f7ee46a0bfa..d638864ea12 100644
--- a/webapprt/mac/moz.build
+++ b/webapprt/mac/moz.build
@@ -15,8 +15,8 @@ SOURCES += [
DEFINES['XPCOM_GLUE'] = True
-GENERATED_INCLUDES += ['/build']
LOCAL_INCLUDES += [
+ '!/build',
'/toolkit/xre',
'/xpcom/base',
'/xpcom/build',
diff --git a/webapprt/win/moz.build b/webapprt/win/moz.build
index 9c159253e53..fad25344c2b 100644
--- a/webapprt/win/moz.build
+++ b/webapprt/win/moz.build
@@ -20,8 +20,8 @@ DEFINES['APP_VERSION'] = CONFIG['FIREFOX_VERSION']
# Statically link against the CRT
USE_STATIC_LIBS = True
-GENERATED_INCLUDES += ['/build']
LOCAL_INCLUDES += [
+ '!/build',
'/toolkit/xre',
'/xpcom/base',
'/xpcom/build',
diff --git a/widget/cocoa/TextInputHandler.mm b/widget/cocoa/TextInputHandler.mm
index 420bcea67e8..bc846c26037 100644
--- a/widget/cocoa/TextInputHandler.mm
+++ b/widget/cocoa/TextInputHandler.mm
@@ -1936,8 +1936,8 @@ TextInputHandler::HandleFlagsChanged(NSEvent* aNativeEvent)
timestamp:[aNativeEvent timestamp]
windowNumber:[aNativeEvent windowNumber]
context:[aNativeEvent context]
- characters:nil
- charactersIgnoringModifiers:nil
+ characters:@""
+ charactersIgnoringModifiers:@""
isARepeat:NO
keyCode:keyCode];
DispatchKeyEventForFlagsChanged(event, dispatchKeyDown);
diff --git a/widget/cocoa/VibrancyManager.h b/widget/cocoa/VibrancyManager.h
index bc3b6b3bb5c..3a6a8e93f9b 100644
--- a/widget/cocoa/VibrancyManager.h
+++ b/widget/cocoa/VibrancyManager.h
@@ -17,7 +17,6 @@
@class NSColor;
@class NSView;
class nsChildView;
-class nsIntRegion;
namespace mozilla {
diff --git a/widget/cocoa/nsNativeThemeCocoa.mm b/widget/cocoa/nsNativeThemeCocoa.mm
index 6b6565c2fae..32650cd300b 100644
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -526,24 +526,24 @@ nsNativeThemeCocoa::nsNativeThemeCocoa()
// before the main event-loop pool is in place
nsAutoreleasePool pool;
- mDisclosureButtonCell = [[NSButtonCell alloc] initTextCell:nil];
+ mDisclosureButtonCell = [[NSButtonCell alloc] initTextCell:@""];
[mDisclosureButtonCell setBezelStyle:NSRoundedDisclosureBezelStyle];
[mDisclosureButtonCell setButtonType:NSPushOnPushOffButton];
[mDisclosureButtonCell setHighlightsBy:NSPushInCellMask];
- mHelpButtonCell = [[NSButtonCell alloc] initTextCell:nil];
+ mHelpButtonCell = [[NSButtonCell alloc] initTextCell:@""];
[mHelpButtonCell setBezelStyle:NSHelpButtonBezelStyle];
[mHelpButtonCell setButtonType:NSMomentaryPushInButton];
[mHelpButtonCell setHighlightsBy:NSPushInCellMask];
- mPushButtonCell = [[NSButtonCell alloc] initTextCell:nil];
+ mPushButtonCell = [[NSButtonCell alloc] initTextCell:@""];
[mPushButtonCell setButtonType:NSMomentaryPushInButton];
[mPushButtonCell setHighlightsBy:NSPushInCellMask];
- mRadioButtonCell = [[RadioButtonCell alloc] initTextCell:nil];
+ mRadioButtonCell = [[RadioButtonCell alloc] initTextCell:@""];
[mRadioButtonCell setButtonType:NSRadioButton];
- mCheckboxCell = [[CheckboxCell alloc] initTextCell:nil];
+ mCheckboxCell = [[CheckboxCell alloc] initTextCell:@""];
[mCheckboxCell setButtonType:NSSwitchButton];
[mCheckboxCell setAllowsMixedState:YES];
diff --git a/widget/gonk/libdisplay/moz.build b/widget/gonk/libdisplay/moz.build
index 3cb1426eec2..25dbe859abc 100644
--- a/widget/gonk/libdisplay/moz.build
+++ b/widget/gonk/libdisplay/moz.build
@@ -52,12 +52,18 @@ DEFINES['XPCOM_GLUE'] = True
DISABLE_STL_WRAPPING = True
-CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
- 'frameworks/native/include/gui',
- 'frameworks/native/opengl/include',
+if CONFIG['ANDROID_VERSION'] > '15':
+ LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+ 'frameworks/native/include/gui',
+ 'frameworks/native/opengl/include',
+ 'system/core/libsuspend/include',
+ ]
+ ]
+
+LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
'hardware/libhardware/include',
'hardware/libhardware_legacy/include',
- 'system/core/libsuspend/include',
]
]
diff --git a/widget/gonk/moz.build b/widget/gonk/moz.build
index 69cd0467651..ae3bd58a4b0 100644
--- a/widget/gonk/moz.build
+++ b/widget/gonk/moz.build
@@ -96,10 +96,14 @@ if CONFIG['ANDROID_VERSION'] != '15':
if CONFIG['MOZ_OMX_DECODER']:
DEFINES['MOZ_OMX_DECODER'] = True
-CXXFLAGS += [
- '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+if CONFIG['ANDROID_VERSION'] > '15':
+ LOCAL_INCLUDES += [
+ '%' + '%s/frameworks/native/opengl/include' % CONFIG['ANDROID_SOURCE'],
+ ]
+
+LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
'hardware/libhardware/include',
'hardware/libhardware_legacy/include',
- 'frameworks/native/opengl/include',
]
]
diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
index f0b7dd2390a..1c3c156d8fb 100644
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -11,6 +11,7 @@
#include "mozilla/MouseEvents.h"
#include "mozilla/TextEvents.h"
#include "mozilla/TouchEvents.h"
+#include "mozilla/UniquePtrExtensions.h"
#include
#include "GeckoProfiler.h"
@@ -2322,7 +2323,7 @@ nsWindow::UpdateAlpha(gfxPattern* aPattern, nsIntRect aBoundsRect)
int32_t stride = GetAlignedStride<4>(BytesPerPixel(SurfaceFormat::A8) *
aBoundsRect.width);
int32_t bufferSize = stride * aBoundsRect.height;
- UniquePtr imageBuffer(new (std::nothrow) uint8_t[bufferSize]);
+ auto imageBuffer = MakeUniqueFallible(bufferSize);
RefPtr drawTarget = gfxPlatform::GetPlatform()->
CreateDrawTargetForData(imageBuffer.get(), aBoundsRect.Size(),
stride, SurfaceFormat::A8);
diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h
index 23ce84804b2..bea27cbe4bf 100644
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -17,6 +17,7 @@
#include "nsTArray.h"
#include "nsITheme.h"
#include "nsITimer.h"
+#include "nsRegionFwd.h"
#include "nsXULAppAPI.h"
#include "mozilla/Maybe.h"
#include "mozilla/EventForwards.h"
@@ -36,7 +37,6 @@ class nsIRollupListener;
class imgIContainer;
class nsIContent;
class ViewWrapper;
-class nsIntRegion;
class nsIScreen;
class nsIRunnable;
diff --git a/widget/nsIWidgetListener.h b/widget/nsIWidgetListener.h
index 2be27145933..76b87073f06 100644
--- a/widget/nsIWidgetListener.h
+++ b/widget/nsIWidgetListener.h
@@ -10,8 +10,9 @@
#include "mozilla/EventForwards.h"
#include "mozilla/TimeStamp.h"
+#include "nsRegionFwd.h"
+
class nsView;
-class nsIntRegion;
class nsIPresShell;
class nsIWidget;
class nsIXULWindow;
diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h
index d8093d2e8e4..df690c731da 100644
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -28,6 +28,7 @@
#include "mozilla/MouseEvents.h"
#include "mozilla/TimeStamp.h"
#include "nsMargin.h"
+#include "nsRegionFwd.h"
#include "nsWinGesture.h"
@@ -49,7 +50,6 @@
class nsNativeDragTarget;
class nsIRollupListener;
-class nsIntRegion;
class imgIContainer;
namespace mozilla {
diff --git a/xpcom/base/ErrorList.h b/xpcom/base/ErrorList.h
index a46c06ddfd6..9ae973fde0a 100644
--- a/xpcom/base/ErrorList.h
+++ b/xpcom/base/ErrorList.h
@@ -926,6 +926,16 @@
ERROR(NS_ERROR_DOM_ANIM_NO_TARGET_ERR, FAILURE(2)),
#undef MODULE
+ /* ======================================================================= */
+ /* 40: NS_ERROR_MODULE_DOM_PUSH */
+ /* ======================================================================= */
+#define MODULE NS_ERROR_MODULE_DOM_PUSH
+ ERROR(NS_ERROR_DOM_PUSH_INVALID_REGISTRATION_ERR, FAILURE(1)),
+ ERROR(NS_ERROR_DOM_PUSH_DENIED_ERR, FAILURE(2)),
+ ERROR(NS_ERROR_DOM_PUSH_ABORT_ERR, FAILURE(3)),
+ ERROR(NS_ERROR_DOM_PUSH_SERVICE_UNREACHABLE, FAILURE(4)),
+#undef MODULE
+
/* ======================================================================= */
/* 51: NS_ERROR_MODULE_GENERAL */
/* ======================================================================= */
diff --git a/xpcom/base/nsError.h b/xpcom/base/nsError.h
index 7fccef1f8d8..cc8f47d0b83 100644
--- a/xpcom/base/nsError.h
+++ b/xpcom/base/nsError.h
@@ -77,6 +77,7 @@
#define NS_ERROR_MODULE_DOM_BLUETOOTH 37
#define NS_ERROR_MODULE_SIGNED_APP 38
#define NS_ERROR_MODULE_DOM_ANIM 39
+#define NS_ERROR_MODULE_DOM_PUSH 40
/* NS_ERROR_MODULE_GENERAL should be used by modules that do not
* care if return code values overlap. Callers of methods that
diff --git a/xpcom/build/moz.build b/xpcom/build/moz.build
index f6a5800e384..b524063fccd 100644
--- a/xpcom/build/moz.build
+++ b/xpcom/build/moz.build
@@ -79,8 +79,8 @@ FINAL_LIBRARY = 'xul'
DEFINES['_IMPL_NS_STRINGAPI'] = True
DEFINES['OMNIJAR_NAME'] = CONFIG['OMNIJAR_NAME']
-GENERATED_INCLUDES += ['..']
LOCAL_INCLUDES += [
+ '!..',
'../base',
'../components',
'../ds',
diff --git a/xpcom/components/moz.build b/xpcom/components/moz.build
index 03a057f8da2..7b2ebef4559 100644
--- a/xpcom/components/moz.build
+++ b/xpcom/components/moz.build
@@ -44,8 +44,8 @@ if CONFIG['GNU_CXX']:
FINAL_LIBRARY = 'xul'
-GENERATED_INCLUDES += ['..']
LOCAL_INCLUDES += [
+ '!..',
'../base',
'../build',
'../ds',
diff --git a/xpcom/glue/nsTArray.h b/xpcom/glue/nsTArray.h
index 498ff36a984..10465ea824d 100644
--- a/xpcom/glue/nsTArray.h
+++ b/xpcom/glue/nsTArray.h
@@ -27,6 +27,7 @@
#include "nsQuickSort.h"
#include "nsDebug.h"
#include "nsISupportsImpl.h"
+#include "nsRegionFwd.h"
#include
namespace JS {
@@ -35,7 +36,6 @@ class Heap;
} /* namespace JS */
class nsRegion;
-class nsIntRegion;
namespace mozilla {
namespace layers {
struct TileClient;
diff --git a/xpcom/io/moz.build b/xpcom/io/moz.build
index f05e7850c02..45732e4cbf2 100644
--- a/xpcom/io/moz.build
+++ b/xpcom/io/moz.build
@@ -134,4 +134,4 @@ FINAL_LIBRARY = 'xul'
if CONFIG['OS_ARCH'] == 'Linux' and 'lib64' in CONFIG['libdir']:
DEFINES['HAVE_USR_LIB64_DIR'] = True
-GENERATED_INCLUDES += ['..']
+LOCAL_INCLUDES += ['!..']
diff --git a/xpcom/libxpcomrt/moz.build b/xpcom/libxpcomrt/moz.build
index c2e0884ab08..cb58cc5a727 100644
--- a/xpcom/libxpcomrt/moz.build
+++ b/xpcom/libxpcomrt/moz.build
@@ -119,8 +119,8 @@ if CONFIG['INTEL_ARCHITECTURE']:
sse_string_path = '/xpcom/string/nsUTF8UtilsSSE2.cpp'
SOURCES[sse_string_path].flags += CONFIG['SSE2_FLAGS']
-GENERATED_INCLUDES += ['..']
LOCAL_INCLUDES = [
+ '!..',
'../base',
'../build',
'../components',
diff --git a/xpcom/typelib/xpt/moz.build b/xpcom/typelib/xpt/moz.build
index c238a4b6fff..e798c4501cc 100644
--- a/xpcom/typelib/xpt/moz.build
+++ b/xpcom/typelib/xpt/moz.build
@@ -22,8 +22,10 @@ EXPORTS += [
FINAL_LIBRARY = 'xul'
-GENERATED_INCLUDES += ['/xpcom/base']
-LOCAL_INCLUDES += ['/xpcom/base']
+LOCAL_INCLUDES += [
+ '!/xpcom/base',
+ '/xpcom/base',
+]
if CONFIG['_MSC_VER']:
CFLAGS += ['-Zl']
diff --git a/xpfe/components/windowds/nsWindowDataSource.cpp b/xpfe/components/windowds/nsWindowDataSource.cpp
index 519b7089f80..cdeb3a13423 100644
--- a/xpfe/components/windowds/nsWindowDataSource.cpp
+++ b/xpfe/components/windowds/nsWindowDataSource.cpp
@@ -265,23 +265,6 @@ nsWindowDataSource::OnCloseWindow(nsIXULWindow *window)
return NS_OK;
}
-struct findWindowClosure {
- nsIRDFResource* targetResource;
- nsIXULWindow *resultWindow;
-};
-
-static PLDHashOperator
-findWindow(nsIXULWindow* aWindow, nsIRDFResource* aResource, void* aClosure)
-{
- findWindowClosure* closure = static_cast(aClosure);
-
- if (aResource == closure->targetResource) {
- closure->resultWindow = aWindow;
- return PL_DHASH_STOP;
- }
- return PL_DHASH_NEXT;
-}
-
// nsIWindowDataSource implementation
NS_IMETHODIMP
@@ -297,20 +280,23 @@ nsWindowDataSource::GetWindowForResource(const char *aResourceString,
getter_AddRefs(windowResource));
// now reverse-lookup in the hashtable
- findWindowClosure closure = { windowResource.get(), nullptr };
- mWindowResources.EnumerateRead(findWindow, &closure);
- if (closure.resultWindow) {
+ for (auto iter = mWindowResources.Iter(); !iter.Done(); iter.Next()) {
+ nsIXULWindow* window = iter.Key();
+ nsIRDFResource* resource = iter.UserData();
- // this sucks, we have to jump through docshell to go from
- // nsIXULWindow -> nsIDOMWindow
- nsCOMPtr docShell;
- closure.resultWindow->GetDocShell(getter_AddRefs(docShell));
+ if (resource == windowResource) {
+ // This sucks, we have to jump through docshell to go from
+ // nsIXULWindow -> nsIDOMWindow.
+ nsCOMPtr docShell;
+ window->GetDocShell(getter_AddRefs(docShell));
- if (docShell) {
- nsCOMPtr result = do_GetInterface(docShell);
+ if (docShell) {
+ nsCOMPtr result = do_GetInterface(docShell);
- *aResult = result;
- NS_IF_ADDREF(*aResult);
+ *aResult = result;
+ NS_IF_ADDREF(*aResult);
+ }
+ break;
}
}