Merge autoland to mozilla-central. a=merge

This commit is contained in:
Gurzau Raul 2019-03-26 11:51:06 +02:00
Родитель d57d523481 f7e4ecddf4
Коммит a7315d7841
208 изменённых файлов: 3060 добавлений и 1999 удалений

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

@ -27,5 +27,10 @@ git = "https://github.com/hsivonen/packed_simd"
branch = "rust_1_32"
replace-with = "vendored-sources"
[source."https://github.com/CraneStation/target-lexicon"]
git = "https://github.com/glandium/target-lexicon"
branch = "thumbv7neon-v0.2"
replace-with = "vendored-sources"
[source.vendored-sources]
directory = '@top_srcdir@/third_party/rust'

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

@ -55,14 +55,6 @@ module.exports = {
}, {
// TODO: Bug 1246594. Empty this list once the rule has landed for all dirs
"files": [
"docshell/test/chrome/docshell_helpers.js",
"docshell/test/navigation/NavigationUtils.js",
"dom/asmjscache/test/**",
"dom/cache/test/mochitest/test_cache_tons_of_fd.html",
"dom/crypto/test/**",
"dom/indexedDB/test/**",
"dom/localstorage/test/unit/test_migration.js",
"dom/plugins/test/mochitest/head.js",
"gfx/layers/apz/test/mochitest/**",
"mobile/android/components/**",
"mobile/android/modules/**",

10
Cargo.lock сгенерированный
Просмотреть файл

@ -170,7 +170,7 @@ dependencies = [
"cranelift-wasm 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"target-lexicon 0.2.0 (git+https://github.com/glandium/target-lexicon?branch=thumbv7neon-v0.2)",
]
[[package]]
@ -591,7 +591,7 @@ dependencies = [
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"target-lexicon 0.2.0 (git+https://github.com/glandium/target-lexicon?branch=thumbv7neon-v0.2)",
]
[[package]]
@ -614,7 +614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cranelift-codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"target-lexicon 0.2.0 (git+https://github.com/glandium/target-lexicon?branch=thumbv7neon-v0.2)",
]
[[package]]
@ -2804,7 +2804,7 @@ dependencies = [
[[package]]
name = "target-lexicon"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/glandium/target-lexicon?branch=thumbv7neon-v0.2#b2d4b34509abb3e12b1c93d19b8593d02ddeed76"
dependencies = [
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3699,7 +3699,7 @@ dependencies = [
"checksum syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4b5274d4a0a3d2749d5c158dc64d3403e60554dc61194648787ada5212473d"
"checksum syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)" = "734ecc29cd36e8123850d9bf21dfd62ef8300aaa8f879aabaa899721808be37c"
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
"checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9"
"checksum target-lexicon 0.2.0 (git+https://github.com/glandium/target-lexicon?branch=thumbv7neon-v0.2)" = "<none>"
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"

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

@ -62,3 +62,4 @@ serde_derive = { git = "https://github.com/servo/serde", branch = "deserialize_f
winapi = { git = "https://github.com/froydnj/winapi-rs", branch = "aarch64" }
cc = { git = "https://github.com/glandium/cc-rs", branch = "1.0.23-clang-cl-aarch64" }
packed_simd = { git = "https://github.com/hsivonen/packed_simd", branch = "rust_1_32" }
target-lexicon = { git = "https://github.com/glandium/target-lexicon", branch = "thumbv7neon-v0.2" }

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

@ -214,22 +214,23 @@ class NotificationController final : public EventQueue,
* @note The caller must guarantee that the given instance still exists when
* the notification is processed.
*/
template <class Class, class Arg>
template <class Class, class... Args>
inline void HandleNotification(
Class* aInstance, typename TNotification<Class, Arg>::Callback aMethod,
Arg* aArg) {
Class* aInstance,
typename TNotification<Class, Args...>::Callback aMethod,
Args*... aArgs) {
if (!IsUpdatePending()) {
#ifdef A11Y_LOG
if (mozilla::a11y::logging::IsEnabled(
mozilla::a11y::logging::eNotifications))
mozilla::a11y::logging::Text("sync notification processing");
#endif
(aInstance->*aMethod)(aArg);
(aInstance->*aMethod)(aArgs...);
return;
}
RefPtr<Notification> notification =
new TNotification<Class, Arg>(aInstance, aMethod, aArg);
new TNotification<Class, Args...>(aInstance, aMethod, aArgs...);
if (notification && mNotifications.AppendElement(notification))
ScheduleProcessing();
}

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

@ -59,13 +59,13 @@ inline void DocAccessible::BindChildDocument(DocAccessible* aDocument) {
mNotificationController->ScheduleChildDocBinding(aDocument);
}
template <class Class, class Arg>
template <class Class, class... Args>
inline void DocAccessible::HandleNotification(
Class* aInstance, typename TNotification<Class, Arg>::Callback aMethod,
Arg* aArg) {
Class* aInstance, typename TNotification<Class, Args...>::Callback aMethod,
Args*... aArgs) {
if (mNotificationController) {
mNotificationController->HandleNotification<Class, Arg>(aInstance, aMethod,
aArg);
mNotificationController->HandleNotification<Class, Args...>(
aInstance, aMethod, aArgs...);
}
}

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

@ -226,10 +226,10 @@ class DocAccessible : public HyperTextAccessibleWrap,
* notification is processed.
* @see NotificationController::HandleNotification
*/
template <class Class, class Arg>
void HandleNotification(Class* aInstance,
typename TNotification<Class, Arg>::Callback aMethod,
Arg* aArg);
template <class Class, class... Args>
void HandleNotification(
Class* aInstance,
typename TNotification<Class, Args...>::Callback aMethod, Args*... aArgs);
/**
* Return the cached accessible by the given DOM node if it's in subtree of

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

@ -161,7 +161,11 @@ nsresult RootAccessible::AddEventListeners() {
// receive untrusted events (synthetic events generated by untrusted code).
// For example, XBL bindings implementations for elements that are hosted in
// non chrome document fire untrusted events.
nsCOMPtr<EventTarget> nstarget = mDocumentNode;
// We must use the window's parent target in order to receive events from
// iframes and shadow DOM; e.g. ValueChange events from a <select> in an
// iframe or shadow DOM. The root document itself doesn't receive these.
nsPIDOMWindowOuter* window = mDocumentNode->GetWindow();
nsCOMPtr<EventTarget> nstarget = window ? window->GetParentTarget() : nullptr;
if (nstarget) {
for (const char *const *e = kEventTypes, *const *e_end =
@ -177,7 +181,8 @@ nsresult RootAccessible::AddEventListeners() {
}
nsresult RootAccessible::RemoveEventListeners() {
nsCOMPtr<EventTarget> target = mDocumentNode;
nsPIDOMWindowOuter* window = mDocumentNode->GetWindow();
nsCOMPtr<EventTarget> target = window ? window->GetParentTarget() : nullptr;
if (target) {
for (const char *const *e = kEventTypes, *const *e_end =
ArrayEnd(kEventTypes);
@ -203,6 +208,14 @@ void RootAccessible::DocumentActivated(DocAccessible* aDocument) {}
NS_IMETHODIMP
RootAccessible::HandleEvent(Event* aDOMEvent) {
MOZ_ASSERT(aDOMEvent);
if (IsDefunct()) {
// Even though we've been shut down, RemoveEventListeners might not have
// removed the event handlers on the window's parent target if GetWindow
// returned null, so we might still get events here in this case. We should
// just ignore these events.
return NS_OK;
}
nsCOMPtr<nsINode> origTargetNode =
do_QueryInterface(aDOMEvent->GetOriginalTarget());
if (!origTargetNode) return NS_OK;
@ -222,46 +235,41 @@ RootAccessible::HandleEvent(Event* aDOMEvent) {
// Root accessible exists longer than any of its descendant documents so
// that we are guaranteed notification is processed before root accessible
// is destroyed.
document->HandleNotification<RootAccessible, Event>(
this, &RootAccessible::ProcessDOMEvent, aDOMEvent);
// For shadow DOM, GetOriginalTarget on the Event returns null if we
// process the event async, so we must pass the target node as well.
document->HandleNotification<RootAccessible, Event, nsINode>(
this, &RootAccessible::ProcessDOMEvent, aDOMEvent, origTargetNode);
}
return NS_OK;
}
// RootAccessible protected
void RootAccessible::ProcessDOMEvent(Event* aDOMEvent) {
void RootAccessible::ProcessDOMEvent(Event* aDOMEvent, nsINode* aTarget) {
MOZ_ASSERT(aDOMEvent);
nsCOMPtr<nsINode> origTargetNode =
do_QueryInterface(aDOMEvent->GetOriginalTarget());
MOZ_ASSERT(aTarget);
nsAutoString eventType;
aDOMEvent->GetType(eventType);
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eDOMEvents))
logging::DOMEvent("processed", origTargetNode, eventType);
logging::DOMEvent("processed", aTarget, eventType);
#endif
if (!origTargetNode) {
// Original target has ceased to exist.
return;
}
if (eventType.EqualsLiteral("popuphiding")) {
HandlePopupHidingEvent(origTargetNode);
HandlePopupHidingEvent(aTarget);
return;
}
DocAccessible* targetDocument =
GetAccService()->GetDocAccessible(origTargetNode->OwnerDoc());
GetAccService()->GetDocAccessible(aTarget->OwnerDoc());
if (!targetDocument) {
// Document has ceased to exist.
return;
}
Accessible* accessible =
targetDocument->GetAccessibleOrContainer(origTargetNode);
Accessible* accessible = targetDocument->GetAccessibleOrContainer(aTarget);
if (!accessible) return;
#ifdef MOZ_XUL

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

@ -54,7 +54,7 @@ class RootAccessible : public DocAccessibleWrap, public nsIDOMEventListener {
/**
* Process the DOM event.
*/
void ProcessDOMEvent(dom::Event* aEvent);
void ProcessDOMEvent(dom::Event* aDOMEvent, nsINode* aTarget);
/**
* Process "popupshown" event. Used by HandleEvent().

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

@ -121,7 +121,7 @@
[ new invokerChecker(EVENT_TEXT_VALUE_CHANGE, getAccessible(aID)) ];
this.invoke = function changeSelectValue_invoke() {
getNode(aID).focus();
getAccessible(aID).takeFocus();
synthesizeKey(aKey, {}, window);
};
@ -167,6 +167,12 @@
gQueue.push(new changeSelectValue("select", "VK_DOWN", "2nd"));
gQueue.push(new changeSelectValue("select", "3", "3rd"));
let iframeSelect = getAccessible("selectIframe").firstChild.firstChild;
gQueue.push(new changeSelectValue(iframeSelect, "VK_DOWN", "2"));
let shadowSelect = getAccessible("selectShadow").firstChild;
gQueue.push(new changeSelectValue(shadowSelect, "VK_DOWN", "2"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
@ -246,5 +252,24 @@
<option>2nd</option>
<option>3rd</option>
</select>
<iframe id="selectIframe"
src="data:text/html,<select id='iframeSelect'><option>1</option><option>2</option></select>">
</iframe>
<div id="selectShadow"></div>
<script>
let host = document.getElementById("selectShadow");
let shadow = host.attachShadow({mode: "open"});
let select = document.createElement("select");
select.id = "shadowSelect";
let option = document.createElement("option");
option.textContent = "1";
select.appendChild(option);
option = document.createElement("option");
option.textContent = "2";
select.appendChild(option);
shadow.appendChild(select);
</script>
</body>
</html>

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

@ -175,13 +175,11 @@
accesskey="&leaveDOMFullScreen.accesskey;"
label="&leaveDOMFullScreen.label;"
oncommand="gContextMenu.leaveDOMFullScreen();"/>
#ifdef NIGHTLY_BUILD
<menuitem id="context-video-pictureinpicture"
accesskey="&pictureInPicture.accesskey;"
label="&pictureInPicture.label;"
type="checkbox"
oncommand="gContextMenu.mediaCommand('pictureinpicture');"/>
#endif
<menuseparator id="context-media-sep-commands"/>
<menuitem id="context-reloadimage"
label="&reloadImageCmd.label;"

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

@ -135,9 +135,14 @@ var gSync = {
let label = this.syncStrings.GetStringFromName("syncnow.label");
syncIcon.setAttribute("label", label);
syncNow.setAttribute("label", label);
// We start with every menuitem hidden, so that we don't need to init
// the sync UI on windows like pageInfo.xul (see bug 1384856).
// We start with every menuitem hidden (except for the "setup sync" state),
// so that we don't need to init the sync UI on windows like pageInfo.xul
// (see bug 1384856).
// maybeUpdateUIState() also optimizes for this - if we should be in the
// "setup sync" state, that function assumes we are already in it and
// doesn't re-initialize the UI elements.
document.getElementById("sync-setup").hidden = false;
document.getElementById("PanelUI-remotetabs-setupsync").hidden = false;
for (let topic of this._obs) {
Services.obs.addObserver(this, topic, true);

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

@ -718,15 +718,15 @@ html|input.urlbar-input {
#PopupAutoComplete > richlistbox > richlistitem[originaltype="loginsFooter"] {
-moz-box-pack: center;
color: var(--btn-text-color);
color: -moz-fieldText;
min-height: 40px;
border-top: 1px solid rgba(38,38,38,.15);
background-color: #EDEDED;
background-color: hsla(0,0%,80%,.35); /* match arrowpanel-dimmed */;
}
#PopupAutoComplete > richlistbox > richlistitem[originaltype="loginsFooter"]:hover,
#PopupAutoComplete > richlistbox > richlistitem[originaltype="loginsFooter"][selected] {
background-color: #DCDCDE;
background-color: hsla(0,0%,80%,.5); /* match arrowpanel-dimmed-further */
}
#PopupAutoComplete[firstresultstyle="insecureWarning"] {

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

@ -53,7 +53,7 @@ with Files("test/performance/browser_appmenu.js"):
BUG_COMPONENT = ("Firefox", "Menus")
with Files("test/permissions/**"):
BUG_COMPONENT = ("Firefox", "Preferences")
BUG_COMPONENT = ("Firefox", "Site Identity and Permission Panels")
with Files("test/plugins/**"):
BUG_COMPONENT = ("Core", "Plug-ins")
@ -62,7 +62,7 @@ with Files("test/popupNotifications/**"):
BUG_COMPONENT = ("Toolkit", "Notifications and Alerts")
with Files("test/popups/**"):
BUG_COMPONENT = ("Toolkit", "Notifications and Alerts")
BUG_COMPONENT = ("Firefox", "Site Identity and Permission Panels")
with Files("test/referrer/**"):
BUG_COMPONENT = ("Core", "Document Navigation")

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

@ -460,17 +460,26 @@ class TabTracker extends TabTrackerBase {
});
}
} else {
if (!event.originalTarget.parentNode) {
// If the tab is already be destroyed, do nothing.
return;
}
// Save the size of the current tab, since the newly-created tab will
// likely be active by the time the promise below resolves and the
// event is dispatched.
const currentTab = nativeTab.ownerGlobal.gBrowser.selectedTab;
const {frameLoader} = currentTab.linkedBrowser;
const currentTabSize = {
width: frameLoader.lazyWidth,
height: frameLoader.lazyHeight,
};
this.emitCreated(event.originalTarget, currentTabSize);
// We need to delay sending this event until the next tick, since the
// tab can become selected immediately after "TabOpen", then onCreated
// should be fired with `active: true`.
Promise.resolve().then(() => {
if (!event.originalTarget.parentNode) {
// If the tab is already be destroyed, do nothing.
return;
}
this.emitCreated(event.originalTarget, currentTabSize);
});
}
break;
@ -488,8 +497,8 @@ class TabTracker extends TabTrackerBase {
break;
case "TabSelect":
// We need to delay sending this event because it shouldn't fire before
// onRemoved when the active tab is removed.
// Because we are delaying calling emitCreated above, we also need to
// delay sending this event because it shouldn't fire before onCreated.
Promise.resolve().then(() => {
if (!nativeTab.parentNode) {
// If the tab is already be destroyed, do nothing.
@ -501,8 +510,8 @@ class TabTracker extends TabTrackerBase {
case "TabMultiSelect":
if (this.has("tabs-highlighted")) {
// Because we are delaying calling emitActivated above, we also need to
// delay sending this event because it shouldn't fire before onActivated.
// Because we are delaying calling emitCreated above, we also need to
// delay sending this event because it shouldn't fire before onCreated.
Promise.resolve().then(() => {
this.emitHighlighted(event.target.ownerGlobal);
});

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

@ -222,6 +222,7 @@ skip-if = (verify && !debug && (os == 'mac'))
[browser_ext_tabs_move_window.js]
[browser_ext_tabs_move_window_multiple.js]
[browser_ext_tabs_move_window_pinned.js]
[browser_ext_tabs_onCreated.js]
[browser_ext_tabs_onHighlighted.js]
[browser_ext_tabs_onUpdated.js]
[browser_ext_tabs_onUpdated_filter.js]

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

@ -401,13 +401,12 @@ add_task(async function testLastTabRemoval() {
async function background() {
let windowId;
browser.tabs.onCreated.addListener(tab => {
windowId = tab.windowId;
browser.test.assertEq(windowId, tab.windowId,
"expecting onCreated after onRemoved on the same window");
browser.test.sendMessage("tabCreated", `${tab.width}x${tab.height}`);
});
browser.tabs.onRemoved.addListener((tabId, info) => {
browser.test.assertEq(windowId, info.windowId,
"expecting onRemoved after onCreated on the same window");
browser.test.sendMessage("tabRemoved");
windowId = info.windowId;
});
}
@ -427,7 +426,6 @@ add_task(async function testLastTabRemoval() {
const actualDims = await extension.awaitMessage("tabCreated");
is(actualDims, expectedDims, "created tab reports a size same to the removed last tab");
await extension.awaitMessage("tabRemoved");
await extension.unload();
await BrowserTestUtils.closeWindow(newWin);

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

@ -0,0 +1,26 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
/* eslint-disable mozilla/no-arbitrary-setTimeout */
"use strict";
add_task(async function test_onCreated_active() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"],
},
background: function() {
browser.tabs.onCreated.addListener(tab => {
browser.tabs.remove(tab.id);
browser.test.sendMessage("onCreated", tab);
});
},
});
await extension.startup();
BrowserOpenTab();
let tab = await extension.awaitMessage("onCreated");
is(true, tab.active, "Tab should be active");
await extension.unload();
});

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

@ -732,7 +732,14 @@ toolbarbutton[constrain-size="true"][cui-areatype="menu-panel"] > .toolbarbutton
}
.PanelUI-fxa-signin-instruction-label {
/* Use 'lighter' font for this to de-emphasize it compared to the title.
* We use 300 on Linux because 100 is too light (lacks contrast with
* the background) for some fonts in combination with anti-aliasing. */
%if defined(XP_MACOSX) || defined(XP_WIN)
font-weight: lighter;
%else
font-weight: 300;
%endif
}
.fxa-avatar-subpanel {

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

@ -9,15 +9,7 @@
#include <stdio.h>
#include <mozilla/Assertions.h>
/* GLIBCXX_3.4.8 is from gcc 4.1.1 (111691)
GLIBCXX_3.4.9 is from gcc 4.2.0 (111690)
GLIBCXX_3.4.10 is from gcc 4.3.0 (126287)
GLIBCXX_3.4.11 is from gcc 4.4.0 (133006)
GLIBCXX_3.4.12 is from gcc 4.4.1 (147138)
GLIBCXX_3.4.13 is from gcc 4.4.2 (151127)
GLIBCXX_3.4.14 is from gcc 4.5.0 (151126)
GLIBCXX_3.4.15 is from gcc 4.6.0 (160071)
GLIBCXX_3.4.16 is from gcc 4.6.1 (172240)
/* GLIBCXX_3.4.16 is from gcc 4.6.1 (172240)
GLIBCXX_3.4.17 is from gcc 4.7.0 (174383)
GLIBCXX_3.4.18 is from gcc 4.8.0 (190787)
GLIBCXX_3.4.19 is from gcc 4.8.1 (199309)
@ -26,8 +18,8 @@
GLIBCXX_3.4.22 is from gcc 6.0 (222482)
This file adds the necessary compatibility tricks to avoid symbols with
version GLIBCXX_3.4.16 and bigger, keeping binary compatibility with
libstdc++ 4.6.1.
version GLIBCXX_3.4.17 and bigger, keeping binary compatibility with
libstdc++ 4.7.
WARNING: all symbols from this file must be defined weak when they
overlap with libstdc++.

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

@ -95,6 +95,8 @@ const PAGE_TYPES = {
};
const PREFERENCES = {
// Preference that drives the display of the "Tabs" category on This Firefox.
LOCAL_TAB_DEBUGGING_ENABLED: "devtools.aboutdebugging.local-tab-debugging",
// Preference that drives the display of the "Processes" debug target category.
PROCESS_DEBUGGING_ENABLED: "devtools.aboutdebugging.process-debugging",
// Preference that drives the display of system addons in about:debugging.

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

@ -13,6 +13,11 @@ function isProcessDebuggingSupported() {
return Services.prefs.getBoolPref(PREFERENCES.PROCESS_DEBUGGING_ENABLED, false);
}
// Process target debugging is disabled by default.
function isLocalTabDebuggingSupported() {
return Services.prefs.getBoolPref(PREFERENCES.LOCAL_TAB_DEBUGGING_ENABLED, false);
}
const ALL_DEBUG_TARGET_PANES = [
DEBUG_TARGET_PANE.INSTALLED_EXTENSION,
...(isProcessDebuggingSupported() ? [DEBUG_TARGET_PANE.PROCESSES] : []),
@ -27,11 +32,13 @@ const ALL_DEBUG_TARGET_PANES = [
const REMOTE_DEBUG_TARGET_PANES = ALL_DEBUG_TARGET_PANES.filter(p =>
p !== DEBUG_TARGET_PANE.TEMPORARY_EXTENSION);
// Main process debugging is not available for This Firefox.
// At the moment only the main process is listed under processes, so remove the category
// for this runtime.
const THIS_FIREFOX_DEBUG_TARGET_PANES = ALL_DEBUG_TARGET_PANES.filter(p =>
p !== DEBUG_TARGET_PANE.PROCESSES);
const THIS_FIREFOX_DEBUG_TARGET_PANES = ALL_DEBUG_TARGET_PANES
// Main process debugging is not available for This Firefox.
// At the moment only the main process is listed under processes, so remove the category
// for this runtime.
.filter(p => p !== DEBUG_TARGET_PANE.PROCESSES)
// Showing tab targets for This Firefox is behind a preference.
.filter(p => p !== DEBUG_TARGET_PANE.TAB || isLocalTabDebuggingSupported());
const SUPPORTED_TARGET_PANE_BY_RUNTIME = {
[RUNTIMES.THIS_FIREFOX]: THIS_FIREFOX_DEBUG_TARGET_PANES,

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

@ -13,8 +13,15 @@ const RUNTIME_APP_NAME = "TestApp";
// Test that the expected supported categories are displayed for USB runtimes.
add_task(async function() {
const mocks = new Mocks();
await checkTargetPanes({ enableLocalTabs: false }, mocks);
const { document, tab, window } = await openAboutDebugging();
info("Check that enableLocalTabs has no impact on the categories displayed for remote" +
" runtimes.");
await checkTargetPanes({ enableLocalTabs: true }, mocks);
});
async function checkTargetPanes({ enableLocalTabs }, mocks) {
const { document, tab, window } = await openAboutDebugging({ enableLocalTabs });
await selectThisFirefoxPage(document, window.AboutDebugging.store);
mocks.createUSBRuntime(RUNTIME_ID, {
@ -51,4 +58,4 @@ add_task(async function() {
await waitUntil(() => !findSidebarItemByText(RUNTIME_DEVICE_NAME, document));
await removeTab(tab);
});
}

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

@ -3,11 +3,6 @@
"use strict";
/**
* Check that the This Firefox page is displayed by default when opening the new
* about:debugging and that it contains the expected categories.
*/
const EXPECTED_TARGET_PANES = [
"Temporary Extensions",
"Extensions",
@ -17,30 +12,56 @@ const EXPECTED_TARGET_PANES = [
"Other Workers",
];
add_task(async function() {
const { document, tab, window } = await openAboutDebugging();
/**
* Check that the This Firefox runtime page contains the expected categories if
* the preference to enable local tab debugging is true.
*/
add_task(async function testThisFirefoxWithLocalTab() {
const { document, tab, window } = await openAboutDebugging({ enableLocalTabs: true });
await selectThisFirefoxPage(document, window.AboutDebugging.store);
// Expect all target panes to be displayed including tabs.
await checkThisFirefoxTargetPanes(document, EXPECTED_TARGET_PANES);
await removeTab(tab);
});
/**
* Check that the This Firefox runtime page contains the expected categories if
* the preference to enable local tab debugging is false.
*/
add_task(async function testThisFirefoxWithoutLocalTab() {
const { document, tab, window } = await openAboutDebugging({ enableLocalTabs: false });
await selectThisFirefoxPage(document, window.AboutDebugging.store);
// Expect all target panes but tabs to be displayed.
const expectedTargetPanesWithoutTabs = EXPECTED_TARGET_PANES.filter(p => p !== "Tabs");
await checkThisFirefoxTargetPanes(document, expectedTargetPanesWithoutTabs);
await removeTab(tab);
});
async function checkThisFirefoxTargetPanes(doc, expectedTargetPanes) {
const win = doc.ownerGlobal;
// Check that the selected sidebar item is "This Firefox"/"This Nightly"/...
const selectedSidebarItem = document.querySelector(".js-sidebar-item-selected");
const selectedSidebarItem = doc.querySelector(".js-sidebar-item-selected");
ok(selectedSidebarItem, "An item is selected in the sidebar");
const thisFirefoxString = getThisFirefoxString(window);
const thisFirefoxString = getThisFirefoxString(win);
is(selectedSidebarItem.textContent, thisFirefoxString,
"The selected sidebar item is " + thisFirefoxString);
const paneTitlesEls = document.querySelectorAll(".js-debug-target-pane-title");
is(paneTitlesEls.length, EXPECTED_TARGET_PANES.length,
"This Firefox has the expecte number of debug target categories");
const paneTitlesEls = doc.querySelectorAll(".js-debug-target-pane-title");
is(paneTitlesEls.length, expectedTargetPanes.length,
"This Firefox has the expected number of debug target categories");
const paneTitles = [...paneTitlesEls].map(el => el.textContent);
for (let i = 0; i < EXPECTED_TARGET_PANES.length; i++) {
const expectedPaneTitle = EXPECTED_TARGET_PANES[i];
for (let i = 0; i < expectedTargetPanes.length; i++) {
const expectedPaneTitle = expectedTargetPanes[i];
const actualPaneTitle = paneTitles[i];
ok(actualPaneTitle.startsWith(expectedPaneTitle),
`Expected debug target category found: ${ expectedPaneTitle }`);
}
}
await removeTab(tab);
});

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

@ -43,11 +43,15 @@ async function enableNewAboutDebugging() {
await pushPref("devtools.aboutdebugging.new-enabled", true);
}
async function openAboutDebugging({ enableWorkerUpdates } = {}) {
async function openAboutDebugging({ enableWorkerUpdates, enableLocalTabs = true } = {}) {
if (!enableWorkerUpdates) {
silenceWorkerUpdates();
}
// This preference changes value depending on the build type, tests need to use a
// consistent value regarless of the build used.
await pushPref("devtools.aboutdebugging.local-tab-debugging", enableLocalTabs);
await enableNewAboutDebugging();
info("opening about:debugging");

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

@ -341,6 +341,14 @@ pref("devtools.responsive.showUserAgentInput", false);
// Enable new about:debugging.
pref("devtools.aboutdebugging.new-enabled", false);
// Show tab debug targets for This Firefox (on by default for local builds).
#ifdef MOZILLA_OFFICIAL
pref("devtools.aboutdebugging.local-tab-debugging", false);
#else
pref("devtools.aboutdebugging.local-tab-debugging", true);
#endif
// Show process debug targets.
pref("devtools.aboutdebugging.process-debugging", false);
// Stringified array of network locations that users can connect to.

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

@ -15,7 +15,7 @@ const {
} = require("devtools/shared/layout/utils");
const defer = require("devtools/shared/defer");
const {
isContentStylesheet,
isAuthorStylesheet,
getCSSStyleRules,
} = require("devtools/shared/inspector/css-logic");
const InspectorUtils = require("InspectorUtils");
@ -773,7 +773,7 @@ var TestActor = exports.TestActor = protocol.ActorClassWithSpec(testSpec, {
const sheet = domRules[i].parentStyleSheet;
sheets.push({
href: sheet.href,
isContentSheet: isContentStylesheet(sheet),
isContentSheet: isAuthorStylesheet(sheet),
});
}

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

@ -35,13 +35,20 @@ const {
getBindingElementAndPseudo,
getCSSStyleRules,
l10n,
isContentStylesheet,
isAgentStylesheet,
isAuthorStylesheet,
isUserStylesheet,
shortSource,
FILTER,
STATUS,
} = require("devtools/shared/inspector/css-logic");
const InspectorUtils = require("InspectorUtils");
const COMPAREMODE = {
"BOOLEAN": "bool",
"INTEGER": "int",
};
/**
* @param {function} isInherited A function that determines if the CSS property
* is inherited.
@ -170,8 +177,7 @@ CssLogic.prototype = {
// Update the CssSheet objects.
this.forEachSheet(function(sheet) {
sheet._sheetAllowed = -1;
if (sheet.contentSheet && sheet.sheetAllowed) {
if (sheet.authorSheet && sheet.sheetAllowed) {
ruleCount += sheet.ruleCount;
}
}, this);
@ -281,7 +287,7 @@ CssLogic.prototype = {
const sheets = [];
this.forEachSheet(function(sheet) {
if (sheet.contentSheet) {
if (sheet.authorSheet) {
sheets.push(sheet);
}
}, this);
@ -324,10 +330,7 @@ CssLogic.prototype = {
let sheetFound = false;
if (cacheId in this._sheets) {
for (let i = 0, numSheets = this._sheets[cacheId].length;
i < numSheets;
i++) {
sheet = this._sheets[cacheId][i];
for (sheet of this._sheets[cacheId]) {
if (sheet.domSheet === domSheet) {
if (index != -1) {
sheet.index = index;
@ -344,7 +347,7 @@ CssLogic.prototype = {
}
sheet = new CssSheet(this, domSheet, index);
if (sheet.sheetAllowed && sheet.contentSheet) {
if (sheet.sheetAllowed && sheet.authorSheet) {
this._ruleCount += sheet.ruleCount;
}
@ -437,19 +440,18 @@ CssLogic.prototype = {
this._matchedSelectors = [];
this._passId++;
for (let i = 0; i < this._matchedRules.length; i++) {
const rule = this._matchedRules[i][0];
const status = this._matchedRules[i][1];
for (const matchedRule of this._matchedRules) {
const [rule, status, distance] = matchedRule;
rule.selectors.forEach(function(selector) {
if (selector._matchId !== this._matchId &&
(selector.elementStyle ||
(selector.inlineStyle ||
this.selectorMatchesElement(rule.domRule,
selector.selectorIndex))) {
selector._matchId = this._matchId;
this._matchedSelectors.push([ selector, status ]);
this._matchedSelectors.push([ selector, status, distance ]);
if (callback) {
callback.call(scope, selector, status);
callback.call(scope, selector, status, distance);
}
}
}, this);
@ -532,6 +534,13 @@ CssLogic.prototype = {
const filter = this.sourceFilter;
let sheetIndex = 0;
// distance is used to tell us how close an ancestor is to an element e.g.
// 0: The rule is directly applied to the current element.
// -1: The rule is inherited from the current element's first parent.
// -2: The rule is inherited from the current element's second parent.
// etc.
let distance = 0;
this._matchId++;
this._passId++;
this._matchedRules = [];
@ -552,9 +561,7 @@ CssLogic.prototype = {
}
// getCSSStyleRules can return null with a shadow DOM element.
const numDomRules = domRules ? domRules.length : 0;
for (let i = 0; i < numDomRules; i++) {
const domRule = domRules[i];
for (const domRule of domRules || []) {
if (domRule.type !== CSSRule.STYLE_RULE) {
continue;
}
@ -565,7 +572,7 @@ CssLogic.prototype = {
sheet._passId = this._passId;
}
if (filter === FILTER.USER && !sheet.contentSheet) {
if (filter === FILTER.USER && !sheet.authorSheet) {
continue;
}
@ -576,7 +583,7 @@ CssLogic.prototype = {
rule._matchId = this._matchId;
rule._passId = this._passId;
this._matchedRules.push([rule, status]);
this._matchedRules.push([rule, status, distance]);
}
// Add element.style information.
@ -584,8 +591,10 @@ CssLogic.prototype = {
const rule = new CssRule(null, { style: element.style }, element);
rule._matchId = this._matchId;
rule._passId = this._passId;
this._matchedRules.push([rule, status]);
this._matchedRules.push([rule, status, distance]);
}
distance--;
} while ((element = element.parentNode) &&
element.nodeType === nodeConstants.ELEMENT_NODE);
},
@ -720,7 +729,7 @@ CssLogic.href = function(sheet) {
function CssSheet(cssLogic, domSheet, index) {
this._cssLogic = cssLogic;
this.domSheet = domSheet;
this.index = this.contentSheet ? index : -100 * index;
this.index = this.authorSheet ? index : -100 * index;
// Cache of the sheets href. Cached by the getter.
this._href = null;
@ -738,23 +747,49 @@ function CssSheet(cssLogic, domSheet, index) {
CssSheet.prototype = {
_passId: null,
_contentSheet: null,
_agentSheet: null,
_authorSheet: null,
_userSheet: null,
/**
* Tells if the stylesheet is provided by the browser or not.
* Check if the stylesheet is an agent stylesheet (provided by the browser).
*
* @return {boolean} false if this is a browser-provided stylesheet, or true
* otherwise.
* @return {boolean} true if this is an agent stylesheet, false otherwise.
*/
get contentSheet() {
if (this._contentSheet === null) {
this._contentSheet = isContentStylesheet(this.domSheet);
get agentSheet() {
if (this._agentSheet === null) {
this._agentSheet = isAgentStylesheet(this.domSheet);
}
return this._contentSheet;
return this._agentSheet;
},
/**
* Tells if the stylesheet is disabled or not.
* Check if the stylesheet is an author stylesheet (provided by the content page).
*
* @return {boolean} true if this is an author stylesheet, false otherwise.
*/
get authorSheet() {
if (this._authorSheet === null) {
this._authorSheet = isAuthorStylesheet(this.domSheet);
}
return this._authorSheet;
},
/**
* Check if the stylesheet is a user stylesheet (provided by userChrome.css or
* userContent.css).
*
* @return {boolean} true if this is a user stylesheet, false otherwise.
*/
get userSheet() {
if (this._userSheet === null) {
this._userSheet = isUserStylesheet(this.domSheet);
}
return this._userSheet;
},
/**
* Check if the stylesheet is disabled or not.
* @return {boolean} true if this stylesheet is disabled, or false otherwise.
*/
get disabled() {
@ -803,7 +838,7 @@ CssSheet.prototype = {
this._sheetAllowed = true;
const filter = this._cssLogic.sourceFilter;
if (filter === FILTER.USER && !this.contentSheet) {
if (filter === FILTER.USER && !this.authorSheet) {
this._sheetAllowed = false;
}
if (filter !== FILTER.USER && filter !== FILTER.UA) {
@ -861,10 +896,7 @@ CssSheet.prototype = {
let ruleFound = false;
if (cacheId in this._rules) {
for (let i = 0, rulesLen = this._rules[cacheId].length;
i < rulesLen;
i++) {
rule = this._rules[cacheId][i];
for (rule of this._rules[cacheId]) {
if (rule.domRule === domRule) {
ruleFound = true;
break;
@ -921,13 +953,17 @@ function CssRule(cssSheet, domRule, element) {
this.source += " @media " + this.mediaText;
}
this.href = this._cssSheet.href;
this.contentRule = this._cssSheet.contentSheet;
this.authorRule = this._cssSheet.authorSheet;
this.userRule = this._cssSheet.userSheet;
this.agentRule = this._cssSheet.agentSheet;
} else if (element) {
this._selectors = [ new CssSelector(this, "@element.style", 0) ];
this.line = -1;
this.source = l10n("rule.sourceElement");
this.href = "#";
this.contentRule = true;
this.authorRule = true;
this.userRule = false;
this.agentRule = false;
this.sourceElement = element;
}
}
@ -1027,7 +1063,7 @@ CssRule.prototype = {
function CssSelector(cssRule, selector, index) {
this.cssRule = cssRule;
this.text = selector;
this.elementStyle = this.text == "@element.style";
this.inlineStyle = this.text == "@element.style";
this._specificity = null;
this.selectorIndex = index;
}
@ -1069,13 +1105,31 @@ CssSelector.prototype = {
},
/**
* Check if the selector comes from a browser-provided stylesheet.
* Check if the selector comes from an agent stylesheet (provided by the browser).
*
* @return {boolean} true if the selector comes from a content-provided
* stylesheet, or false otherwise.
* @return {boolean} true if this is an agent stylesheet, false otherwise.
*/
get contentRule() {
return this.cssRule.contentRule;
get agentRule() {
return this.cssRule.agentRule;
},
/**
* Check if the selector comes from an author stylesheet (provided by the content page).
*
* @return {boolean} true if this is an author stylesheet, false otherwise.
*/
get authorRule() {
return this.cssRule.authorRule;
},
/**
* Check if the selector comes from a user stylesheet (provided by userChrome.css or
* userContent.css).
*
* @return {boolean} true if this is a user stylesheet, false otherwise.
*/
get userRule() {
return this.cssRule.userRule;
},
/**
@ -1127,7 +1181,7 @@ CssSelector.prototype = {
* @return {Number} The selector's specificity.
*/
get specificity() {
if (this.elementStyle) {
if (this.inlineStyle) {
// We can't ask specificity from DOMUtils as element styles don't provide
// CSSStyleRule interface DOMUtils expect. However, specificity of element
// style is constant, 1,0,0,0 or 0x40000000, just return the constant
@ -1135,13 +1189,11 @@ CssSelector.prototype = {
return 0x40000000;
}
if (this._specificity) {
return this._specificity;
if (typeof this._specificity !== "number") {
this._specificity = InspectorUtils.getSpecificity(this.cssRule.domRule,
this.selectorIndex);
}
this._specificity = InspectorUtils.getSpecificity(this.cssRule.domRule,
this.selectorIndex);
return this._specificity;
},
@ -1232,11 +1284,6 @@ CssPropertyInfo.prototype = {
// Sort the selectors by how well they match the given element.
this._matchedSelectors.sort(function(selectorInfo1, selectorInfo2) {
if (selectorInfo1.status > selectorInfo2.status) {
return -1;
} else if (selectorInfo2.status > selectorInfo1.status) {
return 1;
}
return selectorInfo1.compareTo(selectorInfo2);
});
@ -1254,7 +1301,7 @@ CssPropertyInfo.prototype = {
* @param {CssSelector} selector the matched CssSelector object.
* @param {STATUS} status the CssSelector match status.
*/
_processMatchedSelector: function(selector, status) {
_processMatchedSelector: function(selector, status, distance) {
const cssRule = selector.cssRule;
const value = cssRule.getPropertyValue(this.property);
if (value &&
@ -1262,7 +1309,7 @@ CssPropertyInfo.prototype = {
(status == STATUS.PARENT_MATCH &&
this._isInherited(this.property)))) {
const selectorInfo = new CssSelectorInfo(selector, this.property, value,
status);
status, distance);
this._matchedSelectors.push(selectorInfo);
}
},
@ -1311,10 +1358,11 @@ CssPropertyInfo.prototype = {
* @param {STATUS} status The selector match status.
* @constructor
*/
function CssSelectorInfo(selector, property, value, status) {
function CssSelectorInfo(selector, property, value, status, distance) {
this.selector = selector;
this.property = property;
this.status = status;
this.distance = distance;
this.value = value;
const priority = this.selector.cssRule.getPropertyPriority(this.property);
this.important = (priority === "important");
@ -1358,8 +1406,8 @@ CssSelectorInfo.prototype = {
* @return {boolean} true if the CssSelector comes from element.style, or
* false otherwise.
*/
get elementStyle() {
return this.selector.elementStyle;
get inlineStyle() {
return this.selector.inlineStyle;
},
/**
@ -1418,74 +1466,152 @@ CssSelectorInfo.prototype = {
* @return {boolean} true if the selector comes from a browser-provided
* stylesheet, or false otherwise.
*/
get contentRule() {
return this.selector.contentRule;
get agentRule() {
return this.selector.agentRule;
},
/**
* Check if the selector comes from a webpage-provided stylesheet.
*
* @return {boolean} true if the selector comes from a webpage-provided
* stylesheet, or false otherwise.
*/
get authorRule() {
return this.selector.authorRule;
},
/**
* Check if the selector comes from a user stylesheet (userChrome.css or
* userContent.css).
*
* @return {boolean} true if the selector comes from a webpage-provided
* stylesheet, or false otherwise.
*/
get userRule() {
return this.selector.userRule;
},
/**
* Compare the current CssSelectorInfo instance to another instance, based on
* specificity information.
* the CSS cascade (see https://www.w3.org/TR/css-cascade-4/#cascading):
*
* @param {CssSelectorInfo} that The instance to compare ourselves against.
* @return number -1, 0, 1 depending on how that compares with this.
* The cascade sorts declarations according to the following criteria, in
* descending order of priority:
*
* - Rules targetting a node directly must always win over rules targetting an
* ancestor.
*
* - Origin and Importance
* The origin of a declaration is based on where it comes from and its
* importance is whether or not it is declared !important (see below). For
* our purposes here we can safely ignore Transition declarations and
* Animation declarations.
* The precedence of the various origins is, in descending order:
* - Transition declarations (ignored)
* - Important user agent declarations (User-Agent & !important)
* - Important user declarations (User & !important)
* - Important author declarations (Author & !important)
* - Animation declarations (ignored)
* - Normal author declarations (Author, normal weight)
* - Normal user declarations (User, normal weight)
* - Normal user agent declarations (User-Agent, normal weight)
*
* - Specificity (see https://www.w3.org/TR/selectors/#specificity)
* - A selectors specificity is calculated for a given element as follows:
* - count the number of ID selectors in the selector (= A)
* - count the number of class selectors, attributes selectors, and
* pseudo-classes in the selector (= B)
* - count the number of type selectors and pseudo-elements in the
* selector (= C)
* - ignore the universal selector
* - So "UL OL LI.red" has a specificity of a=0 b=1 c=3.
*
* - Order of Appearance
* - The last declaration in document order wins. For this purpose:
* - Declarations from imported style sheets are ordered as if their style
* sheets were substituted in place of the @import rule.
* - Declarations from style sheets independently linked by the
* originating document are treated as if they were concatenated in
* linking order, as determined by the host document language.
* - Declarations from style attributes are ordered according to the
* document order of the element the style attribute appears on, and are
* all placed after any style sheets.
* - We use three methods to calculate this:
* - Sheet index
* - Rule line
* - Rule column
*
* @param {CssSelectorInfo} that
* The instance to compare ourselves against.
* @return {Number}
* -1, 0, 1 depending on how that compares with this.
*/
compareTo: function(that) {
if (!this.contentRule && that.contentRule) {
return 1;
}
if (this.contentRule && !that.contentRule) {
return -1;
let current = null;
// Rules targetting the node must always win over rules targetting a node's
// ancestor.
current = this.compare(that, "distance", COMPAREMODE.INTEGER);
if (current) {
return current;
}
if (this.elementStyle && !that.elementStyle) {
if (!this.important && that.important) {
return 1;
if (this.important) {
// User-Agent & !important
// User & !important
// Author & !important
for (const propName of ["agentRule", "userRule", "authorRule"]) {
current = this.compare(that, propName, COMPAREMODE.BOOLEAN);
if (current) {
return current;
}
}
return -1;
}
if (!this.elementStyle && that.elementStyle) {
if (this.important && !that.important) {
return -1;
// Author, normal weight
// User, normal weight
// User-Agent, normal weight
for (const propName of ["authorRule", "userRule", "agentRule"]) {
current = this.compare(that, propName, COMPAREMODE.BOOLEAN);
if (current) {
return current;
}
return 1;
}
if (this.important && !that.important) {
return -1;
}
if (that.important && !this.important) {
return 1;
// Specificity
// Sheet index
// Rule line
// Rule column
for (const propName of ["specificity", "sheetIndex", "ruleLine", "ruleColumn"]) {
current = this.compare(that, propName, COMPAREMODE.INTEGER);
if (current) {
return current;
}
}
if (this.specificity > that.specificity) {
return -1;
}
if (that.specificity > this.specificity) {
return 1;
}
// A rule has been compared against itself so return 0.
return 0;
},
if (this.sheetIndex > that.sheetIndex) {
return -1;
compare: function(that, propertyName, type) {
switch (type) {
case COMPAREMODE.BOOLEAN:
if (this[propertyName] && !that[propertyName]) {
return -1;
}
if (!this[propertyName] && that[propertyName]) {
return 1;
}
break;
case COMPAREMODE.INTEGER:
if (this[propertyName] > that[propertyName]) {
return -1;
}
if (this[propertyName] < that[propertyName]) {
return 1;
}
break;
}
if (that.sheetIndex > this.sheetIndex) {
return 1;
}
if (this.ruleLine > that.ruleLine) {
return -1;
}
if (that.ruleLine > this.ruleLine) {
return 1;
}
if (this.ruleColumn > that.ruleColumn) {
return -1;
}
if (that.ruleColumn > this.ruleColumn) {
return 1;
}
return 0;
},

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

@ -483,7 +483,7 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
// node.
getSelectorSource: function(selectorInfo, relativeTo) {
let result = selectorInfo.selector.text;
if (selectorInfo.elementStyle) {
if (selectorInfo.inlineStyle) {
const source = selectorInfo.sourceElement;
if (source === relativeTo) {
result = "this";
@ -642,7 +642,7 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
for (let i = domRules.length - 1; i >= 0; i--) {
const domRule = domRules[i];
const isSystem = !SharedCssLogic.isContentStylesheet(domRule.parentStyleSheet);
const isSystem = !SharedCssLogic.isAuthorStylesheet(domRule.parentStyleSheet);
if (isSystem && options.filter != SharedCssLogic.FILTER.UA) {
continue;

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

@ -398,7 +398,7 @@ var StyleSheetActor = protocol.ActorClassWithSpec(styleSheetSpec, {
nodeHref: docHref,
disabled: this.rawSheet.disabled,
title: this.rawSheet.title,
system: !CssLogic.isContentStylesheet(this.rawSheet),
system: !CssLogic.isAuthorStylesheet(this.rawSheet),
styleSheetIndex: this.styleSheetIndex,
sourceMapURL: this.rawSheet.sourceMapURL,
};

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

@ -112,14 +112,36 @@ exports.CSSRuleTypeName = {
exports.l10n = name => styleInspectorL10N.getStr(name);
/**
* Is the given property sheet a content stylesheet?
* Is the given property sheet an author stylesheet?
*
* @param {CSSStyleSheet} sheet a stylesheet
* @return {boolean} true if the given stylesheet is a content stylesheet,
* @return {boolean} true if the given stylesheet is an author stylesheet,
* false otherwise.
*/
exports.isContentStylesheet = function(sheet) {
return sheet.parsingMode !== "agent";
exports.isAuthorStylesheet = function(sheet) {
return sheet.parsingMode === "author";
};
/**
* Is the given property sheet a user stylesheet?
*
* @param {CSSStyleSheet} sheet a stylesheet
* @return {boolean} true if the given stylesheet is a user stylesheet,
* false otherwise.
*/
exports.isUserStylesheet = function(sheet) {
return sheet.parsingMode === "user";
};
/**
* Is the given property sheet a agent stylesheet?
*
* @param {CSSStyleSheet} sheet a stylesheet
* @return {boolean} true if the given stylesheet is a agent stylesheet,
* false otherwise.
*/
exports.isAgentStylesheet = function(sheet) {
return sheet.parsingMode === "agent";
};
/**

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

@ -112,25 +112,25 @@ function doPageNavigation(params) {
// Do some sanity checking on arguments.
if (back && forward)
throw "Can't specify both back and forward";
throw new Error("Can't specify both back and forward");
if (back && uri)
throw "Can't specify both back and a uri";
throw new Error("Can't specify both back and a uri");
if (forward && uri)
throw "Can't specify both forward and a uri";
throw new Error("Can't specify both forward and a uri");
if (reload && (forward || back || uri))
throw "Can't specify reload and another navigation type";
throw new Error("Can't specify reload and another navigation type");
if (!back && !forward && !uri && !reload && !waitOnly)
throw "Must specify back or foward or reload or uri";
throw new Error("Must specify back or foward or reload or uri");
if (params.onNavComplete && eventsToListenFor.length == 0)
throw "Can't use onNavComplete when eventsToListenFor == []";
throw new Error("Can't use onNavComplete when eventsToListenFor == []");
if (params.preventBFCache && eventsToListenFor.length == 0)
throw "Can't use preventBFCache when eventsToListenFor == []";
throw new Error("Can't use preventBFCache when eventsToListenFor == []");
if (params.preventBFCache && waitOnly)
throw "Can't prevent bfcaching when only waiting for events";
throw new Error("Can't prevent bfcaching when only waiting for events");
if (waitOnly && typeof(params.onNavComplete) == "undefined")
throw "Must specify onNavComplete when specifying waitForEventsOnly";
throw new Error("Must specify onNavComplete when specifying waitForEventsOnly");
if (waitOnly && (back || forward || reload || uri))
throw "Can't specify a navigation type when using waitForEventsOnly";
throw new Error("Can't specify a navigation type when using waitForEventsOnly");
for (let anEventType of eventsToListenFor) {
let eventFound = false;
if ( (anEventType == "pageshow") && (!gExpectedEvents) )
@ -148,8 +148,8 @@ function doPageNavigation(params) {
}
}
if (!eventFound)
throw "Event type " + anEventType + " is specified in " +
"eventsToListenFor, but not in expectedEvents";
throw new Error(`Event type ${anEventType} is specified in ` +
"eventsToListenFor, but not in expectedEvents");
}
// If the test explicitly sets .eventsToListenFor to [], don't wait for any
@ -180,7 +180,7 @@ function doPageNavigation(params) {
} else if (waitOnly) {
gNavType = NAV_NONE;
} else {
throw "No valid navigation type passed to doPageNavigation!";
throw new Error("No valid navigation type passed to doPageNavigation!");
}
// If we're listening for events and there is an .onNavComplete callback,

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

@ -163,7 +163,7 @@ function xpcWaitForFinishedFrames(callback, numFrames) {
}
if (finishedFrameCount > numFrames)
throw "Too many frames loaded.";
throw new Error("Too many frames loaded.");
}
var finishedWindows = [];

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

@ -26,14 +26,14 @@ var f2Main = f2(this, null, i32.buffer);
if (this.jsFuns)
ok(jsFuns.isAsmJSFunction(f2Main), "f2.main is an asm.js function");
if (f2Main(4) !== 6)
throw "f2Main(4)";
throw new Error("f2Main(4)");
if (f2Main(100) !== 4950)
throw "f2.main(100)";
throw new Error("f2.main(100)");
var sum = (((i32.length - 1) * i32.length) / 2);
if (f2Main(i32.length) !== sum)
throw "f2.main(" + i32.length + ")";
throw new Error(`f2.main(${i32.length})`);
if (f2Main(i32.length + 100) !== sum)
throw "f2.main(" + i32.length + ")";
throw new Error(`f2.main(${i32.length})`);
/* eslint-disable no-unused-vars,no-shadow */
function f3(stdlib, foreign, buffer) {
@ -59,7 +59,7 @@ var begin;
var lastSum;
function done(sumInner) {
if (sumInner !== ((lastSum + 499500)|0))
throw "bad sum: " + sumInner + ", " + lastSum + ", " + ((lastSum + 499500)|0);
throw new Error(`bad sum: ${sumInner}, ${lastSum}, ${((lastSum + 499500)|0)}`);
lastSum = sumInner;
return (Date.now() - begin) > 3000;
}
@ -70,7 +70,7 @@ if (this.jsFuns)
begin = Date.now();
lastSum = 0;
if (f3Main() !== lastSum)
throw "f3.main()";
throw new Error("f3.main()");
if (!this.jsFuns)
postMessage("ok");

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

@ -48,7 +48,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=929236
SimpleTest.finish();
break;
default:
throw "huh?";
throw new Error("huh?");
}
}

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

@ -53,7 +53,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=944821
finishedCount++;
if (finishedCount < 1 || finishedCount > 2 * N) {
throw "Huh?!";
throw new Error("Huh?!");
} else if (finishedCount == N) {
for (let i = 0; i < N; i++)
evalAsync(codes[i]);

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

@ -56,7 +56,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=941830
document.body.appendChild(script);
break;
default:
throw "Huh?";
throw new Error("Huh?");
}
};

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

@ -54,30 +54,30 @@ async function testCreateTonsOfFD() {
try {
cached_response_array = await Promise.all(promise_array);
} catch (e) {
throw ("Fail to open tons of files with error: " + e);
throw new Error("Fail to open tons of files with error: " + e);
}
if (cached_response_array.length != number_of_fd) {
throw ("Fail to cache.match the cached responses");
throw new Error("Fail to cache.match the cached responses");
}
info("Stage C: Consume the cached body");
for (let i = 0; i < number_of_fd; ++i) {
if (!cached_response_array[i]) {
// Reduce the checking message.
throw ("The cached response doesn't exist");
throw new Error("The cached response doesn't exist");
}
let bodyText = "";
try {
bodyText = await cached_response_array[i].text();
} catch (e) {
throw ("Fail to consume the cached response's body with error: " + e);
throw new Error("Fail to consume the cached response's body with error: " + e);
}
if (bodyText != body) {
// Reduce the checking message.
throw ("The cached body doeen't be the same as original one");
throw new Error("The cached body doeen't be the same as original one");
}
}

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

@ -49,7 +49,7 @@ TestArray.addTest(
var that = this;
var alg = {
get name() {
throw "Oh no, no name!";
throw new Error("Oh no, no name!");
},
};
@ -70,14 +70,14 @@ TestArray.addTest(
function doExport(x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
throw new Error("Invalid key; missing field(s)");
} else if ((x.algorithm.name != alg) ||
(x.algorithm.length != 8 * tv.raw.length) ||
(x.type != "secret") ||
(!x.extractable) ||
(x.usages.length != 1) ||
(x.usages[0] != "encrypt")) {
throw "Invalid key: incorrect key data";
throw new Error("Invalid key: incorrect key data");
}
return crypto.subtle.exportKey("raw", x);
}
@ -136,7 +136,7 @@ TestArray.addTest(
function doExport(x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
throw new Error("Invalid key; missing field(s)");
} else if ((x.algorithm.name != alg.name) ||
(x.algorithm.hash.name != alg.hash) ||
(x.algorithm.modulusLength != 512) ||
@ -145,7 +145,7 @@ TestArray.addTest(
(!x.extractable) ||
(x.usages.length != 1) ||
(x.usages[0] != "sign")) {
throw "Invalid key: incorrect key data";
throw new Error("Invalid key: incorrect key data");
}
return crypto.subtle.exportKey("pkcs8", x);
}
@ -183,7 +183,7 @@ TestArray.addTest(
function doExport(x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
throw new Error("Invalid key; missing field(s)");
} else if ((x.algorithm.name != alg.name) ||
(x.algorithm.modulusLength != 1024) ||
(x.algorithm.publicExponent.byteLength != 3) ||
@ -191,7 +191,7 @@ TestArray.addTest(
(!x.extractable) ||
(x.usages.length != 1) ||
(x.usages[0] != "verify")) {
throw "Invalid key: incorrect key data";
throw new Error("Invalid key: incorrect key data");
}
return crypto.subtle.exportKey("spki", x);
}

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

@ -72,7 +72,7 @@ TestArray.addTest(
.then(function(x) {
// Deriving less bytes works.
if (x.byteLength != 2) {
throw "should have derived two bytes";
throw new Error("should have derived two bytes");
}
})
// Deriving more than the curve yields doesn't.
@ -257,7 +257,7 @@ TestArray.addTest(
(tp.crv != x.crv) &&
(tp.x != x.x) &&
(tp.y != x.y)) {
throw "exported public key doesn't match";
throw new Error("exported public key doesn't match");
}
}, error(that))
.then(doExportPriv, error(that))
@ -341,12 +341,12 @@ TestArray.addTest(
return crypto.subtle.deriveKey({ name: "ECDH", public: pubKey }, privKey, algDerived, false, ["sign", "verify"])
.then(function(x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
throw new Error("Invalid key; missing field(s)");
}
// 512 bit is the default for HMAC-SHA1.
if (x.algorithm.length != 512) {
throw "Invalid key; incorrect length";
throw new Error("Invalid key; incorrect length");
}
return x;
@ -395,7 +395,7 @@ TestArray.addTest(
return derived.then(function(x) {
if (!util.memcmp(x, tv.ecdh_p256.spki)) {
throw "exported key is invalid";
throw new Error("exported key is invalid");
}
if (keys.length) {

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

@ -73,7 +73,7 @@ TestArray.addTest(
function doDerive(x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
throw new Error("Invalid key; missing field(s)");
}
var algo = {
@ -101,7 +101,7 @@ TestArray.addTest(
function doDerive(x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
throw new Error("Invalid key; missing field(s)");
}
var algo = {
@ -130,7 +130,7 @@ TestArray.addTest(
function doDerive(x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
throw new Error("Invalid key; missing field(s)");
}
var algo = {
@ -148,11 +148,11 @@ TestArray.addTest(
return crypto.subtle.deriveKey(algo, x, algDerived, false, ["sign", "verify"])
.then(function(y) {
if (!hasKeyFields(y)) {
throw "Invalid key; missing field(s)";
throw new Error("Invalid key; missing field(s)");
}
if (y.algorithm.length != 512) {
throw "Invalid key; incorrect length";
throw new Error("Invalid key; incorrect length");
}
return y;
@ -214,7 +214,7 @@ TestArray.addTest(
function doDerive(x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
throw new Error("Invalid key; missing field(s)");
}
var algo = {
@ -243,7 +243,7 @@ TestArray.addTest(
function doDerive(x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
throw new Error("Invalid key; missing field(s)");
}
var algo = {
@ -272,7 +272,7 @@ TestArray.addTest(
function doDerive(x) {
if (!hasKeyFields(x)) {
throw "Invalid key; missing field(s)";
throw new Error("Invalid key; missing field(s)");
}
var deriveAlg = {

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

@ -62,7 +62,7 @@
let transaction = request.transaction;
transaction.oncomplete = unexpectedSuccessHandler;
transaction.onabort = grabEventAndContinueHandler;
throw "STOP";
throw new Error("STOP");
};
let event = yield undefined;
@ -106,7 +106,7 @@
request = objectStore.add({}, 1);
request.onsuccess = function(event) {
throw "foo";
throw new Error("foo");
};
event = yield undefined;
@ -155,7 +155,7 @@
request.onsuccess = unexpectedSuccessHandler;
request.onerror = function(event) {
event.preventDefault();
throw "STOP";
throw new Error("STOP");
};
event = yield undefined;

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

@ -45,7 +45,7 @@
function dummyWorkerScript() {
/* eslint-env worker */
onmessage = function(event) {
throw ("Shouldn't be called!");
throw new Error("Shouldn't be called!");
};
}

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

@ -188,22 +188,22 @@ function compareKeys(k1, k2) {
function addPermission(permission, url)
{
throw "addPermission";
throw new Error("addPermission");
}
function removePermission(permission, url)
{
throw "removePermission";
throw new Error("removePermission");
}
function allowIndexedDB(url)
{
throw "allowIndexedDB";
throw new Error("allowIndexedDB");
}
function disallowIndexedDB(url)
{
throw "disallowIndexedDB";
throw new Error("disallowIndexedDB");
}
function enableExperimental()

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

@ -115,7 +115,7 @@ async function testSteps() {
}
default: {
throw ("Unknown type: " + type);
throw new Error("Unknown type: " + type);
}
}

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

@ -26,8 +26,7 @@ GraphRunner::GraphRunner(MediaStreamGraphImpl* aGraph)
mGraph(aGraph),
mStateEnd(0),
mStillProcessing(true),
mShutdown(false),
mStarted(false),
mThreadState(ThreadState::Wait),
// Note that mThread needs to be initialized last, as it may pre-empt the
// thread running this ctor and enter Run() with uninitialized members.
mThread(PR_CreateThread(PR_SYSTEM_THREAD, &Start, this,
@ -38,33 +37,31 @@ GraphRunner::GraphRunner(MediaStreamGraphImpl* aGraph)
GraphRunner::~GraphRunner() {
MOZ_COUNT_DTOR(GraphRunner);
#ifdef DEBUG
{
MonitorAutoLock lock(mMonitor);
MOZ_ASSERT(mShutdown);
}
#endif
PR_JoinThread(mThread);
MOZ_ASSERT(mThreadState == ThreadState::Shutdown);
}
void GraphRunner::Shutdown() {
MonitorAutoLock lock(mMonitor);
mShutdown = true;
mMonitor.Notify();
{
MonitorAutoLock lock(mMonitor);
MOZ_ASSERT(mThreadState == ThreadState::Wait);
mThreadState = ThreadState::Shutdown;
mMonitor.Notify();
}
// We need to wait for runner thread shutdown here for the sake of the
// xpcomWillShutdown case, so that the main thread is not shut down before
// cleanup messages are sent for objects destroyed in
// CycleCollectedJSContext shutdown.
PR_JoinThread(mThread);
mThread = nullptr;
}
bool GraphRunner::OneIteration(GraphTime aStateEnd) {
TRACE_AUDIO_CALLBACK();
MonitorAutoLock lock(mMonitor);
MOZ_ASSERT(!mShutdown);
MOZ_ASSERT(mThreadState == ThreadState::Wait);
mStateEnd = aStateEnd;
if (!mStarted) {
mMonitor.Wait();
MOZ_ASSERT(mStarted);
}
#ifdef DEBUG
if (auto audioDriver = mGraph->CurrentDriver()->AsAudioCallbackDriver()) {
mAudioDriverThreadId = audioDriver->ThreadId();
@ -75,9 +72,13 @@ bool GraphRunner::OneIteration(GraphTime aStateEnd) {
MOZ_CRASH("Unknown GraphDriver");
}
#endif
mMonitor.Notify(); // Signal that mStateEnd was updated
mMonitor.Wait(); // Wait for mStillProcessing to update
// Signal that mStateEnd was updated
mThreadState = ThreadState::Run;
mMonitor.Notify();
// Wait for mStillProcessing to update
do {
mMonitor.Wait();
} while (mThreadState == ThreadState::Run);
#ifdef DEBUG
mAudioDriverThreadId = std::thread::id();
@ -90,17 +91,18 @@ bool GraphRunner::OneIteration(GraphTime aStateEnd) {
void GraphRunner::Run() {
PR_SetCurrentThreadName("GraphRunner");
MonitorAutoLock lock(mMonitor);
mStarted = true;
mMonitor.Notify(); // Signal that mStarted was set, in case the audio
// callback is already waiting for us
while (true) {
mMonitor.Wait(); // Wait for mStateEnd or mShutdown to update
if (mShutdown) {
while (mThreadState == ThreadState::Wait) {
mMonitor.Wait(); // Wait for mStateEnd to update or for shutdown
}
if (mThreadState == ThreadState::Shutdown) {
break;
}
TRACE();
mStillProcessing = mGraph->OneIterationImpl(mStateEnd);
mMonitor.Notify(); // Signal that mStillProcessing was updated
// Signal that mStillProcessing was updated
mThreadState = ThreadState::Wait;
mMonitor.Notify();
}
dom::WorkletThread::DeleteCycleCollectedJSContext();

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

@ -65,13 +65,22 @@ class GraphRunner {
GraphTime mStateEnd;
// Reply from mGraph's OneIteration. Protected by mMonitor.
bool mStillProcessing;
// True after Shutdown(). Protected by mMonitor.
bool mShutdown;
// True after mThread has started running and has entered its main loop.
// Protected by mMonitor.
bool mStarted;
// The thread running mGraph.
PRThread* const mThread;
enum class ThreadState {
Wait, // Waiting for a message. This is the initial state.
// A transition from Run back to Wait occurs on the runner
// thread after it processes as far as mStateEnd and sets
// mStillProcessing.
Run, // Set on driver thread after each mStateEnd update.
Shutdown, // Set when Shutdown() is called on main thread.
};
// Protected by mMonitor until set to Shutdown, after which this is not
// modified.
ThreadState mThreadState;
// The thread running mGraph. Set on construction, after other members are
// initialized. Cleared at the end of Shutdown().
PRThread* mThread;
#ifdef DEBUG
// Set to mGraph's audio callback driver's thread id, if run by an

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

@ -13,8 +13,10 @@ function convertToRTCStatsReport(dict) {
});
}
let report = {};
appendStats(dict.inboundRTPStreamStats, report);
appendStats(dict.outboundRTPStreamStats, report);
appendStats(dict.inboundRtpStreamStats, report);
appendStats(dict.outboundRtpStreamStats, report);
appendStats(dict.remoteInboundRtpStreamStats, report);
appendStats(dict.remoteOutboundRtpStreamStats, report);
appendStats(dict.rtpContributingSourceStats, report);
appendStats(dict.mediaStreamTrackStats, report);
appendStats(dict.mediaStreamStats, report);

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

@ -41,7 +41,7 @@ class VideoConverterListener {
virtual void OnVideoFrameConverted(const webrtc::VideoFrame& aVideoFrame) = 0;
protected:
virtual ~VideoConverterListener() {}
virtual ~VideoConverterListener() = default;
};
// An async video frame format converter.
@ -69,7 +69,7 @@ class VideoFrameConverter {
void QueueVideoChunk(const VideoChunk& aChunk, bool aForceBlack) {
gfx::IntSize size = aChunk.mFrame.GetIntrinsicSize();
if (size.width == 0 || size.width == 0) {
if (size.width == 0 || size.height == 0) {
return;
}
@ -95,8 +95,8 @@ class VideoFrameConverter {
mPacingTimer->WaitUntil(t, __func__)
->Then(mTaskQueue, __func__,
[self = RefPtr<VideoFrameConverter>(this), this,
image = RefPtr<layers::Image>(aChunk.mFrame.GetImage()),
t = std::move(t), size = std::move(size), aForceBlack] {
image = RefPtr<layers::Image>(aChunk.mFrame.GetImage()), t,
size, aForceBlack]() mutable {
QueueForProcessing(std::move(image), t, size, aForceBlack);
},
[] {});
@ -229,7 +229,7 @@ class VideoFrameConverter {
mLastFrameQueuedForProcessing = aTime;
nsresult rv = mTaskQueue->Dispatch(
NewRunnableMethod<StoreCopyPassByRRef<RefPtr<layers::Image>>, TimeStamp,
NewRunnableMethod<StoreCopyPassByLRef<RefPtr<layers::Image>>, TimeStamp,
gfx::IntSize, bool>(
"VideoFrameConverter::ProcessVideoFrame", this,
&VideoFrameConverter::ProcessVideoFrame, std::move(aImage), aTime,
@ -238,7 +238,7 @@ class VideoFrameConverter {
Unused << rv;
}
void ProcessVideoFrame(RefPtr<layers::Image> aImage, TimeStamp aTime,
void ProcessVideoFrame(const RefPtr<layers::Image>& aImage, TimeStamp aTime,
gfx::IntSize aSize, bool aForceBlack) {
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());

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

@ -427,7 +427,28 @@ void VideoTrackEncoder::AppendVideoSegment(VideoSegment&& aSegment) {
return;
}
mIncomingBuffer.AppendFrom(&aSegment);
for (VideoSegment::ConstChunkIterator iter(aSegment); !iter.IsEnded();
iter.Next()) {
if (iter->IsNull()) {
// A null image was sent. This is a signal from the source that we should
// clear any images buffered in the future.
mIncomingBuffer.Clear();
continue; // Don't append iter, as it is null.
}
if (VideoChunk* c = mIncomingBuffer.GetLastChunk()) {
if (iter->mTimeStamp < c->mTimeStamp) {
// Time went backwards. This can happen when a MediaDecoder seeks.
// We need to handle this by removing any frames buffered in the future
// and start over at iter->mTimeStamp.
mIncomingBuffer.Clear();
}
}
mIncomingBuffer.AppendFrame(do_AddRef(iter->mFrame.GetImage()),
iter->mFrame.GetIntrinsicSize(),
iter->mFrame.GetPrincipalHandle(),
iter->mFrame.GetForceBlack(), iter->mTimeStamp);
}
aSegment.Clear();
}
void VideoTrackEncoder::TakeTrackData(VideoSegment& aSegment) {
@ -575,8 +596,6 @@ void VideoTrackEncoder::AdvanceCurrentTime(const TimeStamp& aTime) {
return;
}
MOZ_ASSERT(!mStartTime.IsNull());
if (mSuspended) {
TRACK_LOG(
LogLevel::Verbose,

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

@ -62,9 +62,9 @@ class TestVP8TrackEncoder : public VP8TrackEncoder {
(NS_SUCCEEDED(result) && !aParam.mShouldSucceed)) {
return ::testing::AssertionFailure()
<< " width = " << aParam.mWidth << " height = " << aParam.mHeight;
} else {
return ::testing::AssertionSuccess();
}
return ::testing::AssertionSuccess();
}
};
@ -83,9 +83,9 @@ TEST(VP8VideoTrackEncoder, Initialization) {
{true, 1280, 720} // Standard HD
};
for (size_t i = 0; i < ArrayLength(params); i++) {
for (const InitParam& param : params) {
TestVP8TrackEncoder encoder;
EXPECT_TRUE(encoder.TestInit(params[i]));
EXPECT_TRUE(encoder.TestInit(param));
}
}
@ -99,22 +99,23 @@ TEST(VP8VideoTrackEncoder, FetchMetaData) {
{true, 1280, 720} // Standard HD
};
for (size_t i = 0; i < ArrayLength(params); i++) {
for (const InitParam& param : params) {
TestVP8TrackEncoder encoder;
EXPECT_TRUE(encoder.TestInit(params[i]));
EXPECT_TRUE(encoder.TestInit(param));
RefPtr<TrackMetadataBase> meta = encoder.GetMetadata();
RefPtr<VP8Metadata> vp8Meta(static_cast<VP8Metadata*>(meta.get()));
// METADATA should be depend on how to initiate encoder.
EXPECT_TRUE(vp8Meta->mWidth == params[i].mWidth);
EXPECT_TRUE(vp8Meta->mHeight == params[i].mHeight);
EXPECT_EQ(vp8Meta->mWidth, param.mWidth);
EXPECT_EQ(vp8Meta->mHeight, param.mHeight);
}
}
// Encode test
TEST(VP8VideoTrackEncoder, FrameEncode) {
TestVP8TrackEncoder encoder;
TimeStamp now = TimeStamp::Now();
// Create YUV images as source.
nsTArray<RefPtr<Image>> images;
@ -127,7 +128,6 @@ TEST(VP8VideoTrackEncoder, FrameEncode) {
// Put generated YUV frame into video segment.
// Duration of each frame is 1 second.
VideoSegment segment;
TimeStamp now = TimeStamp::Now();
for (nsTArray<RefPtr<Image>>::size_type i = 0; i < images.Length(); i++) {
RefPtr<Image> image = images[i];
segment.AppendFrame(image.forget(), generator.GetSize(),
@ -147,12 +147,12 @@ TEST(VP8VideoTrackEncoder, FrameEncode) {
// Test that encoding a single frame gives useful output.
TEST(VP8VideoTrackEncoder, SingleFrameEncode) {
TestVP8TrackEncoder encoder;
// Pass a half-second frame to the encoder.
TimeStamp now = TimeStamp::Now();
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
// Pass a half-second frame to the encoder.
VideoSegment segment;
TimeStamp now = TimeStamp::Now();
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -181,12 +181,12 @@ TEST(VP8VideoTrackEncoder, SingleFrameEncode) {
// Test that encoding a couple of identical images gives useful output.
TEST(VP8VideoTrackEncoder, SameFrameEncode) {
TestVP8TrackEncoder encoder;
// Pass 15 100ms frames to the encoder.
TimeStamp now = TimeStamp::Now();
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
// Pass 15 100ms frames to the encoder.
RefPtr<Image> image = generator.GenerateI420Image();
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
for (uint32_t i = 0; i < 15; ++i) {
segment.AppendFrame(do_AddRef(image), generator.GetSize(),
@ -219,10 +219,10 @@ TEST(VP8VideoTrackEncoder, SkippedFrames) {
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
// Pass 100 frames of the shortest possible duration where we don't get
// rounding errors between input/output rate.
VideoSegment segment;
for (uint32_t i = 0; i < 100; ++i) {
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
@ -254,10 +254,10 @@ TEST(VP8VideoTrackEncoder, RoundingErrorFramesEncode) {
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
// Pass nine frames with timestamps not expressable in 90kHz sample rate,
// then one frame to make the total duration one second.
VideoSegment segment;
uint32_t usPerFrame = 99999; // 99.999ms
for (uint32_t i = 0; i < 9; ++i) {
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
@ -292,10 +292,10 @@ TEST(VP8VideoTrackEncoder, RoundingErrorFramesEncode) {
// Test that we're encoding timestamps rather than durations.
TEST(VP8VideoTrackEncoder, TimestampFrameEncode) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -334,7 +334,6 @@ TEST(VP8VideoTrackEncoder, TimestampFrameEncode) {
// Test that we're compensating for drift when encoding.
TEST(VP8VideoTrackEncoder, DriftingFrameEncode) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
@ -383,35 +382,44 @@ TEST(VP8VideoTrackEncoder, DriftingFrameEncode) {
// Test that suspending an encoding works.
TEST(VP8VideoTrackEncoder, Suspended) {
TestVP8TrackEncoder encoder;
TimeStamp now = TimeStamp::Now();
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
// Pass 3 frames with duration 0.1s. We suspend before and resume after the
// second frame.
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
encoder.SetStartOffset(now);
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.1));
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
encoder.SetStartOffset(now);
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.1));
}
encoder.Suspend(now + TimeDuration::FromSeconds(0.1));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromSeconds(0.1));
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.2));
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromSeconds(0.1));
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.2));
}
encoder.Resume(now + TimeDuration::FromSeconds(0.2));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromSeconds(0.2));
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.3));
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromSeconds(0.2));
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.3));
}
encoder.NotifyEndOfStream();
@ -435,26 +443,32 @@ TEST(VP8VideoTrackEncoder, Suspended) {
// Test that ending a track while the video track encoder is suspended works.
TEST(VP8VideoTrackEncoder, SuspendedUntilEnd) {
TestVP8TrackEncoder encoder;
// Pass 2 frames with duration 0.1s. We suspend before the second frame.
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
encoder.SetStartOffset(now);
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.1));
// Pass 2 frames with duration 0.1s. We suspend before the second frame.
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
encoder.SetStartOffset(now);
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.1));
}
encoder.Suspend(now + TimeDuration::FromSeconds(0.1));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromSeconds(0.1));
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.2));
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromSeconds(0.1));
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.2));
}
encoder.NotifyEndOfStream();
@ -478,13 +492,12 @@ TEST(VP8VideoTrackEncoder, SuspendedUntilEnd) {
// Test that ending a track that was always suspended works.
TEST(VP8VideoTrackEncoder, AlwaysSuspended) {
TestVP8TrackEncoder encoder;
// Suspend and then pass a frame with duration 2s.
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
// Suspend and then pass a frame with duration 2s.
encoder.Suspend(now);
VideoSegment segment;
@ -510,28 +523,33 @@ TEST(VP8VideoTrackEncoder, AlwaysSuspended) {
// Test that encoding a track that is suspended in the beginning works.
TEST(VP8VideoTrackEncoder, SuspendedBeginning) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
// Suspend and pass a frame with duration 0.5s. Then resume and pass one more.
encoder.Suspend(now);
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
encoder.SetStartOffset(now);
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.5));
encoder.SetStartOffset(now);
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.5));
}
encoder.Resume(now + TimeDuration::FromSeconds(0.5));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromSeconds(0.5));
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(1));
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromSeconds(0.5));
encoder.AppendVideoSegment(std::move(segment));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(1));
}
encoder.NotifyEndOfStream();
@ -556,30 +574,35 @@ TEST(VP8VideoTrackEncoder, SuspendedBeginning) {
// works.
TEST(VP8VideoTrackEncoder, SuspendedOverlap) {
TestVP8TrackEncoder encoder;
// Pass a 1s frame and suspend after 0.5s.
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
encoder.SetStartOffset(now);
encoder.AppendVideoSegment(std::move(segment));
{
// Pass a 1s frame and suspend after 0.5s.
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
encoder.SetStartOffset(now);
encoder.AppendVideoSegment(std::move(segment));
}
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(0.5));
encoder.Suspend(now + TimeDuration::FromSeconds(0.5));
// Pass another 1s frame and resume after 0.3 of this new frame.
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromSeconds(1));
encoder.AppendVideoSegment(std::move(segment));
{
// Pass another 1s frame and resume after 0.3 of this new frame.
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromSeconds(1));
encoder.AppendVideoSegment(std::move(segment));
}
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(1.3));
encoder.Resume(now + TimeDuration::FromSeconds(1.3));
encoder.AdvanceCurrentTime(now + TimeDuration::FromSeconds(2));
encoder.NotifyEndOfStream();
EncodedFrameContainer container;
@ -599,11 +622,11 @@ TEST(VP8VideoTrackEncoder, SuspendedOverlap) {
// Test that ending a track in the middle of already pushed data works.
TEST(VP8VideoTrackEncoder, PrematureEnding) {
TestVP8TrackEncoder encoder;
// Pass a 1s frame and end the track after 0.5s.
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
// Pass a 1s frame and end the track after 0.5s.
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -629,12 +652,12 @@ TEST(VP8VideoTrackEncoder, PrematureEnding) {
// Test that a track that starts at t > 0 works as expected.
TEST(VP8VideoTrackEncoder, DelayedStart) {
TestVP8TrackEncoder encoder;
// Pass a 2s frame, start (pass first CurrentTime) at 0.5s, end at 1s.
// Should result in a 0.5s encoding.
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
// Pass a 2s frame, start (pass first CurrentTime) at 0.5s, end at 1s.
// Should result in a 0.5s encoding.
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -661,12 +684,12 @@ TEST(VP8VideoTrackEncoder, DelayedStart) {
// SetStartOffset comes after AppendVideoSegment.
TEST(VP8VideoTrackEncoder, DelayedStartOtherEventOrder) {
TestVP8TrackEncoder encoder;
// Pass a 2s frame, start (pass first CurrentTime) at 0.5s, end at 1s.
// Should result in a 0.5s encoding.
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
// Pass a 2s frame, start (pass first CurrentTime) at 0.5s, end at 1s.
// Should result in a 0.5s encoding.
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -692,12 +715,12 @@ TEST(VP8VideoTrackEncoder, DelayedStartOtherEventOrder) {
// Test that a track that starts at t >>> 0 works as expected.
TEST(VP8VideoTrackEncoder, VeryDelayedStart) {
TestVP8TrackEncoder encoder;
// Pass a 1s frame, start (pass first CurrentTime) at 10s, end at 10.5s.
// Should result in a 0.5s encoding.
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
// Pass a 1s frame, start (pass first CurrentTime) at 10s, end at 10.5s.
// Should result in a 0.5s encoding.
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -724,14 +747,15 @@ TEST(VP8VideoTrackEncoder, VeryDelayedStart) {
// second.
TEST(VP8VideoTrackEncoder, LongFramesReEncoded) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
// Pass a frame at t=0 and start encoding.
// Advancing the current time by 1.5s should encode a 1s frame.
// Advancing the current time by another 9.5s should encode another 10 1s
// frames.
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -777,13 +801,13 @@ TEST(VP8VideoTrackEncoder, LongFramesReEncoded) {
// as expected. Short here means shorter than the default (1s).
TEST(VP8VideoTrackEncoder, ShortKeyFrameInterval) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
// Give the encoder a keyframe interval of 500ms.
// Pass frames at 0, 400ms, 600ms, 750ms, 900ms, 1100ms
// Expected keys: ^ ^^^^^ ^^^^^^
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -846,13 +870,13 @@ TEST(VP8VideoTrackEncoder, ShortKeyFrameInterval) {
// as expected. Long here means longer than the default (1s).
TEST(VP8VideoTrackEncoder, LongKeyFrameInterval) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
// Give the encoder a keyframe interval of 2000ms.
// Pass frames at 0, 600ms, 900ms, 1100ms, 1900ms, 2100ms
// Expected keys: ^ ^^^^^^ ^^^^^^
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -915,12 +939,12 @@ TEST(VP8VideoTrackEncoder, LongKeyFrameInterval) {
// as expected. Default interval should be 1000ms.
TEST(VP8VideoTrackEncoder, DefaultKeyFrameInterval) {
TestVP8TrackEncoder encoder;
// Pass frames at 0, 600ms, 900ms, 1100ms, 1900ms, 2100ms
// Expected keys: ^ ^^^^^^ ^^^^^^
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
TimeStamp now = TimeStamp::Now();
// Pass frames at 0, 600ms, 900ms, 1100ms, 1900ms, 2100ms
// Expected keys: ^ ^^^^^^ ^^^^^^
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -982,6 +1006,10 @@ TEST(VP8VideoTrackEncoder, DefaultKeyFrameInterval) {
// encodes keyframes as expected.
TEST(VP8VideoTrackEncoder, DynamicKeyFrameIntervalChanges) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
// Set keyframe interval to 100ms.
// Pass frames at 0, 100ms, 120ms, 130ms, 200ms, 300ms
@ -994,79 +1022,84 @@ TEST(VP8VideoTrackEncoder, DynamicKeyFrameIntervalChanges) {
// Then decrease keyframe interval to 200ms.
// Pass frames at 2500ms, 2600ms, 2800ms, 2900ms
// Expected keys: ^^^^^^ ^^^^^^
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(100));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(120));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(130));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(200));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(300));
// The underlying encoder only gets passed frame N when frame N+1 is known,
// so we pass in the next frame *before* the keyframe interval change.
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(500));
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(100));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(120));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(130));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(200));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(300));
encoder.SetStartOffset(now);
encoder.SetKeyFrameInterval(100);
encoder.AppendVideoSegment(std::move(segment));
// The underlying encoder only gets passed frame N when frame N+1 is known,
// so we pass in the next frame *before* the keyframe interval change.
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(500));
encoder.SetStartOffset(now);
encoder.SetKeyFrameInterval(100);
encoder.AppendVideoSegment(std::move(segment));
}
// Advancing 501ms, so the first bit of the frame starting at 500ms is
// included.
encoder.AdvanceCurrentTime(now + TimeDuration::FromMilliseconds(501));
ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(1300));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(1400));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(2400));
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(1300));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(1400));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(2400));
// The underlying encoder only gets passed frame N when frame N+1 is known,
// so we pass in the next frame *before* the keyframe interval change.
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(2500));
// The underlying encoder only gets passed frame N when frame N+1 is known,
// so we pass in the next frame *before* the keyframe interval change.
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(2500));
encoder.SetKeyFrameInterval(1100);
encoder.AppendVideoSegment(std::move(segment));
encoder.SetKeyFrameInterval(1100);
encoder.AppendVideoSegment(std::move(segment));
}
// Advancing 2000ms from 501ms to 2501ms
encoder.AdvanceCurrentTime(now + TimeDuration::FromMilliseconds(2501));
ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(2600));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(2800));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(2900));
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(2600));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(2800));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(2900));
encoder.SetKeyFrameInterval(200);
encoder.AppendVideoSegment(std::move(segment));
encoder.SetKeyFrameInterval(200);
encoder.AppendVideoSegment(std::move(segment));
}
// Advancing 499ms (compensating back 1ms from the first advancement)
// from 2501ms to 3000ms.
@ -1142,16 +1175,17 @@ TEST(VP8VideoTrackEncoder, DynamicKeyFrameIntervalChanges) {
// frames as expected.
TEST(VP8VideoTrackEncoder, DisableOnFrameTime) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
// Pass a frame in at t=0.
// Pass another frame in at t=100ms.
// Disable the track at t=100ms.
// Stop encoding at t=200ms.
// Should yield 2 frames, 1 real; 1 black.
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -1185,16 +1219,17 @@ TEST(VP8VideoTrackEncoder, DisableOnFrameTime) {
// frames as expected.
TEST(VP8VideoTrackEncoder, DisableBetweenFrames) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
// Pass a frame in at t=0.
// Disable the track at t=50ms.
// Pass another frame in at t=100ms.
// Stop encoding at t=200ms.
// Should yield 3 frames, 1 real [0, 50); 2 black [50, 100) and [100, 200).
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -1228,6 +1263,10 @@ TEST(VP8VideoTrackEncoder, DisableBetweenFrames) {
// frames as expected.
TEST(VP8VideoTrackEncoder, EnableOnFrameTime) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
// Disable the track at t=0.
// Pass a frame in at t=0.
@ -1235,10 +1274,7 @@ TEST(VP8VideoTrackEncoder, EnableOnFrameTime) {
// Enable the track at t=100ms.
// Stop encoding at t=200ms.
// Should yield 2 frames, 1 black; 1 real.
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -1273,6 +1309,10 @@ TEST(VP8VideoTrackEncoder, EnableOnFrameTime) {
// frames as expected.
TEST(VP8VideoTrackEncoder, EnableBetweenFrames) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
// Disable the track at t=0.
// Pass a frame in at t=0.
@ -1280,10 +1320,7 @@ TEST(VP8VideoTrackEncoder, EnableBetweenFrames) {
// Pass another frame in at t=100ms.
// Stop encoding at t=200ms.
// Should yield 3 frames, 1 black [0, 50); 2 real [50, 100) and [100, 200).
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
@ -1314,6 +1351,146 @@ TEST(VP8VideoTrackEncoder, EnableBetweenFrames) {
EXPECT_EQ(PR_USEC_PER_SEC / 1000 * 100UL, frames[2]->GetDuration());
}
// Test that making time go backwards removes any future frames in the encoder.
TEST(VP8VideoTrackEncoder, BackwardsTimeResets) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
encoder.SetStartOffset(now);
// Pass frames in at t=0, t=100ms, t=200ms, t=300ms.
// Advance time to t=125ms.
// Pass frames in at t=150ms, t=250ms, t=350ms.
// Stop encoding at t=300ms.
// Should yield 4 frames, at t=0, t=100ms, t=150ms, t=250ms.
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(100));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(200));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(300));
encoder.AppendVideoSegment(std::move(segment));
}
encoder.AdvanceCurrentTime(now + TimeDuration::FromMilliseconds(125));
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(150));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(250));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(350));
encoder.AppendVideoSegment(std::move(segment));
}
encoder.AdvanceCurrentTime(now + TimeDuration::FromMilliseconds(300));
encoder.NotifyEndOfStream();
ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
EXPECT_TRUE(encoder.IsEncodingComplete());
const nsTArray<RefPtr<EncodedFrame>>& frames = container.GetEncodedFrames();
ASSERT_EQ(4UL, frames.Length());
// [0, 100ms)
EXPECT_EQ(PR_USEC_PER_SEC / 1000 * 100UL, frames[0]->GetDuration());
// [100ms, 150ms)
EXPECT_EQ(PR_USEC_PER_SEC / 1000 * 50UL, frames[1]->GetDuration());
// [150ms, 250ms)
EXPECT_EQ(PR_USEC_PER_SEC / 1000 * 100UL, frames[2]->GetDuration());
// [250ms, 300ms)
EXPECT_EQ(PR_USEC_PER_SEC / 1000 * 50UL, frames[3]->GetDuration());
}
// Test that trying to encode a null image removes any future frames in the
// encoder.
TEST(VP8VideoTrackEncoder, NullImageResets) {
TestVP8TrackEncoder encoder;
YUVBufferGenerator generator;
generator.Init(mozilla::gfx::IntSize(640, 480));
EncodedFrameContainer container;
TimeStamp now = TimeStamp::Now();
encoder.SetStartOffset(now);
// Pass frames in at t=0, t=100ms, t=200ms, t=300ms.
// Advance time to t=125ms.
// Pass in a null image at t=125ms.
// Pass frames in at t=250ms, t=350ms.
// Stop encoding at t=300ms.
// Should yield 3 frames, at t=0, t=100ms, t=250ms.
{
VideoSegment segment;
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false, now);
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(100));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(200));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(300));
encoder.AppendVideoSegment(std::move(segment));
}
encoder.AdvanceCurrentTime(now + TimeDuration::FromMilliseconds(125));
{
VideoSegment segment;
segment.AppendFrame(nullptr, generator.GetSize(), PRINCIPAL_HANDLE_NONE,
false, now + TimeDuration::FromMilliseconds(125));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(250));
segment.AppendFrame(generator.GenerateI420Image(), generator.GetSize(),
PRINCIPAL_HANDLE_NONE, false,
now + TimeDuration::FromMilliseconds(350));
encoder.AppendVideoSegment(std::move(segment));
}
encoder.AdvanceCurrentTime(now + TimeDuration::FromMilliseconds(300));
encoder.NotifyEndOfStream();
ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
EXPECT_TRUE(encoder.IsEncodingComplete());
const nsTArray<RefPtr<EncodedFrame>>& frames = container.GetEncodedFrames();
ASSERT_EQ(3UL, frames.Length());
// [0, 100ms)
EXPECT_EQ(PR_USEC_PER_SEC / 1000 * 100UL, frames[0]->GetDuration());
// [100ms, 250ms)
EXPECT_EQ(PR_USEC_PER_SEC / 1000 * 150UL, frames[1]->GetDuration());
// [250ms, 300ms)
EXPECT_EQ(PR_USEC_PER_SEC / 1000 * 50UL, frames[2]->GetDuration());
}
// EOS test
TEST(VP8VideoTrackEncoder, EncodeComplete) {
TestVP8TrackEncoder encoder;

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

@ -1,160 +1,151 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "YUVBufferGenerator.h"
using namespace mozilla::layers;
using namespace mozilla;
void YUVBufferGenerator::Init(const mozilla::gfx::IntSize& aSize)
{
mImageSize = aSize;
int yPlaneLen = aSize.width * aSize.height;
int cbcrPlaneLen = (yPlaneLen + 1) / 2;
int frameLen = yPlaneLen + cbcrPlaneLen;
// Generate source buffer.
mSourceBuffer.SetLength(frameLen);
// Fill Y plane.
memset(mSourceBuffer.Elements(), 0x10, yPlaneLen);
// Fill Cb/Cr planes.
memset(mSourceBuffer.Elements() + yPlaneLen, 0x80, cbcrPlaneLen);
}
mozilla::gfx::IntSize YUVBufferGenerator::GetSize() const
{
return mImageSize;
}
already_AddRefed<Image> YUVBufferGenerator::GenerateI420Image()
{
return do_AddRef(CreateI420Image());
}
already_AddRefed<Image> YUVBufferGenerator::GenerateNV12Image()
{
return do_AddRef(CreateNV12Image());
}
already_AddRefed<Image> YUVBufferGenerator::GenerateNV21Image()
{
return do_AddRef(CreateNV21Image());
}
Image* YUVBufferGenerator::CreateI420Image()
{
PlanarYCbCrImage* image = new RecyclingPlanarYCbCrImage(new BufferRecycleBin());
PlanarYCbCrData data;
data.mPicSize = mImageSize;
const uint32_t yPlaneSize = mImageSize.width * mImageSize.height;
const uint32_t halfWidth = (mImageSize.width + 1) / 2;
const uint32_t halfHeight = (mImageSize.height + 1) / 2;
const uint32_t uvPlaneSize = halfWidth * halfHeight;
// Y plane.
uint8_t* y = mSourceBuffer.Elements();
data.mYChannel = y;
data.mYSize.width = mImageSize.width;
data.mYSize.height = mImageSize.height;
data.mYStride = mImageSize.width;
data.mYSkip = 0;
// Cr plane.
uint8_t* cr = y + yPlaneSize + uvPlaneSize;
data.mCrChannel = cr;
data.mCrSkip = 0;
// Cb plane
uint8_t* cb = y + yPlaneSize;
data.mCbChannel = cb;
data.mCbSkip = 0;
// CrCb plane vectors.
data.mCbCrStride = halfWidth;
data.mCbCrSize.width = halfWidth;
data.mCbCrSize.height = halfHeight;
image->CopyData(data);
return image;
}
Image* YUVBufferGenerator::CreateNV12Image()
{
NVImage* image = new NVImage();
PlanarYCbCrData data;
data.mPicSize = mImageSize;
const uint32_t yPlaneSize = mImageSize.width * mImageSize.height;
const uint32_t halfWidth = (mImageSize.width + 1) / 2;
const uint32_t halfHeight = (mImageSize.height + 1) / 2;
// Y plane.
uint8_t* y = mSourceBuffer.Elements();
data.mYChannel = y;
data.mYSize.width = mImageSize.width;
data.mYSize.height = mImageSize.height;
data.mYStride = mImageSize.width;
data.mYSkip = 0;
// Cr plane.
uint8_t* cr = y + yPlaneSize;
data.mCrChannel = cr;
data.mCrSkip = 1;
// Cb plane
uint8_t* cb = y + yPlaneSize + 1;
data.mCbChannel = cb;
data.mCbSkip = 1;
// 4:2:0.
data.mCbCrStride = mImageSize.width;
data.mCbCrSize.width = halfWidth;
data.mCbCrSize.height = halfHeight;
image->SetData(data);
return image;
}
Image* YUVBufferGenerator::CreateNV21Image()
{
NVImage* image = new NVImage();
PlanarYCbCrData data;
data.mPicSize = mImageSize;
const uint32_t yPlaneSize = mImageSize.width * mImageSize.height;
const uint32_t halfWidth = (mImageSize.width + 1) / 2;
const uint32_t halfHeight = (mImageSize.height + 1) / 2;
// Y plane.
uint8_t* y = mSourceBuffer.Elements();
data.mYChannel = y;
data.mYSize.width = mImageSize.width;
data.mYSize.height = mImageSize.height;
data.mYStride = mImageSize.width;
data.mYSkip = 0;
// Cr plane.
uint8_t* cr = y + yPlaneSize + 1;
data.mCrChannel = cr;
data.mCrSkip = 1;
// Cb plane
uint8_t* cb = y + yPlaneSize;
data.mCbChannel = cb;
data.mCbSkip = 1;
// 4:2:0.
data.mCbCrStride = mImageSize.width;
data.mCbCrSize.width = halfWidth;
data.mCbCrSize.height = halfHeight;
image->SetData(data);
return image;
}
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "YUVBufferGenerator.h"
using namespace mozilla::layers;
using namespace mozilla;
void YUVBufferGenerator::Init(const mozilla::gfx::IntSize& aSize) {
mImageSize = aSize;
int yPlaneLen = aSize.width * aSize.height;
int cbcrPlaneLen = (yPlaneLen + 1) / 2;
int frameLen = yPlaneLen + cbcrPlaneLen;
// Generate source buffer.
mSourceBuffer.SetLength(frameLen);
// Fill Y plane.
memset(mSourceBuffer.Elements(), 0x10, yPlaneLen);
// Fill Cb/Cr planes.
memset(mSourceBuffer.Elements() + yPlaneLen, 0x80, cbcrPlaneLen);
}
mozilla::gfx::IntSize YUVBufferGenerator::GetSize() const { return mImageSize; }
already_AddRefed<Image> YUVBufferGenerator::GenerateI420Image() {
return do_AddRef(CreateI420Image());
}
already_AddRefed<Image> YUVBufferGenerator::GenerateNV12Image() {
return do_AddRef(CreateNV12Image());
}
already_AddRefed<Image> YUVBufferGenerator::GenerateNV21Image() {
return do_AddRef(CreateNV21Image());
}
Image* YUVBufferGenerator::CreateI420Image() {
PlanarYCbCrImage* image =
new RecyclingPlanarYCbCrImage(new BufferRecycleBin());
PlanarYCbCrData data;
data.mPicSize = mImageSize;
const uint32_t yPlaneSize = mImageSize.width * mImageSize.height;
const uint32_t halfWidth = (mImageSize.width + 1) / 2;
const uint32_t halfHeight = (mImageSize.height + 1) / 2;
const uint32_t uvPlaneSize = halfWidth * halfHeight;
// Y plane.
uint8_t* y = mSourceBuffer.Elements();
data.mYChannel = y;
data.mYSize.width = mImageSize.width;
data.mYSize.height = mImageSize.height;
data.mYStride = mImageSize.width;
data.mYSkip = 0;
// Cr plane.
uint8_t* cr = y + yPlaneSize + uvPlaneSize;
data.mCrChannel = cr;
data.mCrSkip = 0;
// Cb plane
uint8_t* cb = y + yPlaneSize;
data.mCbChannel = cb;
data.mCbSkip = 0;
// CrCb plane vectors.
data.mCbCrStride = halfWidth;
data.mCbCrSize.width = halfWidth;
data.mCbCrSize.height = halfHeight;
image->CopyData(data);
return image;
}
Image* YUVBufferGenerator::CreateNV12Image() {
NVImage* image = new NVImage();
PlanarYCbCrData data;
data.mPicSize = mImageSize;
const uint32_t yPlaneSize = mImageSize.width * mImageSize.height;
const uint32_t halfWidth = (mImageSize.width + 1) / 2;
const uint32_t halfHeight = (mImageSize.height + 1) / 2;
// Y plane.
uint8_t* y = mSourceBuffer.Elements();
data.mYChannel = y;
data.mYSize.width = mImageSize.width;
data.mYSize.height = mImageSize.height;
data.mYStride = mImageSize.width;
data.mYSkip = 0;
// Cr plane.
uint8_t* cr = y + yPlaneSize;
data.mCrChannel = cr;
data.mCrSkip = 1;
// Cb plane
uint8_t* cb = y + yPlaneSize + 1;
data.mCbChannel = cb;
data.mCbSkip = 1;
// 4:2:0.
data.mCbCrStride = mImageSize.width;
data.mCbCrSize.width = halfWidth;
data.mCbCrSize.height = halfHeight;
image->SetData(data);
return image;
}
Image* YUVBufferGenerator::CreateNV21Image() {
NVImage* image = new NVImage();
PlanarYCbCrData data;
data.mPicSize = mImageSize;
const uint32_t yPlaneSize = mImageSize.width * mImageSize.height;
const uint32_t halfWidth = (mImageSize.width + 1) / 2;
const uint32_t halfHeight = (mImageSize.height + 1) / 2;
// Y plane.
uint8_t* y = mSourceBuffer.Elements();
data.mYChannel = y;
data.mYSize.width = mImageSize.width;
data.mYSize.height = mImageSize.height;
data.mYStride = mImageSize.width;
data.mYSkip = 0;
// Cr plane.
uint8_t* cr = y + yPlaneSize + 1;
data.mCrChannel = cr;
data.mCrSkip = 1;
// Cb plane
uint8_t* cb = y + yPlaneSize;
data.mCbChannel = cb;
data.mCbSkip = 1;
// 4:2:0.
data.mCbCrStride = mImageSize.width;
data.mCbCrSize.width = halfWidth;
data.mCbCrSize.height = halfHeight;
image->SetData(data);
return image;
}

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

@ -1,32 +1,32 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef YUVBufferGenerator_h
#define YUVBufferGenerator_h
#include "ImageContainer.h"
#include "mozilla/AlreadyAddRefed.h"
#include "nsTArray.h"
#include "Point.h" // mozilla::gfx::IntSize
// A helper object to generate of different YUV planes.
class YUVBufferGenerator {
public:
void Init(const mozilla::gfx::IntSize& aSize);
mozilla::gfx::IntSize GetSize() const;
already_AddRefed<mozilla::layers::Image> GenerateI420Image();
already_AddRefed<mozilla::layers::Image> GenerateNV12Image();
already_AddRefed<mozilla::layers::Image> GenerateNV21Image();
private:
mozilla::layers::Image* CreateI420Image();
mozilla::layers::Image* CreateNV12Image();
mozilla::layers::Image* CreateNV21Image();
mozilla::gfx::IntSize mImageSize;
nsTArray<uint8_t> mSourceBuffer;
};
#endif // YUVBufferGenerator_h
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef YUVBufferGenerator_h
#define YUVBufferGenerator_h
#include "ImageContainer.h"
#include "mozilla/AlreadyAddRefed.h"
#include "nsTArray.h"
#include "Point.h" // mozilla::gfx::IntSize
// A helper object to generate of different YUV planes.
class YUVBufferGenerator {
public:
void Init(const mozilla::gfx::IntSize& aSize);
mozilla::gfx::IntSize GetSize() const;
already_AddRefed<mozilla::layers::Image> GenerateI420Image();
already_AddRefed<mozilla::layers::Image> GenerateNV12Image();
already_AddRefed<mozilla::layers::Image> GenerateNV21Image();
private:
mozilla::layers::Image* CreateI420Image();
mozilla::layers::Image* CreateNV12Image();
mozilla::layers::Image* CreateNV21Image();
mozilla::gfx::IntSize mImageSize;
nsTArray<uint8_t> mSourceBuffer;
};
#endif // YUVBufferGenerator_h

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

@ -108,8 +108,9 @@ class VPXDecoder : public MediaDataDecoder,
bool IsCompatible(const VPXStreamInfo& aOther) const {
return mImage == aOther.mImage && mProfile == aOther.mProfile &&
mBitDepth == aOther.mBitDepth && mSubSampling_x &&
aOther.mSubSampling_x && mSubSampling_y == aOther.mSubSampling_y;
mBitDepth == aOther.mBitDepth &&
mSubSampling_x == aOther.mSubSampling_x &&
mSubSampling_y == aOther.mSubSampling_y;
}
};

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

@ -1,5 +1,5 @@
skip-if(Android) fuzzy-if(OSX,0-22,0-49977) fuzzy-if(webrender&&cocoaWidget,23-23,76795-76795) skip-if(winWidget) fuzzy-if(gtkWidget&&layersGPUAccelerated,0-70,0-600) HTTP(..) == short.mp4.firstframe.html short.mp4.firstframe-ref.html
skip-if(Android) fuzzy-if(OSX,0-23,0-51392) fuzzy-if(webrender&&cocoaWidget,23-23,76798-76798) fuzzy-if(winWidget,0-59,0-76797) fuzzy-if(gtkWidget&&layersGPUAccelerated,0-60,0-1800) HTTP(..) == short.mp4.lastframe.html short.mp4.lastframe-ref.html
skip-if(Android) skip-if(winWidget) fuzzy-if(gtkWidget&&layersGPUAccelerated,0-55,0-4281) fuzzy-if(OSX,0-3,0-111852) HTTP(..) == bipbop_300_215kbps.mp4.lastframe.html bipbop_300_215kbps.mp4.lastframe-ref.html
skip-if(Android) fuzzy-if(OSX,0-25,0-175921) fuzzy-if(winWidget,0-71,0-179198) HTTP(..) == gizmo.mp4.seek.html gizmo.mp4.55thframe-ref.html
skip-if(Android) == vtt_update_display_after_removed_cue.html vtt_update_display_after_removed_cue_ref.html
skip-if(Android) fuzzy-if(OSX,0-25,0-175921) fuzzy-if((/^Windows\x20NT\x2010\.0/.test(http.oscpu))&&(/^aarch64-msvc/.test(xulRuntime.XPCOMABI)),224-224,178000-178820) fuzzy-if(winWidget,0-71,0-179198) HTTP(..) == gizmo.mp4.seek.html gizmo.mp4.55thframe-ref.html
skip-if(Android) fuzzy-if((/^Windows\x20NT\x2010\.0/.test(http.oscpu))&&(/^aarch64-msvc/.test(xulRuntime.XPCOMABI)),136-136,427600-427680) == vtt_update_display_after_removed_cue.html vtt_update_display_after_removed_cue_ref.html

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

@ -51,7 +51,7 @@ class MediaEngine : public DeviceChangeCallback {
virtual void SetFakeDeviceChangeEvents() {}
protected:
virtual ~MediaEngine() {}
virtual ~MediaEngine() = default;
};
} // namespace mozilla

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

@ -64,7 +64,7 @@ MediaEngineDefaultVideoSource::MediaEngineDefaultVideoSource()
: mTimer(nullptr),
mName(DefaultVideoName()) {}
MediaEngineDefaultVideoSource::~MediaEngineDefaultVideoSource() {}
MediaEngineDefaultVideoSource::~MediaEngineDefaultVideoSource() = default;
nsString MediaEngineDefaultVideoSource::GetName() const { return mName; }
@ -343,7 +343,7 @@ void MediaEngineDefaultVideoSource::Pull(
MediaEngineDefaultAudioSource::MediaEngineDefaultAudioSource()
: mMutex("MediaEngineDefaultAudioSource::mMutex") {}
MediaEngineDefaultAudioSource::~MediaEngineDefaultAudioSource() {}
MediaEngineDefaultAudioSource::~MediaEngineDefaultAudioSource() = default;
nsString MediaEngineDefaultAudioSource::GetName() const {
return NS_LITERAL_STRING(u"Default Audio Device");

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

@ -872,7 +872,7 @@ bool MediaEngineRemoteVideoSource::ChooseCapability(
continue;
}
LogCapability("Hardcoded capability", cap, 0);
candidateSet.AppendElement(CapabilityCandidate(std::move(cap)));
candidateSet.AppendElement(cap);
}
}

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

@ -66,10 +66,9 @@ class MediaEngineRemoteVideoSource : public MediaEngineSource,
~MediaEngineRemoteVideoSource();
struct CapabilityCandidate {
explicit CapabilityCandidate(webrtc::CaptureCapability&& aCapability,
explicit CapabilityCandidate(webrtc::CaptureCapability aCapability,
uint32_t aDistance = 0)
: mCapability(std::forward<webrtc::CaptureCapability>(aCapability)),
mDistance(aDistance) {}
: mCapability(aCapability), mDistance(aDistance) {}
const webrtc::CaptureCapability mCapability;
uint32_t mDistance;
@ -113,8 +112,8 @@ class MediaEngineRemoteVideoSource : public MediaEngineSource,
bool aScary);
// ExternalRenderer
int DeliverFrame(uint8_t* buffer,
const camera::VideoFrameProperties& properties) override;
int DeliverFrame(uint8_t* aBuffer,
const camera::VideoFrameProperties& aProps) override;
// MediaEngineSource
dom::MediaSourceEnum GetMediaSource() const override;

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

@ -48,7 +48,7 @@ class MediaEnginePhotoCallback {
virtual nsresult PhotoError(nsresult aRv) = 0;
protected:
virtual ~MediaEnginePhotoCallback() {}
virtual ~MediaEnginePhotoCallback() = default;
};
/**

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

@ -33,7 +33,7 @@ namespace mozilla {
using namespace mozilla::gfx;
MediaEngineTabVideoSource::MediaEngineTabVideoSource() {}
MediaEngineTabVideoSource::MediaEngineTabVideoSource() = default;
nsresult MediaEngineTabVideoSource::StartRunnable::Run() {
MOZ_ASSERT(NS_IsMainThread());
@ -95,7 +95,9 @@ nsresult MediaEngineTabVideoSource::InitRunnable::Run() {
nsCOMPtr<mozIDOMWindowProxy> win;
rv = mVideoSource->mTabSource->GetTabToStream(getter_AddRefs(win));
NS_ENSURE_SUCCESS(rv, rv);
if (!win) return NS_OK;
if (!win) {
return NS_OK;
}
mVideoSource->mWindow = nsPIDOMWindowOuter::From(win);
MOZ_ASSERT(mVideoSource->mWindow);

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

@ -114,14 +114,14 @@ class MediaEngineTabVideoSource : public MediaEngineSource {
};
protected:
~MediaEngineTabVideoSource() {}
~MediaEngineTabVideoSource() = default;
private:
// These are accessed only on main thread.
int32_t mBufWidthMax = 0;
int32_t mBufHeightMax = 0;
int64_t mWindowId = 0;
bool mScrollWithPage = 0;
bool mScrollWithPage = false;
int32_t mViewportOffsetX = 0;
int32_t mViewportOffsetY = 0;
int32_t mViewportWidth = 0;

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

@ -28,9 +28,9 @@ class AudioInputProcessing;
class MediaEngineWebRTCMicrophoneSource : public MediaEngineSource {
public:
MediaEngineWebRTCMicrophoneSource(RefPtr<AudioDeviceInfo> aInfo,
const nsString& aName,
const nsCString& aUuid,
const nsString& aGroupId,
const nsString& aDeviceName,
const nsCString& aDeviceUUID,
const nsString& aDeviceGroup,
uint32_t aMaxChannelCount,
bool aDelayAgnostic, bool aExtendedFilter);

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

@ -388,7 +388,7 @@ uint32_t MediaConstraintsHelper::FeasibilityDistance(
/* static */
uint32_t MediaConstraintsHelper::FitnessDistance(
nsString aN, const NormalizedConstraintSet::StringRange& aParams) {
const nsString& aN, const NormalizedConstraintSet::StringRange& aParams) {
if (!aParams.mExact.empty() &&
aParams.mExact.find(aN) == aParams.mExact.end()) {
return UINT32_MAX;
@ -440,8 +440,8 @@ uint32_t MediaConstraintsHelper::FitnessDistance(
// Then apply advanced constraints.
for (int i = 0; i < int(c.mAdvanced.size()); i++) {
aggregateConstraints.AppendElement(&c.mAdvanced[i]);
for (const auto& advanced : c.mAdvanced) {
aggregateConstraints.AppendElement(&advanced);
nsTArray<RefPtr<MediaDevice>> rejects;
for (uint32_t j = 0; j < aDevices.Length();) {
uint32_t distance =
@ -527,12 +527,12 @@ static void LogConstraintStringRange(
const NormalizedConstraintSet::StringRange& aRange) {
if (aRange.mExact.size() <= 1 && aRange.mIdeal.size() <= 1) {
LOG(" %s: { exact: [%s], ideal: [%s] }", aRange.mName,
(aRange.mExact.size()
? NS_ConvertUTF16toUTF8(*aRange.mExact.begin()).get()
: ""),
(aRange.mIdeal.size()
? NS_ConvertUTF16toUTF8(*aRange.mIdeal.begin()).get()
: ""));
(aRange.mExact.empty()
? ""
: NS_ConvertUTF16toUTF8(*aRange.mExact.begin()).get()),
(aRange.mIdeal.empty()
? ""
: NS_ConvertUTF16toUTF8(*aRange.mIdeal.begin()).get()));
} else {
LOG(" %s: { exact: [", aRange.mName);
for (auto& entry : aRange.mExact) {

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

@ -52,7 +52,7 @@ class NormalizedConstraintSet {
aList->AppendElement(aMemberPtr);
}
}
virtual ~BaseRange() {}
virtual ~BaseRange() = default;
public:
virtual bool Merge(const BaseRange& aOther) = 0;
@ -76,7 +76,7 @@ class NormalizedConstraintSet {
mMin(aMin),
mMax(aMax),
mMergeDenominator(0) {}
virtual ~Range(){};
virtual ~Range() = default;
template <class ConstrainRange>
void SetFrom(const ConstrainRange& aOther);
@ -206,7 +206,7 @@ class NormalizedConstraintSet {
mIdeal.insert(aOther);
}
~StringRange() {}
~StringRange() = default;
void SetFrom(const dom::ConstrainDOMStringParameters& aOther);
ValueType Clamp(const ValueType& n) const;
@ -311,7 +311,7 @@ class MediaConstraintsHelper {
static uint32_t FeasibilityDistance(ValueType aN,
const NormalizedRange& aRange);
static uint32_t FitnessDistance(
nsString aN, const NormalizedConstraintSet::StringRange& aConstraint);
const nsString& aN, const NormalizedConstraintSet::StringRange& aParams);
protected:
static bool SomeSettingsFit(const NormalizedConstraints& aConstraints,

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

@ -31,7 +31,7 @@ class PeerIdentity final : public RefCounted<PeerIdentity> {
explicit PeerIdentity(const nsAString& aPeerIdentity)
: mPeerIdentity(aPeerIdentity) {}
~PeerIdentity() {}
~PeerIdentity() = default;
bool Equals(const PeerIdentity& aOther) const;
bool Equals(const nsAString& aOtherString) const;

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

@ -28,7 +28,7 @@ RTCIdentityProviderRegistrar::RTCIdentityProviderRegistrar(
mGenerateAssertionCallback(nullptr),
mValidateAssertionCallback(nullptr) {}
RTCIdentityProviderRegistrar::~RTCIdentityProviderRegistrar() {}
RTCIdentityProviderRegistrar::~RTCIdentityProviderRegistrar() = default;
nsIGlobalObject* RTCIdentityProviderRegistrar::GetParentObject() const {
return mGlobal;

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

@ -93,12 +93,14 @@ struct ParamTraits<mozilla::dom::RTCStatsReportInternal> {
WriteParam(aMsg, aParam.mIceCandidatePairStats);
WriteParam(aMsg, aParam.mIceCandidateStats);
WriteParam(aMsg, aParam.mIceComponentStats);
WriteParam(aMsg, aParam.mInboundRTPStreamStats);
WriteParam(aMsg, aParam.mInboundRtpStreamStats);
WriteParam(aMsg, aParam.mLocalSdp);
WriteParam(aMsg, aParam.mMediaStreamStats);
WriteParam(aMsg, aParam.mMediaStreamTrackStats);
WriteParam(aMsg, aParam.mOutboundRTPStreamStats);
WriteParam(aMsg, aParam.mOutboundRtpStreamStats);
WriteParam(aMsg, aParam.mPcid);
WriteParam(aMsg, aParam.mRemoteInboundRtpStreamStats);
WriteParam(aMsg, aParam.mRemoteOutboundRtpStreamStats);
WriteParam(aMsg, aParam.mRemoteSdp);
WriteParam(aMsg, aParam.mTimestamp);
WriteParam(aMsg, aParam.mIceRestarts);
@ -118,12 +120,14 @@ struct ParamTraits<mozilla::dom::RTCStatsReportInternal> {
!ReadParam(aMsg, aIter, &(aResult->mIceCandidatePairStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mIceCandidateStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mIceComponentStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mInboundRTPStreamStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mInboundRtpStreamStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mLocalSdp)) ||
!ReadParam(aMsg, aIter, &(aResult->mMediaStreamStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mMediaStreamTrackStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mOutboundRTPStreamStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mOutboundRtpStreamStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mPcid)) ||
!ReadParam(aMsg, aIter, &(aResult->mRemoteInboundRtpStreamStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mRemoteOutboundRtpStreamStats)) ||
!ReadParam(aMsg, aIter, &(aResult->mRemoteSdp)) ||
!ReadParam(aMsg, aIter, &(aResult->mTimestamp)) ||
!ReadParam(aMsg, aIter, &(aResult->mIceRestarts)) ||
@ -291,116 +295,169 @@ struct ParamTraits<mozilla::dom::RTCIceComponentStats> {
!ReadRTCStats(aMsg, aIter, aResult)) {
return false;
}
return true;
}
};
static void WriteRTCRtpStreamStats(
Message* aMsg, const mozilla::dom::RTCRtpStreamStats& aParam) {
WriteParam(aMsg, aParam.mBitrateMean);
WriteParam(aMsg, aParam.mBitrateStdDev);
WriteParam(aMsg, aParam.mCodecId);
WriteParam(aMsg, aParam.mFirCount);
WriteParam(aMsg, aParam.mFramerateMean);
WriteParam(aMsg, aParam.mFramerateStdDev);
WriteParam(aMsg, aParam.mKind);
WriteParam(aMsg, aParam.mLocalId);
WriteParam(aMsg, aParam.mMediaTrackId);
WriteParam(aMsg, aParam.mMediaType);
WriteParam(aMsg, aParam.mNackCount);
WriteParam(aMsg, aParam.mPliCount);
WriteParam(aMsg, aParam.mQpSum);
WriteParam(aMsg, aParam.mRemoteId);
WriteParam(aMsg, aParam.mSsrc);
WriteParam(aMsg, aParam.mMediaType);
WriteParam(aMsg, aParam.mKind);
WriteParam(aMsg, aParam.mTransportId);
WriteRTCStats(aMsg, aParam);
}
static bool ReadRTCRtpStreamStats(const Message* aMsg, PickleIterator* aIter,
mozilla::dom::RTCRtpStreamStats* aResult) {
if (!ReadParam(aMsg, aIter, &(aResult->mBitrateMean)) ||
!ReadParam(aMsg, aIter, &(aResult->mBitrateStdDev)) ||
!ReadParam(aMsg, aIter, &(aResult->mCodecId)) ||
!ReadParam(aMsg, aIter, &(aResult->mFirCount)) ||
!ReadParam(aMsg, aIter, &(aResult->mFramerateMean)) ||
!ReadParam(aMsg, aIter, &(aResult->mFramerateStdDev)) ||
!ReadParam(aMsg, aIter, &(aResult->mKind)) ||
!ReadParam(aMsg, aIter, &(aResult->mLocalId)) ||
!ReadParam(aMsg, aIter, &(aResult->mMediaTrackId)) ||
!ReadParam(aMsg, aIter, &(aResult->mMediaType)) ||
!ReadParam(aMsg, aIter, &(aResult->mNackCount)) ||
!ReadParam(aMsg, aIter, &(aResult->mPliCount)) ||
!ReadParam(aMsg, aIter, &(aResult->mQpSum)) ||
!ReadParam(aMsg, aIter, &(aResult->mRemoteId)) ||
!ReadParam(aMsg, aIter, &(aResult->mSsrc)) ||
!ReadParam(aMsg, aIter, &(aResult->mTransportId))) {
return false;
}
return ReadParam(aMsg, aIter, &(aResult->mSsrc)) &&
ReadParam(aMsg, aIter, &(aResult->mMediaType)) &&
ReadParam(aMsg, aIter, &(aResult->mKind)) &&
ReadParam(aMsg, aIter, &(aResult->mTransportId)) &&
ReadRTCStats(aMsg, aIter, aResult);
}
return true;
static void WriteRTCReceivedRtpStreamStats(
Message* aMsg, const mozilla::dom::RTCReceivedRtpStreamStats& aParam) {
WriteParam(aMsg, aParam.mPacketsReceived);
WriteParam(aMsg, aParam.mPacketsLost);
WriteParam(aMsg, aParam.mJitter);
WriteParam(aMsg, aParam.mDiscardedPackets);
WriteParam(aMsg, aParam.mPacketsDiscarded);
WriteRTCRtpStreamStats(aMsg, aParam);
}
static bool ReadRTCReceivedRtpStreamStats(
const Message* aMsg, PickleIterator* aIter,
mozilla::dom::RTCReceivedRtpStreamStats* aResult) {
return ReadParam(aMsg, aIter, &(aResult->mPacketsReceived)) &&
ReadParam(aMsg, aIter, &(aResult->mPacketsLost)) &&
ReadParam(aMsg, aIter, &(aResult->mJitter)) &&
ReadParam(aMsg, aIter, &(aResult->mDiscardedPackets)) &&
ReadParam(aMsg, aIter, &(aResult->mPacketsDiscarded)) &&
ReadRTCRtpStreamStats(aMsg, aIter, aResult);
}
template <>
struct ParamTraits<mozilla::dom::RTCInboundRTPStreamStats> {
typedef mozilla::dom::RTCInboundRTPStreamStats paramType;
struct ParamTraits<mozilla::dom::RTCInboundRtpStreamStats> {
typedef mozilla::dom::RTCInboundRtpStreamStats paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.mBytesReceived);
WriteParam(aMsg, aParam.mDiscardedPackets);
WriteParam(aMsg, aParam.mRemoteId);
WriteParam(aMsg, aParam.mFramesDecoded);
WriteParam(aMsg, aParam.mJitter);
WriteParam(aMsg, aParam.mPacketsLost);
WriteParam(aMsg, aParam.mPacketsReceived);
WriteParam(aMsg, aParam.mRoundTripTime);
WriteRTCRtpStreamStats(aMsg, aParam);
WriteRTCStats(aMsg, aParam);
WriteParam(aMsg, aParam.mBytesReceived);
WriteParam(aMsg, aParam.mNackCount);
WriteParam(aMsg, aParam.mFirCount);
WriteParam(aMsg, aParam.mPliCount);
WriteParam(aMsg, aParam.mBitrateMean);
WriteParam(aMsg, aParam.mBitrateStdDev);
WriteParam(aMsg, aParam.mFramerateMean);
WriteParam(aMsg, aParam.mFramerateStdDev);
WriteRTCReceivedRtpStreamStats(aMsg, aParam);
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
if (!ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) ||
!ReadParam(aMsg, aIter, &(aResult->mDiscardedPackets)) ||
!ReadParam(aMsg, aIter, &(aResult->mFramesDecoded)) ||
!ReadParam(aMsg, aIter, &(aResult->mJitter)) ||
!ReadParam(aMsg, aIter, &(aResult->mPacketsLost)) ||
!ReadParam(aMsg, aIter, &(aResult->mPacketsReceived)) ||
!ReadParam(aMsg, aIter, &(aResult->mRoundTripTime)) ||
!ReadRTCRtpStreamStats(aMsg, aIter, aResult) ||
!ReadRTCStats(aMsg, aIter, aResult)) {
return false;
}
return ReadParam(aMsg, aIter, &(aResult->mRemoteId)) &&
ReadParam(aMsg, aIter, &(aResult->mFramesDecoded)) &&
ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) &&
ReadParam(aMsg, aIter, &(aResult->mNackCount)) &&
ReadParam(aMsg, aIter, &(aResult->mFirCount)) &&
ReadParam(aMsg, aIter, &(aResult->mPliCount)) &&
ReadParam(aMsg, aIter, &(aResult->mBitrateMean)) &&
ReadParam(aMsg, aIter, &(aResult->mBitrateStdDev)) &&
ReadParam(aMsg, aIter, &(aResult->mFramerateMean)) &&
ReadParam(aMsg, aIter, &(aResult->mFramerateStdDev)) &&
ReadRTCReceivedRtpStreamStats(aMsg, aIter, aResult);
}
};
return true;
static void WriteRTCSentRtpStreamStats(
Message* aMsg, const mozilla::dom::RTCSentRtpStreamStats& aParam) {
WriteParam(aMsg, aParam.mPacketsSent);
WriteParam(aMsg, aParam.mBytesSent);
WriteRTCRtpStreamStats(aMsg, aParam);
}
static bool ReadRTCSentRtpStreamStats(
const Message* aMsg, PickleIterator* aIter,
mozilla::dom::RTCSentRtpStreamStats* aResult) {
return ReadParam(aMsg, aIter, &(aResult->mPacketsSent)) &&
ReadParam(aMsg, aIter, &(aResult->mBytesSent)) &&
ReadRTCRtpStreamStats(aMsg, aIter, aResult);
}
template <>
struct ParamTraits<mozilla::dom::RTCOutboundRtpStreamStats> {
typedef mozilla::dom::RTCOutboundRtpStreamStats paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.mRemoteId);
WriteParam(aMsg, aParam.mFramesEncoded);
WriteParam(aMsg, aParam.mQpSum);
WriteParam(aMsg, aParam.mNackCount);
WriteParam(aMsg, aParam.mFirCount);
WriteParam(aMsg, aParam.mPliCount);
WriteParam(aMsg, aParam.mBitrateMean);
WriteParam(aMsg, aParam.mBitrateStdDev);
WriteParam(aMsg, aParam.mFramerateMean);
WriteParam(aMsg, aParam.mFramerateStdDev);
WriteParam(aMsg, aParam.mDroppedFrames);
WriteRTCSentRtpStreamStats(aMsg, aParam);
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
return ReadParam(aMsg, aIter, &(aResult->mRemoteId)) &&
ReadParam(aMsg, aIter, &(aResult->mFramesEncoded)) &&
ReadParam(aMsg, aIter, &(aResult->mQpSum)) &&
ReadParam(aMsg, aIter, &(aResult->mNackCount)) &&
ReadParam(aMsg, aIter, &(aResult->mFirCount)) &&
ReadParam(aMsg, aIter, &(aResult->mPliCount)) &&
ReadParam(aMsg, aIter, &(aResult->mBitrateMean)) &&
ReadParam(aMsg, aIter, &(aResult->mBitrateStdDev)) &&
ReadParam(aMsg, aIter, &(aResult->mFramerateMean)) &&
ReadParam(aMsg, aIter, &(aResult->mFramerateStdDev)) &&
ReadParam(aMsg, aIter, &(aResult->mDroppedFrames)) &&
ReadRTCSentRtpStreamStats(aMsg, aIter, aResult);
}
};
template <>
struct ParamTraits<mozilla::dom::RTCOutboundRTPStreamStats> {
typedef mozilla::dom::RTCOutboundRTPStreamStats paramType;
struct ParamTraits<mozilla::dom::RTCRemoteInboundRtpStreamStats> {
typedef mozilla::dom::RTCRemoteInboundRtpStreamStats paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.mBytesSent);
WriteParam(aMsg, aParam.mDroppedFrames);
WriteParam(aMsg, aParam.mFramesEncoded);
WriteParam(aMsg, aParam.mPacketsSent);
WriteParam(aMsg, aParam.mTargetBitrate);
WriteRTCRtpStreamStats(aMsg, aParam);
WriteRTCStats(aMsg, aParam);
WriteParam(aMsg, aParam.mLocalId);
WriteParam(aMsg, aParam.mBytesReceived); // To be removed in Bug 1529405
WriteParam(aMsg, aParam.mRoundTripTime);
WriteRTCReceivedRtpStreamStats(aMsg, aParam);
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
if (!ReadParam(aMsg, aIter, &(aResult->mBytesSent)) ||
!ReadParam(aMsg, aIter, &(aResult->mDroppedFrames)) ||
!ReadParam(aMsg, aIter, &(aResult->mFramesEncoded)) ||
!ReadParam(aMsg, aIter, &(aResult->mPacketsSent)) ||
!ReadParam(aMsg, aIter, &(aResult->mTargetBitrate)) ||
!ReadRTCRtpStreamStats(aMsg, aIter, aResult) ||
!ReadRTCStats(aMsg, aIter, aResult)) {
return false;
}
return ReadParam(aMsg, aIter, &(aResult->mLocalId)) &&
ReadParam(
aMsg, aIter,
&(aResult->mBytesReceived)) && // To be removed in Bug 1529405
ReadParam(aMsg, aIter, &(aResult->mRoundTripTime)) &&
ReadRTCReceivedRtpStreamStats(aMsg, aIter, aResult);
}
};
return true;
template <>
struct ParamTraits<mozilla::dom::RTCRemoteOutboundRtpStreamStats> {
typedef mozilla::dom::RTCRemoteOutboundRtpStreamStats paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.mLocalId);
WriteRTCSentRtpStreamStats(aMsg, aParam);
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
return ReadParam(aMsg, aIter, &(aResult->mLocalId)) &&
ReadRTCSentRtpStreamStats(aMsg, aIter, aResult);
}
};

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

@ -121,8 +121,7 @@ void PaymentMethodChangeEvent::GetMethodDetails(
!rawDetails.billingAddress.phone.IsEmpty()) {
nsCOMPtr<nsPIDOMWindowInner> window =
do_QueryInterface(GetParentObject());
basicCardDetails.mBillingAddress.Construct();
basicCardDetails.mBillingAddress.Value() =
basicCardDetails.mBillingAddress =
new PaymentAddress(window, rawDetails.billingAddress.country,
rawDetails.billingAddress.addressLine,
rawDetails.billingAddress.region,

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

@ -97,21 +97,17 @@ void PaymentResponse::GetDetails(JSContext* aCx,
const BasicCardData& rawData = mDetails.basicCardData();
BasicCardResponse basicCardResponse;
if (!rawData.cardholderName.IsEmpty()) {
basicCardResponse.mCardholderName.Construct();
basicCardResponse.mCardholderName.Value() = rawData.cardholderName;
basicCardResponse.mCardholderName = rawData.cardholderName;
}
basicCardResponse.mCardNumber = rawData.cardNumber;
if (!rawData.expiryMonth.IsEmpty()) {
basicCardResponse.mExpiryMonth.Construct();
basicCardResponse.mExpiryMonth.Value() = rawData.expiryMonth;
basicCardResponse.mExpiryMonth = rawData.expiryMonth;
}
if (!rawData.expiryYear.IsEmpty()) {
basicCardResponse.mExpiryYear.Construct();
basicCardResponse.mExpiryYear.Value() = rawData.expiryYear;
basicCardResponse.mExpiryYear = rawData.expiryYear;
}
if (!rawData.cardSecurityCode.IsEmpty()) {
basicCardResponse.mCardSecurityCode.Construct();
basicCardResponse.mCardSecurityCode.Value() = rawData.cardSecurityCode;
basicCardResponse.mCardSecurityCode = rawData.cardSecurityCode;
}
if (!rawData.billingAddress.country.IsEmpty() ||
!rawData.billingAddress.addressLine.IsEmpty() ||
@ -124,8 +120,7 @@ void PaymentResponse::GetDetails(JSContext* aCx,
!rawData.billingAddress.organization.IsEmpty() ||
!rawData.billingAddress.recipient.IsEmpty() ||
!rawData.billingAddress.phone.IsEmpty()) {
basicCardResponse.mBillingAddress.Construct();
basicCardResponse.mBillingAddress.Value() = new PaymentAddress(
basicCardResponse.mBillingAddress = new PaymentAddress(
GetOwner(), rawData.billingAddress.country,
rawData.billingAddress.addressLine, rawData.billingAddress.region,
rawData.billingAddress.regionCode, rawData.billingAddress.city,

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

@ -55,7 +55,7 @@ function nativeVerticalWheelEventMsg() {
case "mac": return 0; // value is unused, can be anything
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
}
throw "Native wheel events not supported on platform " + getPlatform();
throw new Error("Native wheel events not supported on platform " + getPlatform());
}
/**

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

@ -7647,52 +7647,92 @@ void ClearRequestBase::DeleteFiles(QuotaManager* aQuotaManager,
return;
}
bool initialized;
if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
initialized = aQuotaManager->IsOriginInitialized(origin);
} else {
initialized = aQuotaManager->IsTemporaryStorageInitialized();
}
UsageInfo usageInfo;
if (!mClientType.IsNull()) {
Client::Type clientType = mClientType.Value();
nsAutoString clientDirectoryName;
rv = Client::TypeToText(clientType, clientDirectoryName);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Checking whether there is any other client in the directory is needed.
// If there is not, removing whole directory is needed.
nsCOMPtr<nsIDirectoryEnumerator> originEntries;
bool hasOtherClient = false;
if (NS_WARN_IF(NS_FAILED(
file->GetDirectoryEntries(getter_AddRefs(originEntries)))) ||
!originEntries) {
return;
}
rv = file->Append(clientDirectoryName);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
nsCOMPtr<nsIFile> clientFile;
while (NS_SUCCEEDED((rv = originEntries->GetNextFile(
getter_AddRefs(clientFile)))) &&
clientFile) {
bool isDirectory;
rv = clientFile->IsDirectory(&isDirectory);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
if (!isDirectory) {
continue;
}
nsString leafName;
rv = clientFile->GetLeafName(leafName);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
Client::Type clientType;
rv = Client::TypeFromText(leafName, clientType);
if (NS_FAILED(rv)) {
UNKNOWN_FILE_WARNING(leafName);
continue;
}
if (clientType != mClientType.Value()) {
hasOtherClient = true;
break;
}
}
bool exists;
rv = file->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
if (hasOtherClient) {
nsAutoString clientDirectoryName;
rv = Client::TypeToText(mClientType.Value(), clientDirectoryName);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
rv = file->Append(clientDirectoryName);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
bool exists;
rv = file->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
if (!exists) {
continue;
}
}
if (!exists) {
continue;
}
bool initialized;
if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
initialized = aQuotaManager->IsOriginInitialized(origin);
} else {
initialized = aQuotaManager->IsTemporaryStorageInitialized();
}
Client* client = aQuotaManager->GetClient(clientType);
MOZ_ASSERT(client);
Atomic<bool> dummy(false);
if (initialized) {
Client* client = aQuotaManager->GetClient(mClientType.Value());
MOZ_ASSERT(client);
Atomic<bool> dummy(false);
rv = client->GetUsageForOrigin(aPersistenceType, group, origin, dummy,
&usageInfo);
} else {
rv = client->InitOrigin(aPersistenceType, group, origin, dummy,
&usageInfo);
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
}
}
@ -7711,6 +7751,12 @@ void ClearRequestBase::DeleteFiles(QuotaManager* aQuotaManager,
NS_WARNING("Failed to remove directory, giving up!");
}
// If it hasn't been initialized, we don't need to update the quota and
// notify the removing client.
if (!initialized) {
return;
}
if (aPersistenceType != PERSISTENCE_TYPE_PERSISTENT) {
if (mClientType.IsNull()) {
aQuotaManager->RemoveQuotaForOrigin(aPersistenceType, group, origin);

Двоичные данные
dom/quota/test/unit/clearStorageForPrincipal_profile.zip Normal file

Двоичный файл не отображается.

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

@ -156,6 +156,17 @@ function clear(callback)
return request;
}
function clearClient(principal, persistence, client, callback)
{
let request =
SpecialPowers._getQuotaManager().clearStoragesForPrincipal(principal,
persistence,
client);
request.callback = callback;
return request;
}
function clearOrigin(principal, persistence, callback)
{
let request =

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

@ -0,0 +1,54 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/**
* This test is an unit test for clearStorageForPrincipal. It verifies that if
* the removing client is the last client in the targeting origin, then it is
* expected to remove the origin directory as well.
*/
async function testSteps()
{
const testingOrigins = [
{
origin: "http://example.com",
path: "storage/default/http+++example.com/",
only_idb: false
},
{
origin: "http://www.mozilla.org",
path: "storage/default/http+++www.mozilla.org/",
only_idb: true
}
];
const removingClient = "idb";
info("Installing package to create the environment");
// The package is manually created and it contains:
// - storage/default/http+++www.mozilla.org/idb/
// - storage/default/http+++www.example.com/idb/
// - storage/default/http+++www.example.com/cache/
installPackage("clearStorageForPrincipal_profile");
let request;
let file;
for (let i = 0; i < testingOrigins.length; ++i) {
info("Clearing");
request = clearClient(getPrincipal(testingOrigins[i].origin), null,
removingClient);
await requestFinished(request);
info("Verifying");
file = getRelativeFile(testingOrigins[i].path + removingClient);
ok(!file.exists(), "Client file doesn't exist");
file = getRelativeFile(testingOrigins[i].path);
if (testingOrigins[i].only_idb) {
ok(!file.exists(), "Origin file doesn't exist");
} else {
ok(file.exists(), "Origin file does exist");
}
}
}

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

@ -6,6 +6,7 @@
head = head.js
support-files =
basics_profile.zip
clearStorageForPrincipal_profile.zip
createLocalStorage_profile.zip
defaultStorageUpgrade_profile.zip
getUsage_profile.zip
@ -26,6 +27,7 @@ support-files =
[test_basics.js]
[test_bad_origin_directory.js]
[test_createLocalStorage.js]
[test_clearStorageForPrincipal.js]
[test_defaultStorageUpgrade.js]
[test_getUsage.js]
[test_groupMismatch.js]

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

@ -4,7 +4,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this WebIDL file is
* https://www.w3.org/TR/payment-request/#paymentrequest-interface
* https://www.w3.org/TR/payment-method-basic-card/
*/
dictionary BasicCardRequest {
@ -12,16 +12,16 @@ dictionary BasicCardRequest {
};
dictionary BasicCardResponse {
DOMString cardholderName;
DOMString cardholderName = "";
required DOMString cardNumber;
DOMString expiryMonth;
DOMString expiryYear;
DOMString cardSecurityCode;
PaymentAddress? billingAddress;
DOMString expiryMonth = "";
DOMString expiryYear = "";
DOMString cardSecurityCode = "";
PaymentAddress? billingAddress = null;
};
dictionary BasicCardChangeDetails {
PaymentAddress? billingAddress;
PaymentAddress? billingAddress = null;
};
dictionary BasicCardErrors {

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

@ -33,46 +33,57 @@ dictionary RTCRtpStreamStats : RTCStats {
DOMString mediaType;
DOMString kind;
DOMString transportId;
DOMString codecId;
// Local only measurements, RTCP related but not communicated via RTCP. Not
// present in RTCP case. See Bug 1367562
};
dictionary RTCReceivedRtpStreamStats: RTCRtpStreamStats {
unsigned long packetsReceived;
unsigned long packetsLost;
double jitter;
unsigned long discardedPackets; // non-standard alias for packetsDiscarded
unsigned long packetsDiscarded;
};
dictionary RTCInboundRtpStreamStats : RTCReceivedRtpStreamStats {
DOMString remoteId;
unsigned long framesDecoded;
unsigned long long bytesReceived;
unsigned long nackCount;
unsigned long firCount;
unsigned long pliCount;
unsigned long nackCount;
unsigned long long qpSum;
DOMString remoteId; // See Bug 1515716
DOMString localId; // See Bug 1515716
DOMString mediaTrackId;
// Video encoder/decoder measurements, not present in RTCP case
double bitrateMean;
double bitrateStdDev;
double framerateMean;
double framerateStdDev;
double bitrateMean; // deprecated, to be removed in Bug 1367562
double bitrateStdDev; // deprecated, to be removed in Bug 1367562
double framerateMean; // deprecated, to be removed in Bug 1367562
double framerateStdDev; // deprecated, to be removed in Bug 1367562
};
dictionary RTCInboundRTPStreamStats : RTCRtpStreamStats {
unsigned long packetsReceived;
unsigned long long bytesReceived;
double jitter;
unsigned long packetsLost;
dictionary RTCRemoteInboundRtpStreamStats : RTCReceivedRtpStreamStats {
DOMString localId;
long long bytesReceived; // Deprecated, to be removed in Bug 1529405
double roundTripTime;
// Video decoder measurement, not present in RTCP case
unsigned long discardedPackets;
unsigned long framesDecoded;
};
dictionary RTCOutboundRTPStreamStats : RTCRtpStreamStats {
dictionary RTCSentRtpStreamStats : RTCRtpStreamStats {
unsigned long packetsSent;
unsigned long long bytesSent;
double targetBitrate; // config encoder bitrate target of this SSRC in bits/s
};
// Video encoder measurements, not present in RTCP case
unsigned long droppedFrames;
dictionary RTCOutboundRtpStreamStats : RTCSentRtpStreamStats {
DOMString remoteId;
unsigned long framesEncoded;
unsigned long long qpSum;
unsigned long nackCount;
unsigned long firCount;
unsigned long pliCount;
double bitrateMean; // deprecated, to be removed in Bug 1367562
double bitrateStdDev; // deprecated, to be removed in Bug 1367562
double framerateMean; // deprecated, to be removed in Bug 1367562
double framerateStdDev; // deprecated, to be removed in Bug 1367562
unsigned long droppedFrames; // non-spec alias for framesDropped
// to be deprecated in Bug 1225720
};
dictionary RTCRemoteOutboundRtpStreamStats : RTCSentRtpStreamStats {
DOMString localId;
};
dictionary RTCMediaStreamTrackStats : RTCStats {
@ -177,27 +188,29 @@ dictionary RTCCodecStats : RTCStats {
// to be received from c++
dictionary RTCStatsReportInternal {
DOMString pcid = "";
sequence<RTCInboundRTPStreamStats> inboundRTPStreamStats;
sequence<RTCOutboundRTPStreamStats> outboundRTPStreamStats;
sequence<RTCRTPContributingSourceStats> rtpContributingSourceStats;
sequence<RTCMediaStreamTrackStats> mediaStreamTrackStats;
sequence<RTCMediaStreamStats> mediaStreamStats;
sequence<RTCTransportStats> transportStats;
sequence<RTCIceComponentStats> iceComponentStats;
sequence<RTCIceCandidatePairStats> iceCandidatePairStats;
sequence<RTCIceCandidateStats> iceCandidateStats;
sequence<RTCCodecStats> codecStats;
DOMString localSdp;
DOMString remoteSdp;
DOMHighResTimeStamp timestamp;
unsigned long iceRestarts;
unsigned long iceRollbacks;
boolean offerer; // Is the PC the offerer
boolean closed; // Is the PC now closed
sequence<RTCIceCandidateStats> trickledIceCandidateStats;
sequence<DOMString> rawLocalCandidates;
sequence<DOMString> rawRemoteCandidates;
DOMString pcid = "";
sequence<RTCInboundRtpStreamStats> inboundRtpStreamStats;
sequence<RTCOutboundRtpStreamStats> outboundRtpStreamStats;
sequence<RTCRemoteInboundRtpStreamStats> remoteInboundRtpStreamStats;
sequence<RTCRemoteOutboundRtpStreamStats> remoteOutboundRtpStreamStats;
sequence<RTCRTPContributingSourceStats> rtpContributingSourceStats;
sequence<RTCMediaStreamTrackStats> mediaStreamTrackStats;
sequence<RTCMediaStreamStats> mediaStreamStats;
sequence<RTCTransportStats> transportStats;
sequence<RTCIceComponentStats> iceComponentStats;
sequence<RTCIceCandidatePairStats> iceCandidatePairStats;
sequence<RTCIceCandidateStats> iceCandidateStats;
sequence<RTCCodecStats> codecStats;
DOMString localSdp;
DOMString remoteSdp;
DOMHighResTimeStamp timestamp;
unsigned long iceRestarts;
unsigned long iceRollbacks;
boolean offerer; // Is the PC the offerer
boolean closed; // Is the PC now closed
sequence<RTCIceCandidateStats> trickledIceCandidateStats;
sequence<DOMString> rawLocalCandidates;
sequence<DOMString> rawRemoteCandidates;
};
[Pref="media.peerconnection.enabled",

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

@ -166,8 +166,7 @@ static AnimationHelper::SampleResult SampleAnimationForProperty(
// Process in order, since later animations override earlier ones.
for (PropertyAnimation& animation : aPropertyAnimations) {
MOZ_ASSERT(
(!animation.mOriginTime.IsNull() &&
animation.mStartTime.type() == MaybeTimeDuration::TTimeDuration) ||
(!animation.mOriginTime.IsNull() && animation.mStartTime.isSome()) ||
animation.mIsNotPlaying,
"If we are playing, we should have an origin time and a start time");
@ -192,7 +191,7 @@ static AnimationHelper::SampleResult SampleAnimationForProperty(
// underflow in the middle of the calulation.
const TimeStamp readyTime =
animation.mOriginTime +
(animation.mStartTime.get_TimeDuration() +
(animation.mStartTime.ref() +
animation.mHoldTime.MultDouble(1.0 / animation.mPlaybackRate));
hasFutureReadyTime =
!readyTime.IsNull() && readyTime > aPreviousFrameTime;
@ -216,11 +215,9 @@ static AnimationHelper::SampleResult SampleAnimationForProperty(
// If the animation is not currently playing, e.g. paused or
// finished, then use the hold time to stay at the same position.
TimeDuration elapsedDuration =
animation.mIsNotPlaying ||
animation.mStartTime.type() != MaybeTimeDuration::TTimeDuration
animation.mIsNotPlaying || animation.mStartTime.isNothing()
? animation.mHoldTime
: (timeStamp - animation.mOriginTime -
animation.mStartTime.get_TimeDuration())
: (timeStamp - animation.mOriginTime - animation.mStartTime.ref())
.MultDouble(animation.mPlaybackRate);
ComputedTiming computedTiming = dom::AnimationEffect::GetComputedTimingAt(

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

@ -52,7 +52,7 @@ struct PropertyAnimation {
dom::Nullable<double> mPortionInSegmentOnLastCompose;
TimeStamp mOriginTime;
MaybeTimeDuration mStartTime;
Maybe<TimeDuration> mStartTime;
TimeDuration mHoldTime;
float mPlaybackRate;
dom::IterationCompositeOperation mIterationComposite;

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

@ -88,23 +88,21 @@ bool AnimationInfo::StartPendingAnimations(const TimeStamp& aReadyTime) {
// If the animation is doing an async update of its playback rate, then we
// want to match whatever its current time would be at *aReadyTime*.
if (!std::isnan(anim.previousPlaybackRate()) &&
anim.startTime().type() == MaybeTimeDuration::TTimeDuration &&
if (!std::isnan(anim.previousPlaybackRate()) && anim.startTime().isSome() &&
!anim.originTime().IsNull() && !anim.isNotPlaying()) {
TimeDuration readyTime = aReadyTime - anim.originTime();
anim.holdTime() = dom::Animation::CurrentTimeFromTimelineTime(
readyTime, anim.startTime().get_TimeDuration(),
anim.previousPlaybackRate());
readyTime, anim.startTime().ref(), anim.previousPlaybackRate());
// Make start time null so that we know to update it below.
anim.startTime() = null_t();
anim.startTime() = Nothing();
}
// If the animation is play-pending, resolve the start time.
if (anim.startTime().type() == MaybeTimeDuration::Tnull_t &&
!anim.originTime().IsNull() && !anim.isNotPlaying()) {
if (anim.startTime().isNothing() && !anim.originTime().IsNull() &&
!anim.isNotPlaying()) {
TimeDuration readyTime = aReadyTime - anim.originTime();
anim.startTime() = dom::Animation::StartTimeFromTimelineTime(
readyTime, anim.holdTime(), anim.playbackRate());
anim.startTime() = Some(dom::Animation::StartTimeFromTimelineTime(
readyTime, anim.holdTime(), anim.playbackRate()));
updated = true;
}
}

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

@ -1006,6 +1006,7 @@ void AndroidDynamicToolbarAnimator::NotifyControllerAnimationStopped(
}
mControllerToolbarHeight = aHeight;
RequestComposite();
}
void AndroidDynamicToolbarAnimator::RequestComposite() {

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

@ -719,9 +719,9 @@ TileDescriptor TileClient::GetTileDescriptor() {
}
return TexturedTileDescriptor(
nullptr, mFrontBuffer->GetIPDLActor(),
mFrontBufferOnWhite ? MaybeTexture(mFrontBufferOnWhite->GetIPDLActor())
: MaybeTexture(null_t()),
nullptr, mFrontBuffer->GetIPDLActor(), Nothing(),
mFrontBufferOnWhite ? Some(mFrontBufferOnWhite->GetIPDLActor())
: Nothing(),
mUpdateRect, readLocked, readLockedOnWhite, wasPlaceholder);
}

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

@ -309,9 +309,9 @@ bool TiledLayerBufferComposite::UseTiles(const SurfaceDescriptorTiles& aTiles,
}
}
if (texturedDesc.textureOnWhite().type() == MaybeTexture::TPTextureParent) {
tile.mTextureHostOnWhite = TextureHost::AsTextureHost(
texturedDesc.textureOnWhite().get_PTextureParent());
if (texturedDesc.textureOnWhiteParent().isSome()) {
tile.mTextureHostOnWhite =
TextureHost::AsTextureHost(texturedDesc.textureOnWhiteParent().ref());
if (texturedDesc.readLockedOnWhite()) {
tile.mTextureHostOnWhite->SetReadLocked();
auto actor = tile.mTextureHostOnWhite->GetIPDLActor();

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

@ -133,10 +133,9 @@ bool CompositableParentManager::ReceiveCompositableUpdate(
// because the recycling logic depends on it.
MOZ_ASSERT(texture->NumCompositableRefs() > 0);
}
if (texturedDesc.textureOnWhite().type() ==
MaybeTexture::TPTextureParent) {
if (texturedDesc.textureOnWhiteParent().isSome()) {
texture = TextureHost::AsTextureHost(
texturedDesc.textureOnWhite().get_PTextureParent());
texturedDesc.textureOnWhiteParent().ref());
if (texture) {
texture->SetLastFwdTransactionId(mFwdTransactionId);
// Make sure that each texture was handled by the compositable

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

@ -162,11 +162,6 @@ union TransformFunction {
TransformMatrix;
};
union MaybeTimeDuration {
null_t;
TimeDuration;
};
union Animatable {
null_t;
float;
@ -214,7 +209,7 @@ struct Animation {
TimeStamp originTime;
// The start time is relative to the originTime. This allows us to represent
// start times in the distant past that cannot be expressed using a TimeStamp.
MaybeTimeDuration startTime;
TimeDuration? startTime;
TimeDuration delay;
TimeDuration endDelay;
// The value of the animation's current time at the moment it was sent to the
@ -374,14 +369,9 @@ union ReadLockDescriptor {
null_t;
};
union MaybeTexture {
PTexture;
null_t;
};
struct TexturedTileDescriptor {
PTexture texture;
MaybeTexture textureOnWhite;
PTexture? textureOnWhite;
IntRect updateRect;
bool readLocked;
bool readLockedOnWhite;
@ -457,11 +447,6 @@ struct OpUseComponentAlphaTextures {
bool readLockedWhite;
};
union MaybeRegion {
nsIntRegion;
null_t;
};
struct OpNotifyNotUsed {
uint64_t TextureId;
uint64_t fwdTransactionId;

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

@ -19,16 +19,6 @@ using gfxImageFormat from "gfxTypes.h";
namespace mozilla {
namespace layers {
union OverlayHandle {
int32_t;
null_t;
};
struct OverlaySource {
OverlayHandle handle;
IntSize size;
};
struct SurfaceDescriptorFileMapping {
WindowsHandle handle;
SurfaceFormat format;

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

@ -38,16 +38,6 @@ struct RefCountedShmem {
Shmem buffer;
};
union OptionalTransform {
Matrix4x4;
void_t;
};
union OptionalOpacity {
float;
void_t;
};
struct OpAddExternalImage {
ExternalImageId externalImageId;
ImageKey key;

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

@ -158,10 +158,10 @@ void VRDisplayClient::FireGamepadEvents() {
// axis count. So, we need to check if they are more than zero.
if ((lastState.controllerName[0] == '\0' || !existing) &&
(state.numButtons > 0 || state.numAxes > 0)) {
dom::GamepadAdded info(NS_ConvertUTF8toUTF16(state.controllerName),
dom::GamepadMappingType::_empty, state.hand,
mDisplayInfo.mDisplayID, state.numButtons,
state.numAxes, state.numHaptics);
dom::GamepadAdded info(
NS_ConvertUTF8toUTF16(state.controllerName, kVRControllerNameMaxLen),
dom::GamepadMappingType::_empty, state.hand, mDisplayInfo.mDisplayID,
state.numButtons, state.numAxes, state.numHaptics);
dom::GamepadChangeEventBody body(info);
dom::GamepadChangeEvent event(gamepadId, dom::GamepadServiceType::VR,
body);

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

@ -186,7 +186,7 @@ void VRDisplayHost::StartFrame() {
TimeStamp now = TimeStamp::Now();
#if defined(MOZ_WIDGET_ANDROID)
const TimeStamp lastFrameStart =
mDisplayInfo.mLastFrameStart[mDisplayInfo.mFrameId % kVRMaxLatencyFrames];
mLastFrameStart[mDisplayInfo.mFrameId % kVRMaxLatencyFrames];
const bool isPresenting = mLastUpdateDisplayInfo.GetPresentingGroups() != 0;
double duration =
lastFrameStart.IsNull() ? 0.0 : (now - lastFrameStart).ToMilliseconds();
@ -204,7 +204,7 @@ void VRDisplayHost::StartFrame() {
++mDisplayInfo.mFrameId;
size_t bufferIndex = mDisplayInfo.mFrameId % kVRMaxLatencyFrames;
mDisplayInfo.mLastSensorState[bufferIndex] = GetSensorState();
mDisplayInfo.mLastFrameStart[bufferIndex] = now;
mLastFrameStart[bufferIndex] = now;
mFrameStarted = true;
#if defined(MOZ_WIDGET_ANDROID)
mLastStartedFrame = mDisplayInfo.mFrameId;
@ -256,7 +256,7 @@ void VRDisplayHost::CheckWatchDog() {
// If content fails to call VRDisplay.submitFrame, we must eventually
// time-out and trigger a new frame.
TimeStamp lastFrameStart =
mDisplayInfo.mLastFrameStart[mDisplayInfo.mFrameId % kVRMaxLatencyFrames];
mLastFrameStart[mDisplayInfo.mFrameId % kVRMaxLatencyFrames];
if (lastFrameStart.IsNull()) {
bShouldStartFrame = true;
} else {

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

@ -85,6 +85,7 @@ class VRDisplayHost {
const gfx::Rect& aRightEyeRect) = 0;
VRDisplayInfo mDisplayInfo;
TimeStamp mLastFrameStart[kVRMaxLatencyFrames];
nsTArray<VRLayerParent*> mLayers;
// Weak reference to mLayers entries are cleared in

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

@ -118,8 +118,8 @@ VRManager::~VRManager() {
void VRManager::Destroy() {
StopTasks();
mVRDisplays.Clear();
mVRControllers.Clear();
mVRDisplayIDs.Clear();
mVRControllerIDs.Clear();
for (uint32_t i = 0; i < mManagers.Length(); ++i) {
mManagers[i]->Destroy();
}
@ -133,8 +133,8 @@ void VRManager::Destroy() {
}
void VRManager::Shutdown() {
mVRDisplays.Clear();
mVRControllers.Clear();
mVRDisplayIDs.Clear();
mVRControllerIDs.Clear();
for (uint32_t i = 0; i < mManagers.Length(); ++i) {
mManagers[i]->Shutdown();
}
@ -295,7 +295,7 @@ uint32_t VRManager::GetOptimalTaskInterval() {
* frequently.
*/
bool wantGranularTasks = mVRDisplaysRequested || mVRControllersRequested ||
mVRDisplays.Count() || mVRControllers.Count();
mVRDisplayIDs.Length() || mVRControllerIDs.Length();
if (wantGranularTasks) {
return kVRActiveTaskInterval;
}
@ -315,9 +315,11 @@ void VRManager::Run1msTasks(double aDeltaTime) {
manager->Run1msTasks(aDeltaTime);
}
for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
gfx::VRDisplayHost* display = iter.UserData();
display->Run1msTasks(aDeltaTime);
for (const auto& displayID : mVRDisplayIDs) {
RefPtr<VRDisplayHost> display(GetDisplay(displayID));
if (display) {
display->Run1msTasks(aDeltaTime);
}
}
}
@ -335,9 +337,11 @@ void VRManager::Run10msTasks() {
manager->Run10msTasks();
}
for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
gfx::VRDisplayHost* display = iter.UserData();
display->Run10msTasks();
for (const auto& displayID : mVRDisplayIDs) {
RefPtr<VRDisplayHost> display(GetDisplay(displayID));
if (display) {
display->Run10msTasks();
}
}
}
@ -365,9 +369,11 @@ void VRManager::Run100msTasks() {
manager->Run100msTasks();
}
for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
gfx::VRDisplayHost* display = iter.UserData();
display->Run100msTasks();
for (const auto& displayID : mVRDisplayIDs) {
RefPtr<VRDisplayHost> display(GetDisplay(displayID));
if (display) {
display->Run100msTasks();
}
}
}
@ -481,6 +487,27 @@ void VRManager::EnumerateVRDisplays() {
return;
}
}
nsTArray<RefPtr<gfx::VRDisplayHost>> displays;
for (const auto& manager : mManagers) {
manager->GetHMDs(displays);
}
mVRDisplayIDs.Clear();
for (const auto& display : displays) {
mVRDisplayIDs.AppendElement(display->GetDisplayInfo().GetDisplayID());
}
nsTArray<RefPtr<gfx::VRControllerHost>> controllers;
for (const auto& manager : mManagers) {
manager->GetControllers(controllers);
}
mVRControllerIDs.Clear();
for (const auto& controller : controllers) {
mVRControllerIDs.AppendElement(
controller->GetControllerInfo().GetControllerID());
}
}
void VRManager::RefreshVRDisplays(bool aMustDispatch) {
@ -510,7 +537,7 @@ void VRManager::RefreshVRDisplays(bool aMustDispatch) {
bool displayInfoChanged = false;
bool displaySetChanged = false;
if (displays.Length() != mVRDisplays.Count()) {
if (displays.Length() != mVRDisplayIDs.Length()) {
// Catch cases where a VR display has been removed
displaySetChanged = true;
}
@ -531,9 +558,9 @@ void VRManager::RefreshVRDisplays(bool aMustDispatch) {
// Rebuild the HashMap if there are additions or removals
if (displaySetChanged) {
mVRDisplays.Clear();
mVRDisplayIDs.Clear();
for (const auto& display : displays) {
mVRDisplays.Put(display->GetDisplayInfo().GetDisplayID(), display);
mVRDisplayIDs.AppendElement(display->GetDisplayInfo().GetDisplayID());
}
}
@ -557,36 +584,77 @@ void VRManager::DispatchVRDisplayInfoUpdate() {
*/
void VRManager::GetVRDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayInfo) {
aDisplayInfo.Clear();
for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
gfx::VRDisplayHost* display = iter.UserData();
aDisplayInfo.AppendElement(VRDisplayInfo(display->GetDisplayInfo()));
for (const auto& displayID : mVRDisplayIDs) {
RefPtr<VRDisplayHost> display(GetDisplay(displayID));
if (display) {
aDisplayInfo.AppendElement(display->GetDisplayInfo());
}
}
}
// Verify aDisplayID matches the exisiting displayID from mVRDisplayIDs list,
// then using the exiting displayID to get VRDisplayHost from VRManagers.
RefPtr<gfx::VRDisplayHost> VRManager::GetDisplay(const uint32_t& aDisplayID) {
RefPtr<gfx::VRDisplayHost> display;
if (mVRDisplays.Get(aDisplayID, getter_AddRefs(display))) {
return display;
bool found = false;
for (const auto& displayID : mVRDisplayIDs) {
if (displayID == aDisplayID) {
found = true;
break;
}
}
if (found) {
nsTArray<RefPtr<gfx::VRDisplayHost>> displays;
for (const auto& manager : mManagers) {
manager->GetHMDs(displays);
for (const auto& display : displays) {
if (display->GetDisplayInfo().GetDisplayID() == aDisplayID) {
return display;
}
}
}
}
return nullptr;
}
// Verify aControllerID matches the exisiting controllerID from mVRControllerIDs
// list, then using the exiting controllerID to get VRControllerHost from
// VRManagers.
RefPtr<gfx::VRControllerHost> VRManager::GetController(
const uint32_t& aControllerID) {
RefPtr<gfx::VRControllerHost> controller;
if (mVRControllers.Get(aControllerID, getter_AddRefs(controller))) {
return controller;
bool found = false;
for (const auto& controllerID : mVRControllerIDs) {
if (controllerID == aControllerID) {
found = true;
break;
}
}
if (found) {
nsTArray<RefPtr<gfx::VRControllerHost>> controllers;
for (const auto& manager : mManagers) {
manager->GetControllers(controllers);
for (const auto& controller : controllers) {
if (controller->GetControllerInfo().GetControllerID() ==
aControllerID) {
return controller;
}
}
}
}
return nullptr;
}
void VRManager::GetVRControllerInfo(
nsTArray<VRControllerInfo>& aControllerInfo) {
aControllerInfo.Clear();
for (auto iter = mVRControllers.Iter(); !iter.Done(); iter.Next()) {
gfx::VRControllerHost* controller = iter.UserData();
aControllerInfo.AppendElement(
VRControllerInfo(controller->GetControllerInfo()));
for (const auto& controllerID : mVRControllerIDs) {
RefPtr<VRControllerHost> controller(GetController(controllerID));
if (controller) {
aControllerInfo.AppendElement(controller->GetControllerInfo());
}
}
}
@ -602,7 +670,7 @@ void VRManager::RefreshVRControllers() {
bool controllerInfoChanged = false;
if (controllers.Length() != mVRControllers.Count()) {
if (controllers.Length() != mVRControllerIDs.Length()) {
// Catch cases where VR controllers has been removed
controllerInfoChanged = true;
}
@ -616,10 +684,10 @@ void VRManager::RefreshVRControllers() {
}
if (controllerInfoChanged) {
mVRControllers.Clear();
mVRControllerIDs.Clear();
for (const auto& controller : controllers) {
mVRControllers.Put(controller->GetControllerInfo().GetControllerID(),
controller);
mVRControllerIDs.AppendElement(
controller->GetControllerInfo().GetControllerID());
}
}
}
@ -650,7 +718,7 @@ void VRManager::RemoveControllers() {
for (uint32_t i = 0; i < mManagers.Length(); ++i) {
mManagers[i]->RemoveControllers();
}
mVRControllers.Clear();
mVRControllerIDs.Clear();
}
void VRManager::CreateVRTestSystem() {

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

@ -95,14 +95,8 @@ class VRManager {
typedef nsTArray<RefPtr<VRSystemManager>> VRSystemManagerArray;
VRSystemManagerArray mManagers;
typedef nsRefPtrHashtable<nsUint32HashKey, gfx::VRDisplayHost>
VRDisplayHostHashMap;
VRDisplayHostHashMap mVRDisplays;
typedef nsRefPtrHashtable<nsUint32HashKey, gfx::VRControllerHost>
VRControllerHostHashMap;
VRControllerHostHashMap mVRControllers;
nsTArray<uint32_t> mVRDisplayIDs;
nsTArray<uint32_t> mVRControllerIDs;
Atomic<bool> mInitialized;

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

@ -69,7 +69,6 @@ struct VRDisplayInfo {
VRControllerState mControllerState[kVRControllerMaxCount];
VRHMDSensorState mLastSensorState[kVRMaxLatencyFrames];
TimeStamp mLastFrameStart[kVRMaxLatencyFrames];
const VRHMDSensorState& GetSensorState() const {
return mLastSensorState[mFrameId % kVRMaxLatencyFrames];
}

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

@ -335,8 +335,7 @@ void VRDisplayExternal::VibrateHaptic(uint32_t aControllerIdx,
mDisplayInfo.mLastSensorState[bufferIndex].inputFrameID;
bestSlot.controllerIndex = aControllerIdx;
bestSlot.hapticIndex = aHapticIndex;
bestSlot.pulseStart =
(now - mDisplayInfo.mLastFrameStart[bufferIndex]).ToSeconds();
bestSlot.pulseStart = (now - mLastFrameStart[bufferIndex]).ToSeconds();
bestSlot.pulseDuration = aDuration;
bestSlot.pulseIntensity = aIntensity;
// Convert from seconds to ms

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

@ -17,19 +17,6 @@
namespace IPC {
template <>
struct ParamTraits<mozilla::gfx::VRDeviceType>
: public ContiguousEnumSerializer<
mozilla::gfx::VRDeviceType, mozilla::gfx::VRDeviceType(0),
mozilla::gfx::VRDeviceType(
mozilla::gfx::VRDeviceType::NumVRDeviceTypes)> {};
template <>
struct ParamTraits<mozilla::gfx::VRDisplayCapabilityFlags>
: public BitFlagsEnumSerializer<
mozilla::gfx::VRDisplayCapabilityFlags,
mozilla::gfx::VRDisplayCapabilityFlags::Cap_All> {};
template <>
struct ParamTraits<mozilla::gfx::OpenVRControllerType>
: public ContiguousEnumSerializer<
@ -37,332 +24,19 @@ struct ParamTraits<mozilla::gfx::OpenVRControllerType>
mozilla::gfx::OpenVRControllerType::Vive,
mozilla::gfx::OpenVRControllerType::NumOpenVRControllerTypes> {};
// VRHMDSensorState is POD, we can use PlainOldDataSerializer
static_assert(std::is_pod<mozilla::gfx::VRHMDSensorState>::value,
"mozilla::gfx::VRHMDSensorState must be a POD type.");
template <>
struct ParamTraits<mozilla::gfx::VRDisplayState> {
typedef mozilla::gfx::VRDisplayState paramType;
static void Write(Message* aMsg, const paramType& aParam) {
// TODO - VRDisplayState is asserted to be a POD type
// A simple memcpy may be sufficient here, or
// this code can be refactored out if we use
// shmem between the VR and content process.
nsCString displayName;
displayName.Assign(aParam.displayName);
WriteParam(aMsg, displayName);
WriteParam(aMsg, aParam.capabilityFlags);
WriteParam(aMsg, aParam.eyeResolution.width);
WriteParam(aMsg, aParam.eyeResolution.height);
WriteParam(aMsg, aParam.suppressFrames);
WriteParam(aMsg, aParam.isConnected);
WriteParam(aMsg, aParam.isMounted);
WriteParam(aMsg, aParam.stageSize.width);
WriteParam(aMsg, aParam.stageSize.height);
WriteParam(aMsg, aParam.lastSubmittedFrameId);
WriteParam(aMsg, aParam.presentingGeneration);
for (int i = 0; i < 16; i++) {
// TODO - Should probably memcpy the whole array or
// convert Maxtrix4x4 to a POD type and use it
// instead
WriteParam(aMsg, aParam.sittingToStandingTransform[i]);
}
for (int i = 0; i < mozilla::gfx::VRDisplayState::NumEyes; i++) {
WriteParam(aMsg, aParam.eyeFOV[i]);
WriteParam(aMsg, aParam.eyeTranslation[i].x);
WriteParam(aMsg, aParam.eyeTranslation[i].y);
WriteParam(aMsg, aParam.eyeTranslation[i].z);
}
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
nsCString displayName;
if (!ReadParam(aMsg, aIter, &(displayName)) ||
!ReadParam(aMsg, aIter, &(aResult->capabilityFlags)) ||
!ReadParam(aMsg, aIter, &(aResult->eyeResolution.width)) ||
!ReadParam(aMsg, aIter, &(aResult->eyeResolution.height)) ||
!ReadParam(aMsg, aIter, &(aResult->suppressFrames)) ||
!ReadParam(aMsg, aIter, &(aResult->isConnected)) ||
!ReadParam(aMsg, aIter, &(aResult->isMounted)) ||
!ReadParam(aMsg, aIter, &(aResult->stageSize.width)) ||
!ReadParam(aMsg, aIter, &(aResult->stageSize.height)) ||
!ReadParam(aMsg, aIter, &(aResult->lastSubmittedFrameId)) ||
!ReadParam(aMsg, aIter, &(aResult->presentingGeneration))) {
return false;
}
for (int i = 0; i < 16; i++) {
if (!ReadParam(aMsg, aIter, &(aResult->sittingToStandingTransform[i]))) {
return false;
}
}
strncpy(aResult->displayName, displayName.BeginReading(),
mozilla::gfx::kVRDisplayNameMaxLen);
for (int i = 0; i < mozilla::gfx::VRDisplayState::NumEyes; i++) {
if (!ReadParam(aMsg, aIter, &(aResult->eyeFOV[i])) ||
!ReadParam(aMsg, aIter, &(aResult->eyeTranslation[i].x)) ||
!ReadParam(aMsg, aIter, &(aResult->eyeTranslation[i].y)) ||
!ReadParam(aMsg, aIter, &(aResult->eyeTranslation[i].z))) {
return false;
}
}
return true;
}
};
struct ParamTraits<mozilla::gfx::VRHMDSensorState>
: public PlainOldDataSerializer<mozilla::gfx::VRHMDSensorState> {};
// VRDisplayInfo is POD, we can use PlainOldDataSerializer
static_assert(std::is_pod<mozilla::gfx::VRDisplayInfo>::value,
"mozilla::gfx::VRDisplayInfo must be a POD type.");
template <>
struct ParamTraits<mozilla::gfx::VRDisplayInfo> {
typedef mozilla::gfx::VRDisplayInfo paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.mType);
WriteParam(aMsg, aParam.mDisplayID);
WriteParam(aMsg, aParam.mPresentingGroups);
WriteParam(aMsg, aParam.mGroupMask);
WriteParam(aMsg, aParam.mFrameId);
WriteParam(aMsg, aParam.mDisplayState);
for (size_t i = 0; i < mozilla::ArrayLength(aParam.mLastSensorState); i++) {
WriteParam(aMsg, aParam.mLastSensorState[i]);
}
for (size_t i = 0; i < mozilla::ArrayLength(aParam.mLastFrameStart); i++) {
WriteParam(aMsg, aParam.mLastFrameStart[i]);
}
for (size_t i = 0; i < mozilla::ArrayLength(aParam.mControllerState); i++) {
WriteParam(aMsg, aParam.mControllerState[i]);
}
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
if (!ReadParam(aMsg, aIter, &(aResult->mType)) ||
!ReadParam(aMsg, aIter, &(aResult->mDisplayID)) ||
!ReadParam(aMsg, aIter, &(aResult->mPresentingGroups)) ||
!ReadParam(aMsg, aIter, &(aResult->mGroupMask)) ||
!ReadParam(aMsg, aIter, &(aResult->mFrameId)) ||
!ReadParam(aMsg, aIter, &(aResult->mDisplayState))) {
return false;
}
for (size_t i = 0; i < mozilla::ArrayLength(aResult->mLastSensorState);
i++) {
if (!ReadParam(aMsg, aIter, &(aResult->mLastSensorState[i]))) {
return false;
}
}
for (size_t i = 0; i < mozilla::ArrayLength(aResult->mLastFrameStart);
i++) {
if (!ReadParam(aMsg, aIter, &(aResult->mLastFrameStart[i]))) {
return false;
}
}
for (size_t i = 0; i < mozilla::ArrayLength(aResult->mControllerState);
i++) {
if (!ReadParam(aMsg, aIter, &(aResult->mControllerState[i]))) {
return false;
}
}
return true;
}
};
template <>
struct ParamTraits<mozilla::gfx::VRPose> {
typedef mozilla::gfx::VRPose paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.orientation[0]);
WriteParam(aMsg, aParam.orientation[1]);
WriteParam(aMsg, aParam.orientation[2]);
WriteParam(aMsg, aParam.orientation[3]);
WriteParam(aMsg, aParam.position[0]);
WriteParam(aMsg, aParam.position[1]);
WriteParam(aMsg, aParam.position[2]);
WriteParam(aMsg, aParam.angularVelocity[0]);
WriteParam(aMsg, aParam.angularVelocity[1]);
WriteParam(aMsg, aParam.angularVelocity[2]);
WriteParam(aMsg, aParam.angularAcceleration[0]);
WriteParam(aMsg, aParam.angularAcceleration[1]);
WriteParam(aMsg, aParam.angularAcceleration[2]);
WriteParam(aMsg, aParam.linearVelocity[0]);
WriteParam(aMsg, aParam.linearVelocity[1]);
WriteParam(aMsg, aParam.linearVelocity[2]);
WriteParam(aMsg, aParam.linearAcceleration[0]);
WriteParam(aMsg, aParam.linearAcceleration[1]);
WriteParam(aMsg, aParam.linearAcceleration[2]);
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
if (!ReadParam(aMsg, aIter, &(aResult->orientation[0])) ||
!ReadParam(aMsg, aIter, &(aResult->orientation[1])) ||
!ReadParam(aMsg, aIter, &(aResult->orientation[2])) ||
!ReadParam(aMsg, aIter, &(aResult->orientation[3])) ||
!ReadParam(aMsg, aIter, &(aResult->position[0])) ||
!ReadParam(aMsg, aIter, &(aResult->position[1])) ||
!ReadParam(aMsg, aIter, &(aResult->position[2])) ||
!ReadParam(aMsg, aIter, &(aResult->angularVelocity[0])) ||
!ReadParam(aMsg, aIter, &(aResult->angularVelocity[1])) ||
!ReadParam(aMsg, aIter, &(aResult->angularVelocity[2])) ||
!ReadParam(aMsg, aIter, &(aResult->angularAcceleration[0])) ||
!ReadParam(aMsg, aIter, &(aResult->angularAcceleration[1])) ||
!ReadParam(aMsg, aIter, &(aResult->angularAcceleration[2])) ||
!ReadParam(aMsg, aIter, &(aResult->linearVelocity[0])) ||
!ReadParam(aMsg, aIter, &(aResult->linearVelocity[1])) ||
!ReadParam(aMsg, aIter, &(aResult->linearVelocity[2])) ||
!ReadParam(aMsg, aIter, &(aResult->linearAcceleration[0])) ||
!ReadParam(aMsg, aIter, &(aResult->linearAcceleration[1])) ||
!ReadParam(aMsg, aIter, &(aResult->linearAcceleration[2]))) {
return false;
}
return true;
}
};
template <>
struct ParamTraits<mozilla::gfx::VRHMDSensorState> {
typedef mozilla::gfx::VRHMDSensorState paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.timestamp);
WriteParam(aMsg, aParam.inputFrameID);
WriteParam(aMsg, aParam.flags);
WriteParam(aMsg, aParam.pose);
for (size_t i = 0; i < mozilla::ArrayLength(aParam.leftViewMatrix); i++) {
WriteParam(aMsg, aParam.leftViewMatrix[i]);
}
for (size_t i = 0; i < mozilla::ArrayLength(aParam.rightViewMatrix); i++) {
WriteParam(aMsg, aParam.rightViewMatrix[i]);
}
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
if (!ReadParam(aMsg, aIter, &(aResult->timestamp)) ||
!ReadParam(aMsg, aIter, &(aResult->inputFrameID)) ||
!ReadParam(aMsg, aIter, &(aResult->flags)) ||
!ReadParam(aMsg, aIter, &(aResult->pose))) {
return false;
}
for (size_t i = 0; i < mozilla::ArrayLength(aResult->leftViewMatrix); i++) {
if (!ReadParam(aMsg, aIter, &(aResult->leftViewMatrix[i]))) {
return false;
}
}
for (size_t i = 0; i < mozilla::ArrayLength(aResult->rightViewMatrix);
i++) {
if (!ReadParam(aMsg, aIter, &(aResult->rightViewMatrix[i]))) {
return false;
}
}
return true;
}
};
template <>
struct ParamTraits<mozilla::gfx::VRFieldOfView> {
typedef mozilla::gfx::VRFieldOfView paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.upDegrees);
WriteParam(aMsg, aParam.rightDegrees);
WriteParam(aMsg, aParam.downDegrees);
WriteParam(aMsg, aParam.leftDegrees);
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
if (!ReadParam(aMsg, aIter, &(aResult->upDegrees)) ||
!ReadParam(aMsg, aIter, &(aResult->rightDegrees)) ||
!ReadParam(aMsg, aIter, &(aResult->downDegrees)) ||
!ReadParam(aMsg, aIter, &(aResult->leftDegrees))) {
return false;
}
return true;
}
};
template <>
struct ParamTraits<mozilla::gfx::VRControllerState> {
typedef mozilla::gfx::VRControllerState paramType;
static void Write(Message* aMsg, const paramType& aParam) {
nsCString controllerName;
controllerName.Assign(
aParam.controllerName); // FINDME!! HACK! - Bounds checking?
WriteParam(aMsg, controllerName);
WriteParam(aMsg, aParam.hand);
WriteParam(aMsg, aParam.numButtons);
WriteParam(aMsg, aParam.numAxes);
WriteParam(aMsg, aParam.numHaptics);
WriteParam(aMsg, aParam.buttonPressed);
WriteParam(aMsg, aParam.buttonTouched);
WriteParam(aMsg, aParam.flags);
WriteParam(aMsg, aParam.pose);
WriteParam(aMsg, aParam.isPositionValid);
WriteParam(aMsg, aParam.isOrientationValid);
for (size_t i = 0; i < mozilla::ArrayLength(aParam.axisValue); i++) {
WriteParam(aMsg, aParam.axisValue[i]);
}
for (size_t i = 0; i < mozilla::ArrayLength(aParam.triggerValue); i++) {
WriteParam(aMsg, aParam.triggerValue[i]);
}
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
nsCString controllerName;
if (!ReadParam(aMsg, aIter, &(controllerName)) ||
!ReadParam(aMsg, aIter, &(aResult->hand)) ||
!ReadParam(aMsg, aIter, &(aResult->numButtons)) ||
!ReadParam(aMsg, aIter, &(aResult->numAxes)) ||
!ReadParam(aMsg, aIter, &(aResult->numHaptics)) ||
!ReadParam(aMsg, aIter, &(aResult->buttonPressed)) ||
!ReadParam(aMsg, aIter, &(aResult->buttonTouched)) ||
!ReadParam(aMsg, aIter, &(aResult->flags)) ||
!ReadParam(aMsg, aIter, &(aResult->pose)) ||
!ReadParam(aMsg, aIter, &(aResult->isPositionValid)) ||
!ReadParam(aMsg, aIter, &(aResult->isOrientationValid))) {
return false;
}
for (size_t i = 0; i < mozilla::ArrayLength(aResult->axisValue); i++) {
if (!ReadParam(aMsg, aIter, &(aResult->axisValue[i]))) {
return false;
}
}
for (size_t i = 0; i < mozilla::ArrayLength(aResult->triggerValue); i++) {
if (!ReadParam(aMsg, aIter, &(aResult->triggerValue[i]))) {
return false;
}
}
strncpy(aResult->controllerName, controllerName.BeginReading(),
mozilla::gfx::kVRControllerNameMaxLen); // FINDME! TODO! HACK!
// Safe? Better way?
return true;
}
};
template <>
struct ParamTraits<mozilla::gfx::VRControllerInfo> {
typedef mozilla::gfx::VRControllerInfo paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.mType);
WriteParam(aMsg, aParam.mControllerID);
WriteParam(aMsg, aParam.mMappingType);
WriteParam(aMsg, aParam.mControllerState);
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
if (!ReadParam(aMsg, aIter, &(aResult->mType)) ||
!ReadParam(aMsg, aIter, &(aResult->mControllerID)) ||
!ReadParam(aMsg, aIter, &(aResult->mMappingType)) ||
!ReadParam(aMsg, aIter, &(aResult->mControllerState))) {
return false;
}
return true;
}
};
struct ParamTraits<mozilla::gfx::VRDisplayInfo>
: public PlainOldDataSerializer<mozilla::gfx::VRDisplayInfo> {};
template <>
struct ParamTraits<mozilla::gfx::VRSubmitFrameResultInfo> {

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

@ -104,9 +104,10 @@ static bool DepthFirstSearchUse(MIRGenerator* mir,
}
if (cphi->isInWorklist() || cphi == producer) {
// We are already iterating over the uses of this Phi
// instruction. Skip it.
continue;
// We are already iterating over the uses of this Phi instruction which
// are part of a loop, instead of trying to handle loops, conservatively
// mark them as used.
return push(producer, use);
}
if (cphi->getUsageAnalysis() == PhiUsage::Unused) {

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

@ -14,6 +14,11 @@ slow script test262/built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1499448
skip script non262/reflect-parse/class-fields.js
# Windows10-aarch64 fails certain tests.
# https://bugzilla.mozilla.org/show_bug.cgi?id=1526003
# https://bugzilla.mozilla.org/show_bug.cgi?id=1526012
skip-if((xulRuntime.XPCOMABI.match(/aarch64/))&&(xulRuntime.OS=="WINNT")) script non262/Math/fround.js
skip-if((xulRuntime.XPCOMABI.match(/aarch64/))&&(xulRuntime.OS=="WINNT")) script non262/Math/log2-approx.js
###########################################################################
# Generated jstests.list for test262 when inline |reftest| isn't possible #

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

@ -5,6 +5,66 @@
from __future__ import absolute_import
from marionette_driver.marionette import Actions
class CaretActions(Actions):
def __init__(self, marionette):
super(CaretActions, self).__init__(marionette)
self._reset_action_chain()
def _reset_action_chain(self):
self.mouse_chain = self.sequence("pointer", "pointer_id", {"pointerType": "mouse"})
self.key_chain = self.sequence("key", "keyboard_id")
def flick(self, element, x1, y1, x2, y2, duration=200):
"""Perform a flick gesture on the target element.
:param element: The element to perform the flick gesture on.
:param x1: Starting x-coordinate of flick, relative to the top left
corner of the element.
:param y1: Starting y-coordinate of flick, relative to the top left
corner of the element.
:param x2: Ending x-coordinate of flick, relative to the top left
corner of the element.
:param y2: Ending y-coordinate of flick, relative to the top left
corner of the element.
"""
rect = element.rect
el_x, el_y = rect['x'], rect['y']
# Add element's (x, y) to make the coordinate relative to the viewport.
from_x, from_y = int(el_x + x1), int(el_y + y1)
to_x, to_y = int(el_x + x2), int(el_y + y2)
self.mouse_chain.pointer_move(from_x, from_y) \
.pointer_down() \
.pointer_move(to_x, to_y, duration=duration) \
.pointer_up()
return self
def send_keys(self, keys):
"""Perform a keyDown and keyUp action for each character in `keys`.
:param keys: String of keys to perform key actions with.
"""
self.key_chain.send_keys(keys)
return self
def perform(self):
"""Perform the action chain built so far to the server side for execution
and clears the current chain of actions.
Warning: This method performs all the mouse actions before all the key
actions!
"""
self.mouse_chain.perform()
self.key_chain.perform()
self._reset_action_chain()
class SelectionManager(object):
'''Interface for manipulating the selection and carets of the element.

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

@ -4,10 +4,17 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import string
import sys
import os
# Add this directory to the import path.
sys.path.append(os.path.dirname(__file__))
from selection import (
CaretActions,
SelectionManager,
)
from marionette_driver.by import By
from marionette_driver.legacy_actions import Actions
from marionette_driver.selection import SelectionManager
from marionette_harness.marionette_test import (
MarionetteTestCase,
parameterized,
@ -41,7 +48,11 @@ class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
self.hide_carets_for_mouse: False,
}
self.marionette.set_prefs(self.prefs)
self.actions = Actions(self.marionette)
self.actions = CaretActions(self.marionette)
def tearDown(self):
self.marionette.actions.release()
super(AccessibleCaretCursorModeTestCase, self).tearDown()
def open_test_html(self, test_html):
self.marionette.navigate(self.marionette.absolute_url(test_html))
@ -72,7 +83,7 @@ class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
self.actions.flick(el, first_caret0_x, first_caret0_y,
first_caret1_x, first_caret1_y).perform()
self.actions.key_down(content_to_add).key_up(content_to_add).perform()
self.actions.send_keys(content_to_add).perform()
self.assertEqual(target_content, sel.content)
@parameterized(_input_id, el_id=_input_id)
@ -95,7 +106,7 @@ class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
dest_x, dest_y = el.rect['width'], el.rect['height']
self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
self.actions.key_down(content_to_add).key_up(content_to_add).perform()
self.actions.send_keys(content_to_add).perform()
self.assertEqual(target_content, sel.content)
@parameterized(_input_id, el_id=_input_id)
@ -125,7 +136,7 @@ class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
# Move first caret to the front of the input box.
self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
self.actions.key_down(content_to_add).key_up(content_to_add).perform()
self.actions.send_keys(content_to_add).perform()
self.assertEqual(target_content, sel.content)
def test_caret_not_appear_when_typing_in_scrollable_content(self):
@ -174,7 +185,7 @@ class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
# Drag the caret down by 50px, and insert '!'.
self.actions.flick(el, x, y, x, y + 50).perform()
self.actions.key_down(content_to_add).key_up(content_to_add).perform()
self.actions.send_keys(content_to_add).perform()
self.assertNotEqual(non_target_content, sel.content)
@parameterized(_input_id, el_id=_input_id)
@ -196,9 +207,9 @@ class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
el.tap(*sel.cursor_location())
x, y = sel.first_caret_location()
# Drag the caret up by 50px, and insert '!'.
self.actions.flick(el, x, y, x, y - 50).perform()
self.actions.key_down(content_to_add).key_up(content_to_add).perform()
# Drag the caret up by 40px, and insert '!'.
self.actions.flick(el, x, y, x, y - 40).perform()
self.actions.send_keys(content_to_add).perform()
self.assertNotEqual(non_target_content, sel.content)
def test_drag_caret_from_front_to_end_across_columns(self):
@ -224,7 +235,7 @@ class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
# Drag the first caret to the bottom-right corner of the element.
self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
self.actions.key_down(content_to_add).key_up(content_to_add).perform()
self.actions.send_keys(content_to_add).perform()
self.assertEqual(target_content, sel.content)
def test_move_cursor_to_front_by_dragging_caret_to_front_br_element(self):
@ -258,5 +269,5 @@ class AccessibleCaretCursorModeTestCase(MarionetteTestCase):
# Move first caret to the front of the input box.
self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
self.actions.key_down(content_to_add_1).key_up(content_to_add_1).perform()
self.actions.send_keys(content_to_add_1).perform()
self.assertEqual(target_content, sel.content)

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