Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2015-11-04 12:45:40 +01:00
Родитель 987e88f8e4 3e11f2fe34
Коммит 90803a6363
371 изменённых файлов: 13925 добавлений и 6977 удалений

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

@ -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

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

@ -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);

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