зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to fx-team
This commit is contained in:
Коммит
f5994ff800
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1115998 - (DOMString or sequence<DOMString>) needs binding flush (Bug 1103153)
|
||||
Bug 1006707 - (DOMString or sequence<DOMString>) needs binding flush (Bug 1103153)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="917b6c36717fddc6e71ffc1ec249633c8044c93c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="917b6c36717fddc6e71ffc1ec249633c8044c93c"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="917b6c36717fddc6e71ffc1ec249633c8044c93c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fe91ec3af5396edab45b15e546e21613785724b5"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="917b6c36717fddc6e71ffc1ec249633c8044c93c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="917b6c36717fddc6e71ffc1ec249633c8044c93c"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="917b6c36717fddc6e71ffc1ec249633c8044c93c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="917b6c36717fddc6e71ffc1ec249633c8044c93c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fe91ec3af5396edab45b15e546e21613785724b5"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "917b6c36717fddc6e71ffc1ec249633c8044c93c",
|
||||
"git_revision": "966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "3033c2214b5863d8ac50d2067b34c5cb02fb054d",
|
||||
"revision": "9a9aef701b1c69e9fb76eb3cc629be10aecfa3f3",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="917b6c36717fddc6e71ffc1ec249633c8044c93c"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="917b6c36717fddc6e71ffc1ec249633c8044c93c"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="917b6c36717fddc6e71ffc1ec249633c8044c93c"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fe91ec3af5396edab45b15e546e21613785724b5"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="917b6c36717fddc6e71ffc1ec249633c8044c93c"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="966b3a7a13a7f0d5b86cbc9e64cb78d43ec7dba8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -1703,7 +1703,7 @@ pref("plain_text.wrap_long_lines", true);
|
|||
pref("dom.debug.propagate_gesture_events_through_content", false);
|
||||
|
||||
// The request URL of the GeoLocation backend.
|
||||
pref("geo.wifi.uri", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_API_KEY%");
|
||||
pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
|
||||
|
||||
// Necko IPC security checks only needed for app isolation for cookies/cache/etc:
|
||||
// currently irrelevant for desktop e10s
|
||||
|
|
|
@ -240,16 +240,11 @@ SearchSuggestionUIController.prototype = {
|
|||
|
||||
// Commit composition string forcibly, because setting input value does not
|
||||
// work if input has composition string (see bug 1115616 and bug 632744).
|
||||
try {
|
||||
let imeEditor = this.input.editor.QueryInterface(Components.interfaces.nsIEditorIMESupport);
|
||||
if (imeEditor.composing) {
|
||||
// Ignore input event for compisition end to avoid getting suggestion
|
||||
// again.
|
||||
this._ignoreInputEvent = true;
|
||||
imeEditor.forceCompositionEnd();
|
||||
this._ignoreInputEvent = false;
|
||||
}
|
||||
} catch(e) { }
|
||||
// Ignore input event for composition end to avoid getting suggestion again.
|
||||
this._ignoreInputEvent = true;
|
||||
this.input.blur();
|
||||
this.input.focus();
|
||||
this._ignoreInputEvent = false;
|
||||
|
||||
this.input.value = suggestion;
|
||||
this.input.setAttribute("selection-index", idx);
|
||||
|
|
|
@ -380,6 +380,56 @@ let gTests = [
|
|||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Clicking suggestion list while composing",
|
||||
setup: function() {},
|
||||
run: function()
|
||||
{
|
||||
return Task.spawn(function* () {
|
||||
// Start composition and type "x"
|
||||
let input = gBrowser.contentDocument.getElementById("searchText");
|
||||
input.focus();
|
||||
EventUtils.synthesizeComposition({ type: "compositionstart", data: "" });
|
||||
EventUtils.synthesizeComposition({ type: "compositionupdate", data: "x" });
|
||||
EventUtils.synthesizeCompositionChange({
|
||||
composition: {
|
||||
string: "x",
|
||||
clauses: [
|
||||
{ length: 1, attr: EventUtils.COMPOSITION_ATTR_RAWINPUT }
|
||||
]
|
||||
},
|
||||
caret: { start: 1, length: 0 }
|
||||
});
|
||||
|
||||
// Wait for the search suggestions to become visible.
|
||||
let table =
|
||||
gBrowser.contentDocument.getElementById("searchSuggestionTable");
|
||||
let deferred = Promise.defer();
|
||||
let observer = new MutationObserver(() => {
|
||||
if (input.getAttribute("aria-expanded") == "true") {
|
||||
observer.disconnect();
|
||||
ok(!table.hidden, "Search suggestion table unhidden");
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
observer.observe(input, {
|
||||
attributes: true,
|
||||
attributeFilter: ["aria-expanded"],
|
||||
});
|
||||
yield deferred.promise;
|
||||
|
||||
// Click the second suggestion.
|
||||
let expectedURL = Services.search.currentEngine.
|
||||
getSubmission("xbar", null, "homepage").
|
||||
uri.spec;
|
||||
let loadPromise = waitForDocLoadAndStopIt(expectedURL);
|
||||
let row = table.children[1];
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, row, gBrowser.contentWindow);
|
||||
yield loadPromise;
|
||||
ok(input.value == "xbar", "Suggestion is selected");
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Cmd+k should focus the search box in the page when the search box in the toolbar is absent",
|
||||
setup: function () {
|
||||
|
|
|
@ -411,7 +411,7 @@ pref("privacy.sanitize.migrateFx3Prefs", false);
|
|||
|
||||
// enable geo
|
||||
pref("geo.enabled", true);
|
||||
pref("geo.wifi.uri", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_API_KEY%");
|
||||
pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
|
||||
|
||||
// snapped view
|
||||
pref("browser.ui.snapped.maxWidth", 600);
|
||||
|
|
|
@ -12871,9 +12871,16 @@ nsDocShell::GetTopFrameElement(nsIDOMElement** aElement)
|
|||
win->GetScriptableTop(getter_AddRefs(top));
|
||||
NS_ENSURE_TRUE(top, NS_ERROR_FAILURE);
|
||||
|
||||
// GetFrameElement, /not/ GetScriptableFrameElement -- if |top| is inside
|
||||
// <iframe mozbrowser>, we want to return the iframe, not null.
|
||||
return top->GetFrameElement(aElement);
|
||||
nsCOMPtr<nsPIDOMWindow> piTop = do_QueryInterface(top);
|
||||
NS_ENSURE_TRUE(piTop, NS_ERROR_FAILURE);
|
||||
|
||||
// GetFrameElementInternal, /not/ GetScriptableFrameElement -- if |top| is
|
||||
// inside <iframe mozbrowser>, we want to return the iframe, not null.
|
||||
// And we want to cross the content/chrome boundary.
|
||||
nsCOMPtr<nsIDOMElement> elt =
|
||||
do_QueryInterface(piTop->GetFrameElementInternal());
|
||||
elt.forget(aElement);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -35,11 +35,14 @@ interface nsILoadContext : nsISupports
|
|||
readonly attribute nsIDOMWindow topWindow;
|
||||
|
||||
/**
|
||||
* topFrameElement is the <iframe> or <frame> element which contains the
|
||||
* topWindow with which the load is associated.
|
||||
* topFrameElement is the <iframe>, <frame>, or <browser> element which
|
||||
* contains the topWindow with which the load is associated.
|
||||
*
|
||||
* Note that we may have a topFrameElement even when we don't have an
|
||||
* associatedWindow, if the topFrameElement's content lives out of process.
|
||||
* topFrameElement is available in single-process and multiprocess contexts.
|
||||
* Note that topFrameElement may be in chrome even when the nsILoadContext is
|
||||
* associated with content.
|
||||
*/
|
||||
readonly attribute nsIDOMElement topFrameElement;
|
||||
|
||||
|
|
|
@ -3617,7 +3617,7 @@ nsDocument::SetBaseURI(nsIURI* aURI)
|
|||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
nsresult rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (csp) {
|
||||
if (csp && aURI) {
|
||||
bool permitsBaseURI = false;
|
||||
|
||||
// base-uri is only enforced if explicitly defined in the
|
||||
|
|
|
@ -99,10 +99,6 @@ public:
|
|||
|
||||
bool IsParentActivated()
|
||||
{
|
||||
if (mParentFocusType == ParentFocusType_Ignore) {
|
||||
return mActiveWindow != nullptr;
|
||||
}
|
||||
|
||||
return mParentFocusType == ParentFocusType_Active;
|
||||
}
|
||||
|
||||
|
|
|
@ -13266,7 +13266,12 @@ nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
|
|||
elm->ListenerCount();
|
||||
}
|
||||
if (mDoc) {
|
||||
mDoc->DocAddSizeOfIncludingThis(aWindowSizes);
|
||||
// Multiple global windows can share a document. So only measure the
|
||||
// document if it (a) doesn't have a global window, or (b) it's the
|
||||
// primary document for the window.
|
||||
if (!mDoc->GetInnerWindow() || mDoc->GetInnerWindow() == this) {
|
||||
mDoc->DocAddSizeOfIncludingThis(aWindowSizes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -365,7 +365,7 @@ nsresult TestPaths() {
|
|||
{ "connect-src http://www.example.com/foo%3bsessionid=12%2c34",
|
||||
"connect-src http://www.example.com/foo;sessionid=12,34" },
|
||||
{ "connect-src http://test.com/pathIncludingAz19-._~!$&'()*+=:@",
|
||||
"connect-src http://test.com/pathincludingaz19-._~!$&'()*+=:@" },
|
||||
"connect-src http://test.com/pathIncludingAz19-._~!$&'()*+=:@" },
|
||||
{ "script-src http://www.example.com:88/.js",
|
||||
"script-src http://www.example.com:88/.js" },
|
||||
{ "script-src https://foo.com/_abc/abc_/_/_a_b_c_",
|
||||
|
|
|
@ -62,6 +62,12 @@ var policies = [
|
|||
["blocked", "test1.example.com:8888/tests"],
|
||||
["blocked", "test1.example.com:8888/tests/dom/base/test/csp"],
|
||||
["blocked", "test1.example.com:8888/tests/dom/base/test/csp/file_csp_path_matching.py"],
|
||||
|
||||
// case insensitive matching for scheme and host, but case sensitive matching for paths
|
||||
["allowed", "HTTP://test1.EXAMPLE.com/tests/"],
|
||||
["allowed", "test1.EXAMPLE.com/tests/"],
|
||||
["blocked", "test1.example.com/tests/dom/base/test/CSP/?foo=val"],
|
||||
["blocked", "test1.example.com/tests/dom/base/test/csp/FILE_csp_path_matching.js?foo=val"],
|
||||
]
|
||||
|
||||
var counter = 0;
|
||||
|
|
|
@ -2995,16 +2995,7 @@ CanvasRenderingContext2D::SetFont(const nsAString& font,
|
|||
|
||||
const nsStyleFont* fontStyle = sc->StyleFont();
|
||||
|
||||
nsIAtom* language = fontStyle->mLanguage;
|
||||
if (!language) {
|
||||
language = presShell->GetPresContext()->GetLanguageFromCharset();
|
||||
}
|
||||
|
||||
// use CSS pixels instead of dev pixels to avoid being affected by page zoom
|
||||
const uint32_t aupcp = nsPresContext::AppUnitsPerCSSPixel();
|
||||
|
||||
bool printerFont = (presShell->GetPresContext()->Type() == nsPresContext::eContext_PrintPreview ||
|
||||
presShell->GetPresContext()->Type() == nsPresContext::eContext_Print);
|
||||
nsPresContext *c = presShell->GetPresContext();
|
||||
|
||||
// Purposely ignore the font size that respects the user's minimum
|
||||
// font preference (fontStyle->mFont.size) in favor of the computed
|
||||
|
@ -3012,28 +3003,28 @@ CanvasRenderingContext2D::SetFont(const nsAString& font,
|
|||
// https://bugzilla.mozilla.org/show_bug.cgi?id=698652.
|
||||
MOZ_ASSERT(!fontStyle->mAllowZoom,
|
||||
"expected text zoom to be disabled on this nsStyleFont");
|
||||
gfxFontStyle style(fontStyle->mFont.style,
|
||||
fontStyle->mFont.weight,
|
||||
fontStyle->mFont.stretch,
|
||||
NSAppUnitsToFloatPixels(fontStyle->mSize, float(aupcp)),
|
||||
language,
|
||||
fontStyle->mExplicitLanguage,
|
||||
fontStyle->mFont.sizeAdjust,
|
||||
fontStyle->mFont.systemFont,
|
||||
printerFont,
|
||||
fontStyle->mFont.synthesis & NS_FONT_SYNTHESIS_WEIGHT,
|
||||
fontStyle->mFont.synthesis & NS_FONT_SYNTHESIS_STYLE,
|
||||
fontStyle->mFont.languageOverride);
|
||||
nsFont resizedFont(fontStyle->mFont);
|
||||
// Create a font group working in units of CSS pixels instead of the usual
|
||||
// device pixels, to avoid being affected by page zoom. nsFontMetrics will
|
||||
// convert nsFont size in app units to device pixels for the font group, so
|
||||
// here we first apply to the size the equivalent of a conversion from device
|
||||
// pixels to CSS pixels, to adjust for the difference in expectations from
|
||||
// other nsFontMetrics clients.
|
||||
resizedFont.size =
|
||||
(fontStyle->mSize * c->AppUnitsPerDevPixel()) / c->AppUnitsPerCSSPixel();
|
||||
|
||||
fontStyle->mFont.AddFontFeaturesToStyle(&style);
|
||||
nsRefPtr<nsFontMetrics> metrics;
|
||||
c->DeviceContext()->GetMetricsFor(resizedFont,
|
||||
fontStyle->mLanguage,
|
||||
fontStyle->mExplicitLanguage,
|
||||
gfxFont::eHorizontal,
|
||||
c->GetUserFontSet(),
|
||||
c->GetTextPerfMetrics(),
|
||||
*getter_AddRefs(metrics));
|
||||
|
||||
nsPresContext *c = presShell->GetPresContext();
|
||||
CurrentState().fontGroup =
|
||||
gfxPlatform::GetPlatform()->CreateFontGroup(fontStyle->mFont.fontlist,
|
||||
&style,
|
||||
c->GetUserFontSet());
|
||||
gfxFontGroup* newFontGroup = metrics->GetThebesFontGroup();
|
||||
CurrentState().fontGroup = newFontGroup;
|
||||
NS_ASSERTION(CurrentState().fontGroup, "Could not get font group");
|
||||
CurrentState().fontGroup->SetTextPerfMetrics(c->GetTextPerfMetrics());
|
||||
CurrentState().font = usedFont;
|
||||
CurrentState().fontFont = fontStyle->mFont;
|
||||
CurrentState().fontFont.size = fontStyle->mSize;
|
||||
|
|
|
@ -90,9 +90,12 @@ ContactManager.prototype = {
|
|||
},
|
||||
|
||||
_convertContact: function(aContact) {
|
||||
let contact = Cu.cloneInto(aContact, this._window);
|
||||
let newContact = new this._window.mozContact(contact.properties);
|
||||
newContact.setMetadata(contact.id, contact.published, contact.updated);
|
||||
let properties = aContact.properties;
|
||||
if (properties.photo && properties.photo.length) {
|
||||
properties.photo = Cu.cloneInto(properties.photo, this._window);
|
||||
}
|
||||
let newContact = new this._window.mozContact(aContact.properties);
|
||||
newContact.setMetadata(aContact.id, aContact.published, aContact.updated);
|
||||
return newContact;
|
||||
},
|
||||
|
||||
|
|
|
@ -458,6 +458,10 @@ FORWARDED_EVENT(load,
|
|||
NS_LOAD,
|
||||
EventNameType_All,
|
||||
eBasicEventClass)
|
||||
FORWARDED_EVENT(resize,
|
||||
NS_RESIZE_EVENT,
|
||||
EventNameType_All,
|
||||
eBasicEventClass)
|
||||
FORWARDED_EVENT(scroll,
|
||||
NS_SCROLL_EVENT,
|
||||
(EventNameType_HTMLXUL | EventNameType_SVGSVG),
|
||||
|
@ -512,11 +516,6 @@ WINDOW_EVENT(popstate,
|
|||
eBasicEventClass)
|
||||
// Not supported yet
|
||||
// WINDOW_EVENT(redo)
|
||||
WINDOW_EVENT(resize,
|
||||
NS_RESIZE_EVENT,
|
||||
(EventNameType_XUL | EventNameType_SVGSVG |
|
||||
EventNameType_HTMLBodyOrFramesetOnly),
|
||||
eBasicEventClass)
|
||||
// Not supported yet
|
||||
// WINDOW_EVENT(storage)
|
||||
// Not supported yet
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/TextComposition.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/dom/HTMLFormElement.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
|
||||
#include "HTMLInputElement.h"
|
||||
#include "IMEContentObserver.h"
|
||||
|
@ -388,6 +389,27 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
IMEState newState = GetNewIMEState(aPresContext, aContent);
|
||||
|
||||
// In e10s, remote content may have IME focus. The main process (i.e. this process)
|
||||
// would attempt to set state to DISABLED if, for example, the user clicks
|
||||
// some other remote content. The content process would later re-ENABLE IME, meaning
|
||||
// that all state-changes were unnecessary.
|
||||
// Here we filter the common case where the main process knows that the remote
|
||||
// process controls IME focus. The DISABLED->re-ENABLED progression can
|
||||
// still happen since remote content may be concurrently communicating its claim
|
||||
// on focus to the main process... but this cannot cause bugs like missed keypresses.
|
||||
// (It just means a lot of needless IPC.)
|
||||
if ((newState.mEnabled == IMEState::DISABLED) && TabParent::GetIMETabParent()) {
|
||||
PR_LOG(sISMLog, PR_LOG_DEBUG,
|
||||
("ISM: IMEStateManager::OnChangeFocusInternal(), "
|
||||
"Parent process cancels to set DISABLED state because the content process "
|
||||
"has IME focus and has already sets IME state"));
|
||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"TabParent::GetIMETabParent() should never return non-null value "
|
||||
"in the content process");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!focusActuallyChanging) {
|
||||
// actual focus isn't changing, but if IME enabled state is changing,
|
||||
// we should do it.
|
||||
|
|
|
@ -527,14 +527,14 @@ HTMLMediaElement::GetMozSrcObject() const
|
|||
void
|
||||
HTMLMediaElement::SetMozSrcObject(DOMMediaStream& aValue)
|
||||
{
|
||||
mSrcAttrStream = &aValue;
|
||||
Load();
|
||||
SetMozSrcObject(&aValue);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::SetMozSrcObject(DOMMediaStream* aValue)
|
||||
{
|
||||
SetMozSrcObject(*aValue);
|
||||
mSrcAttrStream = aValue;
|
||||
Load();
|
||||
}
|
||||
|
||||
/* readonly attribute nsIDOMHTMLMediaElement mozAutoplayEnabled; */
|
||||
|
@ -2524,15 +2524,13 @@ nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParen
|
|||
// It's value may have changed, so update it.
|
||||
UpdatePreloadAction();
|
||||
}
|
||||
mElementInTreeState = ELEMENT_INTREE;
|
||||
|
||||
if (mDecoder) {
|
||||
// When the MediaElement is binding to tree, the dormant status is
|
||||
// aligned to document's hidden status.
|
||||
nsIDocument* ownerDoc = OwnerDoc();
|
||||
if (ownerDoc) {
|
||||
mDecoder->SetDormantIfNecessary(ownerDoc->Hidden());
|
||||
}
|
||||
mDecoder->NotifyOwnerActivityChanged();
|
||||
}
|
||||
mElementInTreeState = ELEMENT_INTREE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -2543,12 +2541,14 @@ void HTMLMediaElement::UnbindFromTree(bool aDeep,
|
|||
if (!mPaused && mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY)
|
||||
Pause();
|
||||
|
||||
if (mDecoder) {
|
||||
mDecoder->SetDormantIfNecessary(true);
|
||||
}
|
||||
mElementInTreeState = ELEMENT_NOT_INTREE_HAD_INTREE;
|
||||
|
||||
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||
|
||||
if (mDecoder) {
|
||||
MOZ_ASSERT(IsHidden());
|
||||
mDecoder->NotifyOwnerActivityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -3002,6 +3002,10 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
|
|||
mLoadedDataFired = false;
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
|
||||
if (IsVideo() && mHasVideo) {
|
||||
mMediaSize = aInfo->mVideo.mDisplay;
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("resize"));
|
||||
}
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
|
||||
if (mDecoder && mDecoder->IsTransportSeekable() && mDecoder->IsMediaSeekable()) {
|
||||
ProcessMediaFragmentURI();
|
||||
|
@ -3519,6 +3523,21 @@ void HTMLMediaElement::CheckAutoplayDataReady()
|
|||
}
|
||||
}
|
||||
|
||||
bool HTMLMediaElement::IsActive()
|
||||
{
|
||||
nsIDocument* ownerDoc = OwnerDoc();
|
||||
return ownerDoc && ownerDoc->IsActive() && ownerDoc->IsVisible();
|
||||
}
|
||||
|
||||
bool HTMLMediaElement::IsHidden()
|
||||
{
|
||||
if (mElementInTreeState == ELEMENT_NOT_INTREE_HAD_INTREE) {
|
||||
return true;
|
||||
}
|
||||
nsIDocument* ownerDoc = OwnerDoc();
|
||||
return !ownerDoc || ownerDoc->Hidden();
|
||||
}
|
||||
|
||||
VideoFrameContainer* HTMLMediaElement::GetVideoFrameContainer()
|
||||
{
|
||||
if (mVideoFrameContainer)
|
||||
|
@ -3642,6 +3661,10 @@ void HTMLMediaElement::NotifyDecoderPrincipalChanged()
|
|||
|
||||
void HTMLMediaElement::UpdateMediaSize(nsIntSize size)
|
||||
{
|
||||
if (IsVideo() && mReadyState != HAVE_NOTHING && mMediaSize != size) {
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("resize"));
|
||||
}
|
||||
|
||||
mMediaSize = size;
|
||||
UpdateReadyStateForData(mLastNextFrameStatus);
|
||||
}
|
||||
|
@ -3698,15 +3721,7 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
|
|||
|
||||
if (mDecoder) {
|
||||
mDecoder->SetElementVisibility(!ownerDoc->Hidden());
|
||||
|
||||
if (mElementInTreeState == ELEMENT_NOT_INTREE_HAD_INTREE) {
|
||||
mDecoder->SetDormantIfNecessary(true);
|
||||
} else if (mElementInTreeState == ELEMENT_NOT_INTREE ||
|
||||
mElementInTreeState == ELEMENT_INTREE) {
|
||||
// The MediaElement had never been binded to tree, or in the tree now,
|
||||
// align to document.
|
||||
mDecoder->SetDormantIfNecessary(ownerDoc->Hidden());
|
||||
}
|
||||
mDecoder->NotifyOwnerActivityChanged();
|
||||
}
|
||||
|
||||
// SetVisibilityState will update mMuted with MUTED_BY_AUDIO_CHANNEL via the
|
||||
|
@ -3716,10 +3731,9 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
|
|||
AutoNoJSAPI nojsapi;
|
||||
mAudioChannelAgent->SetVisibilityState(!ownerDoc->Hidden());
|
||||
}
|
||||
bool suspendEvents = !ownerDoc->IsActive() || !ownerDoc->IsVisible();
|
||||
bool pauseElement = suspendEvents || (mMuted & MUTED_BY_AUDIO_CHANNEL);
|
||||
bool pauseElement = !IsActive() || (mMuted & MUTED_BY_AUDIO_CHANNEL);
|
||||
|
||||
SuspendOrResumeElement(pauseElement, suspendEvents);
|
||||
SuspendOrResumeElement(pauseElement, !IsActive());
|
||||
|
||||
AddRemoveSelfReference();
|
||||
}
|
||||
|
|
|
@ -211,6 +211,10 @@ public:
|
|||
// suspended the channel.
|
||||
virtual void NotifySuspendedByCache(bool aIsSuspended) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
virtual bool IsActive() MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
virtual bool IsHidden() MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
// Called by the media decoder and the video frame to get the
|
||||
// ImageContainer containing the video data.
|
||||
virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
@ -374,7 +378,7 @@ public:
|
|||
|
||||
// Called by the media decoder object, on the main thread,
|
||||
// when the connection between Rtsp server and client gets lost.
|
||||
void ResetConnectionState() MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void ResetConnectionState() MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
// XPCOM GetPreload() is OK
|
||||
void SetPreload(const nsAString& aValue, ErrorResult& aRv)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
interface nsIDocument;
|
||||
interface nsIURI;
|
||||
|
||||
[builtinclass, uuid(d6a9d4b6-39b0-4cd2-957d-28a57df5a031)]
|
||||
[builtinclass, uuid(d4367ffe-e435-4195-95f8-0a51b1bbfdfb)]
|
||||
interface nsIServiceWorkerUnregisterCallback : nsISupports
|
||||
{
|
||||
// aState is true if the unregistration succeded.
|
||||
|
@ -28,7 +28,7 @@ interface nsIServiceWorkerManager : nsISupports
|
|||
*
|
||||
* Returns a Promise.
|
||||
*/
|
||||
nsISupports register(in DOMString aScope, in DOMString aScriptURI);
|
||||
nsISupports register(in nsIDOMWindow aWindow, in DOMString aScope, in DOMString aScriptURI);
|
||||
|
||||
/**
|
||||
* Unregister an existing ServiceWorker registration for `aScope`.
|
||||
|
|
|
@ -3337,7 +3337,6 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
|
|||
ParentBlobConstructorParams params(blobParams);
|
||||
|
||||
if (NS_WARN_IF(!aManager->SendPBlobConstructor(actor, params))) {
|
||||
BlobChild::Destroy(actor);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -3402,7 +3401,6 @@ BlobChild::SendSliceConstructor(ChildManagerType* aManager,
|
|||
return newActor;
|
||||
}
|
||||
|
||||
BlobChild::Destroy(newActor);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -3888,7 +3886,6 @@ BlobParent::GetOrCreateFromImpl(ParentManagerType* aManager,
|
|||
|
||||
ChildBlobConstructorParams params(id, blobParams);
|
||||
if (NS_WARN_IF(!aManager->SendPBlobConstructor(actor, params))) {
|
||||
BlobParent::Destroy(actor);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -4051,7 +4048,6 @@ BlobParent::SendSliceConstructor(
|
|||
return newActor;
|
||||
}
|
||||
|
||||
BlobParent::Destroy(newActor);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -2028,14 +2028,25 @@ TabParent::RecvSetInputContext(const int32_t& aIMEEnabled,
|
|||
const int32_t& aCause,
|
||||
const int32_t& aFocusChange)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget || !AllowContentIME()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
InputContext oldContext = widget->GetInputContext();
|
||||
|
||||
// Ignore if current widget IME setting is not DISABLED and didn't come
|
||||
// from remote content. Chrome content may have taken over.
|
||||
if (oldContext.mIMEState.mEnabled != IMEState::DISABLED &&
|
||||
oldContext.IsOriginMainProcess()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// mIMETabParent (which is actually static) tracks which if any TabParent has IMEFocus
|
||||
// When the input mode is set to anything but IMEState::DISABLED,
|
||||
// mIMETabParent should be set to this
|
||||
mIMETabParent =
|
||||
aIMEEnabled != static_cast<int32_t>(IMEState::DISABLED) ? this : nullptr;
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget || !AllowContentIME())
|
||||
return true;
|
||||
|
||||
InputContext context;
|
||||
context.mIMEState.mEnabled = static_cast<IMEState::Enabled>(aIMEEnabled);
|
||||
|
@ -2043,6 +2054,8 @@ TabParent::RecvSetInputContext(const int32_t& aIMEEnabled,
|
|||
context.mHTMLInputType.Assign(aType);
|
||||
context.mHTMLInputInputmode.Assign(aInputmode);
|
||||
context.mActionHint.Assign(aActionHint);
|
||||
context.mOrigin = InputContext::ORIGIN_CONTENT;
|
||||
|
||||
InputContextAction action(
|
||||
static_cast<InputContextAction::Cause>(aCause),
|
||||
static_cast<InputContextAction::FocusChange>(aFocusChange));
|
||||
|
|
|
@ -22,11 +22,9 @@ class SoundTouch;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
template<>
|
||||
struct DefaultDelete<cubeb_stream>
|
||||
struct DestroyPolicy
|
||||
{
|
||||
void operator()(cubeb_stream* aStream) const
|
||||
{
|
||||
void operator()(cubeb_stream* aStream) const {
|
||||
cubeb_stream_destroy(aStream);
|
||||
}
|
||||
};
|
||||
|
@ -362,7 +360,7 @@ private:
|
|||
CircularByteBuffer mBuffer;
|
||||
|
||||
// Owning reference to a cubeb_stream.
|
||||
UniquePtr<cubeb_stream> mCubebStream;
|
||||
UniquePtr<cubeb_stream, DestroyPolicy> mCubebStream;
|
||||
|
||||
uint32_t mBytesPerFrame;
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter)
|
|||
|
||||
NS_IMPL_ISUPPORTS(MediaDecoder, nsIObserver)
|
||||
|
||||
void MediaDecoder::SetDormantIfNecessary(bool aDormant)
|
||||
void MediaDecoder::NotifyOwnerActivityChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
@ -129,7 +129,28 @@ void MediaDecoder::SetDormantIfNecessary(bool aDormant)
|
|||
return;
|
||||
}
|
||||
|
||||
if(aDormant) {
|
||||
if (!mOwner) {
|
||||
NS_WARNING("MediaDecoder without a decoder owner, can't update dormant");
|
||||
return;
|
||||
}
|
||||
|
||||
bool prevDormant = mIsDormant;
|
||||
mIsDormant = false;
|
||||
if (!mOwner->IsActive() && mOwner->GetVideoFrameContainer()) {
|
||||
mIsDormant = true;
|
||||
}
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (mOwner->IsHidden() && mOwner->GetVideoFrameContainer()) {
|
||||
mIsDormant = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (prevDormant == mIsDormant) {
|
||||
// No update to dormant state
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsDormant) {
|
||||
// enter dormant state
|
||||
mDecoderStateMachine->SetDormant(true);
|
||||
|
||||
|
@ -450,7 +471,8 @@ MediaDecoder::MediaDecoder() :
|
|||
mShuttingDown(false),
|
||||
mPausedForPlaybackRateNull(false),
|
||||
mMinimizePreroll(false),
|
||||
mMediaTracksConstructed(false)
|
||||
mMediaTracksConstructed(false),
|
||||
mIsDormant(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MediaDecoder);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
|
|
@ -360,11 +360,12 @@ public:
|
|||
// called.
|
||||
virtual nsresult Play();
|
||||
|
||||
// Set/Unset dormant state if necessary.
|
||||
// Notify activity of the decoder owner is changed.
|
||||
// Based on the activity, dormant state is updated.
|
||||
// Dormant state is a state to free all scarce media resources
|
||||
// (like hw video codec), did not decoding and stay dormant.
|
||||
// It is used to share scarece media resources in system.
|
||||
virtual void SetDormantIfNecessary(bool aDormant);
|
||||
virtual void NotifyOwnerActivityChanged();
|
||||
|
||||
// Pause video playback.
|
||||
virtual void Pause();
|
||||
|
@ -1215,6 +1216,9 @@ protected:
|
|||
// Stores media info, including info of audio tracks and video tracks, should
|
||||
// only be accessed from main thread.
|
||||
nsAutoPtr<MediaInfo> mInfo;
|
||||
|
||||
// True if MediaDecoder is in dormant state.
|
||||
bool mIsDormant;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -120,6 +120,12 @@ public:
|
|||
// HAVE_FUTURE_DATA or HAVE_ENOUGH_DATA.
|
||||
virtual void UpdateReadyStateForData(NextFrameStatus aNextFrame) = 0;
|
||||
|
||||
// Check if the decoder owner is active.
|
||||
virtual bool IsActive() = 0;
|
||||
|
||||
// Check if the decoder owner is hidden.
|
||||
virtual bool IsHidden() = 0;
|
||||
|
||||
// Called by the media decoder and the video frame to get the
|
||||
// ImageContainer containing the video data.
|
||||
virtual VideoFrameContainer* GetVideoFrameContainer() = 0;
|
||||
|
|
|
@ -50,10 +50,15 @@ public:
|
|||
CANCELED
|
||||
};
|
||||
|
||||
typedef MediaPromise<nsRefPtr<AudioData>, NotDecodedReason> AudioDataPromise;
|
||||
typedef MediaPromise<nsRefPtr<VideoData>, NotDecodedReason> VideoDataPromise;
|
||||
typedef MediaPromise<int64_t, nsresult> SeekPromise;
|
||||
typedef MediaPromise<MediaData::Type, WaitForDataRejectValue> WaitForDataPromise;
|
||||
typedef MediaPromise<nsRefPtr<AudioData>, NotDecodedReason, /* IsExclusive = */ true> AudioDataPromise;
|
||||
typedef MediaPromise<nsRefPtr<VideoData>, NotDecodedReason, /* IsExclusive = */ true> VideoDataPromise;
|
||||
typedef MediaPromise<int64_t, nsresult, /* IsExclusive = */ true> SeekPromise;
|
||||
|
||||
// Note that, conceptually, WaitForData makes sense in a non-exclusive sense.
|
||||
// But in the current architecture it's only ever used exclusively (by MDSM),
|
||||
// so we mark it that way to verify our assumptions. If you have a use-case
|
||||
// for multiple WaitForData consumers, feel free to flip the exclusivity here.
|
||||
typedef MediaPromise<MediaData::Type, WaitForDataRejectValue, /* IsExclusive = */ true> WaitForDataPromise;
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReader)
|
||||
|
||||
|
|
|
@ -86,6 +86,11 @@ extern PRLogModuleInfo* gMediaDecoderLog;
|
|||
#undef GetCurrentTime
|
||||
#endif
|
||||
|
||||
// Certain constants get stored as member variables and then adjusted by various
|
||||
// scale factors on a per-decoder basis. We want to make sure to avoid using these
|
||||
// constants directly, so we put them in a namespace.
|
||||
namespace detail {
|
||||
|
||||
// If audio queue has less than this many usecs of decoded audio, we won't risk
|
||||
// trying to decode the video, we'll skip decoding video up to the next
|
||||
// keyframe. We may increase this value for an individual decoder if we
|
||||
|
@ -98,6 +103,8 @@ static const uint32_t LOW_AUDIO_USECS = 300000;
|
|||
// less than the low audio threshold.
|
||||
const int64_t AMPLE_AUDIO_USECS = 1000000;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// When we're only playing audio and we don't have a video stream, we divide
|
||||
// AMPLE_AUDIO_USECS and LOW_AUDIO_USECS by the following value. This reduces
|
||||
// the amount of decoded audio we buffer, reducing our memory usage. We only
|
||||
|
@ -126,6 +133,8 @@ static const int AUDIO_DURATION_USECS = 40000;
|
|||
// increase it by more.
|
||||
static const int THRESHOLD_FACTOR = 2;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// If we have less than this much undecoded data available, we'll consider
|
||||
// ourselves to be running low on undecoded data. We determine how much
|
||||
// undecoded data we have remaining using the reader's GetBuffered()
|
||||
|
@ -137,6 +146,8 @@ static const int64_t LOW_DATA_THRESHOLD_USECS = 5000000;
|
|||
static_assert(LOW_DATA_THRESHOLD_USECS > AMPLE_AUDIO_USECS,
|
||||
"LOW_DATA_THRESHOLD_USECS is too small");
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Amount of excess usecs of data to add in to the "should we buffer" calculation.
|
||||
static const uint32_t EXHAUSTED_DATA_MARGIN_USECS = 60000;
|
||||
|
||||
|
@ -151,6 +162,8 @@ static const uint32_t EXHAUSTED_DATA_MARGIN_USECS = 60000;
|
|||
// back to buffering normally.
|
||||
static const uint32_t QUICK_BUFFER_THRESHOLD_USECS = 2000000;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// If we're quick buffering, we'll remain in buffering mode while we have less than
|
||||
// QUICK_BUFFERING_LOW_DATA_USECS of decoded data available.
|
||||
static const uint32_t QUICK_BUFFERING_LOW_DATA_USECS = 1000000;
|
||||
|
@ -162,6 +175,8 @@ static const uint32_t QUICK_BUFFERING_LOW_DATA_USECS = 1000000;
|
|||
static_assert(QUICK_BUFFERING_LOW_DATA_USECS <= AMPLE_AUDIO_USECS,
|
||||
"QUICK_BUFFERING_LOW_DATA_USECS is too large");
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// The amount of instability we tollerate in calls to
|
||||
// MediaDecoderStateMachine::UpdateEstimatedDuration(); changes of duration
|
||||
// less than this are ignored, as they're assumed to be the result of
|
||||
|
@ -202,8 +217,9 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
|||
mPlaybackRate(1.0),
|
||||
mPreservesPitch(true),
|
||||
mAmpleVideoFrames(2),
|
||||
mLowAudioThresholdUsecs(LOW_AUDIO_USECS),
|
||||
mAmpleAudioThresholdUsecs(AMPLE_AUDIO_USECS),
|
||||
mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS),
|
||||
mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS),
|
||||
mQuickBufferingLowDataThresholdUsecs(detail::QUICK_BUFFERING_LOW_DATA_USECS),
|
||||
mIsAudioPrerolling(false),
|
||||
mIsVideoPrerolling(false),
|
||||
mAudioRequestStatus(RequestStatus::Idle),
|
||||
|
@ -235,7 +251,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
|||
std::max<uint32_t>(Preferences::GetUint("media.video-queue.default-size", 10), 3);
|
||||
|
||||
mBufferingWait = IsRealTime() ? 0 : 30;
|
||||
mLowDataThresholdUsecs = IsRealTime() ? 0 : LOW_DATA_THRESHOLD_USECS;
|
||||
mLowDataThresholdUsecs = IsRealTime() ? 0 : detail::LOW_DATA_THRESHOLD_USECS;
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Ensure high precision timers are enabled on Windows, otherwise the state
|
||||
|
@ -1022,7 +1038,7 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
|
|||
!HasLowUndecodedData())
|
||||
{
|
||||
mLowAudioThresholdUsecs =
|
||||
std::min(THRESHOLD_FACTOR * DurationToUsecs(decodeTime), AMPLE_AUDIO_USECS);
|
||||
std::min(THRESHOLD_FACTOR * DurationToUsecs(decodeTime), mAmpleAudioThresholdUsecs);
|
||||
mAmpleAudioThresholdUsecs = std::max(THRESHOLD_FACTOR * mLowAudioThresholdUsecs,
|
||||
mAmpleAudioThresholdUsecs);
|
||||
DECODER_LOG("Slow video decode, set mLowAudioThresholdUsecs=%lld mAmpleAudioThresholdUsecs=%lld",
|
||||
|
@ -2336,6 +2352,7 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
|
|||
// order to reduce memory usage.
|
||||
mAmpleAudioThresholdUsecs /= NO_VIDEO_AMPLE_AUDIO_DIVISOR;
|
||||
mLowAudioThresholdUsecs /= NO_VIDEO_AMPLE_AUDIO_DIVISOR;
|
||||
mQuickBufferingLowDataThresholdUsecs /= NO_VIDEO_AMPLE_AUDIO_DIVISOR;
|
||||
}
|
||||
|
||||
// Get potentially updated metadata
|
||||
|
@ -2803,7 +2820,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
|||
bool isLiveStream = resource->GetLength() == -1;
|
||||
if ((isLiveStream || !mDecoder->CanPlayThrough()) &&
|
||||
elapsed < TimeDuration::FromSeconds(mBufferingWait * mPlaybackRate) &&
|
||||
(mQuickBuffering ? HasLowDecodedData(QUICK_BUFFERING_LOW_DATA_USECS)
|
||||
(mQuickBuffering ? HasLowDecodedData(mQuickBufferingLowDataThresholdUsecs)
|
||||
: HasLowUndecodedData(mBufferingWait * USECS_PER_S)) &&
|
||||
mDecoder->IsExpectingMoreData())
|
||||
{
|
||||
|
@ -2922,12 +2939,6 @@ MediaDecoderStateMachine::FlushDecoding()
|
|||
DecodeTaskQueue()->FlushAndDispatch(task);
|
||||
}
|
||||
|
||||
// These flags will be reset when the decoded data returned in OnAudioDecoded()
|
||||
// and OnVideoDecoded(). Because the decode tasks are flushed, these flags need
|
||||
// to be reset here.
|
||||
mAudioRequestStatus = RequestStatus::Idle;
|
||||
mVideoRequestStatus = RequestStatus::Idle;
|
||||
|
||||
// We must reset playback so that all references to frames queued
|
||||
// in the state machine are dropped, else subsequent calls to Shutdown()
|
||||
// or ReleaseMediaResources() can fail on B2G.
|
||||
|
|
|
@ -955,6 +955,10 @@ protected:
|
|||
// we detect that the decode can't keep up with rendering.
|
||||
int64_t mAmpleAudioThresholdUsecs;
|
||||
|
||||
// If we're quick buffering, we'll remain in buffering mode while we have less than
|
||||
// QUICK_BUFFERING_LOW_DATA_USECS of decoded data available.
|
||||
int64_t mQuickBufferingLowDataThresholdUsecs;
|
||||
|
||||
// At the start of decoding we want to "preroll" the decode until we've
|
||||
// got a few frames decoded before we consider whether decode is falling
|
||||
// behind. Otherwise our "we're falling behind" logic will trigger
|
||||
|
|
|
@ -439,17 +439,22 @@ VideoDevice::SatisfiesConstraintSets(
|
|||
for (size_t i = 0; i < aConstraintSets.Length(); i++) {
|
||||
auto& c = *aConstraintSets[i];
|
||||
if (c.mFacingMode.WasPassed()) {
|
||||
auto& value = c.mFacingMode.Value();
|
||||
nsString s;
|
||||
GetFacingMode(s);
|
||||
if (!s.EqualsASCII(dom::VideoFacingModeEnumValues::strings[
|
||||
static_cast<uint32_t>(c.mFacingMode.Value())].value)) {
|
||||
return false;
|
||||
if (value.IsString()) {
|
||||
if (s != value.GetAsString()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!value.GetAsStringSequence().Contains(s)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
nsString s;
|
||||
GetMediaSource(s);
|
||||
if (!s.EqualsASCII(dom::MediaSourceEnumValues::strings[
|
||||
static_cast<uint32_t>(c.mMediaSource)].value)) {
|
||||
if (s != c.mMediaSource) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -517,9 +522,9 @@ MediaDevice::GetFacingMode(nsAString& aFacingMode)
|
|||
NS_IMETHODIMP
|
||||
MediaDevice::GetMediaSource(nsAString& aMediaSource)
|
||||
{
|
||||
if (mMediaSource == MediaSourceType::Microphone) {
|
||||
if (mMediaSource == dom::MediaSourceEnum::Microphone) {
|
||||
aMediaSource.Assign(NS_LITERAL_STRING("microphone"));
|
||||
} else if (mMediaSource == MediaSourceType::Window) { // this will go away
|
||||
} else if (mMediaSource == dom::MediaSourceEnum::Window) { // this will go away
|
||||
aMediaSource.Assign(NS_LITERAL_STRING("window"));
|
||||
} else { // all the rest are shared
|
||||
aMediaSource.Assign(NS_ConvertUTF8toUTF16(
|
||||
|
@ -943,7 +948,7 @@ template<class DeviceType, class ConstraintsType>
|
|||
static void
|
||||
GetSources(MediaEngine *engine,
|
||||
ConstraintsType &aConstraints,
|
||||
void (MediaEngine::* aEnumerate)(MediaSourceType,
|
||||
void (MediaEngine::* aEnumerate)(dom::MediaSourceEnum,
|
||||
nsTArray<nsRefPtr<typename DeviceType::Source> >*),
|
||||
nsTArray<nsRefPtr<DeviceType>>& aResult,
|
||||
const char* media_device_name = nullptr)
|
||||
|
@ -955,8 +960,8 @@ static void
|
|||
SourceSet candidateSet;
|
||||
{
|
||||
nsTArray<nsRefPtr<typename DeviceType::Source> > sources;
|
||||
// all MediaSourceEnums are contained in MediaSourceType
|
||||
(engine->*aEnumerate)((MediaSourceType)((int)aConstraints.mMediaSource), &sources);
|
||||
|
||||
(engine->*aEnumerate)(aConstraints.mMediaSourceEnumValue, &sources);
|
||||
/**
|
||||
* We're allowing multiple tabs to access the same camera for parity
|
||||
* with Chrome. See bug 811757 for some of the issues surrounding
|
||||
|
@ -1630,15 +1635,16 @@ MediaManager::GetUserMedia(
|
|||
auto& tc = c.mVideo.GetAsMediaTrackConstraints();
|
||||
if (!tc.mRequire.WasPassed() &&
|
||||
tc.mMandatory.mFacingMode.WasPassed() && !tc.mFacingMode.WasPassed()) {
|
||||
tc.mFacingMode.Construct(tc.mMandatory.mFacingMode.Value());
|
||||
tc.mFacingMode.Construct().SetAsString() = tc.mMandatory.mFacingMode.Value();
|
||||
tc.mRequire.Construct().AppendElement(NS_LITERAL_STRING("facingMode"));
|
||||
}
|
||||
if (tc.mOptional.WasPassed() && !tc.mAdvanced.WasPassed()) {
|
||||
tc.mAdvanced.Construct();
|
||||
for (uint32_t i = 0; i < tc.mOptional.Value().Length(); i++) {
|
||||
for (size_t i = 0; i < tc.mOptional.Value().Length(); i++) {
|
||||
if (tc.mOptional.Value()[i].mFacingMode.WasPassed()) {
|
||||
MediaTrackConstraintSet n;
|
||||
n.mFacingMode.Construct(tc.mOptional.Value()[i].mFacingMode.Value());
|
||||
n.mFacingMode.Construct().SetAsString() =
|
||||
tc.mOptional.Value()[i].mFacingMode.Value();
|
||||
tc.mAdvanced.Value().AppendElement(n);
|
||||
}
|
||||
}
|
||||
|
@ -1654,8 +1660,8 @@ MediaManager::GetUserMedia(
|
|||
}
|
||||
|
||||
if (tc.mAdvanced.WasPassed()) {
|
||||
uint32_t length = tc.mAdvanced.Value().Length();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
size_t length = tc.mAdvanced.Value().Length();
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
if (tc.mAdvanced.Value()[i].mBrowserWindow.WasPassed()) {
|
||||
tc.mAdvanced.Value()[i].mBrowserWindow.Construct(-1);
|
||||
}
|
||||
|
@ -1679,33 +1685,45 @@ MediaManager::GetUserMedia(
|
|||
|
||||
if (c.mVideo.IsMediaTrackConstraints()) {
|
||||
auto& tc = c.mVideo.GetAsMediaTrackConstraints();
|
||||
// deny screensharing request if support is disabled
|
||||
if (tc.mMediaSource != dom::MediaSourceEnum::Camera) {
|
||||
if (tc.mMediaSource == dom::MediaSourceEnum::Browser) {
|
||||
if (!Preferences::GetBool("media.getusermedia.browser.enabled", false)) {
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
} else if (!Preferences::GetBool("media.getusermedia.screensharing.enabled", false)) {
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
/* Deny screensharing if the requesting document is not from a host
|
||||
on the whitelist. */
|
||||
// Block screen/window sharing on Mac OSX 10.6 and WinXP until proved that they work
|
||||
if (
|
||||
MediaSourceEnum src = StringToEnum(dom::MediaSourceEnumValues::strings,
|
||||
tc.mMediaSource,
|
||||
dom::MediaSourceEnum::Other);
|
||||
switch (src) {
|
||||
case dom::MediaSourceEnum::Camera:
|
||||
break;
|
||||
|
||||
case dom::MediaSourceEnum::Browser:
|
||||
case dom::MediaSourceEnum::Screen:
|
||||
case dom::MediaSourceEnum::Application:
|
||||
case dom::MediaSourceEnum::Window:
|
||||
// Deny screensharing request if support is disabled, or
|
||||
// the requesting document is not from a host on the whitelist, or
|
||||
// we're on Mac OSX 10.6 and WinXP until proved that they work
|
||||
if (!Preferences::GetBool(((src == dom::MediaSourceEnum::Browser)?
|
||||
"media.getusermedia.browser.enabled" :
|
||||
"media.getusermedia.screensharing.enabled"),
|
||||
false) ||
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
(
|
||||
!Preferences::GetBool("media.getusermedia.screensharing.allow_on_old_platforms", false) &&
|
||||
!Preferences::GetBool("media.getusermedia.screensharing.allow_on_old_platforms",
|
||||
false) &&
|
||||
#if defined(XP_MACOSX)
|
||||
!nsCocoaFeatures::OnLionOrLater()
|
||||
#endif
|
||||
#if defined (XP_WIN)
|
||||
!IsVistaOrLater()
|
||||
#endif
|
||||
) ||
|
||||
) ||
|
||||
#endif
|
||||
(!privileged && !HostHasPermission(*docURI))) {
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
break;
|
||||
|
||||
case dom::MediaSourceEnum::Microphone:
|
||||
case dom::MediaSourceEnum::Other:
|
||||
default:
|
||||
return task->Denied(NS_LITERAL_STRING("NotFoundError"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2383,9 +2401,9 @@ GetUserMediaCallbackMediaStreamListener::StopScreenWindowSharing()
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
if (mVideoSource && !mStopped &&
|
||||
(mVideoSource->GetMediaSource() == MediaSourceType::Screen ||
|
||||
mVideoSource->GetMediaSource() == MediaSourceType::Application ||
|
||||
mVideoSource->GetMediaSource() == MediaSourceType::Window)) {
|
||||
(mVideoSource->GetMediaSource() == dom::MediaSourceEnum::Screen ||
|
||||
mVideoSource->GetMediaSource() == dom::MediaSourceEnum::Application ||
|
||||
mVideoSource->GetMediaSource() == dom::MediaSourceEnum::Window)) {
|
||||
// Stop the whole stream if there's no audio; just the video track if we have both
|
||||
MediaManager::GetMessageLoop()->PostTask(FROM_HERE,
|
||||
new MediaOperationTask(mAudioSource ? MEDIA_STOP_TRACK : MEDIA_STOP,
|
||||
|
|
|
@ -116,7 +116,7 @@ public:
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
return mVideoSource && !mStopped &&
|
||||
mVideoSource->GetMediaSource() == MediaSourceType::Camera &&
|
||||
mVideoSource->GetMediaSource() == dom::MediaSourceEnum::Camera &&
|
||||
(!mVideoSource->IsFake() ||
|
||||
Preferences::GetBool("media.navigator.permission.fake"));
|
||||
}
|
||||
|
@ -131,19 +131,19 @@ public:
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
return mVideoSource && !mStopped && !mVideoSource->IsAvailable() &&
|
||||
mVideoSource->GetMediaSource() == MediaSourceType::Screen;
|
||||
mVideoSource->GetMediaSource() == dom::MediaSourceEnum::Screen;
|
||||
}
|
||||
bool CapturingWindow()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
return mVideoSource && !mStopped && !mVideoSource->IsAvailable() &&
|
||||
mVideoSource->GetMediaSource() == MediaSourceType::Window;
|
||||
mVideoSource->GetMediaSource() == dom::MediaSourceEnum::Window;
|
||||
}
|
||||
bool CapturingApplication()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
return mVideoSource && !mStopped && !mVideoSource->IsAvailable() &&
|
||||
mVideoSource->GetMediaSource() == MediaSourceType::Application;
|
||||
mVideoSource->GetMediaSource() == dom::MediaSourceEnum::Application;
|
||||
}
|
||||
|
||||
void SetStopped()
|
||||
|
@ -508,7 +508,7 @@ protected:
|
|||
nsString mID;
|
||||
bool mHasFacingMode;
|
||||
dom::VideoFacingModeEnum mFacingMode;
|
||||
MediaSourceType mMediaSource;
|
||||
dom::MediaSourceEnum mMediaSource;
|
||||
nsRefPtr<MediaEngineSource> mSource;
|
||||
};
|
||||
|
||||
|
|
|
@ -45,11 +45,11 @@ nsresult DispatchMediaPromiseRunnable(nsIEventTarget* aTarget, nsIRunnable* aRun
|
|||
* callbacks to be invoked (asynchronously, on a specified thread) when the
|
||||
* request is either completed (resolved) or cannot be completed (rejected).
|
||||
*
|
||||
* By default, resolve and reject callbacks are always invoked on the same thread
|
||||
* where Then() was invoked.
|
||||
* When IsExclusive is true, the MediaPromise does a release-mode assertion that
|
||||
* there is at most one call to either Then(...) or ChainTo(...).
|
||||
*/
|
||||
template<typename T> class MediaPromiseHolder;
|
||||
template<typename ResolveValueT, typename RejectValueT>
|
||||
template<typename ResolveValueT, typename RejectValueT, bool IsExclusive>
|
||||
class MediaPromise
|
||||
{
|
||||
public:
|
||||
|
@ -60,24 +60,23 @@ public:
|
|||
explicit MediaPromise(const char* aCreationSite)
|
||||
: mCreationSite(aCreationSite)
|
||||
, mMutex("MediaPromise Mutex")
|
||||
, mHaveConsumer(false)
|
||||
{
|
||||
PROMISE_LOG("%s creating MediaPromise (%p)", mCreationSite, this);
|
||||
}
|
||||
|
||||
static nsRefPtr<MediaPromise<ResolveValueT, RejectValueT>>
|
||||
static nsRefPtr<MediaPromise>
|
||||
CreateAndResolve(ResolveValueType aResolveValue, const char* aResolveSite)
|
||||
{
|
||||
nsRefPtr<MediaPromise<ResolveValueT, RejectValueT>> p =
|
||||
new MediaPromise<ResolveValueT, RejectValueT>(aResolveSite);
|
||||
nsRefPtr<MediaPromise> p = new MediaPromise(aResolveSite);
|
||||
p->Resolve(aResolveValue, aResolveSite);
|
||||
return p;
|
||||
}
|
||||
|
||||
static nsRefPtr<MediaPromise<ResolveValueT, RejectValueT>>
|
||||
static nsRefPtr<MediaPromise>
|
||||
CreateAndReject(RejectValueType aRejectValue, const char* aRejectSite)
|
||||
{
|
||||
nsRefPtr<MediaPromise<ResolveValueT, RejectValueT>> p =
|
||||
new MediaPromise<ResolveValueT, RejectValueT>(aRejectSite);
|
||||
nsRefPtr<MediaPromise> p = new MediaPromise(aRejectSite);
|
||||
p->Reject(aRejectValue, aRejectSite);
|
||||
return p;
|
||||
}
|
||||
|
@ -246,6 +245,8 @@ public:
|
|||
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_RELEASE_ASSERT(!IsExclusive || !mHaveConsumer);
|
||||
mHaveConsumer = true;
|
||||
ThenValueBase* thenValue = new ThenValue<TargetType, ThisType, ResolveMethodType,
|
||||
RejectMethodType>(aResponseTarget, aThisVal,
|
||||
aResolveMethod, aRejectMethod,
|
||||
|
@ -262,6 +263,8 @@ public:
|
|||
void ChainTo(already_AddRefed<MediaPromise> aChainedPromise, const char* aCallSite)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_RELEASE_ASSERT(!IsExclusive || !mHaveConsumer);
|
||||
mHaveConsumer = true;
|
||||
nsRefPtr<MediaPromise> chainedPromise = aChainedPromise;
|
||||
PROMISE_LOG("%s invoking Chain() [this=%p, chainedPromise=%p, isPending=%d]",
|
||||
aCallSite, this, chainedPromise.get(), (int) IsPending());
|
||||
|
@ -330,6 +333,7 @@ protected:
|
|||
Maybe<RejectValueType> mRejectValue;
|
||||
nsTArray<ThenValueBase*> mThenValues;
|
||||
nsTArray<nsRefPtr<MediaPromise>> mChainedPromises;
|
||||
bool mHaveConsumer;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -1475,6 +1475,9 @@ nsresult FileMediaResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32
|
|||
MutexAutoLock lock(mLock);
|
||||
|
||||
EnsureSizeInitialized();
|
||||
if (!aCount) {
|
||||
return NS_OK;
|
||||
}
|
||||
int64_t offset = 0;
|
||||
nsresult res = mSeekable->Tell(&offset);
|
||||
NS_ENSURE_SUCCESS(res,res);
|
||||
|
@ -1486,6 +1489,9 @@ nsresult FileMediaResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32
|
|||
uint32_t bytesToRead = aCount - bytesRead;
|
||||
res = mInput->Read(aBuffer, bytesToRead, &x);
|
||||
bytesRead += x;
|
||||
if (!x) {
|
||||
res = NS_ERROR_FAILURE;
|
||||
}
|
||||
} while (bytesRead != aCount && res == NS_OK);
|
||||
|
||||
// Reset read head to original position so we don't disturb any other
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace mozilla {
|
|||
|
||||
class SharedThreadPool;
|
||||
|
||||
typedef MediaPromise<bool, bool> ShutdownPromise;
|
||||
typedef MediaPromise<bool, bool, false> ShutdownPromise;
|
||||
|
||||
// Abstracts executing runnables in order in a thread pool. The runnables
|
||||
// dispatched to the MediaTaskQueue will be executed in the order in which
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
namespace mozilla {
|
||||
|
||||
class EMEAudioDecoder : public MediaDataDecoder
|
||||
, public GMPAudioDecoderProxyCallback
|
||||
, public GMPAudioDecoderCallbackProxy
|
||||
{
|
||||
typedef mp4_demuxer::MP4Sample MP4Sample;
|
||||
typedef mp4_demuxer::AudioDecoderConfig AudioDecoderConfig;
|
||||
|
@ -37,7 +37,7 @@ public:
|
|||
virtual nsresult Drain() MOZ_OVERRIDE;
|
||||
virtual nsresult Shutdown() MOZ_OVERRIDE;
|
||||
|
||||
// GMPAudioDecoderProxyCallback implementation.
|
||||
// GMPAudioDecoderCallbackProxy implementation.
|
||||
virtual void Decoded(const nsTArray<int16_t>& aPCM,
|
||||
uint64_t aTimeStamp,
|
||||
uint32_t aChannels,
|
||||
|
|
|
@ -312,7 +312,7 @@ EMEH264Decoder::GmpInput(MP4Sample* aSample)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
UniquePtr<gmp::GMPVideoEncodedFrameImpl> frame(static_cast<gmp::GMPVideoEncodedFrameImpl*>(ftmp));
|
||||
GMPUniquePtr<gmp::GMPVideoEncodedFrameImpl> frame(static_cast<gmp::GMPVideoEncodedFrameImpl*>(ftmp));
|
||||
err = frame->CreateEmptyFrame(sample->size);
|
||||
if (GMP_FAILED(err)) {
|
||||
mCallback->Error();
|
||||
|
@ -333,7 +333,7 @@ EMEH264Decoder::GmpInput(MP4Sample* aSample)
|
|||
frame->SetBufferType(GMP_BufferLength32);
|
||||
|
||||
nsTArray<uint8_t> info; // No codec specific per-frame info to pass.
|
||||
nsresult rv = mGMP->Decode(UniquePtr<GMPVideoEncodedFrame>(frame.release()), false, info, 0);
|
||||
nsresult rv = mGMP->Decode(GMPUniquePtr<GMPVideoEncodedFrame>(frame.release()), false, info, 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
mCallback->Error();
|
||||
return rv;
|
||||
|
|
|
@ -48,7 +48,7 @@ GMPAudioDecoderParent::InitDecode(GMPAudioCodecType aCodecType,
|
|||
uint32_t aBitsPerChannel,
|
||||
uint32_t aSamplesPerSecond,
|
||||
nsTArray<uint8_t>& aExtraData,
|
||||
GMPAudioDecoderProxyCallback* aCallback)
|
||||
GMPAudioDecoderCallbackProxy* aCallback)
|
||||
{
|
||||
if (mIsOpen) {
|
||||
NS_WARNING("Trying to re-init an in-use GMP audio decoder!");
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
uint32_t aBitsPerChannel,
|
||||
uint32_t aSamplesPerSecond,
|
||||
nsTArray<uint8_t>& aExtraData,
|
||||
GMPAudioDecoderProxyCallback* aCallback) MOZ_OVERRIDE;
|
||||
GMPAudioDecoderCallbackProxy* aCallback) MOZ_OVERRIDE;
|
||||
virtual nsresult Decode(GMPAudioSamplesImpl& aInput) MOZ_OVERRIDE;
|
||||
virtual nsresult Reset() MOZ_OVERRIDE;
|
||||
virtual nsresult Drain() MOZ_OVERRIDE;
|
||||
|
@ -55,7 +55,7 @@ private:
|
|||
bool mIsOpen;
|
||||
bool mShuttingDown;
|
||||
nsRefPtr<GMPParent> mPlugin;
|
||||
GMPAudioDecoderProxyCallback* mCallback;
|
||||
GMPAudioDecoderCallbackProxy* mCallback;
|
||||
};
|
||||
|
||||
} // namespace gmp
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
#include "nsTArray.h"
|
||||
#include "mozilla/gmp/GMPTypes.h"
|
||||
|
||||
class GMPAudioDecoderProxyCallback : public GMPCallbackBase {
|
||||
class GMPAudioDecoderCallbackProxy : public GMPCallbackBase {
|
||||
public:
|
||||
virtual ~GMPAudioDecoderProxyCallback() {}
|
||||
virtual ~GMPAudioDecoderCallbackProxy() {}
|
||||
// Note: aChannelCount and aSamplesPerSecond may not be consistent from
|
||||
// one invocation to the next.
|
||||
virtual void Decoded(const nsTArray<int16_t>& aPCM,
|
||||
|
@ -36,7 +36,7 @@ public:
|
|||
uint32_t aBitsPerChannel,
|
||||
uint32_t aSamplesPerSecond,
|
||||
nsTArray<uint8_t>& aExtraData,
|
||||
GMPAudioDecoderProxyCallback* aCallback) = 0;
|
||||
GMPAudioDecoderCallbackProxy* aCallback) = 0;
|
||||
virtual nsresult Decode(mozilla::gmp::GMPAudioSamplesImpl& aSamples) = 0;
|
||||
virtual nsresult Reset() = 0;
|
||||
virtual nsresult Drain() = 0;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GMPUtils_h_
|
||||
#define GMPUtils_h_
|
||||
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename T>
|
||||
struct DestroyPolicy
|
||||
{
|
||||
void operator()(T* aGMPObject) const {
|
||||
aGMPObject->Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using GMPUniquePtr = mozilla::UniquePtr<T, DestroyPolicy<T>>;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -8,6 +8,7 @@
|
|||
#include "mozilla/unused.h"
|
||||
#include "nsAutoRef.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "GMPUtils.h"
|
||||
#include "GMPVideoEncodedFrameImpl.h"
|
||||
#include "GMPVideoi420FrameImpl.h"
|
||||
#include "GMPParent.h"
|
||||
|
@ -108,7 +109,7 @@ GMPVideoDecoderParent::InitDecode(const GMPVideoCodec& aCodecSettings,
|
|||
}
|
||||
|
||||
nsresult
|
||||
GMPVideoDecoderParent::Decode(UniquePtr<GMPVideoEncodedFrame> aInputFrame,
|
||||
GMPVideoDecoderParent::Decode(GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame,
|
||||
bool aMissingFrames,
|
||||
const nsTArray<uint8_t>& aCodecSpecificInfo,
|
||||
int64_t aRenderTimeMs)
|
||||
|
@ -120,7 +121,7 @@ GMPVideoDecoderParent::Decode(UniquePtr<GMPVideoEncodedFrame> aInputFrame,
|
|||
|
||||
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
|
||||
|
||||
UniquePtr<GMPVideoEncodedFrameImpl> inputFrameImpl(
|
||||
GMPUniquePtr<GMPVideoEncodedFrameImpl> inputFrameImpl(
|
||||
static_cast<GMPVideoEncodedFrameImpl*>(aInputFrame.release()));
|
||||
|
||||
// Very rough kill-switch if the plugin stops processing. If it's merely
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/gmp/PGMPVideoDecoderParent.h"
|
||||
#include "GMPMessageUtils.h"
|
||||
#include "GMPSharedMemManager.h"
|
||||
#include "GMPUtils.h"
|
||||
#include "GMPVideoHost.h"
|
||||
#include "GMPVideoDecoderProxy.h"
|
||||
|
||||
|
@ -37,7 +38,7 @@ public:
|
|||
const nsTArray<uint8_t>& aCodecSpecific,
|
||||
GMPVideoDecoderCallbackProxy* aCallback,
|
||||
int32_t aCoreCount) MOZ_OVERRIDE;
|
||||
virtual nsresult Decode(UniquePtr<GMPVideoEncodedFrame> aInputFrame,
|
||||
virtual nsresult Decode(GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame,
|
||||
bool aMissingFrames,
|
||||
const nsTArray<uint8_t>& aCodecSpecificInfo,
|
||||
int64_t aRenderTimeMs = -1) MOZ_OVERRIDE;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "gmp-video-frame-encoded.h"
|
||||
|
||||
#include "GMPCallbackBase.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "GMPUtils.h"
|
||||
|
||||
class GMPVideoDecoderCallbackProxy : public GMPCallbackBase,
|
||||
public GMPVideoDecoderCallback
|
||||
|
@ -38,7 +38,7 @@ public:
|
|||
const nsTArray<uint8_t>& aCodecSpecific,
|
||||
GMPVideoDecoderCallbackProxy* aCallback,
|
||||
int32_t aCoreCount) = 0;
|
||||
virtual nsresult Decode(mozilla::UniquePtr<GMPVideoEncodedFrame> aInputFrame,
|
||||
virtual nsresult Decode(mozilla::GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame,
|
||||
bool aMissingFrames,
|
||||
const nsTArray<uint8_t>& aCodecSpecificInfo,
|
||||
int64_t aRenderTimeMs = -1) = 0;
|
||||
|
@ -51,17 +51,4 @@ public:
|
|||
virtual void Close() = 0;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<>
|
||||
struct DefaultDelete<GMPVideoEncodedFrame>
|
||||
{
|
||||
void operator()(GMPVideoEncodedFrame* aFrame) const
|
||||
{
|
||||
aFrame->Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "gmp-video-frame.h"
|
||||
#include "gmp-video-frame-encoded.h"
|
||||
#include "gmp-decryption.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
#include "mp4_demuxer/DecoderData.h"
|
||||
|
||||
|
@ -116,15 +115,6 @@ private:
|
|||
|
||||
} // namespace gmp
|
||||
|
||||
template<>
|
||||
struct DefaultDelete<mozilla::gmp::GMPVideoEncodedFrameImpl>
|
||||
{
|
||||
void operator()(mozilla::gmp::GMPVideoEncodedFrameImpl* aFrame) const
|
||||
{
|
||||
aFrame->Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GMPVideoEncodedFrameImpl_h_
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "nsThread.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "runnable_utils.h"
|
||||
#include "GMPUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -125,7 +126,7 @@ GMPVideoEncoderParent::InitEncode(const GMPVideoCodec& aCodecSettings,
|
|||
}
|
||||
|
||||
GMPErr
|
||||
GMPVideoEncoderParent::Encode(UniquePtr<GMPVideoi420Frame> aInputFrame,
|
||||
GMPVideoEncoderParent::Encode(GMPUniquePtr<GMPVideoi420Frame> aInputFrame,
|
||||
const nsTArray<uint8_t>& aCodecSpecificInfo,
|
||||
const nsTArray<GMPVideoFrameType>& aFrameTypes)
|
||||
{
|
||||
|
@ -136,7 +137,7 @@ GMPVideoEncoderParent::Encode(UniquePtr<GMPVideoi420Frame> aInputFrame,
|
|||
|
||||
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
|
||||
|
||||
UniquePtr<GMPVideoi420FrameImpl> inputFrameImpl(
|
||||
GMPUniquePtr<GMPVideoi420FrameImpl> inputFrameImpl(
|
||||
static_cast<GMPVideoi420FrameImpl*>(aInputFrame.release()));
|
||||
|
||||
// Very rough kill-switch if the plugin stops processing. If it's merely
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/gmp/PGMPVideoEncoderParent.h"
|
||||
#include "GMPMessageUtils.h"
|
||||
#include "GMPSharedMemManager.h"
|
||||
#include "GMPUtils.h"
|
||||
#include "GMPVideoHost.h"
|
||||
#include "GMPVideoEncoderProxy.h"
|
||||
|
||||
|
@ -38,7 +39,7 @@ public:
|
|||
GMPVideoEncoderCallbackProxy* aCallback,
|
||||
int32_t aNumberOfCores,
|
||||
uint32_t aMaxPayloadSize) MOZ_OVERRIDE;
|
||||
virtual GMPErr Encode(UniquePtr<GMPVideoi420Frame> aInputFrame,
|
||||
virtual GMPErr Encode(GMPUniquePtr<GMPVideoi420Frame> aInputFrame,
|
||||
const nsTArray<uint8_t>& aCodecSpecificInfo,
|
||||
const nsTArray<GMPVideoFrameType>& aFrameTypes) MOZ_OVERRIDE;
|
||||
virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) MOZ_OVERRIDE;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "gmp-video-frame-encoded.h"
|
||||
|
||||
#include "GMPCallbackBase.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "GMPUtils.h"
|
||||
|
||||
class GMPVideoEncoderCallbackProxy : public GMPCallbackBase {
|
||||
public:
|
||||
|
@ -40,7 +40,7 @@ public:
|
|||
GMPVideoEncoderCallbackProxy* aCallback,
|
||||
int32_t aNumberOfCores,
|
||||
uint32_t aMaxPayloadSize) = 0;
|
||||
virtual GMPErr Encode(mozilla::UniquePtr<GMPVideoi420Frame> aInputFrame,
|
||||
virtual GMPErr Encode(mozilla::GMPUniquePtr<GMPVideoi420Frame> aInputFrame,
|
||||
const nsTArray<uint8_t>& aCodecSpecificInfo,
|
||||
const nsTArray<GMPVideoFrameType>& aFrameTypes) = 0;
|
||||
virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0;
|
||||
|
@ -53,17 +53,4 @@ public:
|
|||
virtual void Close() = 0;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<>
|
||||
struct DefaultDelete<GMPVideoi420Frame>
|
||||
{
|
||||
void operator()(GMPVideoi420Frame* aFrame) const
|
||||
{
|
||||
aFrame->Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GMPVideoEncoderProxy_h_
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#define GMPVideoi420FrameImpl_h_
|
||||
|
||||
#include "gmp-video-frame-i420.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
#include "GMPVideoPlaneImpl.h"
|
||||
|
||||
|
@ -80,15 +79,6 @@ private:
|
|||
|
||||
} // namespace gmp
|
||||
|
||||
template<>
|
||||
struct DefaultDelete<mozilla::gmp::GMPVideoi420FrameImpl>
|
||||
{
|
||||
void operator()(mozilla::gmp::GMPVideoi420FrameImpl* aFrame) const
|
||||
{
|
||||
aFrame->Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GMPVideoi420FrameImpl_h_
|
||||
|
|
|
@ -51,6 +51,7 @@ EXPORTS += [
|
|||
'GMPStorageParent.h',
|
||||
'GMPTimerChild.h',
|
||||
'GMPTimerParent.h',
|
||||
'GMPUtils.h',
|
||||
'GMPVideoDecoderChild.h',
|
||||
'GMPVideoDecoderParent.h',
|
||||
'GMPVideoDecoderProxy.h',
|
||||
|
|
|
@ -24,12 +24,28 @@ var startTest = function(test, token) {
|
|||
|
||||
var numVideoElementsFinished = 0;
|
||||
|
||||
var ondurationchange = function(ev) {
|
||||
var v = ev.target;
|
||||
info(v.testName + " got durationchange");
|
||||
v.durationchange = true;
|
||||
};
|
||||
var onresize = function(ev) {
|
||||
var v = ev.target;
|
||||
info(v.testName + " got resize");
|
||||
ok(!v.resize, v.testName + " should only fire resize once for same size");
|
||||
v.resize = true;
|
||||
ok(v.durationchange, v.testName +
|
||||
" durationchange event should have been emitted before resize");
|
||||
is(v.videoWidth, test.width, v.testName + " width should be set on resize");
|
||||
is(v.videoHeight, test.height, v.testName + " height should be set on resize");
|
||||
};
|
||||
var onloadedmetadata = function(ev) {
|
||||
var v = ev.target;
|
||||
info(v.testName + " got loadedmetadata");
|
||||
ok(!v.loadedmetadata, v.testName + " should only fire loadedmetadata once");
|
||||
v.loadedmetadata = true;
|
||||
is(v.videoWidth, test.width, v.testName + " video width should be set on loadedmetadata");
|
||||
is(v.videoHeight, test.height, v.testName + " video height should be set on loadedmetadata");
|
||||
ok(v.resize, v.testName +
|
||||
" resize event should have been emitted before loadedmetadata");
|
||||
|
||||
numVideoElementsFinished += 1;
|
||||
if (v === v1) {
|
||||
|
@ -45,6 +61,10 @@ var startTest = function(test, token) {
|
|||
}
|
||||
};
|
||||
var setupElement = function(v, id) {
|
||||
v.durationchange = false;
|
||||
v.ondurationchange = ondurationchange;
|
||||
v.resize = false;
|
||||
v.onresize = onresize;
|
||||
v.loadedmetadata = false;
|
||||
v.onloadedmetadata = onloadedmetadata;
|
||||
document.body.appendChild(v);
|
||||
|
|
|
@ -23,24 +23,42 @@ var common_tests = [
|
|||
constraints: { video: { facingMode:'left', require:["facingMode"] },
|
||||
fake: true },
|
||||
error: "NotFoundError" },
|
||||
{ message: "video overconstrained by facingMode array fails",
|
||||
constraints: { video: { facingMode:['left', 'right'], require:["facingMode"] },
|
||||
fake: true },
|
||||
error: "NotFoundError" },
|
||||
{ message: "audio overconstrained by facingMode fails",
|
||||
constraints: { audio: { facingMode:'left', require:["facingMode"] },
|
||||
fake: true },
|
||||
error: "NotFoundError" },
|
||||
{ message: "full screensharing requires permission",
|
||||
constraints: { video: { mediaSource:'screen' } },
|
||||
error: "PermissionDeniedError" },
|
||||
{ message: "application screensharing requires permission",
|
||||
constraints: { video: { mediaSource:'application' } },
|
||||
error: "PermissionDeniedError" },
|
||||
{ message: "window screensharing requires permission",
|
||||
constraints: { video: { mediaSource:'window' } },
|
||||
error: "PermissionDeniedError" },
|
||||
{ message: "browser screensharing requires permission",
|
||||
constraints: { video: { mediaSource:'browser' } },
|
||||
error: "PermissionDeniedError" },
|
||||
{ message: "unknown mediaSource fails",
|
||||
constraints: { video: { mediaSource:'uncle' } },
|
||||
error: "NotFoundError" },
|
||||
{ message: "Success-path: optional video facingMode + audio ignoring facingMode",
|
||||
constraints: { fake: true,
|
||||
audio: { facingMode:'left',
|
||||
foo:0,
|
||||
advanced: [{ facingMode:'environment' },
|
||||
{ facingMode:'user' },
|
||||
{ bar:0 }] },
|
||||
video: { // TODO: Bug 767924 sequences in unions
|
||||
//facingMode:['left', 'right', 'user', 'environment'],
|
||||
//require:["facingMode"],
|
||||
audio: { mediaSource:'microphone',
|
||||
facingMode:'left',
|
||||
foo:0,
|
||||
advanced: [{ facingMode:'environment' },
|
||||
{ facingMode:'user' },
|
||||
{ bar:0 }] },
|
||||
video: { mediaSource:'camera',
|
||||
facingMode:['left', 'right', 'user', 'environment'],
|
||||
foo:0,
|
||||
advanced: [{ facingMode:'environment' },
|
||||
{ facingMode:['user'] },
|
||||
{ bar:0 }] } },
|
||||
error: null }
|
||||
];
|
||||
|
@ -63,12 +81,14 @@ function testConstraints(tests) {
|
|||
});
|
||||
}
|
||||
|
||||
var p = new Promise(function(resolve) { resolve(); });
|
||||
var p = new Promise(r => SpecialPowers.pushPrefEnv({
|
||||
set : [ ['media.getusermedia.browser.enabled', false],
|
||||
['media.getusermedia.screensharing.enabled', false] ]
|
||||
}, r));
|
||||
|
||||
tests.forEach(function(test) {
|
||||
p = testgum(p, test);
|
||||
});
|
||||
p.catch(function(reason) {
|
||||
ok(false, "Unexpected failure: " + reason.message);
|
||||
})
|
||||
p.catch(reason => ok(false, "Unexpected failure: " + reason.message))
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ skip-if = (toolkit == 'gonk' && debug) # debug-only failure, turned an intermitt
|
|||
skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 907352, backwards-compatible behavior on mobile only
|
||||
[test_getUserMedia_constraints_mobile.html]
|
||||
skip-if = toolkit != 'gonk' && toolkit != 'android' # Bug 907352, backwards-compatible behavior on mobile only
|
||||
[test_getUserMedia_exceptions.html]
|
||||
[test_getUserMedia_gumWithinGum.html]
|
||||
[test_getUserMedia_playAudioTwice.html]
|
||||
[test_getUserMedia_playVideoAudioTwice.html]
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=795367
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test mozGetUserMedia Exceptions</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795367">Test mozGetUserMedia Exceptions</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
/**
|
||||
These tests verify that the appropriate exception is thrown when incorrect
|
||||
values are provided to the immediate mozGetUserMedia call.
|
||||
*/
|
||||
var exceptionTests = [
|
||||
// Each test here verifies that a caller is required to have all
|
||||
// three arguments in order to call mozGetUserMedia
|
||||
{ params: undefined,
|
||||
error: "Not enough arguments to Navigator.mozGetUserMedia.",
|
||||
message: "no arguments specified" },
|
||||
{ params: [{video: true, fake: true}],
|
||||
error: "Not enough arguments to Navigator.mozGetUserMedia.",
|
||||
message: "one argument specified" },
|
||||
{ params: [{video: true, fake: true}, unexpectedCall],
|
||||
error: "Not enough arguments to Navigator.mozGetUserMedia.",
|
||||
message: "two arguments specified" },
|
||||
|
||||
// Each test here verifies that providing an incorret object
|
||||
// type to any mozGetUserMedia parameter should throw
|
||||
// the correct exception specified
|
||||
{ params: [1, unexpectedCall, unexpectedCall],
|
||||
error: "Argument 1 of Navigator.mozGetUserMedia can't be converted to a dictionary.",
|
||||
message: "wrong object type as first parameter" },
|
||||
{ params: [{video: true, fake: true}, 1, unexpectedCall],
|
||||
error: "Argument 2 of Navigator.mozGetUserMedia is not an object.",
|
||||
message: "wrong object type as second parameter" },
|
||||
{ params: [{video: true, fake: true}, unexpectedCall, 1],
|
||||
error: "Argument 3 of Navigator.mozGetUserMedia is not an object.",
|
||||
message: "wrong object type as third parameter" },
|
||||
|
||||
// Each test here verifies constraint syntax as defined in webidl
|
||||
{ params: [{ fake: true, video: { advanced: [{ facingMode:'foo' }] } },
|
||||
unexpectedCall, unexpectedCall],
|
||||
error: "'facingMode' member of MediaTrackConstraintSet 'foo' is not a valid value for enumeration VideoFacingModeEnum.",
|
||||
message: "invalid facingMode enum value" }
|
||||
];
|
||||
|
||||
/**
|
||||
* A callback function that is only called if a particular
|
||||
* exception was not thrown, resulting in the test failing.
|
||||
*
|
||||
* @param {MediaStream} argument ignored
|
||||
*/
|
||||
function unexpectedCall(obj) {
|
||||
ok(false, "Callback should not have been called");
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the test run by running through each exception
|
||||
* test by verifying that the correct exception type specified
|
||||
* is thrown on the mozGetUserMedia call with the parameters
|
||||
* specified.
|
||||
*/
|
||||
runTest(function () {
|
||||
exceptionTests.forEach(function (test) {
|
||||
var exception = false;
|
||||
try {
|
||||
navigator.mozGetUserMedia.apply(navigator, test.params);
|
||||
} catch (e) {
|
||||
exception = (e.message === test.error);
|
||||
if(!exception) {
|
||||
info(e.message);
|
||||
}
|
||||
}
|
||||
ok(exception, "Exception for " + test.message);
|
||||
});
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -39,16 +39,6 @@ enum MediaEngineState {
|
|||
kReleased
|
||||
};
|
||||
|
||||
// includes everything from dom::MediaSourceEnum (really video sources), plus audio sources
|
||||
enum MediaSourceType {
|
||||
Camera = (int) dom::MediaSourceEnum::Camera,
|
||||
Screen = (int) dom::MediaSourceEnum::Screen,
|
||||
Application = (int) dom::MediaSourceEnum::Application,
|
||||
Window, // = (int) dom::MediaSourceEnum::Window, // XXX bug 1038926
|
||||
Browser = (int) dom::MediaSourceEnum::Browser, // proposed in WG, unclear if it's useful
|
||||
Microphone
|
||||
};
|
||||
|
||||
class MediaEngine
|
||||
{
|
||||
public:
|
||||
|
@ -64,12 +54,12 @@ public:
|
|||
|
||||
/* Populate an array of video sources in the nsTArray. Also include devices
|
||||
* that are currently unavailable. */
|
||||
virtual void EnumerateVideoDevices(MediaSourceType,
|
||||
virtual void EnumerateVideoDevices(dom::MediaSourceEnum,
|
||||
nsTArray<nsRefPtr<MediaEngineVideoSource> >*) = 0;
|
||||
|
||||
/* Populate an array of audio sources in the nsTArray. Also include devices
|
||||
* that are currently unavailable. */
|
||||
virtual void EnumerateAudioDevices(MediaSourceType,
|
||||
virtual void EnumerateAudioDevices(dom::MediaSourceEnum,
|
||||
nsTArray<nsRefPtr<MediaEngineAudioSource> >*) = 0;
|
||||
|
||||
protected:
|
||||
|
@ -127,7 +117,7 @@ public:
|
|||
virtual bool IsFake() = 0;
|
||||
|
||||
/* Returns the type of media source (camera, microphone, screen, window, etc) */
|
||||
virtual const MediaSourceType GetMediaSource() = 0;
|
||||
virtual const dom::MediaSourceEnum GetMediaSource() = 0;
|
||||
|
||||
// Callback interface for TakePhoto(). Either PhotoComplete() or PhotoError()
|
||||
// should be called.
|
||||
|
|
|
@ -49,8 +49,8 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE {
|
||||
return MediaSourceType::Camera;
|
||||
virtual const dom::MediaSourceEnum GetMediaSource() MOZ_OVERRIDE {
|
||||
return dom::MediaSourceEnum::Camera;
|
||||
}
|
||||
|
||||
virtual nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE
|
||||
|
|
|
@ -469,12 +469,12 @@ MediaEngineDefaultAudioSource::Notify(nsITimer* aTimer)
|
|||
}
|
||||
|
||||
void
|
||||
MediaEngineDefault::EnumerateVideoDevices(MediaSourceType aMediaSource,
|
||||
MediaEngineDefault::EnumerateVideoDevices(dom::MediaSourceEnum aMediaSource,
|
||||
nsTArray<nsRefPtr<MediaEngineVideoSource> >* aVSources) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
// only supports camera sources (for now). See Bug 1038241
|
||||
if (aMediaSource != MediaSourceType::Camera) {
|
||||
if (aMediaSource != dom::MediaSourceEnum::Camera) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -490,7 +490,7 @@ MediaEngineDefault::EnumerateVideoDevices(MediaSourceType aMediaSource,
|
|||
}
|
||||
|
||||
void
|
||||
MediaEngineDefault::EnumerateAudioDevices(MediaSourceType aMediaSource,
|
||||
MediaEngineDefault::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource,
|
||||
nsTArray<nsRefPtr<MediaEngineAudioSource> >* aASources) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
int32_t len = mASources.Length();
|
||||
|
|
|
@ -64,8 +64,8 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE {
|
||||
return MediaSourceType::Camera;
|
||||
virtual const dom::MediaSourceEnum GetMediaSource() MOZ_OVERRIDE {
|
||||
return dom::MediaSourceEnum::Camera;
|
||||
}
|
||||
|
||||
virtual nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE
|
||||
|
@ -127,8 +127,8 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE {
|
||||
return MediaSourceType::Microphone;
|
||||
virtual const dom::MediaSourceEnum GetMediaSource() MOZ_OVERRIDE {
|
||||
return dom::MediaSourceEnum::Microphone;
|
||||
}
|
||||
|
||||
virtual nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE
|
||||
|
@ -158,9 +158,9 @@ public:
|
|||
, mMutex("mozilla::MediaEngineDefault")
|
||||
{}
|
||||
|
||||
virtual void EnumerateVideoDevices(MediaSourceType,
|
||||
virtual void EnumerateVideoDevices(dom::MediaSourceEnum,
|
||||
nsTArray<nsRefPtr<MediaEngineVideoSource> >*);
|
||||
virtual void EnumerateAudioDevices(MediaSourceType,
|
||||
virtual void EnumerateAudioDevices(dom::MediaSourceEnum,
|
||||
nsTArray<nsRefPtr<MediaEngineAudioSource> >*);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -29,8 +29,8 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList
|
|||
virtual nsresult Stop(mozilla::SourceMediaStream*, mozilla::TrackID) MOZ_OVERRIDE;
|
||||
virtual nsresult Config(bool, uint32_t, bool, uint32_t, bool, uint32_t, int32_t) MOZ_OVERRIDE;
|
||||
virtual bool IsFake() MOZ_OVERRIDE;
|
||||
virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE {
|
||||
return MediaSourceType::Browser;
|
||||
virtual const dom::MediaSourceEnum GetMediaSource() MOZ_OVERRIDE {
|
||||
return dom::MediaSourceEnum::Browser;
|
||||
}
|
||||
virtual bool SatisfiesConstraintSets(
|
||||
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets) MOZ_OVERRIDE
|
||||
|
|
|
@ -72,14 +72,14 @@ MediaEngineWebRTC::MediaEngineWebRTC(MediaEnginePrefs &aPrefs)
|
|||
}
|
||||
|
||||
void
|
||||
MediaEngineWebRTC::EnumerateVideoDevices(MediaSourceType aMediaSource,
|
||||
MediaEngineWebRTC::EnumerateVideoDevices(dom::MediaSourceEnum aMediaSource,
|
||||
nsTArray<nsRefPtr<MediaEngineVideoSource> >* aVSources)
|
||||
{
|
||||
// We spawn threads to handle gUM runnables, so we must protect the member vars
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
#ifdef MOZ_B2G_CAMERA
|
||||
if (aMediaSource != MediaSourceType::Camera) {
|
||||
if (aMediaSource != dom::MediaSourceEnum::Camera) {
|
||||
// only supports camera sources
|
||||
return;
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ MediaEngineWebRTC::EnumerateVideoDevices(MediaSourceType aMediaSource,
|
|||
#endif
|
||||
|
||||
switch (aMediaSource) {
|
||||
case MediaSourceType::Window:
|
||||
case dom::MediaSourceEnum::Window:
|
||||
mWinEngineConfig.Set<webrtc::CaptureDeviceInfo>(
|
||||
new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Window));
|
||||
if (!mWinEngine) {
|
||||
|
@ -148,7 +148,7 @@ MediaEngineWebRTC::EnumerateVideoDevices(MediaSourceType aMediaSource,
|
|||
videoEngine = mWinEngine;
|
||||
videoEngineInit = &mWinEngineInit;
|
||||
break;
|
||||
case MediaSourceType::Application:
|
||||
case dom::MediaSourceEnum::Application:
|
||||
mAppEngineConfig.Set<webrtc::CaptureDeviceInfo>(
|
||||
new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Application));
|
||||
if (!mAppEngine) {
|
||||
|
@ -159,7 +159,7 @@ MediaEngineWebRTC::EnumerateVideoDevices(MediaSourceType aMediaSource,
|
|||
videoEngine = mAppEngine;
|
||||
videoEngineInit = &mAppEngineInit;
|
||||
break;
|
||||
case MediaSourceType::Screen:
|
||||
case dom::MediaSourceEnum::Screen:
|
||||
mScreenEngineConfig.Set<webrtc::CaptureDeviceInfo>(
|
||||
new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Screen));
|
||||
if (!mScreenEngine) {
|
||||
|
@ -170,7 +170,7 @@ MediaEngineWebRTC::EnumerateVideoDevices(MediaSourceType aMediaSource,
|
|||
videoEngine = mScreenEngine;
|
||||
videoEngineInit = &mScreenEngineInit;
|
||||
break;
|
||||
case MediaSourceType::Browser:
|
||||
case dom::MediaSourceEnum::Browser:
|
||||
mBrowserEngineConfig.Set<webrtc::CaptureDeviceInfo>(
|
||||
new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Browser));
|
||||
if (!mBrowserEngine) {
|
||||
|
@ -181,7 +181,7 @@ MediaEngineWebRTC::EnumerateVideoDevices(MediaSourceType aMediaSource,
|
|||
videoEngine = mBrowserEngine;
|
||||
videoEngineInit = &mBrowserEngineInit;
|
||||
break;
|
||||
case MediaSourceType::Camera:
|
||||
case dom::MediaSourceEnum::Camera:
|
||||
// fall through
|
||||
default:
|
||||
if (!mVideoEngine) {
|
||||
|
@ -274,7 +274,7 @@ MediaEngineWebRTC::EnumerateVideoDevices(MediaSourceType aMediaSource,
|
|||
}
|
||||
}
|
||||
|
||||
if (mHasTabVideoSource || MediaSourceType::Browser == aMediaSource)
|
||||
if (mHasTabVideoSource || dom::MediaSourceEnum::Browser == aMediaSource)
|
||||
aVSources->AppendElement(new MediaEngineTabVideoSource());
|
||||
|
||||
return;
|
||||
|
@ -282,7 +282,7 @@ MediaEngineWebRTC::EnumerateVideoDevices(MediaSourceType aMediaSource,
|
|||
}
|
||||
|
||||
void
|
||||
MediaEngineWebRTC::EnumerateAudioDevices(MediaSourceType aMediaSource,
|
||||
MediaEngineWebRTC::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource,
|
||||
nsTArray<nsRefPtr<MediaEngineAudioSource> >* aASources)
|
||||
{
|
||||
ScopedCustomReleasePtr<webrtc::VoEBase> ptrVoEBase;
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
virtual bool IsTextureSupported() MOZ_OVERRIDE { return false; }
|
||||
|
||||
MediaEngineWebRTCVideoSource(webrtc::VideoEngine* aVideoEnginePtr, int aIndex,
|
||||
MediaSourceType aMediaSource = MediaSourceType::Camera)
|
||||
dom::MediaSourceEnum aMediaSource = dom::MediaSourceEnum::Camera)
|
||||
: MediaEngineCameraVideoSource(aIndex, "WebRTCCamera.Monitor")
|
||||
, mVideoEngine(aVideoEnginePtr)
|
||||
, mMinFps(-1)
|
||||
|
@ -99,7 +99,7 @@ public:
|
|||
TrackID aId,
|
||||
StreamTime aDesiredTime) MOZ_OVERRIDE;
|
||||
|
||||
virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE {
|
||||
virtual const dom::MediaSourceEnum GetMediaSource() MOZ_OVERRIDE {
|
||||
return mMediaSource;
|
||||
}
|
||||
virtual nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE
|
||||
|
@ -127,7 +127,7 @@ private:
|
|||
webrtc::ViERender* mViERender;
|
||||
|
||||
int mMinFps; // Min rate we want to accept
|
||||
MediaSourceType mMediaSource; // source of media (camera | application | screen)
|
||||
dom::MediaSourceEnum mMediaSource; // source of media (camera | application | screen)
|
||||
|
||||
static bool SatisfiesConstraintSet(const dom::MediaTrackConstraintSet& aConstraints,
|
||||
const webrtc::CaptureCapability& aCandidate);
|
||||
|
@ -185,8 +185,8 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE {
|
||||
return MediaSourceType::Microphone;
|
||||
virtual const dom::MediaSourceEnum GetMediaSource() MOZ_OVERRIDE {
|
||||
return dom::MediaSourceEnum::Microphone;
|
||||
}
|
||||
|
||||
virtual nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE
|
||||
|
@ -254,9 +254,9 @@ public:
|
|||
// before invoking Shutdown on this class.
|
||||
void Shutdown();
|
||||
|
||||
virtual void EnumerateVideoDevices(MediaSourceType,
|
||||
virtual void EnumerateVideoDevices(dom::MediaSourceEnum,
|
||||
nsTArray<nsRefPtr<MediaEngineVideoSource> >*);
|
||||
virtual void EnumerateAudioDevices(MediaSourceType,
|
||||
virtual void EnumerateAudioDevices(dom::MediaSourceEnum,
|
||||
nsTArray<nsRefPtr<MediaEngineAudioSource> >*);
|
||||
private:
|
||||
~MediaEngineWebRTC() {
|
||||
|
|
|
@ -12,6 +12,22 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
template<class EnumValuesStrings, class Enum>
|
||||
static const char* EnumToASCII(const EnumValuesStrings& aStrings, Enum aValue) {
|
||||
return aStrings[uint32_t(aValue)].value;
|
||||
}
|
||||
|
||||
template<class EnumValuesStrings, class Enum>
|
||||
static Enum StringToEnum(const EnumValuesStrings& aStrings, const nsAString& aValue,
|
||||
Enum aDefaultValue) {
|
||||
for (size_t i = 0; aStrings[i].value; i++) {
|
||||
if (aValue.EqualsASCII(aStrings[i].value)) {
|
||||
return Enum(i);
|
||||
}
|
||||
}
|
||||
return aDefaultValue;
|
||||
}
|
||||
|
||||
// Normalized internal version of MediaTrackConstraints to simplify downstream
|
||||
// processing. This implementation-only helper is included as needed by both
|
||||
// MediaManager (for gUM camera selection) and MediaEngine (for applyConstraints).
|
||||
|
@ -25,6 +41,7 @@ public:
|
|||
bool mUnsupportedRequirement;
|
||||
MediaTrackConstraintSet mRequired;
|
||||
dom::Sequence<MediaTrackConstraintSet> mNonrequired;
|
||||
dom::MediaSourceEnum mMediaSourceEnumValue;
|
||||
|
||||
MediaTrackConstraintsN(const dom::MediaTrackConstraints &aOther,
|
||||
const dom::EnumEntry* aStrings)
|
||||
|
@ -34,8 +51,8 @@ public:
|
|||
{
|
||||
if (mRequire.WasPassed()) {
|
||||
auto& array = mRequire.Value();
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
auto value = ToEnum(array[i]);
|
||||
for (size_t i = 0; i < array.Length(); i++) {
|
||||
auto value = StringToEnum(mStrings, array[i], Kind::Other);
|
||||
if (value != Kind::Other) {
|
||||
mRequireN.AppendElement(value);
|
||||
} else {
|
||||
|
@ -43,18 +60,22 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// treat MediaSource special because it's always required
|
||||
mRequired.mMediaSource = mMediaSource;
|
||||
|
||||
// we guarantee (int) equivalence from MediaSourceEnum ->MediaSourceType
|
||||
// (but not the other way)
|
||||
if (mMediaSource != dom::MediaSourceEnum::Camera && mAdvanced.WasPassed()) {
|
||||
// iterate through advanced, forcing mediaSource to match "root"
|
||||
auto& array = mAdvanced.Value();
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
if (array[i].mMediaSource == dom::MediaSourceEnum::Camera) {
|
||||
array[i].mMediaSource = mMediaSource;
|
||||
mMediaSourceEnumValue = StringToEnum(dom::MediaSourceEnumValues::strings,
|
||||
mMediaSource,
|
||||
dom::MediaSourceEnum::Other);
|
||||
if (mAdvanced.WasPassed()) {
|
||||
if(mMediaSourceEnumValue != dom::MediaSourceEnum::Camera) {
|
||||
// iterate through advanced, forcing mediaSource to match "root"
|
||||
auto& array = mAdvanced.Value();
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
auto& ms = array[i].mMediaSource;
|
||||
if (ms.EqualsASCII(EnumToASCII(dom::MediaSourceEnumValues::strings,
|
||||
dom::MediaSourceEnum::Camera))) {
|
||||
ms = mMediaSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,14 +90,6 @@ protected:
|
|||
}
|
||||
}
|
||||
private:
|
||||
Kind ToEnum(const nsAString& aSrc) {
|
||||
for (size_t i = 0; mStrings[i].value; i++) {
|
||||
if (aSrc.EqualsASCII(mStrings[i].value)) {
|
||||
return Kind(i);
|
||||
}
|
||||
}
|
||||
return Kind::Other;
|
||||
}
|
||||
const dom::EnumEntry* mStrings;
|
||||
};
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ LOCAL_INCLUDES += [
|
|||
'/dom/plugins/ipc',
|
||||
'/layout/generic',
|
||||
'/layout/xul',
|
||||
'/netwerk/base',
|
||||
'/widget',
|
||||
'/widget/android',
|
||||
'/widget/cocoa',
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "nsIURL.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIProtocolProxyService2.h"
|
||||
#include "nsProtocolProxyService.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
#include "nsIFile.h"
|
||||
#if defined(XP_MACOSX)
|
||||
|
@ -606,32 +606,30 @@ nsresult nsPluginHost::FindProxyForURL(const char* url, char* *result)
|
|||
}
|
||||
nsresult res;
|
||||
|
||||
nsCOMPtr<nsIURI> uriIn;
|
||||
nsCOMPtr<nsIProtocolProxyService> proxyService;
|
||||
nsCOMPtr<nsIProtocolProxyService2> proxyService2;
|
||||
nsCOMPtr<nsIIOService> ioService;
|
||||
|
||||
proxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &res);
|
||||
nsCOMPtr<nsIProtocolProxyService> proxyService =
|
||||
do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &res);
|
||||
if (NS_FAILED(res) || !proxyService)
|
||||
return res;
|
||||
|
||||
proxyService2 = do_QueryInterface(proxyService, &res);
|
||||
if (NS_FAILED(res) || !proxyService2)
|
||||
return res;
|
||||
nsRefPtr<nsProtocolProxyService> rawProxyService = do_QueryObject(proxyService);
|
||||
if (!rawProxyService) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &res);
|
||||
nsCOMPtr<nsIIOService> ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &res);
|
||||
if (NS_FAILED(res) || !ioService)
|
||||
return res;
|
||||
|
||||
// make an nsURI from the argument url
|
||||
res = ioService->NewURI(nsDependentCString(url), nullptr, nullptr, getter_AddRefs(uriIn));
|
||||
// make a temporary channel from the argument url
|
||||
nsCOMPtr<nsIChannel> tempChannel;
|
||||
res = ioService->NewChannel(nsDependentCString(url), nullptr, nullptr, getter_AddRefs(tempChannel));
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
nsCOMPtr<nsIProxyInfo> pi;
|
||||
|
||||
// Remove this with bug 778201
|
||||
res = proxyService2->DeprecatedBlockingResolve(uriIn, 0, getter_AddRefs(pi));
|
||||
// Remove this deprecated call in the future (see Bug 778201):
|
||||
res = rawProxyService->DeprecatedBlockingResolve(tempChannel, 0, getter_AddRefs(pi));
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
|
|
|
@ -510,14 +510,12 @@ void
|
|||
nsCSPHostSrc::setPort(const nsAString& aPort)
|
||||
{
|
||||
mPort = aPort;
|
||||
ToLowerCase(mPort);
|
||||
}
|
||||
|
||||
void
|
||||
nsCSPHostSrc::appendPath(const nsAString& aPath)
|
||||
{
|
||||
mPath.Append(aPath);
|
||||
ToLowerCase(mPath);
|
||||
}
|
||||
|
||||
/* ===== nsCSPKeywordSrc ===================== */
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
// These dictionaries need to be in a separate file from their use in unions
|
||||
// in MediaTrackConstraintSet.webidl due to a webidl compiler limitation.
|
||||
|
||||
// These enums are in the spec even though they're not used directly in the API
|
||||
// due to https://www.w3.org/Bugs/Public/show_bug.cgi?id=19936
|
||||
// Their binding code is quite useful though, and is used in the implementation.
|
||||
|
||||
enum VideoFacingModeEnum {
|
||||
"user",
|
||||
"environment",
|
||||
|
@ -19,7 +23,9 @@ enum MediaSourceEnum {
|
|||
"screen",
|
||||
"application",
|
||||
"window",
|
||||
"browser"
|
||||
"browser",
|
||||
"microphone",
|
||||
"other"
|
||||
};
|
||||
|
||||
dictionary ConstrainLongRange {
|
||||
|
|
|
@ -75,6 +75,7 @@ interface GlobalEventHandlers {
|
|||
attribute EventHandler onprogress;
|
||||
attribute EventHandler onratechange;
|
||||
attribute EventHandler onreset;
|
||||
attribute EventHandler onresize;
|
||||
attribute EventHandler onscroll;
|
||||
attribute EventHandler onseeked;
|
||||
attribute EventHandler onseeking;
|
||||
|
@ -130,7 +131,6 @@ interface WindowEventHandlers {
|
|||
attribute EventHandler onpagehide;
|
||||
attribute EventHandler onpageshow;
|
||||
attribute EventHandler onpopstate;
|
||||
attribute EventHandler onresize;
|
||||
//(Not implemented)attribute EventHandler onstorage;
|
||||
attribute EventHandler onunload;
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@ dictionary MediaTrackConstraints : MediaTrackConstraintSet {
|
|||
|
||||
// TODO(jib): Remove in 6+ weeks (Bug 997365)
|
||||
dictionary MobileLegacyMediaTrackConstraintSet {
|
||||
VideoFacingModeEnum facingMode;
|
||||
DOMString facingMode;
|
||||
};
|
||||
|
||||
interface MediaStreamTrack {
|
||||
|
|
|
@ -22,24 +22,16 @@ enum SupportedAudioConstraints {
|
|||
"other"
|
||||
};
|
||||
|
||||
|
||||
dictionary MediaTrackConstraintSet {
|
||||
ConstrainLongRange width;
|
||||
ConstrainLongRange height;
|
||||
ConstrainDoubleRange frameRate;
|
||||
ConstrainVideoFacingMode facingMode;
|
||||
ConstrainMediaSource mediaSource = "camera";
|
||||
ConstrainDOMString facingMode;
|
||||
DOMString mediaSource = "camera";
|
||||
long long browserWindow;
|
||||
boolean scrollWithPage;
|
||||
};
|
||||
|
||||
// TODO: Bug 995352 can't nest unions
|
||||
//typedef (long or ConstrainLongRange) ConstrainLong;
|
||||
//typedef (double or ConstrainDoubleRange) ConstrainDouble;
|
||||
|
||||
typedef VideoFacingModeEnum ConstrainVideoFacingMode;
|
||||
typedef MediaSourceEnum ConstrainMediaSource;
|
||||
|
||||
// TODO: Bug 767924 sequences in unions
|
||||
//typedef (VideoFacingModeEnum or sequence<VideoFacingModeEnum>) ConstrainVideoFacingMode;
|
||||
//typedef (MediaSourceEnum or sequence<MediaSourceEnum>) ConstrainMediaSource;
|
||||
typedef (long or ConstrainLongRange) ConstrainLong;
|
||||
typedef (double or ConstrainDoubleRange) ConstrainDouble;
|
||||
typedef (DOMString or sequence<DOMString>) ConstrainDOMString;
|
||||
|
|
|
@ -4,21 +4,19 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html
|
||||
* http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-obj
|
||||
*
|
||||
*/
|
||||
|
||||
// Still unclear what should be subclassed.
|
||||
// https://github.com/slightlyoff/ServiceWorker/issues/189
|
||||
[Pref="dom.serviceWorkers.enabled",
|
||||
// XXXbz I have no idea where this should be exposed. The spec makes
|
||||
// no sense. But since it's got a pref, let's say window.
|
||||
// FIXME(nsm): Bug 1113522. Should also be exposed on Workers too.
|
||||
Exposed=Window]
|
||||
interface ServiceWorker : EventTarget {
|
||||
readonly attribute DOMString scope;
|
||||
readonly attribute DOMString url;
|
||||
|
||||
readonly attribute USVString scriptURL;
|
||||
readonly attribute ServiceWorkerState state;
|
||||
|
||||
attribute EventHandler onstatechange;
|
||||
};
|
||||
|
||||
|
|
|
@ -2203,7 +2203,6 @@ RuntimeService::CreateServiceWorker(const GlobalObject& aGlobal,
|
|||
new ServiceWorker(window, sharedWorker);
|
||||
|
||||
serviceWorker->mURL = aScriptURL;
|
||||
serviceWorker->mScope = NS_ConvertUTF8toUTF16(aScope);
|
||||
|
||||
serviceWorker.forget(aServiceWorker);
|
||||
return rv;
|
||||
|
@ -2230,7 +2229,6 @@ RuntimeService::CreateServiceWorkerFromLoadInfo(JSContext* aCx,
|
|||
new ServiceWorker(nullptr, sharedWorker);
|
||||
|
||||
serviceWorker->mURL = aScriptURL;
|
||||
serviceWorker->mScope = NS_ConvertUTF8toUTF16(aScope);
|
||||
|
||||
serviceWorker.forget(aServiceWorker);
|
||||
return rv;
|
||||
|
|
|
@ -41,13 +41,7 @@ public:
|
|||
}
|
||||
|
||||
void
|
||||
GetScope(nsString& aScope) const
|
||||
{
|
||||
aScope = mScope;
|
||||
}
|
||||
|
||||
void
|
||||
GetUrl(nsString& aURL) const
|
||||
GetScriptURL(nsString& aURL) const
|
||||
{
|
||||
aURL = mURL;
|
||||
}
|
||||
|
@ -63,7 +57,6 @@ private:
|
|||
~ServiceWorker();
|
||||
|
||||
ServiceWorkerState mState;
|
||||
nsString mScope;
|
||||
nsString mURL;
|
||||
|
||||
// To allow ServiceWorkers to potentially drop the backing DOMEventTargetHelper and
|
||||
|
|
|
@ -81,7 +81,7 @@ ServiceWorkerContainer::Register(const nsAString& aScriptURL,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
aRv = swm->Register(aOptions.mScope, aScriptURL, getter_AddRefs(promise));
|
||||
aRv = swm->Register(GetOwner(), aOptions.mScope, aScriptURL, getter_AddRefs(promise));
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(InstallPhaseEvent, Event, mPromise)
|
|||
|
||||
InstallEvent::InstallEvent(EventTarget* aOwner)
|
||||
: InstallPhaseEvent(aOwner)
|
||||
, mActivateImmediately(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ class InstallEvent MOZ_FINAL : public InstallPhaseEvent
|
|||
{
|
||||
// FIXME(nsm): Bug 982787 will allow actually populating this.
|
||||
nsRefPtr<ServiceWorker> mActiveWorker;
|
||||
bool mActivateImmediately;
|
||||
|
||||
protected:
|
||||
explicit InstallEvent(mozilla::dom::EventTarget* aOwner);
|
||||
|
@ -126,9 +127,14 @@ public:
|
|||
void
|
||||
Replace()
|
||||
{
|
||||
// FIXME(nsm): Unspecced. Bug 982711
|
||||
NS_WARNING("Not Implemented");
|
||||
mActivateImmediately = true;
|
||||
};
|
||||
|
||||
bool
|
||||
ActivateImmediately() const
|
||||
{
|
||||
return mActivateImmediately;
|
||||
}
|
||||
};
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/WeakPtr.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/ServiceWorkerBinding.h" // For ServiceWorkerState
|
||||
#include "mozilla/dom/ServiceWorkerCommon.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
|
@ -32,45 +33,6 @@ class ServiceWorkerRegistration;
|
|||
namespace workers {
|
||||
|
||||
class ServiceWorker;
|
||||
class ServiceWorkerUpdateInstance;
|
||||
|
||||
/**
|
||||
* UpdatePromise is a utility class that sort of imitates Promise, but not
|
||||
* completely. Using DOM Promise from C++ is a pain when we know the precise types
|
||||
* we're dealing with since it involves dealing with JSAPI. In this case we
|
||||
* also don't (yet) need the 'thenables added after resolution should trigger
|
||||
* immediately' support and other things like that. All we want is something
|
||||
* that works reasonably Promise like and can resolve real DOM Promises added
|
||||
* pre-emptively.
|
||||
*/
|
||||
class UpdatePromise MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
UpdatePromise();
|
||||
~UpdatePromise();
|
||||
|
||||
void AddPromise(Promise* aPromise);
|
||||
void ResolveAllPromises(const nsACString& aScriptSpec, const nsACString& aScope);
|
||||
void RejectAllPromises(nsresult aRv);
|
||||
void RejectAllPromises(const ErrorEventInit& aErrorDesc);
|
||||
|
||||
bool
|
||||
IsRejected() const
|
||||
{
|
||||
return mState == Rejected;
|
||||
}
|
||||
|
||||
private:
|
||||
enum {
|
||||
Pending,
|
||||
Resolved,
|
||||
Rejected
|
||||
} mState;
|
||||
|
||||
// XXXnsm: Right now we don't need to support AddPromise() after
|
||||
// already being resolved (i.e. true Promise-like behaviour).
|
||||
nsTArray<WeakPtr<Promise>> mPromises;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wherever the spec treats a worker instance and a description of said worker
|
||||
|
@ -81,6 +43,7 @@ private:
|
|||
class ServiceWorkerInfo MOZ_FINAL
|
||||
{
|
||||
nsCString mScriptSpec;
|
||||
ServiceWorkerState mState;
|
||||
|
||||
~ServiceWorkerInfo()
|
||||
{ }
|
||||
|
@ -96,7 +59,98 @@ public:
|
|||
|
||||
explicit ServiceWorkerInfo(const nsACString& aScriptSpec)
|
||||
: mScriptSpec(aScriptSpec)
|
||||
, mState(ServiceWorkerState::EndGuard_)
|
||||
{ }
|
||||
|
||||
void
|
||||
UpdateState(ServiceWorkerState aState)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// Any state can directly transition to redundant, but everything else is
|
||||
// ordered.
|
||||
if (aState != ServiceWorkerState::Redundant) {
|
||||
MOZ_ASSERT_IF(mState == ServiceWorkerState::EndGuard_, aState == ServiceWorkerState::Installing);
|
||||
MOZ_ASSERT_IF(mState == ServiceWorkerState::Installing, aState == ServiceWorkerState::Installed);
|
||||
MOZ_ASSERT_IF(mState == ServiceWorkerState::Installed, aState == ServiceWorkerState::Activating);
|
||||
MOZ_ASSERT_IF(mState == ServiceWorkerState::Activating, aState == ServiceWorkerState::Activated);
|
||||
}
|
||||
// Activated can only go to redundant.
|
||||
MOZ_ASSERT_IF(mState == ServiceWorkerState::Activated, aState == ServiceWorkerState::Redundant);
|
||||
#endif
|
||||
mState = aState;
|
||||
// FIXME(nsm): Inform all relevant ServiceWorker instances.
|
||||
}
|
||||
};
|
||||
|
||||
class ServiceWorkerJobQueue;
|
||||
|
||||
class ServiceWorkerJob : public nsISupports
|
||||
{
|
||||
// The queue keeps the jobs alive, so they can hold a rawptr back to the
|
||||
// queue.
|
||||
ServiceWorkerJobQueue* mQueue;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual void Start() = 0;
|
||||
|
||||
protected:
|
||||
explicit ServiceWorkerJob(ServiceWorkerJobQueue* aQueue)
|
||||
: mQueue(aQueue)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ServiceWorkerJob()
|
||||
{ }
|
||||
|
||||
void
|
||||
Done(nsresult aStatus);
|
||||
};
|
||||
|
||||
class ServiceWorkerJobQueue MOZ_FINAL
|
||||
{
|
||||
friend class ServiceWorkerJob;
|
||||
|
||||
nsTArray<nsRefPtr<ServiceWorkerJob>> mJobs;
|
||||
|
||||
public:
|
||||
~ServiceWorkerJobQueue()
|
||||
{
|
||||
// FIXME(nsm): Clean up jobs.
|
||||
MOZ_ASSERT(mJobs.IsEmpty());
|
||||
}
|
||||
|
||||
void
|
||||
Append(ServiceWorkerJob* aJob)
|
||||
{
|
||||
MOZ_ASSERT(aJob);
|
||||
MOZ_ASSERT(!mJobs.Contains(aJob));
|
||||
bool wasEmpty = mJobs.IsEmpty();
|
||||
mJobs.AppendElement(aJob);
|
||||
if (wasEmpty) {
|
||||
aJob->Start();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
Pop()
|
||||
{
|
||||
MOZ_ASSERT(!mJobs.IsEmpty());
|
||||
mJobs.RemoveElementAt(0);
|
||||
if (!mJobs.IsEmpty()) {
|
||||
mJobs[0]->Start();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Done(ServiceWorkerJob* aJob)
|
||||
{
|
||||
MOZ_ASSERT(!mJobs.IsEmpty());
|
||||
MOZ_ASSERT(mJobs[0] == aJob);
|
||||
Pop();
|
||||
}
|
||||
};
|
||||
|
||||
// Needs to inherit from nsISupports because NS_ProxyRelease() does not support
|
||||
|
@ -115,30 +169,15 @@ public:
|
|||
// the URLs of the following three workers.
|
||||
nsCString mScriptSpec;
|
||||
|
||||
nsRefPtr<ServiceWorkerInfo> mCurrentWorker;
|
||||
nsRefPtr<ServiceWorkerInfo> mActiveWorker;
|
||||
nsRefPtr<ServiceWorkerInfo> mWaitingWorker;
|
||||
nsRefPtr<ServiceWorkerInfo> mInstallingWorker;
|
||||
|
||||
nsAutoPtr<UpdatePromise> mUpdatePromise;
|
||||
nsRefPtr<ServiceWorkerUpdateInstance> mUpdateInstance;
|
||||
|
||||
void
|
||||
AddUpdatePromiseObserver(Promise* aPromise)
|
||||
{
|
||||
MOZ_ASSERT(HasUpdatePromise());
|
||||
mUpdatePromise->AddPromise(aPromise);
|
||||
}
|
||||
|
||||
bool
|
||||
HasUpdatePromise()
|
||||
{
|
||||
return mUpdatePromise;
|
||||
}
|
||||
|
||||
// When unregister() is called on a registration, it is not immediately
|
||||
// removed since documents may be controlled. It is marked as
|
||||
// pendingUninstall and when all controlling documents go away, removed.
|
||||
bool mPendingUninstall;
|
||||
bool mWaitingToActivate;
|
||||
|
||||
explicit ServiceWorkerRegistrationInfo(const nsACString& aScope);
|
||||
|
||||
|
@ -151,7 +190,7 @@ public:
|
|||
} else if (mWaitingWorker) {
|
||||
newest = mWaitingWorker;
|
||||
} else {
|
||||
newest = mCurrentWorker;
|
||||
newest = mActiveWorker;
|
||||
}
|
||||
|
||||
return newest.forget();
|
||||
|
@ -172,11 +211,20 @@ public:
|
|||
bool
|
||||
IsControllingDocuments() const
|
||||
{
|
||||
return mControlledDocumentsCounter > 0;
|
||||
return mActiveWorker && mControlledDocumentsCounter > 0;
|
||||
}
|
||||
|
||||
void
|
||||
Clear();
|
||||
|
||||
void
|
||||
TryToActivate();
|
||||
|
||||
void
|
||||
Activate();
|
||||
|
||||
void
|
||||
FinishActivate(bool aSuccess);
|
||||
};
|
||||
|
||||
#define NS_SERVICEWORKERMANAGER_IMPL_IID \
|
||||
|
@ -195,14 +243,13 @@ public:
|
|||
class ServiceWorkerManager MOZ_FINAL : public nsIServiceWorkerManager
|
||||
{
|
||||
friend class ActivationRunnable;
|
||||
friend class RegisterRunnable;
|
||||
friend class CallInstallRunnable;
|
||||
friend class CancelServiceWorkerInstallationRunnable;
|
||||
friend class ServiceWorkerRegistrationInfo;
|
||||
friend class ServiceWorkerUpdateInstance;
|
||||
friend class ServiceWorkerRegisterJob;
|
||||
friend class GetReadyPromiseRunnable;
|
||||
friend class GetRegistrationsRunnable;
|
||||
friend class GetRegistrationRunnable;
|
||||
friend class QueueFireUpdateFoundRunnable;
|
||||
friend class UnregisterRunnable;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -244,6 +291,8 @@ public:
|
|||
|
||||
nsRefPtrHashtable<nsISupportsHashKey, ServiceWorkerRegistrationInfo> mControlledDocuments;
|
||||
|
||||
nsClassHashtable<nsCStringHashKey, ServiceWorkerJobQueue> mJobQueues;
|
||||
|
||||
ServiceWorkerDomainInfo()
|
||||
{ }
|
||||
|
||||
|
@ -275,6 +324,12 @@ public:
|
|||
mServiceWorkerRegistrationInfos.Remove(aRegistration->mScope);
|
||||
}
|
||||
|
||||
ServiceWorkerJobQueue*
|
||||
GetOrCreateJobQueue(const nsCString& aScope)
|
||||
{
|
||||
return mJobQueues.LookupOrAdd(aScope);
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(ServiceWorkerDomainInfo)
|
||||
|
||||
private:
|
||||
|
@ -284,26 +339,9 @@ public:
|
|||
|
||||
nsRefPtrHashtable<nsCStringHashKey, ServiceWorkerDomainInfo> mDomainMap;
|
||||
|
||||
void
|
||||
ResolveRegisterPromises(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
const nsACString& aWorkerScriptSpec);
|
||||
|
||||
void
|
||||
RejectUpdatePromiseObservers(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
nsresult aResult);
|
||||
|
||||
void
|
||||
RejectUpdatePromiseObservers(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
const ErrorEventInit& aErrorDesc);
|
||||
|
||||
void
|
||||
FinishFetch(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
void
|
||||
FinishInstall(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
void
|
||||
FinishActivate(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
void
|
||||
HandleError(JSContext* aCx,
|
||||
|
@ -333,10 +371,6 @@ private:
|
|||
nsresult
|
||||
Update(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
void
|
||||
Install(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
ServiceWorkerInfo* aServiceWorkerInfo);
|
||||
|
||||
NS_IMETHOD
|
||||
CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
|
||||
const nsACString& aScriptSpec,
|
||||
|
@ -390,10 +424,17 @@ private:
|
|||
static void
|
||||
RemoveScope(nsTArray<nsCString>& aList, const nsACString& aScope);
|
||||
|
||||
void
|
||||
QueueFireEventOnServiceWorkerRegistrations(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
const nsAString& aName);
|
||||
|
||||
void
|
||||
FireEventOnServiceWorkerRegistrations(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
const nsAString& aName);
|
||||
|
||||
void
|
||||
FireControllerChange(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
void
|
||||
StorePendingReadyPromise(nsPIDOMWindow* aWindow, nsIURI* aURI, Promise* aPromise);
|
||||
|
||||
|
|
|
@ -237,7 +237,9 @@ ServiceWorkerRegistration::GetWorkerReference(WhichServiceWorker aWhichOne)
|
|||
MOZ_CRASH("Invalid enum value");
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv) || rv == NS_ERROR_DOM_NOT_FOUND_ERR,
|
||||
"Unexpected error getting service worker instance from ServiceWorkerManager");
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -462,14 +462,14 @@ GetterOnlyJSNative(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
|
|||
|
||||
namespace {
|
||||
|
||||
class UnregisterRunnable;
|
||||
class WorkerScopeUnregisterRunnable;
|
||||
class UnregisterResultRunnable MOZ_FINAL : public WorkerRunnable
|
||||
{
|
||||
public:
|
||||
enum State { Succeeded, Failed };
|
||||
|
||||
UnregisterResultRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
UnregisterRunnable* aRunnable,
|
||||
WorkerScopeUnregisterRunnable* aRunnable,
|
||||
State aState, bool aValue)
|
||||
: WorkerRunnable(aWorkerPrivate,
|
||||
WorkerThreadUnchangedBusyCount)
|
||||
|
@ -483,14 +483,14 @@ public:
|
|||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
nsRefPtr<UnregisterRunnable> mRunnable;
|
||||
nsRefPtr<WorkerScopeUnregisterRunnable> mRunnable;
|
||||
State mState;
|
||||
bool mValue;
|
||||
};
|
||||
|
||||
class UnregisterRunnable MOZ_FINAL : public nsRunnable
|
||||
, public nsIServiceWorkerUnregisterCallback
|
||||
, public WorkerFeature
|
||||
class WorkerScopeUnregisterRunnable MOZ_FINAL : public nsRunnable
|
||||
, public nsIServiceWorkerUnregisterCallback
|
||||
, public WorkerFeature
|
||||
{
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
nsRefPtr<Promise> mWorkerPromise;
|
||||
|
@ -500,9 +500,9 @@ class UnregisterRunnable MOZ_FINAL : public nsRunnable
|
|||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
UnregisterRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
Promise* aWorkerPromise,
|
||||
const nsAString& aScope)
|
||||
WorkerScopeUnregisterRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
Promise* aWorkerPromise,
|
||||
const nsAString& aScope)
|
||||
: mWorkerPrivate(aWorkerPrivate)
|
||||
, mWorkerPromise(aWorkerPromise)
|
||||
, mScope(aScope)
|
||||
|
@ -564,7 +564,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
~UnregisterRunnable()
|
||||
~WorkerScopeUnregisterRunnable()
|
||||
{
|
||||
MOZ_ASSERT(mCleanedUp);
|
||||
}
|
||||
|
@ -604,7 +604,7 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(UnregisterRunnable, nsRunnable,
|
||||
NS_IMPL_ISUPPORTS_INHERITED(WorkerScopeUnregisterRunnable, nsRunnable,
|
||||
nsIServiceWorkerUnregisterCallback)
|
||||
|
||||
bool
|
||||
|
@ -635,8 +635,8 @@ ServiceWorkerGlobalScope::Unregister(ErrorResult& aRv)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<UnregisterRunnable> runnable =
|
||||
new UnregisterRunnable(mWorkerPrivate, promise, mScope);
|
||||
nsRefPtr<WorkerScopeUnregisterRunnable> runnable =
|
||||
new WorkerScopeUnregisterRunnable(mWorkerPrivate, promise, mScope);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
|
||||
return promise.forget();
|
||||
|
|
|
@ -24,37 +24,42 @@
|
|||
window.opener.postMessage({status: "done"}, "*");
|
||||
}
|
||||
|
||||
if (navigator.serviceWorker.controller) {
|
||||
my_ok(navigator.serviceWorker.controller.scope.match(/serviceworkers\/control$/),
|
||||
navigator.serviceWorker.ready.then(function(swr) {
|
||||
my_ok(swr.scope.match(/serviceworkers\/control$/),
|
||||
"This page should be controlled by upper level registration");
|
||||
my_ok(navigator.serviceWorker.installing == undefined,
|
||||
my_ok(swr.installing == undefined,
|
||||
"Upper level registration should not have a installing worker.");
|
||||
// We are controlled.
|
||||
// Register a new worker for this sub-scope. After that, controller should still be for upper level, but active should change to be this scope's.
|
||||
navigator.serviceWorker.register("../worker2.js", { scope: "./" }).then(function(e) {
|
||||
my_ok("installing" in e, "ServiceWorkerRegistration.installing exists.");
|
||||
my_ok(e.installing instanceof ServiceWorker, "ServiceWorkerRegistration.installing is a ServiceWorker.");
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// We are controlled.
|
||||
// Register a new worker for this sub-scope. After that, controller should still be for upper level, but active should change to be this scope's.
|
||||
navigator.serviceWorker.register("../worker2.js", { scope: "./" }).then(function(e) {
|
||||
my_ok("installing" in e, "ServiceWorkerRegistration.installing exists.");
|
||||
my_ok(e.installing instanceof ServiceWorker, "ServiceWorkerRegistration.installing is a ServiceWorker.");
|
||||
|
||||
my_ok("waiting" in e, "ServiceWorkerRegistration.waiting exists.");
|
||||
my_ok("active" in e, "ServiceWorkerRegistration.active exists.");
|
||||
my_ok("waiting" in e, "ServiceWorkerRegistration.waiting exists.");
|
||||
my_ok("active" in e, "ServiceWorkerRegistration.active exists.");
|
||||
|
||||
my_ok(e.installing &&
|
||||
e.installing.scope.match(/controller\/$/),
|
||||
"Installing is serviceworker/controller");
|
||||
my_ok(e.installing &&
|
||||
e.installing.scriptURL.match(/worker2.js$/),
|
||||
"Installing is serviceworker/controller");
|
||||
|
||||
my_ok("scope" in e, "ServiceWorkerRegistration.scope exists.");
|
||||
my_ok(e.scope.match(/serviceworkers\/controller\/$/), "Scope is serviceworker/controller " + e.scope);
|
||||
my_ok("scope" in e, "ServiceWorkerRegistration.scope exists.");
|
||||
my_ok(e.scope.match(/serviceworkers\/controller\/$/), "Scope is serviceworker/controller " + e.scope);
|
||||
|
||||
my_ok("unregister" in e, "ServiceWorkerRegistration.unregister exists.");
|
||||
my_ok("unregister" in e, "ServiceWorkerRegistration.unregister exists.");
|
||||
|
||||
my_ok(navigator.serviceWorker.controller.scope.match(/serviceworkers\/control$/),
|
||||
"Controller is still serviceworker/control");
|
||||
my_ok(navigator.serviceWorker.controller.scriptURL.match(/worker\.js$/),
|
||||
"Controller is still worker.js");
|
||||
finish();
|
||||
});
|
||||
} else {
|
||||
my_ok(false, "Should've been controlled!");
|
||||
finish();
|
||||
});
|
||||
} else {
|
||||
my_ok(false, "Should've been controlled!");
|
||||
}
|
||||
}).catch(function(e) {
|
||||
my_ok(false, "Some test threw an error " + e);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -10,8 +10,10 @@ support-files =
|
|||
simpleregister/ready.html
|
||||
controller/index.html
|
||||
unregister/index.html
|
||||
workerUpdate/update.html
|
||||
sw_clients/simple.html
|
||||
get_serviced_worker.js
|
||||
worker_update.js
|
||||
|
||||
[test_unregister.html]
|
||||
skip-if = true # bug 1094375
|
||||
|
@ -22,3 +24,5 @@ skip-if = true # bug 1094375
|
|||
[test_navigator.html]
|
||||
[test_scopes.html]
|
||||
[test_controller.html]
|
||||
[test_workerUpdate.html]
|
||||
skip-if = true # Enable after Bug 982726 postMessage is landed.
|
||||
|
|
|
@ -66,9 +66,9 @@
|
|||
// because the registration is for the realworker scope, so the workers
|
||||
// should be obtained for that scope and not for
|
||||
// test_installation_simple.html
|
||||
var worker = wr.installing || wr.waiting || wr.active;
|
||||
ok(worker && worker.scope.match(/realworker$/) &&
|
||||
worker.url.match(/worker.js$/), "Valid worker instance should be available.");
|
||||
var worker = wr.installing;
|
||||
ok(worker && wr.scope.match(/realworker$/) &&
|
||||
worker.scriptURL.match(/worker.js$/), "Valid worker instance should be available.");
|
||||
}, function(e) {
|
||||
info("Error: " + e.name);
|
||||
ok(false, "realWorker Registration should have succeeded!");
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1065366 - Test ServiceWorkerGlobalScope.update</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function simpleRegister() {
|
||||
return navigator.serviceWorker.register("worker_update.js", { scope: "workerUpdate/" });
|
||||
}
|
||||
|
||||
function waitForMessages(sw) {
|
||||
var p = new Promise(function(resolve, reject) {
|
||||
window.onmessage = function(e) {
|
||||
if (e.data === "FINISH") {
|
||||
ok(true, "The worker has updated itself");
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var frame = document.createElement("iframe");
|
||||
frame.setAttribute("src", "workerUpdate/update.html");
|
||||
document.body.appendChild(frame);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
simpleRegister().then(waitForMessages).catch(function(e) {
|
||||
ok(false, "Something went wrong.");
|
||||
}).then(function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true]
|
||||
]}, runTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test worker::update</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
|
||||
onmessage = function(e) { parent.postMessage(e.data, "*"); }
|
||||
navigator.serviceWorker.ready.then(function() {
|
||||
navigator.serviceWorker.controller.postMessage("GO");
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// For now this test only calls update to verify that our registration
|
||||
// job queueing works properly when called from the worker thread. We should
|
||||
// test actual update scenarios with a SJS test.
|
||||
onmessage = function(e) {
|
||||
self.update();
|
||||
clients.getServiced().then(function(c) {
|
||||
if (c.length == 0) {
|
||||
// We cannot proceed.
|
||||
return;
|
||||
}
|
||||
|
||||
c[0].postMessage('FINISH');
|
||||
});
|
||||
}
|
|
@ -9,6 +9,8 @@
|
|||
#include <cmath>
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ToString.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
@ -80,6 +82,14 @@ struct BasePoint {
|
|||
return *static_cast<Sub*>(this);
|
||||
}
|
||||
|
||||
// "Finite" means not inf and not NaN
|
||||
bool IsFinite() const
|
||||
{
|
||||
typedef typename mozilla::Conditional<mozilla::IsSame<T, float>::value, float, double>::Type FloatType;
|
||||
return (mozilla::IsFinite(FloatType(x)) && mozilla::IsFinite(FloatType(y)));
|
||||
return true;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& stream, const BasePoint<T, Sub, Coord>& aPoint) {
|
||||
return stream << '(' << aPoint.x << ',' << aPoint.y << ')';
|
||||
}
|
||||
|
|
|
@ -571,13 +571,13 @@ Factory::CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA,
|
|||
|
||||
newTargetA = new DrawTargetD2D();
|
||||
if (!newTargetA->Init(aTextureA, aFormat)) {
|
||||
gfxWarning() << "Failed to create draw target for D3D10 texture.";
|
||||
gfxWarning() << "Failed to create dual draw target for D3D10 texture.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
newTargetB = new DrawTargetD2D();
|
||||
if (!newTargetB->Init(aTextureB, aFormat)) {
|
||||
gfxWarning() << "Failed to create draw target for D3D10 texture.";
|
||||
gfxWarning() << "Failed to create new draw target for D3D10 texture.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -633,7 +633,7 @@ Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceForma
|
|||
return retVal;
|
||||
}
|
||||
|
||||
gfxWarning() << "Failed to create draw target for D3D10 texture.";
|
||||
gfxWarning() << "Failed to create draw target for D3D11 texture.";
|
||||
|
||||
// Failed
|
||||
return nullptr;
|
||||
|
|
|
@ -20,12 +20,19 @@ PathBuilderCG::~PathBuilderCG()
|
|||
void
|
||||
PathBuilderCG::MoveTo(const Point &aPoint)
|
||||
{
|
||||
if (!aPoint.IsFinite()) {
|
||||
return;
|
||||
}
|
||||
CGPathMoveToPoint(mCGPath, nullptr, aPoint.x, aPoint.y);
|
||||
}
|
||||
|
||||
void
|
||||
PathBuilderCG::LineTo(const Point &aPoint)
|
||||
{
|
||||
if (!aPoint.IsFinite()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CGPathIsEmpty(mCGPath))
|
||||
MoveTo(aPoint);
|
||||
else
|
||||
|
@ -37,6 +44,9 @@ PathBuilderCG::BezierTo(const Point &aCP1,
|
|||
const Point &aCP2,
|
||||
const Point &aCP3)
|
||||
{
|
||||
if (!aCP1.IsFinite() || !aCP2.IsFinite() || !aCP3.IsFinite()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CGPathIsEmpty(mCGPath))
|
||||
MoveTo(aCP1);
|
||||
|
@ -49,13 +59,17 @@ PathBuilderCG::BezierTo(const Point &aCP1,
|
|||
|
||||
void
|
||||
PathBuilderCG::QuadraticBezierTo(const Point &aCP1,
|
||||
const Point &aCP2)
|
||||
const Point &aCP2)
|
||||
{
|
||||
if (!aCP1.IsFinite() || !aCP2.IsFinite()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CGPathIsEmpty(mCGPath))
|
||||
MoveTo(aCP1);
|
||||
CGPathAddQuadCurveToPoint(mCGPath, nullptr,
|
||||
aCP1.x, aCP1.y,
|
||||
aCP2.x, aCP2.y);
|
||||
aCP1.x, aCP1.y,
|
||||
aCP2.x, aCP2.y);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -69,6 +83,11 @@ void
|
|||
PathBuilderCG::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
|
||||
Float aEndAngle, bool aAntiClockwise)
|
||||
{
|
||||
if (!aOrigin.IsFinite() || !IsFinite(aRadius) ||
|
||||
!IsFinite(aStartAngle) || !IsFinite(aEndAngle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disabled for now due to a CG bug when using CGPathAddArc with stroke
|
||||
// dashing and rotation transforms that are multiples of 90 degrees. See:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=949661#c8
|
||||
|
|
|
@ -364,7 +364,7 @@ RotatedContentBuffer::EnsureBufferOnWhite()
|
|||
}
|
||||
|
||||
NS_WARN_IF_FALSE(mDTBufferOnWhite, "no buffer");
|
||||
return mDTBufferOnWhite;
|
||||
return !!mDTBufferOnWhite;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -198,7 +198,7 @@ ParentLayerCoord Axis::GetOverscroll() const {
|
|||
ParentLayerCoord result = (mOverscroll - mOverscrollOffset) / mOverscrollScale;
|
||||
|
||||
// Assert that we return overscroll in the correct direction
|
||||
MOZ_ASSERT((result.value * mOverscrollOffset.value) >= 0.0f);
|
||||
MOZ_ASSERT((result.value * mFirstOverscrollAnimationSample.value) >= 0.0f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче