Merge mozilla-central to mozilla-inbound. r=merge a=merge CLOSED TREE

This commit is contained in:
Ciure Andrei 2017-11-17 12:11:30 +02:00
commit 0792c2eee8
154 changed files with 2744 additions and 1747 deletions

View File

@ -25,8 +25,6 @@
ok(!isAccessible("statusbarpanel"),
"statusbarpanel shouldn't be accessible.");
testRole("statusbarpanel-iconic", ROLE_PUSHBUTTON);
testRole("statusbarpanel-iconic-text", ROLE_PUSHBUTTON);
testRole("statusbar", ROLE_STATUSBAR);
SimpleTest.finish();
@ -57,8 +55,6 @@
<image id="image-onclick" src="../moz.png" onclick=""/>
<statusbarpanel id="statusbarpanel"></statusbarpanel>
<statusbarpanel id="statusbarpanel-iconic" class="statusbarpanel-iconic"></statusbarpanel>
<statusbarpanel id="statusbarpanel-iconic-text" class="statusbarpanel-iconic-text"></statusbarpanel>
<statusbar id="statusbar"></statusbar>
</hbox>

View File

@ -247,24 +247,26 @@ var BrowserPageActions = {
let popupSet = document.getElementById("mainPopupSet");
popupSet.appendChild(panelNode);
panelNode.addEventListener("popuphidden", () => {
if (iframeNode) {
action.onIframeHidden(iframeNode, panelNode);
}
panelNode.remove();
}, { once: true });
if (iframeNode) {
panelNode.addEventListener("popupshown", () => {
action.onIframeShown(iframeNode, panelNode);
panelNode.addEventListener("popupshowing", () => {
action.onIframeShowing(iframeNode, panelNode);
}, { once: true });
panelNode.addEventListener("popuphiding", () => {
action.onIframeHiding(iframeNode, panelNode);
}, { once: true });
panelNode.addEventListener("popuphidden", () => {
action.onIframeHidden(iframeNode, panelNode);
}, { once: true });
}
if (panelViewNode) {
action.subview.onPlaced(panelViewNode);
action.subview.onShowing(panelViewNode);
panelNode.addEventListener("popupshowing", () => {
action.subview.onShowing(panelViewNode);
}, { once: true });
}
return panelNode;
@ -956,14 +958,11 @@ BrowserPageActions.sendToDevice = {
}
},
onShowingInPanel(buttonNode) {
onLocationChange() {
let action = PageActions.actionForID("sendToDevice");
let browser = gBrowser.selectedBrowser;
let url = browser.currentURI.spec;
if (gSync.isSendableURI(url)) {
buttonNode.removeAttribute("disabled");
} else {
buttonNode.setAttribute("disabled", "true");
}
action.setDisabled(!gSync.isSendableURI(url), window);
},
onShowingSubview(panelViewNode) {
@ -1008,7 +1007,7 @@ BrowserPageActions.sendToDevice = {
bodyNode.setAttribute("state", "notready");
// Force a background Sync
Services.tm.dispatchToMainThread(async () => {
await Weave.Service.sync([]); // [] = clients engine only
await Weave.Service.sync({why: "pageactions", engines: []}); // [] = clients engine only
// There's no way Sync is still syncing at this point, but we check
// anyway to avoid infinite looping.
if (!window.closed && !gSync.syncConfiguredAndLoading) {

View File

@ -5695,6 +5695,7 @@ var gUIDensity = {
}
TabsInTitlebar.updateAppearance(true);
gBrowser.tabContainer.uiDensityChanged();
},
};

View File

@ -6823,6 +6823,14 @@
]]></body>
</method>
<method name="uiDensityChanged">
<body><![CDATA[
this._positionPinnedTabs();
this._updateCloseButtons();
this._handleTabSelect(true);
]]></body>
</method>
<field name="_lastNumPinned">0</field>
<field name="_pinnedTabsLayoutCache">null</field>
<method name="_positionPinnedTabs">
@ -6835,9 +6843,12 @@
this.setAttribute("positionpinnedtabs", "true");
let layoutData = this._pinnedTabsLayoutCache;
if (!layoutData) {
let uiDensity = document.documentElement.getAttribute("uidensity");
if (!layoutData ||
layoutData.uiDensity != uiDensity) {
let arrowScrollbox = this.arrowScrollbox;
layoutData = this._pinnedTabsLayoutCache = {
uiDensity,
pinnedTabWidth: this.childNodes[0].getBoundingClientRect().width,
scrollButtonWidth: arrowScrollbox._scrollButtonDown.getBoundingClientRect().width
};

View File

@ -174,34 +174,27 @@ add_task(async function copyURLFromURLBar() {
});
add_task(async function sendToDevice_nonSendable() {
// Open a tab that's not sendable. An about: page like about:home is
// convenient.
await BrowserTestUtils.withNewTab("about:home", async () => {
// ... but the page actions should be hidden on about:home, including the
// main button. (It's not easy to load a page that's both actionable and
// not sendable.) So first check that that's the case, and then unhide the
// main button so that this test can continue.
Assert.equal(
window.getComputedStyle(BrowserPageActions.mainButtonNode).display,
"none",
"Main button should be hidden on about:home"
);
BrowserPageActions.mainButtonNode.style.display = "-moz-box";
// Open a tab that's not sendable but where the page action buttons still
// appear. about:about is convenient.
await BrowserTestUtils.withNewTab("about:about", async () => {
await promiseSyncReady();
// Open the panel. Send to Device should be disabled.
await promisePageActionPanelOpen();
Assert.equal(BrowserPageActions.mainButtonNode.getAttribute("open"),
"true", "Main button has 'open' attribute");
let sendToDeviceButton =
document.getElementById("pageAction-panel-sendToDevice");
Assert.ok(sendToDeviceButton.disabled);
Assert.equal(BrowserPageActions.mainButtonNode.getAttribute("open"), "true",
"Main button has 'open' attribute");
let panelButton =
BrowserPageActions.panelButtonNodeForActionID("sendToDevice");
Assert.equal(panelButton.disabled, true,
"The panel button should be disabled");
let hiddenPromise = promisePageActionPanelHidden();
BrowserPageActions.panelNode.hidePopup();
await hiddenPromise;
Assert.ok(!BrowserPageActions.mainButtonNode.hasAttribute("open"),
"Main button no longer has 'open' attribute");
// Remove the `display` style set above.
BrowserPageActions.mainButtonNode.style.removeProperty("display");
"Main button no longer has 'open' attribute");
// The urlbar button shouldn't exist.
let urlbarButton =
BrowserPageActions.urlbarButtonNodeForActionID("sendToDevice");
Assert.equal(urlbarButton, null, "The urlbar button shouldn't exist");
});
});
@ -550,7 +543,9 @@ add_task(async function sendToDevice_inUrlbar() {
let urlbarButton = document.getElementById(
BrowserPageActions.urlbarButtonNodeIDForActionID(action.id)
);
Assert.ok(!urlbarButton.disabled);
Assert.notEqual(urlbarButton, null, "The urlbar button should exist");
Assert.ok(!urlbarButton.disabled,
"The urlbar button should not be disabled");
let panelPromise =
promisePanelShown(BrowserPageActions._activatedActionPanelID);
EventUtils.synthesizeMouseAtCenter(urlbarButton, {});

View File

@ -139,7 +139,7 @@ var PocketPageAction = {
onPlacedInPanel(panelNode, urlbarNode) {
PocketOverlay.onWindowOpened(panelNode.ownerGlobal);
},
onIframeShown(iframe, panel) {
onIframeShowing(iframe, panel) {
Pocket.onShownInPhotonPageActionPanel(panel, iframe);
let doc = panel.ownerDocument;

View File

@ -525,9 +525,9 @@ this.PageActions = {
* onIframeHidden(iframeNode, parentPanelNode)
* * iframeNode: The iframe.
* * parentPanelNode: The panel node in which the iframe is shown.
* @param onIframeShown (function, optional)
* Called when the action's iframe is shown to the user:
* onIframeShown(iframeNode, parentPanelNode)
* @param onIframeShowing (function, optional)
* Called when the action's iframe is showing to the user:
* onIframeShowing(iframeNode, parentPanelNode)
* * iframeNode: The iframe.
* * parentPanelNode: The panel node in which the iframe is shown.
* @param onLocationChange (function, optional)
@ -584,7 +584,7 @@ function Action(options) {
onCommand: false,
onIframeHiding: false,
onIframeHidden: false,
onIframeShown: false,
onIframeShowing: false,
onLocationChange: false,
onPlacedInPanel: false,
onPlacedInUrlbar: false,
@ -901,16 +901,16 @@ Action.prototype = {
},
/**
* Call this when the action's iframe is shown.
* Call this when the action's iframe is showing.
*
* @param iframeNode (DOM node, required)
* The iframe that's being shown.
* @param parentPanelNode (DOM node, required)
* The panel in which the iframe is shown.
*/
onIframeShown(iframeNode, parentPanelNode) {
if (this._onIframeShown) {
this._onIframeShown(iframeNode, parentPanelNode);
onIframeShowing(iframeNode, parentPanelNode) {
if (this._onIframeShowing) {
this._onIframeShowing(iframeNode, parentPanelNode);
}
},
@ -1229,8 +1229,8 @@ var gBuiltInActions = [
onPlacedInPanel(buttonNode) {
browserPageActions(buttonNode).sendToDevice.onPlacedInPanel(buttonNode);
},
onShowingInPanel(buttonNode) {
browserPageActions(buttonNode).sendToDevice.onShowingInPanel(buttonNode);
onLocationChange(browserWindow) {
browserPageActions(browserWindow).sendToDevice.onLocationChange();
},
subview: {
buttons: [

View File

@ -455,7 +455,7 @@ add_task(async function withIframe() {
let onCommandCallCount = 0;
let onPlacedInPanelCallCount = 0;
let onPlacedInUrlbarCallCount = 0;
let onIframeShownCount = 0;
let onIframeShowingCount = 0;
let panelButtonID = BrowserPageActions.panelButtonNodeIDForActionID(id);
let urlbarButtonID = BrowserPageActions.urlbarButtonNodeIDForActionID(id);
@ -469,8 +469,8 @@ add_task(async function withIframe() {
onCommand(event, buttonNode) {
onCommandCallCount++;
},
onIframeShown(iframeNode, panelNode) {
onIframeShownCount++;
onIframeShowing(iframeNode, panelNode) {
onIframeShowingCount++;
Assert.ok(iframeNode, "iframeNode should be non-null: " + iframeNode);
Assert.equal(iframeNode.localName, "iframe", "iframe localName");
Assert.ok(panelNode, "panelNode should be non-null: " + panelNode);
@ -496,8 +496,8 @@ add_task(async function withIframe() {
"onPlacedInPanelCallCount should be inc'ed");
Assert.equal(onPlacedInUrlbarCallCount, 1,
"onPlacedInUrlbarCallCount should be inc'ed");
Assert.equal(onIframeShownCount, 0,
"onIframeShownCount should remain 0");
Assert.equal(onIframeShowingCount, 0,
"onIframeShowingCount should remain 0");
Assert.equal(onCommandCallCount, 0,
"onCommandCallCount should remain 0");
@ -519,11 +519,11 @@ add_task(async function withIframe() {
// Open the panel, click the action's button.
await promisePageActionPanelOpen();
Assert.equal(onIframeShownCount, 0, "onIframeShownCount should remain 0");
Assert.equal(onIframeShowingCount, 0, "onIframeShowingCount should remain 0");
EventUtils.synthesizeMouseAtCenter(panelButtonNode, {});
await promisePanelShown(BrowserPageActions._activatedActionPanelID);
Assert.equal(onCommandCallCount, 0, "onCommandCallCount should remain 0");
Assert.equal(onIframeShownCount, 1, "onIframeShownCount should be inc'ed");
Assert.equal(onIframeShowingCount, 1, "onIframeShowingCount should be inc'ed");
// The activated-action panel should have opened, anchored to the action's
// urlbar button.
@ -538,7 +538,7 @@ add_task(async function withIframe() {
EventUtils.synthesizeMouseAtCenter(urlbarButtonNode, {});
await promisePanelShown(BrowserPageActions._activatedActionPanelID);
Assert.equal(onCommandCallCount, 0, "onCommandCallCount should remain 0");
Assert.equal(onIframeShownCount, 2, "onIframeShownCount should be inc'ed");
Assert.equal(onIframeShowingCount, 2, "onIframeShowingCount should be inc'ed");
// The activated-action panel should have opened, again anchored to the
// action's urlbar button.
@ -558,7 +558,7 @@ add_task(async function withIframe() {
EventUtils.synthesizeMouseAtCenter(panelButtonNode, {});
await promisePanelShown(BrowserPageActions._activatedActionPanelID);
Assert.equal(onCommandCallCount, 0, "onCommandCallCount should remain 0");
Assert.equal(onIframeShownCount, 3, "onIframeShownCount should be inc'ed");
Assert.equal(onIframeShowingCount, 3, "onIframeShowingCount should be inc'ed");
// The activated-action panel should have opened, this time anchored to the
// main page action button in the urlbar.

View File

@ -66,7 +66,7 @@ tabbrowser {
padding: 0 @horizontalTabPadding@;
}
.tab-content[pinned] {
:root:not([uidensity=compact]) .tab-content[pinned] {
padding: 0 12px;
}
@ -193,7 +193,7 @@ tabbrowser {
100% { transform: translateX(100%); }
}
#TabsToolbar[brighttext] .tab-throbber[busy]:not([visuallyselected=true])::before {
#TabsToolbar[brighttext] .tab-throbber[busy]:not([selected=true])::before {
/* Don't change the --tab-loading-fill variable because this should only affect
tabs that are not visually selected. */
fill: #717171;
@ -205,7 +205,7 @@ tabbrowser {
opacity: 1;
}
#TabsToolbar[brighttext] .tab-throbber[progress]:not([visuallyselected=true])::before {
#TabsToolbar[brighttext] .tab-throbber[progress]:not([selected=true])::before {
/* Don't change the --tab-loading-fill variable because this should only affect
tabs that are not visually selected. */
fill: #84c1ff;

14
build/moz.configure/compile-checks.configure Normal file → Executable file
View File

@ -105,6 +105,8 @@ def check_and_add_flags(flag, cflags, cxxflags, test_flags,
if when is None:
when = always
results = []
if test_flags:
flags = test_flags
else:
@ -132,6 +134,10 @@ def check_and_add_flags(flag, cflags, cxxflags, test_flags,
if result:
list_of_flags.append(flag)
results.append(result)
return tuple(results)
@dependable
def warnings_cflags():
@ -168,8 +174,8 @@ def check_and_add_gcc_warning(warning, compiler=None, when=None, check=True):
else:
flags = ['-Werror', warning]
check_and_add_flags(warning, warnings_cflags, warnings_cxxflags,
flags, compiler=compiler, when=when, check=check)
return check_and_add_flags(warning, warnings_cflags, warnings_cxxflags,
flags, compiler=compiler, when=when, check=check)
# Add the given warning to the list of warning flags for the build.
@ -212,8 +218,8 @@ def compilation_cxxflags():
def check_and_add_gcc_flag(flag, compiler=None, when=None, check=True):
flags = ['-Werror', flag]
check_and_add_flags(flag, compilation_cflags, compilation_cxxflags,
flags, compiler=compiler, when=when, check=check)
return check_and_add_flags(flag, compilation_cflags, compilation_cxxflags,
flags, compiler=compiler, when=when, check=check)
# Add the given flag to the list of flags for the build.

View File

@ -102,31 +102,45 @@ check_and_add_gcc_warning('-Wno-error=coverage-mismatch', when='MOZ_PGO')
check_and_add_gcc_warning('-Wno-error=free-nonheap-object')
# catches format/argument mismatches with printf
check_and_add_gcc_warning('-Wformat')
c_format_warning, cxx_format_warning = check_and_add_gcc_warning(
'-Wformat', when=depends(target)(lambda t: t.kernel != 'WINNT'))
# We use mix of both POSIX and Win32 printf format across the tree, so format
# warnings are useless on mingw.
check_and_add_gcc_warning('-Wno-format',
when=depends(target)(lambda t: t.kernel == 'WINNT'))
# Add compile-time warnings for unprotected functions and format functions
# that represent possible security problems. Enable this only when -Wformat
# is enabled, otherwise it is an error
check_and_add_gcc_warning('-Wformat-security',
when=c_format_warning & cxx_format_warning)
check_and_add_gcc_warning('-Wformat-overflow=2',
when=c_format_warning & cxx_format_warning)
# When compiling for Windows with gcc, we encounter lots of "#pragma warning"'s
# which is an MSVC-only pragma that GCC does not recognize.
check_and_add_gcc_warning('-Wno-unknown-pragmas',
when=depends(target)(lambda t: t.kernel == 'WINNT'))
# Other MinGW specific things
with only_when(depends(target)(lambda t: t.kernel == 'WINNT')):
# When compiling for Windows with gcc, we encounter lots of "#pragma warning"'s
# which is an MSVC-only pragma that GCC does not recognize.
check_and_add_gcc_warning('-Wno-unknown-pragmas')
# When compiling for Windows with gcc, gcc throws false positives and true
# positives where the callsite is ifdef-ed out
check_and_add_gcc_warning('-Wno-unused-function',
when=depends(target)(lambda t: t.kernel == 'WINNT'))
# When compiling for Windows with gcc, gcc throws false positives and true
# positives where the callsite is ifdef-ed out
check_and_add_gcc_warning('-Wno-unused-function')
# When compiling for Windows with gcc, gcc cannot produce this warning
# correctly: it mistakes DWORD_PTR and ULONG_PTR as types you cannot
# give NULL to. (You can in fact do that.)
check_and_add_gcc_warning('-Wno-conversion-null')
# Throughout the codebase we regularly have switch statements off of enums
# without covering every value in the enum. We don't care about these warnings.
check_and_add_gcc_warning('-Wno-switch')
# Another code pattern we have is using start and end constants in enums of
# different types. We do this for safety, but then when comparing it throws
# an error, which we would like to ignore. This seems to only affect the MinGW
# build, but we're not sure why.
check_and_add_gcc_warning('-Wno-enum-compare')
# We hit this all over the place with the gtest INSTANTIATE_TEST_CASE_P macro
check_and_add_gcc_warning('-Wno-gnu-zero-variadic-macro-arguments')
# Add compile-time warnings for unprotected functions and format functions
# that represent possible security problems
check_and_add_gcc_warning('-Wformat-security')
check_and_add_gcc_warning('-Wformat-overflow=2')
# Disable a warning with gcc 7. See bug 1320656
# We are far from using C++17 and the impact of the warning will be
# limited to a potential public ABI.

View File

@ -37,27 +37,8 @@ PYTHON ?= $(shell which python2.7 > /dev/null 2>&1 && echo python2.7 || echo pyt
####################################
# Load mozconfig Options
# See build pages, http://www.mozilla.org/build/ for how to set up mozconfig.
define CR
endef
# As $(shell) doesn't preserve newlines, use sed to replace them with an
# unlikely sequence (||), which is then replaced back to newlines by make
# before evaluation. $(shell) replacing newlines with spaces, || is always
# followed by a space (since sed doesn't remove newlines), except on the
# last line, so replace both '|| ' and '||'.
MOZCONFIG_CONTENT := $(subst ||,$(CR),$(subst || ,$(CR),$(shell cat $(OBJDIR)/.mozconfig-client-mk | sed 's/$$/||/')))
include $(OBJDIR)/.mozconfig-client-mk
# As '||' was used as a newline separator, it means it's not occurring in
# lines themselves. It can thus safely be used to replaces normal spaces,
# to then replace newlines with normal spaces. This allows to get a list
# of mozconfig output lines.
MOZCONFIG_OUT_LINES := $(subst $(CR), ,$(subst $(NULL) $(NULL),||,$(MOZCONFIG_CONTENT)))
ifdef MOZ_PARALLEL_BUILD
MOZ_MAKE_FLAGS := $(filter-out -j%,$(MOZ_MAKE_FLAGS))
MOZ_MAKE_FLAGS += -j$(MOZ_PARALLEL_BUILD)
@ -92,23 +73,6 @@ $(error client.mk must be used via `mach`. Try running \
`./mach $(firstword $(MAKECMDGOALS) $(.DEFAULT_GOAL))`)
endif
# For now, only output "export" lines and lines containing UPLOAD_EXTRA_FILES.
MOZCONFIG_MK_LINES := $(filter export||% UPLOAD_EXTRA_FILES% %UPLOAD_EXTRA_FILES%,$(MOZCONFIG_OUT_LINES))
$(OBJDIR)/.mozconfig.mk: $(TOPSRCDIR)/client.mk $(FOUND_MOZCONFIG)
$(if $(MOZCONFIG_MK_LINES),( $(foreach line,$(MOZCONFIG_MK_LINES), echo '$(subst ||, ,$(line))';) )) > $@
# Include that makefile so that it is created. This should not actually change
# the environment since MOZCONFIG_CONTENT, which MOZCONFIG_OUT_LINES derives
# from, has already been eval'ed.
include $(OBJDIR)/.mozconfig.mk
# Print out any options loaded from mozconfig.
all build clean distclean export libs install realclean::
ifneq (,$(strip $(MOZCONFIG_OUT_LINES)))
$(info Adding client.mk options from $(FOUND_MOZCONFIG):)
$(foreach line,$(MOZCONFIG_OUT_LINES),$(info $(NULL) $(NULL) $(NULL) $(NULL) $(subst ||, ,$(line))))
endif
# In automation, manage an sccache daemon. The starting of the server
# needs to be in a make file so sccache inherits the jobserver.
ifdef MOZBUILD_MANAGE_SCCACHE_DAEMON
@ -174,24 +138,9 @@ configure-files: $(CONFIGURES)
configure-preqs = \
configure-files \
save-mozconfig \
$(OBJDIR)/.mozconfig.json \
$(NULL)
CREATE_MOZCONFIG_JSON = $(shell $(TOPSRCDIR)/mach environment --format=json -o $(OBJDIR)/.mozconfig.json)
# Force CREATE_MOZCONFIG_JSON above to be resolved, without side effects in
# case the result is non empty, and allowing an override on the make command
# line not running the command (using := $(shell) still runs the shell command).
ifneq (,$(CREATE_MOZCONFIG_JSON))
endif
$(OBJDIR)/.mozconfig.json: ;
save-mozconfig: $(FOUND_MOZCONFIG)
ifdef FOUND_MOZCONFIG
-cp $(FOUND_MOZCONFIG) $(OBJDIR)/.mozconfig
endif
configure:: $(configure-preqs)
$(call BUILDSTATUS,TIERS configure)
$(call BUILDSTATUS,TIER_START configure)
@ -210,12 +159,7 @@ $(OBJDIR)/config.status: $(CONFIG_STATUS_DEPS)
else
$(OBJDIR)/Makefile: $(CONFIG_STATUS_DEPS)
endif
@$(MAKE) -f $(TOPSRCDIR)/client.mk configure CREATE_MOZCONFIG_JSON=
ifneq (,$(CONFIG_STATUS))
$(OBJDIR)/config/autoconf.mk: $(TOPSRCDIR)/config/autoconf.mk.in
$(PYTHON) $(OBJDIR)/config.status -n --file=$(OBJDIR)/config/autoconf.mk
endif
@$(MAKE) -f $(TOPSRCDIR)/client.mk configure
####################################
# Build it

View File

@ -3,8 +3,10 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {DOM, Component, PropTypes} = require("devtools/client/shared/vendor/react");
const {img, button, span} = DOM;
const { Component } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const {img, button, span} = dom;
class ToolboxTab extends Component {
// See toolbox-toolbar propTypes for details on the props used here.

View File

@ -3,10 +3,11 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {DOM, Component, createFactory, PropTypes} = require("devtools/client/shared/vendor/react");
const { Component, createFactory } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const {findDOMNode} = require("devtools/client/shared/vendor/react-dom");
const {button, div} = DOM;
const {button, div} = dom;
const Menu = require("devtools/client/framework/menu");
const MenuItem = require("devtools/client/framework/menu-item");

View File

@ -3,8 +3,10 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {DOM, Component, createFactory, PropTypes} = require("devtools/client/shared/vendor/react");
const {div, button} = DOM;
const { Component, createFactory } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const {div, button} = dom;
const ToolboxTab = createFactory(require("devtools/client/framework/components/toolbox-tab"));
const ToolboxTabs = createFactory(require("devtools/client/framework/components/toolbox-tabs"));

View File

@ -7,17 +7,7 @@ devtools.jar:
content/shared/vendor/d3.js (shared/vendor/d3.js)
content/shared/vendor/dagre-d3.js (shared/vendor/dagre-d3.js)
content/shared/widgets/widgets.css (shared/widgets/widgets.css)
content/netmonitor/src/assets/styles/httpi.css (netmonitor/src/assets/styles/httpi.css)
content/netmonitor/src/assets/styles/MdnLink.css (netmonitor/src/assets/styles/MdnLink.css)
content/netmonitor/src/assets/styles/netmonitor.css (netmonitor/src/assets/styles/netmonitor.css)
content/netmonitor/src/assets/styles/NetworkDetailsPanel.css (netmonitor/src/assets/styles/NetworkDetailsPanel.css)
content/netmonitor/src/assets/styles/RequestList.css (netmonitor/src/assets/styles/RequestList.css)
content/netmonitor/src/assets/styles/StatisticsPanel.css (netmonitor/src/assets/styles/StatisticsPanel.css)
content/netmonitor/src/assets/styles/StatusBar.css (netmonitor/src/assets/styles/StatusBar.css)
content/netmonitor/src/assets/styles/Toolbar.css (netmonitor/src/assets/styles/Toolbar.css)
content/netmonitor/src/assets/styles/variables.css (netmonitor/src/assets/styles/variables.css)
content/shared/widgets/VariablesView.xul (shared/widgets/VariablesView.xul)
content/netmonitor/index.html (netmonitor/index.html)
content/webconsole/webconsole.html (webconsole/webconsole.html)
content/webconsole/webconsole.xul (webconsole/webconsole.xul)
content/scratchpad/scratchpad.xul (scratchpad/scratchpad.xul)
@ -318,3 +308,16 @@ devtools.jar:
skin/images/debugger/stepIn.svg (themes/images/debugger/stepIn.svg)
skin/images/debugger/stepOut.svg (themes/images/debugger/stepOut.svg)
skin/images/debugger/stepOver.svg (themes/images/debugger/stepOver.svg)
# Netmonitor
content/netmonitor/src/assets/styles/httpi.css (netmonitor/src/assets/styles/httpi.css)
content/netmonitor/src/assets/styles/MdnLink.css (netmonitor/src/assets/styles/MdnLink.css)
content/netmonitor/src/assets/styles/netmonitor.css (netmonitor/src/assets/styles/netmonitor.css)
content/netmonitor/src/assets/styles/NetworkDetailsPanel.css (netmonitor/src/assets/styles/NetworkDetailsPanel.css)
content/netmonitor/src/assets/styles/RequestList.css (netmonitor/src/assets/styles/RequestList.css)
content/netmonitor/src/assets/styles/StatisticsPanel.css (netmonitor/src/assets/styles/StatisticsPanel.css)
content/netmonitor/src/assets/styles/StatusBar.css (netmonitor/src/assets/styles/StatusBar.css)
content/netmonitor/src/assets/styles/Toolbar.css (netmonitor/src/assets/styles/Toolbar.css)
content/netmonitor/src/assets/styles/variables.css (netmonitor/src/assets/styles/variables.css)
content/netmonitor/src/assets/icons/play.svg (netmonitor/src/assets/icons/play.svg)
content/netmonitor/index.html (netmonitor/index.html)

View File

@ -25,7 +25,6 @@ const BinaryInput = CC("@mozilla.org/binaryinputstream;1",
const BufferStream = CC("@mozilla.org/io/arraybuffer-input-stream;1",
"nsIArrayBufferInputStream", "setData");
const encodingLength = 2;
const encoder = new TextEncoder();
// Localization
loader.lazyGetter(this, "jsonViewStrings", () => {
@ -58,7 +57,7 @@ Converter.prototype = {
* 1. asyncConvertData captures the listener
* 2. onStartRequest fires, initializes stuff, modifies the listener
* to match our output type
* 3. onDataAvailable converts to UTF-8 and spits back to the listener
* 3. onDataAvailable decodes and inserts data into a text node
* 4. onStopRequest flushes data and spits back to the listener
* 5. convert does nothing, it's just the synchronous version
* of asyncConvertData
@ -87,20 +86,15 @@ Converter.prototype = {
this.determineEncoding(request, context);
}
// Spit back the data if the encoding is UTF-8, otherwise convert it first.
if (!this.decoder) {
this.listener.onDataAvailable(request, context, inputStream, offset, count);
} else {
let buffer = new ArrayBuffer(count);
new BinaryInput(inputStream).readArrayBuffer(count, buffer);
this.convertAndSendBuffer(request, context, buffer);
}
// Decode and insert data.
let buffer = new ArrayBuffer(count);
new BinaryInput(inputStream).readArrayBuffer(count, buffer);
this.decodeAndInsertBuffer(request, context, buffer);
},
onStartRequest: function (request, context) {
// Set the content type to HTML in order to parse the doctype, styles
// and scripts, but later a <plaintext> element will switch the tokenizer
// to the plaintext state in order to parse the JSON.
// and scripts. The JSON will be manually inserted as text.
request.QueryInterface(Ci.nsIChannel);
request.contentType = "text/html";
@ -121,14 +115,14 @@ Converter.prototype = {
// Initialize stuff.
let win = NetworkHelper.getWindowForRequest(request);
this.data = exportData(win, request);
win.addEventListener("DOMContentLoaded", event => {
win.addEventListener("contentMessage", onContentMessage, false, true);
}, {once: true});
insertJsonData(win, this.data.json);
win.addEventListener("contentMessage", onContentMessage, false, true);
keepThemeUpdated(win);
// Send the initial HTML code.
let bytes = encoder.encode(initialHTML(win.document));
this.convertAndSendBuffer(request, context, bytes.buffer);
let buffer = new TextEncoder().encode(initialHTML(win.document)).buffer;
let stream = new BufferStream(buffer, 0, buffer.byteLength);
this.listener.onDataAvailable(request, context, stream, 0, stream.available());
// Create an array to store data until the encoding is determined.
this.encodingArray = [];
@ -139,7 +133,7 @@ Converter.prototype = {
if (this.encodingArray) {
this.determineEncoding(request, context, true);
} else {
this.convertAndSendBuffer(request, context, new ArrayBuffer(0), true);
this.decodeAndInsertBuffer(request, context, new ArrayBuffer(0), true);
}
// Stop the request.
@ -168,32 +162,24 @@ Converter.prototype = {
}
}
// Create a decoder unless the data is already in UTF-8.
if (encoding !== "UTF-8") {
this.decoder = new TextDecoder(encoding, {ignoreBOM: true});
}
// Create a decoder for that encoding.
this.decoder = new TextDecoder(encoding);
this.data.encoding = encoding;
// Send the bytes in encodingArray, and remove it.
// Decode and insert the bytes in encodingArray, and remove it.
let buffer = new Uint8Array(bytes).buffer;
this.convertAndSendBuffer(request, context, buffer, flush);
this.decodeAndInsertBuffer(request, context, buffer, flush);
this.encodingArray = null;
},
// Converts an ArrayBuffer to UTF-8 and sends it.
convertAndSendBuffer: function (request, context, buffer, flush = false) {
// If the encoding is not UTF-8, decode the buffer and encode into UTF-8.
if (this.decoder) {
let data = this.decoder.decode(buffer, {stream: !flush});
buffer = encoder.encode(data).buffer;
}
// Decodes an ArrayBuffer into a string and inserts it into the page.
decodeAndInsertBuffer: function (request, context, buffer, flush = false) {
// Decode the buffer into a string.
let data = this.decoder.decode(buffer, {stream: !flush});
// Create an input stream that contains the bytes in the buffer.
let stream = new BufferStream(buffer, 0, buffer.byteLength);
// Send the input stream.
this.listener.onDataAvailable(request, context, stream, 0, stream.available());
// Using `appendData` instead of `textContent +=` is important to avoid
// repainting previous data.
this.data.json.appendData(data);
}
};
@ -231,6 +217,8 @@ function exportData(win, request) {
data.debug = debug;
data.json = new win.Text();
let Locale = {
$STR: key => {
try {
@ -266,23 +254,18 @@ function exportData(win, request) {
return data;
}
// Serializes a qualifiedName and an optional set of attributes into an HTML
// start tag. Be aware qualifiedName and attribute names are not validated.
// Attribute values are escaped with escapingString algorithm in attribute mode
// (https://html.spec.whatwg.org/multipage/syntax.html#escapingString).
function startTag(qualifiedName, attributes = {}) {
return Object.entries(attributes).reduce(function (prev, [attr, value]) {
return prev + " " + attr + "=\"" +
value.replace(/&/g, "&amp;")
.replace(/\u00a0/g, "&nbsp;")
.replace(/"/g, "&quot;") +
"\"";
}, "<" + qualifiedName) + ">";
}
// Builds an HTML string that will be used to load stylesheets and scripts,
// and switch the parser to plaintext state.
// Builds an HTML string that will be used to load stylesheets and scripts.
function initialHTML(doc) {
// Creates an element with the specified type, attributes and children.
function element(type, attributes = {}, children = []) {
let el = doc.createElement(type);
for (let [attr, value] of Object.entries(attributes)) {
el.setAttribute(attr, value);
}
el.append(...children);
return el;
}
let os;
let platform = Services.appinfo.OS;
if (platform.startsWith("WINNT")) {
@ -297,29 +280,53 @@ function initialHTML(doc) {
// because the latter can be blocked by a CSP base-uri directive (bug 1316393)
let baseURI = "resource://devtools-client-jsonview/";
let style = doc.createElement("link");
style.rel = "stylesheet";
style.type = "text/css";
style.href = baseURI + "css/main.css";
let script = doc.createElement("script");
script.src = baseURI + "lib/require.js";
script.dataset.main = baseURI + "viewer-config.js";
script.defer = true;
let head = doc.createElement("head");
head.append(style, script);
return "<!DOCTYPE html>\n" +
startTag("html", {
element("html", {
"platform": os,
"class": "theme-" + Services.prefs.getCharPref("devtools.theme"),
"dir": Services.locale.isAppLocaleRTL ? "rtl" : "ltr"
}) +
head.outerHTML +
startTag("body") +
startTag("div", {"id": "content"}) +
startTag("plaintext", {"id": "json"});
}, [
element("head", {}, [
element("link", {
rel: "stylesheet",
type: "text/css",
href: baseURI + "css/main.css",
}),
element("script", {
src: baseURI + "lib/require.js",
"data-main": baseURI + "viewer-config.js",
defer: true,
})
]),
element("body", {}, [
element("div", {"id": "content"}, [
element("div", {"id": "json"})
])
])
]).outerHTML;
}
// We insert the received data into a text node, which should be appended into
// the #json element so that the JSON is still displayed even if JS is disabled.
// However, the HTML parser is not synchronous, so this function uses a mutation
// observer to detect the creation of the element. Then the text node is appended.
function insertJsonData(win, json) {
new win.MutationObserver(function (mutations, observer) {
for (let {target, addedNodes} of mutations) {
if (target.nodeType == 1 && target.id == "content") {
for (let node of addedNodes) {
if (node.nodeType == 1 && node.id == "json") {
observer.disconnect();
node.append(json);
return;
}
}
}
}
}).observe(win.document, {
childList: true,
subtree: true,
});
}
function keepThemeUpdated(win) {

View File

@ -12,7 +12,6 @@ define(function (require, exports, module) {
const { MainTabbedArea } = createFactories(require("./components/MainTabbedArea"));
const TreeViewClass = require("devtools/client/shared/components/tree/TreeView");
const json = document.getElementById("json");
const AUTO_EXPAND_MAX_SIZE = 100 * 1024;
const AUTO_EXPAND_MAX_LEVEL = 7;
@ -20,18 +19,13 @@ define(function (require, exports, module) {
// Application state object.
let input = {
jsonText: json.textContent,
jsonText: JSONView.json.textContent,
jsonPretty: null,
headers: JSONView.headers,
tabActive: 0,
prettified: false
};
// Remove BOM.
if (input.jsonText.startsWith("\ufeff")) {
input.jsonText = input.jsonText.slice(1);
}
try {
input.json = JSON.parse(input.jsonText);
} catch (err) {
@ -48,8 +42,6 @@ define(function (require, exports, module) {
input.expandedNodes = new Set();
}
json.remove();
/**
* Application actions/commands. This list implements all commands
* available for the JSON viewer.

View File

@ -50,6 +50,12 @@ add_task(function* () {
"UTF-16LE": "%FF%FE"
};
// Test double BOM.
tests.push(Object.entries(bom).reduce((obj, [prop, value]) => {
obj[prop + " with BOM"] = value;
return obj;
}, {[text]: "\uFEFF"}));
for (let test of tests) {
let result = test[text];
for (let [encoding, data] of Object.entries(test)) {

View File

@ -13,6 +13,6 @@ add_task(function* () {
yield selectJsonViewContentTab("rawdata");
let rawData = yield getElementText(".textPanelBox .data");
is(rawData, "\"foo_\uFFFD_bar\"",
"The NUL character has been replaced by the replacement character.");
is(rawData, "\"foo_\u0000_bar\"",
"The NUL character has been preserved.");
});

View File

@ -0,0 +1,8 @@
<!-- 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/. -->
<svg width="10" height="12" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="context-fill #0b0b0b">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<polygon id="Triangle-2" fill="#0A84FF" points="14 6 4 12 4 0"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 505 B

View File

@ -41,6 +41,6 @@
/* Icons */
:root {
--play-icon-url: url("chrome://devtools/skin/images/play.svg");
--play-icon-url: url("chrome://devtools/content/netmonitor/src/assets/icons/play.svg");
--pause-icon-url: url("chrome://devtools/skin/images/pause.svg");
}

View File

@ -103,7 +103,10 @@ class RequestListHeader extends Component {
return (
div({ className: "devtools-toolbar requests-list-headers-wrapper" },
div({ className: "devtools-toolbar requests-list-headers" },
div({
className: "devtools-toolbar requests-list-headers",
onContextMenu: this.onContextMenu
},
HEADERS.filter((header) => columns.get(header.name)).map((header) => {
let name = header.name;
let boxName = header.boxName || name;
@ -127,7 +130,6 @@ class RequestListHeader extends Component {
ref: `${name}Header`,
// Used to style the next column.
"data-active": active,
onContextMenu: this.onContextMenu,
},
button({
id: `requests-list-${name}-button`,

View File

@ -22,8 +22,28 @@ add_task(function* () {
yield testVisibleColumnContextMenuItem(column, document, parent);
}
}
for (let [column, shown] of store.getState().ui.columns) {
if (shown) {
yield testVisibleColumnContextMenuItem(column, document, parent);
// Right click on the white-space for the context menu to appear
// and toggle column visibility
yield testWhiteSpaceContextMenuItem(column, document, parent);
}
}
});
function* testWhiteSpaceContextMenuItem(column, document, parent) {
ok(!document.querySelector(`#requests-list-${column}-button`),
`Column ${column} should be hidden`);
info(`Right clicking on white-space in the header to get the context menu`);
EventUtils.sendMouseEvent({ type: "contextmenu" },
document.querySelector(".devtools-toolbar.requests-list-headers"));
yield toggleAndCheckColumnVisibility(column, document, parent);
}
function* testVisibleColumnContextMenuItem(column, document, parent) {
ok(document.querySelector(`#requests-list-${column}-button`),
`Column ${column} should be visible`);
@ -59,6 +79,10 @@ function* testHiddenColumnContextMenuItem(column, document, parent) {
document.querySelector("#requests-list-status-button") ||
document.querySelector("#requests-list-waterfall-button"));
yield toggleAndCheckColumnVisibility(column, document, parent);
}
function* toggleAndCheckColumnVisibility(column, document, parent) {
let menuItem = parent.document.querySelector(`#request-list-header-${column}-toggle`);
is(menuItem.getAttribute("type"), "checkbox",

View File

@ -190,8 +190,13 @@ HUD_SERVICE.prototype =
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
// Ensure that the root actor and the tab actors have been registered on the DebuggerServer,
// so that the Browser Console can retrieve the console actors.
// (See Bug 1416105 for rationale).
DebuggerServer.registerActors({ root: true, browser: false, tab: true });
DebuggerServer.allowChromeProcess = true;
let client = new DebuggerClient(DebuggerServer.connectPipe());

View File

@ -56,8 +56,6 @@ support-files =
test-bug-597136-external-script-errors.js
test-bug-597756-reopen-closed-tab.html
test-bug-599725-response-headers.sjs
test-bug-600183-charset.html
test-bug-600183-charset.html^headers^
test-bug-601177-log-levels.html
test-bug-601177-log-levels.js
test-bug-603750-websocket.html
@ -166,6 +164,7 @@ support-files =
!/devtools/client/netmonitor/test/sjs_cors-test-server.sjs
!/image/test/mochitest/blue.png
!/devtools/client/framework/test/shared-head.js
!/devtools/client/netmonitor/test/shared-head.js
[browser_console.js]
skip-if = true # Bug 1406060
[browser_console_addonsdk_loader_exception.js]
@ -230,13 +229,10 @@ tags = mcb
[browser_webconsole_cached_messages.js]
[browser_webconsole_cd_iframe.js]
[browser_webconsole_certificate_messages.js]
[browser_webconsole_charset.js]
skip-if = true # Bug 1404400
[browser_webconsole_click_function_to_source.js]
skip-if = true # Bug 1406038
[browser_webconsole_clickable_urls.js]
[browser_webconsole_closing_after_completion.js]
skip-if = true # Bug 1408927
[browser_webconsole_closure_inspection.js]
skip-if = true # Bug 1405250
[browser_webconsole_completion.js]

View File

@ -1,61 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// See Bug 600183.
const INIT_URI = "data:text/html;charset=utf-8,Web Console - bug 600183 test";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-bug-600183-charset.html";
function performTest(lastFinishedRequest, console) {
let deferred = defer();
ok(lastFinishedRequest, "charset test page was loaded and logged");
HUDService.lastFinishedRequest.callback = null;
executeSoon(() => {
console.webConsoleClient.getResponseContent(lastFinishedRequest.actor,
(response) => {
ok(!response.contentDiscarded, "response body was not discarded");
let body = response.content.text;
ok(body, "we have the response body");
// 的问候!
let chars = "\u7684\u95ee\u5019!";
isnot(body.indexOf("<p>" + chars + "</p>"), -1,
"found the chinese simplified string");
HUDService.lastFinishedRequest.callback = null;
executeSoon(deferred.resolve);
});
});
return deferred.promise;
}
function waitForRequest() {
let deferred = defer();
HUDService.lastFinishedRequest.callback = (req, console) => {
performTest(req, console).then(deferred.resolve);
};
return deferred.promise;
}
add_task(function* () {
let { browser } = yield loadTab(INIT_URI);
yield openConsole();
let gotLastRequest = waitForRequest();
let loaded = loadBrowser(browser);
BrowserTestUtils.loadURI(browser, TEST_URI);
yield loaded;
yield gotLastRequest;
});

View File

@ -9,17 +9,15 @@
"use strict";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-console.html";
"new-console-output/test/mochitest/test-console.html";
add_task(function* () {
let { browser } = yield loadTab(TEST_URI);
add_task(async function () {
let tab = await addTab(TEST_URI);
const browser = tab.linkedBrowser;
const hud = await openConsole();
let hud = yield openConsole();
yield testClosingAfterCompletion(hud, browser);
});
function testClosingAfterCompletion(hud, browser) {
let deferred = defer();
// Fire a completion.
await jstermSetValueAndComplete(hud.jsterm, "doc");
let errorWhileClosing = false;
function errorListener() {
@ -27,21 +25,17 @@ function testClosingAfterCompletion(hud, browser) {
}
browser.addEventListener("error", errorListener);
const onToolboxDestroyed = gDevTools.once("toolbox-destroyed");
// Focus the jsterm and perform the keycombo to close the WebConsole.
hud.jsterm.focus();
gDevTools.once("toolbox-destroyed", function () {
browser.removeEventListener("error", errorListener);
is(errorWhileClosing, false, "no error while closing the WebConsole");
deferred.resolve();
EventUtils.synthesizeKey("i", {
accelKey: true,
[Services.appinfo.OS == "Darwin" ? "altKey" : "shiftKey"]: true
});
if (Services.appinfo.OS == "Darwin") {
EventUtils.synthesizeKey("i", { accelKey: true, altKey: true });
} else {
EventUtils.synthesizeKey("i", { accelKey: true, shiftKey: true });
}
await onToolboxDestroyed;
return deferred.promise;
}
browser.removeEventListener("error", errorListener);
is(errorWhileClosing, false, "no error while closing the WebConsole");
});

View File

@ -1,9 +0,0 @@
<!DOCTYPE HTML>
<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
<meta charset="gb2312">
<title>Console HTTP test page (chinese)</title>
</head>
<body>
<p>的问候!</p>
</body>
</html>

View File

@ -1 +0,0 @@
Content-Type: text/html; charset=gb2312

View File

@ -361,8 +361,7 @@ public:
static bool IsCustomElementEnabled(JSContext* aCx = nullptr,
JSObject* aObject = nullptr)
{
return nsContentUtils::IsCustomElementsEnabled() ||
nsContentUtils::IsWebComponentsEnabled();
return nsContentUtils::IsCustomElementsEnabled();
}
explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);

View File

@ -211,7 +211,7 @@ load 1324500.html
pref(dom.IntersectionObserver.enabled,true) load 1326194-1.html
pref(dom.IntersectionObserver.enabled,true) load 1326194-2.html
pref(dom.IntersectionObserver.enabled,true) load 1332939.html
pref(dom.webcomponents.enabled,true) load 1341693.html
pref(dom.webcomponents.customelements.enabled,true) load 1341693.html
load 1352453.html
pref(dom.IntersectionObserver.enabled,true) load 1353529.xul
load 1368327.html

View File

@ -22,7 +22,6 @@ public:
BufferMediaResource(const uint8_t* aBuffer, uint32_t aLength)
: mBuffer(aBuffer)
, mLength(aLength)
, mOffset(0)
{
}
@ -41,14 +40,11 @@ private:
}
*aBytes = std::min(mLength - static_cast<uint32_t>(aOffset), aCount);
memcpy(aBuffer, mBuffer + aOffset, *aBytes);
mOffset = aOffset + *aBytes;
return NS_OK;
}
// Memory-based and no locks, caching discouraged.
bool ShouldCacheReads() override { return false; }
int64_t Tell() override { return mOffset; }
void Pin() override {}
void Unpin() override {}
int64_t GetLength() override { return mLength; }
@ -80,7 +76,6 @@ private:
private:
const uint8_t * mBuffer;
uint32_t mLength;
uint32_t mOffset;
};
} // namespace mozilla

View File

@ -675,11 +675,6 @@ ChannelMediaResource::ThrottleReadahead(bool bThrottle)
mCacheStream.ThrottleReadahead(bThrottle);
}
int64_t ChannelMediaResource::Tell()
{
return mCacheStream.Tell();
}
nsresult ChannelMediaResource::GetCachedRanges(MediaByteRangeSet& aRanges)
{
return mCacheStream.GetCachedRanges(aRanges);

View File

@ -124,7 +124,6 @@ public:
uint32_t aCount, uint32_t* aBytes) override;
// Data stored in IO&lock-encumbered MediaCacheStream, caching recommended.
bool ShouldCacheReads() override { return true; }
int64_t Tell() override;
// Any thread
void Pin() override;

View File

@ -202,7 +202,6 @@ CloneableWithRangeMediaResource::ReadFromCache(char* aBuffer, int64_t aOffset,
return rv;
}
mCurrentPosition = bytes + aOffset;
return bytes == aCount ? NS_OK : NS_ERROR_FAILURE;
}
@ -223,14 +222,7 @@ CloneableWithRangeMediaResource::ReadAt(int64_t aOffset, char* aBuffer,
return rv;
}
mCurrentPosition = *aBytes + aOffset;
return NS_OK;
}
int64_t CloneableWithRangeMediaResource::Tell()
{
MaybeInitialize();
return mCurrentPosition;
}
} // mozilla namespace

View File

@ -22,7 +22,6 @@ public:
: BaseMediaResource(aCallback, aChannel, aURI)
, mStream(do_QueryInterface(aStream))
, mSize(aSize)
, mCurrentPosition(0)
, mInitialized(false)
{
MOZ_ASSERT(mStream);
@ -49,7 +48,6 @@ public:
uint32_t aCount, uint32_t* aBytes) override;
// (Probably) file-based, caching recommended.
bool ShouldCacheReads() override { return true; }
int64_t Tell() override;
// Any thread
void Pin() override {}
@ -105,9 +103,6 @@ private:
// The stream size.
uint64_t mSize;
// The current position.
uint64_t mCurrentPosition;
bool mInitialized;
};

View File

@ -212,17 +212,4 @@ FileMediaResource::UnsafeSeek(int32_t aWhence, int64_t aOffset)
return mSeekable->Seek(aWhence, aOffset);
}
int64_t
FileMediaResource::Tell()
{
MutexAutoLock lock(mLock);
EnsureSizeInitialized();
int64_t offset = 0;
// Return mSize as offset (end of stream) in case of error
if (!mSeekable || NS_FAILED(mSeekable->Tell(&offset)))
return mSize;
return offset;
}
} // mozilla namespace

View File

@ -45,7 +45,6 @@ public:
uint32_t aCount, uint32_t* aBytes) override;
// (Probably) file-based, caching recommended.
bool ShouldCacheReads() override { return true; }
int64_t Tell() override;
// Any thread
void Pin() override {}

View File

@ -2510,13 +2510,6 @@ MediaCacheStream::ReadBlockFromCache(int64_t aOffset,
return bytesRead;
}
int64_t
MediaCacheStream::Tell()
{
ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
return mStreamOffset;
}
nsresult
MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
{

View File

@ -333,7 +333,6 @@ public:
// These methods must be called on a different thread from the main
// thread. They should always be called on the same thread for a given
// stream.
int64_t Tell();
// *aBytes gets the number of bytes that were actually read. This can
// be less than aCount. If the first byte of data is not in the cache,
// this will block until the data is available or the stream is

View File

@ -152,17 +152,6 @@ static Atomic<bool> sInShutdown;
typedef media::Pledge<bool, dom::MediaStreamError*> PledgeVoid;
static bool
HostIsHttps(nsIURI &docURI)
{
bool isHttps;
nsresult rv = docURI.SchemeIs("https", &isHttps);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
return isHttps;
}
class SourceListener : public MediaStreamListener {
public:
SourceListener();
@ -2346,7 +2335,7 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
"media.getusermedia.browser.enabled" :
"media.getusermedia.screensharing.enabled"),
false) ||
(!privileged && !HostIsHttps(*docURI))) {
(!privileged && !aWindow->IsSecureContext())) {
RefPtr<MediaStreamError> error =
new MediaStreamError(aWindow,
NS_LITERAL_STRING("NotAllowedError"));

View File

@ -69,12 +69,6 @@ public:
// each read.
virtual bool ShouldCacheReads() = 0;
// Report the current offset in bytes from the start of the stream.
// This is used to approximate where we currently are in the playback of a
// media.
// A call to ReadAt will update this position.
virtual int64_t Tell() = 0;
// These can be called on any thread.
// Cached blocks associated with this stream will not be evicted
// while the stream is pinned.

View File

@ -20,7 +20,6 @@ public:
uint32_t* aBytes) override;
// Data stored in file, caching recommended.
bool ShouldCacheReads() override { return true; }
int64_t Tell() override { return 0; }
void Pin() override {}
void Unpin() override {}
int64_t GetLength() override;

View File

@ -67,10 +67,6 @@ SourceBufferResource::ReadAtInternal(int64_t aOffset,
uint32_t available = GetLength() - aOffset;
uint32_t count = std::min(aCount, available);
// Keep the position of the last read to have Tell() approximately give us
// the position we're up to in the stream.
mOffset = aOffset + count;
SBR_DEBUGV("offset=%" PRId64 " GetLength()=%" PRId64
" available=%u count=%u mEnded=%d",
aOffset,
@ -160,12 +156,7 @@ SourceBufferResource::~SourceBufferResource()
SourceBufferResource::SourceBufferResource()
#if defined(DEBUG)
: mTaskQueue(AbstractThread::GetCurrent()->AsTaskQueue())
, mOffset(0)
#else
: mOffset(0)
#endif
, mClosed(false)
, mEnded(false)
{
SBR_DEBUG("");
}

View File

@ -37,7 +37,6 @@ public:
uint32_t* aBytes) override;
// Memory-based and no locks, caching discouraged.
bool ShouldCacheReads() override { return false; }
int64_t Tell() override { return mOffset; }
void Pin() override { UNIMPLEMENTED(); }
void Unpin() override { UNIMPLEMENTED(); }
int64_t GetLength() override { return mInputBuffer.GetLength(); }
@ -139,9 +138,8 @@ private:
// The buffer holding resource data.
ResourceQueue mInputBuffer;
uint64_t mOffset;
bool mClosed;
bool mEnded;
bool mClosed = false;
bool mEnded = false;
};
} // namespace mozilla

View File

@ -39,6 +39,31 @@ mozilla::LazyLogModule gCamerasParentLog("CamerasParent");
namespace mozilla {
namespace camera {
std::map<uint32_t, const char *> sDeviceUniqueIDs;
std::map<uint32_t, webrtc::VideoCaptureCapability> sAllRequestedCapabilities;
uint32_t
ResolutionFeasibilityDistance(int32_t candidate, int32_t requested)
{
// The purpose of this function is to find a smallest resolution
// which is larger than all requested capabilities.
// Then we can use down-scaling to fulfill each request.
uint32_t distance;
if (candidate >= requested) {
distance = (candidate - requested) * 1000 / std::max(candidate, requested);
} else {
distance = (UINT32_MAX / 2) + (requested - candidate) *
1000 / std::max(candidate, requested);
}
return distance;
}
uint32_t
FeasibilityDistance(int32_t candidate, int32_t requested)
{
return std::abs(candidate - requested) * 1000 / std::max(candidate, requested);
}
RefPtr<VideoEngine> CamerasParent::sEngines[CaptureEngine::MaxEngine];
int32_t CamerasParent::sNumOfOpenCamerasParentEngines = 0;
int32_t CamerasParent::sNumOfCamerasParents = 0;
@ -556,6 +581,17 @@ CamerasParent::RecvGetCaptureCapability(const CaptureEngine& aCapEngine,
if (auto devInfo = engine->GetOrCreateVideoCaptureDeviceInfo()){
error = devInfo->GetCapability(unique_id.get(), num, webrtcCaps);
}
if (!error && aCapEngine == CameraEngine) {
auto iter = self->mAllCandidateCapabilities.find(unique_id);
if (iter == self->mAllCandidateCapabilities.end()) {
std::map<uint32_t, webrtc::VideoCaptureCapability> candidateCapabilities;
candidateCapabilities.emplace(num, webrtcCaps);
self->mAllCandidateCapabilities.emplace(nsCString(unique_id), candidateCapabilities);
} else {
(iter->second).emplace(num, webrtcCaps);
}
}
}
RefPtr<nsIRunnable> ipc_runnable =
media::NewRunnableFrom([self, webrtcCaps, error]() -> nsresult {
@ -816,8 +852,9 @@ CamerasParent::RecvStartCapture(const CaptureEngine& aCapEngine,
new CallbackHelper(static_cast<CaptureEngine>(aCapEngine), capnum, self));
engine = self->sEngines[aCapEngine];
engine->WithEntry(capnum, [&error, &ipcCaps, &cbh](VideoEngine::CaptureEntry& cap) {
error = 0;
engine->WithEntry(capnum,
[&capnum, &aCapEngine, &error, &ipcCaps, &cbh, self]
(VideoEngine::CaptureEntry& cap) {
webrtc::VideoCaptureCapability capability;
capability.width = ipcCaps.width();
capability.height = ipcCaps.height();
@ -827,11 +864,59 @@ CamerasParent::RecvStartCapture(const CaptureEngine& aCapEngine,
capability.codecType = static_cast<webrtc::VideoCodecType>(ipcCaps.codecType());
capability.interlaced = ipcCaps.interlaced();
if (!error) {
error = cap.VideoCapture()->StartCapture(capability);
if (aCapEngine == CameraEngine) {
#ifdef DEBUG
auto deviceUniqueID = sDeviceUniqueIDs.find(capnum);
MOZ_ASSERT(deviceUniqueID == sDeviceUniqueIDs.end());
#endif
sDeviceUniqueIDs.emplace(capnum, cap.VideoCapture()->CurrentDeviceName());
sAllRequestedCapabilities.emplace(capnum, capability);
for (const auto &it : sDeviceUniqueIDs) {
if (strcmp(it.second, cap.VideoCapture()->CurrentDeviceName()) == 0) {
capability.width = std::max(
capability.width, sAllRequestedCapabilities[it.first].width);
capability.height = std::max(
capability.height, sAllRequestedCapabilities[it.first].height);
capability.maxFPS = std::max(
capability.maxFPS, sAllRequestedCapabilities[it.first].maxFPS);
}
}
auto candidateCapabilities = self->mAllCandidateCapabilities.find(
nsCString(cap.VideoCapture()->CurrentDeviceName()));
MOZ_ASSERT(candidateCapabilities != self->mAllCandidateCapabilities.end());
MOZ_ASSERT(candidateCapabilities->second.size() > 0);
int32_t minIdx = -1;
uint64_t minDistance = UINT64_MAX;
for (auto & candidateCapability : candidateCapabilities->second) {
if (candidateCapability.second.rawType != capability.rawType) {
continue;
}
// The first priority is finding a suitable resolution.
// So here we raise the weight of width and height
uint64_t distance =
uint64_t(ResolutionFeasibilityDistance(
candidateCapability.second.width, capability.width)) +
uint64_t(ResolutionFeasibilityDistance(
candidateCapability.second.height, capability.height)) +
uint64_t(FeasibilityDistance(
candidateCapability.second.maxFPS, capability.maxFPS));
if (distance < minDistance) {
minIdx = candidateCapability.first;;
minDistance = distance;
}
}
MOZ_ASSERT(minIdx != -1);
capability = candidateCapabilities->second[minIdx];
}
error = cap.VideoCapture()->StartCapture(capability);
if (!error) {
cap.VideoCapture()->RegisterCaptureDataCallback(static_cast<rtc::VideoSinkInterface<webrtc::VideoFrame>*>(*cbh));
cap.VideoCapture()->RegisterCaptureDataCallback(
static_cast<rtc::VideoSinkInterface<webrtc::VideoFrame>*>(*cbh));
}
});
}
@ -866,11 +951,16 @@ CamerasParent::StopCapture(const CaptureEngine& aCapEngine,
mCallbacks[i - 1]->mStreamId == (uint32_t)capnum) {
CallbackHelper* cbh = mCallbacks[i-1];
engine->WithEntry(capnum,[cbh](VideoEngine::CaptureEntry& cap) {
engine->WithEntry(capnum,[cbh, &capnum, &aCapEngine](VideoEngine::CaptureEntry& cap){
if (cap.VideoCapture()) {
cap.VideoCapture()->DeRegisterCaptureDataCallback(
static_cast<rtc::VideoSinkInterface<webrtc::VideoFrame>*>(cbh));
cap.VideoCapture()->StopCaptureIfAllClientsClose();
if (aCapEngine == CameraEngine) {
sDeviceUniqueIDs.erase(capnum);
sAllRequestedCapabilities.erase(capnum);
}
}
});

View File

@ -164,6 +164,8 @@ protected:
// read cross-thread.
mozilla::Atomic<bool> mWebRTCAlive;
RefPtr<InputObserver> mCameraObserver;
std::map<nsCString, std::map<uint32_t, webrtc::VideoCaptureCapability>>
mAllCandidateCapabilities;
};
PCamerasParent* CreateCamerasParent();

View File

@ -1,6 +1,8 @@
WEBVTT
Region: id=testOne lines=2 width=30%
Region: id=testTwo lines=4 width=20%
REGION
id=testOne lines=2 width=30%
REGION
id=testTwo lines=4 width=20%
1
00:00.500 --> 00:00.700 region:testOne

View File

@ -1,5 +1,6 @@
WEBVTT
Region: id=fred width=62% lines=5 regionanchor=4%,78% viewportanchor=10%,90% scroll=up
REGION
id=fred width=62% lines=5 regionanchor=4%,78% viewportanchor=10%,90% scroll=up
00:01.000 --> 00:02.000 region:fred
Test here.

View File

@ -80,6 +80,7 @@ struct ParamTraits<mozilla::dom::RTCStatsReportInternal>
WriteParam(aMsg, aParam.mIceRollbacks);
WriteParam(aMsg, aParam.mTransportStats);
WriteParam(aMsg, aParam.mRtpContributingSourceStats);
WriteParam(aMsg, aParam.mOfferer);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
@ -100,7 +101,8 @@ struct ParamTraits<mozilla::dom::RTCStatsReportInternal>
!ReadParam(aMsg, aIter, &(aResult->mIceRestarts)) ||
!ReadParam(aMsg, aIter, &(aResult->mIceRollbacks)) ||
!ReadParam(aMsg, aIter, &(aResult->mTransportStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mRtpContributingSourceStats))) {
!ReadParam(aMsg, aIter, &(aResult->mRtpContributingSourceStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mOfferer))) {
return false;
}

View File

@ -1200,7 +1200,6 @@ const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
// 3.4 WebVTT region and WebVTT region settings syntax
function parseRegion(input) {
var settings = new Settings();
parseOptions(input, function (k, v) {
switch (k) {
case "id":
@ -1275,6 +1274,16 @@ const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
}
}
function parseRegionOrStyle(input) {
switch (self.substate) {
case "REGION":
parseRegion(input);
break;
case "STYLE":
// TODO : not supported yet.
break;
}
}
// Parsing the region and style information.
// See spec, https://w3c.github.io/webvtt/#collect-a-webvtt-block
//
@ -1290,33 +1299,46 @@ const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
let line = null;
while (self.buffer && self.state === "HEADER") {
line = collectNextLine();
var tempStr = "";
if (/^REGION|^STYLE/.test(line)) {
self.substate = /^REGION/.test(line) ? "REGION" : "STYLE";
if (/^REGION|^STYLE/i.test(line)) {
parseOptions(line, function (k, v) {
switch (k.toUpperCase()) {
case "REGION":
parseRegion(v);
break;
case "STYLE":
// TODO : not supported yet.
while (true) {
line = collectNextLine();
if (!line || maybeIsTimeStampFormat(line) || onlyContainsWhiteSpaces(line) || containsTimeDirectionSymbol(line)) {
// parse the tempStr and break the while loop.
parseRegionOrStyle(tempStr);
break;
} else if (/^REGION|^STYLE/.test(line)) {
// The line is another REGION/STYLE, parse tempStr then reset tempStr.
// Don't break the while loop to parse the next REGION/STYLE.
parseRegionOrStyle(tempStr);
self.substate = /^REGION/.test(line) ? "REGION" : "STYLE";
tempStr = "";
} else {
tempStr += line;;
}
}, ":");
} else if (maybeIsTimeStampFormat(line)) {
}
}
if (maybeIsTimeStampFormat(line)) {
self.state = "CUE";
break;
} else if (!line ||
onlyContainsWhiteSpaces(line) ||
containsTimeDirectionSymbol(line)) {
// empty line, whitespaces or string contains "-->"
} else if (containsTimeDirectionSymbol(line)) {
// string contains "-->"
break;
} else if (!line || onlyContainsWhiteSpaces(line)) {
// empty line, whitespaces
continue;
} else {
//It is an ID.
break;
}
}
} // self.state === "HEADER"
// End parsing header part and doesn't see the timestamp.
if (self.state === "HEADER") {
self.state = "ID";
line = null
}
return line;
}
@ -1378,8 +1400,9 @@ const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
break;
case "BADCUE": // BADCUE
// 54-62 - Collect and discard the remaining cue.
if (!line) {
self.state = "ID";
self.state = "ID";
if (line) { // keep this line to ID state.
continue;
}
break;
}

View File

@ -49,7 +49,3 @@ LOCAL_INCLUDES += [
'/netwerk/base',
'/netwerk/protocol/data', # for nsDataHandler.h
]
if CONFIG['GNU_CC']:
CFLAGS += ['-Wformat-security']
CXXFLAGS += ['-Wformat-security']

View File

@ -47,7 +47,7 @@ test();
// test with webcomponents disabled
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{ 'set': [["dom.webcomponents.enabled", false]]}, runTest);
{ 'set': [["dom.webcomponents.customelements.enabled", false]]}, runTest);
</script>
</pre>

View File

@ -185,6 +185,7 @@ dictionary RTCStatsReportInternal {
DOMHighResTimeStamp timestamp;
unsigned long iceRestarts;
unsigned long iceRollbacks;
boolean offerer; // Is the PC the offerer
boolean closed; // Is the PC now closed
};

View File

@ -289,7 +289,7 @@ AsyncImagePipelineManager::ApplyAsyncImages()
float opacity = 1.0f;
builder.PushStackingContext(wr::ToLayoutRect(pipeline->mScBounds),
0,
nullptr,
&opacity,
pipeline->mScTransform.IsIdentity() ? nullptr : &pipeline->mScTransform,
wr::TransformStyle::Flat,

View File

@ -23,7 +23,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
wr::DisplayListBuilder& aBuilder,
const nsTArray<wr::WrFilterOp>& aFilters,
const gfx::Matrix4x4* aBoundTransform,
uint64_t aAnimationsId,
const wr::WrAnimationProperty* aAnimation,
float* aOpacityPtr,
gfx::Matrix4x4* aTransformPtr,
gfx::Matrix4x4* aPerspectivePtr,
@ -44,7 +44,7 @@ StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParen
}
mBuilder->PushStackingContext(wr::LayoutRect(),
aAnimationsId,
aAnimation,
aOpacityPtr,
aTransformPtr,
aIsPreserve3D ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat,

View File

@ -31,7 +31,7 @@ public:
wr::DisplayListBuilder& aBuilder,
const nsTArray<wr::WrFilterOp>& aFilters = nsTArray<wr::WrFilterOp>(),
const gfx::Matrix4x4* aBoundTransform = nullptr,
uint64_t aAnimationsId = 0,
const wr::WrAnimationProperty* aAnimation = nullptr,
float* aOpacityPtr = nullptr,
gfx::Matrix4x4* aTransformPtr = nullptr,
gfx::Matrix4x4* aPerspectivePtr = nullptr,

View File

@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_COMPOSITORHITTESTINFO_H_
#define MOZILLA_GFX_COMPOSITORHITTESTINFO_H_
#include "mozilla/TypedEnumBits.h"
namespace mozilla {
namespace gfx {
// This set of flags is used to figure out what information a frame has
// that is relevant to hit-testing in the compositor. The flags are
// intentionally set up so that if all of them are 0 the item is effectively
// invisible to hit-testing, and no information for this frame needs to be
// sent to the compositor.
enum class CompositorHitTestInfo : uint8_t {
// Shortcut for checking that none of the flags are set
eInvisibleToHitTest = 0,
// The frame participates in hit-testing
eVisibleToHitTest = 1 << 0,
// The frame requires main-thread handling for events
eDispatchToContent = 1 << 1,
// The touch action flags are set up so that the default of
// touch-action:auto on an element leaves all the flags as 0.
eTouchActionPanXDisabled = 1 << 2,
eTouchActionPanYDisabled = 1 << 3,
eTouchActionPinchZoomDisabled = 1 << 4,
eTouchActionDoubleTapZoomDisabled = 1 << 5,
// Mask to check for all the touch-action flags at once
eTouchActionMask = (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5),
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CompositorHitTestInfo)
} // namespace gfx
} // namespace mozilla
#endif /* MOZILLA_GFX_COMPOSITORHITTESTINFO_H_ */

View File

@ -47,6 +47,7 @@ EXPORTS.mozilla += [
]
EXPORTS.mozilla.gfx += [
'CompositorHitTestInfo.h',
'TiledRegion.h',
]

View File

@ -491,6 +491,7 @@ private:
DECL_GFX_PREF(Live, "gfx.webrender.blob-images", WebRenderBlobImages, bool, false);
DECL_GFX_PREF(Live, "gfx.webrender.highlight-painted-layers",WebRenderHighlightPaintedLayers, bool, false);
DECL_GFX_PREF(Live, "gfx.webrender.hit-test", WebRenderHitTest, bool, false);
// Use vsync events generated by hardware
DECL_GFX_PREF(Once, "gfx.work-around-driver-bugs", WorkAroundDriverBugs, bool, true);

View File

@ -11,7 +11,6 @@
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/widget/CompositorWidget.h"
#include "mozilla/widget/CompositorWidget.h"
#include "mozilla/layers/SynchronousTask.h"
#define WRDL_LOG(...)
@ -222,6 +221,18 @@ WebRenderAPI::UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
wr_scroll_layer_with_id(mDocHandle, aPipelineId, aScrollId, aScrollPosition);
}
bool
WebRenderAPI::HitTest(const wr::WorldPoint& aPoint,
wr::WrPipelineId& aOutPipelineId,
layers::FrameMetrics::ViewID& aOutScrollId,
gfx::CompositorHitTestInfo& aOutHitInfo)
{
static_assert(sizeof(gfx::CompositorHitTestInfo) == sizeof(uint8_t),
"CompositorHitTestInfo should be u8-sized");
return wr_api_hit_test(mDocHandle, aPoint,
&aOutPipelineId, &aOutScrollId, (uint8_t*)&aOutHitInfo);
}
void
WebRenderAPI::GenerateFrame()
{
@ -686,7 +697,7 @@ DisplayListBuilder::Finalize(wr::LayoutSize& aOutContentSize,
void
DisplayListBuilder::PushStackingContext(const wr::LayoutRect& aBounds,
const uint64_t& aAnimationId,
const WrAnimationProperty* aAnimation,
const float* aOpacity,
const gfx::Matrix4x4* aTransform,
wr::TransformStyle aTransformStyle,
@ -707,7 +718,7 @@ DisplayListBuilder::PushStackingContext(const wr::LayoutRect& aBounds,
const wr::LayoutTransform* maybePerspective = aPerspective ? &perspective : nullptr;
WRDL_LOG("PushStackingContext b=%s t=%s\n", mWrState, Stringify(aBounds).c_str(),
aTransform ? Stringify(*aTransform).c_str() : "none");
wr_dp_push_stacking_context(mWrState, aBounds, aAnimationId, aOpacity,
wr_dp_push_stacking_context(mWrState, aBounds, aAnimation, aOpacity,
maybeTransform, aTransformStyle, maybePerspective,
aMixBlendMode, aFilters.Elements(), aFilters.Length(), aIsBackfaceVisible);
}
@ -1248,5 +1259,20 @@ DisplayListBuilder::TopmostIsClip()
return mClipStack.back().is<wr::WrClipId>();
}
void
DisplayListBuilder::SetHitTestInfo(const layers::FrameMetrics::ViewID& aScrollId,
gfx::CompositorHitTestInfo aHitInfo)
{
static_assert(sizeof(gfx::CompositorHitTestInfo) == sizeof(uint8_t),
"CompositorHitTestInfo should be u8-sized");
wr_set_item_tag(mWrState, aScrollId, static_cast<uint8_t>(aHitInfo));
}
void
DisplayListBuilder::ClearHitTestInfo()
{
wr_clear_item_tag(mWrState);
}
} // namespace wr
} // namespace mozilla

View File

@ -12,6 +12,7 @@
#include <unordered_set>
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/gfx/CompositorHitTestInfo.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/Range.h"
#include "mozilla/webrender/webrender_ffi.h"
@ -143,6 +144,10 @@ public:
void UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
const layers::FrameMetrics::ViewID& aScrollId,
const wr::LayoutPoint& aScrollPosition);
bool HitTest(const wr::WorldPoint& aPoint,
wr::WrPipelineId& aOutPipelineId,
layers::FrameMetrics::ViewID& aOutScrollId,
gfx::CompositorHitTestInfo& aOutHitInfo);
void GenerateFrame();
void GenerateFrame(const nsTArray<wr::WrOpacityProperty>& aOpacityArray,
@ -228,7 +233,7 @@ public:
wr::BuiltDisplayList& aOutDisplayList);
void PushStackingContext(const wr::LayoutRect& aBounds, // TODO: We should work with strongly typed rects
const uint64_t& aAnimationId,
const wr::WrAnimationProperty* aAnimation,
const float* aOpacity,
const gfx::Matrix4x4* aTransform,
wr::TransformStyle aTransformStyle,
@ -421,6 +426,13 @@ public:
// If the topmost item on the stack is a clip or a scroll layer
bool TopmostIsClip();
// Set the hit-test info to be used for all display items until the next call
// to SetHitTestInfo or ClearHitTestInfo.
void SetHitTestInfo(const layers::FrameMetrics::ViewID& aScrollId,
gfx::CompositorHitTestInfo aHitInfo);
// Clears the hit-test info so that subsequent display items will not have it.
void ClearHitTestInfo();
// Try to avoid using this when possible.
wr::WrState* Raw() { return mWrState; }

View File

@ -333,6 +333,18 @@ impl ExternalImageHandler for WrExternalImageHandler {
}
}
#[repr(u32)]
pub enum WrAnimationType {
Transform = 0,
Opacity = 1,
}
#[repr(C)]
pub struct WrAnimationProperty {
effect_type: WrAnimationType,
id: u64,
}
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum WrFilterOpType {
@ -1178,6 +1190,7 @@ impl WebRenderFrameBuilder {
pub struct WrState {
pipeline_id: WrPipelineId,
frame_builder: WebRenderFrameBuilder,
current_tag: Option<ItemTag>,
}
#[no_mangle]
@ -1191,6 +1204,7 @@ pub extern "C" fn wr_state_new(pipeline_id: WrPipelineId,
frame_builder: WebRenderFrameBuilder::with_capacity(pipeline_id,
content_size,
capacity),
current_tag: None,
});
Box::into_raw(state)
@ -1224,7 +1238,7 @@ pub extern "C" fn wr_dp_clear_save(state: &mut WrState) {
#[no_mangle]
pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
bounds: LayoutRect,
animation_id: u64,
animation: *const WrAnimationProperty,
opacity: *const f32,
transform: *const LayoutTransform,
transform_style: TransformStyle,
@ -1250,26 +1264,28 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
}
}).collect();
let opacity = unsafe { opacity.as_ref() };
if let Some(opacity) = opacity {
let opacity_ref = unsafe { opacity.as_ref() };
if let Some(opacity) = opacity_ref {
if *opacity < 1.0 {
filters.push(FilterOp::Opacity(PropertyBinding::Value(*opacity)));
}
} else {
if animation_id > 0 {
filters.push(FilterOp::Opacity(PropertyBinding::Binding(PropertyBindingKey::new(animation_id))));
}
}
let transform = unsafe { transform.as_ref() };
let transform_binding = match animation_id {
0 => match transform {
Some(transform) => Some(PropertyBinding::Value(transform.clone())),
None => None,
},
_ => Some(PropertyBinding::Binding(PropertyBindingKey::new(animation_id))),
let transform_ref = unsafe { transform.as_ref() };
let mut transform_binding = match transform_ref {
Some(transform) => Some(PropertyBinding::Value(transform.clone())),
None => None,
};
let anim = unsafe { animation.as_ref() };
if let Some(anim) = anim {
debug_assert!(anim.id > 0);
match anim.effect_type {
WrAnimationType::Opacity => filters.push(FilterOp::Opacity(PropertyBinding::Binding(PropertyBindingKey::new(anim.id)))),
WrAnimationType::Transform => transform_binding = Some(PropertyBinding::Binding(PropertyBindingKey::new(anim.id))),
}
}
let perspective_ref = unsafe { perspective.as_ref() };
let perspective = match perspective_ref {
Some(perspective) => Some(perspective.clone()),
@ -1278,6 +1294,7 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::new(bounds);
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
@ -1468,6 +1485,7 @@ pub extern "C" fn wr_dp_push_iframe(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::new(rect);
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder.dl_builder.push_iframe(&prim_info, pipeline_id);
}
@ -1481,6 +1499,7 @@ pub extern "C" fn wr_dp_push_rect(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder.dl_builder.push_rect(&prim_info,
color);
}
@ -1507,6 +1526,7 @@ pub extern "C" fn wr_dp_push_image(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_image(&prim_info,
@ -1531,6 +1551,7 @@ pub extern "C" fn wr_dp_push_yuv_planar_image(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_yuv_image(&prim_info,
@ -1553,6 +1574,7 @@ pub extern "C" fn wr_dp_push_yuv_NV12_image(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_yuv_image(&prim_info,
@ -1574,6 +1596,7 @@ pub extern "C" fn wr_dp_push_yuv_interleaved_image(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_yuv_image(&prim_info,
@ -1598,6 +1621,7 @@ pub extern "C" fn wr_dp_push_text(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_text(&prim_info,
@ -1617,6 +1641,7 @@ pub extern "C" fn wr_dp_push_shadow(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder.dl_builder.push_shadow(&prim_info, shadow.into());
}
@ -1640,6 +1665,7 @@ pub extern "C" fn wr_dp_push_line(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(*bounds, (*clip).into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_line(&prim_info,
@ -1672,6 +1698,7 @@ pub extern "C" fn wr_dp_push_border(state: &mut WrState,
});
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_border(&prim_info,
@ -1702,6 +1729,7 @@ pub extern "C" fn wr_dp_push_border_image(state: &mut WrState,
});
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_border(&prim_info,
@ -1738,6 +1766,7 @@ pub extern "C" fn wr_dp_push_border_gradient(state: &mut WrState,
});
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_border(&prim_info,
@ -1775,6 +1804,7 @@ pub extern "C" fn wr_dp_push_border_radial_gradient(state: &mut WrState,
});
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_border(&prim_info,
@ -1807,6 +1837,7 @@ pub extern "C" fn wr_dp_push_linear_gradient(state: &mut WrState,
extend_mode.into());
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_gradient(&prim_info,
@ -1840,6 +1871,7 @@ pub extern "C" fn wr_dp_push_radial_gradient(state: &mut WrState,
extend_mode.into());
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_radial_gradient(&prim_info,
@ -1864,6 +1896,7 @@ pub extern "C" fn wr_dp_push_box_shadow(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_box_shadow(&prim_info,
@ -1891,6 +1924,38 @@ pub unsafe extern "C" fn wr_api_finalize_builder(state: &mut WrState,
*dl_descriptor = descriptor;
}
#[no_mangle]
pub extern "C" fn wr_set_item_tag(state: &mut WrState,
scroll_id: u64,
hit_info: u8) {
state.current_tag = Some((scroll_id, hit_info));
}
#[no_mangle]
pub extern "C" fn wr_clear_item_tag(state: &mut WrState) {
state.current_tag = None;
}
#[no_mangle]
pub extern "C" fn wr_api_hit_test(dh: &mut DocumentHandle,
point: WorldPoint,
out_pipeline_id: &mut WrPipelineId,
out_scroll_id: &mut u64,
out_hit_info: &mut u8) -> bool {
let result = dh.api.hit_test(dh.document_id, None, point, HitTestFlags::empty());
for item in &result.items {
// For now we should never be getting results back for which the tag is
// 0 (== CompositorHitTestInfo::eInvisibleToHitTest). In the future if
// we allow this, we'll want to |continue| on the loop in this scenario.
debug_assert!(item.tag.1 != 0);
*out_pipeline_id = item.pipeline;
*out_scroll_id = item.tag.0;
*out_hit_info = item.tag.1;
return true;
}
return false;
}
pub type VecU8 = Vec<u8>;
pub type ArcVecU8 = Arc<VecU8>;

View File

@ -2,7 +2,7 @@
* 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/. */
/* Generated with cbindgen:0.1.29 */
/* Generated with cbindgen:0.2.0 */
/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
* To generate this file:
@ -202,6 +202,13 @@ enum class TransformStyle : uint32_t {
Sentinel /* this must be last for serialization purposes. */
};
enum class WrAnimationType : uint32_t {
Transform = 0,
Opacity = 1,
Sentinel /* this must be last for serialization purposes. */
};
enum class WrExternalImageType : uint32_t {
NativeTexture = 0,
RawData = 1,
@ -431,6 +438,19 @@ struct WrTransformProperty {
typedef IdNamespace WrIdNamespace;
// A 2d Point tagged with a unit.
struct TypedPoint2D_f32__WorldPixel {
float x;
float y;
bool operator==(const TypedPoint2D_f32__WorldPixel& aOther) const {
return x == aOther.x &&
y == aOther.y;
}
};
typedef TypedPoint2D_f32__WorldPixel WorldPoint;
// Represents RGBA screen colors with floating point numbers.
//
// All components must be between 0.0 and 1.0.
@ -653,6 +673,16 @@ struct Shadow {
}
};
struct WrAnimationProperty {
WrAnimationType effect_type;
uint64_t id;
bool operator==(const WrAnimationProperty& aOther) const {
return effect_type == aOther.effect_type &&
id == aOther.id;
}
};
struct WrFilterOp {
WrFilterOpType filter_type;
float argument;
@ -1005,6 +1035,14 @@ WR_INLINE
WrIdNamespace wr_api_get_namespace(DocumentHandle *aDh)
WR_FUNC;
WR_INLINE
bool wr_api_hit_test(DocumentHandle *aDh,
WorldPoint aPoint,
WrPipelineId *aOutPipelineId,
uint64_t *aOutScrollId,
uint8_t *aOutHitInfo)
WR_FUNC;
WR_INLINE
void wr_api_remove_pipeline(DocumentHandle *aDh,
WrPipelineId aPipelineId)
@ -1052,6 +1090,10 @@ void wr_api_update_resources(DocumentHandle *aDh,
ResourceUpdates *aResources)
WR_FUNC;
WR_INLINE
void wr_clear_item_tag(WrState *aState)
WR_FUNC;
WR_INLINE
void wr_dec_ref_arc(const VecU8 *aArc)
WR_FUNC;
@ -1276,7 +1318,7 @@ WR_FUNC;
WR_INLINE
void wr_dp_push_stacking_context(WrState *aState,
LayoutRect aBounds,
uint64_t aAnimationId,
const WrAnimationProperty *aAnimation,
const float *aOpacity,
const LayoutTransform *aTransform,
TransformStyle aTransformStyle,
@ -1524,6 +1566,12 @@ void wr_scroll_layer_with_id(DocumentHandle *aDh,
LayoutPoint aNewScrollOrigin)
WR_FUNC;
WR_INLINE
void wr_set_item_tag(WrState *aState,
uint64_t aScrollId,
uint8_t aHitInfo)
WR_FUNC;
WR_INLINE
void wr_shutdown_external_log_handler()
WR_FUNC;

View File

@ -42,11 +42,11 @@ class AccessibleCaretEventHub::NoActionState
: public AccessibleCaretEventHub::State
{
public:
virtual const char* Name() const override { return "NoActionState"; }
const char* Name() const override { return "NoActionState"; }
virtual nsEventStatus OnPress(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint, int32_t aTouchId,
EventClassID aEventClass) override
nsEventStatus OnPress(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint, int32_t aTouchId,
EventClassID aEventClass) override
{
nsEventStatus rv = nsEventStatus_eIgnore;
@ -63,37 +63,36 @@ public:
return rv;
}
virtual void OnScrollStart(AccessibleCaretEventHub* aContext) override
void OnScrollStart(AccessibleCaretEventHub* aContext) override
{
aContext->mManager->OnScrollStart();
aContext->SetState(aContext->ScrollState());
}
virtual void OnScrollPositionChanged(
AccessibleCaretEventHub* aContext) override
void OnScrollPositionChanged(AccessibleCaretEventHub* aContext) override
{
aContext->mManager->OnScrollPositionChanged();
}
virtual void OnSelectionChanged(AccessibleCaretEventHub* aContext,
nsIDOMDocument* aDoc, nsISelection* aSel,
int16_t aReason) override
void OnSelectionChanged(AccessibleCaretEventHub* aContext,
nsIDOMDocument* aDoc, nsISelection* aSel,
int16_t aReason) override
{
aContext->mManager->OnSelectionChanged(aDoc, aSel, aReason);
}
virtual void OnBlur(AccessibleCaretEventHub* aContext,
bool aIsLeavingDocument) override
void OnBlur(AccessibleCaretEventHub* aContext,
bool aIsLeavingDocument) override
{
aContext->mManager->OnBlur();
}
virtual void OnReflow(AccessibleCaretEventHub* aContext) override
void OnReflow(AccessibleCaretEventHub* aContext) override
{
aContext->mManager->OnReflow();
}
virtual void Enter(AccessibleCaretEventHub* aContext) override
void Enter(AccessibleCaretEventHub* aContext) override
{
aContext->mPressPoint = nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
aContext->mActiveTouchId = kInvalidTouchId;
@ -107,10 +106,10 @@ class AccessibleCaretEventHub::PressCaretState
: public AccessibleCaretEventHub::State
{
public:
virtual const char* Name() const override { return "PressCaretState"; }
const char* Name() const override { return "PressCaretState"; }
virtual nsEventStatus OnMove(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
nsEventStatus OnMove(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
{
if (aContext->MoveDistanceIsLarge(aPoint)) {
if (NS_SUCCEEDED(aContext->mManager->DragCaret(aPoint))) {
@ -121,7 +120,7 @@ public:
return nsEventStatus_eConsumeNoDefault;
}
virtual nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override
nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override
{
aContext->mManager->ReleaseCaret();
aContext->mManager->TapCaret(aContext->mPressPoint);
@ -130,8 +129,8 @@ public:
return nsEventStatus_eConsumeNoDefault;
}
virtual nsEventStatus OnLongTap(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
nsEventStatus OnLongTap(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
{
return nsEventStatus_eConsumeNoDefault;
}
@ -144,17 +143,17 @@ class AccessibleCaretEventHub::DragCaretState
: public AccessibleCaretEventHub::State
{
public:
virtual const char* Name() const override { return "DragCaretState"; }
const char* Name() const override { return "DragCaretState"; }
virtual nsEventStatus OnMove(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
nsEventStatus OnMove(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
{
aContext->mManager->DragCaret(aPoint);
return nsEventStatus_eConsumeNoDefault;
}
virtual nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override
nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override
{
aContext->mManager->ReleaseCaret();
aContext->SetState(aContext->NoActionState());
@ -170,10 +169,10 @@ class AccessibleCaretEventHub::PressNoCaretState
: public AccessibleCaretEventHub::State
{
public:
virtual const char* Name() const override { return "PressNoCaretState"; }
const char* Name() const override { return "PressNoCaretState"; }
virtual nsEventStatus OnMove(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
nsEventStatus OnMove(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
{
if (aContext->MoveDistanceIsLarge(aPoint)) {
aContext->SetState(aContext->NoActionState());
@ -182,29 +181,29 @@ public:
return nsEventStatus_eIgnore;
}
virtual nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override
nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override
{
aContext->SetState(aContext->NoActionState());
return nsEventStatus_eIgnore;
}
virtual nsEventStatus OnLongTap(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
nsEventStatus OnLongTap(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
{
aContext->SetState(aContext->LongTapState());
return aContext->GetState()->OnLongTap(aContext, aPoint);
}
virtual void OnScrollStart(AccessibleCaretEventHub* aContext) override
void OnScrollStart(AccessibleCaretEventHub* aContext) override
{
aContext->mManager->OnScrollStart();
aContext->SetState(aContext->ScrollState());
}
virtual void OnBlur(AccessibleCaretEventHub* aContext,
bool aIsLeavingDocument) override
void OnBlur(AccessibleCaretEventHub* aContext,
bool aIsLeavingDocument) override
{
aContext->mManager->OnBlur();
if (aIsLeavingDocument) {
@ -212,24 +211,24 @@ public:
}
}
virtual void OnSelectionChanged(AccessibleCaretEventHub* aContext,
nsIDOMDocument* aDoc, nsISelection* aSel,
int16_t aReason) override
void OnSelectionChanged(AccessibleCaretEventHub* aContext,
nsIDOMDocument* aDoc, nsISelection* aSel,
int16_t aReason) override
{
aContext->mManager->OnSelectionChanged(aDoc, aSel, aReason);
}
virtual void OnReflow(AccessibleCaretEventHub* aContext) override
void OnReflow(AccessibleCaretEventHub* aContext) override
{
aContext->mManager->OnReflow();
}
virtual void Enter(AccessibleCaretEventHub* aContext) override
void Enter(AccessibleCaretEventHub* aContext) override
{
aContext->LaunchLongTapInjector();
}
virtual void Leave(AccessibleCaretEventHub* aContext) override
void Leave(AccessibleCaretEventHub* aContext) override
{
aContext->CancelLongTapInjector();
}
@ -242,21 +241,20 @@ class AccessibleCaretEventHub::ScrollState
: public AccessibleCaretEventHub::State
{
public:
virtual const char* Name() const override { return "ScrollState"; }
const char* Name() const override { return "ScrollState"; }
virtual void OnScrollEnd(AccessibleCaretEventHub* aContext) override
void OnScrollEnd(AccessibleCaretEventHub* aContext) override
{
aContext->SetState(aContext->PostScrollState());
}
virtual void OnScrollPositionChanged(
AccessibleCaretEventHub* aContext) override
void OnScrollPositionChanged(AccessibleCaretEventHub* aContext) override
{
aContext->mManager->OnScrollPositionChanged();
}
virtual void OnBlur(AccessibleCaretEventHub* aContext,
bool aIsLeavingDocument) override
void OnBlur(AccessibleCaretEventHub* aContext,
bool aIsLeavingDocument) override
{
aContext->mManager->OnBlur();
if (aIsLeavingDocument) {
@ -273,11 +271,11 @@ class AccessibleCaretEventHub::PostScrollState
: public AccessibleCaretEventHub::State
{
public:
virtual const char* Name() const override { return "PostScrollState"; }
const char* Name() const override { return "PostScrollState"; }
virtual nsEventStatus OnPress(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint, int32_t aTouchId,
EventClassID aEventClass) override
nsEventStatus OnPress(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint, int32_t aTouchId,
EventClassID aEventClass) override
{
aContext->mManager->OnScrollEnd();
aContext->SetState(aContext->NoActionState());
@ -286,19 +284,19 @@ public:
aEventClass);
}
virtual void OnScrollStart(AccessibleCaretEventHub* aContext) override
void OnScrollStart(AccessibleCaretEventHub* aContext) override
{
aContext->SetState(aContext->ScrollState());
}
virtual void OnScrollEnd(AccessibleCaretEventHub* aContext) override
void OnScrollEnd(AccessibleCaretEventHub* aContext) override
{
aContext->mManager->OnScrollEnd();
aContext->SetState(aContext->NoActionState());
}
virtual void OnBlur(AccessibleCaretEventHub* aContext,
bool aIsLeavingDocument) override
void OnBlur(AccessibleCaretEventHub* aContext,
bool aIsLeavingDocument) override
{
aContext->mManager->OnBlur();
if (aIsLeavingDocument) {
@ -306,13 +304,13 @@ public:
}
}
virtual void Enter(AccessibleCaretEventHub* aContext) override
void Enter(AccessibleCaretEventHub* aContext) override
{
// Launch the injector to leave PostScrollState.
aContext->LaunchScrollEndInjector();
}
virtual void Leave(AccessibleCaretEventHub* aContext) override
void Leave(AccessibleCaretEventHub* aContext) override
{
aContext->CancelScrollEndInjector();
}
@ -325,10 +323,10 @@ class AccessibleCaretEventHub::LongTapState
: public AccessibleCaretEventHub::State
{
public:
virtual const char* Name() const override { return "LongTapState"; }
const char* Name() const override { return "LongTapState"; }
virtual nsEventStatus OnLongTap(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
nsEventStatus OnLongTap(AccessibleCaretEventHub* aContext,
const nsPoint& aPoint) override
{
// In general text selection is lower-priority than the context menu. If
// we consume this long-press event, then it prevents the context menu from
@ -338,7 +336,7 @@ public:
return nsEventStatus_eIgnore;
}
virtual nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override
nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override
{
aContext->SetState(aContext->NoActionState());
@ -347,13 +345,13 @@ public:
return nsEventStatus_eIgnore;
}
virtual void OnScrollStart(AccessibleCaretEventHub* aContext) override
void OnScrollStart(AccessibleCaretEventHub* aContext) override
{
aContext->mManager->OnScrollStart();
aContext->SetState(aContext->ScrollState());
}
virtual void OnReflow(AccessibleCaretEventHub* aContext) override
void OnReflow(AccessibleCaretEventHub* aContext) override
{
aContext->mManager->OnReflow();
}
@ -401,10 +399,6 @@ AccessibleCaretEventHub::AccessibleCaretEventHub(nsIPresShell* aPresShell)
}
}
AccessibleCaretEventHub::~AccessibleCaretEventHub()
{
}
void
AccessibleCaretEventHub::Init()
{

View File

@ -11,6 +11,7 @@
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "nsCOMPtr.h"
#include "nsDocShell.h"
#include "nsIFrame.h"
#include "nsIReflowObserver.h"
#include "nsIScrollObserver.h"
@ -19,7 +20,6 @@
#include "mozilla/RefPtr.h"
#include "nsWeakReference.h"
class nsDocShell;
class nsIPresShell;
class nsITimer;
@ -89,7 +89,7 @@ public:
State* GetState() const;
protected:
virtual ~AccessibleCaretEventHub();
virtual ~AccessibleCaretEventHub() = default;
#define MOZ_DECL_STATE_CLASS_GETTER(aClassName) \
class aClassName; \

View File

@ -122,10 +122,6 @@ AccessibleCaretManager::AccessibleCaretManager(nsIPresShell* aPresShell)
}
}
AccessibleCaretManager::~AccessibleCaretManager()
{
}
void
AccessibleCaretManager::Terminate()
{
@ -219,7 +215,7 @@ AccessibleCaretManager::HideCarets()
}
void
AccessibleCaretManager::UpdateCarets(UpdateCaretsHintSet aHint)
AccessibleCaretManager::UpdateCarets(const UpdateCaretsHintSet& aHint)
{
FlushLayout();
if (IsTerminated()) {
@ -280,7 +276,7 @@ AccessibleCaretManager::HasNonEmptyTextContent(nsINode* aNode) const
}
void
AccessibleCaretManager::UpdateCaretsForCursorMode(UpdateCaretsHintSet aHints)
AccessibleCaretManager::UpdateCaretsForCursorMode(const UpdateCaretsHintSet& aHints)
{
AC_LOG("%s, selection: %p", __FUNCTION__, GetSelection());
@ -339,7 +335,7 @@ AccessibleCaretManager::UpdateCaretsForCursorMode(UpdateCaretsHintSet aHints)
}
void
AccessibleCaretManager::UpdateCaretsForSelectionMode(UpdateCaretsHintSet aHints)
AccessibleCaretManager::UpdateCaretsForSelectionMode(const UpdateCaretsHintSet& aHints)
{
AC_LOG("%s: selection: %p", __FUNCTION__, GetSelection());
@ -789,24 +785,24 @@ AccessibleCaretManager::GetFrameSelection() const
MOZ_ASSERT(fm);
nsIContent* focusedContent = fm->GetFocusedContent();
if (focusedContent) {
nsIFrame* focusFrame = focusedContent->GetPrimaryFrame();
if (!focusFrame) {
return nullptr;
}
// Prevent us from touching the nsFrameSelection associated with other
// PresShell.
RefPtr<nsFrameSelection> fs = focusFrame->GetFrameSelection();
if (!fs || fs->GetShell() != mPresShell) {
return nullptr;
}
return fs.forget();
} else {
if (!focusedContent) {
// For non-editable content
return mPresShell->FrameSelection();
}
nsIFrame* focusFrame = focusedContent->GetPrimaryFrame();
if (!focusFrame) {
return nullptr;
}
// Prevent us from touching the nsFrameSelection associated with other
// PresShell.
RefPtr<nsFrameSelection> fs = focusFrame->GetFrameSelection();
if (!fs || fs->GetShell() != mPresShell) {
return nullptr;
}
return fs.forget();
}
nsAutoString

View File

@ -49,7 +49,7 @@ class AccessibleCaretManager
{
public:
explicit AccessibleCaretManager(nsIPresShell* aPresShell);
virtual ~AccessibleCaretManager();
virtual ~AccessibleCaretManager() = default;
// Called by AccessibleCaretEventHub to inform us that PresShell is destroyed.
void Terminate();
@ -145,13 +145,13 @@ protected:
// Update carets based on current selection status. This function will flush
// layout, so caller must ensure the PresShell is still valid after calling
// this method.
void UpdateCarets(UpdateCaretsHintSet aHints = UpdateCaretsHint::Default);
void UpdateCarets(const UpdateCaretsHintSet& aHints = UpdateCaretsHint::Default);
// Force hiding all carets regardless of the current selection status.
void HideCarets();
void UpdateCaretsForCursorMode(UpdateCaretsHintSet aHints);
void UpdateCaretsForSelectionMode(UpdateCaretsHintSet aHints);
void UpdateCaretsForCursorMode(const UpdateCaretsHintSet& aHints);
void UpdateCaretsForSelectionMode(const UpdateCaretsHintSet& aHints);
// Provide haptic / touch feedback, primarily for select on longpress.
void ProvideHapticFeedback();

View File

@ -71,15 +71,15 @@ public:
mInitialized = true;
}
virtual nsPoint GetTouchEventPosition(WidgetTouchEvent* aEvent,
int32_t aIdentifier) const override
nsPoint GetTouchEventPosition(WidgetTouchEvent* aEvent,
int32_t aIdentifier) const override
{
// Return the device point directly.
LayoutDeviceIntPoint touchIntPoint = aEvent->mTouches[0]->mRefPoint;
return nsPoint(touchIntPoint.x, touchIntPoint.y);
}
virtual nsPoint GetMouseEventPosition(WidgetMouseEvent* aEvent) const override
nsPoint GetMouseEventPosition(WidgetMouseEvent* aEvent) const override
{
// Return the device point directly.
LayoutDeviceIntPoint mouseIntPoint = aEvent->AsGUIEvent()->mRefPoint;
@ -112,7 +112,7 @@ public:
mHub.get()->AddRef();
}
~AccessibleCaretEventHubTester()
~AccessibleCaretEventHubTester() override
{
// Release the ref added in the constructor.
mHub.get()->Release();

View File

@ -36,13 +36,13 @@ public:
public:
MockAccessibleCaret() : AccessibleCaret(nullptr) {}
virtual void SetAppearance(Appearance aAppearance) override
void SetAppearance(Appearance aAppearance) override
{
// A simplified version without touching CaretElement().
mAppearance = aAppearance;
}
virtual void SetSelectionBarEnabled(bool aEnabled) override
void SetSelectionBarEnabled(bool aEnabled) override
{
// A simplified version without touching CaretElement().
mSelectionBarEnabled = aEnabled;
@ -80,22 +80,22 @@ public:
return static_cast<MockAccessibleCaret&>(*mSecondCaret);
}
virtual bool CompareTreePosition(nsIFrame* aStartFrame,
nsIFrame* aEndFrame) const override
bool CompareTreePosition(nsIFrame* aStartFrame,
nsIFrame* aEndFrame) const override
{
return true;
}
virtual bool IsCaretDisplayableInCursorMode(
nsIFrame** aOutFrame = nullptr, int32_t* aOutOffset = nullptr) const override
bool IsCaretDisplayableInCursorMode(nsIFrame** aOutFrame = nullptr,
int32_t* aOutOffset = nullptr) const override
{
return true;
}
virtual bool UpdateCaretsForOverlappingTilt() override { return true; }
bool UpdateCaretsForOverlappingTilt() override { return true; }
virtual void UpdateCaretsForAlwaysTilt(nsIFrame* aStartFrame,
nsIFrame* aEndFrame)
void UpdateCaretsForAlwaysTilt(nsIFrame* aStartFrame,
nsIFrame* aEndFrame) override
{
if (mFirstCaret->IsVisuallyVisible()) {
mFirstCaret->SetAppearance(Appearance::Left);
@ -105,7 +105,7 @@ public:
}
}
virtual bool IsTerminated() const override { return false; }
bool IsTerminated() const override { return false; }
MOCK_CONST_METHOD0(GetCaretMode, CaretMode());
MOCK_CONST_METHOD1(DispatchCaretStateChangedEvent,

View File

@ -586,7 +586,7 @@ load 1039454-1.html
load 1042489.html
load 1054010-1.html
load 1058954-1.html
asserts-if(!stylo,0-2) skip-if(stylo) pref(dom.webcomponents.enabled,true) load 1059138-1.html # bug 1389936 for non-stylo, bug 1409136 for stylo.
asserts-if(!stylo,0-2) pref(dom.webcomponents.enabled,true) pref(dom.webcomponents.customelements.enabled,true) load 1059138-1.html # bug 1389936
load 1134531.html
load 1134667.html
load 1137723-1.html

View File

@ -204,6 +204,7 @@ LOCAL_INCLUDES += [
'../svg',
'../tables',
'../xul',
'/docshell/base',
'/dom/base',
'/dom/html',
'/dom/xul',

View File

@ -22,6 +22,7 @@
#include "nsCOMPtr.h"
#include "nsFrameList.h"
#include "nsPlaceholderFrame.h"
#include "nsPluginFrame.h"
#include "nsIContent.h"
#include "nsIContentInlines.h"
#include "nsContentUtils.h"
@ -3021,6 +3022,13 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
eventRegions = nullptr;
}
}
if (aBuilder->BuildCompositorHitTestInfo()) {
CompositorHitTestInfo info = GetCompositorHitTestInfo(aBuilder);
if (info != CompositorHitTestInfo::eInvisibleToHitTest) {
set.BorderBackground()->AppendNewToBottom(
new (aBuilder) nsDisplayCompositorHitTestInfo(aBuilder, this, info));
}
}
}
if (aBuilder->IsBackgroundOnly()) {
@ -3451,6 +3459,13 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
CheckForApzAwareEventHandlers(aBuilder, child);
if (aBuilder->BuildCompositorHitTestInfo()) {
CompositorHitTestInfo info = child->GetCompositorHitTestInfo(aBuilder);
if (info != CompositorHitTestInfo::eInvisibleToHitTest) {
aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayCompositorHitTestInfo(aBuilder, child, info));
}
}
nsDisplayLayerEventRegions* eventRegions = aBuilder->GetLayerEventRegions();
if (eventRegions) {
eventRegions->AddFrame(aBuilder, child);
@ -3668,6 +3683,18 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
child->MarkAbsoluteFramesForDisplayList(aBuilder);
if (aBuilder->BuildCompositorHitTestInfo()) {
CompositorHitTestInfo info = child->GetCompositorHitTestInfo(aBuilder);
if (info != CompositorHitTestInfo::eInvisibleToHitTest) {
nsDisplayItem* item =
new (aBuilder) nsDisplayCompositorHitTestInfo(aBuilder, child, info);
if (isPositioned) {
list.AppendNewToTop(item);
} else {
aLists.BorderBackground()->AppendNewToTop(item);
}
}
}
if (aBuilder->IsBuildingLayerEventRegions()) {
// If this frame has a different animated geometry root than its parent,
// make sure we accumulate event regions for its layer.
@ -11182,6 +11209,80 @@ nsIFrame::AddSizeOfExcludingThisForTree(nsWindowSizes& aSizes) const
}
}
CompositorHitTestInfo
nsIFrame::GetCompositorHitTestInfo(nsDisplayListBuilder* aBuilder)
{
CompositorHitTestInfo result = CompositorHitTestInfo::eInvisibleToHitTest;
if (aBuilder->IsInsidePointerEventsNoneDoc()) {
// Somewhere up the parent document chain is a subdocument with pointer-
// events:none set on it.
return result;
}
if (!GetParent()) {
MOZ_ASSERT(IsViewportFrame());
// Viewport frames are never event targets, other frames, like canvas frames,
// are the event targets for any regions viewport frames may cover.
return result;
}
uint8_t pointerEvents = StyleUserInterface()->GetEffectivePointerEvents(this);
if (pointerEvents == NS_STYLE_POINTER_EVENTS_NONE) {
return result;
}
if (!StyleVisibility()->IsVisible()) {
return result;
}
// Anything that didn't match the above conditions is visible to hit-testing.
result |= CompositorHitTestInfo::eVisibleToHitTest;
if (aBuilder->IsBuildingNonLayerizedScrollbar() ||
aBuilder->GetAncestorHasApzAwareEventHandler()) {
// Scrollbars may be painted into a layer below the actual layer they will
// scroll, and therefore wheel events may be dispatched to the outer frame
// instead of the intended scrollframe. To address this, we force a d-t-c
// region on scrollbar frames that won't be placed in their own layer. See
// bug 1213324 for details.
result |= CompositorHitTestInfo::eDispatchToContent;
} else if (IsObjectFrame()) {
// If the frame is a plugin frame and wants to handle wheel events as
// default action, we should add the frame to dispatch-to-content region.
nsPluginFrame* pluginFrame = do_QueryFrame(this);
if (pluginFrame && pluginFrame->WantsToHandleWheelEventAsDefaultAction()) {
result |= CompositorHitTestInfo::eDispatchToContent;
}
}
nsIFrame* touchActionFrame = this;
if (nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(this)) {
touchActionFrame = do_QueryFrame(scrollFrame);
}
uint32_t touchAction = nsLayoutUtils::GetTouchActionFromFrame(touchActionFrame);
// The CSS allows the syntax auto | none | [pan-x || pan-y] | manipulation
// so we can eliminate some combinations of things.
if (touchAction == NS_STYLE_TOUCH_ACTION_AUTO) {
// nothing to do
} else if (touchAction & NS_STYLE_TOUCH_ACTION_MANIPULATION) {
result |= CompositorHitTestInfo::eTouchActionDoubleTapZoomDisabled;
} else {
if (!(touchAction & NS_STYLE_TOUCH_ACTION_PAN_X)) {
result |= CompositorHitTestInfo::eTouchActionPanXDisabled;
}
if (!(touchAction & NS_STYLE_TOUCH_ACTION_PAN_Y)) {
result |= CompositorHitTestInfo::eTouchActionPanYDisabled;
}
if (touchAction & NS_STYLE_TOUCH_ACTION_NONE) {
result |= CompositorHitTestInfo::eTouchActionPinchZoomDisabled
| CompositorHitTestInfo::eTouchActionDoubleTapZoomDisabled;
// pan-x and pan-y disabled flags will already have been set above
MOZ_ASSERT(result & CompositorHitTestInfo::eTouchActionPanXDisabled);
MOZ_ASSERT(result & CompositorHitTestInfo::eTouchActionPanYDisabled);
}
}
return result;
}
// Box layout debugging
#ifdef DEBUG_REFLOW
int32_t gIndent2 = 0;

View File

@ -43,6 +43,7 @@
#include "Visibility.h"
#include "nsChangeHint.h"
#include "nsStyleContextInlines.h"
#include "mozilla/gfx/CompositorHitTestInfo.h"
#include "mozilla/gfx/MatrixFwd.h"
#include "nsDisplayItemTypes.h"
@ -4145,6 +4146,8 @@ public:
bool BuiltBlendContainer() { return mBuiltBlendContainer; }
void SetBuiltBlendContainer(bool aBuilt) { mBuiltBlendContainer = aBuilt; }
mozilla::gfx::CompositorHitTestInfo GetCompositorHitTestInfo(nsDisplayListBuilder* aBuilder);
protected:
static void DestroyAnonymousContent(nsPresContext* aPresContext,
already_AddRefed<nsIContent>&& aContent);

View File

@ -28,6 +28,7 @@ DECLARE_DISPLAY_ITEM_TYPE(CHECKED_RADIOBUTTON, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(CLEAR_BACKGROUND, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(COLUMN_RULE, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(COMBOBOX_FOCUS, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(COMPOSITOR_HITTEST_INFO, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(EVENT_RECEIVER, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(LAYER_EVENT_REGIONS, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(FIELDSET_BORDER_BACKGROUND, 0)

View File

@ -82,7 +82,6 @@
#include "nsDOMTokenList.h"
#include "mozilla/RuleNodeCacheConditions.h"
#include "nsCSSProps.h"
#include "nsPluginFrame.h"
#include "nsSVGMaskFrame.h"
#include "nsTableCellFrame.h"
#include "nsTableColFrame.h"
@ -964,6 +963,11 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
{
MOZ_COUNT_CTOR(nsDisplayListBuilder);
mBuildCompositorHitTestInfo = gfxVars::UseWebRender()
&& gfxPrefs::WebRenderHitTest()
&& mAsyncPanZoomEnabled
&& mMode == nsDisplayListBuilderMode::PAINTING;
nsPresContext* pc = aReferenceFrame->PresContext();
nsIPresShell *shell = pc->PresShell();
if (pc->IsRenderingOnlySelection()) {
@ -4829,36 +4833,83 @@ nsDisplayEventReceiver::HitTest(nsDisplayListBuilder* aBuilder,
aOutFrames->AppendElement(mFrame);
}
bool
nsDisplayEventReceiver::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder)
{
// This display item should never be getting created when building a display
// list for WebRender consumption, so this function should never get called.
MOZ_ASSERT(false);
return true;
}
bool
nsDisplayCompositorHitTestInfo::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder)
{
nsRect borderBox;
nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(mFrame);
if (scrollFrame) {
// If the frame is content of a scrollframe, then we need to pick up the
// area corresponding to the overflow rect as well. Otherwise the parts of
// the overflow that are not occupied by descendants get skipped and the
// APZ code sends touch events to the content underneath instead.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1127773#c15.
borderBox = mFrame->GetScrollableOverflowRect();
} else {
borderBox = nsRect(nsPoint(0, 0), mFrame->GetSize());
}
if (borderBox.IsEmpty()) {
return true;
}
wr::LayoutRect rect = aSc.ToRelativeLayoutRect(
LayoutDeviceRect::FromAppUnits(
borderBox + aDisplayListBuilder->ToReferenceFrame(mFrame),
mFrame->PresContext()->AppUnitsPerDevPixel()));
// XXX: eventually this scrollId computation and the SetHitTestInfo
// call will get moved out into the WR display item iteration code so that
// we don't need to do it as often, and so that we can do it for other
// display item types as well (reducing the need for as many instances of
// this display item).
FrameMetrics::ViewID scrollId = FrameMetrics::NULL_SCROLL_ID;
if (const ActiveScrolledRoot* asr = GetActiveScrolledRoot()) {
scrollId = nsLayoutUtils::ViewIDForASR(asr);
}
// Insert a transparent rectangle with the hit-test info
aBuilder.SetHitTestInfo(scrollId, mHitTestInfo);
aBuilder.PushRect(rect, rect, true, wr::ToColorF(gfx::Color()));
aBuilder.ClearHitTestInfo();
return true;
}
void
nsDisplayCompositorHitTestInfo::WriteDebugInfo(std::stringstream& aStream)
{
aStream << nsPrintfCString(" (hitTestInfo 0x%x)", (int)mHitTestInfo).get();
}
void
nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame)
{
NS_ASSERTION(aBuilder->FindReferenceFrameFor(aFrame) == aBuilder->FindReferenceFrameFor(mFrame),
"Reference frame mismatch");
if (aBuilder->IsInsidePointerEventsNoneDoc()) {
// Somewhere up the parent document chain is a subdocument with pointer-
// events:none set on it.
CompositorHitTestInfo hitInfo =
aFrame->GetCompositorHitTestInfo(aBuilder);
if (hitInfo == CompositorHitTestInfo::eInvisibleToHitTest) {
return;
}
if (!aFrame->GetParent()) {
MOZ_ASSERT(aFrame->IsViewportFrame());
// Viewport frames are never event targets, other frames, like canvas frames,
// are the event targets for any regions viewport frames may cover.
return;
}
uint8_t pointerEvents =
aFrame->StyleUserInterface()->GetEffectivePointerEvents(aFrame);
if (pointerEvents == NS_STYLE_POINTER_EVENTS_NONE) {
return;
}
bool simpleRegions = aFrame->HasAnyStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS);
if (!simpleRegions) {
if (!aFrame->StyleVisibility()->IsVisible()) {
return;
}
}
// XXX handle other pointerEvents values for SVG
@ -4889,6 +4940,11 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder,
borderBox += aBuilder->ToReferenceFrame(aFrame);
bool borderBoxHasRoundedCorners = false;
// use the NS_FRAME_SIMPLE_EVENT_REGIONS to avoid calling the slightly
// expensive HasNonZeroCorner function if we know from a previous run that
// the frame has zero corners.
bool simpleRegions = aFrame->HasAnyStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS);
if (!simpleRegions) {
if (nsLayoutUtils::HasNonZeroCorner(aFrame->StyleBorder()->mBorderRadius)) {
borderBoxHasRoundedCorners = true;
@ -4914,39 +4970,25 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder,
mHitRegion.Add(aFrame, borderBox);
}
if (aBuilder->IsBuildingNonLayerizedScrollbar() ||
aBuilder->GetAncestorHasApzAwareEventHandler())
{
// Scrollbars may be painted into a layer below the actual layer they will
// scroll, and therefore wheel events may be dispatched to the outer frame
// instead of the intended scrollframe. To address this, we force a d-t-c
// region on scrollbar frames that won't be placed in their own layer. See
// bug 1213324 for details.
if (hitInfo & CompositorHitTestInfo::eDispatchToContent) {
mDispatchToContentHitRegion.Add(aFrame, borderBox);
} else if (aFrame->IsObjectFrame()) {
// If the frame is a plugin frame and wants to handle wheel events as
// default action, we should add the frame to dispatch-to-content region.
nsPluginFrame* pluginFrame = do_QueryFrame(aFrame);
if (pluginFrame && pluginFrame->WantsToHandleWheelEventAsDefaultAction()) {
mDispatchToContentHitRegion.Add(aFrame, borderBox);
}
}
// Touch action region
nsIFrame* touchActionFrame = aFrame;
if (scrollFrame) {
touchActionFrame = do_QueryFrame(scrollFrame);
}
uint32_t touchAction = nsLayoutUtils::GetTouchActionFromFrame(touchActionFrame);
if (touchAction != NS_STYLE_TOUCH_ACTION_AUTO) {
if (touchAction & NS_STYLE_TOUCH_ACTION_NONE) {
auto touchFlags = hitInfo & CompositorHitTestInfo::eTouchActionMask;
if (touchFlags) {
// something was disabled
if (touchFlags == CompositorHitTestInfo::eTouchActionMask) {
// everything was disabled, so touch-action:none
mNoActionRegion.Add(aFrame, borderBox);
} else {
if ((touchAction & NS_STYLE_TOUCH_ACTION_PAN_X)) {
if (!(hitInfo & CompositorHitTestInfo::eTouchActionPanXDisabled)) {
// pan-x is allowed
mHorizontalPanRegion.Add(aFrame, borderBox);
}
if ((touchAction & NS_STYLE_TOUCH_ACTION_PAN_Y)) {
if (!(hitInfo & CompositorHitTestInfo::eTouchActionPanYDisabled)) {
// pan-y is allowed
mVerticalPanRegion.Add(aFrame, borderBox);
}
}
@ -6510,10 +6552,14 @@ nsDisplayOpacity::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuil
// Note that animationsId can be 0 (uninitialized in AnimationInfo) if there
// are no active animations.
uint64_t animationsId = animationInfo.GetCompositorAnimationsId();
wr::WrAnimationProperty prop;
if (!animationInfo.GetAnimations().IsEmpty()) {
opacityForSC = nullptr;
OptionalOpacity opacityForCompositor = mOpacity;
prop.id = animationsId;
prop.effect_type = wr::WrAnimationType::Opacity;
OpAddCompositorAnimations
anim(CompositorAnimations(animationInfo.GetAnimations(), animationsId),
@ -6526,7 +6572,8 @@ nsDisplayOpacity::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuil
}
nsTArray<mozilla::wr::WrFilterOp> filters;
StackingContextHelper sc(aSc, aBuilder, filters, nullptr, animationsId,
StackingContextHelper sc(aSc, aBuilder, filters, nullptr,
animationsId ? &prop : nullptr,
opacityForSC);
aManager->CommandBuilder().CreateWebRenderCommandsFromDisplayList(&mList,
@ -6815,8 +6862,13 @@ nsDisplayOwnLayer::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBui
animationInfo.EnsureAnimationsId();
mWrAnimationId = animationInfo.GetCompositorAnimationsId();
StackingContextHelper sc(aSc, aBuilder, nsTArray<wr::WrFilterOp>(), nullptr,
mWrAnimationId);
wr::WrAnimationProperty prop;
prop.id = mWrAnimationId;
prop.effect_type = wr::WrAnimationType::Transform;
StackingContextHelper sc(aSc, aBuilder, nsTArray<wr::WrFilterOp>(),
nullptr, &prop);
nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc,
aManager, aDisplayListBuilder);
@ -8324,13 +8376,16 @@ nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBu
// Note that animationsId can be 0 (uninitialized in AnimationInfo) if there
// are no active animations.
uint64_t animationsId = animationInfo.GetCompositorAnimationsId();
wr::WrAnimationProperty prop;
if (!animationInfo.GetAnimations().IsEmpty()) {
// Update transfrom as nullptr in stacking context if there exists
// transform animation, the transform value will be resolved
// after animation sampling on the compositor
transformForSC = nullptr;
prop.id = animationsId;
prop.effect_type = wr::WrAnimationType::Transform;
// Pass default transform to compositor in case gecko fails to
// get animated value after animation sampling.
OptionalTransform transformForCompositor = newTransformMatrix;
@ -8350,7 +8405,7 @@ nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBu
aBuilder,
filters,
&newTransformMatrix,
animationsId,
animationsId ? &prop : nullptr,
nullptr,
transformForSC,
nullptr,

View File

@ -502,6 +502,11 @@ public:
return mMode == nsDisplayListBuilderMode::PAINTING_SELECTION_BACKGROUND;
}
bool BuildCompositorHitTestInfo()
{
return mBuildCompositorHitTestInfo;
}
bool WillComputePluginGeometry() { return mWillComputePluginGeometry; }
/**
* @return true if "painting is suppressed" during page load and we
@ -1817,6 +1822,7 @@ private:
bool mHitTestIsForVisibility;
bool mIsBuilding;
bool mInInvalidSubtree;
bool mBuildCompositorHitTestInfo;
};
class nsDisplayItem;
@ -4299,11 +4305,60 @@ public:
}
#endif
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER)
};
/**
* Similar to nsDisplayEventReceiver in that it is used for hit-testing. However
* this gets built when we're doing widget painting and we need to send the
* compositor some hit-test info for a frame. This is effectively a dummy item
* whose sole purpose is to carry the hit-test info to the compositor.
*/
class nsDisplayCompositorHitTestInfo : public nsDisplayEventReceiver {
public:
nsDisplayCompositorHitTestInfo(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
mozilla::gfx::CompositorHitTestInfo aHitTestInfo)
: nsDisplayEventReceiver(aBuilder, aFrame)
, mHitTestInfo(aHitTestInfo)
{
MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo);
// We should never even create this display item if we're not building
// compositor hit-test info or if the computed hit info indicated the
// frame is invisible to hit-testing
MOZ_ASSERT(aBuilder->BuildCompositorHitTestInfo());
MOZ_ASSERT(mHitTestInfo != mozilla::gfx::CompositorHitTestInfo::eInvisibleToHitTest);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayCompositorHitTestInfo()
{
MOZ_COUNT_DTOR(nsDisplayCompositorHitTestInfo);
}
#endif
mozilla::gfx::CompositorHitTestInfo HitTestInfo() const { return mHitTestInfo; }
bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
void WriteDebugInfo(std::stringstream& aStream) override;
NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO)
private:
mozilla::gfx::CompositorHitTestInfo mHitTestInfo;
};
/**
* A display item that tracks event-sensitive regions which will be set
* on the ContainerLayer that eventually contains this item.

View File

@ -3673,6 +3673,7 @@ PeerConnectionImpl::BuildStatsQuery_m(
NS_ConvertASCIItoUTF16(localDescription.c_str()));
query->report->mRemoteSdp.Construct(
NS_ConvertASCIItoUTF16(remoteDescription.c_str()));
query->report->mOfferer.Construct(mJsepSession->IsOfferer());
}
}

View File

@ -644,8 +644,8 @@ public class GeckoPreferences
preferences.removePreference(pref);
i--;
continue;
} else if (PREFS_CATEGORY_EXPERIMENTAL_FEATURES.equals(key)
&& !AppConstants.MOZ_ANDROID_PWA) {
} else if (PREFS_CATEGORY_EXPERIMENTAL_FEATURES.equals(key) && ((PreferenceGroup) pref).getPreferenceCount() == 0) {
preferences.removePreference(pref);
i--;
continue;

View File

@ -15,5 +15,4 @@ tags = webextensions
[test_ext_options_ui.html]
[test_ext_pageAction_show_hide.html]
[test_ext_pageAction_getPopup_setPopup.html]
skip-if = os == 'android' # bug 1373170
[test_ext_popup_behavior.html]

View File

@ -31,9 +31,9 @@ add_task(async function test_setPopup_and_getPopup() {
async function createAndTestNewTab(expectedPopup, url) {
// Create a tab.
let [tab] = await Promise.all([
browser.tabs.create({url}),
let [, tab] = await Promise.all([
tabCreatedPromise,
browser.tabs.create({url}),
]);
// Test that the default popup is returned before the popup is set for the tab.
@ -58,12 +58,12 @@ add_task(async function test_setPopup_and_getPopup() {
popup = await browser.pageAction.getPopup({tabId: tab2.id});
browser.test.assertTrue(popup.includes("b.html"), "Expected the second tab popup");
// Unset the title for the first tab and confirm that it is unset.
// Unset the popup for the first tab and confirm that it is unset.
browser.pageAction.setPopup({tabId: tab1.id, popup: ""});
popup = await browser.pageAction.getPopup({tabId: tab1.id});
browser.test.assertTrue(popup.includes("default.html"), "Expected the default popup to be returned");
// Reset the title for the first tab.
// Set the popup for the first tab.
browser.pageAction.setPopup({tabId: tab1.id, popup: "a.html"});
popup = await browser.pageAction.getPopup({tabId: tab1.id});
browser.test.assertTrue(popup.includes("a.html"), "Expected the first tab popup");
@ -78,25 +78,37 @@ add_task(async function test_setPopup_and_getPopup() {
browser.test.onMessage.addListener(async (msg, data) => {
if (msg === "select-tab") {
// Check if the requested tabId is already selected.
const [activeTab] = await browser.tabs.query({active: true});
if (activeTab.id === data.tabId) {
browser.test.sendMessage("tab-selected");
return;
}
// Select the requested tabId and wait the tab to be activated.
const onActivatedListener = ({tabId}) => {
if (tabId === data.tabId) {
browser.tabs.onActivated.removeListener(onActivatedListener);
browser.test.sendMessage("tab-selected");
}
};
browser.tabs.onActivated.addListener(onActivatedListener);
await browser.tabs.update(data.tabId, {active: true});
browser.test.sendMessage("tab-selected");
} else if (msg === "page-action-show") {
browser.pageAction.show(data.tabId).then(() => {
browser.test.sendMessage("page-action-shown");
});
await browser.pageAction.show(data.tabId);
browser.test.sendMessage("page-action-shown");
} else if (msg == "page-action-set-popup") {
if (data.popup == "") {
expectingOnClicked[data.tabId] = true;
} else {
delete expectingOnClicked[tabId];
}
browser.pageAction.setPopup({tabId: data.tabId, popup: data.popup}).then(() => {
browser.test.sendMessage("page-action-popup-set");
});
await browser.pageAction.setPopup({tabId: data.tabId, popup: data.popup});
browser.test.sendMessage("page-action-popup-set");
} else if (msg == "page-action-get-popup") {
browser.pageAction.getPopup({tabId: data.tabId}).then(url => {
browser.test.sendMessage("page-action-got-popup", url);
});
const url = await browser.pageAction.getPopup({tabId: data.tabId});
browser.test.sendMessage("page-action-got-popup", url);
} else if (msg === "finish") {
await browser.tabs.remove([tab1.id, tab2.id]);
browser.test.notifyPass("page-action-popup");
@ -110,6 +122,7 @@ add_task(async function test_setPopup_and_getPopup() {
window.onload = () => {
browser.test.sendMessage("page-action-from-popup", location.href);
};
browser.test.onMessage.addListener((msg, details) => {
if (msg == "page-action-close-popup") {
if (details.location == location.href) {
@ -168,13 +181,17 @@ add_task(async function test_setPopup_and_getPopup() {
await extension.awaitMessage("page-action-shown");
ok(PageActions.isShown(uuid), "page action is shown");
info(`Click on the pageAction on tab ${tabId} and wait the popup to be loaded`);
PageActions.synthesizeClick(uuid);
let location = await extension.awaitMessage("page-action-from-popup");
ok(location.includes(expectedPopup), "The popup with the correct URL should be shown.");
const onceTabClosed = tabClosedPromise();
extension.sendMessage("page-action-close-popup", {location});
location = await tabClosedPromise();
ok(location.includes(expectedPopup), "The popup with the correct URL should be closed.");
location = await onceTabClosed;
ok(location.includes(expectedPopup), "The popup with the correct URL should be closed");
}
await extension.startup();

View File

@ -32,6 +32,7 @@ import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.graphics.drawable.shapes.Shape;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.TypedValue;
@ -84,6 +85,20 @@ public class BaseMessageDialog extends Dialog {
private boolean isHtml = false;
private boolean isClosing = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
int flags = window.getDecorView().getSystemUiVisibility();
flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
window.getDecorView().setSystemUiVisibility(flags);
}
}
protected BaseMessageDialog(Activity activity, boolean fullscreen, BaseMessageOptions options,
WebInterstitialOptions webOptions, HTMLOptions htmlOptions) {
super(activity, getTheme(activity));

View File

@ -32,6 +32,7 @@ import com.leanplum.LeanplumActivityHelper;
import com.leanplum.callbacks.ActionCallback;
import com.leanplum.callbacks.PostponableAction;
import com.leanplum.callbacks.VariablesChangedCallback;
import com.leanplum.utils.SizeUtil;
/**
* Registers a Leanplum action that displays a HTML message.
@ -50,10 +51,12 @@ public class HTMLTemplate extends BaseMessageDialog {
@Override
public boolean dispatchTouchEvent(@NonNull MotionEvent ev) {
if (!htmlOptions.isFullScreen()) {
int height = SizeUtil.dpToPx(Leanplum.getContext(), htmlOptions.getHtmlHeight());
int statusBarHeight = SizeUtil.getStatusBarHeight(Leanplum.getContext());
if (htmlOptions.getHtmlAlign().equals(MessageTemplates.Args.HTML_ALIGN_TOP) && ev.getY()
> htmlOptions.getHtmlHeight() ||
> height + statusBarHeight ||
htmlOptions.getHtmlAlign().equals(MessageTemplates.Args.HTML_ALIGN_BOTTOM) && ev.getY()
< dialogView.getHeight() - htmlOptions.getHtmlHeight()) {
< dialogView.getHeight() + statusBarHeight - height) {
activity.dispatchTouchEvent(ev);
}
}

View File

@ -114,4 +114,17 @@ public class SizeUtil {
}
return result;
}
public static int getStatusBarHeight(Context context) {
init(context);
int result = 0;
try {
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
} catch (Throwable ignored) {
}
return result;
}
}

View File

@ -13,6 +13,7 @@ from mozbuild.backend.base import PartialBackend, HybridBackend
from mozbuild.backend.recursivemake import RecursiveMakeBackend
from mozbuild.shellutil import quote as shell_quote
from mozbuild.util import OrderedDefaultDict
from collections import defaultdict
from mozpack.files import (
FileFinder,
@ -21,17 +22,22 @@ from mozpack.files import (
from .common import CommonBackend
from ..frontend.data import (
ChromeManifestEntry,
ComputedFlags,
ContextDerived,
Defines,
FinalTargetFiles,
FinalTargetPreprocessedFiles,
GeneratedFile,
GeneratedSources,
HostDefines,
JARManifest,
ObjdirFiles,
PerSourceFlag,
Sources,
)
from ..util import (
FileAvoidWrite,
expand_variables,
)
from ..frontend.context import (
AbsolutePath,
@ -55,6 +61,9 @@ class BackendTupfile(object):
self.defines = []
self.host_defines = []
self.delayed_generated_files = []
self.per_source_flags = defaultdict(list)
self.local_flags = defaultdict(list)
self.sources = defaultdict(list)
self.fh = FileAvoidWrite(self.name, capture_diff=True)
self.fh.write('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.\n')
@ -68,7 +77,8 @@ class BackendTupfile(object):
self.write('include_rules\n')
self.rules_included = True
def rule(self, cmd, inputs=None, outputs=None, display=None, extra_outputs=None, check_unchanged=False):
def rule(self, cmd, inputs=None, outputs=None, display=None,
extra_inputs=None, extra_outputs=None, check_unchanged=False):
inputs = inputs or []
outputs = outputs or []
display = display or ""
@ -85,8 +95,9 @@ class BackendTupfile(object):
else:
caret_text = flags
self.write(': %(inputs)s |> %(display)s%(cmd)s |> %(outputs)s%(extra_outputs)s\n' % {
self.write(': %(inputs)s%(extra_inputs)s |> %(display)s%(cmd)s |> %(outputs)s%(extra_outputs)s\n' % {
'inputs': ' '.join(inputs),
'extra_inputs': ' | ' + ' '.join(extra_inputs) if extra_inputs else '',
'display': '^%s^ ' % caret_text if caret_text else '',
'cmd': ' '.join(cmd),
'outputs': ' '.join(outputs),
@ -106,6 +117,29 @@ class BackendTupfile(object):
outputs=outputs,
)
def gen_sources_rules(self, extra_inputs):
compilers = [
('.S', 'AS', 'ASFLAGS'),
('.cpp', 'CXX', 'CXXFLAGS'),
('.c', 'CC', 'CFLAGS'),
]
for extension, compiler, flags in compilers:
srcs = sorted(self.sources[extension])
for src in srcs:
# AS can be set to $(CC), so we need to call expand_variables on
# the compiler to get the real value.
cmd = [expand_variables(self.environment.substs[compiler], self.environment.substs)]
cmd.extend(self.local_flags[flags])
cmd.extend(self.per_source_flags[src])
cmd.extend(['-c', '%f', '-o', '%o'])
self.rule(
cmd=cmd,
inputs=[src],
extra_inputs=extra_inputs,
outputs=['%B.o'],
display='%s %%f' % compiler,
)
def export_shell(self):
if not self.shell_exported:
# These are used by mach/mixin/process.py to determine the current
@ -141,8 +175,9 @@ class TupOnly(CommonBackend, PartialBackend):
'*.rs',
)
# This is a 'group' dependency - All rules that list this as an output
# These are 'group' dependencies - All rules that list these as an output
# will be built before any rules that list this as an input.
self._installed_idls = '$(MOZ_OBJ_ROOT)/<installed-idls>'
self._installed_files = '$(MOZ_OBJ_ROOT)/<installed-files>'
def _get_backend_file(self, relativedir):
@ -217,6 +252,13 @@ class TupOnly(CommonBackend, PartialBackend):
self._process_final_target_pp_files(obj, backend_file)
elif isinstance(obj, JARManifest):
self._consume_jar_manifest(obj)
elif isinstance(obj, PerSourceFlag):
backend_file.per_source_flags[obj.file_name].extend(obj.flags)
elif isinstance(obj, ComputedFlags):
self._process_computed_flags(obj, backend_file)
elif isinstance(obj, (Sources, GeneratedSources)):
if obj.relobjdir.startswith('xpcom'):
backend_file.sources[obj.canonical_suffix].extend(obj.files)
return True
@ -233,6 +275,7 @@ class TupOnly(CommonBackend, PartialBackend):
for objdir, backend_file in sorted(self._backend_files.items()):
for obj in backend_file.delayed_generated_files:
self._process_generated_file(backend_file, obj)
backend_file.gen_sources_rules([self._installed_files])
with self._write_file(fh=backend_file):
pass
@ -274,6 +317,11 @@ class TupOnly(CommonBackend, PartialBackend):
'layout/style/test', # HostSimplePrograms
'toolkit/library', # libxul.so
)
install_exts = (
'.h',
'.inc',
'new', # 'new' is an output from make-stl-wrappers.py
)
if obj.script and obj.method and obj.relobjdir not in skip_directories:
backend_file.export_shell()
cmd = self._py_action('file_generate')
@ -291,11 +339,14 @@ class TupOnly(CommonBackend, PartialBackend):
outputs.extend(obj.outputs)
outputs.append('%s.pp' % obj.outputs[0])
extra_outputs = [self._installed_files] if any(f.endswith(install_exts) for f in obj.outputs) else None
backend_file.rule(
display='python {script}:{method} -> [%o]'.format(script=obj.script, method=obj.method),
cmd=cmd,
inputs=full_inputs,
outputs=outputs,
extra_outputs=extra_outputs,
)
def _process_defines(self, backend_file, obj, host=False):
@ -376,13 +427,23 @@ class TupOnly(CommonBackend, PartialBackend):
self._preprocess(backend_file, f.full_path,
destdir=mozpath.join(self.environment.topobjdir, obj.install_target, path))
def _process_computed_flags(self, obj, backend_file):
for var, flags in obj.get_flags():
backend_file.local_flags[var] = flags
def _process_unified_sources(self, obj):
backend_file = self._get_backend_file_for(obj)
if obj.relobjdir.startswith('xpcom'):
files = [f[0] for f in obj.unified_source_mapping]
backend_file.sources[obj.canonical_suffix].extend(files)
def _handle_idl_manager(self, manager):
if self.environment.is_artifact_build:
return
dist_idl_backend_file = self._get_backend_file('dist/idl')
for idl in manager.idls.values():
dist_idl_backend_file.symlink_rule(idl['source'], output_group=self._installed_files)
dist_idl_backend_file.symlink_rule(idl['source'], output_group=self._installed_idls)
backend_file = self._get_backend_file('xpcom/xpidl')
backend_file.export_shell()
@ -409,11 +470,12 @@ class TupOnly(CommonBackend, PartialBackend):
inputs=[
'$(MOZ_OBJ_ROOT)/xpcom/idl-parser/xpidl/xpidllex.py',
'$(MOZ_OBJ_ROOT)/xpcom/idl-parser/xpidl/xpidlyacc.py',
self._installed_files,
self._installed_idls,
],
display='XPIDL %s' % module,
cmd=cmd,
outputs=outputs,
extra_outputs=[self._installed_files],
)
for manifest, entries in manager.interface_manifests.items():
@ -491,6 +553,7 @@ class TupOnly(CommonBackend, PartialBackend):
display='IPDL code generation',
cmd=cmd,
outputs=outputs,
extra_outputs=[self._installed_files],
check_unchanged=True,
)
@ -522,6 +585,7 @@ class TupOnly(CommonBackend, PartialBackend):
cmd=cmd,
inputs=webidls.all_non_static_basenames(),
outputs=outputs,
extra_outputs=[self._installed_files],
check_unchanged=True,
)

View File

@ -4,6 +4,7 @@
from __future__ import absolute_import, unicode_literals
import errno
import getpass
import io
import json
@ -1337,21 +1338,66 @@ class BuildDriver(MozbuildObject):
if self._check_clobber(mozconfig, os.environ):
return 1
mozconfig_make_lines = []
for arg in mozconfig['make_extra'] or []:
mozconfig_make_lines.append(arg)
if mozconfig['make_flags']:
mozconfig_make_lines.append(b'MOZ_MAKE_FLAGS=%s' %
b' '.join(mozconfig['make_flags']))
objdir = mozpath.normsep(self.topobjdir)
mozconfig_make_lines.append(b'MOZ_OBJDIR=%s' % objdir)
mozconfig_make_lines.append(b'OBJDIR=%s' % objdir)
if mozconfig['path']:
mozconfig_make_lines.append(b'FOUND_MOZCONFIG=%s' %
mozpath.normsep(mozconfig['path']))
mozconfig_make_lines.append(b'export FOUND_MOZCONFIG')
# The .mozconfig.mk file only contains exported variables and lines with
# UPLOAD_EXTRA_FILES.
mozconfig_filtered_lines = [
line for line in mozconfig_make_lines
# Bug 1418122 investigate why UPLOAD_EXTRA_FILES is special and
# remove it.
if line.startswith(b'export ') or b'UPLOAD_EXTRA_FILES' in line
]
mozconfig_client_mk = os.path.join(self.topobjdir,
'.mozconfig-client-mk')
with FileAvoidWrite(mozconfig_client_mk) as fh:
for arg in mozconfig['make_extra'] or []:
fh.write(arg)
fh.write(b'\n')
if mozconfig['make_flags']:
fh.write(b'MOZ_MAKE_FLAGS=%s\n' % b' '.join(mozconfig['make_flags']))
objdir = mozpath.normsep(self.topobjdir)
fh.write(b'MOZ_OBJDIR=%s\n' % objdir)
fh.write(b'OBJDIR=%s\n' % objdir)
if mozconfig['path']:
fh.write(b'FOUND_MOZCONFIG=%s\n' %
mozpath.normsep(mozconfig['path']))
fh.write(b'export FOUND_MOZCONFIG\n')
fh.write(b'\n'.join(mozconfig_make_lines))
mozconfig_mk = os.path.join(self.topobjdir, '.mozconfig.mk')
with FileAvoidWrite(mozconfig_mk) as fh:
fh.write(b'\n'.join(mozconfig_filtered_lines))
mozconfig_json = os.path.join(self.topobjdir, '.mozconfig.json')
with FileAvoidWrite(mozconfig_json) as fh:
json.dump({
'topsrcdir': self.topsrcdir,
'topobjdir': self.topobjdir,
'mozconfig': mozconfig,
}, fh, sort_keys=True, indent=2)
# Copy the original mozconfig to the objdir.
mozconfig_objdir = os.path.join(self.topobjdir, '.mozconfig')
if mozconfig['path']:
with open(mozconfig['path'], 'rb') as ifh:
with FileAvoidWrite(mozconfig_objdir) as ofh:
ofh.write(ifh.read())
else:
try:
os.unlink(mozconfig_objdir)
except OSError as e:
if e.errno != errno.ENOENT:
raise
if mozconfig_make_lines:
self.log(logging.WARNING, 'mozconfig_content', {
'path': mozconfig['path'],
'content': '\n '.join(mozconfig_make_lines),
}, 'Adding make options from {path}\n {content}')
append_env['OBJDIR'] = mozpath.normsep(self.topobjdir)

View File

@ -161,7 +161,7 @@ let SyncedTabsInternal = {
// Ask Sync to just do the tabs engine if it can.
try {
log.info("Doing a tab sync.");
await Weave.Service.sync(["tabs"]);
await Weave.Service.sync({why: "tabs", engines: ["tabs"]});
return true;
} catch (ex) {
log.error("Sync failed", ex);

View File

@ -433,7 +433,7 @@ Sync11Service.prototype = {
// Sync in the background (it's fine not to wait on the returned promise
// because sync() has a lock).
// [] = clients collection only
this.sync([]).catch(e => {
this.sync({why: "collection_changed", engines: []}).catch(e => {
this._log.error(e);
});
}
@ -1082,7 +1082,7 @@ Sync11Service.prototype = {
return reason;
},
async sync(engineNamesToSync) {
async sync({engines, why} = {}) {
let dateStr = Utils.formatTimestamp(new Date());
this._log.debug("User-Agent: " + Utils.userAgent);
this._log.info(`Starting sync at ${dateStr} in browser session ${browserSessionID}`);
@ -1097,16 +1097,16 @@ Sync11Service.prototype = {
} else {
this._log.trace("In sync: no need to login.");
}
await this._lockedSync(engineNamesToSync);
await this._lockedSync(engines, why);
})();
},
/**
* Sync up engines with the server.
*/
async _lockedSync(engineNamesToSync) {
async _lockedSync(engineNamesToSync, why) {
return this._lock("service.js: sync",
this._notify("sync", "", async function onNotify() {
this._notify("sync", JSON.stringify({why}), async function onNotify() {
let histogram = Services.telemetry.getHistogramById("WEAVE_START_COUNT");
histogram.add(1);

View File

@ -218,7 +218,7 @@ class EngineRecord {
}
class TelemetryRecord {
constructor(allowedEngines) {
constructor(allowedEngines, why) {
this.allowedEngines = allowedEngines;
// Our failure reason. This property only exists in the generated ping if an
// error actually occurred.
@ -227,6 +227,7 @@ class TelemetryRecord {
this.when = Date.now();
this.startTime = tryGetMonotonicTimestamp();
this.took = 0; // will be set later.
this.why = why;
// All engines that have finished (ie, does not include the "current" one)
// We omit this from the ping if it's empty.
@ -243,6 +244,9 @@ class TelemetryRecord {
status: this.status,
devices: this.devices,
};
if (this.why) {
result.why = this.why;
}
let engines = [];
for (let engine of this.engines) {
engines.push(engine.toJSON());
@ -497,13 +501,14 @@ class SyncTelemetryImpl {
}
onSyncStarted() {
onSyncStarted(data) {
const why = data && JSON.parse(data).why;
if (this.current) {
log.warn("Observed weave:service:sync:start, but we're already recording a sync!");
// Just discard the old record, consistent with our handling of engines, above.
this.current = null;
}
this.current = new TelemetryRecord(this.allowedEngines);
this.current = new TelemetryRecord(this.allowedEngines, why);
}
_checkCurrent(topic) {
@ -605,7 +610,7 @@ class SyncTelemetryImpl {
/* sync itself state changes */
case "weave:service:sync:start":
this.onSyncStarted();
this.onSyncStarted(data);
break;
case "weave:service:sync:finish":

View File

@ -53,7 +53,7 @@
"service": { "type": "string" }
}
},
"why": { "enum": ["startup", "schedule", "score", "user", "tabs"] },
"why": { "type": "string" },
"took": { "type": "integer", "minimum": -1 },
"failureReason": { "$ref": "#/definitions/error" },
"engines": {

View File

@ -394,7 +394,7 @@ add_task(async function test_bookmark_change_during_sync() {
// because the bookmarks engine will automatically schedule a follow-up
// sync for us.
_("Perform first sync and immediate follow-up sync");
Service.sync(["bookmarks"]);
Service.sync({engines: ["bookmarks"]});
let pings = await pingsPromise;
equal(pings.length, 2, "Should submit two pings");

View File

@ -90,7 +90,7 @@ add_task(async function test_noEngines() {
try {
_("Sync with no engines specified.");
await Service.sync([]);
await Service.sync({engines: []});
deepEqual(syncedEngines, [], "no engines were synced");
} finally {
@ -108,7 +108,7 @@ add_task(async function test_oneEngine() {
try {
_("Sync with 1 engine specified.");
await Service.sync(["steam"]);
await Service.sync({engines: ["steam"]});
deepEqual(syncedEngines, ["steam"]);
} finally {
@ -125,7 +125,7 @@ add_task(async function test_bothEnginesSpecified() {
try {
_("Sync with both engines specified.");
await Service.sync(["steam", "stirling"]);
await Service.sync({engines: ["steam", "stirling"]});
deepEqual(syncedEngines, ["steam", "stirling"]);
} finally {
@ -142,7 +142,7 @@ add_task(async function test_bothEnginesSpecified() {
try {
_("Sync with both engines specified.");
await Service.sync(["stirling", "steam"]);
await Service.sync({engines: ["stirling", "steam"]});
deepEqual(syncedEngines, ["stirling", "steam"]);
} finally {

View File

@ -525,6 +525,29 @@ add_task(async function test_nserror() {
}
});
add_task(async function test_sync_why() {
enableValidationPrefs();
await Service.engineManager.register(SteamEngine);
let engine = Service.engineManager.get("steam");
engine.enabled = true;
let server = await serverForFoo(engine);
await SyncTestingInfrastructure(server);
let e = new Error("generic failure message");
engine._errToThrow = e;
try {
_(`test_generic_engine_fail: Steam tracker contents: ${
JSON.stringify(engine._tracker.changedIDs)}`);
let ping = await wait_for_ping(() => Service.sync({why: "user"}), true, false);
_(JSON.stringify(ping))
equal(ping.why, "user");
} finally {
await cleanAndGo(engine, server);
Service.engineManager.unregister(engine);
}
});
add_task(async function test_discarding() {
enableValidationPrefs();

1
servo/.gitignore vendored
View File

@ -9,6 +9,7 @@
/ports/android/obj
/python/_virtualenv
/python/tidy/servo_tidy.egg-info
/tests/wpt/sync
*~
*.pkl
*.pyc

66
servo/Cargo.lock generated
View File

@ -297,8 +297,8 @@ dependencies = [
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"offscreen_gl_context 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1",
"webrender 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender 0.53.2 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -315,7 +315,7 @@ dependencies = [
"offscreen_gl_context 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -472,8 +472,8 @@ dependencies = [
"servo_url 0.0.1",
"style_traits 0.0.1",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender 0.53.2 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -509,7 +509,7 @@ dependencies = [
"servo_remutex 0.0.1",
"servo_url 0.0.1",
"style_traits 0.0.1",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
"webvr_traits 0.0.1",
]
@ -802,7 +802,7 @@ dependencies = [
"servo_geometry 0.0.1",
"servo_url 0.0.1",
"style_traits 0.0.1",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
"x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1090,7 +1090,7 @@ dependencies = [
"truetype 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
"xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"xml5ever 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1171,7 +1171,7 @@ dependencies = [
"servo_url 0.0.1",
"style_traits 0.0.1",
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1500,7 +1500,7 @@ dependencies = [
"style_traits 0.0.1",
"unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -1550,7 +1550,7 @@ dependencies = [
"servo_url 0.0.1",
"style 0.0.1",
"style_traits 0.0.1",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -1565,7 +1565,7 @@ dependencies = [
"profile_traits 0.0.1",
"script_traits 0.0.1",
"servo_url 0.0.1",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -1649,8 +1649,8 @@ dependencies = [
"style 0.0.1",
"style_traits 0.0.1",
"webdriver_server 0.0.1",
"webrender 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender 0.53.2 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
"webvr 0.0.1",
"webvr_traits 0.0.1",
]
@ -1703,7 +1703,7 @@ dependencies = [
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
"xml5ever 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1921,7 +1921,7 @@ dependencies = [
"malloc_size_of_derive 0.0.1",
"nonzero 0.0.1",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -1970,7 +1970,7 @@ dependencies = [
"profile_traits 0.0.1",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-websocket 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-websocket 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1",
"servo_url 0.0.1",
"threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1979,7 +1979,7 @@ dependencies = [
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -2036,7 +2036,7 @@ dependencies = [
"servo_url 0.0.1",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -2659,7 +2659,7 @@ dependencies = [
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"utf-8 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
"webvr_traits 0.0.1",
"xml5ever 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2692,7 +2692,7 @@ dependencies = [
"servo_atoms 0.0.1",
"servo_url 0.0.1",
"style 0.0.1",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -2736,7 +2736,7 @@ dependencies = [
"style_traits 0.0.1",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
"webvr_traits 0.0.1",
]
@ -2933,10 +2933,10 @@ dependencies = [
[[package]]
name = "servo-websocket"
version = "0.19.1"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3249,7 +3249,7 @@ dependencies = [
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_arc 0.0.1",
"servo_atoms 0.0.1",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -3633,8 +3633,8 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.53.1"
source = "git+https://github.com/servo/webrender#30413c20684b4c8d82baf9e1296f9e10189c3591"
version = "0.53.2"
source = "git+https://github.com/servo/webrender#6dba5ed000b0c08e507390fff09ef4a134222cf0"
dependencies = [
"app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3655,13 +3655,13 @@ dependencies = [
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.53.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.53.2 (git+https://github.com/servo/webrender)",
]
[[package]]
name = "webrender_api"
version = "0.53.1"
source = "git+https://github.com/servo/webrender#30413c20684b4c8d82baf9e1296f9e10189c3591"
version = "0.53.2"
source = "git+https://github.com/servo/webrender#6dba5ed000b0c08e507390fff09ef4a134222cf0"
dependencies = [
"app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -4042,7 +4042,7 @@ dependencies = [
"checksum servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9232032c2e85118c0282c6562c84cab12316e655491ba0a5d1905b2320060d1b"
"checksum servo-glutin 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "91cdbc8014ea1171264622545b9b3d653f20336abb0e924682e98c951171fa58"
"checksum servo-skia 0.30000007.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0abf282739e8b8e987f2b69736a0287a83b0f87189f53cc786a97bd2019e543d"
"checksum servo-websocket 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8a1ff13c5d852c2793805226e688044309f2c1d8f063784805a13e99cb75b611"
"checksum servo-websocket 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efde78dfcf2178d5a11e1e2268e0d8df0627dfe2724546db8585d6678e1af150"
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
"checksum shared_library 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fb04126b6fcfd2710fb5b6d18f4207b6c535f2850a7e1a43bcd526d44f30a79a"
"checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d"
@ -4100,8 +4100,8 @@ dependencies = [
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
"checksum webdriver 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d548aabf87411b1b4ba91fd07eacd8b238135c7131a452b8a9f6386209167e18"
"checksum webrender 0.53.1 (git+https://github.com/servo/webrender)" = "<none>"
"checksum webrender_api 0.53.1 (git+https://github.com/servo/webrender)" = "<none>"
"checksum webrender 0.53.2 (git+https://github.com/servo/webrender)" = "<none>"
"checksum webrender_api 0.53.2 (git+https://github.com/servo/webrender)" = "<none>"
"checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

View File

@ -34,7 +34,7 @@ serde = "1.0"
serde_json = "1.0"
servo_config = {path = "../config"}
servo_url = {path = "../url"}
servo-websocket = "0.19"
servo-websocket = "0.20"
threadpool = "1.0"
time = "0.1.17"
unicase = "1.4.0"

View File

@ -0,0 +1,8 @@
{
"xmlhttprequest.rs": [
"XMLHttpRequest"
],
"range.rs": [
"dom/ranges"
]
}

View File

@ -1418,7 +1418,7 @@ impl Window {
Vector2D::new(0.0, 0.0)
}
// https://drafts.csswg.org/cssom-view/#dom-element-scroll
// https://drafts.csswg.org/cssom-view/#element-scrolling-members
pub fn scroll_node(&self,
node: &Node,
x_: f64,

View File

@ -81,7 +81,7 @@ def write(directory, filename, content):
def write_html(properties):
properties = dict(
(p.name, {
"flag": p.experimental,
"flag": p.servo_pref,
"shorthand": hasattr(p, "sub_properties")
})
for p in properties.longhands + properties.shorthands

Some files were not shown because too many files have changed in this diff Show More