зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to mozilla-central. a=merge
This commit is contained in:
Коммит
a7315d7841
|
@ -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/**",
|
||||
|
|
|
@ -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 selector’s 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);
|
||||
|
|
Двоичный файл не отображается.
|
@ -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)
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче