зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to b2g-inbound
This commit is contained in:
Коммит
90803a6363
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Merge day clobber
|
||||
Bug 1214058 New xpcshell test not getting picked up
|
||||
|
|
|
@ -1238,11 +1238,13 @@ Accessible::ApplyARIAState(uint64_t* aState) const
|
|||
*aState &= ~states::READONLY;
|
||||
|
||||
if (mContent->HasID()) {
|
||||
// If has a role & ID and aria-activedescendant on the container, assume focusable
|
||||
nsIContent *ancestorContent = mContent;
|
||||
while ((ancestorContent = ancestorContent->GetParent()) != nullptr) {
|
||||
if (ancestorContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant)) {
|
||||
// ancestor has activedescendant property, this content could be active
|
||||
// If has a role & ID and aria-activedescendant on the container, assume
|
||||
// focusable.
|
||||
const Accessible* ancestor = this;
|
||||
while ((ancestor = ancestor->Parent()) && !ancestor->IsDoc()) {
|
||||
dom::Element* el = ancestor->Elm();
|
||||
if (el &&
|
||||
el->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant)) {
|
||||
*aState |= states::FOCUSABLE;
|
||||
break;
|
||||
}
|
||||
|
@ -1251,12 +1253,12 @@ Accessible::ApplyARIAState(uint64_t* aState) const
|
|||
}
|
||||
|
||||
if (*aState & states::FOCUSABLE) {
|
||||
// Special case: aria-disabled propagates from ancestors down to any focusable descendant
|
||||
nsIContent *ancestorContent = mContent;
|
||||
while ((ancestorContent = ancestorContent->GetParent()) != nullptr) {
|
||||
if (ancestorContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_disabled,
|
||||
nsGkAtoms::_true, eCaseMatters)) {
|
||||
// ancestor has aria-disabled property, this is disabled
|
||||
// Propogate aria-disabled from ancestors down to any focusable descendant.
|
||||
const Accessible* ancestor = this;
|
||||
while ((ancestor = ancestor->Parent()) && !ancestor->IsDoc()) {
|
||||
dom::Element* el = ancestor->Elm();
|
||||
if (el && el->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_disabled,
|
||||
nsGkAtoms::_true, eCaseMatters)) {
|
||||
*aState |= states::UNAVAILABLE;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -191,6 +191,12 @@
|
|||
testGroupAttrs("table_cell", 3, 4);
|
||||
testGroupAttrs("table_row", 2, 2);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ARIA list constructed by ARIA owns
|
||||
testGroupAttrs("t1_li1", 1, 3);
|
||||
testGroupAttrs("t1_li2", 2, 3);
|
||||
testGroupAttrs("t1_li3", 3, 3);
|
||||
|
||||
// Test that group position information updates after deleting node.
|
||||
testGroupAttrs("tree4_ti1", 1, 2, 1);
|
||||
testGroupAttrs("tree4_ti2", 2, 2, 1);
|
||||
|
@ -453,5 +459,11 @@
|
|||
<div role="cell" id="table_cell" aria-colindex="3">cell</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div role="list" aria-owns="t1_li1 t1_li2 t1_li3">
|
||||
<div role="listitem" id="t1_li2">Apples</div>
|
||||
<div role="listitem" id="t1_li1">Oranges</div>
|
||||
</span>
|
||||
<div role="listitem" id="t1_li3">Bananas</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -51,7 +51,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429547
|
|||
var container = getNode(aID);
|
||||
var itemNode = document.createElement("div");
|
||||
itemNode.setAttribute("id", aNewItemID);
|
||||
itemNode.textContent = "item3";
|
||||
itemNode.textContent = aNewItemID;
|
||||
container.appendChild(itemNode);
|
||||
|
||||
container.setAttribute("aria-activedescendant", aNewItemID);
|
||||
|
@ -68,14 +68,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429547
|
|||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new synthFocus("container", new focusChecker("item1")));
|
||||
gQueue.push(new changeARIAActiveDescendant("container", "item2"));
|
||||
gQueue.push(new synthFocus("listbox", new focusChecker("item1")));
|
||||
gQueue.push(new changeARIAActiveDescendant("listbox", "item2"));
|
||||
gQueue.push(new changeARIAActiveDescendant("listbox", "item3"));
|
||||
|
||||
gQueue.push(new synthFocus("combobox_entry", new focusChecker("combobox_entry")));
|
||||
gQueue.push(new changeARIAActiveDescendant("combobox", "combobox_option2"));
|
||||
|
||||
todo(false, "No focus for inserted element, bug 687011");
|
||||
//gQueue.push(new insertItemNFocus("container", "item3"));
|
||||
//gQueue.push(new insertItemNFocus("listbox", "item4"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
@ -101,10 +102,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429547
|
|||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<div role="listbox" aria-activedescendant="item1" id="container" tabindex="1">
|
||||
<div role="listbox" aria-activedescendant="item1" id="listbox" tabindex="1"
|
||||
aria-owns="item3">
|
||||
<div role="listitem" id="item1">item1</div>
|
||||
<div role="listitem" id="item2">item2</div>
|
||||
</div>
|
||||
<div role="listitem" id="item3">item3</div>
|
||||
|
||||
<div role="combobox" id="combobox">
|
||||
<input id="combobox_entry">
|
||||
|
|
|
@ -500,7 +500,8 @@
|
|||
<!-- Test that aria-disabled state gets propagated to all descendants -->
|
||||
<div id="group" role="group" aria-disabled="true">
|
||||
<button>hi</button>
|
||||
<div tabindex="0" role="listbox" aria-activedescendant="item1">
|
||||
<div tabindex="0" role="listbox" aria-activedescendant="item1"
|
||||
aria-owns="item5">
|
||||
<div role="option" id="item1">Item 1</div>
|
||||
<div role="option" id="item2">Item 2</div>
|
||||
<div role="option" id="item3">Item 3</div>
|
||||
|
@ -508,6 +509,7 @@
|
|||
</div>
|
||||
<div role="slider" tabindex="0">A slider</div>
|
||||
</div>
|
||||
<div role="option" id="item5">Item 5</div>
|
||||
|
||||
<!-- Test active state -->
|
||||
<div id="as_listbox" tabindex="0" role="listbox"
|
||||
|
|
|
@ -183,7 +183,7 @@ CONTEXTS.SelectorContext = Class({
|
|||
let selector = this.selector;
|
||||
|
||||
while (!(popupNode instanceof Ci.nsIDOMDocument)) {
|
||||
if (popupNode.mozMatchesSelector(selector))
|
||||
if (popupNode.matches(selector))
|
||||
return popupNode;
|
||||
|
||||
popupNode = popupNode.parentNode;
|
||||
|
|
|
@ -294,21 +294,21 @@ exports.testStringOverload = createProxyTest(html, function (helper, assert) {
|
|||
);
|
||||
});
|
||||
|
||||
exports["test MozMatchedSelector"] = createProxyTest("", function (helper) {
|
||||
exports["test Element.matches()"] = createProxyTest("", function (helper) {
|
||||
helper.createWorker(
|
||||
'new ' + function ContentScriptScope() {
|
||||
// Check mozMatchesSelector XrayWrappers bug:
|
||||
// mozMatchesSelector returns bad results when we are not calling it from the node itself
|
||||
// SEE BUG 658909: mozMatchesSelector returns incorrect results with XrayWrappers
|
||||
assert(document.createElement( "div" ).mozMatchesSelector("div"),
|
||||
"mozMatchesSelector works while being called from the node");
|
||||
assert(document.documentElement.mozMatchesSelector.call(
|
||||
// Check matches XrayWrappers bug (Bug 658909):
|
||||
// Test that Element.matches() does not return bad results when we are
|
||||
// not calling it from the node itself.
|
||||
assert(document.createElement( "div" ).matches("div"),
|
||||
"matches works while being called from the node");
|
||||
assert(document.documentElement.matches.call(
|
||||
document.createElement( "div" ),
|
||||
"div"
|
||||
),
|
||||
"mozMatchesSelector works while being called from a " +
|
||||
"matches works while being called from a " +
|
||||
"function reference to " +
|
||||
"document.documentElement.mozMatchesSelector.call");
|
||||
"document.documentElement.matches.call");
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
|
|
@ -294,21 +294,21 @@ exports.testStringOverload = createProxyTest(html, function (helper, assert) {
|
|||
);
|
||||
});
|
||||
|
||||
exports["test MozMatchedSelector"] = createProxyTest("", function (helper) {
|
||||
exports["test Element.matches()"] = createProxyTest("", function (helper) {
|
||||
helper.createWorker(
|
||||
'new ' + function ContentScriptScope() {
|
||||
// Check mozMatchesSelector XrayWrappers bug:
|
||||
// mozMatchesSelector returns bad results when we are not calling it from the node itself
|
||||
// SEE BUG 658909: mozMatchesSelector returns incorrect results with XrayWrappers
|
||||
assert(document.createElement( "div" ).mozMatchesSelector("div"),
|
||||
"mozMatchesSelector works while being called from the node");
|
||||
assert(document.documentElement.mozMatchesSelector.call(
|
||||
// Check matches XrayWrappers bug (Bug 658909):
|
||||
// Test that Element.matches() does not return bad results when we are
|
||||
// not calling it from the node itself.
|
||||
assert(document.createElement( "div" ).matches("div"),
|
||||
"matches works while being called from the node");
|
||||
assert(document.documentElement.matches.call(
|
||||
document.createElement( "div" ),
|
||||
"div"
|
||||
),
|
||||
"mozMatchesSelector works while being called from a " +
|
||||
"matches works while being called from a " +
|
||||
"function reference to " +
|
||||
"document.documentElement.mozMatchesSelector.call");
|
||||
"document.documentElement.matches.call");
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
// host and the cert is bad (STS Spec section 7.3) or if the
|
||||
// certerror is in a frame (bug 633691).
|
||||
if (cssClass == "badStsCert" || window != top) {
|
||||
document.getElementById("advancedPanel").setAttribute("hidden", "true");
|
||||
document.getElementById("exceptionDialogButton").setAttribute("hidden", "true");
|
||||
}
|
||||
if (cssClass != "badStsCert") {
|
||||
document.getElementById("badStsCertExplanation").setAttribute("hidden", "true");
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// This is testing the aboutCertError page (Bug 1207107). It's a start,
|
||||
// but should be expanded to include cert_domain_link / badStsCert
|
||||
// but should be expanded to include cert_domain_link
|
||||
|
||||
const GOOD_PAGE = "https://example.com/";
|
||||
const BAD_CERT = "https://expired.example.com/";
|
||||
const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443";
|
||||
|
||||
add_task(function* checkReturnToAboutHome() {
|
||||
info("Loading a bad cert page directly and making sure 'return to previous page' goes to about:home");
|
||||
|
@ -68,6 +69,26 @@ add_task(function* checkReturnToPreviousPage() {
|
|||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* checkBadStsCert() {
|
||||
info("Loading a badStsCert and making sure exception button doesn't show up");
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, GOOD_PAGE);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
||||
info("Loading and waiting for the cert error");
|
||||
let certErrorLoaded = waitForCertErrorLoad(browser);
|
||||
BrowserTestUtils.loadURI(browser, BAD_STS_CERT);
|
||||
yield certErrorLoaded;
|
||||
|
||||
let exceptionButtonHidden = yield ContentTask.spawn(browser, null, function* () {
|
||||
let doc = content.document;
|
||||
let exceptionButton = doc.getElementById("exceptionDialogButton");
|
||||
return exceptionButton.hidden;
|
||||
});
|
||||
ok(exceptionButtonHidden, "Exception button is hidden");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
function waitForCertErrorLoad(browser) {
|
||||
return new Promise(resolve => {
|
||||
info("Waiting for DOMContentLoaded event");
|
||||
|
|
|
@ -40,10 +40,8 @@ body,
|
|||
}
|
||||
|
||||
.mozilla-logo {
|
||||
background: url("../img/mozilla-logo.svg#logo") no-repeat;
|
||||
background-size: contain;
|
||||
height: 26px;
|
||||
width: 100px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
/* Standalone Overlay wrapper */
|
||||
|
@ -95,9 +93,6 @@ html[dir="rtl"] .standalone-overlay-wrapper > .general-support-url {
|
|||
.standalone-overlay-wrapper > .standalone-moz-logo {
|
||||
width: 50px;
|
||||
height: 13px;
|
||||
background-size: contain;
|
||||
background-image: url("../img/mozilla-logo.svg#logo-white");
|
||||
background-repeat: no-repeat;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
|
|
|
@ -122,7 +122,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
|
||||
),
|
||||
React.createElement(ToSView, {dispatcher: this.props.dispatcher}),
|
||||
React.createElement("p", {className: "mozilla-logo"})
|
||||
React.createElement("img", {className: "mozilla-logo", src: "img/mozilla-logo.svg#logo"})
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -654,7 +654,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
React.createElement("div", {className: "standalone-overlay-wrapper"},
|
||||
React.createElement("div", {className: "hello-logo"}),
|
||||
React.createElement(GeneralSupportURL, {dispatcher: this.props.dispatcher}),
|
||||
React.createElement("div", {className: "standalone-moz-logo"})
|
||||
React.createElement("img", {className: "standalone-moz-logo", src: "img/mozilla-logo.svg#logo-white"})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
}
|
||||
</div>
|
||||
<ToSView dispatcher={this.props.dispatcher} />
|
||||
<p className="mozilla-logo" />
|
||||
<img className="mozilla-logo" src="img/mozilla-logo.svg#logo" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -654,7 +654,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
<div className="standalone-overlay-wrapper">
|
||||
<div className="hello-logo"></div>
|
||||
<GeneralSupportURL dispatcher={this.props.dispatcher} />
|
||||
<div className="standalone-moz-logo" />
|
||||
<img className="standalone-moz-logo" src="img/mozilla-logo.svg#logo-white" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ app.get("/content/c/config.js", getConfigFile);
|
|||
// /content - for the standalone files.
|
||||
|
||||
app.use("/ui", express.static(path.join(__dirname, "..", "ui")));
|
||||
app.use("/ui/img/", express.static(path.join(__dirname, "..", "standalone", "content", "img")));
|
||||
app.use("/ui/loop/", express.static(path.join(__dirname, "..", "content")));
|
||||
app.use("/ui/shared/", express.static(path.join(__dirname, "..", "content",
|
||||
"shared")));
|
||||
|
|
|
@ -2934,8 +2934,8 @@ var SessionStoreInternal = {
|
|||
// In case we didn't collect/receive data for any tabs yet we'll have to
|
||||
// fill the array with at least empty tabData objects until |_tPos| or
|
||||
// we'll end up with |null| entries.
|
||||
for (let tab of Array.slice(tabbrowser.tabs, 0, tab._tPos)) {
|
||||
let emptyState = {entries: [], lastAccessed: tab.lastAccessed};
|
||||
for (let otherTab of Array.slice(tabbrowser.tabs, 0, tab._tPos)) {
|
||||
let emptyState = {entries: [], lastAccessed: otherTab.lastAccessed};
|
||||
this._windows[window.__SSi].tabs.push(emptyState);
|
||||
}
|
||||
|
||||
|
|
|
@ -2162,8 +2162,8 @@ if (AppConstants.MOZ_SERVICES_HEALTHREPORT) {
|
|||
_serializeJSONDaily: function(data) {
|
||||
let result = {_v: this.version };
|
||||
|
||||
for (let [field, data] of data) {
|
||||
result[field] = data;
|
||||
for (let [field, value] of data) {
|
||||
result[field] = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -8,5 +8,13 @@
|
|||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 12057960,
|
||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"setup": "setup.sh",
|
||||
"unpack": true
|
||||
}
|
||||
]
|
||||
|
|
|
@ -31,6 +31,11 @@ player.animationDurationLabel=Duration:
|
|||
# displayed before the animation delay.
|
||||
player.animationDelayLabel=Delay:
|
||||
|
||||
# LOCALIZATION NOTE (player.animationRateLabel):
|
||||
# This string is displayed in each animation player widget. It is the label
|
||||
# displayed before the animation playback rate.
|
||||
player.animationRateLabel=Playback rate:
|
||||
|
||||
# LOCALIZATION NOTE (player.animationIterationCountLabel):
|
||||
# This string is displayed in each animation player widget. It is the label
|
||||
# displayed before the number of times the animation is set to repeat.
|
||||
|
|
|
@ -188,8 +188,8 @@ case "$target" in
|
|||
esac
|
||||
|
||||
])
|
||||
|
||||
AC_DEFUN([MOZ_ANDROID_STLPORT],
|
||||
|
||||
AC_DEFUN([MOZ_ANDROID_CPU_ARCH],
|
||||
[
|
||||
|
||||
if test "$OS_TARGET" = "Android" -a -z "$gonkdir"; then
|
||||
|
@ -209,7 +209,13 @@ if test "$OS_TARGET" = "Android" -a -z "$gonkdir"; then
|
|||
esac
|
||||
|
||||
AC_SUBST(ANDROID_CPU_ARCH)
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([MOZ_ANDROID_STLPORT],
|
||||
[
|
||||
|
||||
if test "$OS_TARGET" = "Android" -a -z "$gonkdir"; then
|
||||
cpu_arch_dir="$ANDROID_CPU_ARCH"
|
||||
if test "$MOZ_THUMB2" = 1; then
|
||||
cpu_arch_dir="$cpu_arch_dir/thumb"
|
||||
|
|
|
@ -109,6 +109,7 @@ leak:libdricore.so
|
|||
leak:libGL.so
|
||||
leak:libglib-2.0.so
|
||||
leak:libp11-kit.so
|
||||
leak:libpixman-1.so
|
||||
leak:libpulse.so
|
||||
leak:libpulsecommon-1.1.so
|
||||
leak:libresolv.so
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
# To do try builds with Gtk+2, uncomment the following line, and remove
|
||||
# everything after that.
|
||||
#ac_add_options --enable-default-toolkit=cairo-gtk2
|
||||
|
||||
TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
|
||||
|
||||
# $TOOLTOOL_DIR/gtk3 comes from tooltool, when the tooltool manifest contains it.
|
||||
if [ -d "$TOOLTOOL_DIR/gtk3" ]; then
|
||||
if [ -z "$PKG_CONFIG_LIBDIR" ]; then
|
||||
echo PKG_CONFIG_LIBDIR must be set >&2
|
||||
exit 1
|
||||
fi
|
||||
export PKG_CONFIG_SYSROOT_DIR="$TOOLTOOL_DIR/gtk3"
|
||||
export PKG_CONFIG_PATH="$TOOLTOOL_DIR/gtk3/usr/local/lib/pkgconfig"
|
||||
PKG_CONFIG="$TOOLTOOL_DIR/gtk3/usr/local/bin/pkg-config"
|
||||
export PATH="$TOOLTOOL_DIR/gtk3/usr/local/bin:${PATH}"
|
||||
# Ensure cairo, gdk-pixbuf, etc. are not taken from the system installed packages.
|
||||
LDFLAGS="-L$TOOLTOOL_DIR/gtk3/usr/local/lib ${LDFLAGS}"
|
||||
ac_add_options --enable-default-toolkit=cairo-gtk3
|
||||
|
||||
# Set things up to use Gtk+3 from the tooltool package
|
||||
mk_add_options "export FONTCONFIG_PATH=$TOOLTOOL_DIR/gtk3/usr/local/etc/fonts"
|
||||
mk_add_options "export PANGO_SYSCONFDIR=$TOOLTOOL_DIR/gtk3/usr/local/etc"
|
||||
mk_add_options "export PANGO_LIBDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib"
|
||||
mk_add_options "export GDK_PIXBUF_MODULE_FILE=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
|
||||
mk_add_options "export GDK_PIXBUF_MODULEDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders"
|
||||
mk_add_options "export LD_LIBRARY_PATH=$TOOLTOOL_DIR/gtk3/usr/local/lib"
|
||||
|
||||
# Until a tooltool with bug 1188571 landed is available everywhere
|
||||
$TOOLTOOL_DIR/gtk3/setup.sh
|
||||
else
|
||||
PKG_CONFIG=pkg-config
|
||||
ac_add_options --enable-default-toolkit=cairo-gtk2
|
||||
# $TOOLTOOL_DIR/gtk3 comes from tooltool, and must be included in the tooltool manifest.
|
||||
if [ -z "$PKG_CONFIG_LIBDIR" ]; then
|
||||
echo PKG_CONFIG_LIBDIR must be set >&2
|
||||
exit 1
|
||||
fi
|
||||
export PKG_CONFIG_SYSROOT_DIR="$TOOLTOOL_DIR/gtk3"
|
||||
export PKG_CONFIG_PATH="$TOOLTOOL_DIR/gtk3/usr/local/lib/pkgconfig"
|
||||
PKG_CONFIG="$TOOLTOOL_DIR/gtk3/usr/local/bin/pkg-config"
|
||||
export PATH="$TOOLTOOL_DIR/gtk3/usr/local/bin:${PATH}"
|
||||
# Ensure cairo, gdk-pixbuf, etc. are not taken from the system installed packages.
|
||||
LDFLAGS="-L$TOOLTOOL_DIR/gtk3/usr/local/lib ${LDFLAGS}"
|
||||
ac_add_options --enable-default-toolkit=cairo-gtk3
|
||||
|
||||
# Set things up to use Gtk+3 from the tooltool package
|
||||
mk_add_options "export FONTCONFIG_PATH=$TOOLTOOL_DIR/gtk3/usr/local/etc/fonts"
|
||||
mk_add_options "export PANGO_SYSCONFDIR=$TOOLTOOL_DIR/gtk3/usr/local/etc"
|
||||
mk_add_options "export PANGO_LIBDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib"
|
||||
mk_add_options "export GDK_PIXBUF_MODULE_FILE=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
|
||||
mk_add_options "export GDK_PIXBUF_MODULEDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders"
|
||||
mk_add_options "export LD_LIBRARY_PATH=$TOOLTOOL_DIR/gtk3/usr/local/lib"
|
||||
|
||||
# Until a tooltool with bug 1188571 landed is available everywhere
|
||||
$TOOLTOOL_DIR/gtk3/setup.sh
|
||||
|
|
|
@ -1341,7 +1341,7 @@ endif
|
|||
# it.
|
||||
|
||||
ifneq (,$(filter-out all chrome default export realchrome clean clobber clobber_all distclean realclean,$(MAKECMDGOALS)))
|
||||
MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(EXTRA_MDDEPEND_FILES) $(addsuffix .pp,$(notdir $(sort $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)))))))
|
||||
MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(addsuffix .pp,$(notdir $(sort $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)))))))
|
||||
|
||||
ifneq (,$(MDDEPEND_FILES))
|
||||
$(call include_deps,$(MDDEPEND_FILES))
|
||||
|
@ -1349,16 +1349,12 @@ endif
|
|||
|
||||
endif
|
||||
|
||||
|
||||
ifneq (,$(filter export,$(MAKECMDGOALS)))
|
||||
MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(EXTRA_EXPORT_MDDEPEND_FILES))))
|
||||
MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(EXTRA_MDDEPEND_FILES))))
|
||||
|
||||
ifneq (,$(MDDEPEND_FILES))
|
||||
$(call include_deps,$(MDDEPEND_FILES))
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
#############################################################################
|
||||
|
||||
-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-rules.mk
|
||||
|
|
21
configure.in
21
configure.in
|
@ -321,7 +321,11 @@ if test -n "$gonkdir" ; then
|
|||
direct_nspr_config=1
|
||||
android_cxx_stl=mozstlport
|
||||
else
|
||||
MOZ_ANDROID_NDK
|
||||
if test "$COMPILE_ENVIRONMENT"; then
|
||||
MOZ_ANDROID_NDK
|
||||
else
|
||||
AC_DEFINE(ANDROID)
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
|
||||
case "$target" in
|
||||
*-android*|*-linuxandroid*)
|
||||
|
@ -1197,7 +1201,14 @@ esac
|
|||
|
||||
dnl Configure platform-specific CPU architecture compiler options.
|
||||
dnl ==============================================================
|
||||
MOZ_ARCH_OPTS
|
||||
if test "$COMPILE_ENVIRONMENT"; then
|
||||
MOZ_ARCH_OPTS
|
||||
else
|
||||
if test "$OS_TARGET" = Android -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk"; then
|
||||
dnl Default Android builds to ARMv7.
|
||||
MOZ_ARCH=armv7-a
|
||||
fi
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
|
||||
dnl =================================================================
|
||||
dnl Set up and test static assertion macros used to avoid AC_TRY_RUN,
|
||||
|
@ -1246,7 +1257,10 @@ dnl Android libstdc++, placed here so it can use MOZ_ARCH
|
|||
dnl computed above.
|
||||
dnl ========================================================
|
||||
|
||||
MOZ_ANDROID_STLPORT
|
||||
MOZ_ANDROID_CPU_ARCH
|
||||
if test "$COMPILE_ENVIRONMENT"; then
|
||||
MOZ_ANDROID_STLPORT
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
|
||||
dnl ========================================================
|
||||
dnl Suppress Clang Argument Warnings
|
||||
|
@ -2532,6 +2546,7 @@ esac
|
|||
if test -z "$COMPILE_ENVIRONMENT"; then
|
||||
SKIP_COMPILER_CHECKS=1
|
||||
SKIP_LIBRARY_CHECKS=1
|
||||
PKG_SKIP_STRIP=1
|
||||
else
|
||||
MOZ_COMPILER_OPTS
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
|
|
|
@ -86,6 +86,8 @@ var getServerTraits = Task.async(function*(target) {
|
|||
method: "stopAnimationPlayerUpdates" },
|
||||
{ name: "hasSetPlaybackRate", actor: "animationplayer",
|
||||
method: "setPlaybackRate" },
|
||||
{ name: "hasSetPlaybackRates", actor: "animations",
|
||||
method: "setPlaybackRates" },
|
||||
{ name: "hasTargetNode", actor: "domwalker",
|
||||
method: "getNodeFromActor" },
|
||||
{ name: "hasSetCurrentTimes", actor: "animations",
|
||||
|
@ -284,6 +286,23 @@ var AnimationsController = {
|
|||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Set all known animations' playback rates to the provided rate.
|
||||
* @param {Number} rate.
|
||||
* @return {Promise} Resolves when the rate has been set.
|
||||
*/
|
||||
setPlaybackRateAll: Task.async(function*(rate) {
|
||||
if (this.traits.hasSetPlaybackRates) {
|
||||
// If the backend can set all playback rates at the same time, use that.
|
||||
yield this.animationsFront.setPlaybackRates(this.animationPlayers, rate);
|
||||
} else if (this.traits.hasSetPlaybackRate) {
|
||||
// Otherwise, fall back to setting each rate individually.
|
||||
for (let animation of this.animationPlayers) {
|
||||
yield animation.setPlaybackRate(rate);
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
// AnimationPlayerFront objects are managed by this controller. They are
|
||||
// retrieved when refreshAnimationPlayers is called, stored in the
|
||||
// animationPlayers array, and destroyed when refreshAnimationPlayers is
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<div id="timeline-toolbar" class="theme-toolbar">
|
||||
<button id="rewind-timeline" standalone="true" class="devtools-button"></button>
|
||||
<button id="pause-resume-timeline" standalone="true" class="devtools-button pause-button paused"></button>
|
||||
<span id="timeline-rate"></span>
|
||||
<span id="timeline-current-time" class="label"></span>
|
||||
</div>
|
||||
<div id="players"></div>
|
||||
|
|
|
@ -3,12 +3,14 @@
|
|||
/* 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/. */
|
||||
/* globals AnimationsController, document, performance, promise,
|
||||
gToolbox, gInspector, requestAnimationFrame, cancelAnimationFrame, L10N */
|
||||
/* globals AnimationsController, document, promise, gToolbox, gInspector */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {AnimationsTimeline} = require("devtools/client/animationinspector/components");
|
||||
const {
|
||||
AnimationsTimeline,
|
||||
RateSelector
|
||||
} = require("devtools/client/animationinspector/components");
|
||||
const {formatStopwatchTime} = require("devtools/client/animationinspector/utils");
|
||||
|
||||
var $ = (selector, target = document) => target.querySelector(selector);
|
||||
|
@ -39,6 +41,7 @@ var AnimationsPanel = {
|
|||
this.playTimelineButtonEl = $("#pause-resume-timeline");
|
||||
this.rewindTimelineButtonEl = $("#rewind-timeline");
|
||||
this.timelineCurrentTimeEl = $("#timeline-current-time");
|
||||
this.rateSelectorEl = $("#timeline-rate");
|
||||
|
||||
// If the server doesn't support toggling all animations at once, hide the
|
||||
// whole global toolbar.
|
||||
|
@ -49,7 +52,8 @@ var AnimationsPanel = {
|
|||
// Binding functions that need to be called in scope.
|
||||
for (let functionName of ["onPickerStarted", "onPickerStopped",
|
||||
"refreshAnimationsUI", "toggleAll", "onTabNavigated",
|
||||
"onTimelineDataChanged", "playPauseTimeline", "rewindTimeline"]) {
|
||||
"onTimelineDataChanged", "playPauseTimeline", "rewindTimeline",
|
||||
"onRateChanged"]) {
|
||||
this[functionName] = this[functionName].bind(this);
|
||||
}
|
||||
let hUtils = gToolbox.highlighterUtils;
|
||||
|
@ -58,12 +62,16 @@ var AnimationsPanel = {
|
|||
this.animationsTimelineComponent = new AnimationsTimeline(gInspector);
|
||||
this.animationsTimelineComponent.init(this.playersEl);
|
||||
|
||||
if (AnimationsController.traits.hasSetPlaybackRate) {
|
||||
this.rateSelectorComponent = new RateSelector();
|
||||
this.rateSelectorComponent.init(this.rateSelectorEl);
|
||||
}
|
||||
|
||||
this.startListeners();
|
||||
|
||||
yield this.refreshAnimationsUI();
|
||||
|
||||
this.initialized.resolve();
|
||||
|
||||
this.emit(this.PANEL_INITIALIZED);
|
||||
}),
|
||||
|
||||
|
@ -83,10 +91,15 @@ var AnimationsPanel = {
|
|||
this.animationsTimelineComponent.destroy();
|
||||
this.animationsTimelineComponent = null;
|
||||
|
||||
if (this.rateSelectorComponent) {
|
||||
this.rateSelectorComponent.destroy();
|
||||
this.rateSelectorComponent = null;
|
||||
}
|
||||
|
||||
this.playersEl = this.errorMessageEl = null;
|
||||
this.toggleAllButtonEl = this.pickerButtonEl = null;
|
||||
this.playTimelineButtonEl = this.rewindTimelineButtonEl = null;
|
||||
this.timelineCurrentTimeEl = null;
|
||||
this.timelineCurrentTimeEl = this.rateSelectorEl = null;
|
||||
|
||||
this.destroyed.resolve();
|
||||
}),
|
||||
|
@ -107,6 +120,10 @@ var AnimationsPanel = {
|
|||
|
||||
this.animationsTimelineComponent.on("timeline-data-changed",
|
||||
this.onTimelineDataChanged);
|
||||
|
||||
if (this.rateSelectorComponent) {
|
||||
this.rateSelectorComponent.on("rate-changed", this.onRateChanged);
|
||||
}
|
||||
},
|
||||
|
||||
stopListeners: function() {
|
||||
|
@ -125,6 +142,10 @@ var AnimationsPanel = {
|
|||
|
||||
this.animationsTimelineComponent.off("timeline-data-changed",
|
||||
this.onTimelineDataChanged);
|
||||
|
||||
if (this.rateSelectorComponent) {
|
||||
this.rateSelectorComponent.off("rate-changed", this.onRateChanged);
|
||||
}
|
||||
},
|
||||
|
||||
togglePlayers: function(isVisible) {
|
||||
|
@ -173,13 +194,23 @@ var AnimationsPanel = {
|
|||
.catch(e => console.error(e));
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the playback rate of all current animations shown in the timeline to
|
||||
* the value of this.rateSelectorEl.
|
||||
*/
|
||||
onRateChanged: function(e, rate) {
|
||||
AnimationsController.setPlaybackRateAll(rate)
|
||||
.then(() => this.refreshAnimationsStateAndUI())
|
||||
.catch(e => console.error(e));
|
||||
},
|
||||
|
||||
onTabNavigated: function() {
|
||||
this.toggleAllButtonEl.classList.remove("paused");
|
||||
},
|
||||
|
||||
onTimelineDataChanged: function(e, data) {
|
||||
this.timelineData = data;
|
||||
let {isMoving, isPaused, isUserDrag, time} = data;
|
||||
let {isMoving, isUserDrag, time} = data;
|
||||
|
||||
this.playTimelineButtonEl.classList.toggle("paused", !isMoving);
|
||||
|
||||
|
@ -232,6 +263,11 @@ var AnimationsPanel = {
|
|||
AnimationsController.animationPlayers,
|
||||
AnimationsController.documentCurrentTime);
|
||||
|
||||
// Re-render the rate selector component.
|
||||
if (this.rateSelectorComponent) {
|
||||
this.rateSelectorComponent.render(AnimationsController.animationPlayers);
|
||||
}
|
||||
|
||||
// If there are no players to show, show the error message instead and
|
||||
// return.
|
||||
if (!AnimationsController.animationPlayers.length) {
|
||||
|
|
|
@ -34,6 +34,8 @@ const L10N = new ViewHelpers.L10N(STRINGS_URI);
|
|||
const MILLIS_TIME_FORMAT_MAX_DURATION = 4000;
|
||||
// The minimum spacing between 2 time graduation headers in the timeline (px).
|
||||
const TIME_GRADUATION_MIN_SPACING = 40;
|
||||
// List of playback rate presets displayed in the timeline toolbar.
|
||||
const PLAYBACK_RATES = [.1, .25, .5, 1, 2, 5, 10];
|
||||
// The size of the fast-track icon (for compositor-running animations), this is
|
||||
// used to position the icon correctly.
|
||||
const FAST_TRACK_ICON_SIZE = 20;
|
||||
|
@ -187,6 +189,10 @@ AnimationTargetNode.prototype = {
|
|||
this.previewEl.appendChild(document.createTextNode(">"));
|
||||
}
|
||||
|
||||
this.startListeners();
|
||||
},
|
||||
|
||||
startListeners: function() {
|
||||
// Init events for highlighting and selecting the node.
|
||||
this.previewEl.addEventListener("mouseover", this.onPreviewMouseOver);
|
||||
this.previewEl.addEventListener("mouseout", this.onPreviewMouseOut);
|
||||
|
@ -200,15 +206,19 @@ AnimationTargetNode.prototype = {
|
|||
TargetNodeHighlighter.on("highlighted", this.onTargetHighlighterLocked);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
TargetNodeHighlighter.unhighlight().catch(e => console.error(e));
|
||||
|
||||
stopListeners: function() {
|
||||
TargetNodeHighlighter.off("highlighted", this.onTargetHighlighterLocked);
|
||||
this.inspector.off("markupmutation", this.onMarkupMutations);
|
||||
this.previewEl.removeEventListener("mouseover", this.onPreviewMouseOver);
|
||||
this.previewEl.removeEventListener("mouseout", this.onPreviewMouseOut);
|
||||
this.previewEl.removeEventListener("click", this.onSelectNodeClick);
|
||||
this.highlightNodeEl.removeEventListener("click", this.onHighlightNodeClick);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
TargetNodeHighlighter.unhighlight().catch(e => console.error(e));
|
||||
|
||||
this.stopListeners();
|
||||
|
||||
this.el.remove();
|
||||
this.el = this.tagNameEl = this.idEl = this.classEl = null;
|
||||
|
@ -217,21 +227,26 @@ AnimationTargetNode.prototype = {
|
|||
},
|
||||
|
||||
get highlighterUtils() {
|
||||
return this.inspector.toolbox.highlighterUtils;
|
||||
if (this.inspector && this.inspector.toolbox) {
|
||||
return this.inspector.toolbox.highlighterUtils;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
onPreviewMouseOver: function() {
|
||||
if (!this.nodeFront) {
|
||||
if (!this.nodeFront || !this.highlighterUtils) {
|
||||
return;
|
||||
}
|
||||
this.highlighterUtils.highlightNodeFront(this.nodeFront);
|
||||
this.highlighterUtils.highlightNodeFront(this.nodeFront)
|
||||
.catch(e => console.error(e));
|
||||
},
|
||||
|
||||
onPreviewMouseOut: function() {
|
||||
if (!this.nodeFront) {
|
||||
if (!this.nodeFront || !this.highlighterUtils) {
|
||||
return;
|
||||
}
|
||||
this.highlighterUtils.unhighlight();
|
||||
this.highlighterUtils.unhighlight()
|
||||
.catch(e => console.error(e));
|
||||
},
|
||||
|
||||
onSelectNodeClick: function() {
|
||||
|
@ -331,6 +346,90 @@ AnimationTargetNode.prototype = {
|
|||
})
|
||||
};
|
||||
|
||||
/**
|
||||
* UI component responsible for displaying a playback rate selector UI.
|
||||
* The rendering logic is such that a predefined list of rates is generated.
|
||||
* If *all* animations passed to render share the same rate, then that rate is
|
||||
* selected in the <select> element, otherwise, the empty value is selected.
|
||||
* If the rate that all animations share isn't part of the list of predefined
|
||||
* rates, than that rate is added to the list.
|
||||
*/
|
||||
function RateSelector() {
|
||||
this.onRateChanged = this.onRateChanged.bind(this);
|
||||
EventEmitter.decorate(this);
|
||||
}
|
||||
|
||||
exports.RateSelector = RateSelector;
|
||||
|
||||
RateSelector.prototype = {
|
||||
init: function(containerEl) {
|
||||
this.selectEl = createNode({
|
||||
parent: containerEl,
|
||||
nodeType: "select",
|
||||
attributes: {"class": "devtools-button"}
|
||||
});
|
||||
|
||||
this.selectEl.addEventListener("change", this.onRateChanged);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.selectEl.removeEventListener("change", this.onRateChanged);
|
||||
this.selectEl.remove();
|
||||
this.selectEl = null;
|
||||
},
|
||||
|
||||
getAnimationsRates: function(animations) {
|
||||
return sortedUnique(animations.map(a => a.state.playbackRate));
|
||||
},
|
||||
|
||||
getAllRates: function(animations) {
|
||||
let animationsRates = this.getAnimationsRates(animations);
|
||||
if (animationsRates.length > 1) {
|
||||
return PLAYBACK_RATES;
|
||||
}
|
||||
|
||||
return sortedUnique(PLAYBACK_RATES.concat(animationsRates));
|
||||
},
|
||||
|
||||
render: function(animations) {
|
||||
let allRates = this.getAnimationsRates(animations);
|
||||
let hasOneRate = allRates.length === 1;
|
||||
|
||||
this.selectEl.innerHTML = "";
|
||||
|
||||
if (!hasOneRate) {
|
||||
// When the animations displayed have mixed playback rates, we can't
|
||||
// select any of the predefined ones, instead, insert an empty rate.
|
||||
createNode({
|
||||
parent: this.selectEl,
|
||||
nodeType: "option",
|
||||
attributes: {value: "", selector: "true"},
|
||||
textContent: "-"
|
||||
});
|
||||
}
|
||||
for (let rate of this.getAllRates(animations)) {
|
||||
let option = createNode({
|
||||
parent: this.selectEl,
|
||||
nodeType: "option",
|
||||
attributes: {value: rate},
|
||||
textContent: L10N.getFormatStr("player.playbackRateLabel", rate)
|
||||
});
|
||||
|
||||
// If there's only one rate and this is the option for it, select it.
|
||||
if (hasOneRate && rate === allRates[0]) {
|
||||
option.setAttribute("selected", "true");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onRateChanged: function() {
|
||||
let rate = parseFloat(this.selectEl.value);
|
||||
if (!isNaN(rate)) {
|
||||
this.emit("rate-changed", rate);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The TimeScale helper object is used to know which size should something be
|
||||
* displayed with in the animation panel, depending on the animations that are
|
||||
|
@ -858,21 +957,49 @@ AnimationTimeBlock.prototype = {
|
|||
getTooltipText: function(state) {
|
||||
let getTime = time => L10N.getFormatStr("player.timeLabel",
|
||||
L10N.numberWithDecimals(time / 1000, 2));
|
||||
// The type isn't always available, older servers don't send it.
|
||||
let title =
|
||||
|
||||
let text = "";
|
||||
|
||||
// Adding the name (the type isn't always available, older servers don't
|
||||
// send it).
|
||||
text +=
|
||||
state.type
|
||||
? L10N.getFormatStr("timeline." + state.type + ".nameLabel", state.name)
|
||||
: state.name;
|
||||
let delay = L10N.getStr("player.animationDelayLabel") + " " +
|
||||
getTime(state.delay);
|
||||
let duration = L10N.getStr("player.animationDurationLabel") + " " +
|
||||
getTime(state.duration);
|
||||
let iterations = L10N.getStr("player.animationIterationCountLabel") + " " +
|
||||
(state.iterationCount ||
|
||||
L10N.getStr("player.infiniteIterationCountText"));
|
||||
let compositor = state.isRunningOnCompositor
|
||||
? L10N.getStr("player.runningOnCompositorTooltip")
|
||||
: "";
|
||||
return [title, duration, iterations, delay, compositor].join("\n");
|
||||
text += "\n";
|
||||
|
||||
// Adding the delay.
|
||||
text += L10N.getStr("player.animationDelayLabel") + " ";
|
||||
text += getTime(state.delay);
|
||||
text += "\n";
|
||||
|
||||
// Adding the duration.
|
||||
text += L10N.getStr("player.animationDurationLabel") + " ";
|
||||
text += getTime(state.duration);
|
||||
text += "\n";
|
||||
|
||||
// Adding the iteration count (the infinite symbol, or an integer).
|
||||
// XXX: see bug 1219608 to remove this if the count is 1.
|
||||
text += L10N.getStr("player.animationIterationCountLabel") + " ";
|
||||
text += state.iterationCount ||
|
||||
L10N.getStr("player.infiniteIterationCountText");
|
||||
text += "\n";
|
||||
|
||||
// Adding the playback rate if it's different than 1.
|
||||
if (state.playbackRate !== 1) {
|
||||
text += L10N.getStr("player.animationRateLabel") + " ";
|
||||
text += state.playbackRate;
|
||||
text += "\n";
|
||||
}
|
||||
|
||||
// Adding a note that the animation is running on the compositor thread if
|
||||
// needed.
|
||||
if (state.isRunningOnCompositor) {
|
||||
text += L10N.getStr("player.runningOnCompositorTooltip");
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
let sortedUnique = arr => [...new Set(arr)].sort((a, b) => a > b);
|
||||
|
|
|
@ -28,6 +28,7 @@ support-files =
|
|||
[browser_animation_timeline_currentTime.js]
|
||||
[browser_animation_timeline_header.js]
|
||||
[browser_animation_timeline_pause_button.js]
|
||||
[browser_animation_timeline_rate_selector.js]
|
||||
[browser_animation_timeline_rewind_button.js]
|
||||
[browser_animation_timeline_scrubber_exists.js]
|
||||
[browser_animation_timeline_scrubber_movable.js]
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Check that the timeline toolbar contains a playback rate selector UI and that
|
||||
// it can be used to change the playback rate of animations in the timeline.
|
||||
// Also check that it displays the rate of the current animations in case they
|
||||
// all have the same rate, or that it displays the empty value in case they
|
||||
// have mixed rates.
|
||||
|
||||
add_task(function*() {
|
||||
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||
|
||||
let {panel, controller, inspector, toolbox} = yield openAnimationInspector();
|
||||
|
||||
// In this test, we disable the highlighter on purpose because of the way
|
||||
// events are simulated to select an option in the playbackRate <select>.
|
||||
// Indeed, this may cause mousemove events to be triggered on the nodes that
|
||||
// are underneath the <select>, and these are AnimationTargetNode instances.
|
||||
// Simulating mouse events on them will cause the highlighter to emit requests
|
||||
// and this might cause the test to fail if they happen after it has ended.
|
||||
disableHighlighter(toolbox);
|
||||
|
||||
let select = panel.rateSelectorEl.firstChild;
|
||||
|
||||
ok(select, "The rate selector exists");
|
||||
|
||||
info("Change all of the current animations' rates to 0.5");
|
||||
yield changeTimelinePlaybackRate(panel, .5);
|
||||
checkAllAnimationsRatesChanged(controller, select, .5);
|
||||
|
||||
info("Select just one animated node and change its rate only");
|
||||
yield selectNode(".animated", inspector);
|
||||
|
||||
yield changeTimelinePlaybackRate(panel, 2);
|
||||
checkAllAnimationsRatesChanged(controller, select, 2);
|
||||
|
||||
info("Select the <body> again, it should now have mixed-rates animations");
|
||||
yield selectNode("body", inspector);
|
||||
|
||||
is(select.value, "", "The selected rate is empty");
|
||||
|
||||
info("Change the rate for these mixed-rate animations");
|
||||
yield changeTimelinePlaybackRate(panel, 1);
|
||||
checkAllAnimationsRatesChanged(controller, select, 1);
|
||||
});
|
||||
|
||||
function checkAllAnimationsRatesChanged({animationPlayers}, select, rate) {
|
||||
ok(animationPlayers.every(({state}) => state.playbackRate === rate),
|
||||
"All animations' rates have been set to " + rate);
|
||||
is(select.value, rate, "The right value is displayed in the select");
|
||||
}
|
|
@ -480,6 +480,11 @@ function* assertScrubberMoving(panel, isMoving) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the play/pause button in the timeline toolbar and wait for animations
|
||||
* to update.
|
||||
* @param {AnimationsPanel} panel
|
||||
*/
|
||||
function* clickTimelinePlayPauseButton(panel) {
|
||||
let onUiUpdated = panel.once(panel.UI_UPDATED_EVENT);
|
||||
|
||||
|
@ -491,6 +496,11 @@ function* clickTimelinePlayPauseButton(panel) {
|
|||
yield waitForAllAnimationTargets(panel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the rewind button in the timeline toolbar and wait for animations to
|
||||
* update.
|
||||
* @param {AnimationsPanel} panel
|
||||
*/
|
||||
function* clickTimelineRewindButton(panel) {
|
||||
let onUiUpdated = panel.once(panel.UI_UPDATED_EVENT);
|
||||
|
||||
|
@ -501,3 +511,52 @@ function* clickTimelineRewindButton(panel) {
|
|||
yield onUiUpdated;
|
||||
yield waitForAllAnimationTargets(panel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a rate inside the playback rate selector in the timeline toolbar and
|
||||
* wait for animations to update.
|
||||
* @param {AnimationsPanel} panel
|
||||
* @param {Number} rate The new rate value to be selected
|
||||
*/
|
||||
function* changeTimelinePlaybackRate(panel, rate) {
|
||||
let onUiUpdated = panel.once(panel.UI_UPDATED_EVENT);
|
||||
|
||||
let select = panel.rateSelectorEl.firstChild;
|
||||
let win = select.ownerDocument.defaultView;
|
||||
|
||||
// Get the right option.
|
||||
let option = [...select.options].filter(o => o.value === rate + "")[0];
|
||||
if (!option) {
|
||||
ok(false,
|
||||
"Could not find an option for rate " + rate + " in the rate selector. " +
|
||||
"Values are: " + [...select.options].map(o => o.value));
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulate the right events to select the option in the drop-down.
|
||||
EventUtils.synthesizeMouseAtCenter(select, {type: "mousedown"}, win);
|
||||
EventUtils.synthesizeMouseAtCenter(option, {type: "mouseup"}, win);
|
||||
|
||||
yield onUiUpdated;
|
||||
yield waitForAllAnimationTargets(panel);
|
||||
|
||||
// Simulate a mousemove outside of the rate selector area to avoid subsequent
|
||||
// tests from failing because of unwanted mouseover events.
|
||||
EventUtils.synthesizeMouseAtCenter(win.document.querySelector("#timeline-toolbar"),
|
||||
{type: "mousemove"}, win);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent the toolbox common highlighter from making backend requests.
|
||||
* @param {Toolbox} toolbox
|
||||
*/
|
||||
function disableHighlighter(toolbox) {
|
||||
toolbox._highlighter = {
|
||||
showBoxModel: () => new Promise(r => r()),
|
||||
hideBoxModel: () => new Promise(r => r()),
|
||||
pick: () => new Promise(r => r()),
|
||||
cancelPick: () => new Promise(r => r()),
|
||||
destroy: () => {},
|
||||
traits: {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
|
|||
loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
|
||||
loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/main", true);
|
||||
|
||||
const DefaultTools = require("devtools/client/definitions").defaultTools;
|
||||
const {defaultTools: DefaultTools, defaultThemes: DefaultThemes} =
|
||||
require("devtools/client/definitions");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const Telemetry = require("devtools/client/shared/telemetry");
|
||||
const {JsonView} = require("devtools/client/jsonview/main");
|
||||
|
@ -286,10 +287,17 @@ DevTools.prototype = {
|
|||
|
||||
let currTheme = Services.prefs.getCharPref("devtools.theme");
|
||||
|
||||
// Change the current theme if it's being dynamically removed together
|
||||
// with the owner (bootstrapped) extension.
|
||||
// But, do not change it if the application is just shutting down.
|
||||
if (!Services.startup.shuttingDown && theme.id == currTheme) {
|
||||
// Note that we can't check if `theme` is an item
|
||||
// of `DefaultThemes` as we end up reloading definitions
|
||||
// module and end up with different theme objects
|
||||
let isCoreTheme = DefaultThemes.some(t => t.id === themeId);
|
||||
|
||||
// Reset the theme if an extension theme that's currently applied
|
||||
// is being removed.
|
||||
// Ignore shutdown since addons get disabled during that time.
|
||||
if (!Services.startup.shuttingDown &&
|
||||
!isCoreTheme &&
|
||||
theme.id == currTheme) {
|
||||
Services.prefs.setCharPref("devtools.theme", "light");
|
||||
|
||||
let data = {
|
||||
|
|
|
@ -150,8 +150,9 @@ devtools.jar:
|
|||
content/aboutdebugging/aboutdebugging.js (aboutdebugging/aboutdebugging.js)
|
||||
% skin devtools classic/1.0 %skin/
|
||||
* skin/themes/common.css (themes/common.css)
|
||||
* skin/themes/dark-theme.css (themes/dark-theme.css)
|
||||
* skin/themes/light-theme.css (themes/light-theme.css)
|
||||
skin/themes/dark-theme.css (themes/dark-theme.css)
|
||||
skin/themes/light-theme.css (themes/light-theme.css)
|
||||
skin/themes/toolbars.css (themes/toolbars.css)
|
||||
skin/themes/variables.css (themes/variables.css)
|
||||
skin/themes/images/add.svg (themes/images/add.svg)
|
||||
skin/themes/images/filters.svg (themes/images/filters.svg)
|
||||
|
|
|
@ -85,6 +85,7 @@ skip-if = os == 'linux' # bug 1186322
|
|||
[browser_perf-overview-selection-03.js]
|
||||
[browser_perf-overview-time-interval.js]
|
||||
[browser_perf-private-browsing.js]
|
||||
skip-if = os == 'linux' # bug 1210140
|
||||
[browser_perf-states.js]
|
||||
skip-if = debug # bug 1203888
|
||||
[browser_perf-refresh.js]
|
||||
|
|
|
@ -134,3 +134,4 @@ skip-if = buildapp == 'mulet' || e10s # The developertoolbar error count isn't c
|
|||
[browser_treeWidget_keyboard_interaction.js]
|
||||
[browser_treeWidget_mouse_interaction.js]
|
||||
[browser_devices.js]
|
||||
[browser_theme_switching.js]
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var toolbox;
|
||||
|
||||
add_task(function*() {
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
let toolbox = yield gDevTools.showToolbox(target);
|
||||
let root = toolbox.frame.contentDocument.documentElement;
|
||||
|
||||
let platform = root.getAttribute("platform");
|
||||
let expectedPlatform = getPlatform();
|
||||
is(platform, expectedPlatform, ":root[platform] is correct");
|
||||
|
||||
let theme = Services.prefs.getCharPref("devtools.theme");
|
||||
let className = "theme-" + theme;
|
||||
ok(root.classList.contains(className), ":root has " + className + " class (current theme)");
|
||||
|
||||
yield toolbox.destroy();
|
||||
});
|
||||
|
||||
function getPlatform() {
|
||||
let {OS} = Services.appinfo;
|
||||
if (OS == "WINNT") {
|
||||
return "win";
|
||||
} else if (OS == "Darwin") {
|
||||
return "mac";
|
||||
} else {
|
||||
return "linux";
|
||||
}
|
||||
}
|
|
@ -107,6 +107,17 @@
|
|||
const {require} = Components.utils.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const StylesheetUtils = require("sdk/stylesheet/utils");
|
||||
|
||||
let os;
|
||||
let platform = navigator.platform;
|
||||
if (platform.startsWith("Win")) {
|
||||
os = "win";
|
||||
} else if (platform.startsWith("Mac")) {
|
||||
os = "mac";
|
||||
} else {
|
||||
os = "linux";
|
||||
}
|
||||
documentElement.setAttribute("platform", os);
|
||||
|
||||
if (documentElement.hasAttribute("force-theme")) {
|
||||
switchTheme(documentElement.getAttribute("force-theme"));
|
||||
} else {
|
||||
|
|
|
@ -161,6 +161,13 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
#timeline-rate select {
|
||||
-moz-appearance: none;
|
||||
text-align: center;
|
||||
color: inherit;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
/* Animation timeline component */
|
||||
|
||||
.animation-timeline {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
@import url(variables.css);
|
||||
@import url(toolbars.css);
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
|
@ -374,6 +375,3 @@ div.CodeMirror span.eval-text {
|
|||
background-color: #0f171f;
|
||||
color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
|
||||
%include toolbars.inc.css
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
@import url(variables.css);
|
||||
@import url(toolbars.css);
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
|
@ -372,6 +373,3 @@ div.CodeMirror span.eval-text {
|
|||
box-shadow: 0 0 4px rgba(128, 128, 128, .5);
|
||||
background-color: var(--theme-sidebar-background);
|
||||
}
|
||||
|
||||
|
||||
%include toolbars.inc.css
|
||||
|
|
|
@ -87,7 +87,7 @@ html, body, #app, #memory-tool {
|
|||
* TODO bug 1213100
|
||||
* Once we figure out how to store invertable buttons (pseudo element like in
|
||||
* this case?) we should add a .invertable class to handle this generally,
|
||||
* rather than the definitions in toolbars.inc.css.
|
||||
* rather than the definitions in toolbars.css.
|
||||
*
|
||||
* @see bug 1173397 for another inverted related bug
|
||||
*/
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
%if 0
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
%endif
|
||||
|
||||
/* CSS Variables specific to the devtools toolbar that aren't defined by the themes */
|
||||
.theme-light {
|
||||
|
@ -332,15 +331,16 @@
|
|||
-moz-appearance: none;
|
||||
margin: 1px 3px;
|
||||
border: 1px solid;
|
||||
%ifdef XP_MACOSX
|
||||
border-radius: 20px;
|
||||
%else
|
||||
border-radius: 2px;
|
||||
%endif
|
||||
padding: 4px 6px;
|
||||
border-color: var(--theme-splitter-color);
|
||||
}
|
||||
|
||||
:root[platform="mac"] .devtools-textinput,
|
||||
:root[platform="mac"] .devtools-searchinput {
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.devtools-searchinput {
|
||||
padding: 0;
|
||||
-moz-padding-start: 22px;
|
||||
|
@ -401,7 +401,6 @@
|
|||
|
||||
.devtools-rule-searchbox {
|
||||
-moz-box-flex: 1;
|
||||
padding-right: 23px;
|
||||
width: 100%;
|
||||
font: inherit;
|
||||
}
|
||||
|
@ -409,6 +408,7 @@
|
|||
.devtools-rule-searchbox[filled] {
|
||||
background-color: var(--searchbox-background-color);
|
||||
border-color: var(--searchbox-border-color);
|
||||
padding-right: 23px;
|
||||
}
|
||||
|
||||
.devtools-style-searchbox-no-match {
|
|
@ -265,7 +265,8 @@ self.random = {
|
|||
{
|
||||
let h, n = 0xefc8249d;
|
||||
|
||||
for (let i = 0, data = data.toString(), len = data.length; i < len; i++) {
|
||||
data = data.toString();
|
||||
for (let i = 0, len = data.length; i < len; i++) {
|
||||
n += data.charCodeAt(i);
|
||||
h = 0.02519603282416938 * n;
|
||||
n = h >>> 0;
|
||||
|
|
|
@ -228,8 +228,8 @@ Object.defineProperty(ASPp, "b2gBinary", {
|
|||
file = this.addon.getResourceURI().QueryInterface(Ci.nsIFileURL).file;
|
||||
file.append("firefox");
|
||||
let binaries = {
|
||||
win32: "firefox-bin.exe",
|
||||
mac64: "B2G.app/Contents/MacOS/firefox-bin",
|
||||
win32: "firefox.exe",
|
||||
mac64: "FirefoxNightly.app/Contents/MacOS/firefox-bin",
|
||||
linux32: "firefox-bin",
|
||||
linux64: "firefox-bin",
|
||||
};
|
||||
|
|
|
@ -410,7 +410,7 @@ var AnimationPlayerActor = ActorClass({
|
|||
* Set the current time of the animation player.
|
||||
*/
|
||||
setCurrentTime: method(function(currentTime) {
|
||||
this.player.currentTime = currentTime;
|
||||
this.player.currentTime = currentTime * this.player.playbackRate;
|
||||
}, {
|
||||
request: {
|
||||
currentTime: Arg(0, "number")
|
||||
|
@ -849,6 +849,23 @@ var AnimationsActor = exports.AnimationsActor = ActorClass({
|
|||
shouldPause: Arg(2, "boolean")
|
||||
},
|
||||
response: {}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Set the playback rate of several animations at the same time.
|
||||
* @param {Array} players A list of AnimationPlayerActor.
|
||||
* @param {Number} rate The new rate.
|
||||
*/
|
||||
setPlaybackRates: method(function(players, rate) {
|
||||
for (let player of players) {
|
||||
player.setPlaybackRate(rate);
|
||||
}
|
||||
}, {
|
||||
request: {
|
||||
players: Arg(0, "array:animationplayer"),
|
||||
rate: Arg(1, "number")
|
||||
},
|
||||
response: {}
|
||||
})
|
||||
});
|
||||
|
||||
|
|
|
@ -230,6 +230,12 @@ function WebappsActor(aConnection) {
|
|||
WebappsActor.prototype = {
|
||||
actorPrefix: "webapps",
|
||||
|
||||
// For now, launch and close requests are only supported on B2G products
|
||||
// like devices, mulet/simulators, graphene and b2gdroid.
|
||||
// We set that attribute on the prototype in order to allow test
|
||||
// to enable this feature.
|
||||
supportsLaunch: require("devtools/shared/system").constants.MOZ_B2G,
|
||||
|
||||
disconnect: function () {
|
||||
try {
|
||||
this.unwatchApps();
|
||||
|
@ -873,9 +879,7 @@ WebappsActor.prototype = {
|
|||
|
||||
let deferred = promise.defer();
|
||||
|
||||
if (Services.appinfo.ID &&
|
||||
Services.appinfo.ID != "{3c2e2abc-06d4-11e1-ac3b-374f68613e61}" &&
|
||||
Services.appinfo.ID != "{d1bfe7d9-c01e-4237-998b-7b5f960a4314}") {
|
||||
if (!this.supportsLaunch) {
|
||||
return { error: "notSupported",
|
||||
message: "Not B2G. Can't launch app." };
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
// Check that a player's playbackRate can be changed.
|
||||
// Check that a player's playbackRate can be changed, and that multiple players
|
||||
// can have their rates changed at the same time.
|
||||
|
||||
add_task(function*() {
|
||||
let {client, walker, animations} =
|
||||
|
@ -32,6 +33,19 @@ add_task(function*() {
|
|||
state = yield player.getCurrentState();
|
||||
is(state.playbackRate, 1, "The playbackRate was changed back");
|
||||
|
||||
info("Retrieve several animation players and set their rates");
|
||||
node = yield walker.querySelector(walker.rootNode, "body");
|
||||
let players = yield animations.getAnimationPlayersForNode(node);
|
||||
|
||||
info("Change all animations in <body> to .5 rate");
|
||||
yield animations.setPlaybackRates(players, .5);
|
||||
|
||||
info("Query their states and check they are correct");
|
||||
for (let player of players) {
|
||||
let state = yield player.getCurrentState();
|
||||
is(state.playbackRate, .5, "The playbackRate was updated");
|
||||
}
|
||||
|
||||
yield closeDebuggerClient(client);
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
|
|
@ -90,6 +90,10 @@ function setup() {
|
|||
WebappOSUtils.getPackagePath = function(aApp) {
|
||||
return aApp.basePath + "/" + aApp.id;
|
||||
}
|
||||
|
||||
// Enable launch/close method of the webapps actor
|
||||
let {WebappsActor} = require("devtools/server/actors/webapps");
|
||||
WebappsActor.prototype.supportsLaunch = true;
|
||||
}
|
||||
|
||||
function do_get_webappsdir() {
|
||||
|
|
|
@ -126,8 +126,8 @@ function recursiveWalk(breakdown, edge, report, visitor) {
|
|||
visitor.exit(breakdown, report, edge);
|
||||
} else {
|
||||
visitor.enter(breakdown, report, edge);
|
||||
for (let { edge, referent, breakdown } of getReportEdges(breakdown, report)) {
|
||||
recursiveWalk(breakdown, edge, referent, visitor);
|
||||
for (let { edge, referent, breakdown: subBreakdown } of getReportEdges(breakdown, report)) {
|
||||
recursiveWalk(subBreakdown, edge, referent, visitor);
|
||||
}
|
||||
visitor.exit(breakdown, report, edge);
|
||||
}
|
||||
|
|
|
@ -79,6 +79,27 @@ ConsoleReportCollector::FlushConsoleReports(nsIDocument* aDocument)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConsoleReportCollector::FlushConsoleReports(nsIConsoleReportCollector* aCollector)
|
||||
{
|
||||
MOZ_ASSERT(aCollector);
|
||||
|
||||
nsTArray<PendingReport> reports;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mPendingReports.SwapElements(reports);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < reports.Length(); ++i) {
|
||||
PendingReport& report = reports[i];
|
||||
aCollector->AddConsoleReport(report.mErrorFlags, report.mCategory,
|
||||
report.mPropertiesFile, report.mSourceFileURI,
|
||||
report.mLineNumber, report.mColumnNumber,
|
||||
report.mMessageName, report.mStringParams);
|
||||
}
|
||||
}
|
||||
|
||||
ConsoleReportCollector::~ConsoleReportCollector()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -29,6 +29,9 @@ public:
|
|||
void
|
||||
FlushConsoleReports(nsIDocument* aDocument) override;
|
||||
|
||||
void
|
||||
FlushConsoleReports(nsIConsoleReportCollector* aCollector) override;
|
||||
|
||||
private:
|
||||
~ConsoleReportCollector();
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "ScriptSettings.h"
|
||||
|
||||
using mozilla::Unused; // <snicker>
|
||||
using namespace mozilla::dom;
|
||||
|
@ -650,7 +651,10 @@ nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
|
|||
for (uint32_t i = 0; i < mPermissionRequests.Length(); ++i) {
|
||||
nsCString type = mPermissionRequests[i].type();
|
||||
|
||||
mozilla::AutoSafeJSContext cx;
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
|
||||
JSContext* cx = jsapi.cx();
|
||||
JS::Rooted<JSObject*> obj(cx, &aChoices.toObject());
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
|
||||
|
@ -658,10 +662,12 @@ nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
|
|||
|
||||
if (!JS_GetProperty(cx, obj, type.BeginReading(), &val) ||
|
||||
!val.isString()) {
|
||||
// no setting for the permission type, skip it
|
||||
// no setting for the permission type, clear exception and skip it
|
||||
jsapi.ClearException();
|
||||
} else {
|
||||
nsAutoJSString choice;
|
||||
if (!choice.init(cx, val)) {
|
||||
jsapi.ClearException();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
choices.AppendElement(PermissionChoice(type, choice));
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
aLineNumber, aColumnNumber, aMessageName, params);
|
||||
}
|
||||
|
||||
// Flush all pending reports to the console.
|
||||
// Flush all pending reports to the console. Main thread only.
|
||||
//
|
||||
// aDocument An optional document representing where to flush the
|
||||
// reports. If provided, then the corresponding window's
|
||||
|
@ -74,6 +74,14 @@ public:
|
|||
// go to the browser console.
|
||||
virtual void
|
||||
FlushConsoleReports(nsIDocument* aDocument) = 0;
|
||||
|
||||
// Flush all pending reports to another collector. May be called from any
|
||||
// thread.
|
||||
//
|
||||
// aCollector A required collector object that will effectively take
|
||||
// ownership of our currently console reports.
|
||||
virtual void
|
||||
FlushConsoleReports(nsIConsoleReportCollector* aCollector) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIConsoleReportCollector, NS_NSICONSOLEREPORTCOLLECTOR_IID)
|
||||
|
|
|
@ -329,6 +329,12 @@ JSObject* GetDefaultScopeFromJSContext(JSContext *cx)
|
|||
|
||||
bool nsAutoJSString::init(const JS::Value &v)
|
||||
{
|
||||
return init(nsContentUtils::RootingCxForThread(), v);
|
||||
JSContext* cx = nsContentUtils::RootingCxForThread();
|
||||
if (!init(nsContentUtils::RootingCxForThread(), v)) {
|
||||
JS_ClearPendingException(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,6 +102,8 @@ skip-if = (toolkit == 'gonk' && !debug)
|
|||
[test_browserElement_oop_VisibilityChange.html]
|
||||
[test_browserElement_oop_XFrameOptions.html]
|
||||
[test_browserElement_oop_XFrameOptionsAllowFrom.html]
|
||||
# bug 1189592
|
||||
skip-if = asan
|
||||
[test_browserElement_oop_XFrameOptionsDeny.html]
|
||||
[test_browserElement_oop_XFrameOptionsSameOrigin.html]
|
||||
# Disabled until bug 930449 makes it stop timing out
|
||||
|
|
|
@ -21,10 +21,16 @@ using namespace dom;
|
|||
using namespace gfx;
|
||||
|
||||
struct ImageCacheKey {
|
||||
ImageCacheKey(Element* aImage, HTMLCanvasElement* aCanvas)
|
||||
: mImage(aImage), mCanvas(aCanvas) {}
|
||||
ImageCacheKey(Element* aImage,
|
||||
HTMLCanvasElement* aCanvas,
|
||||
bool aIsAccelerated)
|
||||
: mImage(aImage)
|
||||
, mCanvas(aCanvas)
|
||||
, mIsAccelerated(aIsAccelerated)
|
||||
{}
|
||||
Element* mImage;
|
||||
HTMLCanvasElement* mCanvas;
|
||||
bool mIsAccelerated;
|
||||
};
|
||||
|
||||
struct ImageCacheEntryData {
|
||||
|
@ -32,6 +38,7 @@ struct ImageCacheEntryData {
|
|||
: mImage(aOther.mImage)
|
||||
, mILC(aOther.mILC)
|
||||
, mCanvas(aOther.mCanvas)
|
||||
, mIsAccelerated(aOther.mIsAccelerated)
|
||||
, mRequest(aOther.mRequest)
|
||||
, mSourceSurface(aOther.mSourceSurface)
|
||||
, mSize(aOther.mSize)
|
||||
|
@ -40,6 +47,7 @@ struct ImageCacheEntryData {
|
|||
: mImage(aKey.mImage)
|
||||
, mILC(nullptr)
|
||||
, mCanvas(aKey.mCanvas)
|
||||
, mIsAccelerated(aKey.mIsAccelerated)
|
||||
{}
|
||||
|
||||
nsExpirationState* GetExpirationState() { return &mState; }
|
||||
|
@ -50,6 +58,7 @@ struct ImageCacheEntryData {
|
|||
RefPtr<Element> mImage;
|
||||
nsIImageLoadingContent* mILC;
|
||||
RefPtr<HTMLCanvasElement> mCanvas;
|
||||
bool mIsAccelerated;
|
||||
// Value
|
||||
nsCOMPtr<imgIRequest> mRequest;
|
||||
RefPtr<SourceSurface> mSourceSurface;
|
||||
|
@ -70,46 +79,61 @@ public:
|
|||
|
||||
bool KeyEquals(KeyTypePointer key) const
|
||||
{
|
||||
return mData->mImage == key->mImage && mData->mCanvas == key->mCanvas;
|
||||
return mData->mImage == key->mImage &&
|
||||
mData->mCanvas == key->mCanvas &&
|
||||
mData->mIsAccelerated == key->mIsAccelerated;
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType& key) { return &key; }
|
||||
static PLDHashNumber HashKey(KeyTypePointer key)
|
||||
{
|
||||
return HashGeneric(key->mImage, key->mCanvas);
|
||||
return HashGeneric(key->mImage, key->mCanvas, key->mIsAccelerated);
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
nsAutoPtr<ImageCacheEntryData> mData;
|
||||
};
|
||||
|
||||
struct SimpleImageCacheKey {
|
||||
SimpleImageCacheKey(const imgIRequest* aImage,
|
||||
bool aIsAccelerated)
|
||||
: mImage(aImage)
|
||||
, mIsAccelerated(aIsAccelerated)
|
||||
{}
|
||||
const imgIRequest* mImage;
|
||||
bool mIsAccelerated;
|
||||
};
|
||||
|
||||
class SimpleImageCacheEntry : public PLDHashEntryHdr {
|
||||
public:
|
||||
typedef imgIRequest& KeyType;
|
||||
typedef const imgIRequest* KeyTypePointer;
|
||||
typedef SimpleImageCacheKey KeyType;
|
||||
typedef const SimpleImageCacheKey* KeyTypePointer;
|
||||
|
||||
explicit SimpleImageCacheEntry(KeyTypePointer aKey)
|
||||
: mRequest(const_cast<imgIRequest*>(aKey))
|
||||
: mRequest(const_cast<imgIRequest*>(aKey->mImage))
|
||||
, mIsAccelerated(aKey->mIsAccelerated)
|
||||
{}
|
||||
SimpleImageCacheEntry(const SimpleImageCacheEntry &toCopy)
|
||||
: mRequest(toCopy.mRequest)
|
||||
, mIsAccelerated(toCopy.mIsAccelerated)
|
||||
, mSourceSurface(toCopy.mSourceSurface)
|
||||
{}
|
||||
~SimpleImageCacheEntry() {}
|
||||
|
||||
bool KeyEquals(KeyTypePointer key) const
|
||||
{
|
||||
return key == mRequest;
|
||||
return key->mImage == mRequest && key->mIsAccelerated == mIsAccelerated;
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType key) { return &key; }
|
||||
static KeyTypePointer KeyToPointer(KeyType& key) { return &key; }
|
||||
static PLDHashNumber HashKey(KeyTypePointer key)
|
||||
{
|
||||
return NS_PTR_TO_UINT32(key) >> 2;
|
||||
return HashGeneric(key->mImage, key->mIsAccelerated);
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
nsCOMPtr<imgIRequest> mRequest;
|
||||
bool mIsAccelerated;
|
||||
RefPtr<SourceSurface> mSourceSurface;
|
||||
};
|
||||
|
||||
|
@ -130,8 +154,8 @@ public:
|
|||
mTotal -= aObject->SizeInBytes();
|
||||
RemoveObject(aObject);
|
||||
// Deleting the entry will delete aObject since the entry owns aObject
|
||||
mSimpleCache.RemoveEntry(*aObject->mRequest);
|
||||
mCache.RemoveEntry(ImageCacheKey(aObject->mImage, aObject->mCanvas));
|
||||
mSimpleCache.RemoveEntry(SimpleImageCacheKey(aObject->mRequest, aObject->mIsAccelerated));
|
||||
mCache.RemoveEntry(ImageCacheKey(aObject->mImage, aObject->mCanvas, aObject->mIsAccelerated));
|
||||
}
|
||||
|
||||
nsTHashtable<ImageCacheEntry> mCache;
|
||||
|
@ -237,20 +261,22 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
|
|||
HTMLCanvasElement* aCanvas,
|
||||
imgIRequest* aRequest,
|
||||
SourceSurface* aSource,
|
||||
const IntSize& aSize)
|
||||
const IntSize& aSize,
|
||||
bool aIsAccelerated)
|
||||
{
|
||||
if (!gImageCache) {
|
||||
gImageCache = new ImageCache();
|
||||
nsContentUtils::RegisterShutdownObserver(new CanvasImageCacheShutdownObserver());
|
||||
}
|
||||
|
||||
ImageCacheEntry* entry = gImageCache->mCache.PutEntry(ImageCacheKey(aImage, aCanvas));
|
||||
ImageCacheEntry* entry =
|
||||
gImageCache->mCache.PutEntry(ImageCacheKey(aImage, aCanvas, aIsAccelerated));
|
||||
if (entry) {
|
||||
if (entry->mData->mSourceSurface) {
|
||||
// We are overwriting an existing entry.
|
||||
gImageCache->mTotal -= entry->mData->SizeInBytes();
|
||||
gImageCache->RemoveObject(entry->mData);
|
||||
gImageCache->mSimpleCache.RemoveEntry(*entry->mData->mRequest);
|
||||
gImageCache->mSimpleCache.RemoveEntry(SimpleImageCacheKey(entry->mData->mRequest, entry->mData->mIsAccelerated));
|
||||
}
|
||||
gImageCache->AddObject(entry->mData);
|
||||
|
||||
|
@ -267,7 +293,7 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
|
|||
|
||||
if (entry->mData->mRequest) {
|
||||
SimpleImageCacheEntry* simpleentry =
|
||||
gImageCache->mSimpleCache.PutEntry(*entry->mData->mRequest);
|
||||
gImageCache->mSimpleCache.PutEntry(SimpleImageCacheKey(entry->mData->mRequest, aIsAccelerated));
|
||||
simpleentry->mSourceSurface = aSource;
|
||||
}
|
||||
}
|
||||
|
@ -283,12 +309,14 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
|
|||
SourceSurface*
|
||||
CanvasImageCache::Lookup(Element* aImage,
|
||||
HTMLCanvasElement* aCanvas,
|
||||
gfx::IntSize* aSize)
|
||||
gfx::IntSize* aSize,
|
||||
bool aIsAccelerated)
|
||||
{
|
||||
if (!gImageCache)
|
||||
return nullptr;
|
||||
|
||||
ImageCacheEntry* entry = gImageCache->mCache.GetEntry(ImageCacheKey(aImage, aCanvas));
|
||||
ImageCacheEntry* entry =
|
||||
gImageCache->mCache.GetEntry(ImageCacheKey(aImage, aCanvas, aIsAccelerated));
|
||||
if (!entry || !entry->mData->mILC)
|
||||
return nullptr;
|
||||
|
||||
|
@ -304,7 +332,8 @@ CanvasImageCache::Lookup(Element* aImage,
|
|||
}
|
||||
|
||||
SourceSurface*
|
||||
CanvasImageCache::SimpleLookup(Element* aImage)
|
||||
CanvasImageCache::SimpleLookup(Element* aImage,
|
||||
bool aIsAccelerated)
|
||||
{
|
||||
if (!gImageCache)
|
||||
return nullptr;
|
||||
|
@ -319,7 +348,7 @@ CanvasImageCache::SimpleLookup(Element* aImage)
|
|||
if (!request)
|
||||
return nullptr;
|
||||
|
||||
SimpleImageCacheEntry* entry = gImageCache->mSimpleCache.GetEntry(*request);
|
||||
SimpleImageCacheEntry* entry = gImageCache->mSimpleCache.GetEntry(SimpleImageCacheKey(request, aIsAccelerated));
|
||||
if (!entry)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -33,7 +33,8 @@ public:
|
|||
dom::HTMLCanvasElement* aCanvas,
|
||||
imgIRequest* aRequest,
|
||||
SourceSurface* aSource,
|
||||
const gfx::IntSize& aSize);
|
||||
const gfx::IntSize& aSize,
|
||||
bool aIsAccelerated);
|
||||
|
||||
/**
|
||||
* Check whether aImage has recently been drawn into aCanvas. If we return
|
||||
|
@ -43,14 +44,16 @@ public:
|
|||
*/
|
||||
static SourceSurface* Lookup(dom::Element* aImage,
|
||||
dom::HTMLCanvasElement* aCanvas,
|
||||
gfx::IntSize* aSize);
|
||||
gfx::IntSize* aSize,
|
||||
bool aIsAccelerated);
|
||||
|
||||
/**
|
||||
* This is the same as Lookup, except it works on any image recently drawn
|
||||
* into any canvas. Security checks need to be done again if using the
|
||||
* results from this.
|
||||
*/
|
||||
static SourceSurface* SimpleLookup(dom::Element* aImage);
|
||||
static SourceSurface* SimpleLookup(dom::Element* aImage,
|
||||
bool aIsAccelerated);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -4312,7 +4312,8 @@ CanvasRenderingContext2D::CachedSurfaceFromElement(Element* aElement)
|
|||
return res;
|
||||
}
|
||||
|
||||
res.mSourceSurface = CanvasImageCache::SimpleLookup(aElement);
|
||||
res.mSourceSurface =
|
||||
CanvasImageCache::SimpleLookup(aElement, mIsSkiaGL);
|
||||
if (!res.mSourceSurface) {
|
||||
return res;
|
||||
}
|
||||
|
@ -4418,7 +4419,7 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
|
|||
}
|
||||
|
||||
srcSurf =
|
||||
CanvasImageCache::Lookup(element, mCanvasElement, &imgSize);
|
||||
CanvasImageCache::Lookup(element, mCanvasElement, &imgSize, mIsSkiaGL);
|
||||
}
|
||||
|
||||
nsLayoutUtils::DirectDrawInfo drawInfo;
|
||||
|
@ -4566,7 +4567,7 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
|
|||
if (res.mSourceSurface) {
|
||||
if (res.mImageRequest) {
|
||||
CanvasImageCache::NotifyDrawImage(element, mCanvasElement, res.mImageRequest,
|
||||
res.mSourceSurface, imgSize);
|
||||
res.mSourceSurface, imgSize, mIsSkiaGL);
|
||||
}
|
||||
|
||||
srcSurf = res.mSourceSurface;
|
||||
|
|
|
@ -508,6 +508,7 @@ skip-if = os == 'android'
|
|||
skip-if = os == 'mac'
|
||||
[webgl-conformance/_wrappers/test_conformance__canvas__drawingbuffer-test.html]
|
||||
[webgl-conformance/_wrappers/test_conformance__canvas__viewport-unchanged-upon-resize.html]
|
||||
skip-if = os == 'mac'
|
||||
[webgl-conformance/_wrappers/test_conformance__context__constants.html]
|
||||
[webgl-conformance/_wrappers/test_conformance__context__context-attributes-alpha-depth-stencil-antialias.html]
|
||||
skip-if = (os == 'b2g')
|
||||
|
|
|
@ -108,6 +108,9 @@ fail-if = (os == 'linux')
|
|||
[_wrappers/test_conformance__canvas__drawingbuffer-static-canvas-test.html]
|
||||
# Intermittent crash on OSX.
|
||||
skip-if = os == 'mac'
|
||||
[_wrappers/test_conformance__canvas__viewport-unchanged-upon-resize.html]
|
||||
# New OSX r7 machines and 10.10.5 is causing perma failure (bug 1216549)
|
||||
skip-if = os == 'mac'
|
||||
|
||||
########################################################################
|
||||
# Win
|
||||
|
|
|
@ -2557,6 +2557,8 @@ EventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame,
|
|||
case WidgetWheelEvent::SCROLL_DEFAULT:
|
||||
if (isDeltaModePixel) {
|
||||
mode = nsIScrollableFrame::NORMAL;
|
||||
} else if (aEvent->mFlags.mHandledByAPZ) {
|
||||
mode = nsIScrollableFrame::SMOOTH_MSD;
|
||||
} else {
|
||||
mode = nsIScrollableFrame::SMOOTH;
|
||||
}
|
||||
|
@ -3119,6 +3121,14 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
|||
if (pluginFrame) {
|
||||
MOZ_ASSERT(pluginFrame->WantsToHandleWheelEventAsDefaultAction());
|
||||
action = WheelPrefs::ACTION_SEND_TO_PLUGIN;
|
||||
} else if (nsLayoutUtils::IsScrollFrameWithSnapping(frameToScroll)) {
|
||||
// If the target has scroll-snapping points then we want to handle
|
||||
// the wheel event on the main thread even if we have APZ enabled. Do
|
||||
// so and let the APZ know that it should ignore this event.
|
||||
if (wheelEvent->mFlags.mHandledByAPZ) {
|
||||
wheelEvent->mFlags.mDefaultPrevented = true;
|
||||
}
|
||||
action = WheelPrefs::GetInstance()->ComputeActionFor(wheelEvent);
|
||||
} else if (wheelEvent->mFlags.mHandledByAPZ) {
|
||||
action = WheelPrefs::ACTION_NONE;
|
||||
} else {
|
||||
|
|
|
@ -459,25 +459,22 @@ HangMonitorParent::HangMonitorParent(ProcessHangMonitor* aMonitor)
|
|||
mReportHangs = mozilla::Preferences::GetBool("dom.ipc.reportProcessHangs", false);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
DeleteMinidump(const uint32_t& aPluginId, nsString aCrashId, void* aUserData)
|
||||
{
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
if (!aCrashId.IsEmpty()) {
|
||||
CrashReporter::DeleteMinidumpFilesForID(aCrashId);
|
||||
}
|
||||
#endif
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
HangMonitorParent::~HangMonitorParent()
|
||||
{
|
||||
// For some reason IPDL doesn't automatically delete the channel for a
|
||||
// bridged protocol (bug 1090570). So we have to do it ourselves.
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(GetTransport()));
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
MutexAutoLock lock(mBrowserCrashDumpHashLock);
|
||||
mBrowserCrashDumpIds.EnumerateRead(DeleteMinidump, nullptr);
|
||||
|
||||
for (auto iter = mBrowserCrashDumpIds.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsString crashId = iter.UserData();
|
||||
if (!crashId.IsEmpty()) {
|
||||
CrashReporter::DeleteMinidumpFilesForID(crashId);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -599,37 +599,19 @@ ProcessPriorityManagerImpl::ObserveContentParentDestroyed(nsISupports* aSubject)
|
|||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
FreezeParticularProcessPriorityManagers(
|
||||
const uint64_t& aKey,
|
||||
RefPtr<ParticularProcessPriorityManager> aValue,
|
||||
void* aUserData)
|
||||
{
|
||||
aValue->Freeze();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
UnfreezeParticularProcessPriorityManagers(
|
||||
const uint64_t& aKey,
|
||||
RefPtr<ParticularProcessPriorityManager> aValue,
|
||||
void* aUserData)
|
||||
{
|
||||
aValue->Unfreeze();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManagerImpl::ObserveScreenStateChanged(const char16_t* aData)
|
||||
{
|
||||
if (NS_LITERAL_STRING("on").Equals(aData)) {
|
||||
sFrozen = false;
|
||||
mParticularManagers.EnumerateRead(
|
||||
&UnfreezeParticularProcessPriorityManagers, nullptr);
|
||||
for (auto iter = mParticularManagers.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.UserData()->Unfreeze();
|
||||
}
|
||||
} else {
|
||||
sFrozen = true;
|
||||
mParticularManagers.EnumerateRead(
|
||||
&FreezeParticularProcessPriorityManagers, nullptr);
|
||||
for (auto iter = mParticularManagers.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.UserData()->Freeze();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -198,14 +198,14 @@ VideoData::ShallowCopyUpdateTimestampAndDuration(const VideoData* aOther,
|
|||
}
|
||||
|
||||
/* static */
|
||||
void VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
const VideoInfo& aInfo,
|
||||
const YCbCrBuffer &aBuffer,
|
||||
const IntRect& aPicture,
|
||||
bool aCopyData)
|
||||
{
|
||||
if (!aVideoImage) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
|
||||
const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
|
||||
|
@ -229,9 +229,9 @@ void VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
|||
|
||||
aVideoImage->SetDelayedConversion(true);
|
||||
if (aCopyData) {
|
||||
aVideoImage->SetData(data);
|
||||
return aVideoImage->SetData(data);
|
||||
} else {
|
||||
aVideoImage->SetDataNoCopy(data);
|
||||
return aVideoImage->SetDataNoCopy(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,12 +330,10 @@ VideoData::Create(const VideoInfo& aInfo,
|
|||
"Wrong format?");
|
||||
PlanarYCbCrImage* videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
|
||||
|
||||
if (!aImage) {
|
||||
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||
true /* aCopyData */);
|
||||
} else {
|
||||
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||
false /* aCopyData */);
|
||||
bool shouldCopyData = (aImage == nullptr);
|
||||
if (!VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||
shouldCopyData)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
|
@ -346,8 +344,10 @@ VideoData::Create(const VideoInfo& aInfo,
|
|||
return nullptr;
|
||||
}
|
||||
videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
|
||||
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||
true /* aCopyData */);
|
||||
if(!VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||
true /* aCopyData */)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return v.forget();
|
||||
|
@ -473,7 +473,9 @@ VideoData::Create(const VideoInfo& aInfo,
|
|||
data.mPicSize = aPicture.Size();
|
||||
data.mGraphicBuffer = aBuffer;
|
||||
|
||||
videoImage->SetData(data);
|
||||
if (!videoImage->SetData(data)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return v.forget();
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ public:
|
|||
|
||||
// Initialize PlanarYCbCrImage. Only When aCopyData is true,
|
||||
// video data is copied to PlanarYCbCrImage.
|
||||
static void SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
static bool SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
const VideoInfo& aInfo,
|
||||
const YCbCrBuffer &aBuffer,
|
||||
const IntRect& aPicture,
|
||||
|
|
|
@ -745,6 +745,9 @@ MediaDecoder::NotifyDataEnded(nsresult aStatus)
|
|||
{
|
||||
RefPtr<MediaDecoder> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
|
||||
if (self->mShuttingDown) {
|
||||
return;
|
||||
}
|
||||
self->NotifyDownloadEnded(aStatus);
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
HTMLMediaElement* element = self->mOwner->GetMediaElement();
|
||||
|
|
|
@ -80,7 +80,10 @@ VideoFrame::CreateBlackImage(const gfx::IntSize& aSize)
|
|||
data.mStereoMode = StereoMode::MONO;
|
||||
|
||||
// SetData copies data, so we can free data.
|
||||
planar->SetData(data);
|
||||
if (!planar->SetData(data)) {
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return image.forget();
|
||||
}
|
||||
|
|
|
@ -58,6 +58,12 @@ var gVideoTests = [
|
|||
{ name:"bogus.duh", type:"bogus/duh" }
|
||||
];
|
||||
|
||||
// Temp hack for trackIDs and captureStream() -- bug 1215769
|
||||
var gLongerTests = [
|
||||
{ name:"seek.webm", type:"video/webm", width:320, height:240, duration:3.966 },
|
||||
{ name:"gizmo.mp4", type:"video/mp4", width:560, height:320, duration:5.56 },
|
||||
];
|
||||
|
||||
// Used by test_progress to ensure we get the correct progress information
|
||||
// during resource download.
|
||||
var gProgressTests = [
|
||||
|
|
|
@ -14,7 +14,7 @@ createHTML({
|
|||
title: "Captured video-only over peer connection",
|
||||
visible: true
|
||||
}).then(() => new Promise(resolve => {
|
||||
manager.runTests(getPlayableVideos(gSmallTests), startTest);
|
||||
manager.runTests(getPlayableVideos(gLongerTests), startTest);
|
||||
manager.onFinished = () => {
|
||||
// Tear down before SimpleTest.finish.
|
||||
if ("nsINetworkInterfaceListService" in SpecialPowers.Ci) {
|
||||
|
|
|
@ -250,10 +250,16 @@ MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
|
|||
0, 0);
|
||||
#endif
|
||||
|
||||
ycbcr_image->SetData(data);
|
||||
bool setData = ycbcr_image->SetData(data);
|
||||
MOZ_ASSERT(setData);
|
||||
|
||||
// SetData copies data, so we can free the frame
|
||||
ReleaseFrame(data);
|
||||
|
||||
if (!setData) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
// implicitly releases last image
|
||||
|
|
|
@ -315,7 +315,10 @@ MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer,
|
|||
data.mPicSize = IntSize(mWidth, mHeight);
|
||||
data.mStereoMode = StereoMode::MONO;
|
||||
|
||||
videoImage->SetData(data);
|
||||
if (!videoImage->SetData(data)) {
|
||||
MOZ_ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static uint32_t frame_num = 0;
|
||||
|
|
|
@ -1444,31 +1444,6 @@ PluginInstanceParent::AllocPPluginScriptableObjectParent()
|
|||
return new PluginScriptableObjectParent(Proxy);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
namespace {
|
||||
|
||||
struct ActorSearchData
|
||||
{
|
||||
PluginScriptableObjectParent* actor;
|
||||
bool found;
|
||||
};
|
||||
|
||||
PLDHashOperator
|
||||
ActorSearch(NPObject* aKey,
|
||||
PluginScriptableObjectParent* aData,
|
||||
void* aUserData)
|
||||
{
|
||||
ActorSearchData* asd = reinterpret_cast<ActorSearchData*>(aUserData);
|
||||
if (asd->actor == aData) {
|
||||
asd->found = true;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#endif // DEBUG
|
||||
|
||||
bool
|
||||
PluginInstanceParent::DeallocPPluginScriptableObjectParent(
|
||||
PPluginScriptableObjectParent* aObject)
|
||||
|
@ -1484,9 +1459,10 @@ PluginInstanceParent::DeallocPPluginScriptableObjectParent(
|
|||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
ActorSearchData asd = { actor, false };
|
||||
mScriptableObjects.EnumerateRead(ActorSearch, &asd);
|
||||
NS_ASSERTION(!asd.found, "Actor in the hash with a null NPObject!");
|
||||
for (auto iter = mScriptableObjects.Iter(); !iter.Done(); iter.Next()) {
|
||||
NS_ASSERTION(actor != iter.UserData(),
|
||||
"Actor in the hash with a null NPObject!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -22,16 +22,17 @@ interface nsITCPDeviceInfo: nsISupports
|
|||
readonly attribute uint16_t port;
|
||||
};
|
||||
|
||||
[scriptable, uuid(fbb890a9-9e95-47d1-a425-86fd95881d81)]
|
||||
[scriptable, uuid(09bddfaf-fcc2-4dc9-b33e-a509a1c2fb6d)]
|
||||
interface nsITCPPresentationServerListener: nsISupports
|
||||
{
|
||||
/**
|
||||
* Callback while the server socket stops listening.
|
||||
* @param aReason
|
||||
* The reason of the socket close. NS_OK for manually |close|.
|
||||
* <other-error> on failure.
|
||||
* Callback while the server socket changes port.
|
||||
* This event won't be cached so you should get current port after setting
|
||||
* this listener to make sure the value is updated.
|
||||
* @param aPort
|
||||
* The port of the server socket.
|
||||
*/
|
||||
void onClose(in nsresult aReason);
|
||||
void onPortChange(in uint16_t aPort);
|
||||
|
||||
/**
|
||||
* Callback while the remote host is requesting to start a presentation session.
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "nsIPropertyBag2.h"
|
||||
|
@ -25,16 +26,12 @@
|
|||
|
||||
#define SERVICE_TYPE "_mozilla_papi._tcp."
|
||||
|
||||
inline static PRLogModuleInfo*
|
||||
GetProviderLog()
|
||||
{
|
||||
static PRLogModuleInfo* log = PR_NewLogModule("MulticastDNSDeviceProvider");
|
||||
return log;
|
||||
}
|
||||
static mozilla::LazyLogModule sMulticastDNSProviderLogModule("MulticastDNSDeviceProvider");
|
||||
|
||||
#undef LOG_I
|
||||
#define LOG_I(...) MOZ_LOG(GetProviderLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG_I(...) MOZ_LOG(sMulticastDNSProviderLogModule, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#undef LOG_E
|
||||
#define LOG_E(...) MOZ_LOG(GetProviderLog(), mozilla::LogLevel::Error, (__VA_ARGS__))
|
||||
#define LOG_E(...) MOZ_LOG(sMulticastDNSProviderLogModule, mozilla::LogLevel::Error, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -261,20 +258,35 @@ MulticastDNSDeviceProvider::RegisterService()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mRegisterRequest);
|
||||
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->SetListener(mWrappedListener)))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->StartService(0)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint16_t servicePort;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->GetPort(&servicePort)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* If |servicePort| is non-zero, it means PresentationServer is running.
|
||||
* Otherwise, we should make it start serving.
|
||||
*/
|
||||
if (!servicePort) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->SetListener(mWrappedListener)))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->StartService(0)))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->GetPort(&servicePort)))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel on going service registration.
|
||||
if (mRegisterRequest) {
|
||||
mRegisterRequest->Cancel(NS_OK);
|
||||
mRegisterRequest = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the presentation control channel server as an mDNS service.
|
||||
*/
|
||||
|
@ -755,12 +767,9 @@ MulticastDNSDeviceProvider::OnRegistrationFailed(nsIDNSServiceInfo* aServiceInfo
|
|||
|
||||
mRegisterRequest = nullptr;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (aErrorCode == nsIDNSRegistrationListener::ERROR_SERVICE_NOT_RUNNING) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = RegisterService()))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_DispatchToMainThread(
|
||||
NS_NewRunnableMethod(this, &MulticastDNSDeviceProvider::RegisterService));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -855,17 +864,13 @@ MulticastDNSDeviceProvider::OnResolveFailed(nsIDNSServiceInfo* aServiceInfo,
|
|||
|
||||
// nsITCPPresentationServerListener
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnClose(nsresult aReason)
|
||||
MulticastDNSDeviceProvider::OnPortChange(uint16_t aPort)
|
||||
{
|
||||
LOG_I("OnClose: %x", aReason);
|
||||
LOG_I("OnPortChange: %d", aPort);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
UnregisterService(aReason);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (mDiscoverable && NS_WARN_IF(NS_FAILED(rv = RegisterService()))) {
|
||||
return rv;
|
||||
if (mDiscoverable) {
|
||||
RegisterService();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -40,16 +40,11 @@ TCPPresentationServer.prototype = {
|
|||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (typeof aPort === "undefined") {
|
||||
DEBUG && log("TCPPresentationServer - aPort should not be undefined");
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 0 or undefined indicates opt-out parameter, and a port will be selected
|
||||
* automatically.
|
||||
*/
|
||||
let serverSocketPort = (aPort !== 0) ? aPort : -1;
|
||||
let serverSocketPort = (typeof aPort !== "undefined" && aPort !== 0) ? aPort : -1;
|
||||
|
||||
this._serverSocket = Cc["@mozilla.org/network/server-socket;1"]
|
||||
.createInstance(Ci.nsIServerSocket);
|
||||
|
@ -70,7 +65,12 @@ TCPPresentationServer.prototype = {
|
|||
|
||||
this._port = this._serverSocket.port;
|
||||
|
||||
DEBUG && log("TCPPresentationServer - service start on port: " + aPort);
|
||||
DEBUG && log("TCPPresentationServer - service start on port: " + this._port);
|
||||
|
||||
// Monitor network interface change to restart server socket.
|
||||
// Only B2G has nsINetworkManager
|
||||
Services.obs.addObserver(this, "network-active-changed", false);
|
||||
Services.obs.addObserver(this, "network:offline-status-changed", false);
|
||||
},
|
||||
|
||||
get id() {
|
||||
|
@ -178,31 +178,74 @@ TCPPresentationServer.prototype = {
|
|||
// nsIServerSocketListener (Triggered by nsIServerSocket.init)
|
||||
onStopListening: function(aServerSocket, aStatus) {
|
||||
DEBUG && log("TCPPresentationServer - onStopListening: " + aStatus);
|
||||
|
||||
if (this._serverSocket) {
|
||||
DEBUG && log("TCPPresentationServer - should be non-manually closed");
|
||||
this.close();
|
||||
} else if (aStatus === Cr.NS_BINDING_ABORTED) {
|
||||
DEBUG && log("TCPPresentationServer - should be manually closed");
|
||||
aStatus = Cr.NS_OK;
|
||||
}
|
||||
|
||||
this._listener && this._listener.onClose(aStatus);
|
||||
},
|
||||
|
||||
close: function() {
|
||||
DEBUG && log("TCPPresentationServer - close");
|
||||
if (this._serverSocket) {
|
||||
if (this._isServiceInit()) {
|
||||
DEBUG && log("TCPPresentationServer - close server socket");
|
||||
this._serverSocket.close();
|
||||
this._serverSocket = null;
|
||||
|
||||
Services.obs.removeObserver(this, "network-active-changed");
|
||||
Services.obs.removeObserver(this, "network:offline-status-changed");
|
||||
}
|
||||
this._port = 0;
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
DEBUG && log("TCPPresentationServer - observe: " + aTopic);
|
||||
switch (aTopic) {
|
||||
case "network-active-changed": {
|
||||
if (!aSubject) {
|
||||
DEBUG && log("No active network");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart service only when original status is online because other
|
||||
* cases will be handled by "network:offline-status-changed".
|
||||
*/
|
||||
if (!Services.io.offline) {
|
||||
this._restartService();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "network:offline-status-changed": {
|
||||
if (aData == "offline") {
|
||||
DEBUG && log("network offline");
|
||||
return;
|
||||
}
|
||||
this._restartService();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_restartService: function() {
|
||||
DEBUG && log("TCPPresentationServer - restart service");
|
||||
|
||||
// restart server socket
|
||||
if (this._isServiceInit()) {
|
||||
let port = this._port;
|
||||
this.close();
|
||||
|
||||
try {
|
||||
this.startService();
|
||||
if (this._listener && this._port !== port) {
|
||||
this._listener.onPortChange(this._port);
|
||||
}
|
||||
} catch (e) {
|
||||
DEBUG && log("TCPPresentationServer - restart service fail: " + e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
classID: Components.ID("{f4079b8b-ede5-4b90-a112-5b415a931deb}"),
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIServerSocketListener,
|
||||
Ci.nsITCPPresentationServer]),
|
||||
Ci.nsITCPPresentationServer,
|
||||
Ci.nsIObserver]),
|
||||
};
|
||||
|
||||
function ChannelDescription(aInit) {
|
||||
|
|
|
@ -1002,7 +1002,8 @@ function serverClosed() {
|
|||
Assert.equal(listener.devices.length, 1);
|
||||
|
||||
let serverListener = provider.QueryInterface(Ci.nsITCPPresentationServerListener);
|
||||
serverListener.onClose(Cr.NS_ERROR_UNEXPECTED);
|
||||
let randomPort = 9527;
|
||||
serverListener.onPortChange(randomPort);
|
||||
|
||||
Assert.equal(mockObj.serviceRegistered, 2);
|
||||
Assert.equal(mockObj.serviceUnregistered, 1);
|
||||
|
|
|
@ -183,17 +183,17 @@ function testPresentationServer() {
|
|||
}
|
||||
|
||||
function setOffline() {
|
||||
let expectedReason;
|
||||
tps.listener = {
|
||||
onClose: function(aReason) {
|
||||
Assert.equal(aReason, Cr.NS_ERROR_ABORT, 'TCPPresentationServer close as expected');
|
||||
Services.io.offline = false;
|
||||
onPortChange: function(aPort) {
|
||||
Assert.notEqual(aPort, 0, 'TCPPresentationServer port changed and the port should be valid');
|
||||
tps.close();
|
||||
run_next_test();
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
// Let the server socket be closed non-manually
|
||||
// Let the server socket restart automatically.
|
||||
Services.io.offline = true;
|
||||
Services.io.offline = false;
|
||||
}
|
||||
|
||||
function oneMoreLoop() {
|
||||
|
@ -210,12 +210,13 @@ function oneMoreLoop() {
|
|||
function shutdown()
|
||||
{
|
||||
tps.listener = {
|
||||
onClose: function(aReason) {
|
||||
Assert.equal(aReason, Cr.NS_OK, 'TCPPresentationServer close success');
|
||||
run_next_test();
|
||||
onPortChange: function(aPort) {
|
||||
Assert.ok(false, 'TCPPresentationServer port changed');
|
||||
},
|
||||
}
|
||||
};
|
||||
tps.close();
|
||||
Assert.equal(tps.port, 0, "TCPPresentationServer closed");
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
// Test manually close control channel with NS_ERROR_FAILURE
|
||||
|
|
|
@ -113,10 +113,7 @@ AsyncLog(nsIInterceptedChannel *aInterceptedChannel,
|
|||
const nsACString& aMessageName, const nsTArray<nsString>& aParams)
|
||||
{
|
||||
MOZ_ASSERT(aInterceptedChannel);
|
||||
// Since the intercepted channel is kept alive and paused while handling
|
||||
// the FetchEvent, we are guaranteed the reporter is stable on the worker
|
||||
// thread.
|
||||
nsIConsoleReportCollector* reporter =
|
||||
nsCOMPtr<nsIConsoleReportCollector> reporter =
|
||||
aInterceptedChannel->GetConsoleReportCollector();
|
||||
if (reporter) {
|
||||
reporter->AddConsoleReport(nsIScriptError::errorFlag,
|
||||
|
|
|
@ -27,14 +27,12 @@ public:
|
|||
protected:
|
||||
virtual ~nsGroupsEnumerator();
|
||||
|
||||
static PLDHashOperator HashEnum(const nsACString& aKey,
|
||||
nsTArray<nsCString>* aData, void* aClosure);
|
||||
nsresult Initialize();
|
||||
|
||||
protected:
|
||||
nsControllerCommandGroup::GroupsHashtable& mHashTable;
|
||||
int32_t mIndex;
|
||||
char** mGroupNames; // array of pointers to char16_t* in the hash table
|
||||
const char** mGroupNames; // array of pointers to char16_t* in the hash table
|
||||
bool mInitted;
|
||||
};
|
||||
|
||||
|
@ -92,7 +90,7 @@ nsGroupsEnumerator::GetNext(nsISupports** aResult)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
char* thisGroupName = mGroupNames[mIndex];
|
||||
const char* thisGroupName = mGroupNames[mIndex];
|
||||
|
||||
nsCOMPtr<nsISupportsCString> supportsString =
|
||||
do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
|
||||
|
@ -104,18 +102,6 @@ nsGroupsEnumerator::GetNext(nsISupports** aResult)
|
|||
return CallQueryInterface(supportsString, aResult);
|
||||
}
|
||||
|
||||
/* static */
|
||||
/* return false to stop */
|
||||
PLDHashOperator
|
||||
nsGroupsEnumerator::HashEnum(const nsACString& aKey, nsTArray<nsCString>* aData,
|
||||
void* aClosure)
|
||||
{
|
||||
nsGroupsEnumerator* groupsEnum = static_cast<nsGroupsEnumerator*>(aClosure);
|
||||
groupsEnum->mGroupNames[groupsEnum->mIndex] = (char*)aKey.Data();
|
||||
groupsEnum->mIndex++;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGroupsEnumerator::Initialize()
|
||||
{
|
||||
|
@ -123,13 +109,16 @@ nsGroupsEnumerator::Initialize()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
mGroupNames = new char*[mHashTable.Count()];
|
||||
mGroupNames = new const char*[mHashTable.Count()];
|
||||
if (!mGroupNames) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mIndex = 0;
|
||||
mHashTable.EnumerateRead(HashEnum, this);
|
||||
for (auto iter = mHashTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
mGroupNames[mIndex] = iter.Key().Data();
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
mIndex = -1;
|
||||
mInitted = true;
|
||||
|
|
|
@ -34,29 +34,19 @@ nsCommandManager::~nsCommandManager()
|
|||
{
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
TraverseCommandObservers(const char* aKey,
|
||||
nsCommandManager::ObserverList* aObservers,
|
||||
void* aClosure)
|
||||
{
|
||||
nsCycleCollectionTraversalCallback* cb =
|
||||
static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
|
||||
|
||||
int32_t i, numItems = aObservers->Length();
|
||||
for (i = 0; i < numItems; ++i) {
|
||||
cb->NoteXPCOMChild(aObservers->ElementAt(i));
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsCommandManager)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCommandManager)
|
||||
tmp->mObserversTable.Clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCommandManager)
|
||||
tmp->mObserversTable.EnumerateRead(TraverseCommandObservers, &cb);
|
||||
for (auto iter = tmp->mObserversTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCommandManager::ObserverList* observers = iter.UserData();
|
||||
int32_t numItems = observers->Length();
|
||||
for (int32_t i = 0; i < numItems; ++i) {
|
||||
cb.NoteXPCOMChild(observers->ElementAt(i));
|
||||
}
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCommandManager)
|
||||
|
|
|
@ -178,18 +178,6 @@ nsControllerCommandTable::GetCommandState(const char* aCommandName,
|
|||
aCommandRefCon);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
AddCommand(const nsACString& aKey, nsIControllerCommand* aData, void* aArg)
|
||||
{
|
||||
// aArg is a pointer to a array of strings. It gets incremented after
|
||||
// allocating each one so that it points to the next location for AddCommand
|
||||
// to assign a string to.
|
||||
char*** commands = static_cast<char***>(aArg);
|
||||
(**commands) = ToNewCString(aKey);
|
||||
(*commands)++;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsControllerCommandTable::GetSupportedCommands(uint32_t* aCount,
|
||||
char*** aCommands)
|
||||
|
@ -199,7 +187,10 @@ nsControllerCommandTable::GetSupportedCommands(uint32_t* aCount,
|
|||
*aCount = mCommandsTable.Count();
|
||||
*aCommands = commands;
|
||||
|
||||
mCommandsTable.EnumerateRead(AddCommand, &commands);
|
||||
for (auto iter = mCommandsTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
*commands = ToNewCString(iter.Key());
|
||||
commands++;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,12 +103,6 @@ struct nsWebBrowserPersist::URIData
|
|||
nsresult GetLocalURI(nsIURI *targetBaseURI, nsCString& aSpecOut);
|
||||
};
|
||||
|
||||
struct nsWebBrowserPersist::URIFixupData
|
||||
{
|
||||
RefPtr<FlatURIMap> mFlatMap;
|
||||
nsCOMPtr<nsIURI> mTargetBaseURI;
|
||||
};
|
||||
|
||||
// Information about the output stream
|
||||
struct nsWebBrowserPersist::OutputData
|
||||
{
|
||||
|
@ -593,13 +587,69 @@ nsWebBrowserPersist::SerializeNextFile()
|
|||
// number of times this method is called. If it becomes a
|
||||
// bottleneck, the count of not-yet-persisted URIs could be
|
||||
// maintained separately.
|
||||
mURIMap.EnumerateRead(EnumCountURIsToPersist, &urisToPersist);
|
||||
for (auto iter = mURIMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
URIData *data = iter.UserData();
|
||||
if (data->mNeedsPersisting && !data->mSaved) {
|
||||
urisToPersist++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (urisToPersist > 0) {
|
||||
// Persist each file in the uri map. The document(s)
|
||||
// will be saved after the last one of these is saved.
|
||||
mURIMap.EnumerateRead(EnumPersistURIs, this);
|
||||
for (auto iter = mURIMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
URIData *data = iter.UserData();
|
||||
|
||||
if (!data->mNeedsPersisting || data->mSaved) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Create a URI from the key.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), iter.Key(),
|
||||
data->mCharset.get());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Make a URI to save the data to.
|
||||
nsCOMPtr<nsIURI> fileAsURI;
|
||||
rv = data->mDataPath->Clone(getter_AddRefs(fileAsURI));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
break;
|
||||
}
|
||||
rv = AppendPathToURI(fileAsURI, data->mFilename);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// The Referrer Policy doesn't matter here since the referrer is
|
||||
// nullptr.
|
||||
rv = SaveURIInternal(uri, nullptr, nullptr,
|
||||
mozilla::net::RP_Default, nullptr, nullptr,
|
||||
fileAsURI, true, mIsPrivate);
|
||||
// If SaveURIInternal fails, then it will have called EndDownload,
|
||||
// which means that |data| is no longer valid memory. We MUST bail.
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (rv == NS_OK) {
|
||||
// Store the actual object because once it's persisted this
|
||||
// will be fixed up with the right file extension.
|
||||
data->mFile = fileAsURI;
|
||||
data->mSaved = true;
|
||||
} else {
|
||||
data->mNeedsFixup = false;
|
||||
}
|
||||
|
||||
if (mSerializingOutput) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there are downloads happening, wait until they're done; the
|
||||
|
@ -652,17 +702,18 @@ nsWebBrowserPersist::SerializeNextFile()
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mFlatURIMap must be rebuilt each time through SerializeNextFile, as
|
||||
// mTargetBaseURI is used to create the relative URLs and will be different
|
||||
// with each serialized document.
|
||||
RefPtr<FlatURIMap> flatMap = new FlatURIMap(targetBaseSpec);
|
||||
|
||||
URIFixupData fixupData;
|
||||
fixupData.mFlatMap = flatMap;
|
||||
fixupData.mTargetBaseURI = mTargetBaseURI;
|
||||
|
||||
mURIMap.EnumerateRead(EnumCopyURIsToFlatMap, &fixupData);
|
||||
for (auto iter = mURIMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsAutoCString mapTo;
|
||||
nsresult rv = iter.UserData()->GetLocalURI(mTargetBaseURI, mapTo);
|
||||
if (NS_SUCCEEDED(rv) || !mapTo.IsVoid()) {
|
||||
flatMap->Add(iter.Key(), mapTo);
|
||||
}
|
||||
}
|
||||
mFlatURIMap = flatMap.forget();
|
||||
|
||||
nsCOMPtr<nsIFile> localFile;
|
||||
|
@ -1755,23 +1806,35 @@ nsWebBrowserPersist::FinishSaveDocumentInternal(nsIURI* aFile,
|
|||
void nsWebBrowserPersist::Cleanup()
|
||||
{
|
||||
mURIMap.Clear();
|
||||
mOutputMap.EnumerateRead(EnumCleanupOutputMap, this);
|
||||
for (auto iter = mOutputMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(iter.Key());
|
||||
if (channel) {
|
||||
channel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
}
|
||||
mOutputMap.Clear();
|
||||
mUploadList.EnumerateRead(EnumCleanupUploadList, this);
|
||||
|
||||
for (auto iter = mUploadList.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(iter.Key());
|
||||
if (channel) {
|
||||
channel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
}
|
||||
mUploadList.Clear();
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < mDocList.Length(); i++)
|
||||
{
|
||||
for (i = 0; i < mDocList.Length(); i++) {
|
||||
DocData *docData = mDocList.ElementAt(i);
|
||||
delete docData;
|
||||
}
|
||||
mDocList.Clear();
|
||||
for (i = 0; i < mCleanupList.Length(); i++)
|
||||
{
|
||||
|
||||
for (i = 0; i < mCleanupList.Length(); i++) {
|
||||
CleanupData *cleanupData = mCleanupList.ElementAt(i);
|
||||
delete cleanupData;
|
||||
}
|
||||
mCleanupList.Clear();
|
||||
|
||||
mFilenameList.Clear();
|
||||
}
|
||||
|
||||
|
@ -2319,85 +2382,72 @@ nsWebBrowserPersist::EndDownload(nsresult aResult)
|
|||
mEventSink = nullptr;
|
||||
}
|
||||
|
||||
struct MOZ_STACK_CLASS FixRedirectData
|
||||
{
|
||||
nsCOMPtr<nsIChannel> mNewChannel;
|
||||
nsCOMPtr<nsIURI> mOriginalURI;
|
||||
nsCOMPtr<nsISupports> mMatchingKey;
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsWebBrowserPersist::FixRedirectedChannelEntry(nsIChannel *aNewChannel)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNewChannel);
|
||||
|
||||
// Iterate through existing open channels looking for one with a URI
|
||||
// matching the one specified.
|
||||
nsCOMPtr<nsIURI> originalURI;
|
||||
aNewChannel->GetOriginalURI(getter_AddRefs(originalURI));
|
||||
for (auto iter = mOutputMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsISupports* key = iter.Key();
|
||||
nsCOMPtr<nsIChannel> thisChannel = do_QueryInterface(key);
|
||||
nsCOMPtr<nsIURI> thisURI;
|
||||
|
||||
// Enumerate through existing open channels looking for one with
|
||||
// a URI matching the one specified.
|
||||
thisChannel->GetOriginalURI(getter_AddRefs(thisURI));
|
||||
|
||||
FixRedirectData data;
|
||||
data.mNewChannel = aNewChannel;
|
||||
data.mNewChannel->GetOriginalURI(getter_AddRefs(data.mOriginalURI));
|
||||
mOutputMap.EnumerateRead(EnumFixRedirect, &data);
|
||||
// Compare this channel's URI to the one passed in.
|
||||
bool matchingURI = false;
|
||||
thisURI->Equals(originalURI, &matchingURI);
|
||||
if (matchingURI) {
|
||||
// If a match is found, remove the data entry with the old channel
|
||||
// key and re-add it with the new channel key.
|
||||
nsAutoPtr<OutputData> outputData;
|
||||
mOutputMap.RemoveAndForget(key, outputData);
|
||||
NS_ENSURE_TRUE(outputData, NS_ERROR_FAILURE);
|
||||
|
||||
// If a match is found, remove the data entry with the old channel key
|
||||
// and re-add it with the new channel key.
|
||||
// Store data again with new channel unless told to ignore redirects
|
||||
if (!(mPersistFlags & PERSIST_FLAGS_IGNORE_REDIRECTED_DATA)) {
|
||||
nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(aNewChannel);
|
||||
mOutputMap.Put(keyPtr, outputData.forget());
|
||||
}
|
||||
|
||||
if (data.mMatchingKey)
|
||||
{
|
||||
nsAutoPtr<OutputData> outputData;
|
||||
mOutputMap.RemoveAndForget(data.mMatchingKey, outputData);
|
||||
NS_ENSURE_TRUE(outputData, NS_ERROR_FAILURE);
|
||||
|
||||
// Store data again with new channel unless told to ignore redirects
|
||||
if (!(mPersistFlags & PERSIST_FLAGS_IGNORE_REDIRECTED_DATA))
|
||||
{
|
||||
nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(aNewChannel);
|
||||
mOutputMap.Put(keyPtr, outputData.forget());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumFixRedirect(nsISupports *aKey, OutputData *aData, void* aClosure)
|
||||
{
|
||||
FixRedirectData *data = static_cast<FixRedirectData*>(aClosure);
|
||||
|
||||
nsCOMPtr<nsIChannel> thisChannel = do_QueryInterface(aKey);
|
||||
nsCOMPtr<nsIURI> thisURI;
|
||||
|
||||
thisChannel->GetOriginalURI(getter_AddRefs(thisURI));
|
||||
|
||||
// Compare this channel's URI to the one passed in.
|
||||
bool matchingURI = false;
|
||||
thisURI->Equals(data->mOriginalURI, &matchingURI);
|
||||
if (matchingURI)
|
||||
{
|
||||
data->mMatchingKey = aKey;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsWebBrowserPersist::CalcTotalProgress()
|
||||
{
|
||||
mTotalCurrentProgress = 0;
|
||||
mTotalMaxProgress = 0;
|
||||
|
||||
if (mOutputMap.Count() > 0)
|
||||
{
|
||||
if (mOutputMap.Count() > 0) {
|
||||
// Total up the progress of each output stream
|
||||
mOutputMap.EnumerateRead(EnumCalcProgress, this);
|
||||
for (auto iter = mOutputMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
// Only count toward total progress if destination file is local.
|
||||
OutputData* data = iter.UserData();
|
||||
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(data->mFile);
|
||||
if (fileURL) {
|
||||
mTotalCurrentProgress += data->mSelfProgress;
|
||||
mTotalMaxProgress += data->mSelfProgressMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mUploadList.Count() > 0)
|
||||
{
|
||||
if (mUploadList.Count() > 0) {
|
||||
// Total up the progress of each upload
|
||||
mUploadList.EnumerateRead(EnumCalcUploadProgress, this);
|
||||
for (auto iter = mUploadList.Iter(); !iter.Done(); iter.Next()) {
|
||||
UploadData* data = iter.UserData();
|
||||
if (data) {
|
||||
mTotalCurrentProgress += data->mSelfProgress;
|
||||
mTotalMaxProgress += data->mSelfProgressMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XXX this code seems pretty bogus and pointless
|
||||
|
@ -2409,133 +2459,6 @@ nsWebBrowserPersist::CalcTotalProgress()
|
|||
}
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCalcProgress(nsISupports *aKey, OutputData *aData, void* aClosure)
|
||||
{
|
||||
nsWebBrowserPersist *pthis = static_cast<nsWebBrowserPersist*>(aClosure);
|
||||
|
||||
// only count toward total progress if destination file is local
|
||||
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aData->mFile);
|
||||
if (fileURL)
|
||||
{
|
||||
pthis->mTotalCurrentProgress += aData->mSelfProgress;
|
||||
pthis->mTotalMaxProgress += aData->mSelfProgressMax;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCalcUploadProgress(nsISupports *aKey, UploadData *aData, void* aClosure)
|
||||
{
|
||||
if (aData && aClosure)
|
||||
{
|
||||
nsWebBrowserPersist *pthis = static_cast<nsWebBrowserPersist*>(aClosure);
|
||||
pthis->mTotalCurrentProgress += aData->mSelfProgress;
|
||||
pthis->mTotalMaxProgress += aData->mSelfProgressMax;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCountURIsToPersist(const nsACString &aKey, URIData *aData, void* aClosure)
|
||||
{
|
||||
uint32_t *count = static_cast<uint32_t*>(aClosure);
|
||||
if (aData->mNeedsPersisting && !aData->mSaved)
|
||||
{
|
||||
(*count)++;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumPersistURIs(const nsACString &aKey, URIData *aData, void* aClosure)
|
||||
{
|
||||
if (!aData->mNeedsPersisting || aData->mSaved)
|
||||
{
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsWebBrowserPersist *pthis = static_cast<nsWebBrowserPersist*>(aClosure);
|
||||
nsresult rv;
|
||||
|
||||
// Create a URI from the key
|
||||
nsAutoCString key = nsAutoCString(aKey);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri),
|
||||
nsDependentCString(key.get(), key.Length()),
|
||||
aData->mCharset.get());
|
||||
NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
|
||||
|
||||
// Make a URI to save the data to
|
||||
nsCOMPtr<nsIURI> fileAsURI;
|
||||
rv = aData->mDataPath->Clone(getter_AddRefs(fileAsURI));
|
||||
NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
|
||||
rv = pthis->AppendPathToURI(fileAsURI, aData->mFilename);
|
||||
NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
|
||||
|
||||
// The Referrer Policy doesn't matter here since the referrer is nullptr.
|
||||
rv = pthis->SaveURIInternal(uri, nullptr, nullptr, mozilla::net::RP_Default,
|
||||
nullptr, nullptr, fileAsURI, true, pthis->mIsPrivate);
|
||||
// if SaveURIInternal fails, then it will have called EndDownload,
|
||||
// which means that |aData| is no longer valid memory. we MUST bail.
|
||||
NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
|
||||
|
||||
if (rv == NS_OK)
|
||||
{
|
||||
// Store the actual object because once it's persisted this
|
||||
// will be fixed up with the right file extension.
|
||||
|
||||
aData->mFile = fileAsURI;
|
||||
aData->mSaved = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aData->mNeedsFixup = false;
|
||||
}
|
||||
|
||||
if (pthis->mSerializingOutput)
|
||||
return PL_DHASH_STOP;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCleanupOutputMap(nsISupports *aKey, OutputData *aData, void* aClosure)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aKey);
|
||||
if (channel)
|
||||
{
|
||||
channel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCleanupUploadList(nsISupports *aKey, UploadData *aData, void* aClosure)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aKey);
|
||||
if (channel)
|
||||
{
|
||||
channel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCopyURIsToFlatMap(const nsACString &aKey,
|
||||
URIData *aData,
|
||||
void* aClosure)
|
||||
{
|
||||
URIFixupData *fixupData = static_cast<URIFixupData*>(aClosure);
|
||||
FlatURIMap* theMap = fixupData->mFlatMap;
|
||||
nsAutoCString mapTo;
|
||||
nsresult rv = aData->GetLocalURI(fixupData->mTargetBaseURI, mapTo);
|
||||
if (NS_SUCCEEDED(rv) || !mapTo.IsVoid()) {
|
||||
theMap->Add(aKey, mapTo);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebBrowserPersist::StoreURI(
|
||||
const char *aURI, bool aNeedsPersisting, URIData **aData)
|
||||
|
|
|
@ -136,24 +136,6 @@ private:
|
|||
|
||||
void SetApplyConversionIfNeeded(nsIChannel *aChannel);
|
||||
|
||||
// Hash table enumerators
|
||||
static PLDHashOperator EnumPersistURIs(
|
||||
const nsACString &aKey, URIData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCleanupOutputMap(
|
||||
nsISupports *aKey, OutputData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCleanupUploadList(
|
||||
nsISupports *aKey, UploadData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCalcProgress(
|
||||
nsISupports *aKey, OutputData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCalcUploadProgress(
|
||||
nsISupports *aKey, UploadData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumFixRedirect(
|
||||
nsISupports *aKey, OutputData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCountURIsToPersist(
|
||||
const nsACString &aKey, URIData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCopyURIsToFlatMap(
|
||||
const nsACString &aKey, URIData *aData, void* aClosure);
|
||||
|
||||
nsCOMPtr<nsIURI> mCurrentDataPath;
|
||||
bool mCurrentDataPathIsRelative;
|
||||
nsCString mCurrentRelativePathToData;
|
||||
|
|
|
@ -57,7 +57,7 @@ GrallocImage::~GrallocImage()
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
GrallocImage::SetData(const Data& aData)
|
||||
{
|
||||
MOZ_ASSERT(!mTextureClient, "TextureClient is already set");
|
||||
|
@ -70,7 +70,7 @@ GrallocImage::SetData(const Data& aData)
|
|||
|
||||
if (gfxPlatform::GetPlatform()->IsInGonkEmulator()) {
|
||||
// Emulator does not support HAL_PIXEL_FORMAT_YV12.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<GrallocTextureClientOGL> textureClient =
|
||||
|
@ -88,7 +88,7 @@ GrallocImage::SetData(const Data& aData)
|
|||
sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
|
||||
if (!result || !graphicBuffer.get()) {
|
||||
mTextureClient = nullptr;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
mTextureClient = textureClient;
|
||||
|
@ -96,7 +96,7 @@ GrallocImage::SetData(const Data& aData)
|
|||
void* vaddr;
|
||||
if (graphicBuffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
|
||||
&vaddr) != OK) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* yChannel = static_cast<uint8_t*>(vaddr);
|
||||
|
@ -144,12 +144,14 @@ GrallocImage::SetData(const Data& aData)
|
|||
mData.mYChannel = nullptr;
|
||||
mData.mCrChannel = nullptr;
|
||||
mData.mCbChannel = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrallocImage::SetData(const GrallocData& aData)
|
||||
bool GrallocImage::SetData(const GrallocData& aData)
|
||||
{
|
||||
mTextureClient = static_cast<GrallocTextureClientOGL*>(aData.mGraphicBuffer.get());
|
||||
mSize = aData.mPicSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -66,13 +66,13 @@ public:
|
|||
* This makes a copy of the data buffers, in order to support functioning
|
||||
* in all different layer managers.
|
||||
*/
|
||||
virtual void SetData(const Data& aData);
|
||||
virtual bool SetData(const Data& aData);
|
||||
|
||||
/**
|
||||
* Share the SurfaceDescriptor without making the copy, in order
|
||||
* to support functioning in all different layer managers.
|
||||
*/
|
||||
virtual void SetData(const GrallocData& aData);
|
||||
virtual bool SetData(const GrallocData& aData);
|
||||
|
||||
// From [android 4.0.4]/hardware/msm7k/libgralloc-qsd8k/gralloc_priv.h
|
||||
enum {
|
||||
|
|
|
@ -484,7 +484,7 @@ CopyPlane(uint8_t *aDst, const uint8_t *aSrc,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
PlanarYCbCrImage::CopyData(const Data& aData)
|
||||
{
|
||||
mData = aData;
|
||||
|
@ -496,7 +496,7 @@ PlanarYCbCrImage::CopyData(const Data& aData)
|
|||
// get new buffer
|
||||
mBuffer = AllocateBuffer(size);
|
||||
if (!mBuffer)
|
||||
return;
|
||||
return false;
|
||||
|
||||
// update buffer size
|
||||
mBufferSize = size;
|
||||
|
@ -513,12 +513,13 @@ PlanarYCbCrImage::CopyData(const Data& aData)
|
|||
mData.mCbCrSize, mData.mCbCrStride, mData.mCrSkip);
|
||||
|
||||
mSize = aData.mPicSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
PlanarYCbCrImage::SetData(const Data &aData)
|
||||
{
|
||||
CopyData(aData);
|
||||
return CopyData(aData);
|
||||
}
|
||||
|
||||
gfxImageFormat
|
||||
|
@ -529,11 +530,12 @@ PlanarYCbCrImage::GetOffscreenFormat()
|
|||
mOffscreenFormat;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
PlanarYCbCrImage::SetDataNoCopy(const Data &aData)
|
||||
{
|
||||
mData = aData;
|
||||
mSize = aData.mPicSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
|
|
|
@ -656,7 +656,7 @@ public:
|
|||
* This makes a copy of the data buffers, in order to support functioning
|
||||
* in all different layer managers.
|
||||
*/
|
||||
virtual void SetData(const Data& aData);
|
||||
virtual bool SetData(const Data& aData);
|
||||
|
||||
/**
|
||||
* This doesn't make a copy of the data buffers. Can be used when mBuffer is
|
||||
|
@ -665,7 +665,7 @@ public:
|
|||
* The GStreamer media backend uses this to decode into PlanarYCbCrImage(s)
|
||||
* directly.
|
||||
*/
|
||||
virtual void SetDataNoCopy(const Data &aData);
|
||||
virtual bool SetDataNoCopy(const Data &aData);
|
||||
|
||||
/**
|
||||
* This allocates and returns a new buffer
|
||||
|
@ -709,7 +709,7 @@ protected:
|
|||
*
|
||||
* @param aData Input image data.
|
||||
*/
|
||||
void CopyData(const Data& aData);
|
||||
bool CopyData(const Data& aData);
|
||||
|
||||
/**
|
||||
* Return a buffer to store image data in.
|
||||
|
|
|
@ -1051,6 +1051,11 @@ APZCTreeManager::ProcessMouseEvent(WidgetMouseEventBase& aEvent,
|
|||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutInputBlockId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Note, we call this before having transformed the reference point.
|
||||
UpdateWheelTransaction(aEvent);
|
||||
|
||||
MouseInput input(aEvent);
|
||||
input.mOrigin = ScreenPoint(aEvent.refPoint.x, aEvent.refPoint.y);
|
||||
|
||||
|
|
|
@ -3351,11 +3351,8 @@ AsyncPanZoomController::CurrentPanGestureBlock()
|
|||
}
|
||||
|
||||
void
|
||||
AsyncPanZoomController::ResetInputState()
|
||||
AsyncPanZoomController::ResetTouchInputState()
|
||||
{
|
||||
// This may be called during non-touch input blocks as well. We send
|
||||
// a fake cancel touch event here but on the assumption that none of the
|
||||
// code in GEL assumes a CurrentTouchBlock()
|
||||
MultiTouchInput cancel(MultiTouchInput::MULTITOUCH_CANCEL, 0, TimeStamp::Now(), 0);
|
||||
RefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||
if (listener) {
|
||||
|
|
|
@ -834,9 +834,9 @@ public:
|
|||
bool ArePointerEventsConsumable(TouchBlockState* aBlock, uint32_t aTouchPoints);
|
||||
|
||||
/**
|
||||
* Clear internal state relating to input handling.
|
||||
* Clear internal state relating to touch input handling.
|
||||
*/
|
||||
void ResetInputState();
|
||||
void ResetTouchInputState();
|
||||
|
||||
private:
|
||||
void CancelAnimationAndGestureState();
|
||||
|
|
|
@ -651,7 +651,9 @@ InputQueue::ProcessInputBlocks() {
|
|||
curBlock->DropEvents();
|
||||
} else if (curBlock->IsDefaultPrevented()) {
|
||||
curBlock->DropEvents();
|
||||
target->ResetInputState();
|
||||
if (curBlock->AsTouchBlock()) {
|
||||
target->ResetTouchInputState();
|
||||
}
|
||||
} else {
|
||||
UpdateActiveApzc(curBlock->GetTargetApzc());
|
||||
curBlock->HandleEvents();
|
||||
|
@ -677,7 +679,7 @@ void
|
|||
InputQueue::UpdateActiveApzc(const RefPtr<AsyncPanZoomController>& aNewActive) {
|
||||
if (mLastActiveApzc && mLastActiveApzc != aNewActive
|
||||
&& mTouchCounter.GetActiveTouchCount() > 0) {
|
||||
mLastActiveApzc->ResetInputState();
|
||||
mLastActiveApzc->ResetTouchInputState();
|
||||
}
|
||||
mLastActiveApzc = aNewActive;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void SetData(const Data& aData) override;
|
||||
virtual bool SetData(const Data& aData) override;
|
||||
virtual void SetDelayedConversion(bool aDelayed) override { mDelayedConversion = aDelayed; }
|
||||
|
||||
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
|
||||
|
@ -91,20 +91,20 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void
|
||||
bool
|
||||
BasicPlanarYCbCrImage::SetData(const Data& aData)
|
||||
{
|
||||
PlanarYCbCrImage::SetData(aData);
|
||||
|
||||
if (mDelayedConversion) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do some sanity checks to prevent integer overflow
|
||||
if (aData.mYSize.width > PlanarYCbCrImage::MAX_DIMENSION ||
|
||||
aData.mYSize.height > PlanarYCbCrImage::MAX_DIMENSION) {
|
||||
NS_ERROR("Illegal image source width or height");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat format = gfx::ImageFormatToSurfaceFormat(GetOffscreenFormat());
|
||||
|
@ -114,7 +114,7 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
|
|||
if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
|
||||
size.height > PlanarYCbCrImage::MAX_DIMENSION) {
|
||||
NS_ERROR("Illegal image dest width or height");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
gfxImageFormat iFormat = gfx::SurfaceFormatToImageFormat(format);
|
||||
|
@ -122,12 +122,14 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
|
|||
mDecodedBuffer = AllocateBuffer(size.height * mStride);
|
||||
if (!mDecodedBuffer) {
|
||||
// out of memory
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::ConvertYCbCrToRGB(aData, format, size, mDecodedBuffer, mStride);
|
||||
SetOffscreenFormat(iFormat);
|
||||
mSize = size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface>
|
||||
|
|
|
@ -1650,6 +1650,7 @@ CompositorParent::SetControllerForLayerTree(uint64_t aLayersId,
|
|||
/*static*/ APZCTreeManager*
|
||||
CompositorParent::GetAPZCTreeManager(uint64_t aLayersId)
|
||||
{
|
||||
EnsureLayerTreeMapReady();
|
||||
const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId);
|
||||
if (state && state->mParent) {
|
||||
return state->mParent->mApzcTreeManager;
|
||||
|
|
|
@ -80,7 +80,7 @@ SharedPlanarYCbCrImage::GetAsSourceSurface()
|
|||
return PlanarYCbCrImage::GetAsSourceSurface();
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
SharedPlanarYCbCrImage::SetData(const PlanarYCbCrData& aData)
|
||||
{
|
||||
// If mTextureClient has not already been allocated (through Allocate(aData))
|
||||
|
@ -88,20 +88,21 @@ SharedPlanarYCbCrImage::SetData(const PlanarYCbCrData& aData)
|
|||
// been called since it will trigger a full copy.
|
||||
PlanarYCbCrData data = aData;
|
||||
if (!mTextureClient && !Allocate(data)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mTextureClient->AsTextureClientYCbCr());
|
||||
if (!mTextureClient->Lock(OpenMode::OPEN_WRITE_ONLY)) {
|
||||
MOZ_ASSERT(false, "Failed to lock the texture.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
TextureClientAutoUnlock unlock(mTextureClient);
|
||||
if (!mTextureClient->AsTextureClientYCbCr()->UpdateYCbCr(aData)) {
|
||||
MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
mTextureClient->MarkImmutable();
|
||||
return true;
|
||||
}
|
||||
|
||||
// needs to be overriden because the parent class sets mBuffer which we
|
||||
|
@ -131,12 +132,12 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
|
|||
return serializer.GetData();
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
|
||||
{
|
||||
MOZ_ASSERT(mTextureClient, "This Image should have already allocated data");
|
||||
if (!mTextureClient) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
mData = aData;
|
||||
mSize = aData.mPicSize;
|
||||
|
@ -159,6 +160,7 @@ SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
|
|||
aData.mYSize,
|
||||
aData.mCbCrSize,
|
||||
aData.mStereoMode);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
|
|
|
@ -35,8 +35,8 @@ public:
|
|||
virtual uint8_t* GetBuffer() override;
|
||||
|
||||
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
|
||||
virtual void SetData(const PlanarYCbCrData& aData) override;
|
||||
virtual void SetDataNoCopy(const Data &aData) override;
|
||||
virtual bool SetData(const PlanarYCbCrData& aData) override;
|
||||
virtual bool SetDataNoCopy(const Data &aData) override;
|
||||
|
||||
virtual bool Allocate(PlanarYCbCrData& aData);
|
||||
virtual uint8_t* AllocateBuffer(uint32_t aSize) override;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "nsMathUtils.h"
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include <algorithm>
|
||||
|
@ -57,6 +58,22 @@ inline void VERIFY_COORD(nscoord aCoord) {
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide aSpace by aN. Assign the resulting quotient to aQuotient and
|
||||
* return the remainder.
|
||||
*/
|
||||
inline nscoord NSCoordDivRem(nscoord aSpace, size_t aN, nscoord* aQuotient)
|
||||
{
|
||||
#ifdef NS_COORD_IS_FLOAT
|
||||
*aQuotient = aSpace / aN;
|
||||
return 0.0f;
|
||||
#else
|
||||
div_t result = div(aSpace, aN);
|
||||
*aQuotient = nscoord(result.quot);
|
||||
return nscoord(result.rem);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline nscoord NSCoordMulDiv(nscoord aMult1, nscoord aMult2, nscoord aDiv) {
|
||||
#ifdef NS_COORD_IS_FLOAT
|
||||
return (aMult1 * aMult2 / aDiv);
|
||||
|
|
|
@ -1297,7 +1297,7 @@ js::AsmJSFunctionToString(JSContext* cx, HandleFunction fun)
|
|||
|
||||
size_t nameEnd = begin + fun->atom()->length();
|
||||
Rooted<JSFlatString*> src(cx, source->substring(cx, nameEnd, end));
|
||||
if (!AppendUseStrictSource(cx, fun, src, out))
|
||||
if (!src || !AppendUseStrictSource(cx, fun, src, out))
|
||||
return nullptr;
|
||||
} else {
|
||||
Rooted<JSFlatString*> src(cx, source->substring(cx, begin, end));
|
||||
|
|
|
@ -1928,6 +1928,27 @@ NewUDateFormat(JSContext* cx, HandleObject dateTimeFormat)
|
|||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
if (!uTimeZone) {
|
||||
#if ENABLE_INTL_API && defined(ICU_TZ_HAS_RECREATE_DEFAULT)
|
||||
// JS::ResetTimeZone() recomputes the JS language's LocalTZA value. It
|
||||
// *should* also recreate ICU's default time zone (used for formatting
|
||||
// when no time zone has been specified), but this operation is slow.
|
||||
// Doing it eagerly introduces a perf regression -- see bug 1220693.
|
||||
// Therefore we perform it lazily, responding to the value of a global
|
||||
// atomic variable that records whether ICU's default time zone is
|
||||
// accurate. Baroque, but it's the only way to get the job done.
|
||||
//
|
||||
// Beware: this is kosher *only* if every place using ICU's default
|
||||
// time zone performs the atomic compare-exchange and possible
|
||||
// recreation song and dance routine here.
|
||||
if (js::DefaultTimeZoneStatus.compareExchange(IcuTimeZoneStatus::NeedsUpdate,
|
||||
IcuTimeZoneStatus::Updating))
|
||||
{
|
||||
icu::TimeZone::recreateDefault();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// If building with ICU headers before 50.1, use UDAT_IGNORE instead of
|
||||
// UDAT_PATTERN.
|
||||
UDateFormat* df =
|
||||
|
|
|
@ -793,7 +793,10 @@ ModuleObject::evaluate(JSContext* cx, HandleModuleObject self, MutableHandleValu
|
|||
{
|
||||
RootedScript script(cx, self->script());
|
||||
RootedModuleEnvironmentObject scope(cx, self->environment());
|
||||
MOZ_ASSERT(scope);
|
||||
if (!scope) {
|
||||
JS_ReportError(cx, "Module declarations have not yet been instantiated");
|
||||
return false;
|
||||
}
|
||||
|
||||
return Execute(cx, script, *scope, rval.address());
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ js::obj_propertyIsEnumerable(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
/* Step 1. */
|
||||
RootedId idRoot(cx);
|
||||
if (!ValueToId<CanGC>(cx, idValue, &idRoot))
|
||||
if (!ToPropertyKey(cx, idValue, &idRoot))
|
||||
return false;
|
||||
|
||||
/* Step 2. */
|
||||
|
@ -531,7 +531,7 @@ js::obj_hasOwnProperty(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
/* Step 1. */
|
||||
RootedId idRoot(cx);
|
||||
if (!ValueToId<CanGC>(cx, idValue, &idRoot))
|
||||
if (!ToPropertyKey(cx, idValue, &idRoot))
|
||||
return false;
|
||||
|
||||
/* Step 2. */
|
||||
|
@ -774,7 +774,7 @@ js::obj_defineProperty(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (!GetFirstArgumentAsObject(cx, args, "Object.defineProperty", &obj))
|
||||
return false;
|
||||
RootedId id(cx);
|
||||
if (!ValueToId<CanGC>(cx, args.get(1), &id))
|
||||
if (!ToPropertyKey(cx, args.get(1), &id))
|
||||
return false;
|
||||
|
||||
// Steps 4-5.
|
||||
|
|
|
@ -2491,8 +2491,9 @@ ASTSerializer::forInit(ParseNode* pn, MutableHandleValue dst)
|
|||
return true;
|
||||
}
|
||||
|
||||
return (pn->isKind(PNK_VAR))
|
||||
? variableDeclaration(pn, false, dst)
|
||||
bool lexical = pn->isKind(PNK_LET) || pn->isKind(PNK_CONST);
|
||||
return (lexical || pn->isKind(PNK_VAR))
|
||||
? variableDeclaration(pn, lexical, dst)
|
||||
: expression(pn, dst);
|
||||
}
|
||||
|
||||
|
@ -2641,32 +2642,31 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
if (!statement(pn->pn_right, &stmt))
|
||||
return false;
|
||||
|
||||
if (head->isKind(PNK_FORIN)) {
|
||||
if (head->isKind(PNK_FORIN) || head->isKind(PNK_FOROF)) {
|
||||
RootedValue var(cx);
|
||||
return (!head->pn_kid1
|
||||
? pattern(head->pn_kid2, &var)
|
||||
: head->pn_kid1->isKind(PNK_LEXICALSCOPE)
|
||||
? variableDeclaration(head->pn_kid1->pn_expr, true, &var)
|
||||
: variableDeclaration(head->pn_kid1, false, &var)) &&
|
||||
forIn(pn, head, var, stmt, dst);
|
||||
}
|
||||
|
||||
if (head->isKind(PNK_FOROF)) {
|
||||
RootedValue var(cx);
|
||||
return (!head->pn_kid1
|
||||
? pattern(head->pn_kid2, &var)
|
||||
: head->pn_kid1->isKind(PNK_LEXICALSCOPE)
|
||||
? variableDeclaration(head->pn_kid1->pn_expr, true, &var)
|
||||
: variableDeclaration(head->pn_kid1, false, &var)) &&
|
||||
forOf(pn, head, var, stmt, dst);
|
||||
if (!head->pn_kid1) {
|
||||
if (!pattern(head->pn_kid2, &var))
|
||||
return false;
|
||||
} else if (head->pn_kid1->isKind(PNK_LEXICALSCOPE)) {
|
||||
if (!variableDeclaration(head->pn_kid1->pn_expr, true, &var))
|
||||
return false;
|
||||
} else {
|
||||
if (!variableDeclaration(head->pn_kid1,
|
||||
head->pn_kid1->isKind(PNK_LET) ||
|
||||
head->pn_kid1->isKind(PNK_CONST),
|
||||
&var))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (head->isKind(PNK_FORIN))
|
||||
return forIn(pn, head, var, stmt, dst);
|
||||
return forOf(pn, head, var, stmt, dst);
|
||||
}
|
||||
|
||||
RootedValue init(cx), test(cx), update(cx);
|
||||
|
||||
return forInit(head->pn_kid1 && !head->pn_kid1->isKind(PNK_FRESHENBLOCK)
|
||||
? head->pn_kid1
|
||||
: nullptr,
|
||||
&init) &&
|
||||
return forInit(head->pn_kid1, &init) &&
|
||||
optExpression(head->pn_kid2, &test) &&
|
||||
optExpression(head->pn_kid3, &update) &&
|
||||
builder.forStatement(init, test, update, stmt, &pn->pn_pos, dst);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче