зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound
This commit is contained in:
Коммит
2d528aa145
|
@ -244,13 +244,11 @@ nsAccUtils::GetSelectableContainer(Accessible* aAccessible, uint64_t aState)
|
|||
}
|
||||
|
||||
bool
|
||||
nsAccUtils::IsARIASelected(Accessible* aAccessible)
|
||||
nsAccUtils::IsDOMAttrTrue(const Accessible* aAccessible, nsAtom* aAttr)
|
||||
{
|
||||
if (!aAccessible->GetContent()->IsElement())
|
||||
return false;
|
||||
return aAccessible->GetContent()->AsElement()->
|
||||
AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_selected,
|
||||
nsGkAtoms::_true, eCaseMatters);
|
||||
dom::Element* el = aAccessible->Elm();
|
||||
return el && el->AttrValueIs(kNameSpaceID_None, aAttr, nsGkAtoms::_true,
|
||||
eCaseMatters);
|
||||
}
|
||||
|
||||
Accessible*
|
||||
|
|
|
@ -137,11 +137,27 @@ public:
|
|||
|
||||
static Accessible* TableFor(Accessible* aRow);
|
||||
|
||||
/**
|
||||
* Return true if the DOM node of a given accessible has a given attribute
|
||||
* with a value of "true".
|
||||
*/
|
||||
static bool IsDOMAttrTrue(const Accessible* aAccessible, nsAtom* aAttr);
|
||||
|
||||
/**
|
||||
* Return true if the DOM node of given accessible has aria-selected="true"
|
||||
* attribute.
|
||||
*/
|
||||
static bool IsARIASelected(Accessible* aAccessible);
|
||||
static inline bool IsARIASelected(const Accessible* aAccessible) {
|
||||
return IsDOMAttrTrue(aAccessible, nsGkAtoms::aria_selected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the DOM node of given accessible has
|
||||
* aria-multiselectable="true" attribute.
|
||||
*/
|
||||
static inline bool IsARIAMultiSelectable(const Accessible* aAccessible) {
|
||||
return IsDOMAttrTrue(aAccessible, nsGkAtoms::aria_multiselectable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given coordinates to coordinates relative screen.
|
||||
|
|
|
@ -8,4 +8,5 @@ support-files =
|
|||
[test_menu.xul]
|
||||
[test_menulist.xul]
|
||||
[test_select.html]
|
||||
[test_tabs.xul]
|
||||
[test_tree.xul]
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="XUL tabs selectable tests">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js" />
|
||||
<script type="application/javascript"
|
||||
src="../role.js" />
|
||||
<script type="application/javascript"
|
||||
src="../states.js" />
|
||||
<script type="application/javascript"
|
||||
src="../selectable.js" />
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var id = "tabs_single";
|
||||
ok(isAccessible(id, [nsIAccessibleSelectable]),
|
||||
"No selectable accessible for tabs_single");
|
||||
var select = getAccessible(id, [nsIAccessibleSelectable]);
|
||||
|
||||
testSelectableSelection(select, ["tab_single1"]);
|
||||
|
||||
select.unselectAll();
|
||||
select.addItemToSelection(1); // tab_single2
|
||||
testSelectableSelection(select, ["tab_single2"], "select tab_single2: ");
|
||||
|
||||
id = "tabs_multi";
|
||||
ok(isAccessible(id, [nsIAccessibleSelectable]),
|
||||
"No selectable accessible for tabs_multi");
|
||||
select = getAccessible(id, [nsIAccessibleSelectable]);
|
||||
|
||||
// Make sure both XUL selection and ARIA selection are included.
|
||||
testSelectableSelection(select, ["tab_multi_xul1", "tab_multi_aria"]);
|
||||
|
||||
select.unselectAll();
|
||||
select.addItemToSelection(2); // tab_multi_xul2
|
||||
// We can only affect XUL selection, so ARIA selection won't change.
|
||||
testSelectableSelection(select, ["tab_multi_aria", "tab_multi_xul2"],
|
||||
"select tab_multi_xul2: ");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<hbox flex="1" style="overflow: auto;">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1480058"
|
||||
title="XUL tabs don't support ARIA selection">
|
||||
Mozilla Bug 1480058
|
||||
</a><br/>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
<vbox flex="1">
|
||||
<tabbox>
|
||||
<tabs id="tabs_single">
|
||||
<tab id="tab_single1" label="tab1" selected="true"/>
|
||||
<tab id="tab_single2" label="tab2"/>
|
||||
</tabs>
|
||||
</tabbox>
|
||||
|
||||
<tabbox>
|
||||
<tabs id="tabs_multi" aria-multiselectable="true">
|
||||
<tab id="tab_multi_xul1" label="tab1" selected="true"/>
|
||||
<tab id="tab_multi_aria" label="tab2" aria-selected="true"/>
|
||||
<tab id="tab_multi_xul2" label="tab3"/>
|
||||
</tabs>
|
||||
</tabbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
</window>
|
|
@ -24,6 +24,14 @@
|
|||
testStates("pressed_button", STATE_PRESSED, 0, STATE_CHECKABLE);
|
||||
testStates("pressed_menu_button", STATE_PRESSED | STATE_HASPOPUP, 0, STATE_CHECKABLE);
|
||||
|
||||
testStates("tabs", STATE_MULTISELECTABLE);
|
||||
// Make sure XUL selection works, since aria-selected defaults to false.
|
||||
testStates("tab1", STATE_SELECTED);
|
||||
// aria-selected="true".
|
||||
testStates("tab2", STATE_SELECTED);
|
||||
// Neither.
|
||||
testStates("tab3", 0, 0, STATE_SELECTED);
|
||||
|
||||
SimpleTest.finish()
|
||||
}
|
||||
|
||||
|
@ -53,6 +61,14 @@
|
|||
<menuitem label="I am a menu item" />
|
||||
</menupopup>
|
||||
</button>
|
||||
|
||||
<tabbox>
|
||||
<tabs id="tabs" aria-multiselectable="true">
|
||||
<tab id="tab1" label="tab1" selected="true"/>
|
||||
<tab id="tab2" label="tab2" aria-selected="true"/>
|
||||
<tab id="tab3" label="tab3"/>
|
||||
</tabs>
|
||||
</tabbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "XULTabAccessible.h"
|
||||
|
||||
#include "ARIAMap.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "Relation.h"
|
||||
#include "Role.h"
|
||||
|
@ -123,6 +124,17 @@ XULTabAccessible::RelationByType(RelationType aType) const
|
|||
return rel;
|
||||
}
|
||||
|
||||
void
|
||||
XULTabAccessible::ApplyARIAState(uint64_t* aState) const
|
||||
{
|
||||
HyperTextAccessibleWrap::ApplyARIAState(aState);
|
||||
// XUL tab has an implicit ARIA role of tab, so support aria-selected.
|
||||
// Don't use aria::MapToState because that will set the SELECTABLE state
|
||||
// even if the tab is disabled.
|
||||
if (nsAccUtils::IsARIASelected(this)) {
|
||||
*aState |= states::SELECTED;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// XULTabsAccessible
|
||||
|
@ -159,6 +171,66 @@ XULTabsAccessible::NativeName(nsString& aName) const
|
|||
return eNameOK;
|
||||
}
|
||||
|
||||
void
|
||||
XULTabsAccessible::ApplyARIAState(uint64_t* aState) const
|
||||
{
|
||||
XULSelectControlAccessible::ApplyARIAState(aState);
|
||||
// XUL tabs has an implicit ARIA role of tablist, so support
|
||||
// aria-multiselectable.
|
||||
MOZ_ASSERT(Elm());
|
||||
aria::MapToState(aria::eARIAMultiSelectable, Elm(), aState);
|
||||
}
|
||||
|
||||
// XUL tabs is a single selection control and doesn't allow ARIA selection.
|
||||
// However, if aria-multiselectable is used, it becomes a multiselectable
|
||||
// control, where both native and ARIA markup are used to set selection.
|
||||
// Therefore, if aria-multiselectable is set, use the base implementation of
|
||||
// the selection retrieval methods in order to support ARIA selection.
|
||||
// We don't bother overriding the selection setting methods because
|
||||
// current front-end code using XUL tabs doesn't support setting of
|
||||
// aria-selected by the a11y engine and we still want to be able to set the
|
||||
// primary selected item according to XUL.
|
||||
|
||||
void
|
||||
XULTabsAccessible::SelectedItems(nsTArray<Accessible*>* aItems)
|
||||
{
|
||||
if (nsAccUtils::IsARIAMultiSelectable(this)) {
|
||||
AccessibleWrap::SelectedItems(aItems);
|
||||
} else {
|
||||
XULSelectControlAccessible::SelectedItems(aItems);
|
||||
}
|
||||
}
|
||||
|
||||
Accessible*
|
||||
XULTabsAccessible::GetSelectedItem(uint32_t aIndex)
|
||||
{
|
||||
if (nsAccUtils::IsARIAMultiSelectable(this)) {
|
||||
return AccessibleWrap::GetSelectedItem(aIndex);
|
||||
}
|
||||
|
||||
return XULSelectControlAccessible::GetSelectedItem(aIndex);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
XULTabsAccessible::SelectedItemCount()
|
||||
{
|
||||
if (nsAccUtils::IsARIAMultiSelectable(this)) {
|
||||
return AccessibleWrap::SelectedItemCount();
|
||||
}
|
||||
|
||||
return XULSelectControlAccessible::SelectedItemCount();
|
||||
}
|
||||
|
||||
bool
|
||||
XULTabsAccessible::IsItemSelected(uint32_t aIndex)
|
||||
{
|
||||
if (nsAccUtils::IsARIAMultiSelectable(this)) {
|
||||
return AccessibleWrap::IsItemSelected(aIndex);
|
||||
}
|
||||
|
||||
return XULSelectControlAccessible::IsItemSelected(aIndex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// XULTabpanelsAccessible
|
||||
|
|
|
@ -29,6 +29,7 @@ public:
|
|||
virtual uint64_t NativeState() const override;
|
||||
virtual uint64_t NativeInteractiveState() const override;
|
||||
virtual Relation RelationByType(RelationType aType) const override;
|
||||
virtual void ApplyARIAState(uint64_t* aState) const override;
|
||||
|
||||
// ActionAccessible
|
||||
virtual uint8_t ActionCount() const override;
|
||||
|
@ -48,10 +49,17 @@ public:
|
|||
// Accessible
|
||||
virtual void Value(nsString& aValue) const override;
|
||||
virtual a11y::role NativeRole() const override;
|
||||
virtual void ApplyARIAState(uint64_t* aState) const override;
|
||||
|
||||
// ActionAccessible
|
||||
virtual uint8_t ActionCount() const override;
|
||||
|
||||
// SelectAccessible
|
||||
virtual void SelectedItems(nsTArray<Accessible*>* aItems) override;
|
||||
virtual uint32_t SelectedItemCount() override;
|
||||
virtual Accessible* GetSelectedItem(uint32_t aIndex) override;
|
||||
virtual bool IsItemSelected(uint32_t aIndex) override;
|
||||
|
||||
protected:
|
||||
// Accessible
|
||||
virtual ENameValueFlag NativeName(nsString& aName) const override;
|
||||
|
|
|
@ -111,7 +111,6 @@ skip-if = (verify && (os == 'linux' || os == 'mac'))
|
|||
[browser_ext_menus_events.js]
|
||||
[browser_ext_menus_refresh.js]
|
||||
[browser_ext_omnibox.js]
|
||||
skip-if = (debug && (os == 'linux' || os == 'mac')) || (verify && (os == 'linux' || os == 'mac')) # Bug 1416103 (was bug 1417052)
|
||||
[browser_ext_openPanel.js]
|
||||
skip-if = (verify && !debug && (os == 'linux' || os == 'mac'))
|
||||
[browser_ext_optionsPage_browser_style.js]
|
||||
|
|
|
@ -67,27 +67,18 @@ class TabsListBase {
|
|||
|
||||
for (let tab of this.gBrowser.tabs) {
|
||||
if (this.filterFn(tab)) {
|
||||
let row = this._createRow(tab);
|
||||
row.tab = tab;
|
||||
row.addEventListener("command", this);
|
||||
this.tabToElement.set(tab, row);
|
||||
if (this.className) {
|
||||
row.classList.add(this.className);
|
||||
}
|
||||
|
||||
fragment.appendChild(row);
|
||||
fragment.appendChild(this._createRow(tab));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.insertBefore) {
|
||||
this.insertBefore.parentNode.insertBefore(fragment, this.insertBefore);
|
||||
} else {
|
||||
this.containerNode.appendChild(fragment);
|
||||
}
|
||||
|
||||
this._addElement(fragment);
|
||||
this._setupListeners();
|
||||
}
|
||||
|
||||
_addElement(elementOrFragment) {
|
||||
this.containerNode.insertBefore(elementOrFragment, this.insertBefore);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the menuitems from the DOM, cleanup internal state and listeners.
|
||||
*/
|
||||
|
@ -115,11 +106,32 @@ class TabsListBase {
|
|||
let item = this.tabToElement.get(tab);
|
||||
if (item) {
|
||||
if (!this.filterFn(tab)) {
|
||||
// If the tab is no longer in this set of tabs, hide the item.
|
||||
// The tab no longer matches our criteria, remove it.
|
||||
this._removeItem(item, tab);
|
||||
} else {
|
||||
this._setRowAttributes(item, tab);
|
||||
}
|
||||
} else if (this.filterFn(tab)) {
|
||||
// The tab now matches our criteria, add a row for it.
|
||||
this._addTab(tab);
|
||||
}
|
||||
}
|
||||
|
||||
_addTab(newTab) {
|
||||
let newRow = this._createRow(newTab);
|
||||
let nextTab = newTab.nextSibling;
|
||||
|
||||
while (nextTab && !this.filterFn(nextTab)) {
|
||||
nextTab = nextTab.nextSibling;
|
||||
}
|
||||
|
||||
if (nextTab) {
|
||||
// If we found a tab after this one in the list, insert the new row before it.
|
||||
let nextRow = this.tabToElement.get(nextTab);
|
||||
nextRow.parentNode.insertBefore(newRow, nextRow);
|
||||
} else {
|
||||
// If there's no next tab then insert it as usual.
|
||||
this._addElement(newRow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,6 +218,12 @@ class TabsPanel extends TabsListBase {
|
|||
let {doc} = this;
|
||||
let row = doc.createElementNS(NSXUL, "toolbaritem");
|
||||
row.setAttribute("class", "all-tabs-item");
|
||||
if (this.className) {
|
||||
row.classList.add(this.className);
|
||||
}
|
||||
row.tab = tab;
|
||||
row.addEventListener("command", this);
|
||||
this.tabToElement.set(tab, row);
|
||||
|
||||
let button = doc.createElementNS(NSXUL, "toolbarbutton");
|
||||
button.setAttribute("class", "all-tabs-button subviewbutton subviewbutton-iconic");
|
||||
|
|
|
@ -804,6 +804,10 @@
|
|||
box-shadow: inset -4px 0 var(--blue-40);
|
||||
}
|
||||
|
||||
.all-tabs-button {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
}
|
||||
|
||||
.all-tabs-secondary-button > label {
|
||||
display: none;
|
||||
margin: 0 5.5px;
|
||||
|
|
|
@ -2,20 +2,26 @@
|
|||
* 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/. */
|
||||
|
||||
@import "resource://devtools/client/themes/variables.css";
|
||||
@import "chrome://global/skin/in-content/common.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/App.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/ConnectPage.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/RuntimeInfo.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/RuntimePage.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/Sidebar.css";
|
||||
@import "resource://devtools/client/aboutdebugging-new/src/components/SidebarItem.css";
|
||||
|
||||
:root {
|
||||
/* Import css variables from common.css */
|
||||
--text-color: var(--in-content-page-color);
|
||||
}
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/content/aboutdebugging-new/aboutdebugging.css"/>
|
||||
<script src="chrome://devtools/content/aboutdebugging-new/aboutdebugging.js"></script>
|
||||
</head>
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* The current layout of the about:debugging is
|
||||
* The current layout of about:debugging is
|
||||
*
|
||||
* +-------------+-------------------------------+
|
||||
* | Sidebar | RuntimePage |
|
||||
* | Sidebar | Page (Runtime or Connect) |
|
||||
* | (240px) | |
|
||||
* | | |
|
||||
* +-------------+-------------------------------+
|
||||
|
@ -14,8 +14,13 @@
|
|||
.app {
|
||||
display: grid;
|
||||
font-size: 15px;
|
||||
grid-column-gap: 40px;
|
||||
grid-template-columns: 240px auto;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.page {
|
||||
padding-block-start: 60px;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
|||
|
||||
const { PAGES } = require("../constants");
|
||||
|
||||
const ConnectPage = createFactory(require("./ConnectPage"));
|
||||
const RuntimePage = createFactory(require("./RuntimePage"));
|
||||
const Sidebar = createFactory(require("./Sidebar"));
|
||||
|
||||
|
@ -29,6 +30,8 @@ class App extends PureComponent {
|
|||
switch (this.props.selectedPage) {
|
||||
case PAGES.THIS_FIREFOX:
|
||||
return RuntimePage();
|
||||
case PAGES.CONNECT:
|
||||
return ConnectPage();
|
||||
default:
|
||||
// Invalid page, blank.
|
||||
return null;
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/* 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/. */
|
||||
|
||||
.connect-page__steps {
|
||||
list-style-type: decimal;
|
||||
margin-inline-start: 40px;
|
||||
line-height: 1.5em;
|
||||
margin-block-end: 20px;
|
||||
}
|
||||
|
||||
.connect-page__step {
|
||||
padding-inline-start: 20px;
|
||||
}
|
||||
|
||||
.connect-page__section__title {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.connect-page__section__icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-inline-end: 5px;
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
|
||||
const USB_ICON_SRC = "chrome://devtools/skin/images/aboutdebugging-connect-icon.svg";
|
||||
const WIFI_ICON_SRC = "chrome://devtools/skin/images/aboutdebugging-connect-icon.svg";
|
||||
|
||||
class RuntimePage extends PureComponent {
|
||||
renderSteps(steps) {
|
||||
return dom.ul(
|
||||
{
|
||||
className: "connect-page__steps"
|
||||
},
|
||||
steps.map(step => dom.li(
|
||||
{
|
||||
className: "connect-page__step"
|
||||
},
|
||||
step)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderWifi() {
|
||||
return dom.section(
|
||||
{},
|
||||
dom.h2(
|
||||
{
|
||||
className: "connect-page__section__title"
|
||||
},
|
||||
dom.img(
|
||||
{
|
||||
className: "connect-page__section__icon",
|
||||
src: WIFI_ICON_SRC
|
||||
}
|
||||
),
|
||||
"Via WiFi (Recommended)"
|
||||
),
|
||||
this.renderSteps([
|
||||
"Ensure that your browser and device are on the same network",
|
||||
"Open Firefox for Android",
|
||||
"Go to Options -> Settings -> Advanced",
|
||||
"Enable Remote Debugging via WiFi in the Developer Tools section",
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
renderUsb() {
|
||||
return dom.section(
|
||||
{},
|
||||
dom.h2(
|
||||
{
|
||||
className: "connect-page__section__title"
|
||||
},
|
||||
dom.img(
|
||||
{
|
||||
className: "connect-page__section__icon",
|
||||
src: USB_ICON_SRC
|
||||
}
|
||||
),
|
||||
"Via USB"
|
||||
),
|
||||
this.renderSteps([
|
||||
"Enable Developer menu on your Android device",
|
||||
"Enable USB Debugging on the Android Developer Menu",
|
||||
"Connect the USB Device to your computer",
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return dom.article(
|
||||
{
|
||||
className: "page connect-page",
|
||||
},
|
||||
dom.h1(
|
||||
{
|
||||
className: "connect-page__title"
|
||||
},
|
||||
"Connect a Device"
|
||||
),
|
||||
this.renderWifi(),
|
||||
this.renderUsb(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RuntimePage;
|
|
@ -1,7 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.runtime-page {
|
||||
padding-block-start: 60px;
|
||||
}
|
|
@ -15,7 +15,7 @@ class RuntimePage extends PureComponent {
|
|||
render() {
|
||||
return dom.article(
|
||||
{
|
||||
className: "runtime-page",
|
||||
className: "page",
|
||||
},
|
||||
RuntimeInfo({
|
||||
icon: "chrome://branding/content/icon64.png",
|
||||
|
|
|
@ -3,20 +3,32 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.sidebar-item {
|
||||
--sidebar-item-color: var(--grey-50);
|
||||
--sidebar-item-selected-color: var(--blue-55);
|
||||
/* Import css variables from common.css */
|
||||
--sidebar-text-color: var(--in-content-category-text);
|
||||
--sidebar-selected-color: var(--in-content-category-text-selected);
|
||||
--sidebar-background-hover: var(--in-content-category-background-hover);
|
||||
}
|
||||
|
||||
.sidebar-item {
|
||||
color: var(--sidebar-item-color);
|
||||
align-items: center;
|
||||
border-radius: 2px;
|
||||
color: var(--sidebar-text-color);
|
||||
display: flex;
|
||||
font-size: 20px;
|
||||
font-size: 16px;
|
||||
height: 48px;
|
||||
margin-inline-start: 24px;
|
||||
padding-inline-end: 10px;
|
||||
padding-inline-start: 10px;
|
||||
transition: background-color 150ms;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.sidebar-item:hover {
|
||||
background-color: var(--sidebar-background-hover);
|
||||
}
|
||||
|
||||
.sidebar-item__icon {
|
||||
fill: var(--sidebar-item-color);
|
||||
fill: currentColor;
|
||||
height: 24px;
|
||||
margin-inline-end: 9px;
|
||||
width: 24px;
|
||||
|
@ -24,9 +36,5 @@
|
|||
}
|
||||
|
||||
.sidebar-item--selected {
|
||||
color: var(--sidebar-item-selected-color);
|
||||
}
|
||||
|
||||
.sidebar-item__icon--selected {
|
||||
fill: var(--sidebar-item-selected-color);
|
||||
color: var(--sidebar-selected-color);
|
||||
}
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
DevToolsModules(
|
||||
'App.css',
|
||||
'App.js',
|
||||
'ConnectPage.css',
|
||||
'ConnectPage.js',
|
||||
'RuntimeInfo.css',
|
||||
'RuntimeInfo.js',
|
||||
'RuntimePage.css',
|
||||
'RuntimePage.js',
|
||||
'Sidebar.css',
|
||||
'Sidebar.js',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html><html><head><meta charset="UTF-8"></head><body>
|
||||
<object>
|
||||
<embed src="doc_inspector_menu.html" type="application/html"
|
||||
<embed src="doc_inspector_menu.html" type="text/html"
|
||||
width="422" height="258"></embed>
|
||||
</object>
|
||||
</body></html>
|
||||
|
|
|
@ -170,7 +170,6 @@ skip-if = verify
|
|||
[browser_num-l10n.js]
|
||||
[browser_options-view-01.js]
|
||||
[browser_outputparser.js]
|
||||
skip-if = e10s # Test intermittently fails with e10s. Bug 1124162.
|
||||
[browser_poller.js]
|
||||
[browser_prefs-01.js]
|
||||
[browser_prefs-02.js]
|
||||
|
|
|
@ -283,7 +283,7 @@ function testParseFilter(doc, parser) {
|
|||
}
|
||||
|
||||
function testParseAngle(doc, parser) {
|
||||
let frag = parser.parseCssProperty("image-orientation", "90deg", {
|
||||
let frag = parser.parseCssProperty("rotate", "90deg", {
|
||||
angleSwatchClass: "test-angleswatch"
|
||||
});
|
||||
|
||||
|
|
|
@ -3240,7 +3240,7 @@ nsDOMWindowUtils::GetPlugins(JSContext* cx, JS::MutableHandle<JS::Value> aPlugin
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetScrollPositionClampingScrollPortSize(float aWidth, float aHeight)
|
||||
nsDOMWindowUtils::SetVisualViewportSize(float aWidth, float aHeight)
|
||||
{
|
||||
if (!(aWidth >= 0.0 && aHeight >= 0.0)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
@ -3251,7 +3251,7 @@ nsDOMWindowUtils::SetScrollPositionClampingScrollPortSize(float aWidth, float aH
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsLayoutUtils::SetScrollPositionClampingScrollPortSize(presShell, CSSSize(aWidth, aHeight));
|
||||
nsLayoutUtils::SetVisualViewportSize(presShell, CSSSize(aWidth, aHeight));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -3137,9 +3137,9 @@ nsGlobalWindowOuter::GetInnerSize(CSSIntSize& aSize)
|
|||
* be the visual viewport, but we fall back to the CSS viewport
|
||||
* if it is not set.
|
||||
*/
|
||||
if (presShell->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
if (presShell->IsVisualViewportSizeSet()) {
|
||||
aSize = CSSIntRect::FromAppUnitsRounded(
|
||||
presShell->GetScrollPositionClampingScrollPortSize());
|
||||
presShell->GetVisualViewportSize());
|
||||
} else {
|
||||
RefPtr<nsViewManager> viewManager = presShell->GetViewManager();
|
||||
if (viewManager) {
|
||||
|
|
|
@ -1810,12 +1810,15 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
|||
IsPluginType(newMime_Type)) {
|
||||
newType = newMime_Type;
|
||||
LOG(("OBJLC [%p]: Plugin type with no URI, skipping channel load", this));
|
||||
} else if (newURI) {
|
||||
} else if (newURI && (mOriginalContentType.IsEmpty() || newMime_Type != eType_Null)) {
|
||||
// We could potentially load this if we opened a channel on mURI, indicate
|
||||
// This by leaving type as loading
|
||||
// this by leaving type as loading.
|
||||
//
|
||||
// If a MIME type was requested in the tag, but we have decided to set load
|
||||
// type to null, ignore (otherwise we'll default to document type loading).
|
||||
newType = eType_Loading;
|
||||
} else {
|
||||
// Unloadable - no URI, and no plugin type. Non-plugin types (images,
|
||||
// Unloadable - no URI, and no plugin/MIME type. Non-plugin types (images,
|
||||
// documents) always load with a channel.
|
||||
newType = eType_Null;
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ function run()
|
|||
var newHeight = oldHeight / 2;
|
||||
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
utils.setScrollPositionClampingScrollPortSize(newWidth, newHeight);
|
||||
is(window.innerWidth, newWidth, "innerWidth not updated to scroll port width");
|
||||
is(window.innerHeight, newHeight, "innerHeight not updated to scroll port height");
|
||||
utils.setVisualViewportSize(newWidth, newHeight);
|
||||
is(window.innerWidth, newWidth, "innerWidth not updated to viewport width");
|
||||
is(window.innerHeight, newHeight, "innerHeight not updated to viewport height");
|
||||
|
||||
var innerWidthGetter = Object.getOwnPropertyDescriptor(window, "innerWidth").get;
|
||||
var innerHeightGetter = Object.getOwnPropertyDescriptor(window, "innerHeight").get;
|
||||
|
|
|
@ -2753,7 +2753,7 @@ EventStateManager::GetScrollAmount(nsPresContext* aPresContext,
|
|||
aScrollableFrame->GetLineScrollAmount();
|
||||
}
|
||||
|
||||
// If there is no scrollable frame and page scrolling, use view port size.
|
||||
// If there is no scrollable frame and page scrolling, use viewport size.
|
||||
if (isPage) {
|
||||
return aPresContext->GetVisibleArea().Size();
|
||||
}
|
||||
|
|
|
@ -1591,12 +1591,12 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
readonly attribute jsval plugins;
|
||||
|
||||
/**
|
||||
* Set the scrollport size for the purposes of clamping scroll positions for
|
||||
* Set the viewport size for the purposes of clamping scroll positions for
|
||||
* the root scroll frame of this document to be (aWidth,aHeight) in CSS pixels.
|
||||
*
|
||||
* The caller of this method must have chrome privileges.
|
||||
*/
|
||||
void setScrollPositionClampingScrollPortSize(in float aWidth, in float aHeight);
|
||||
void setVisualViewportSize(in float aWidth, in float aHeight);
|
||||
|
||||
/**
|
||||
* These are used to control whether dialogs (alert, prompt, confirm) are
|
||||
|
|
|
@ -140,7 +140,9 @@ IsMediaElementAllowedToPlay(const HTMLMediaElement& aElement)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (aElement.OwnerDoc()->MediaDocumentKind() == nsIDocument::MediaDocumentKind::Video) {
|
||||
nsIDocument* topDocument = ApproverDocOf(*aElement.OwnerDoc());
|
||||
if (topDocument &&
|
||||
topDocument->MediaDocumentKind() == nsIDocument::MediaDocumentKind::Video) {
|
||||
AUTOPLAY_LOG("Allow video document %p to autoplay\n", &aElement);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1419,8 +1419,12 @@ class RTCPeerConnection {
|
|||
}
|
||||
this._closed = true;
|
||||
this.changeIceConnectionState("closed");
|
||||
this._localIdp.close();
|
||||
this._remoteIdp.close();
|
||||
if (this._localIdp) {
|
||||
this._localIdp.close();
|
||||
}
|
||||
if (this._remoteIdp) {
|
||||
this._remoteIdp.close();
|
||||
}
|
||||
this._impl.close();
|
||||
this._suppressEvents = true;
|
||||
delete this._pc;
|
||||
|
|
|
@ -280,9 +280,9 @@ struct ParamTraits<mozilla::dom::RTCIceComponentStats>
|
|||
}
|
||||
};
|
||||
|
||||
static void WriteRTCRTPStreamStats(
|
||||
static void WriteRTCRtpStreamStats(
|
||||
Message* aMsg,
|
||||
const mozilla::dom::RTCRTPStreamStats& aParam)
|
||||
const mozilla::dom::RTCRtpStreamStats& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mBitrateMean);
|
||||
WriteParam(aMsg, aParam.mBitrateStdDev);
|
||||
|
@ -297,9 +297,9 @@ static void WriteRTCRTPStreamStats(
|
|||
WriteParam(aMsg, aParam.mTransportId);
|
||||
}
|
||||
|
||||
static bool ReadRTCRTPStreamStats(
|
||||
static bool ReadRTCRtpStreamStats(
|
||||
const Message* aMsg, PickleIterator* aIter,
|
||||
mozilla::dom::RTCRTPStreamStats* aResult)
|
||||
mozilla::dom::RTCRtpStreamStats* aResult)
|
||||
{
|
||||
if (!ReadParam(aMsg, aIter, &(aResult->mBitrateMean)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mBitrateStdDev)) ||
|
||||
|
@ -334,7 +334,7 @@ struct ParamTraits<mozilla::dom::RTCInboundRTPStreamStats>
|
|||
WriteParam(aMsg, aParam.mRoundTripTime);
|
||||
WriteParam(aMsg, aParam.mPacketsLost);
|
||||
WriteParam(aMsg, aParam.mPacketsReceived);
|
||||
WriteRTCRTPStreamStats(aMsg, aParam);
|
||||
WriteRTCRtpStreamStats(aMsg, aParam);
|
||||
WriteRTCStats(aMsg, aParam);
|
||||
}
|
||||
|
||||
|
@ -349,7 +349,7 @@ struct ParamTraits<mozilla::dom::RTCInboundRTPStreamStats>
|
|||
!ReadParam(aMsg, aIter, &(aResult->mRoundTripTime)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mPacketsLost)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mPacketsReceived)) ||
|
||||
!ReadRTCRTPStreamStats(aMsg, aIter, aResult) ||
|
||||
!ReadRTCRtpStreamStats(aMsg, aIter, aResult) ||
|
||||
!ReadRTCStats(aMsg, aIter, aResult)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -373,7 +373,7 @@ struct ParamTraits<mozilla::dom::RTCOutboundRTPStreamStats>
|
|||
WriteParam(aMsg, aParam.mFirCount);
|
||||
WriteParam(aMsg, aParam.mNackCount);
|
||||
WriteParam(aMsg, aParam.mPliCount);
|
||||
WriteRTCRTPStreamStats(aMsg, aParam);
|
||||
WriteRTCRtpStreamStats(aMsg, aParam);
|
||||
WriteRTCStats(aMsg, aParam);
|
||||
}
|
||||
|
||||
|
@ -387,7 +387,7 @@ struct ParamTraits<mozilla::dom::RTCOutboundRTPStreamStats>
|
|||
!ReadParam(aMsg, aIter, &(aResult->mFirCount)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mNackCount)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mPliCount)) ||
|
||||
!ReadRTCRTPStreamStats(aMsg, aIter, aResult) ||
|
||||
!ReadRTCRtpStreamStats(aMsg, aIter, aResult) ||
|
||||
!ReadRTCStats(aMsg, aIter, aResult)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ with Files("**"):
|
|||
BUG_COMPONENT = ("Core", "DOM")
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsCWebBrowserPersist.idl',
|
||||
'nsIWebBrowserPersist.idl',
|
||||
'nsIWebBrowserPersistDocument.idl',
|
||||
]
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#include "nsIWebBrowserPersist.idl"
|
||||
|
||||
%{ C++
|
||||
// {7E677795-C582-4cd1-9E8D-8271B3474D2A}
|
||||
#define NS_WEBBROWSERPERSIST_CID \
|
||||
{ 0x7e677795, 0xc582, 0x4cd1, { 0x9e, 0x8d, 0x82, 0x71, 0xb3, 0x47, 0x4d, 0x2a } }
|
||||
#define NS_WEBBROWSERPERSIST_CONTRACTID \
|
||||
"@mozilla.org/embedding/browser/nsWebBrowserPersist;1"
|
||||
%}
|
|
@ -261,3 +261,16 @@ interface nsIWebBrowserPersist : nsICancelable
|
|||
*/
|
||||
void cancelSave();
|
||||
};
|
||||
|
||||
/**
|
||||
* We don't export nsWebBrowserPersist.h as a public header, so we need a place
|
||||
* to put the CID/ContractID. All places uses the WebBrowserPersist include
|
||||
* nsIWebBrowserPersist.h, so we define our contract IDs here for now.
|
||||
*/
|
||||
%{ C++
|
||||
// {7E677795-C582-4cd1-9E8D-8271B3474D2A}
|
||||
#define NS_WEBBROWSERPERSIST_CID \
|
||||
{ 0x7e677795, 0xc582, 0x4cd1, { 0x9e, 0x8d, 0x82, 0x71, 0xb3, 0x47, 0x4d, 0x2a } }
|
||||
#define NS_WEBBROWSERPERSIST_CONTRACTID \
|
||||
"@mozilla.org/embedding/browser/nsWebBrowserPersist;1"
|
||||
%}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "nsIProgressEventSink.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIWebProgressListener2.h"
|
||||
#include "nsIWebBrowserPersist.h"
|
||||
#include "nsIWebBrowserPersistDocument.h"
|
||||
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
@ -28,8 +29,6 @@
|
|||
#include "nsHashKeys.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "nsCWebBrowserPersist.h"
|
||||
|
||||
class nsIStorageStream;
|
||||
class nsIWebBrowserPersistDocument;
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ dictionary RTCStats {
|
|||
DOMString id;
|
||||
};
|
||||
|
||||
dictionary RTCRTPStreamStats : RTCStats {
|
||||
dictionary RTCRtpStreamStats : RTCStats {
|
||||
unsigned long ssrc;
|
||||
DOMString mediaType;
|
||||
DOMString remoteId;
|
||||
|
@ -48,7 +48,7 @@ dictionary RTCRTPStreamStats : RTCStats {
|
|||
unsigned long nackCount;
|
||||
};
|
||||
|
||||
dictionary RTCInboundRTPStreamStats : RTCRTPStreamStats {
|
||||
dictionary RTCInboundRTPStreamStats : RTCRtpStreamStats {
|
||||
unsigned long packetsReceived;
|
||||
unsigned long long bytesReceived;
|
||||
double jitter;
|
||||
|
@ -62,7 +62,7 @@ dictionary RTCInboundRTPStreamStats : RTCRTPStreamStats {
|
|||
unsigned long framesDecoded;
|
||||
};
|
||||
|
||||
dictionary RTCOutboundRTPStreamStats : RTCRTPStreamStats {
|
||||
dictionary RTCOutboundRTPStreamStats : RTCRtpStreamStats {
|
||||
unsigned long packetsSent;
|
||||
unsigned long long bytesSent;
|
||||
double targetBitrate; // config encoder bitrate target of this SSRC in bits/s
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
|
||||
|
||||
/* fluent-dom@aa95b1f (July 10, 2018) */
|
||||
/* fluent-dom@cab517f (July 31, 2018) */
|
||||
|
||||
const { Localization } =
|
||||
ChromeUtils.import("resource://gre/modules/Localization.jsm", {});
|
||||
|
@ -60,10 +60,10 @@ const LOCALIZABLE_ATTRIBUTES = {
|
|||
th: ["abbr"]
|
||||
},
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul": {
|
||||
description: ["value"],
|
||||
global: [
|
||||
"accesskey", "aria-label", "aria-valuetext", "aria-moz-hint", "label"
|
||||
],
|
||||
description: ["value"],
|
||||
key: ["key", "keycode"],
|
||||
label: ["value"],
|
||||
textbox: ["placeholder"],
|
||||
|
@ -523,7 +523,7 @@ class DOMLocalization extends Localization {
|
|||
if (this.windowElement) {
|
||||
if (this.windowElement !== newRoot.ownerGlobal) {
|
||||
throw new Error(`Cannot connect a root:
|
||||
DOMLocalization already has a root from a different window`);
|
||||
DOMLocalization already has a root from a different window.`);
|
||||
}
|
||||
} else {
|
||||
this.windowElement = newRoot.ownerGlobal;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
|
||||
|
||||
/* fluent-dom@aa95b1f (July 10, 2018) */
|
||||
/* fluent-dom@cab517f (July 31, 2018) */
|
||||
|
||||
/* eslint no-console: ["error", { allow: ["warn", "error"] }] */
|
||||
/* global console */
|
||||
|
@ -25,13 +25,25 @@ const { L10nRegistry } = ChromeUtils.import("resource://gre/modules/L10nRegistry
|
|||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
|
||||
const { AppConstants } = ChromeUtils.import("resource://gre/modules/AppConstants.jsm", {});
|
||||
|
||||
/*
|
||||
* CachedAsyncIterable caches the elements yielded by an iterable.
|
||||
*
|
||||
* It can be used to iterate over an iterable many times without depleting the
|
||||
* iterable.
|
||||
*/
|
||||
class CachedAsyncIterable {
|
||||
class CachedIterable extends Array {
|
||||
/**
|
||||
* Create a `CachedIterable` instance from an iterable or, if another
|
||||
* instance of `CachedIterable` is passed, return it without any
|
||||
* modifications.
|
||||
*
|
||||
* @param {Iterable} iterable
|
||||
* @returns {CachedIterable}
|
||||
*/
|
||||
static from(iterable) {
|
||||
if (iterable instanceof this) {
|
||||
return iterable;
|
||||
}
|
||||
|
||||
return new this(iterable);
|
||||
}
|
||||
}
|
||||
|
||||
class CachedAsyncIterable extends CachedIterable {
|
||||
/**
|
||||
* Create an `CachedAsyncIterable` instance.
|
||||
*
|
||||
|
@ -39,6 +51,8 @@ class CachedAsyncIterable {
|
|||
* @returns {CachedAsyncIterable}
|
||||
*/
|
||||
constructor(iterable) {
|
||||
super();
|
||||
|
||||
if (Symbol.asyncIterator in Object(iterable)) {
|
||||
this.iterator = iterable[Symbol.asyncIterator]();
|
||||
} else if (Symbol.iterator in Object(iterable)) {
|
||||
|
@ -46,20 +60,46 @@ class CachedAsyncIterable {
|
|||
} else {
|
||||
throw new TypeError("Argument must implement the iteration protocol.");
|
||||
}
|
||||
|
||||
this.seen = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronous iterator over the cached elements.
|
||||
*
|
||||
* Return a generator object implementing the iterator protocol over the
|
||||
* cached elements of the original (async or sync) iterable.
|
||||
*/
|
||||
[Symbol.iterator]() {
|
||||
const cached = this;
|
||||
let cur = 0;
|
||||
|
||||
return {
|
||||
next() {
|
||||
if (cached.length === cur) {
|
||||
return {value: undefined, done: true};
|
||||
}
|
||||
return cached[cur++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous iterator caching the yielded elements.
|
||||
*
|
||||
* Elements yielded by the original iterable will be cached and available
|
||||
* synchronously. Returns an async generator object implementing the
|
||||
* iterator protocol over the elements of the original (async or sync)
|
||||
* iterable.
|
||||
*/
|
||||
[Symbol.asyncIterator]() {
|
||||
const { seen, iterator } = this;
|
||||
const cached = this;
|
||||
let cur = 0;
|
||||
|
||||
return {
|
||||
async next() {
|
||||
if (seen.length <= cur) {
|
||||
seen.push(await iterator.next());
|
||||
if (cached.length <= cur) {
|
||||
cached.push(await cached.iterator.next());
|
||||
}
|
||||
return seen[cur++];
|
||||
return cached[cur++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -71,13 +111,17 @@ class CachedAsyncIterable {
|
|||
* @param {number} count - number of elements to consume
|
||||
*/
|
||||
async touchNext(count = 1) {
|
||||
const { seen, iterator } = this;
|
||||
let idx = 0;
|
||||
while (idx++ < count) {
|
||||
if (seen.length === 0 || seen[seen.length - 1].done === false) {
|
||||
seen.push(await iterator.next());
|
||||
const last = this[this.length - 1];
|
||||
if (last && last.done) {
|
||||
break;
|
||||
}
|
||||
this.push(await this.iterator.next());
|
||||
}
|
||||
// Return the last cached {value, done} object to allow the calling
|
||||
// code to decide if it needs to call touchNext again.
|
||||
return this[this.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,8 +156,8 @@ class Localization {
|
|||
constructor(resourceIds = [], generateMessages = defaultGenerateMessages) {
|
||||
this.resourceIds = resourceIds;
|
||||
this.generateMessages = generateMessages;
|
||||
this.ctxs =
|
||||
new CachedAsyncIterable(this.generateMessages(this.resourceIds));
|
||||
this.ctxs = CachedAsyncIterable.from(
|
||||
this.generateMessages(this.resourceIds));
|
||||
}
|
||||
|
||||
addResourceIds(resourceIds) {
|
||||
|
@ -276,8 +320,8 @@ class Localization {
|
|||
* that language negotiation or available resources changed.
|
||||
*/
|
||||
onChange() {
|
||||
this.ctxs =
|
||||
new CachedAsyncIterable(this.generateMessages(this.resourceIds));
|
||||
this.ctxs = CachedAsyncIterable.from(
|
||||
this.generateMessages(this.resourceIds));
|
||||
this.ctxs.touchNext(2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
|
||||
|
||||
/* fluent@aa95b1f (July 10, 2018) */
|
||||
/* fluent@0.7.0 */
|
||||
|
||||
/* eslint no-magic-numbers: [0] */
|
||||
|
||||
|
@ -25,6 +25,9 @@ const MAX_PLACEABLES = 100;
|
|||
const entryIdentifierRe = /-?[a-zA-Z][a-zA-Z0-9_-]*/y;
|
||||
const identifierRe = /[a-zA-Z][a-zA-Z0-9_-]*/y;
|
||||
const functionIdentifierRe = /^[A-Z][A-Z_?-]*$/;
|
||||
const unicodeEscapeRe = /^[a-fA-F0-9]{4}$/;
|
||||
const trailingWSRe = /[ \t\n\r]+$/;
|
||||
|
||||
|
||||
/**
|
||||
* The `Parser` class is responsible for parsing FTL resources.
|
||||
|
@ -94,46 +97,15 @@ class RuntimeParser {
|
|||
const ch = this._source[this._index];
|
||||
|
||||
// We don't care about comments or sections at runtime
|
||||
if (ch === "/" ||
|
||||
(ch === "#" &&
|
||||
[" ", "#", "\n"].includes(this._source[this._index + 1]))) {
|
||||
if (ch === "#" &&
|
||||
[" ", "#", "\n"].includes(this._source[this._index + 1])) {
|
||||
this.skipComment();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch === "[") {
|
||||
this.skipSection();
|
||||
return;
|
||||
}
|
||||
|
||||
this.getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip the section entry from the current index.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
skipSection() {
|
||||
this._index += 1;
|
||||
if (this._source[this._index] !== "[") {
|
||||
throw this.error('Expected "[[" to open a section');
|
||||
}
|
||||
|
||||
this._index += 1;
|
||||
|
||||
this.skipInlineWS();
|
||||
this.getVariantName();
|
||||
this.skipInlineWS();
|
||||
|
||||
if (this._source[this._index] !== "]" ||
|
||||
this._source[this._index + 1] !== "]") {
|
||||
throw this.error('Expected "]]" to close a section');
|
||||
}
|
||||
|
||||
this._index += 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the source string from the current index as an FTL message
|
||||
* and add it to the entries property on the Parser.
|
||||
|
@ -147,6 +119,8 @@ class RuntimeParser {
|
|||
|
||||
if (this._source[this._index] === "=") {
|
||||
this._index++;
|
||||
} else {
|
||||
throw this.error("Expected \"=\" after the identifier");
|
||||
}
|
||||
|
||||
this.skipInlineWS();
|
||||
|
@ -236,7 +210,7 @@ class RuntimeParser {
|
|||
* Get identifier using the provided regex.
|
||||
*
|
||||
* By default this will get identifiers of public messages, attributes and
|
||||
* external arguments (without the $).
|
||||
* variables (without the $).
|
||||
*
|
||||
* @returns {String}
|
||||
* @private
|
||||
|
@ -311,21 +285,30 @@ class RuntimeParser {
|
|||
* @private
|
||||
*/
|
||||
getString() {
|
||||
const start = this._index + 1;
|
||||
let value = "";
|
||||
this._index++;
|
||||
|
||||
while (++this._index < this._length) {
|
||||
while (this._index < this._length) {
|
||||
const ch = this._source[this._index];
|
||||
|
||||
if (ch === '"') {
|
||||
this._index++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch === "\n") {
|
||||
throw this.error("Unterminated string expression");
|
||||
}
|
||||
|
||||
if (ch === "\\") {
|
||||
value += this.getEscapedCharacter(["{", "\\", "\""]);
|
||||
} else {
|
||||
this._index++;
|
||||
value += ch;
|
||||
}
|
||||
}
|
||||
|
||||
return this._source.substring(start, this._index++);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -349,10 +332,17 @@ class RuntimeParser {
|
|||
eol = this._length;
|
||||
}
|
||||
|
||||
const firstLineContent = start !== eol ?
|
||||
this._source.slice(start, eol) : null;
|
||||
// If there's any text between the = and the EOL, store it for now. The next
|
||||
// non-empty line will decide what to do with it.
|
||||
const firstLineContent = start !== eol
|
||||
// Trim the trailing whitespace in case this is a single-line pattern.
|
||||
// Multiline patterns are parsed anew by getComplexPattern.
|
||||
? this._source.slice(start, eol).replace(trailingWSRe, "")
|
||||
: null;
|
||||
|
||||
if (firstLineContent && firstLineContent.includes("{")) {
|
||||
if (firstLineContent
|
||||
&& (firstLineContent.includes("{")
|
||||
|| firstLineContent.includes("\\"))) {
|
||||
return this.getComplexPattern();
|
||||
}
|
||||
|
||||
|
@ -439,13 +429,19 @@ class RuntimeParser {
|
|||
}
|
||||
ch = this._source[this._index];
|
||||
continue;
|
||||
} else if (ch === "\\") {
|
||||
const ch2 = this._source[this._index + 1];
|
||||
if (ch2 === '"' || ch2 === "{" || ch2 === "\\") {
|
||||
ch = ch2;
|
||||
this._index++;
|
||||
}
|
||||
} else if (ch === "{") {
|
||||
}
|
||||
|
||||
if (ch === undefined) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch === "\\") {
|
||||
buffer += this.getEscapedCharacter();
|
||||
ch = this._source[this._index];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch === "{") {
|
||||
// Push the buffer to content array right before placeable
|
||||
if (buffer.length) {
|
||||
content.push(buffer);
|
||||
|
@ -457,18 +453,13 @@ class RuntimeParser {
|
|||
buffer = "";
|
||||
content.push(this.getPlaceable());
|
||||
|
||||
this._index++;
|
||||
|
||||
ch = this._source[this._index];
|
||||
ch = this._source[++this._index];
|
||||
placeables++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch) {
|
||||
buffer += ch;
|
||||
}
|
||||
this._index++;
|
||||
ch = this._source[this._index];
|
||||
buffer += ch;
|
||||
ch = this._source[++this._index];
|
||||
}
|
||||
|
||||
if (content.length === 0) {
|
||||
|
@ -476,13 +467,42 @@ class RuntimeParser {
|
|||
}
|
||||
|
||||
if (buffer.length) {
|
||||
content.push(buffer);
|
||||
// Trim trailing whitespace, too.
|
||||
content.push(buffer.replace(trailingWSRe, ""));
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
/* eslint-enable complexity */
|
||||
|
||||
/**
|
||||
* Parse an escape sequence and return the unescaped character.
|
||||
*
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
getEscapedCharacter(specials = ["{", "\\"]) {
|
||||
this._index++;
|
||||
const next = this._source[this._index];
|
||||
|
||||
if (specials.includes(next)) {
|
||||
this._index++;
|
||||
return next;
|
||||
}
|
||||
|
||||
if (next === "u") {
|
||||
const sequence = this._source.slice(this._index + 1, this._index + 5);
|
||||
if (unicodeEscapeRe.test(sequence)) {
|
||||
this._index += 5;
|
||||
return String.fromCodePoint(parseInt(sequence, 16));
|
||||
}
|
||||
|
||||
throw this.error(`Invalid Unicode escape sequence: \\u${sequence}`);
|
||||
}
|
||||
|
||||
throw this.error(`Unknown escape sequence: \\${next}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a single placeable in a Message pattern and returns its
|
||||
* expression.
|
||||
|
@ -519,7 +539,7 @@ class RuntimeParser {
|
|||
const ch = this._source[this._index];
|
||||
|
||||
if (ch === "}") {
|
||||
if (selector.type === "attr" && selector.id.name.startsWith("-")) {
|
||||
if (selector.type === "getattr" && selector.id.name.startsWith("-")) {
|
||||
throw this.error(
|
||||
"Attributes of private messages cannot be interpolated."
|
||||
);
|
||||
|
@ -536,11 +556,11 @@ class RuntimeParser {
|
|||
throw this.error("Message references cannot be used as selectors.");
|
||||
}
|
||||
|
||||
if (selector.type === "var") {
|
||||
if (selector.type === "getvar") {
|
||||
throw this.error("Variants cannot be used as selectors.");
|
||||
}
|
||||
|
||||
if (selector.type === "attr" && !selector.id.name.startsWith("-")) {
|
||||
if (selector.type === "getattr" && !selector.id.name.startsWith("-")) {
|
||||
throw this.error(
|
||||
"Attributes of public messages cannot be used as selectors."
|
||||
);
|
||||
|
@ -578,6 +598,10 @@ class RuntimeParser {
|
|||
* @private
|
||||
*/
|
||||
getSelectorExpression() {
|
||||
if (this._source[this._index] === "{") {
|
||||
return this.getPlaceable();
|
||||
}
|
||||
|
||||
const literal = this.getLiteral();
|
||||
|
||||
if (literal.type !== "ref") {
|
||||
|
@ -590,7 +614,7 @@ class RuntimeParser {
|
|||
const name = this.getIdentifier();
|
||||
this._index++;
|
||||
return {
|
||||
type: "attr",
|
||||
type: "getattr",
|
||||
id: literal,
|
||||
name
|
||||
};
|
||||
|
@ -602,7 +626,7 @@ class RuntimeParser {
|
|||
const key = this.getVariantKey();
|
||||
this._index++;
|
||||
return {
|
||||
type: "var",
|
||||
type: "getvar",
|
||||
id: literal,
|
||||
key
|
||||
};
|
||||
|
@ -640,7 +664,7 @@ class RuntimeParser {
|
|||
const args = [];
|
||||
|
||||
while (this._index < this._length) {
|
||||
this.skipInlineWS();
|
||||
this.skipWS();
|
||||
|
||||
if (this._source[this._index] === ")") {
|
||||
return args;
|
||||
|
@ -657,7 +681,7 @@ class RuntimeParser {
|
|||
|
||||
if (this._source[this._index] === ":") {
|
||||
this._index++;
|
||||
this.skipInlineWS();
|
||||
this.skipWS();
|
||||
|
||||
const val = this.getSelectorExpression();
|
||||
|
||||
|
@ -685,7 +709,7 @@ class RuntimeParser {
|
|||
}
|
||||
}
|
||||
|
||||
this.skipInlineWS();
|
||||
this.skipWS();
|
||||
|
||||
if (this._source[this._index] === ")") {
|
||||
break;
|
||||
|
@ -885,7 +909,7 @@ class RuntimeParser {
|
|||
if (cc0 === 36) { // $
|
||||
this._index++;
|
||||
return {
|
||||
type: "ext",
|
||||
type: "var",
|
||||
name: this.getIdentifier()
|
||||
};
|
||||
}
|
||||
|
@ -925,12 +949,11 @@ class RuntimeParser {
|
|||
// to parse them properly and skip their content.
|
||||
let eol = this._source.indexOf("\n", this._index);
|
||||
|
||||
while (eol !== -1 &&
|
||||
((this._source[eol + 1] === "/" && this._source[eol + 2] === "/") ||
|
||||
(this._source[eol + 1] === "#" &&
|
||||
[" ", "#"].includes(this._source[eol + 2])))) {
|
||||
this._index = eol + 3;
|
||||
while (eol !== -1
|
||||
&& this._source[eol + 1] === "#"
|
||||
&& [" ", "#"].includes(this._source[eol + 2])) {
|
||||
|
||||
this._index = eol + 3;
|
||||
eol = this._source.indexOf("\n", this._index);
|
||||
|
||||
if (eol === -1) {
|
||||
|
@ -972,7 +995,7 @@ class RuntimeParser {
|
|||
|
||||
if ((cc >= 97 && cc <= 122) || // a-z
|
||||
(cc >= 65 && cc <= 90) || // A-Z
|
||||
cc === 47 || cc === 91) { // /[
|
||||
cc === 45) { // -
|
||||
this._index = start;
|
||||
return;
|
||||
}
|
||||
|
@ -1169,11 +1192,11 @@ function values(opts) {
|
|||
* The role of the Fluent resolver is to format a translation object to an
|
||||
* instance of `FluentType` or an array of instances.
|
||||
*
|
||||
* Translations can contain references to other messages or external arguments,
|
||||
* Translations can contain references to other messages or variables,
|
||||
* conditional logic in form of select expressions, traits which describe their
|
||||
* grammatical features, and can use Fluent builtins which make use of the
|
||||
* `Intl` formatters to format numbers, dates, lists and more into the
|
||||
* context's language. See the documentation of the Fluent syntax for more
|
||||
* context's language. See the documentation of the Fluent syntax for more
|
||||
* information.
|
||||
*
|
||||
* In case of errors the resolver will try to salvage as much of the
|
||||
|
@ -1436,8 +1459,8 @@ function Type(env, expr) {
|
|||
return new FluentSymbol(expr.name);
|
||||
case "num":
|
||||
return new FluentNumber(expr.val);
|
||||
case "ext":
|
||||
return ExternalArgument(env, expr);
|
||||
case "var":
|
||||
return VariableReference(env, expr);
|
||||
case "fun":
|
||||
return FunctionReference(env, expr);
|
||||
case "call":
|
||||
|
@ -1446,11 +1469,11 @@ function Type(env, expr) {
|
|||
const message = MessageReference(env, expr);
|
||||
return Type(env, message);
|
||||
}
|
||||
case "attr": {
|
||||
case "getattr": {
|
||||
const attr = AttributeExpression(env, expr);
|
||||
return Type(env, attr);
|
||||
}
|
||||
case "var": {
|
||||
case "getvar": {
|
||||
const variant = VariantExpression(env, expr);
|
||||
return Type(env, variant);
|
||||
}
|
||||
|
@ -1474,7 +1497,7 @@ function Type(env, expr) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Resolve a reference to an external argument.
|
||||
* Resolve a reference to a variable.
|
||||
*
|
||||
* @param {Object} env
|
||||
* Resolver environment object.
|
||||
|
@ -1485,11 +1508,11 @@ function Type(env, expr) {
|
|||
* @returns {FluentType}
|
||||
* @private
|
||||
*/
|
||||
function ExternalArgument(env, {name}) {
|
||||
function VariableReference(env, {name}) {
|
||||
const { args, errors } = env;
|
||||
|
||||
if (!args || !args.hasOwnProperty(name)) {
|
||||
errors.push(new ReferenceError(`Unknown external: ${name}`));
|
||||
errors.push(new ReferenceError(`Unknown variable: ${name}`));
|
||||
return new FluentNone(name);
|
||||
}
|
||||
|
||||
|
@ -1512,7 +1535,7 @@ function ExternalArgument(env, {name}) {
|
|||
}
|
||||
default:
|
||||
errors.push(
|
||||
new TypeError(`Unsupported external type: ${name}, ${typeof arg}`)
|
||||
new TypeError(`Unsupported variable type: ${name}, ${typeof arg}`)
|
||||
);
|
||||
return new FluentNone(name);
|
||||
}
|
||||
|
@ -1691,13 +1714,13 @@ class FluentResource extends Map {
|
|||
* responsible for parsing translation resources in the Fluent syntax and can
|
||||
* format translation units (entities) to strings.
|
||||
*
|
||||
* Always use `MessageContext.format` to retrieve translation units from
|
||||
* a context. Translations can contain references to other entities or
|
||||
* external arguments, conditional logic in form of select expressions, traits
|
||||
* which describe their grammatical features, and can use Fluent builtins which
|
||||
* make use of the `Intl` formatters to format numbers, dates, lists and more
|
||||
* into the context's language. See the documentation of the Fluent syntax for
|
||||
* more information.
|
||||
* Always use `MessageContext.format` to retrieve translation units from a
|
||||
* context. Translations can contain references to other entities or variables,
|
||||
* conditional logic in form of select expressions, traits which describe their
|
||||
* grammatical features, and can use Fluent builtins which make use of the
|
||||
* `Intl` formatters to format numbers, dates, lists and more into the
|
||||
* context's language. See the documentation of the Fluent syntax for more
|
||||
* information.
|
||||
*/
|
||||
class MessageContext {
|
||||
|
||||
|
@ -1849,8 +1872,8 @@ class MessageContext {
|
|||
* Format a message to a string or null.
|
||||
*
|
||||
* Format a raw `message` from the context into a string (or a null if it has
|
||||
* a null value). `args` will be used to resolve references to external
|
||||
* arguments inside of the translation.
|
||||
* a null value). `args` will be used to resolve references to variables
|
||||
* passed as arguments to the translation.
|
||||
*
|
||||
* In case of errors `format` will try to salvage as much of the translation
|
||||
* as possible and will still return a string. For performance reasons, the
|
||||
|
@ -1868,7 +1891,7 @@ class MessageContext {
|
|||
*
|
||||
* // Returns 'Hello, name!' and `errors` is now:
|
||||
*
|
||||
* [<ReferenceError: Unknown external: name>]
|
||||
* [<ReferenceError: Unknown variable: name>]
|
||||
*
|
||||
* @param {Object | string} message
|
||||
* @param {Object | undefined} args
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -19,10 +19,10 @@
|
|||
async function * generateMessages(locales, resourceIds) {
|
||||
const mc = new MessageContext(locales);
|
||||
mc.addMessages(`
|
||||
file-menu
|
||||
file-menu =
|
||||
.label = File
|
||||
.accesskey = F
|
||||
new-tab
|
||||
new-tab =
|
||||
.label = New Tab
|
||||
.accesskey = N
|
||||
`);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
async function* mockGenerateMessages(locales, resourceIds) {
|
||||
const mc = new MessageContext(locales);
|
||||
mc.addMessages("title = Hello World");
|
||||
mc.addMessages("link\n .title = Click me");
|
||||
mc.addMessages("link =\n .title = Click me");
|
||||
yield mc;
|
||||
}
|
||||
|
||||
|
|
|
@ -626,7 +626,8 @@ TokenStreamChars<Utf8Unit, AnyCharsAccess>::internalEncodingError(uint8_t releva
|
|||
|
||||
TokenStreamAnyChars& anyChars = anyCharsAccess();
|
||||
|
||||
if (bool hasLineOfContext = anyChars.fillExcludingContext(&err, offset)) {
|
||||
bool hasLineOfContext = anyChars.fillExcludingContext(&err, offset);
|
||||
if (hasLineOfContext) {
|
||||
if (!internalComputeLineOfContext(&err, offset))
|
||||
break;
|
||||
|
||||
|
|
|
@ -301,8 +301,8 @@ MobileViewportManager::UpdateSPCSPS(const ScreenIntSize& aDisplaySize,
|
|||
compositionSize.width -= scrollbars.LeftRight();
|
||||
compositionSize.height -= scrollbars.TopBottom();
|
||||
CSSSize compSize = compositionSize / aZoom;
|
||||
MVM_LOG("%p: Setting SPCSPS %s\n", this, Stringify(compSize).c_str());
|
||||
nsLayoutUtils::SetScrollPositionClampingScrollPortSize(mPresShell, compSize);
|
||||
MVM_LOG("%p: Setting VVPS %s\n", this, Stringify(compSize).c_str());
|
||||
nsLayoutUtils::SetVisualViewportSize(mPresShell, compSize);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -777,7 +777,7 @@ nsIPresShell::nsIPresShell()
|
|||
, mIsFirstPaint(false)
|
||||
, mObservesMutationsForPrint(false)
|
||||
, mWasLastReflowInterrupted(false)
|
||||
, mScrollPositionClampingScrollPortSizeSet(false)
|
||||
, mVisualViewportSizeSet(false)
|
||||
, mNeedLayoutFlush(true)
|
||||
, mNeedStyleFlush(true)
|
||||
, mObservingStyleFlushes(false)
|
||||
|
@ -850,7 +850,7 @@ PresShell::PresShell()
|
|||
mFrozen = false;
|
||||
mRenderFlags = 0;
|
||||
|
||||
mScrollPositionClampingScrollPortSizeSet = false;
|
||||
mVisualViewportSizeSet = false;
|
||||
|
||||
static bool addedSynthMouseMove = false;
|
||||
if (!addedSynthMouseMove) {
|
||||
|
@ -3445,7 +3445,7 @@ static void ScrollToShowRect(nsIScrollableFrame* aFrameAsScrollable,
|
|||
{
|
||||
nsPoint scrollPt = aFrameAsScrollable->GetScrollPosition();
|
||||
nsRect visibleRect(scrollPt,
|
||||
aFrameAsScrollable->GetScrollPositionClampingScrollPortSize());
|
||||
aFrameAsScrollable->GetVisualViewportSize());
|
||||
|
||||
nsSize lineSize;
|
||||
// Don't call GetLineScrollAmount unless we actually need it. Not only
|
||||
|
@ -10590,14 +10590,14 @@ nsIPresShell::MarkFixedFramesForReflow(IntrinsicDirty aIntrinsicDirty)
|
|||
}
|
||||
|
||||
void
|
||||
nsIPresShell::SetScrollPositionClampingScrollPortSize(nscoord aWidth, nscoord aHeight)
|
||||
nsIPresShell::SetVisualViewportSize(nscoord aWidth, nscoord aHeight)
|
||||
{
|
||||
if (!mScrollPositionClampingScrollPortSizeSet ||
|
||||
mScrollPositionClampingScrollPortSize.width != aWidth ||
|
||||
mScrollPositionClampingScrollPortSize.height != aHeight) {
|
||||
mScrollPositionClampingScrollPortSizeSet = true;
|
||||
mScrollPositionClampingScrollPortSize.width = aWidth;
|
||||
mScrollPositionClampingScrollPortSize.height = aHeight;
|
||||
if (!mVisualViewportSizeSet ||
|
||||
mVisualViewportSize.width != aWidth ||
|
||||
mVisualViewportSize.height != aHeight) {
|
||||
mVisualViewportSizeSet = true;
|
||||
mVisualViewportSize.width = aWidth;
|
||||
mVisualViewportSize.height = aHeight;
|
||||
|
||||
if (nsIScrollableFrame* rootScrollFrame = GetRootScrollFrameAsScrollable()) {
|
||||
rootScrollFrame->MarkScrollbarsDirtyForReflow();
|
||||
|
|
|
@ -1660,13 +1660,13 @@ public:
|
|||
// clears that capture.
|
||||
static void ClearMouseCapture(nsIFrame* aFrame);
|
||||
|
||||
void SetScrollPositionClampingScrollPortSize(nscoord aWidth, nscoord aHeight);
|
||||
bool IsScrollPositionClampingScrollPortSizeSet() {
|
||||
return mScrollPositionClampingScrollPortSizeSet;
|
||||
void SetVisualViewportSize(nscoord aWidth, nscoord aHeight);
|
||||
bool IsVisualViewportSizeSet() {
|
||||
return mVisualViewportSizeSet;
|
||||
}
|
||||
nsSize GetScrollPositionClampingScrollPortSize() {
|
||||
NS_ASSERTION(mScrollPositionClampingScrollPortSizeSet, "asking for scroll port when its not set?");
|
||||
return mScrollPositionClampingScrollPortSize;
|
||||
nsSize GetVisualViewportSize() {
|
||||
NS_ASSERTION(mVisualViewportSizeSet, "asking for visual viewport size when its not set?");
|
||||
return mVisualViewportSize;
|
||||
}
|
||||
|
||||
void SetVisualViewportOffset(const nsPoint& aScrollOffset) {
|
||||
|
@ -1753,7 +1753,7 @@ protected:
|
|||
// Count of the number of times this presshell has been painted to a window.
|
||||
uint64_t mPaintCount;
|
||||
|
||||
nsSize mScrollPositionClampingScrollPortSize;
|
||||
nsSize mVisualViewportSize;
|
||||
|
||||
nsPoint mVisualViewportOffset;
|
||||
|
||||
|
@ -1813,7 +1813,7 @@ protected:
|
|||
|
||||
// Whether the most recent interruptible reflow was actually interrupted:
|
||||
bool mWasLastReflowInterrupted : 1;
|
||||
bool mScrollPositionClampingScrollPortSizeSet : 1;
|
||||
bool mVisualViewportSizeSet : 1;
|
||||
|
||||
// True if a layout flush might not be a no-op
|
||||
bool mNeedLayoutFlush : 1;
|
||||
|
|
|
@ -9040,11 +9040,11 @@ MaybeReflowForInflationScreenSizeChange(nsPresContext *aPresContext)
|
|||
}
|
||||
|
||||
/* static */ void
|
||||
nsLayoutUtils::SetScrollPositionClampingScrollPortSize(nsIPresShell* aPresShell, CSSSize aSize)
|
||||
nsLayoutUtils::SetVisualViewportSize(nsIPresShell* aPresShell, CSSSize aSize)
|
||||
{
|
||||
MOZ_ASSERT(aSize.width >= 0.0 && aSize.height >= 0.0);
|
||||
|
||||
aPresShell->SetScrollPositionClampingScrollPortSize(
|
||||
aPresShell->SetVisualViewportSize(
|
||||
nsPresContext::CSSPixelsToAppUnits(aSize.width),
|
||||
nsPresContext::CSSPixelsToAppUnits(aSize.height));
|
||||
|
||||
|
|
|
@ -2852,11 +2852,11 @@ public:
|
|||
static bool HasDocumentLevelListenersForApzAwareEvents(nsIPresShell* aShell);
|
||||
|
||||
/**
|
||||
* Set the scroll port size for the purpose of clamping the scroll position
|
||||
* Set the viewport size for the purpose of clamping the scroll position
|
||||
* for the root scroll frame of this document
|
||||
* (see nsIDOMWindowUtils.setScrollPositionClampingScrollPortSize).
|
||||
* (see nsIDOMWindowUtils.setVisualViewportSize).
|
||||
*/
|
||||
static void SetScrollPositionClampingScrollPortSize(nsIPresShell* aPresShell,
|
||||
static void SetVisualViewportSize(nsIPresShell* aPresShell,
|
||||
CSSSize aSize);
|
||||
|
||||
/**
|
||||
|
|
|
@ -281,12 +281,12 @@ ViewportFrame::AdjustReflowInputAsContainingBlock(ReflowInput* aReflowInput) con
|
|||
"We don't handle correct positioning of fixed frames with "
|
||||
"scrollbars in odd positions");
|
||||
|
||||
// If a scroll position clamping scroll-port size has been set, layout
|
||||
// If a scroll position clamping viewport size has been set, layout
|
||||
// fixed position elements to this size instead of the computed size.
|
||||
nsRect rect(0, 0, aReflowInput->ComputedWidth(), aReflowInput->ComputedHeight());
|
||||
nsIPresShell* ps = PresShell();
|
||||
if (ps->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
rect.SizeTo(ps->GetScrollPositionClampingScrollPortSize());
|
||||
if (ps->IsVisualViewportSizeSet()) {
|
||||
rect.SizeTo(ps->GetVisualViewportSize());
|
||||
}
|
||||
|
||||
return rect;
|
||||
|
|
|
@ -68,7 +68,7 @@ public:
|
|||
|
||||
/**
|
||||
* Adjust aReflowInput to account for scrollbars and pres shell
|
||||
* GetScrollPositionClampingScrollPortSizeSet and
|
||||
* GetVisualViewportSizeSet and
|
||||
* GetContentDocumentFixedPositionMargins adjustments.
|
||||
* @return the rect to use as containing block rect
|
||||
*/
|
||||
|
|
|
@ -384,14 +384,14 @@ nsHTMLScrollFrame::TryLayout(ScrollReflowInput* aState,
|
|||
nsSize scrollPortSize = nsSize(std::max(0, aState->mInsideBorderSize.width - vScrollbarDesiredWidth),
|
||||
std::max(0, aState->mInsideBorderSize.height - hScrollbarDesiredHeight));
|
||||
|
||||
nsSize visualScrollPortSize = scrollPortSize;
|
||||
nsSize visualViewportSize = scrollPortSize;
|
||||
nsIPresShell* presShell = PresShell();
|
||||
if (mHelper.mIsRoot && presShell->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
if (mHelper.mIsRoot && presShell->IsVisualViewportSizeSet()) {
|
||||
nsSize compositionSize = nsLayoutUtils::CalculateCompositionSizeForFrame(this, false);
|
||||
float resolution = presShell->GetResolution();
|
||||
compositionSize.width /= resolution;
|
||||
compositionSize.height /= resolution;
|
||||
visualScrollPortSize = nsSize(std::max(0, compositionSize.width - vScrollbarDesiredWidth),
|
||||
visualViewportSize = nsSize(std::max(0, compositionSize.width - vScrollbarDesiredWidth),
|
||||
std::max(0, compositionSize.height - hScrollbarDesiredHeight));
|
||||
}
|
||||
|
||||
|
@ -405,7 +405,7 @@ nsHTMLScrollFrame::TryLayout(ScrollReflowInput* aState,
|
|||
if (aState->mStyles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) {
|
||||
bool wantHScrollbar =
|
||||
aState->mStyles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL ||
|
||||
scrolledRect.XMost() >= visualScrollPortSize.width + oneDevPixel ||
|
||||
scrolledRect.XMost() >= visualViewportSize.width + oneDevPixel ||
|
||||
scrolledRect.x <= -oneDevPixel;
|
||||
if (scrollPortSize.width < hScrollbarMinSize.width)
|
||||
wantHScrollbar = false;
|
||||
|
@ -417,7 +417,7 @@ nsHTMLScrollFrame::TryLayout(ScrollReflowInput* aState,
|
|||
if (aState->mStyles.mVertical != NS_STYLE_OVERFLOW_HIDDEN) {
|
||||
bool wantVScrollbar =
|
||||
aState->mStyles.mVertical == NS_STYLE_OVERFLOW_SCROLL ||
|
||||
scrolledRect.YMost() >= visualScrollPortSize.height + oneDevPixel ||
|
||||
scrolledRect.YMost() >= visualViewportSize.height + oneDevPixel ||
|
||||
scrolledRect.y <= -oneDevPixel;
|
||||
if (scrollPortSize.height < vScrollbarMinSize.height)
|
||||
wantVScrollbar = false;
|
||||
|
@ -2860,10 +2860,10 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsAtom* aOrig
|
|||
|
||||
nsPoint dist(std::abs(pt.x - mLastUpdateFramesPos.x),
|
||||
std::abs(pt.y - mLastUpdateFramesPos.y));
|
||||
nsSize scrollPortSize = GetScrollPositionClampingScrollPortSize();
|
||||
nscoord horzAllowance = std::max(scrollPortSize.width / std::max(sHorzScrollFraction, 1),
|
||||
nsSize visualViewportSize = GetVisualViewportSize();
|
||||
nscoord horzAllowance = std::max(visualViewportSize.width / std::max(sHorzScrollFraction, 1),
|
||||
nsPresContext::AppUnitsPerCSSPixel());
|
||||
nscoord vertAllowance = std::max(scrollPortSize.height / std::max(sVertScrollFraction, 1),
|
||||
nscoord vertAllowance = std::max(visualViewportSize.height / std::max(sVertScrollFraction, 1),
|
||||
nsPresContext::AppUnitsPerCSSPixel());
|
||||
if (dist.x >= horzAllowance || dist.y >= vertAllowance) {
|
||||
needFrameVisibilityUpdate = true;
|
||||
|
@ -3491,7 +3491,7 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
const nsStyleDisplay* disp = mOuter->StyleDisplay();
|
||||
if (disp && (disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_SCROLL)) {
|
||||
aBuilder->AddToWillChangeBudget(mOuter, GetScrollPositionClampingScrollPortSize());
|
||||
aBuilder->AddToWillChangeBudget(mOuter, GetVisualViewportSize());
|
||||
}
|
||||
|
||||
mScrollParentID = aBuilder->GetCurrentScrollParentId();
|
||||
|
@ -4056,16 +4056,16 @@ ScrollFrameHelper::GetScrollRangeForClamping() const
|
|||
return nsRect(nscoord_MIN/2, nscoord_MIN/2,
|
||||
nscoord_MAX - nscoord_MIN/2, nscoord_MAX - nscoord_MIN/2);
|
||||
}
|
||||
nsSize scrollPortSize = GetScrollPositionClampingScrollPortSize();
|
||||
return GetScrollRange(scrollPortSize.width, scrollPortSize.height);
|
||||
nsSize visualViewportSize = GetVisualViewportSize();
|
||||
return GetScrollRange(visualViewportSize.width, visualViewportSize.height);
|
||||
}
|
||||
|
||||
nsSize
|
||||
ScrollFrameHelper::GetScrollPositionClampingScrollPortSize() const
|
||||
ScrollFrameHelper::GetVisualViewportSize() const
|
||||
{
|
||||
nsIPresShell* presShell = mOuter->PresShell();
|
||||
if (mIsRoot && presShell->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
return presShell->GetScrollPositionClampingScrollPortSize();
|
||||
if (mIsRoot && presShell->IsVisualViewportSizeSet()) {
|
||||
return presShell->GetVisualViewportSize();
|
||||
}
|
||||
return mScrollPort.Size();
|
||||
}
|
||||
|
@ -5296,7 +5296,7 @@ ScrollFrameHelper::IsScrollingActive(nsDisplayListBuilder* aBuilder) const
|
|||
{
|
||||
const nsStyleDisplay* disp = mOuter->StyleDisplay();
|
||||
if (disp && (disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_SCROLL) &&
|
||||
aBuilder->IsInWillChangeBudget(mOuter, GetScrollPositionClampingScrollPortSize())) {
|
||||
aBuilder->IsInWillChangeBudget(mOuter, GetVisualViewportSize())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -5604,7 +5604,7 @@ ScrollFrameHelper::ReflowFinished()
|
|||
}
|
||||
|
||||
nsRect scrolledContentRect = GetScrolledRect();
|
||||
nsSize scrollClampingScrollPort = GetScrollPositionClampingScrollPortSize();
|
||||
nsSize scrollClampingScrollPort = GetVisualViewportSize();
|
||||
nscoord minX = scrolledContentRect.x;
|
||||
nscoord maxX = scrolledContentRect.XMost() - scrollClampingScrollPort.width;
|
||||
nscoord minY = scrolledContentRect.y;
|
||||
|
@ -5824,12 +5824,12 @@ ScrollFrameHelper::LayoutScrollbars(nsBoxLayoutState& aState,
|
|||
bool scrollbarOnLeft = !IsScrollbarOnRight();
|
||||
bool overlayScrollBarsWithZoom =
|
||||
mIsRoot && LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) &&
|
||||
presShell->IsScrollPositionClampingScrollPortSizeSet();
|
||||
presShell->IsVisualViewportSizeSet();
|
||||
|
||||
nsSize scrollPortClampingSize = mScrollPort.Size();
|
||||
double res = 1.0;
|
||||
if (overlayScrollBarsWithZoom) {
|
||||
scrollPortClampingSize = presShell->GetScrollPositionClampingScrollPortSize();
|
||||
scrollPortClampingSize = presShell->GetVisualViewportSize();
|
||||
res = presShell->GetCumulativeResolution();
|
||||
}
|
||||
|
||||
|
@ -6109,11 +6109,11 @@ ScrollFrameHelper::GetScrolledRect() const
|
|||
// For that, we first convert the scroll port and the scrolled rect to rects
|
||||
// relative to the reference frame, since that's the space where painting does
|
||||
// snapping.
|
||||
nsSize scrollPortSize = GetScrollPositionClampingScrollPortSize();
|
||||
nsSize visualViewportSize = GetVisualViewportSize();
|
||||
const nsIFrame* referenceFrame =
|
||||
mReferenceFrameDuringPainting ? mReferenceFrameDuringPainting : nsLayoutUtils::GetReferenceFrame(mOuter);
|
||||
nsPoint toReferenceFrame = mOuter->GetOffsetToCrossDoc(referenceFrame);
|
||||
nsRect scrollPort(mScrollPort.TopLeft() + toReferenceFrame, scrollPortSize);
|
||||
nsRect scrollPort(mScrollPort.TopLeft() + toReferenceFrame, visualViewportSize);
|
||||
nsRect scrolledRect = result + scrollPort.TopLeft();
|
||||
|
||||
if (scrollPort.Overflows() || scrolledRect.Overflows()) {
|
||||
|
|
|
@ -214,9 +214,9 @@ public:
|
|||
return pt;
|
||||
}
|
||||
nsRect GetScrollRange() const;
|
||||
// Get the scroll range assuming the scrollport has size (aWidth, aHeight).
|
||||
// Get the scroll range assuming the viewport has size (aWidth, aHeight).
|
||||
nsRect GetScrollRange(nscoord aWidth, nscoord aHeight) const;
|
||||
nsSize GetScrollPositionClampingScrollPortSize() const;
|
||||
nsSize GetVisualViewportSize() const;
|
||||
void ScrollSnap(nsIScrollableFrame::ScrollMode aMode = nsIScrollableFrame::SMOOTH_MSD);
|
||||
void ScrollSnap(const nsPoint &aDestination,
|
||||
nsIScrollableFrame::ScrollMode aMode = nsIScrollableFrame::SMOOTH_MSD);
|
||||
|
@ -852,8 +852,8 @@ public:
|
|||
virtual nsRect GetScrollRange() const override {
|
||||
return mHelper.GetScrollRange();
|
||||
}
|
||||
virtual nsSize GetScrollPositionClampingScrollPortSize() const override {
|
||||
return mHelper.GetScrollPositionClampingScrollPortSize();
|
||||
virtual nsSize GetVisualViewportSize() const override {
|
||||
return mHelper.GetVisualViewportSize();
|
||||
}
|
||||
virtual nsSize GetLineScrollAmount() const override {
|
||||
return mHelper.GetLineScrollAmount();
|
||||
|
@ -1304,8 +1304,8 @@ public:
|
|||
virtual nsRect GetScrollRange() const override {
|
||||
return mHelper.GetScrollRange();
|
||||
}
|
||||
virtual nsSize GetScrollPositionClampingScrollPortSize() const override {
|
||||
return mHelper.GetScrollPositionClampingScrollPortSize();
|
||||
virtual nsSize GetVisualViewportSize() const override {
|
||||
return mHelper.GetVisualViewportSize();
|
||||
}
|
||||
virtual nsSize GetLineScrollAmount() const override {
|
||||
return mHelper.GetLineScrollAmount();
|
||||
|
|
|
@ -148,10 +148,10 @@ public:
|
|||
*/
|
||||
virtual nsRect GetScrollRange() const = 0;
|
||||
/**
|
||||
* Get the size of the scroll port to use when clamping the scroll
|
||||
* Get the size of the view port to use when clamping the scroll
|
||||
* position.
|
||||
*/
|
||||
virtual nsSize GetScrollPositionClampingScrollPortSize() const = 0;
|
||||
virtual nsSize GetVisualViewportSize() const = 0;
|
||||
/**
|
||||
* Return how much we would try to scroll by in each direction if
|
||||
* asked to scroll by one "line" vertically and horizontally.
|
||||
|
|
|
@ -7017,8 +7017,8 @@ nsDisplayFixedPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
if (viewportFrame) {
|
||||
// Fixed position frames are reflowed into the scroll-port size if one has
|
||||
// been set.
|
||||
if (presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
anchorRect.SizeTo(presContext->PresShell()->GetScrollPositionClampingScrollPortSize());
|
||||
if (presContext->PresShell()->IsVisualViewportSizeSet()) {
|
||||
anchorRect.SizeTo(presContext->PresShell()->GetVisualViewportSize());
|
||||
} else {
|
||||
anchorRect.SizeTo(viewportFrame->GetSize());
|
||||
}
|
||||
|
@ -7193,9 +7193,9 @@ nsDisplayStickyPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
// reflowed into the scroll-port size if one has been set.
|
||||
nsSize scrollFrameSize = scrollFrame->GetSize();
|
||||
if (scrollFrame == presContext->PresShell()->GetRootScrollFrame() &&
|
||||
presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
presContext->PresShell()->IsVisualViewportSizeSet()) {
|
||||
scrollFrameSize = presContext->PresShell()->
|
||||
GetScrollPositionClampingScrollPortSize();
|
||||
GetVisualViewportSize();
|
||||
}
|
||||
|
||||
nsLayoutUtils::SetFixedPositionLayerData(layer, scrollFrame,
|
||||
|
|
|
@ -1465,12 +1465,11 @@ public:
|
|||
if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) &&
|
||||
aBuilder->IsPaintingToWindow()) {
|
||||
// position: fixed items are reflowed into and only drawn inside the
|
||||
// viewport, or the scroll position clamping scrollport size, if one is
|
||||
// set.
|
||||
// viewport, or the visual viewport size, if one is set.
|
||||
nsIPresShell* ps = aFrame->PresShell();
|
||||
if (ps->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
if (ps->IsVisualViewportSizeSet()) {
|
||||
dirtyRectRelativeToDirtyFrame =
|
||||
nsRect(nsPoint(0, 0), ps->GetScrollPositionClampingScrollPortSize());
|
||||
nsRect(nsPoint(0, 0), ps->GetVisualViewportSize());
|
||||
visible = dirtyRectRelativeToDirtyFrame;
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
} else {
|
||||
|
|
|
@ -292,8 +292,8 @@ function setupViewport(contentRootElement) {
|
|||
var sw = attrOrDefault(contentRootElement, "reftest-scrollport-w", 0);
|
||||
var sh = attrOrDefault(contentRootElement, "reftest-scrollport-h", 0);
|
||||
if (sw !== 0 || sh !== 0) {
|
||||
LogInfo("Setting scrollport to <w=" + sw + ", h=" + sh + ">");
|
||||
windowUtils().setScrollPositionClampingScrollPortSize(sw, sh);
|
||||
LogInfo("Setting viewport to <w=" + sw + ", h=" + sh + ">");
|
||||
windowUtils().setVisualViewportSize(sw, sh);
|
||||
}
|
||||
|
||||
// XXX support resolution when needed
|
||||
|
|
|
@ -208,6 +208,10 @@ public:
|
|||
{
|
||||
return false;
|
||||
}
|
||||
bool UnsetRemoteSSRC(uint32_t ssrc) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool GetRemoteSSRC(unsigned int* ssrc) override;
|
||||
bool SetLocalCNAME(const char* cname) override;
|
||||
bool SetLocalMID(const std::string& mid) override;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace webrtc {
|
||||
class VideoFrame;
|
||||
|
@ -40,64 +41,6 @@ enum class MediaSessionConduitLocalDirection : int {
|
|||
|
||||
using RtpExtList = std::vector<webrtc::RtpExtension>;
|
||||
|
||||
// Wrap the webrtc.org Call class adding mozilla add/ref support.
|
||||
class WebRtcCallWrapper : public RefCounted<WebRtcCallWrapper>
|
||||
{
|
||||
public:
|
||||
typedef webrtc::Call::Config Config;
|
||||
|
||||
static RefPtr<WebRtcCallWrapper> Create()
|
||||
{
|
||||
return new WebRtcCallWrapper();
|
||||
}
|
||||
|
||||
static RefPtr<WebRtcCallWrapper> Create(UniquePtr<webrtc::Call>&& aCall)
|
||||
{
|
||||
return new WebRtcCallWrapper(std::move(aCall));
|
||||
}
|
||||
|
||||
webrtc::Call* Call() const
|
||||
{
|
||||
return mCall.get();
|
||||
}
|
||||
|
||||
virtual ~WebRtcCallWrapper()
|
||||
{
|
||||
if (mCall->voice_engine()) {
|
||||
webrtc::VoiceEngine* voice_engine = mCall->voice_engine();
|
||||
mCall.reset(nullptr); // Force it to release the voice engine reference
|
||||
// Delete() must be after all refs are released
|
||||
webrtc::VoiceEngine::Delete(voice_engine);
|
||||
} else {
|
||||
// Must ensure it's destroyed *before* the EventLog!
|
||||
mCall.reset(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(WebRtcCallWrapper)
|
||||
|
||||
private:
|
||||
WebRtcCallWrapper()
|
||||
{
|
||||
webrtc::Call::Config config(&mEventLog);
|
||||
mCall.reset(webrtc::Call::Create(config));
|
||||
}
|
||||
|
||||
explicit WebRtcCallWrapper(UniquePtr<webrtc::Call>&& aCall)
|
||||
{
|
||||
MOZ_ASSERT(aCall);
|
||||
mCall = std::move(aCall);
|
||||
}
|
||||
|
||||
// Don't allow copying/assigning.
|
||||
WebRtcCallWrapper(const WebRtcCallWrapper&) = delete;
|
||||
void operator=(const WebRtcCallWrapper&) = delete;
|
||||
|
||||
UniquePtr<webrtc::Call> mCall;
|
||||
webrtc::RtcEventLogNullImpl mEventLog;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Abstract Interface for transporting RTP packets - audio/vidoeo
|
||||
* The consumers of this interface are responsible for passing in
|
||||
|
@ -268,6 +211,7 @@ public:
|
|||
|
||||
virtual bool GetRemoteSSRC(unsigned int* ssrc) = 0;
|
||||
virtual bool SetRemoteSSRC(unsigned int ssrc) = 0;
|
||||
virtual bool UnsetRemoteSSRC(uint32_t ssrc) = 0;
|
||||
virtual bool SetLocalCNAME(const char* cname) = 0;
|
||||
|
||||
virtual bool SetLocalMID(const std::string& mid) = 0;
|
||||
|
@ -319,6 +263,87 @@ public:
|
|||
|
||||
};
|
||||
|
||||
// Wrap the webrtc.org Call class adding mozilla add/ref support.
|
||||
class WebRtcCallWrapper : public RefCounted<WebRtcCallWrapper>
|
||||
{
|
||||
public:
|
||||
typedef webrtc::Call::Config Config;
|
||||
|
||||
static RefPtr<WebRtcCallWrapper> Create()
|
||||
{
|
||||
return new WebRtcCallWrapper();
|
||||
}
|
||||
|
||||
static RefPtr<WebRtcCallWrapper> Create(UniquePtr<webrtc::Call>&& aCall)
|
||||
{
|
||||
return new WebRtcCallWrapper(std::move(aCall));
|
||||
}
|
||||
|
||||
// Don't allow copying/assigning.
|
||||
WebRtcCallWrapper(const WebRtcCallWrapper&) = delete;
|
||||
void operator=(const WebRtcCallWrapper&) = delete;
|
||||
|
||||
webrtc::Call* Call() const
|
||||
{
|
||||
return mCall.get();
|
||||
}
|
||||
|
||||
virtual ~WebRtcCallWrapper()
|
||||
{
|
||||
if (mCall->voice_engine()) {
|
||||
webrtc::VoiceEngine* voice_engine = mCall->voice_engine();
|
||||
mCall.reset(nullptr); // Force it to release the voice engine reference
|
||||
// Delete() must be after all refs are released
|
||||
webrtc::VoiceEngine::Delete(voice_engine);
|
||||
} else {
|
||||
// Must ensure it's destroyed *before* the EventLog!
|
||||
mCall.reset(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool UnsetRemoteSSRC(uint32_t ssrc)
|
||||
{
|
||||
for (auto conduit : mConduits) {
|
||||
if (!conduit->UnsetRemoteSSRC(ssrc)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RegisterConduit(MediaSessionConduit* conduit)
|
||||
{
|
||||
mConduits.insert(conduit);
|
||||
}
|
||||
|
||||
void UnregisterConduit(MediaSessionConduit* conduit)
|
||||
{
|
||||
mConduits.erase(conduit);
|
||||
}
|
||||
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(WebRtcCallWrapper)
|
||||
|
||||
private:
|
||||
WebRtcCallWrapper()
|
||||
{
|
||||
webrtc::Call::Config config(&mEventLog);
|
||||
mCall.reset(webrtc::Call::Create(config));
|
||||
}
|
||||
|
||||
explicit WebRtcCallWrapper(UniquePtr<webrtc::Call>&& aCall)
|
||||
{
|
||||
MOZ_ASSERT(aCall);
|
||||
mCall = std::move(aCall);
|
||||
}
|
||||
|
||||
UniquePtr<webrtc::Call> mCall;
|
||||
webrtc::RtcEventLogNullImpl mEventLog;
|
||||
// Allows conduits to know about one another, to avoid remote SSRC
|
||||
// collisions.
|
||||
std::set<MediaSessionConduit*> mConduits;
|
||||
};
|
||||
|
||||
// Abstract base classes for external encoder/decoder.
|
||||
class CodecPluginID
|
||||
{
|
||||
|
@ -389,6 +414,7 @@ public:
|
|||
virtual void DisableSsrcChanges() = 0;
|
||||
|
||||
bool SetRemoteSSRC(unsigned int ssrc) override = 0;
|
||||
bool UnsetRemoteSSRC(uint32_t ssrc) override = 0;
|
||||
|
||||
/**
|
||||
* Function to deliver a capture video frame for encoding and transport.
|
||||
|
|
|
@ -277,6 +277,7 @@ WebrtcVideoConduit::WebrtcVideoConduit(RefPtr<WebRtcCallWrapper> aCall,
|
|||
, mRecvCodecPlugin(nullptr)
|
||||
, mVideoStatsTimer(NS_NewTimer())
|
||||
{
|
||||
mCall->RegisterConduit(this);
|
||||
mRecvStreamConfig.renderer = this;
|
||||
|
||||
// Video Stats Callback
|
||||
|
@ -307,6 +308,7 @@ WebrtcVideoConduit::~WebrtcVideoConduit()
|
|||
{
|
||||
CSFLogDebug(LOGTAG, "%s ", __FUNCTION__);
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
mCall->UnregisterConduit(this);
|
||||
if (mVideoStatsTimer) {
|
||||
CSFLogDebug(LOGTAG, "canceling StreamStats for VideoConduit: %p", this);
|
||||
MutexAutoLock lock(mCodecMutex);
|
||||
|
@ -884,6 +886,22 @@ WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig)
|
|||
return condError;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
GenerateRandomSSRC()
|
||||
{
|
||||
uint32_t ssrc;
|
||||
do {
|
||||
SECStatus rv = PK11_GenerateRandom(reinterpret_cast<unsigned char*>(&ssrc), sizeof(ssrc));
|
||||
if (rv != SECSuccess) {
|
||||
CSFLogError(LOGTAG, "%s: PK11_GenerateRandom failed with error %d",
|
||||
__FUNCTION__, rv);
|
||||
return 0;
|
||||
}
|
||||
} while (ssrc == 0); // webrtc.org code has fits if you select an SSRC of 0
|
||||
|
||||
return ssrc;
|
||||
}
|
||||
|
||||
bool
|
||||
WebrtcVideoConduit::SetRemoteSSRC(unsigned int ssrc)
|
||||
{
|
||||
|
@ -902,6 +920,11 @@ WebrtcVideoConduit::SetRemoteSSRC(unsigned int ssrc)
|
|||
}
|
||||
|
||||
CSFLogDebug(LOGTAG, "%s: SSRC %u (0x%x)", __FUNCTION__, ssrc, ssrc);
|
||||
if (!mCall->UnsetRemoteSSRC(ssrc)) {
|
||||
CSFLogError(LOGTAG, "%s: Failed to unset SSRC %u (0x%x) on other conduits,"
|
||||
" bailing", __FUNCTION__, ssrc, ssrc);
|
||||
return false;
|
||||
}
|
||||
mRecvStreamConfig.rtp.remote_ssrc = ssrc;
|
||||
mWaitingForInitialSsrc = false;
|
||||
|
||||
|
@ -926,6 +949,33 @@ WebrtcVideoConduit::SetRemoteSSRC(unsigned int ssrc)
|
|||
return (StartReceiving() == kMediaConduitNoError);
|
||||
}
|
||||
|
||||
bool
|
||||
WebrtcVideoConduit::UnsetRemoteSSRC(uint32_t ssrc)
|
||||
{
|
||||
unsigned int our_ssrc;
|
||||
if (!GetRemoteSSRC(&our_ssrc)) {
|
||||
// This only fails when we aren't sending, which isn't really an error here
|
||||
return true;
|
||||
}
|
||||
|
||||
if (our_ssrc != ssrc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
while (our_ssrc == ssrc) {
|
||||
our_ssrc = GenerateRandomSSRC();
|
||||
if (our_ssrc == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// There is a (tiny) chance that this new random ssrc will collide with some
|
||||
// other conduit's remote ssrc, in which case that conduit will choose a new
|
||||
// one.
|
||||
SetRemoteSSRC(our_ssrc);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WebrtcVideoConduit::GetRemoteSSRC(unsigned int* ssrc)
|
||||
{
|
||||
|
@ -1428,13 +1478,12 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
|
|||
// Handle un-signalled SSRCs by creating a random one and then when it actually gets set,
|
||||
// we'll destroy and recreate. Simpler than trying to unwind all the logic that assumes
|
||||
// the receive stream is created and started when we ConfigureRecvMediaCodecs()
|
||||
unsigned int ssrc;
|
||||
do {
|
||||
SECStatus rv = PK11_GenerateRandom(reinterpret_cast<unsigned char*>(&ssrc), sizeof(ssrc));
|
||||
if (rv != SECSuccess) {
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
} while (ssrc == 0); // webrtc.org code has fits if you select an SSRC of 0
|
||||
uint32_t ssrc = GenerateRandomSSRC();
|
||||
if (ssrc == 0) {
|
||||
// webrtc.org code has fits if you select an SSRC of 0, so that's how
|
||||
// we signal an error.
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
|
||||
mRecvStreamConfig.rtp.remote_ssrc = ssrc;
|
||||
mRecvSSRC = ssrc;
|
||||
|
@ -1451,13 +1500,12 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
|
|||
auto ssrc = mSendStreamConfig.rtp.ssrcs.front();
|
||||
Unused << NS_WARN_IF(ssrc == mRecvStreamConfig.rtp.remote_ssrc);
|
||||
|
||||
while (ssrc == mRecvStreamConfig.rtp.remote_ssrc || ssrc == 0) {
|
||||
SECStatus rv = PK11_GenerateRandom(reinterpret_cast<unsigned char*>(&ssrc), sizeof(ssrc));
|
||||
if (rv != SECSuccess) {
|
||||
while (ssrc == mRecvStreamConfig.rtp.remote_ssrc) {
|
||||
ssrc = GenerateRandomSSRC();
|
||||
if (ssrc == 0) {
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
}
|
||||
// webrtc.org code has fits if you select an SSRC of 0
|
||||
|
||||
mRecvStreamConfig.rtp.local_ssrc = ssrc;
|
||||
CSFLogDebug(LOGTAG, "%s (%p): Local SSRC 0x%08x (of %u), remote SSRC 0x%08x",
|
||||
|
|
|
@ -275,6 +275,7 @@ public:
|
|||
bool SetLocalSSRCs(const std::vector<unsigned int> & ssrcs) override;
|
||||
bool GetRemoteSSRC(unsigned int* ssrc) override;
|
||||
bool SetRemoteSSRC(unsigned int ssrc) override;
|
||||
bool UnsetRemoteSSRC(uint32_t ssrc) override;
|
||||
bool SetLocalCNAME(const char* cname) override;
|
||||
bool SetLocalMID(const std::string& mid) override;
|
||||
|
||||
|
|
|
@ -880,10 +880,6 @@ pref("media.openUnsupportedTypeWithExternalApp", true);
|
|||
|
||||
pref("dom.keyboardevent.dispatch_during_composition", true);
|
||||
|
||||
#if CPU_ARCH == aarch64
|
||||
pref("javascript.options.native_regexp", false);
|
||||
#endif
|
||||
|
||||
// Ask for permission when enumerating WebRTC devices.
|
||||
pref("media.navigator.permission.device", true);
|
||||
|
||||
|
|
|
@ -581,6 +581,7 @@ def config_status_deps(build_env, build_project):
|
|||
extra_deps = [os.path.join(topobjdir[:-7], '.mozconfig.json')]
|
||||
|
||||
return list(__sandbox__._all_paths) + extra_deps + [
|
||||
os.path.join(topsrcdir, 'CLOBBER'),
|
||||
os.path.join(topsrcdir, 'configure'),
|
||||
os.path.join(topsrcdir, 'js', 'src', 'configure'),
|
||||
os.path.join(topsrcdir, 'configure.in'),
|
||||
|
|
|
@ -711,11 +711,9 @@ class TupBackend(CommonBackend):
|
|||
'PYTHON': self.environment.substs['PYTHON'],
|
||||
'PYTHONDONTWRITEBYTECODE': '1',
|
||||
}
|
||||
cargo_incremental = self.environment.substs.get('CARGO_INCREMENTAL')
|
||||
if cargo_incremental is not None:
|
||||
# TODO (bug 1468527): CARGO_INCREMENTAL produces outputs that Tup
|
||||
# doesn't know about, disable it unconditionally for now.
|
||||
pass # env['CARGO_INCREMENTAL'] = cargo_incremental
|
||||
# TODO (bug 1468527): CARGO_INCREMENTAL produces outputs that Tup
|
||||
# doesn't know about, disable it unconditionally for now.
|
||||
env['CARGO_INCREMENTAL'] = '0'
|
||||
|
||||
rust_simd = self.environment.substs.get('MOZ_RUST_SIMD')
|
||||
if rust_simd is not None:
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[object-in-svg-foreignobject.sub.html]
|
||||
disabled: https://github.com/web-platform-tests/wpt/issues/12282
|
|
@ -20,7 +20,7 @@
|
|||
It uses demo web applications to simulate user actions such as adding to-do items.
|
||||
</p>
|
||||
<p id="screen-size-warning"><strong>
|
||||
Your browser window is too small. For most accurate results, please make the view port size at least 850px by 650px.<br>
|
||||
Your browser window is too small. For most accurate results, please make the viewport size at least 850px by 650px.<br>
|
||||
It's currently <span id="screen-size"></span>.
|
||||
</strong></p>
|
||||
<div class="buttons">
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
StyleBench is a browser benchmark that measures the performance of the style resolution mechanism.
|
||||
</p>
|
||||
<p id="screen-size-warning"><strong>
|
||||
Your browser window is too small. For most accurate results, please make the view port size at least 850px by 650px.<br>
|
||||
Your browser window is too small. For most accurate results, please make the viewport size at least 850px by 650px.<br>
|
||||
It's currently <span id="screen-size"></span>.
|
||||
</strong>
|
||||
<div class="buttons">
|
||||
|
|
|
@ -10,7 +10,6 @@ with Files('**'):
|
|||
DIRS += ['build']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsCWebBrowser.idl',
|
||||
'nsIEmbeddingSiteWindow.idl',
|
||||
'nsIWebBrowser.idl',
|
||||
'nsIWebBrowserChrome.idl',
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#include "nsIWebBrowser.idl"
|
||||
#include "nsIBaseWindow.idl"
|
||||
#include "nsIScrollable.idl"
|
||||
#include "nsITextScroll.idl"
|
||||
|
||||
/*
|
||||
nsCWebBrowser implements:
|
||||
-------------------------
|
||||
nsIWebBrowser
|
||||
nsIDocShellTreeItem
|
||||
nsIWebNavigation
|
||||
nsIWebProgress
|
||||
nsIBaseWindow
|
||||
nsIScrollable
|
||||
nsITextScroll
|
||||
nsIInterfaceRequestor
|
||||
|
||||
|
||||
Outwardly communicates with:
|
||||
----------------------------
|
||||
nsIWebBrowserChrome
|
||||
nsIBaseWindow
|
||||
nsIInterfaceRequestor
|
||||
*/
|
||||
|
||||
%{ C++
|
||||
#include "nsEmbedCID.h"
|
||||
%}
|
|
@ -43,15 +43,4 @@
|
|||
#define NS_PROMPTSERVICE_CONTRACTID \
|
||||
"@mozilla.org/embedcomp/prompt-service;1"
|
||||
|
||||
/**
|
||||
* This contract ID should be implemented by password managers to be able to
|
||||
* override the standard implementation of nsIAuthPrompt2. It will be used as
|
||||
* a service.
|
||||
*
|
||||
* This contract implements the following interfaces:
|
||||
* nsIPromptFactory
|
||||
*/
|
||||
#define NS_PWMGR_AUTHPROMPTFACTORY \
|
||||
"@mozilla.org/passwordmanager/authpromptfactory;1"
|
||||
|
||||
#endif // NSEMBEDCID_H
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "nsISHistoryListener.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIWebBrowserPersist.h"
|
||||
#include "nsCWebBrowserPersist.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "Layers.h"
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
// Interfaces needed
|
||||
#include "nsCWebBrowser.h"
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
|
|
|
@ -989,9 +989,10 @@ function EngineURL(aType, aMethod, aTemplate, aResultDomain) {
|
|||
FAIL("new EngineURL: template uses invalid scheme!", Cr.NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
this.templateHost = templateURI.host;
|
||||
// If no resultDomain was specified in the engine definition file, use the
|
||||
// host from the template.
|
||||
this.resultDomain = aResultDomain || templateURI.host;
|
||||
this.resultDomain = aResultDomain || this.templateHost;
|
||||
}
|
||||
EngineURL.prototype = {
|
||||
|
||||
|
@ -4154,6 +4155,33 @@ SearchService.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
if (!sendSubmissionURL) {
|
||||
// ... or engines that are the same domain as a default engine.
|
||||
let engineHost = engine._getURLOfType(URLTYPE_SEARCH_HTML).templateHost;
|
||||
for (let name in this._engines) {
|
||||
let innerEngine = this._engines[name];
|
||||
if (!innerEngine._isDefault) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let innerEngineURL = innerEngine._getURLOfType(URLTYPE_SEARCH_HTML);
|
||||
if (innerEngineURL.templateHost == engineHost) {
|
||||
sendSubmissionURL = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sendSubmissionURL) {
|
||||
// ... or well known search domains.
|
||||
//
|
||||
// Starts with: www.google., search.aol., yandex.
|
||||
// or
|
||||
// Ends with: search.yahoo.com, .ask.com, .bing.com, .startpage.com, baidu.com, duckduckgo.com
|
||||
const urlTest = /^(?:www\.google\.|search\.aol\.|yandex\.)|(?:search\.yahoo|\.ask|\.bing|\.startpage|\.baidu|\.duckduckgo)\.com$/;
|
||||
sendSubmissionURL = urlTest.test(engineHost);
|
||||
}
|
||||
}
|
||||
|
||||
if (sendSubmissionURL) {
|
||||
let uri = engine._getURLOfType("text/html")
|
||||
.getSubmission("", engine, "searchbar").uri;
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*
|
||||
* Tests covering sending submission URLs for major engines
|
||||
*/
|
||||
|
||||
const SUBMISSION_YES = new Map([
|
||||
["Google1 Test", "https://www.google.com/search?q={searchTerms}"],
|
||||
["Google2 Test", "https://www.google.co.uk/search?q={searchTerms}"],
|
||||
["Yahoo1 Test", "https://search.yahoo.com/search?p={searchTerms}"],
|
||||
["Yahoo2 Test", "https://uk.search.yahoo.com/search?p={searchTerms}"],
|
||||
["AOL1 Test", "https://search.aol.com/aol/search?q={searchTerms}"],
|
||||
["AOL2 Test", "https://search.aol.co.uk/aol/search?q={searchTerms}"],
|
||||
["Yandex1 Test", "https://yandex.ru/search/?text={searchTerms}"],
|
||||
["Yandex2 Test", "https://yandex.com/search/?text{searchTerms}"],
|
||||
["Ask1 Test", "https://www.ask.com/web?q={searchTerms}"],
|
||||
["Ask2 Test", "https://fr.ask.com/web?q={searchTerms}"],
|
||||
["Bing Test", "https://www.bing.com/search?q={searchTerms}"],
|
||||
["Startpage Test", "https://www.startpage.com/do/search?query={searchTerms}"],
|
||||
["DuckDuckGo Test", "https://duckduckgo.com/?q={searchTerms}"],
|
||||
["Baidu Test", "https://www.baidu.com/s?wd={searchTerms}"],
|
||||
]);
|
||||
|
||||
const SUBMISSION_NO = new Map([
|
||||
["Other1 Test", "https://example.com?q={searchTerms}"],
|
||||
["Other2 Test", "https://googlebutnotgoogle.com?q={searchTerms}"],
|
||||
]);
|
||||
|
||||
function addAndMakeDefault(name, searchURL) {
|
||||
Services.search.addEngineWithDetails(name, null, null, null, "GET", searchURL);
|
||||
let engine = Services.search.getEngineByName(name);
|
||||
Services.search.currentEngine = engine;
|
||||
return engine;
|
||||
}
|
||||
|
||||
add_task(async function test() {
|
||||
Assert.ok(!Services.search.isInitialized);
|
||||
|
||||
await asyncInit();
|
||||
|
||||
let engineInfo;
|
||||
let engine;
|
||||
|
||||
for (let [name, searchURL] of SUBMISSION_YES) {
|
||||
engine = addAndMakeDefault(name, searchURL);
|
||||
engineInfo = Services.search.getDefaultEngineInfo();
|
||||
Assert.equal(engineInfo.submissionURL, searchURL.replace("{searchTerms}", ""));
|
||||
Services.search.removeEngine(engine);
|
||||
}
|
||||
|
||||
for (let [name, searchURL] of SUBMISSION_NO) {
|
||||
engine = addAndMakeDefault(name, searchURL);
|
||||
engineInfo = Services.search.getDefaultEngineInfo();
|
||||
Assert.equal(engineInfo.submissionURL, null);
|
||||
Services.search.removeEngine(engine);
|
||||
}
|
||||
});
|
|
@ -101,3 +101,4 @@ skip-if = (verify && !debug && (os == 'linux'))
|
|||
[test_engineUpdate.js]
|
||||
[test_paramSubstitution.js]
|
||||
[test_migrateWebExtensionEngine.js]
|
||||
[test_sendSubmissionURL.js]
|
||||
|
|
|
@ -42,7 +42,7 @@ Structure:
|
|||
name: <string>, // engine name, e.g. "Yahoo"; or "NONE" if no default
|
||||
loadPath: <string>, // where the engine line is located; missing if no default
|
||||
origin: <string>, // 'default', 'verified', 'unverified', or 'invalid'; based on the presence and validity of the engine's loadPath verification hash.
|
||||
submissionURL: <string> // missing if no default or for user-installed engines
|
||||
submissionURL: <string> // set for default engines or well known search domains
|
||||
},
|
||||
searchCohort: <string>, // optional, contains an identifier for any active search A/B experiments
|
||||
e10sEnabled: <bool>, // whether e10s is on, i.e. browser tabs open by default in a different process
|
||||
|
|
|
@ -12,12 +12,33 @@ function setup_test_preference() {
|
|||
|
||||
function checkIsVideoDocumentAutoplay(browser) {
|
||||
return ContentTask.spawn(browser, null, async () => {
|
||||
let video = content.document.getElementsByTagName("video")[0];
|
||||
let played = video && await video.play().then(() => true, () => false);
|
||||
const video = content.document.getElementsByTagName("video")[0];
|
||||
const played = video && await video.play().then(() => true, () => false);
|
||||
ok(played, "Should be able to play in video document.");
|
||||
});
|
||||
}
|
||||
|
||||
async function checkIsIframeVideoDocumentAutoplay(browser) {
|
||||
info("- create iframe video document -");
|
||||
await ContentTask.spawn(browser, PAGE, async (pageURL) => {
|
||||
const iframe = content.document.createElement("iframe");
|
||||
iframe.src = pageURL;
|
||||
content.document.body.appendChild(iframe);
|
||||
const iframeLoaded = new Promise((resolve, reject) => {
|
||||
iframe.addEventListener("load", e => resolve(), {once: true});
|
||||
});
|
||||
await iframeLoaded;
|
||||
});
|
||||
|
||||
info("- check whether iframe video document starts playing -");
|
||||
await ContentTask.spawn(browser, null, async () => {
|
||||
const iframe = content.document.querySelector("iframe");
|
||||
const video = iframe.contentDocument.querySelector("video");
|
||||
ok(video.paused, "Subdoc video should not have played");
|
||||
is(video.played.length, 0, "Should have empty played ranges");
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async () => {
|
||||
await BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
|
@ -31,3 +52,16 @@ add_task(async () => {
|
|||
});
|
||||
});
|
||||
|
||||
add_task(async () => {
|
||||
await BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: "about:blank",
|
||||
}, async (browser) => {
|
||||
info("- setup test preference -");
|
||||
await setup_test_preference();
|
||||
|
||||
info(`- check whether video document in iframe is autoplay -`);
|
||||
await checkIsIframeVideoDocumentAutoplay(browser);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include "nsIScreenManager.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsCWebBrowserPersist.h"
|
||||
#include "nsToolkit.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
|
|
Загрузка…
Ссылка в новой задаче