зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team
This commit is contained in:
Коммит
57fcc86793
|
@ -193,9 +193,9 @@ const LRESULT = ctypes.size_t;
|
|||
const ULONG_PTR = ctypes.uintptr_t;
|
||||
const PVOID = ctypes.voidptr_t;
|
||||
const LPVOID = PVOID;
|
||||
const LPCTSTR = ctypes.jschar.ptr;
|
||||
const LPCWSTR = ctypes.jschar.ptr;
|
||||
const LPTSTR = ctypes.jschar.ptr;
|
||||
const LPCTSTR = ctypes.char16_t.ptr;
|
||||
const LPCWSTR = ctypes.char16_t.ptr;
|
||||
const LPTSTR = ctypes.char16_t.ptr;
|
||||
const LPSTR = ctypes.char.ptr;
|
||||
const LPCSTR = ctypes.char.ptr;
|
||||
const LPBYTE = ctypes.char.ptr;
|
||||
|
@ -707,8 +707,8 @@ function subprocess_win32(options) {
|
|||
if(environment.length) {
|
||||
//An environment block consists of
|
||||
//a null-terminated block of null-terminated strings.
|
||||
//Using CREATE_UNICODE_ENVIRONMENT so needs to be jschar
|
||||
environment = ctypes.jschar.array()(environment.join('\0') + '\0');
|
||||
//Using CREATE_UNICODE_ENVIRONMENT so needs to be char16_t
|
||||
environment = ctypes.char16_t.array()(environment.join('\0') + '\0');
|
||||
} else {
|
||||
environment = null;
|
||||
}
|
||||
|
|
|
@ -976,12 +976,12 @@ pref("apz.subframe.enabled", true);
|
|||
|
||||
// Overscroll-related settings
|
||||
pref("apz.overscroll.enabled", true);
|
||||
pref("apz.overscroll.fling_friction", "0.02");
|
||||
pref("apz.overscroll.fling_friction", "0.05");
|
||||
pref("apz.overscroll.fling_stopped_threshold", "0.4");
|
||||
pref("apz.overscroll.stretch_factor", "0.5");
|
||||
pref("apz.overscroll.snap_back.spring_stiffness", "0.6");
|
||||
pref("apz.overscroll.snap_back.spring_stiffness", "0.05");
|
||||
pref("apz.overscroll.snap_back.spring_friction", "0.1");
|
||||
pref("apz.overscroll.snap_back.mass", "1200");
|
||||
pref("apz.overscroll.snap_back.mass", "100");
|
||||
|
||||
// This preference allows FirefoxOS apps (and content, I think) to force
|
||||
// the use of software (instead of hardware accelerated) 2D canvases by
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4acd3e69b263b54f4111e3586ff4ade84b49b4da"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4abb193ddae0f9780ad12ffe5e31772feee3926a"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -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="4acd3e69b263b54f4111e3586ff4ade84b49b4da"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4abb193ddae0f9780ad12ffe5e31772feee3926a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4acd3e69b263b54f4111e3586ff4ade84b49b4da"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4abb193ddae0f9780ad12ffe5e31772feee3926a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="facdb3593e63dcbb740709303a5b2527113c50a0"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4acd3e69b263b54f4111e3586ff4ade84b49b4da"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4abb193ddae0f9780ad12ffe5e31772feee3926a"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -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="4acd3e69b263b54f4111e3586ff4ade84b49b4da"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4abb193ddae0f9780ad12ffe5e31772feee3926a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4acd3e69b263b54f4111e3586ff4ade84b49b4da"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4abb193ddae0f9780ad12ffe5e31772feee3926a"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4acd3e69b263b54f4111e3586ff4ade84b49b4da"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4abb193ddae0f9780ad12ffe5e31772feee3926a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="facdb3593e63dcbb740709303a5b2527113c50a0"/>
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "4ea08e48f566bc02e4df1600ec1aeae413c1a1d7",
|
||||
"revision": "d43b2e2dba496f624d62c1b72a22dc5e34953fbd",
|
||||
"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="4acd3e69b263b54f4111e3586ff4ade84b49b4da"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4abb193ddae0f9780ad12ffe5e31772feee3926a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -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="4acd3e69b263b54f4111e3586ff4ade84b49b4da"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4abb193ddae0f9780ad12ffe5e31772feee3926a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4acd3e69b263b54f4111e3586ff4ade84b49b4da"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4abb193ddae0f9780ad12ffe5e31772feee3926a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="facdb3593e63dcbb740709303a5b2527113c50a0"/>
|
||||
|
|
|
@ -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="4acd3e69b263b54f4111e3586ff4ade84b49b4da"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4abb193ddae0f9780ad12ffe5e31772feee3926a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -1279,6 +1279,7 @@ pref("services.sync.prefs.sync.privacy.clearOnShutdown.siteSettings", true);
|
|||
pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true);
|
||||
pref("services.sync.prefs.sync.privacy.donottrackheader.value", true);
|
||||
pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true);
|
||||
pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true);
|
||||
pref("services.sync.prefs.sync.security.OCSP.enabled", true);
|
||||
pref("services.sync.prefs.sync.security.OCSP.require", true);
|
||||
pref("services.sync.prefs.sync.security.default_personal_cert", true);
|
||||
|
|
|
@ -44,8 +44,11 @@ const gXPInstallObserver = {
|
|||
} catch (e) {
|
||||
browser = winOrBrowser;
|
||||
}
|
||||
if (!browser)
|
||||
// Note that the above try/catch will pass through dead object proxies and
|
||||
// other degenerate objects. Make sure the browser is bonafide.
|
||||
if (!browser || gBrowser.browsers.indexOf(browser) == -1)
|
||||
return;
|
||||
|
||||
const anchorID = "addons-notification-icon";
|
||||
var messageString, action;
|
||||
var brandShortName = brandBundle.getString("brandShortName");
|
||||
|
@ -80,8 +83,16 @@ const gXPInstallObserver = {
|
|||
action, null, options);
|
||||
break;
|
||||
case "addon-install-blocked":
|
||||
let originatingHost;
|
||||
try {
|
||||
originatingHost = installInfo.originatingURI.host;
|
||||
} catch (ex) {
|
||||
// Need to deal with missing originatingURI and with about:/data: URIs more gracefully,
|
||||
// see bug 1063418 - but for now, bail:
|
||||
return;
|
||||
}
|
||||
messageString = gNavigatorBundle.getFormattedString("xpinstallPromptWarning",
|
||||
[brandShortName, installInfo.originatingURI.host]);
|
||||
[brandShortName, originatingHost]);
|
||||
|
||||
let secHistogram = Components.classes["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry).getHistogramById("SECURITY_UI");
|
||||
action = {
|
||||
|
|
|
@ -2336,6 +2336,9 @@ let BrowserOnClick = {
|
|||
|
||||
let originalTarget = event.originalTarget;
|
||||
let ownerDoc = originalTarget.ownerDocument;
|
||||
if (!ownerDoc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gMultiProcessBrowser &&
|
||||
ownerDoc.documentURI.toLowerCase() == "about:newtab") {
|
||||
|
|
|
@ -370,6 +370,9 @@ let ClickEventHandler = {
|
|||
|
||||
let originalTarget = event.originalTarget;
|
||||
let ownerDoc = originalTarget.ownerDocument;
|
||||
if (!ownerDoc) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle click events from about pages
|
||||
if (ownerDoc.documentURI.startsWith("about:certerror")) {
|
||||
|
|
|
@ -143,6 +143,7 @@ add_task(function* formHistory() {
|
|||
let deferred = Promise.defer();
|
||||
Services.obs.addObserver(function onAdd(subj, topic, data) {
|
||||
if (data == "formhistory-add") {
|
||||
Services.obs.removeObserver(onAdd, "satchel-storage-changed");
|
||||
executeSoon(() => deferred.resolve());
|
||||
}
|
||||
}, "satchel-storage-changed", false);
|
||||
|
@ -167,8 +168,9 @@ add_task(function* formHistory() {
|
|||
|
||||
// Wait for Satchel.
|
||||
deferred = Promise.defer();
|
||||
Services.obs.addObserver(function onAdd(subj, topic, data) {
|
||||
Services.obs.addObserver(function onRemove(subj, topic, data) {
|
||||
if (data == "formhistory-remove") {
|
||||
Services.obs.removeObserver(onRemove, "satchel-storage-changed");
|
||||
executeSoon(() => deferred.resolve());
|
||||
}
|
||||
}, "satchel-storage-changed", false);
|
||||
|
|
|
@ -659,7 +659,7 @@ var gAdvancedPane = {
|
|||
}
|
||||
try {
|
||||
const DRIVE_FIXED = 3;
|
||||
const LPCWSTR = ctypes.jschar.ptr;
|
||||
const LPCWSTR = ctypes.char16_t.ptr;
|
||||
const UINT = ctypes.uint32_t;
|
||||
let kernel32 = ctypes.open("kernel32");
|
||||
let GetDriveType = kernel32.declare("GetDriveTypeW", ctypes.default_abi, UINT, LPCWSTR);
|
||||
|
|
|
@ -133,7 +133,9 @@ function windowLoad(event, win, dialog) {
|
|||
return;
|
||||
|
||||
if (tests[currentTest].observances.length == 0) {
|
||||
// Should fail here as we are not expecting a notification.
|
||||
// Should fail here as we are not expecting a notification, but we don't.
|
||||
// See bug 1063410.
|
||||
return;
|
||||
}
|
||||
|
||||
let permission = aSubject.QueryInterface(Ci.nsIPermission);
|
||||
|
|
|
@ -17,6 +17,10 @@ function notification(win, topic) {
|
|||
}
|
||||
|
||||
let { notification, window } = expected.shift();
|
||||
if (Cu.isDeadWrapper(window)) {
|
||||
// Sometimes we end up with a nuked window reference here :-(
|
||||
return;
|
||||
}
|
||||
is(topic, notification, "Saw the expected notification");
|
||||
is(win, window, "Saw the expected window");
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ add_task(function* SetCurrentEngine() {
|
|||
info("Test observed " + data);
|
||||
if (data == "engine-current") {
|
||||
ok(true, "Test observed engine-current");
|
||||
Services.obs.removeObserver(obs, "browser-search-engine-modified", false);
|
||||
Services.obs.removeObserver(obs, "browser-search-engine-modified");
|
||||
deferred.resolve();
|
||||
}
|
||||
}, "browser-search-engine-modified", false);
|
||||
|
@ -188,6 +188,7 @@ add_task(function* GetSuggestions_AddFormHistoryEntry_RemoveFormHistoryEntry() {
|
|||
let deferred = Promise.defer();
|
||||
Services.obs.addObserver(function onAdd(subj, topic, data) {
|
||||
if (data == "formhistory-add") {
|
||||
Services.obs.removeObserver(onAdd, "satchel-storage-changed");
|
||||
executeSoon(() => deferred.resolve());
|
||||
}
|
||||
}, "satchel-storage-changed", false);
|
||||
|
@ -224,6 +225,7 @@ add_task(function* GetSuggestions_AddFormHistoryEntry_RemoveFormHistoryEntry() {
|
|||
deferred = Promise.defer();
|
||||
Services.obs.addObserver(function onRemove(subj, topic, data) {
|
||||
if (data == "formhistory-remove") {
|
||||
Services.obs.removeObserver(onRemove, "satchel-storage-changed");
|
||||
executeSoon(() => deferred.resolve());
|
||||
}
|
||||
}, "satchel-storage-changed", false);
|
||||
|
|
|
@ -255,7 +255,8 @@ function test_auth() {
|
|||
|
||||
let winObs = new WindowObserver(function(authWin) {
|
||||
ok(authWin, "Authentication window opened");
|
||||
ok(authWin.contentWindow.location);
|
||||
// See bug 1063404.
|
||||
// ok(authWin.location);
|
||||
});
|
||||
|
||||
Services.ww.registerNotification(winObs);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "nsTextFormatter.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIEffectiveTLDService.h"
|
||||
#include "nsIProperties.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsIFile.h"
|
||||
|
@ -580,6 +581,35 @@ DenyAccessIfURIHasFlags(nsIURI* aURI, uint32_t aURIFlags)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
EqualOrSubdomain(nsIURI* aProbeArg, nsIURI* aBase)
|
||||
{
|
||||
// Make a clone of the incoming URI, because we're going to mutate it.
|
||||
nsCOMPtr<nsIURI> probe;
|
||||
nsresult rv = aProbeArg->Clone(getter_AddRefs(probe));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsCOMPtr<nsIEffectiveTLDService> tldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(tldService, false);
|
||||
while (true) {
|
||||
if (nsScriptSecurityManager::SecurityCompareURIs(probe, aBase)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsAutoCString host, newHost;
|
||||
nsresult rv = probe->GetHost(host);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
rv = tldService->GetNextSubDomain(host, newHost);
|
||||
if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
|
||||
return false;
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
rv = probe->SetHost(newHost);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
nsIURI *aTargetURI,
|
||||
|
@ -796,7 +826,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
|||
// Allow domains that were whitelisted in the prefs. In 99.9% of cases,
|
||||
// this array is empty.
|
||||
for (size_t i = 0; i < mFileURIWhitelist.Length(); ++i) {
|
||||
if (SecurityCompareURIs(mFileURIWhitelist[i], sourceURI)) {
|
||||
if (EqualOrSubdomain(sourceURI, mFileURIWhitelist[i])) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
@ -1433,7 +1463,7 @@ nsScriptSecurityManager::AddSitesToFileURIWhitelist(const nsCString& aSiteList)
|
|||
if (NS_FAILED(sIOService->ExtractScheme(site, unused))) {
|
||||
AddSitesToFileURIWhitelist(NS_LITERAL_CSTRING("http://") + site);
|
||||
AddSitesToFileURIWhitelist(NS_LITERAL_CSTRING("https://") + site);
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Convert it to a URI and add it to our list.
|
||||
|
|
|
@ -82,13 +82,18 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=995943
|
|||
pushPrefs.bind(null, [['capability.policy.policynames', ',somepolicy, someotherpolicy, '],
|
||||
['capability.policy.somepolicy.checkloaduri.enabled', 'allaccess'],
|
||||
['capability.policy.someotherpolicy.checkloaduri.enabled', 'nope'],
|
||||
['capability.policy.somepolicy.sites', ' http://example.org https://example.com test1.example.com'],
|
||||
['capability.policy.somepolicy.sites', ' http://example.org test1.example.com https://test2.example.com '],
|
||||
['capability.policy.someotherpolicy.sites', 'http://example.net ']]))
|
||||
.then(checkLoadFileURI.bind(null, 'http://example.org', true))
|
||||
.then(checkLoadFileURI.bind(null, 'http://example.com', false))
|
||||
.then(checkLoadFileURI.bind(null, 'http://test2.example.com', false))
|
||||
.then(checkLoadFileURI.bind(null, 'https://test2.example.com', true))
|
||||
.then(checkLoadFileURI.bind(null, 'http://sub1.test2.example.com', false))
|
||||
.then(checkLoadFileURI.bind(null, 'https://sub1.test2.example.com', true))
|
||||
.then(checkLoadFileURI.bind(null, 'http://example.net', false))
|
||||
.then(checkLoadFileURI.bind(null, 'http://test1.example.com', true))
|
||||
.then(checkLoadFileURI.bind(null, 'https://test1.example.com', true))
|
||||
.then(checkLoadFileURI.bind(null, 'http://sub1.test1.example.com', true))
|
||||
.then(checkLoadFileURI.bind(null, 'https://sub1.test1.example.com', true))
|
||||
.then(pushPrefs.bind(null, [['capability.policy.someotherpolicy.checkloaduri.enabled', 'allAccess']]))
|
||||
.then(checkLoadFileURI.bind(null, 'http://example.net', true))
|
||||
.then(popPrefs)
|
||||
|
|
|
@ -574,10 +574,6 @@ def tarjan(V, E):
|
|||
|
||||
|
||||
def main():
|
||||
# Suppress the build time check if MOZ_NO_BUILD_TIME_SM_CHECKS is set.
|
||||
if "MOZ_NO_BUILD_TIME_SM_CHECKS" in os.environ:
|
||||
sys.exit(0)
|
||||
|
||||
ok = check_style()
|
||||
|
||||
if ok:
|
||||
|
|
|
@ -6408,7 +6408,7 @@ nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
|
|||
|
||||
JS::Rooted<JSObject*> re(cx,
|
||||
JS_NewUCRegExpObjectNoStatics(cx,
|
||||
static_cast<jschar*>(aPattern.BeginWriting()),
|
||||
static_cast<char16_t*>(aPattern.BeginWriting()),
|
||||
aPattern.Length(), 0));
|
||||
if (!re) {
|
||||
JS_ClearPendingException(cx);
|
||||
|
@ -6418,7 +6418,7 @@ nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
|
|||
JS::Rooted<JS::Value> rval(cx, JS::NullValue());
|
||||
size_t idx = 0;
|
||||
if (!JS_ExecuteRegExpNoStatics(cx, re,
|
||||
static_cast<jschar*>(aValue.BeginWriting()),
|
||||
static_cast<char16_t*>(aValue.BeginWriting()),
|
||||
aValue.Length(), &idx, true, &rval)) {
|
||||
JS_ClearPendingException(cx);
|
||||
return true;
|
||||
|
|
|
@ -512,7 +512,7 @@ nsFrameMessageManager::GetDelayedFrameScripts(JSContext* aCx, JS::MutableHandle<
|
|||
}
|
||||
|
||||
static bool
|
||||
JSONCreator(const jschar* aBuf, uint32_t aLen, void* aData)
|
||||
JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData)
|
||||
{
|
||||
nsAString* result = static_cast<nsAString*>(aData);
|
||||
result->Append(static_cast<const char16_t*>(aBuf),
|
||||
|
@ -542,7 +542,7 @@ GetParamsForMessage(JSContext* aCx,
|
|||
NS_ENSURE_TRUE(!json.IsEmpty(), false);
|
||||
|
||||
JS::Rooted<JS::Value> val(aCx, JS::NullValue());
|
||||
NS_ENSURE_TRUE(JS_ParseJSON(aCx, static_cast<const jschar*>(json.get()),
|
||||
NS_ENSURE_TRUE(JS_ParseJSON(aCx, static_cast<const char16_t*>(json.get()),
|
||||
json.Length(), &val), false);
|
||||
|
||||
return WriteStructuredClone(aCx, val, aBuffer, aClosure);
|
||||
|
@ -638,7 +638,7 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName,
|
|||
}
|
||||
|
||||
JS::Rooted<JS::Value> ret(aCx);
|
||||
if (!JS_ParseJSON(aCx, static_cast<const jschar*>(retval[i].get()),
|
||||
if (!JS_ParseJSON(aCx, static_cast<const char16_t*>(retval[i].get()),
|
||||
retval[i].Length(), &ret)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
@ -996,7 +996,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
|||
}
|
||||
JS::Rooted<JSString*> jsMessage(cx,
|
||||
JS_NewUCStringCopyN(cx,
|
||||
static_cast<const jschar*>(aMessage.BeginReading()),
|
||||
static_cast<const char16_t*>(aMessage.BeginReading()),
|
||||
aMessage.Length()));
|
||||
NS_ENSURE_TRUE(jsMessage, NS_ERROR_OUT_OF_MEMORY);
|
||||
JS::Rooted<JS::Value> syncv(cx, JS::BooleanValue(aIsSync));
|
||||
|
@ -1489,7 +1489,7 @@ nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
|
|||
nsCOMPtr<nsIInputStream> input;
|
||||
channel->Open(getter_AddRefs(input));
|
||||
nsString dataString;
|
||||
jschar* dataStringBuf = nullptr;
|
||||
char16_t* dataStringBuf = nullptr;
|
||||
size_t dataStringLength = 0;
|
||||
uint64_t avail64 = 0;
|
||||
if (input && NS_SUCCEEDED(input->Available(&avail64)) && avail64) {
|
||||
|
|
|
@ -109,7 +109,7 @@ public:
|
|||
bool mIsInline; // Is the script inline or loaded?
|
||||
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
|
||||
nsString mSourceMapURL; // Holds source map url for loaded scripts
|
||||
jschar* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
|
||||
char16_t* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
|
||||
size_t mScriptTextLength; // use nsString so we can give ownership to jsapi.
|
||||
uint32_t mJSVersion;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
|
@ -898,7 +898,7 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest, void **aOffThreadT
|
|||
|
||||
NS_ENSURE_ARG(aRequest);
|
||||
nsAutoString textData;
|
||||
const jschar* scriptBuf = nullptr;
|
||||
const char16_t* scriptBuf = nullptr;
|
||||
size_t scriptLength = 0;
|
||||
JS::SourceBufferHolder::Ownership giveScriptOwnership =
|
||||
JS::SourceBufferHolder::NoOwnership;
|
||||
|
@ -1278,7 +1278,7 @@ DetectByteOrderMark(const unsigned char* aBytes, int32_t aLen, nsCString& oChars
|
|||
nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
|
||||
uint32_t aLength, const nsAString& aHintCharset,
|
||||
nsIDocument* aDocument,
|
||||
jschar*& aBufOut, size_t& aLengthOut)
|
||||
char16_t*& aBufOut, size_t& aLengthOut)
|
||||
{
|
||||
if (!aLength) {
|
||||
aBufOut = nullptr;
|
||||
|
@ -1335,7 +1335,7 @@ nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
|
|||
aLength, &unicodeLength);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aBufOut = static_cast<jschar*>(js_malloc(unicodeLength * sizeof(jschar)));
|
||||
aBufOut = static_cast<char16_t*>(js_malloc(unicodeLength * sizeof(char16_t)));
|
||||
if (!aBufOut) {
|
||||
aLengthOut = 0;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
|
|
@ -170,17 +170,17 @@ public:
|
|||
* attribute). May be the empty string.
|
||||
* @param aDocument Document which the data is loaded for. Must not be
|
||||
* null.
|
||||
* @param aBufOut [out] jschar array allocated by ConvertToUTF16 and
|
||||
* @param aBufOut [out] char16_t array allocated by ConvertToUTF16 and
|
||||
* containing data converted to unicode. Caller must
|
||||
* js_free() this data when no longer needed.
|
||||
* @param aLengthOut [out] Length of array returned in aBufOut in number
|
||||
* of jschars.
|
||||
* of char16_t code units.
|
||||
*/
|
||||
static nsresult ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
|
||||
uint32_t aLength,
|
||||
const nsAString& aHintCharset,
|
||||
nsIDocument* aDocument,
|
||||
jschar*& aBufOut, size_t& aLengthOut);
|
||||
char16_t*& aBufOut, size_t& aLengthOut);
|
||||
|
||||
/**
|
||||
* Processes any pending requests that are ready for processing.
|
||||
|
|
|
@ -766,7 +766,7 @@ nsXMLHttpRequest::CreateResponseParsedJSON(JSContext* aCx)
|
|||
// The Unicode converter has already zapped the BOM if there was one
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!JS_ParseJSON(aCx,
|
||||
static_cast<const jschar*>(mResponseText.get()), mResponseText.Length(),
|
||||
static_cast<const char16_t*>(mResponseText.get()), mResponseText.Length(),
|
||||
&value)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@ function afterLoad() {
|
|||
.getService(SpecialPowers.Ci.nsIProperties)
|
||||
.get("TmpD", SpecialPowers.Ci.nsILocalFile);
|
||||
file.append("345339_test.file");
|
||||
file.createUnique(SpecialPowers.Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
|
||||
// Only the file's path is used, so it doesn't need to be created.
|
||||
// See also bug 1058977.
|
||||
filePath = file.path;
|
||||
|
||||
SpecialPowers.wrap(iframeDoc).getElementById("file").value = filePath;
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
submit_invalid_file.sjs
|
||||
[test_autocompleteinfo.html]
|
||||
[test_submit_invalid_file.html]
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
save_restore_radio_groups.sjs
|
||||
submit_invalid_file.sjs
|
||||
test_input_number_data.js
|
||||
|
||||
[test_bug1039548.html]
|
||||
|
@ -91,7 +90,6 @@ skip-if = e10s
|
|||
[test_step_attribute.html]
|
||||
skip-if = e10s
|
||||
[test_stepup_stepdown.html]
|
||||
[test_submit_invalid_file.html]
|
||||
[test_textarea_attributes_reflection.html]
|
||||
[test_validation.html]
|
||||
skip-if = buildapp == 'b2g' || e10s # b2g(374 total, bug 901848, no keygen support) b2g-debug(374 total, bug 901848, no keygen support) b2g-desktop(374 total, bug 901848, no keygen support)
|
||||
|
|
|
@ -67,7 +67,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=722599
|
|||
|
||||
function testUserInput() {
|
||||
//Simulating an OK click and with a file name return.
|
||||
MockFilePicker.useAnyFile();
|
||||
MockFilePicker.useBlobFile();
|
||||
MockFilePicker.returnValue = MockFilePicker.returnOK;
|
||||
var input = document.getElementById('fileInput');
|
||||
input.focus();
|
||||
|
|
|
@ -59,7 +59,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
|||
|
||||
function testUserInput() {
|
||||
// Simulating an OK click and with a file name return.
|
||||
MockFilePicker.useAnyFile();
|
||||
MockFilePicker.useBlobFile();
|
||||
MockFilePicker.returnValue = MockFilePicker.returnOK;
|
||||
var input = document.getElementById('fileInput');
|
||||
input.focus();
|
||||
|
|
|
@ -179,17 +179,12 @@ for (var test of data) {
|
|||
.getService(SpecialPowers.Ci.nsIProperties);
|
||||
var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
|
||||
file.append('635499_file');
|
||||
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(SpecialPowers.Ci.nsIFileOutputStream);
|
||||
outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||
0666, 0);
|
||||
outStream.write("foo", 3);
|
||||
outStream.close();
|
||||
// Only the file's path is used, so it doesn't need to be created.
|
||||
// See also bug 1058977.
|
||||
|
||||
SpecialPowers.wrap(input).value = file.path;
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
file.remove(false);
|
||||
break;
|
||||
case 'date':
|
||||
input.max = '2012-06-27';
|
||||
|
|
|
@ -177,17 +177,12 @@ for (var test of data) {
|
|||
.getService(SpecialPowers.Ci.nsIProperties);
|
||||
var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
|
||||
file.append('635499_file');
|
||||
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(SpecialPowers.Ci.nsIFileOutputStream);
|
||||
outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||
0666, 0);
|
||||
outStream.write("foo", 3);
|
||||
outStream.close();
|
||||
// Only the file's path is used, so it doesn't need to be created.
|
||||
// See also bug 1058977.
|
||||
|
||||
SpecialPowers.wrap(input).value = file.path;
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
file.remove(false);
|
||||
break;
|
||||
case 'date':
|
||||
input.value = '2012-06-28';
|
||||
|
|
|
@ -308,22 +308,18 @@ function checkInputRequiredValidityForFile()
|
|||
element.type = 'file'
|
||||
document.forms[0].appendChild(element);
|
||||
|
||||
function createFileWithData(fileName, fileData) {
|
||||
function createFile(fileName) {
|
||||
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIProperties);
|
||||
var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
|
||||
testFile.append(fileName);
|
||||
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(SpecialPowers.Ci.nsIFileOutputStream);
|
||||
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||
0666, 0);
|
||||
outStream.write(fileData, fileData.length);
|
||||
outStream.close();
|
||||
// Only the file's path is used, so it doesn't need to be created.
|
||||
// See also bug 1058977.
|
||||
|
||||
return testFile;
|
||||
}
|
||||
|
||||
var file = createFileWithData("345822_file", "file content");
|
||||
var file = createFile("345822_file");
|
||||
|
||||
SpecialPowers.wrap(element).value = "";
|
||||
element.required = false;
|
||||
|
@ -350,7 +346,6 @@ function checkInputRequiredValidityForFile()
|
|||
|
||||
element.required = true;
|
||||
SpecialPowers.wrap(element).value = '';
|
||||
file.remove(false);
|
||||
document.forms[0].removeChild(element);
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
}
|
||||
|
|
|
@ -132,17 +132,12 @@ for (var test of data) {
|
|||
.getService(SpecialPowers.Ci.nsIProperties);
|
||||
var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
|
||||
file.append('635499_file');
|
||||
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(SpecialPowers.Ci.nsIFileOutputStream);
|
||||
outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||
0666, 0);
|
||||
outStream.write("foo", 3);
|
||||
outStream.close();
|
||||
// Only the file's path is used, so it doesn't need to be created.
|
||||
// See also bug 1058977.
|
||||
|
||||
SpecialPowers.wrap(input).value = file.path;
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
file.remove(false);
|
||||
break;
|
||||
case 'date':
|
||||
// For date, the step is calulated on the timestamp since 1970-01-01
|
||||
|
|
|
@ -6,14 +6,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=702949
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test invalid file submission</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=702949">Mozilla Bug 702949</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<form action='submit_invalid_file.sjs' method='post' target='result'
|
||||
<form action='http://mochi.test:8888/chrome/content/html/content/test/forms/submit_invalid_file.sjs' method='post' target='result'
|
||||
enctype='multipart/form-data'>
|
||||
<input type='file' name='file'>
|
||||
</form>
|
||||
|
|
|
@ -60,7 +60,7 @@ SimpleTest.waitForFocus(function() {
|
|||
b2.click();
|
||||
|
||||
// Now, we can launch tests when file picker isn't canceled.
|
||||
MockFilePicker.useAnyFile();
|
||||
MockFilePicker.useBlobFile();
|
||||
MockFilePicker.returnValue = MockFilePicker.returnOK;
|
||||
|
||||
var b = document.getElementById('b');
|
||||
|
|
|
@ -30,7 +30,9 @@ class nsXPCClassInfo;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
class DOMLocalMediaStream;
|
||||
class MediaStream;
|
||||
class MediaEngineSource;
|
||||
|
||||
namespace dom {
|
||||
class AudioNode;
|
||||
|
@ -102,6 +104,8 @@ public:
|
|||
|
||||
virtual void StopTrack(TrackID aTrackID);
|
||||
|
||||
virtual DOMLocalMediaStream* AsDOMLocalMediaStream() { return nullptr; }
|
||||
|
||||
bool IsFinished();
|
||||
/**
|
||||
* Returns a principal indicating who may access this stream. The stream contents
|
||||
|
@ -301,6 +305,8 @@ public:
|
|||
|
||||
virtual void Stop();
|
||||
|
||||
virtual MediaEngineSource* GetMediaEngine(TrackID aTrackID) { return nullptr; }
|
||||
|
||||
/**
|
||||
* Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream.
|
||||
*/
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
#include "mozilla/dom/ImageCaptureErrorEvent.h"
|
||||
#include "mozilla/dom/ImageCaptureErrorEventBinding.h"
|
||||
#include "mozilla/dom/VideoStreamTrack.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "CaptureTask.h"
|
||||
#include "MediaEngine.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -77,6 +79,69 @@ ImageCapture::GetVideoStreamTrack() const
|
|||
return mVideoStreamTrack;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ImageCapture::TakePhotoByMediaEngine()
|
||||
{
|
||||
// Callback for TakPhoto(), it also monitor the principal. If principal
|
||||
// changes, it returns PHOTO_ERROR with security error.
|
||||
class TakePhotoCallback : public MediaEngineSource::PhotoCallback,
|
||||
public DOMMediaStream::PrincipalChangeObserver
|
||||
{
|
||||
public:
|
||||
TakePhotoCallback(DOMMediaStream* aStream, ImageCapture* aImageCapture)
|
||||
: mStream(aStream)
|
||||
, mImageCapture(aImageCapture)
|
||||
, mPrincipalChanged(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mStream->AddPrincipalChangeObserver(this);
|
||||
}
|
||||
|
||||
void PrincipalChanged(DOMMediaStream* aMediaStream) MOZ_OVERRIDE
|
||||
{
|
||||
mPrincipalChanged = true;
|
||||
}
|
||||
|
||||
nsresult PhotoComplete(already_AddRefed<DOMFile> aBlob) MOZ_OVERRIDE
|
||||
{
|
||||
nsRefPtr<DOMFile> blob = aBlob;
|
||||
|
||||
if (mPrincipalChanged) {
|
||||
return PhotoError(NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
return mImageCapture->PostBlobEvent(blob);
|
||||
}
|
||||
|
||||
nsresult PhotoError(nsresult aRv) MOZ_OVERRIDE
|
||||
{
|
||||
return mImageCapture->PostErrorEvent(ImageCaptureError::PHOTO_ERROR, aRv);
|
||||
}
|
||||
|
||||
protected:
|
||||
~TakePhotoCallback()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mStream->RemovePrincipalChangeObserver(this);
|
||||
}
|
||||
|
||||
nsRefPtr<DOMMediaStream> mStream;
|
||||
nsRefPtr<ImageCapture> mImageCapture;
|
||||
bool mPrincipalChanged;
|
||||
};
|
||||
|
||||
nsRefPtr<DOMMediaStream> domStream = mVideoStreamTrack->GetStream();
|
||||
DOMLocalMediaStream* domLocalStream = domStream->AsDOMLocalMediaStream();
|
||||
if (domLocalStream) {
|
||||
nsRefPtr<MediaEngineSource> mediaEngine =
|
||||
domLocalStream->GetMediaEngine(mVideoStreamTrack->GetTrackID());
|
||||
nsRefPtr<MediaEngineSource::PhotoCallback> callback =
|
||||
new TakePhotoCallback(domStream, this);
|
||||
return mediaEngine->TakePhoto(callback);
|
||||
}
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void
|
||||
ImageCapture::TakePhoto(ErrorResult& aResult)
|
||||
{
|
||||
|
@ -90,12 +155,20 @@ ImageCapture::TakePhoto(ErrorResult& aResult)
|
|||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<CaptureTask> task =
|
||||
new CaptureTask(this, mVideoStreamTrack->GetTrackID());
|
||||
// Try if MediaEngine supports taking photo.
|
||||
nsresult rv = TakePhotoByMediaEngine();
|
||||
|
||||
// It adds itself into MediaStreamGraph, so ImageCapture doesn't need to hold the
|
||||
// reference.
|
||||
task->AttachStream();
|
||||
// It falls back to MediaStreamGraph image capture if MediaEngine doesn't
|
||||
// support TakePhoto().
|
||||
if (rv == NS_ERROR_NOT_IMPLEMENTED) {
|
||||
IC_LOG("MediaEngine doesn't support TakePhoto(), it falls back to MediaStreamGraph.");
|
||||
nsRefPtr<CaptureTask> task =
|
||||
new CaptureTask(this, mVideoStreamTrack->GetTrackID());
|
||||
|
||||
// It adds itself into MediaStreamGraph, so ImageCapture doesn't need to hold
|
||||
// the reference.
|
||||
task->AttachStream();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -41,6 +41,11 @@ class VideoStreamTrack;
|
|||
* be sent back as a JPG format via Blob event.
|
||||
*
|
||||
* All the functions in ImageCapture are run in main thread.
|
||||
*
|
||||
* There are two ways to capture image, MediaEngineSource and MediaStreamGraph.
|
||||
* When the implementation of MediaEngineSource supports TakePhoto() in platform
|
||||
* like B2G, it uses the platform camera to grab image. Otherwise, it falls back
|
||||
* to the MediaStreamGraph way.
|
||||
*/
|
||||
|
||||
class ImageCapture MOZ_FINAL : public DOMEventTargetHelper
|
||||
|
@ -86,6 +91,10 @@ public:
|
|||
protected:
|
||||
virtual ~ImageCapture();
|
||||
|
||||
// Capture image by MediaEngine. If it's not support taking photo, this function
|
||||
// should return NS_ERROR_NOT_IMPLEMENTED.
|
||||
nsresult TakePhotoByMediaEngine();
|
||||
|
||||
nsRefPtr<VideoStreamTrack> mVideoStreamTrack;
|
||||
};
|
||||
|
||||
|
|
|
@ -173,17 +173,8 @@ MediaSourceDecoder::SetMediaSourceDuration(double aDuration)
|
|||
}
|
||||
|
||||
void
|
||||
MediaSourceDecoder::WaitForData()
|
||||
MediaSourceDecoder::NotifyTimeRangesChanged()
|
||||
{
|
||||
MSE_DEBUG("MediaSourceDecoder(%p)::WaitForData()", this);
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
mon.Wait();
|
||||
}
|
||||
|
||||
void
|
||||
MediaSourceDecoder::NotifyGotData()
|
||||
{
|
||||
MSE_DEBUG("MediaSourceDecoder(%p)::NotifyGotData()", this);
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
mon.NotifyAll();
|
||||
}
|
||||
|
|
|
@ -55,11 +55,9 @@ public:
|
|||
|
||||
void SetMediaSourceDuration(double aDuration);
|
||||
|
||||
// Provide a mechanism for MediaSourceReader to block waiting on data from a SourceBuffer.
|
||||
void WaitForData();
|
||||
|
||||
// Called whenever a SourceBuffer has new data appended.
|
||||
void NotifyGotData();
|
||||
// Called whenever a TrackBuffer has new data appended or a new decoder
|
||||
// initializes. Safe to call from any thread.
|
||||
void NotifyTimeRangesChanged();
|
||||
|
||||
// Indicates the point in time at which the reader should consider
|
||||
// registered TrackBuffers essential for initialization.
|
||||
|
|
|
@ -84,16 +84,15 @@ MediaSourceReader::RequestAudioData()
|
|||
GetCallback()->OnDecodeError();
|
||||
return;
|
||||
}
|
||||
if (SwitchAudioReader(double(mLastAudioTime) / USECS_PER_S)) {
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::RequestAudioData switching audio reader", this);
|
||||
}
|
||||
mAudioIsSeeking = false;
|
||||
SwitchAudioReader(double(mLastAudioTime) / USECS_PER_S);
|
||||
mAudioReader->RequestAudioData();
|
||||
}
|
||||
|
||||
void
|
||||
MediaSourceReader::OnAudioDecoded(AudioData* aSample)
|
||||
{
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::OnAudioDecoded mTime=%lld mDuration=%lld d=%d",
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::OnAudioDecoded [mTime=%lld mDuration=%lld mDiscontinuity=%d]",
|
||||
this, aSample->mTime, aSample->mDuration, aSample->mDiscontinuity);
|
||||
if (mDropAudioBeforeThreshold) {
|
||||
if (aSample->mTime < mTimeThreshold) {
|
||||
|
@ -106,14 +105,12 @@ MediaSourceReader::OnAudioDecoded(AudioData* aSample)
|
|||
mDropAudioBeforeThreshold = false;
|
||||
}
|
||||
|
||||
// If we are seeking we need to make sure the first sample decoded after
|
||||
// that seek has the mDiscontinuity field set to ensure the media decoder
|
||||
// state machine picks up that the seek is complete.
|
||||
if (mAudioIsSeeking) {
|
||||
mAudioIsSeeking = false;
|
||||
aSample->mDiscontinuity = true;
|
||||
// Any OnAudioDecoded callbacks received while mAudioIsSeeking must be not
|
||||
// update our last used timestamp, as these are emitted by the reader we're
|
||||
// switching away from.
|
||||
if (!mAudioIsSeeking) {
|
||||
mLastAudioTime = aSample->mTime + aSample->mDuration;
|
||||
}
|
||||
mLastAudioTime = aSample->mTime + aSample->mDuration;
|
||||
GetCallback()->OnAudioDecoded(aSample);
|
||||
}
|
||||
|
||||
|
@ -148,16 +145,15 @@ MediaSourceReader::RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThres
|
|||
mDropAudioBeforeThreshold = true;
|
||||
mDropVideoBeforeThreshold = true;
|
||||
}
|
||||
if (SwitchVideoReader(double(mLastVideoTime) / USECS_PER_S)) {
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::RequestVideoData switching video reader", this);
|
||||
}
|
||||
mVideoIsSeeking = false;
|
||||
SwitchVideoReader(double(mLastVideoTime) / USECS_PER_S);
|
||||
mVideoReader->RequestVideoData(aSkipToNextKeyframe, aTimeThreshold);
|
||||
}
|
||||
|
||||
void
|
||||
MediaSourceReader::OnVideoDecoded(VideoData* aSample)
|
||||
{
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::OnVideoDecoded mTime=%lld mDuration=%lld d=%d",
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::OnVideoDecoded [mTime=%lld mDuration=%lld mDiscontinuity=%d]",
|
||||
this, aSample->mTime, aSample->mDuration, aSample->mDiscontinuity);
|
||||
if (mDropVideoBeforeThreshold) {
|
||||
if (aSample->mTime < mTimeThreshold) {
|
||||
|
@ -170,14 +166,12 @@ MediaSourceReader::OnVideoDecoded(VideoData* aSample)
|
|||
mDropVideoBeforeThreshold = false;
|
||||
}
|
||||
|
||||
// If we are seeking we need to make sure the first sample decoded after
|
||||
// that seek has the mDiscontinuity field set to ensure the media decoder
|
||||
// state machine picks up that the seek is complete.
|
||||
if (mVideoIsSeeking) {
|
||||
mVideoIsSeeking = false;
|
||||
aSample->mDiscontinuity = true;
|
||||
// Any OnVideoDecoded callbacks received while mVideoIsSeeking must be not
|
||||
// update our last used timestamp, as these are emitted by the reader we're
|
||||
// switching away from.
|
||||
if (!mVideoIsSeeking) {
|
||||
mLastVideoTime = aSample->mTime + aSample->mDuration;
|
||||
}
|
||||
mLastVideoTime = aSample->mTime + aSample->mDuration;
|
||||
GetCallback()->OnVideoDecoded(aSample);
|
||||
}
|
||||
|
||||
|
@ -234,45 +228,90 @@ MediaSourceReader::BreakCycles()
|
|||
}
|
||||
|
||||
bool
|
||||
MediaSourceReader::SwitchAudioReader(double aTarget)
|
||||
MediaSourceReader::CanSelectAudioReader(MediaDecoderReader* aNewReader)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
// XXX: Can't handle adding an audio track after ReadMetadata yet.
|
||||
if (!mAudioTrack) {
|
||||
AudioInfo currentInfo = mAudioReader->GetMediaInfo().mAudio;
|
||||
AudioInfo newInfo = aNewReader->GetMediaInfo().mAudio;
|
||||
|
||||
// TODO: We can't handle switching audio formats yet.
|
||||
if (currentInfo.mRate != newInfo.mRate ||
|
||||
currentInfo.mChannels != newInfo.mChannels) {
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::CanSelectAudioReader(%p) skip reader due to format mismatch",
|
||||
this, aNewReader);
|
||||
return false;
|
||||
}
|
||||
auto& decoders = mAudioTrack->Decoders();
|
||||
for (uint32_t i = 0; i < decoders.Length(); ++i) {
|
||||
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
|
||||
decoders[i]->GetBuffered(ranges);
|
||||
|
||||
MediaDecoderReader* newReader = decoders[i]->GetReader();
|
||||
MSE_DEBUGV("MediaDecoderReader(%p)::SwitchAudioReader(%f) audioReader=%p reader=%p ranges=%s",
|
||||
this, aTarget, mAudioReader.get(), newReader, DumpTimeRanges(ranges).get());
|
||||
if (aNewReader->AudioQueue().AtEndOfStream()) {
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::CanSelectAudioReader(%p) skip reader due to queue EOS",
|
||||
this, aNewReader);
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioInfo targetInfo = newReader->GetMediaInfo().mAudio;
|
||||
AudioInfo currentInfo = mAudioReader->GetMediaInfo().mAudio;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: We can't handle switching audio formats yet.
|
||||
if (currentInfo.mRate != targetInfo.mRate ||
|
||||
currentInfo.mChannels != targetInfo.mChannels) {
|
||||
bool
|
||||
MediaSourceReader::CanSelectVideoReader(MediaDecoderReader* aNewReader)
|
||||
{
|
||||
if (aNewReader->VideoQueue().AtEndOfStream()) {
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::CanSelectVideoReader(%p) skip reader due to queue EOS",
|
||||
this, aNewReader);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<MediaDecoderReader>
|
||||
MediaSourceReader::SelectReader(double aTarget,
|
||||
bool (MediaSourceReader::*aCanSelectReader)(MediaDecoderReader*),
|
||||
const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders)
|
||||
{
|
||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
|
||||
// Consider decoders in order of newest to oldest, as a newer decoder
|
||||
// providing a given buffered range is expected to replace an older one.
|
||||
for (int32_t i = aTrackDecoders.Length() - 1; i >= 0; --i) {
|
||||
nsRefPtr<MediaDecoderReader> newReader = aTrackDecoders[i]->GetReader();
|
||||
|
||||
// Check the track-type-specific aspects first, as it's assumed these
|
||||
// are cheaper than a buffered range comparison, which seems worthwhile
|
||||
// to avoid on any reader we'd subsequently reject.
|
||||
if (!(this->*aCanSelectReader)(newReader)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ranges->Find(aTarget) != dom::TimeRanges::NoIndex) {
|
||||
if (newReader->AudioQueue().AtEndOfStream()) {
|
||||
continue;
|
||||
}
|
||||
if (mAudioReader) {
|
||||
mAudioReader->SetIdle();
|
||||
}
|
||||
mAudioReader = newReader;
|
||||
MSE_DEBUG("MediaDecoderReader(%p)::SwitchAudioReader(%f) switching to audio reader %p",
|
||||
this, aTarget, mAudioReader.get());
|
||||
return true;
|
||||
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
|
||||
aTrackDecoders[i]->GetBuffered(ranges);
|
||||
if (ranges->Find(aTarget) == dom::TimeRanges::NoIndex) {
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::SelectReader(%f) newReader=%p target not in ranges=%s",
|
||||
this, aTarget, newReader.get(), DumpTimeRanges(ranges).get());
|
||||
continue;
|
||||
}
|
||||
|
||||
return newReader.forget();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
MediaSourceReader::SwitchAudioReader(double aTarget)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
// XXX: Can't handle adding an audio track after ReadMetadata.
|
||||
if (!mAudioTrack) {
|
||||
return false;
|
||||
}
|
||||
nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget,
|
||||
&MediaSourceReader::CanSelectAudioReader,
|
||||
mAudioTrack->Decoders());
|
||||
if (newReader && newReader != mAudioReader) {
|
||||
mAudioReader->SetIdle();
|
||||
mAudioReader = newReader;
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::SwitchAudioReader switched reader to %p", this, mAudioReader.get());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -280,33 +319,19 @@ bool
|
|||
MediaSourceReader::SwitchVideoReader(double aTarget)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
// XXX: Can't handle adding a video track after ReadMetadata yet.
|
||||
// XXX: Can't handle adding a video track after ReadMetadata.
|
||||
if (!mVideoTrack) {
|
||||
return false;
|
||||
}
|
||||
auto& decoders = mVideoTrack->Decoders();
|
||||
for (uint32_t i = 0; i < decoders.Length(); ++i) {
|
||||
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
|
||||
decoders[i]->GetBuffered(ranges);
|
||||
|
||||
MediaDecoderReader* newReader = decoders[i]->GetReader();
|
||||
MSE_DEBUGV("MediaDecoderReader(%p)::SwitchVideoReader(%f) videoReader=%p reader=%p ranges=%s",
|
||||
this, aTarget, mVideoReader.get(), newReader, DumpTimeRanges(ranges).get());
|
||||
|
||||
if (ranges->Find(aTarget) != dom::TimeRanges::NoIndex) {
|
||||
if (newReader->VideoQueue().AtEndOfStream()) {
|
||||
continue;
|
||||
}
|
||||
if (mVideoReader) {
|
||||
mVideoReader->SetIdle();
|
||||
}
|
||||
mVideoReader = newReader;
|
||||
MSE_DEBUG("MediaDecoderReader(%p)::SwitchVideoReader(%f) switching to video reader %p",
|
||||
this, aTarget, mVideoReader.get());
|
||||
return true;
|
||||
}
|
||||
nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget,
|
||||
&MediaSourceReader::CanSelectVideoReader,
|
||||
mVideoTrack->Decoders());
|
||||
if (newReader && newReader != mVideoReader) {
|
||||
mVideoReader->SetIdle();
|
||||
mVideoReader = newReader;
|
||||
MSE_DEBUGV("MediaSourceReader(%p)::SwitchVideoReader switched reader to %p", this, mVideoReader.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -413,6 +438,21 @@ private:
|
|||
nsRefPtr<AbstractMediaDecoder> mDecoder;
|
||||
};
|
||||
|
||||
void
|
||||
MediaSourceReader::WaitForTimeRange(double aTime)
|
||||
{
|
||||
MSE_DEBUG("MediaSourceReader(%p)::WaitForTimeRange(%f)", this, aTime);
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
|
||||
// Loop until we have the requested time range in the active TrackBuffers.
|
||||
// Ideally, this wait loop would use an async request and callback
|
||||
// instead. Bug 1056441 covers that change.
|
||||
while (!TrackBuffersContainTime(aTime) && !IsShutdown() && !IsEnded()) {
|
||||
MSE_DEBUG("MediaSourceReader(%p)::WaitForTimeRange(%f) waiting", this, aTime);
|
||||
mon.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MediaSourceReader::TrackBuffersContainTime(double aTime)
|
||||
{
|
||||
|
@ -448,14 +488,7 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
|
|||
NS_DispatchToMainThread(new ChangeToHaveMetadata(mDecoder));
|
||||
}
|
||||
|
||||
// Loop until we have the requested time range in the source buffers.
|
||||
// This is a workaround for our lack of async functionality in the
|
||||
// MediaDecoderStateMachine. Bug 979104 implements what we need and
|
||||
// we'll remove this for an async approach based on that in bug 1056441.
|
||||
while (!TrackBuffersContainTime(target) && !IsShutdown() && !IsEnded()) {
|
||||
MSE_DEBUG("MediaSourceReader(%p)::Seek waiting for target=%f", this, target);
|
||||
static_cast<MediaSourceDecoder*>(mDecoder)->WaitForData();
|
||||
}
|
||||
WaitForTimeRange(target);
|
||||
|
||||
if (IsShutdown()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -463,8 +496,8 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
|
|||
|
||||
if (mAudioTrack) {
|
||||
mAudioIsSeeking = true;
|
||||
DebugOnly<bool> ok = SwitchAudioReader(target);
|
||||
MOZ_ASSERT(ok && static_cast<SourceBufferDecoder*>(mAudioReader->GetDecoder())->ContainsTime(target));
|
||||
SwitchAudioReader(target);
|
||||
MOZ_ASSERT(static_cast<SourceBufferDecoder*>(mAudioReader->GetDecoder())->ContainsTime(target));
|
||||
nsresult rv = mAudioReader->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
|
||||
MSE_DEBUG("MediaSourceReader(%p)::Seek audio reader=%p rv=%x", this, mAudioReader.get(), rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -473,8 +506,8 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
|
|||
}
|
||||
if (mVideoTrack) {
|
||||
mVideoIsSeeking = true;
|
||||
DebugOnly<bool> ok = SwitchVideoReader(target);
|
||||
MOZ_ASSERT(ok && static_cast<SourceBufferDecoder*>(mVideoReader->GetDecoder())->ContainsTime(target));
|
||||
SwitchVideoReader(target);
|
||||
MOZ_ASSERT(static_cast<SourceBufferDecoder*>(mVideoReader->GetDecoder())->ContainsTime(target));
|
||||
nsresult rv = mVideoReader->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
|
||||
MSE_DEBUG("MediaSourceReader(%p)::Seek video reader=%p rv=%x", this, mVideoReader.get(), rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
|
@ -105,6 +105,27 @@ private:
|
|||
bool SwitchAudioReader(double aTarget);
|
||||
bool SwitchVideoReader(double aTarget);
|
||||
|
||||
// Return a reader from the set available in aTrackDecoders that is considered
|
||||
// usable by the aCanUserReader callback and has data available in the range
|
||||
// requested by aTarget.
|
||||
// aCanSelectReader is passed each reader available in aTrackDecoders and is
|
||||
// expected to return true if the reader is considerable selectable.
|
||||
already_AddRefed<MediaDecoderReader> SelectReader(double aTarget,
|
||||
bool (MediaSourceReader::*aCanSelectReader)(MediaDecoderReader*),
|
||||
const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders);
|
||||
|
||||
// Passed to SelectReader to enforce any track format specific requirements.
|
||||
// In the case of CanSelectAudioReader, verifies that aNewReader has a
|
||||
// matching audio format to the existing reader, as format switching is not
|
||||
// yet supported.
|
||||
bool CanSelectAudioReader(MediaDecoderReader* aNewReader);
|
||||
bool CanSelectVideoReader(MediaDecoderReader* aNewReader);
|
||||
|
||||
// Waits on the decoder monitor for aTime to become available in the active
|
||||
// TrackBuffers. Used to block a Seek call until the necessary data has been
|
||||
// provided to the relevant SourceBuffers.
|
||||
void WaitForTimeRange(double aTime);
|
||||
|
||||
nsRefPtr<MediaDecoderReader> mAudioReader;
|
||||
nsRefPtr<MediaDecoderReader> mVideoReader;
|
||||
|
||||
|
|
|
@ -440,8 +440,13 @@ SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
|
|||
return;
|
||||
}
|
||||
StartUpdating();
|
||||
/// TODO: Run coded frame removal algorithm asynchronously (would call StopUpdating()).
|
||||
StopUpdating();
|
||||
/// TODO: Run coded frame removal algorithm.
|
||||
|
||||
// Run the final step of the coded frame removal algorithm asynchronously
|
||||
// to ensure the SourceBuffer's updating flag transition behaves as
|
||||
// required by the spec.
|
||||
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating);
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -561,7 +566,7 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
|
|||
// TODO: Run coded frame eviction algorithm.
|
||||
// TODO: Test buffer full flag.
|
||||
StartUpdating();
|
||||
// TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
|
||||
// TODO: Run more of the buffer append algorithm asynchronously.
|
||||
if (mParser->IsInitSegmentPresent(aData, aLength)) {
|
||||
MSE_DEBUG("SourceBuffer(%p)::AppendData: New initialization segment.", this);
|
||||
mMediaSource->QueueInitializationEvent();
|
||||
|
@ -632,13 +637,16 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
|
|||
// the current start point.
|
||||
mMediaSource->NotifyEvicted(0.0, GetBufferedStart());
|
||||
}
|
||||
StopUpdating();
|
||||
|
||||
// Run the final step of the buffer append algorithm asynchronously to
|
||||
// ensure the SourceBuffer's updating flag transition behaves as required
|
||||
// by the spec.
|
||||
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating);
|
||||
NS_DispatchToMainThread(event);
|
||||
|
||||
// Schedule the state machine thread to ensure playback starts
|
||||
// if required when data is appended.
|
||||
mMediaSource->GetDecoder()->ScheduleStateMachineThread();
|
||||
|
||||
mMediaSource->GetDecoder()->NotifyGotData();
|
||||
}
|
||||
|
||||
double
|
||||
|
|
|
@ -106,10 +106,13 @@ TrackBuffer::AppendData(const uint8_t* aData, uint32_t aLength)
|
|||
}
|
||||
|
||||
SourceBufferResource* resource = mCurrentDecoder->GetResource();
|
||||
int64_t appendOffset = resource->GetLength();
|
||||
resource->AppendData(aData, aLength);
|
||||
// XXX: For future reference: NDA call must run on the main thread.
|
||||
mCurrentDecoder->NotifyDataArrived(reinterpret_cast<const char*>(aData),
|
||||
aLength, resource->GetLength());
|
||||
resource->AppendData(aData, aLength);
|
||||
aLength, appendOffset);
|
||||
mParentDecoder->NotifyTimeRangesChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -245,6 +248,7 @@ TrackBuffer::RegisterDecoder(nsRefPtr<SourceBufferDecoder> aDecoder)
|
|||
MSE_DEBUG("TrackBuffer(%p)::RegisterDecoder with mismatched audio/video tracks", this);
|
||||
}
|
||||
mInitializedDecoders.AppendElement(aDecoder);
|
||||
mParentDecoder->NotifyTimeRangesChanged();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -9,9 +9,7 @@ function fetchWithXHR(uri, onLoadFunction) {
|
|||
xhr.open("GET", uri, true);
|
||||
xhr.responseType = "blob";
|
||||
xhr.addEventListener("load", function (e) {
|
||||
if (xhr.status != 200) {
|
||||
return;
|
||||
}
|
||||
is(xhr.status, 200, "fetchWithXHR load uri='" + uri + "' status=" + xhr.status);
|
||||
var rdr = new FileReader();
|
||||
rdr.addEventListener("load", function (e) {
|
||||
onLoadFunction(e.target.result);
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
[DEFAULT]
|
||||
skip-if = e10s
|
||||
support-files = mediasource.js seek.webm seek.webm^headers^
|
||||
|
||||
[test_MediaSource.html]
|
||||
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
|
||||
|
||||
[test_SplitAppend.html]
|
||||
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
|
||||
|
||||
[test_SplitAppendDelay.html]
|
||||
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
|
||||
skip-if = e10s || buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
|
||||
support-files =
|
||||
mediasource.js
|
||||
seek.webm seek.webm^headers^
|
||||
seek_lowres.webm seek_lowres.webm^headers^
|
||||
|
||||
[test_BufferedSeek.html]
|
||||
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
|
||||
[test_FrameSelection.html]
|
||||
[test_MediaSource.html]
|
||||
[test_SplitAppendDelay.html]
|
||||
[test_SplitAppend.html]
|
||||
|
||||
|
|
Двоичный файл не отображается.
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -25,7 +25,9 @@ runWithMSE(function () {
|
|||
|
||||
fetchWithXHR("seek.webm", function (arrayBuffer) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer));
|
||||
ms.endOfStream();
|
||||
sb.addEventListener("updateend", function () {
|
||||
ms.endOfStream()
|
||||
});
|
||||
});
|
||||
|
||||
var target = 2;
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>MSE: verify correct frames selected for given position</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="mediasource.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
runWithMSE(function () {
|
||||
var ms = new MediaSource();
|
||||
|
||||
var v = document.createElement("video");
|
||||
v.preload = "auto";
|
||||
v.src = URL.createObjectURL(ms);
|
||||
document.body.appendChild(v);
|
||||
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
var sb = ms.addSourceBuffer("video/webm");
|
||||
|
||||
fetchWithXHR("seek.webm", function (arrayBuffer) {
|
||||
// Append entire file covering range [0, 4].
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer));
|
||||
});
|
||||
|
||||
var targets = [{ currentTime: 3, videoWidth: 160, videoHeight: 120 },
|
||||
{ currentTime: 2, videoWidth: 160, videoHeight: 120 },
|
||||
{ currentTime: 0, videoWidth: 320, videoHeight: 240 }];
|
||||
var target;
|
||||
|
||||
v.addEventListener("loadedmetadata", function () {
|
||||
is(v.currentTime, 0, "currentTime has incorrect initial value");
|
||||
is(v.videoWidth, 320, "videoWidth has incorrect initial value");
|
||||
is(v.videoHeight, 240, "videoHeight has incorrect initial value");
|
||||
|
||||
fetchWithXHR("seek_lowres.webm", function (arrayBuffer) {
|
||||
// Append initialization segment.
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 438));
|
||||
var first = true;
|
||||
sb.addEventListener("updateend", function () {
|
||||
if (first) {
|
||||
// Append media segment covering range [2, 4].
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 51003));
|
||||
first = false;
|
||||
} else {
|
||||
ms.endOfStream();
|
||||
}
|
||||
});
|
||||
target = targets.shift();
|
||||
v.currentTime = target.currentTime;
|
||||
});
|
||||
});
|
||||
|
||||
v.addEventListener("seeked", function () {
|
||||
is(v.currentTime, target.currentTime, "Video currentTime not at target");
|
||||
|
||||
is(v.videoWidth, target.videoWidth, "videoWidth has incorrect final value");
|
||||
is(v.videoHeight, target.videoHeight, "videoHeight has incorrect final value");
|
||||
|
||||
target = targets.shift();
|
||||
if (target) {
|
||||
v.currentTime = target.currentTime;
|
||||
} else {
|
||||
v.parentNode.removeChild(v);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -52,7 +52,16 @@ runWithMSE(function () {
|
|||
|
||||
fetchWithXHR("seek.webm", function (arrayBuffer) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer));
|
||||
is(sb.updating, true, "SourceBuffer.updating is expected value after appendBuffer");
|
||||
});
|
||||
|
||||
sb.addEventListener("update", function () {
|
||||
is(sb.updating, false, "SourceBuffer.updating is expected value in update event");
|
||||
ms.endOfStream();
|
||||
});
|
||||
|
||||
sb.addEventListener("updateend", function () {
|
||||
is(sb.updating, false, "SourceBuffer.updating is expected value in updateend event");
|
||||
v.play();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -25,8 +25,15 @@ runWithMSE(function () {
|
|||
|
||||
fetchWithXHR("seek.webm", function (arrayBuffer) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
|
||||
ms.endOfStream();
|
||||
var first = true;
|
||||
sb.addEventListener("updateend", function () {
|
||||
if (first) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
|
||||
first = false;
|
||||
} else {
|
||||
ms.endOfStream();
|
||||
}
|
||||
});
|
||||
v.play();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -25,10 +25,17 @@ runWithMSE(function () {
|
|||
|
||||
fetchWithXHR("seek.webm", function (arrayBuffer) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
|
||||
window.setTimeout(function () {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
|
||||
ms.endOfStream();
|
||||
}, 1000);
|
||||
var first = true;
|
||||
sb.addEventListener("updateend", function () {
|
||||
if (first) {
|
||||
window.setTimeout(function () {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
|
||||
first = false;
|
||||
}, 1000);
|
||||
} else {
|
||||
ms.endOfStream();
|
||||
}
|
||||
});
|
||||
v.play();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,9 +10,14 @@
|
|||
#include "DOMMediaStream.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "mozilla/dom/VideoStreamTrack.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class DOMFile;
|
||||
}
|
||||
|
||||
struct VideoTrackConstraintsN;
|
||||
struct AudioTrackConstraintsN;
|
||||
|
||||
|
@ -137,6 +142,29 @@ public:
|
|||
/* Returns the type of media source (camera, microphone, screen, window, etc) */
|
||||
virtual const MediaSourceType GetMediaSource() = 0;
|
||||
|
||||
// Callback interface for TakePhoto(). Either PhotoComplete() or PhotoError()
|
||||
// should be called.
|
||||
class PhotoCallback {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PhotoCallback)
|
||||
|
||||
// aBlob is the image captured by MediaEngineSource. It is
|
||||
// called on main thread.
|
||||
virtual nsresult PhotoComplete(already_AddRefed<dom::DOMFile> aBlob) = 0;
|
||||
|
||||
// It is called on main thread. aRv is the error code.
|
||||
virtual nsresult PhotoError(nsresult aRv) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~PhotoCallback() {}
|
||||
};
|
||||
|
||||
/* If implementation of MediaEngineSource supports TakePhoto(), the picture
|
||||
* should be return via aCallback object. Otherwise, it returns NS_ERROR_NOT_IMPLEMENTED.
|
||||
* Currently, only Gonk MediaEngineSource implementation supports it.
|
||||
*/
|
||||
virtual nsresult TakePhoto(PhotoCallback* aCallback) = 0;
|
||||
|
||||
/* Return false if device is currently allocated or started */
|
||||
bool IsAvailable() {
|
||||
if (mState == kAllocated || mState == kStarted) {
|
||||
|
|
|
@ -65,6 +65,11 @@ public:
|
|||
return MediaSourceType::Camera;
|
||||
}
|
||||
|
||||
virtual nsresult TakePhoto(PhotoCallback* aCallback)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
|
@ -125,6 +130,11 @@ public:
|
|||
return MediaSourceType::Microphone;
|
||||
}
|
||||
|
||||
virtual nsresult TakePhoto(PhotoCallback* aCallback)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
|
|
|
@ -34,6 +34,11 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList
|
|||
return MediaSourceType::Browser;
|
||||
}
|
||||
|
||||
virtual nsresult TakePhoto(PhotoCallback* aCallback)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void Draw();
|
||||
|
||||
class StartRunnable : public nsRunnable {
|
||||
|
|
|
@ -80,7 +80,7 @@ class GetCameraNameRunnable;
|
|||
* MainThread:
|
||||
* mCaptureIndex, mLastCapture, mState, mWidth, mHeight,
|
||||
*
|
||||
* Where mWidth, mHeight, mImage are protected by mMonitor
|
||||
* Where mWidth, mHeight, mImage, mPhotoCallbacks are protected by mMonitor
|
||||
* mState is protected by mCallbackMonitor
|
||||
* Other variable is accessed only from single thread
|
||||
*/
|
||||
|
@ -175,6 +175,11 @@ public:
|
|||
|
||||
#ifndef MOZ_B2G_CAMERA
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
nsresult TakePhoto(PhotoCallback* aCallback)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#else
|
||||
// We are subclassed from CameraControlListener, which implements a
|
||||
// threadsafe reference-count for us.
|
||||
|
@ -193,6 +198,9 @@ public:
|
|||
void SnapshotImpl();
|
||||
void RotateImage(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight);
|
||||
void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration);
|
||||
|
||||
nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE;
|
||||
|
||||
#endif
|
||||
|
||||
// This runnable is for creating a temporary file on the main thread.
|
||||
|
@ -230,6 +238,7 @@ private:
|
|||
// This is only modified on MainThread (AllocImpl and DeallocImpl)
|
||||
nsRefPtr<ICameraControl> mCameraControl;
|
||||
nsCOMPtr<nsIDOMFile> mLastCapture;
|
||||
nsTArray<nsRefPtr<PhotoCallback>> mPhotoCallbacks;
|
||||
|
||||
// These are protected by mMonitor below
|
||||
int mRotation;
|
||||
|
@ -330,6 +339,11 @@ public:
|
|||
return MediaSourceType::Microphone;
|
||||
}
|
||||
|
||||
virtual nsresult TakePhoto(PhotoCallback* aCallback)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// VoEMediaProcess.
|
||||
void Process(int channel, webrtc::ProcessingTypes type,
|
||||
int16_t audio10ms[], int length,
|
||||
|
|
|
@ -877,18 +877,95 @@ MediaEngineWebRTCVideoSource::GetRotation()
|
|||
void
|
||||
MediaEngineWebRTCVideoSource::OnUserError(UserContext aContext, nsresult aError)
|
||||
{
|
||||
ReentrantMonitorAutoEnter sync(mCallbackMonitor);
|
||||
mCallbackMonitor.Notify();
|
||||
{
|
||||
// Scope the monitor, since there is another monitor below and we don't want
|
||||
// unexpected deadlock.
|
||||
ReentrantMonitorAutoEnter sync(mCallbackMonitor);
|
||||
mCallbackMonitor.Notify();
|
||||
}
|
||||
|
||||
// A main thread runnable to send error code to all queued PhotoCallbacks.
|
||||
class TakePhotoError : public nsRunnable {
|
||||
public:
|
||||
TakePhotoError(nsTArray<nsRefPtr<PhotoCallback>>& aCallbacks,
|
||||
nsresult aRv)
|
||||
: mRv(aRv)
|
||||
{
|
||||
mCallbacks.SwapElements(aCallbacks);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
uint32_t callbackNumbers = mCallbacks.Length();
|
||||
for (uint8_t i = 0; i < callbackNumbers; i++) {
|
||||
mCallbacks[i]->PhotoError(mRv);
|
||||
}
|
||||
// PhotoCallback needs to dereference on main thread.
|
||||
mCallbacks.Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsTArray<nsRefPtr<PhotoCallback>> mCallbacks;
|
||||
nsresult mRv;
|
||||
};
|
||||
|
||||
if (aContext == UserContext::kInTakePicture) {
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
if (mPhotoCallbacks.Length()) {
|
||||
NS_DispatchToMainThread(new TakePhotoError(mPhotoCallbacks, aError));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineWebRTCVideoSource::OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType)
|
||||
{
|
||||
ReentrantMonitorAutoEnter sync(mCallbackMonitor);
|
||||
mLastCapture = dom::DOMFile::CreateMemoryFile(static_cast<void*>(aData),
|
||||
static_cast<uint64_t>(aLength),
|
||||
aMimeType);
|
||||
mCallbackMonitor.Notify();
|
||||
// It needs to start preview because Gonk camera will stop preview while
|
||||
// taking picture.
|
||||
mCameraControl->StartPreview();
|
||||
|
||||
// Create a main thread runnable to generate a blob and call all current queued
|
||||
// PhotoCallbacks.
|
||||
class GenerateBlobRunnable : public nsRunnable {
|
||||
public:
|
||||
GenerateBlobRunnable(nsTArray<nsRefPtr<PhotoCallback>>& aCallbacks,
|
||||
uint8_t* aData,
|
||||
uint32_t aLength,
|
||||
const nsAString& aMimeType)
|
||||
{
|
||||
mCallbacks.SwapElements(aCallbacks);
|
||||
mPhoto.AppendElements(aData, aLength);
|
||||
mMimeType = aMimeType;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsRefPtr<dom::DOMFile> blob =
|
||||
dom::DOMFile::CreateMemoryFile(mPhoto.Elements(), mPhoto.Length(), mMimeType);
|
||||
uint32_t callbackCounts = mCallbacks.Length();
|
||||
for (uint8_t i = 0; i < callbackCounts; i++) {
|
||||
nsRefPtr<dom::DOMFile> tempBlob = blob;
|
||||
mCallbacks[i]->PhotoComplete(tempBlob.forget());
|
||||
}
|
||||
// PhotoCallback needs to dereference on main thread.
|
||||
mCallbacks.Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<PhotoCallback>> mCallbacks;
|
||||
nsTArray<uint8_t> mPhoto;
|
||||
nsString mMimeType;
|
||||
};
|
||||
|
||||
// All elements in mPhotoCallbacks will be swapped in GenerateBlobRunnable
|
||||
// constructor. This captured image will be sent to all the queued
|
||||
// PhotoCallbacks in this runnable.
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
if (mPhotoCallbacks.Length()) {
|
||||
NS_DispatchToMainThread(
|
||||
new GenerateBlobRunnable(mPhotoCallbacks, aData, aLength, aMimeType));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -976,6 +1053,28 @@ MediaEngineWebRTCVideoSource::OnNewPreviewFrame(layers::Image* aImage, uint32_t
|
|||
|
||||
return true; // return true because we're accepting the frame
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaEngineWebRTCVideoSource::TakePhoto(PhotoCallback* aCallback)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
// If other callback exists, that means there is a captured picture on the way,
|
||||
// it doesn't need to TakePicture() again.
|
||||
if (!mPhotoCallbacks.Length()) {
|
||||
nsresult rv = mCameraControl->TakePicture();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
mPhotoCallbacks.AppendElement(aCallback);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -455,7 +455,7 @@ protected:
|
|||
* If the current transcluded script is being compiled off thread, the
|
||||
* source for that script.
|
||||
*/
|
||||
jschar* mOffThreadCompileStringBuf;
|
||||
char16_t* mOffThreadCompileStringBuf;
|
||||
size_t mOffThreadCompileStringLength;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1584,8 +1584,8 @@ static const uint32_t sAsmJSCookie = 0x600d600d;
|
|||
|
||||
bool
|
||||
OpenEntryForRead(nsIPrincipal* aPrincipal,
|
||||
const jschar* aBegin,
|
||||
const jschar* aLimit,
|
||||
const char16_t* aBegin,
|
||||
const char16_t* aLimit,
|
||||
size_t* aSize,
|
||||
const uint8_t** aMemory,
|
||||
intptr_t* aFile)
|
||||
|
@ -1643,8 +1643,8 @@ CloseEntryForRead(size_t aSize,
|
|||
bool
|
||||
OpenEntryForWrite(nsIPrincipal* aPrincipal,
|
||||
bool aInstalled,
|
||||
const jschar* aBegin,
|
||||
const jschar* aEnd,
|
||||
const char16_t* aBegin,
|
||||
const char16_t* aEnd,
|
||||
size_t aSize,
|
||||
uint8_t** aMemory,
|
||||
intptr_t* aFile)
|
||||
|
|
|
@ -80,8 +80,8 @@ struct WriteParams
|
|||
// Parameters specific to opening a cache entry for reading
|
||||
struct ReadParams
|
||||
{
|
||||
const jschar* mBegin;
|
||||
const jschar* mLimit;
|
||||
const char16_t* mBegin;
|
||||
const char16_t* mLimit;
|
||||
|
||||
ReadParams()
|
||||
: mBegin(nullptr),
|
||||
|
@ -103,8 +103,8 @@ struct ReadParams
|
|||
|
||||
bool
|
||||
OpenEntryForRead(nsIPrincipal* aPrincipal,
|
||||
const jschar* aBegin,
|
||||
const jschar* aLimit,
|
||||
const char16_t* aBegin,
|
||||
const char16_t* aLimit,
|
||||
size_t* aSize,
|
||||
const uint8_t** aMemory,
|
||||
intptr_t *aHandle);
|
||||
|
@ -115,8 +115,8 @@ CloseEntryForRead(size_t aSize,
|
|||
bool
|
||||
OpenEntryForWrite(nsIPrincipal* aPrincipal,
|
||||
bool aInstalled,
|
||||
const jschar* aBegin,
|
||||
const jschar* aEnd,
|
||||
const char16_t* aBegin,
|
||||
const char16_t* aEnd,
|
||||
size_t aSize,
|
||||
uint8_t** aMemory,
|
||||
intptr_t* aHandle);
|
||||
|
|
|
@ -1366,7 +1366,7 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto)
|
|||
|
||||
// Don't overwrite a property set by content.
|
||||
bool contentDefinedProperty;
|
||||
if (!::JS_AlreadyHasOwnUCProperty(cx, global, reinterpret_cast<const jschar*>(mData->mNameUTF16),
|
||||
if (!::JS_AlreadyHasOwnUCProperty(cx, global, reinterpret_cast<const char16_t*>(mData->mNameUTF16),
|
||||
NS_strlen(mData->mNameUTF16),
|
||||
&contentDefinedProperty)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -97,10 +97,6 @@ using namespace mozilla::dom;
|
|||
|
||||
const size_t gStackSize = 8192;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* gJSDiagnostics;
|
||||
#endif
|
||||
|
||||
// Thank you Microsoft!
|
||||
#ifdef CompareString
|
||||
#undef CompareString
|
||||
|
@ -352,212 +348,102 @@ NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
|
|||
return called;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
AsyncErrorReporter::AsyncErrorReporter(JSRuntime* aRuntime,
|
||||
JSErrorReport* aErrorReport,
|
||||
const char* aFallbackMessage,
|
||||
bool aIsChromeError,
|
||||
nsPIDOMWindow* aWindow)
|
||||
: mSourceLine(static_cast<const char16_t*>(aErrorReport->uclinebuf))
|
||||
, mLineNumber(aErrorReport->lineno)
|
||||
, mColumn(aErrorReport->column)
|
||||
, mFlags(aErrorReport->flags)
|
||||
{
|
||||
if (!aErrorReport->filename) {
|
||||
mFileName.SetIsVoid(true);
|
||||
} else {
|
||||
mFileName.AssignWithConversion(aErrorReport->filename);
|
||||
}
|
||||
|
||||
const char16_t* m = static_cast<const char16_t*>(aErrorReport->ucmessage);
|
||||
if (m) {
|
||||
JSFlatString* name = js::GetErrorTypeName(aRuntime, aErrorReport->exnType);
|
||||
if (name) {
|
||||
AssignJSFlatString(mErrorMsg, name);
|
||||
mErrorMsg.AppendLiteral(": ");
|
||||
}
|
||||
mErrorMsg.Append(m);
|
||||
}
|
||||
|
||||
if (mErrorMsg.IsEmpty() && aFallbackMessage) {
|
||||
mErrorMsg.AssignWithConversion(aFallbackMessage);
|
||||
}
|
||||
|
||||
mCategory = aIsChromeError ? NS_LITERAL_CSTRING("chrome javascript") :
|
||||
NS_LITERAL_CSTRING("content javascript");
|
||||
|
||||
mInnerWindowID = 0;
|
||||
if (aWindow) {
|
||||
MOZ_ASSERT(aWindow->IsInnerWindow());
|
||||
mInnerWindowID = aWindow->WindowID();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AsyncErrorReporter::ReportError()
|
||||
{
|
||||
nsCOMPtr<nsIScriptError> errorObject =
|
||||
do_CreateInstance("@mozilla.org/scripterror;1");
|
||||
if (!errorObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = errorObject->InitWithWindowID(mErrorMsg, mFileName,
|
||||
mSourceLine, mLineNumber,
|
||||
mColumn, mFlags, mCategory,
|
||||
mInnerWindowID);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIConsoleService> consoleService =
|
||||
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
if (!consoleService) {
|
||||
return;
|
||||
}
|
||||
|
||||
consoleService->LogMessage(errorObject);
|
||||
return;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class ScriptErrorEvent : public AsyncErrorReporter
|
||||
class ScriptErrorEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ScriptErrorEvent(JSRuntime* aRuntime,
|
||||
JSErrorReport* aErrorReport,
|
||||
const char* aFallbackMessage,
|
||||
xpc::ErrorReport* aReport,
|
||||
nsIPrincipal* aScriptOriginPrincipal,
|
||||
nsIPrincipal* aGlobalPrincipal,
|
||||
nsPIDOMWindow* aWindow,
|
||||
JS::Handle<JS::Value> aError,
|
||||
bool aDispatchEvent)
|
||||
// Pass an empty category, then compute ours
|
||||
: AsyncErrorReporter(aRuntime, aErrorReport, aFallbackMessage,
|
||||
nsContentUtils::IsSystemPrincipal(aGlobalPrincipal),
|
||||
aWindow)
|
||||
: mReport(aReport)
|
||||
, mOriginPrincipal(aScriptOriginPrincipal)
|
||||
, mDispatchEvent(aDispatchEvent)
|
||||
, mError(aRuntime, aError)
|
||||
, mWindow(aWindow)
|
||||
{
|
||||
MOZ_ASSERT_IF(mWindow, mWindow->IsInnerWindow());
|
||||
}
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsPIDOMWindow* win = mReport->mWindow;
|
||||
MOZ_ASSERT(win);
|
||||
// First, notify the DOM that we have a script error, but only if
|
||||
// our window is still the current inner, if we're associated with a window.
|
||||
if (mDispatchEvent && (!mWindow || mWindow->IsCurrentInnerWindow())) {
|
||||
nsIDocShell* docShell = mWindow ? mWindow->GetDocShell() : nullptr;
|
||||
if (docShell &&
|
||||
!JSREPORT_IS_WARNING(mFlags) &&
|
||||
!sHandlingScriptError) {
|
||||
AutoRestore<bool> recursionGuard(sHandlingScriptError);
|
||||
sHandlingScriptError = true;
|
||||
// our window is still the current inner.
|
||||
if (mDispatchEvent && win->IsCurrentInnerWindow() &&
|
||||
win->GetDocShell() && !JSREPORT_IS_WARNING(mReport->mFlags) &&
|
||||
!sHandlingScriptError)
|
||||
{
|
||||
AutoRestore<bool> recursionGuard(sHandlingScriptError);
|
||||
sHandlingScriptError = true;
|
||||
|
||||
nsRefPtr<nsPresContext> presContext;
|
||||
docShell->GetPresContext(getter_AddRefs(presContext));
|
||||
nsRefPtr<nsPresContext> presContext;
|
||||
win->GetDocShell()->GetPresContext(getter_AddRefs(presContext));
|
||||
|
||||
ThreadsafeAutoJSContext cx;
|
||||
RootedDictionary<ErrorEventInit> init(cx);
|
||||
init.mCancelable = true;
|
||||
init.mFilename = mFileName;
|
||||
init.mBubbles = true;
|
||||
ThreadsafeAutoJSContext cx;
|
||||
RootedDictionary<ErrorEventInit> init(cx);
|
||||
init.mCancelable = true;
|
||||
init.mFilename = mReport->mFileName;
|
||||
init.mBubbles = true;
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(mWindow));
|
||||
NS_ENSURE_STATE(sop);
|
||||
nsIPrincipal* p = sop->GetPrincipal();
|
||||
NS_ENSURE_STATE(p);
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
|
||||
NS_ENSURE_STATE(sop);
|
||||
nsIPrincipal* p = sop->GetPrincipal();
|
||||
NS_ENSURE_STATE(p);
|
||||
|
||||
bool sameOrigin = !mOriginPrincipal;
|
||||
bool sameOrigin = !mOriginPrincipal;
|
||||
|
||||
if (p && !sameOrigin) {
|
||||
if (NS_FAILED(p->Subsumes(mOriginPrincipal, &sameOrigin))) {
|
||||
sameOrigin = false;
|
||||
}
|
||||
if (p && !sameOrigin) {
|
||||
if (NS_FAILED(p->Subsumes(mOriginPrincipal, &sameOrigin))) {
|
||||
sameOrigin = false;
|
||||
}
|
||||
|
||||
NS_NAMED_LITERAL_STRING(xoriginMsg, "Script error.");
|
||||
if (sameOrigin) {
|
||||
init.mMessage = mErrorMsg;
|
||||
init.mLineno = mLineNumber;
|
||||
init.mColno = mColumn;
|
||||
init.mError = mError;
|
||||
} else {
|
||||
NS_WARNING("Not same origin error!");
|
||||
init.mMessage = xoriginMsg;
|
||||
init.mLineno = 0;
|
||||
}
|
||||
|
||||
nsRefPtr<ErrorEvent> event =
|
||||
ErrorEvent::Constructor(static_cast<nsGlobalWindow*>(mWindow.get()),
|
||||
NS_LITERAL_STRING("error"), init);
|
||||
event->SetTrusted(true);
|
||||
|
||||
EventDispatcher::DispatchDOMEvent(mWindow, nullptr, event, presContext,
|
||||
&status);
|
||||
}
|
||||
|
||||
NS_NAMED_LITERAL_STRING(xoriginMsg, "Script error.");
|
||||
if (sameOrigin) {
|
||||
init.mMessage = mReport->mErrorMsg;
|
||||
init.mLineno = mReport->mLineNumber;
|
||||
init.mColno = mReport->mColumn;
|
||||
init.mError = mError;
|
||||
} else {
|
||||
NS_WARNING("Not same origin error!");
|
||||
init.mMessage = xoriginMsg;
|
||||
init.mLineno = 0;
|
||||
}
|
||||
|
||||
nsRefPtr<ErrorEvent> event =
|
||||
ErrorEvent::Constructor(static_cast<nsGlobalWindow*>(win),
|
||||
NS_LITERAL_STRING("error"), init);
|
||||
event->SetTrusted(true);
|
||||
|
||||
EventDispatcher::DispatchDOMEvent(win, nullptr, event, presContext,
|
||||
&status);
|
||||
}
|
||||
|
||||
if (status != nsEventStatus_eConsumeNoDefault) {
|
||||
AsyncErrorReporter::ReportError();
|
||||
mReport->LogToConsole();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<xpc::ErrorReport> mReport;
|
||||
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
|
||||
bool mDispatchEvent;
|
||||
JS::PersistentRootedValue mError;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
static bool sHandlingScriptError;
|
||||
};
|
||||
|
||||
bool ScriptErrorEvent::sHandlingScriptError = false;
|
||||
|
||||
// NOTE: This function could be refactored to use the above. The only reason
|
||||
// it has not been done is that the code below only fills the error event
|
||||
// after it has a good nsPresContext - whereas using the above function
|
||||
// would involve always filling it. Is that a concern?
|
||||
// This temporarily lives here to avoid code churn. It will go away entirely
|
||||
// soon.
|
||||
namespace xpc {
|
||||
|
||||
void
|
||||
NS_ScriptErrorReporter(JSContext *cx,
|
||||
const char *message,
|
||||
JSErrorReport *report)
|
||||
SystemErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
|
||||
{
|
||||
// We don't want to report exceptions too eagerly, but warnings in the
|
||||
// absence of werror are swallowed whole, so report those now.
|
||||
if (!JSREPORT_IS_WARNING(report->flags)) {
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
if (JS::DescribeScriptedCaller(cx)) {
|
||||
xpc->MarkErrorUnreported(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (xpc) {
|
||||
nsAXPCNativeCallContext *cc = nullptr;
|
||||
xpc->GetCurrentNativeCallContext(&cc);
|
||||
if (cc) {
|
||||
nsAXPCNativeCallContext *prev = cc;
|
||||
while (NS_SUCCEEDED(prev->GetPreviousCallContext(&prev)) && prev) {
|
||||
uint16_t lang;
|
||||
if (NS_SUCCEEDED(prev->GetLanguage(&lang)) &&
|
||||
lang == nsAXPCNativeCallContext::LANG_JS) {
|
||||
xpc->MarkErrorUnreported(cx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> exception(cx);
|
||||
::JS_GetPendingException(cx, &exception);
|
||||
|
||||
|
@ -566,27 +452,43 @@ NS_ScriptErrorReporter(JSContext *cx,
|
|||
|
||||
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
|
||||
nsCOMPtr<nsIGlobalObject> globalObject;
|
||||
|
||||
// The eventual plan is for error reporting to happen in the AutoJSAPI
|
||||
// destructor using the global with which the AutoJSAPI was initialized. We
|
||||
// can't _quite_ do that yet, so we take a sloppy stab at those semantics. If
|
||||
// we have an nsIScriptContext, we'll get the right answer modulo
|
||||
// non-current-inners.
|
||||
//
|
||||
// Otherwise, we just use the privileged junk scope. This has the effect of
|
||||
// causing us to report the error as "chrome javascript" rather than "content
|
||||
// javascript", and not invoking any error reporters. This is exactly what we
|
||||
// want here.
|
||||
if (nsIScriptContext* scx = GetScriptContextFromJSContext(cx)) {
|
||||
nsCOMPtr<nsPIDOMWindow> outer = do_QueryInterface(scx->GetGlobalObject());
|
||||
if (outer) {
|
||||
globalObject = static_cast<nsGlobalWindow*>(outer->GetCurrentInnerWindow());
|
||||
}
|
||||
} else {
|
||||
globalObject = xpc::GetNativeForGlobal(xpc::PrivilegedJunkScope());
|
||||
}
|
||||
if (globalObject) {
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
|
||||
MOZ_ASSERT_IF(win, win->IsInnerWindow());
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
|
||||
do_QueryInterface(globalObject);
|
||||
NS_ASSERTION(scriptPrincipal, "Global objects must implement "
|
||||
"nsIScriptObjectPrincipal");
|
||||
if (globalObject) {
|
||||
nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
xpcReport->Init(report, message, globalObject);
|
||||
|
||||
// If there's no window to fire an event at, report it to the console
|
||||
// directly.
|
||||
if (!xpcReport->mWindow) {
|
||||
xpcReport->LogToConsole();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we need to asynchronously invoke onerror before we can decide
|
||||
// whether or not to report the error to the console.
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new ScriptErrorEvent(JS_GetRuntime(cx),
|
||||
report,
|
||||
message,
|
||||
xpcReport,
|
||||
nsJSPrincipals::get(report->originPrincipals),
|
||||
scriptPrincipal->GetPrincipal(),
|
||||
win,
|
||||
exception,
|
||||
/* We do not try to report Out Of Memory via a dom
|
||||
* event because the dom event handler would
|
||||
|
@ -597,51 +499,10 @@ NS_ScriptErrorReporter(JSContext *cx,
|
|||
*/
|
||||
report->errorNumber != JSMSG_OUT_OF_MEMORY));
|
||||
}
|
||||
|
||||
if (nsContentUtils::DOMWindowDumpEnabled()) {
|
||||
// Print it to stderr as well, for the benefit of those invoking
|
||||
// mozilla with -console.
|
||||
nsAutoCString error;
|
||||
error.AssignLiteral("JavaScript ");
|
||||
if (JSREPORT_IS_STRICT(report->flags))
|
||||
error.AppendLiteral("strict ");
|
||||
if (JSREPORT_IS_WARNING(report->flags))
|
||||
error.AppendLiteral("warning: ");
|
||||
else
|
||||
error.AppendLiteral("error: ");
|
||||
error.Append(report->filename);
|
||||
error.AppendLiteral(", line ");
|
||||
error.AppendInt(report->lineno, 10);
|
||||
error.AppendLiteral(": ");
|
||||
if (report->ucmessage) {
|
||||
AppendUTF16toUTF8(reinterpret_cast<const char16_t*>(report->ucmessage),
|
||||
error);
|
||||
} else {
|
||||
error.Append(message);
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s\n", error.get());
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (!gJSDiagnostics)
|
||||
gJSDiagnostics = PR_NewLogModule("JSDiagnostics");
|
||||
|
||||
if (gJSDiagnostics) {
|
||||
PR_LOG(gJSDiagnostics,
|
||||
JSREPORT_IS_WARNING(report->flags) ? PR_LOG_WARNING : PR_LOG_ERROR,
|
||||
("file %s, line %u: %s\n%s%s",
|
||||
report->filename, report->lineno, message,
|
||||
report->linebuf ? report->linebuf : "",
|
||||
(report->linebuf &&
|
||||
report->linebuf[strlen(report->linebuf)-1] != '\n')
|
||||
? "\n"
|
||||
: ""));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} /* namespace xpc */
|
||||
|
||||
#ifdef DEBUG
|
||||
// A couple of useful functions to call when you're debugging.
|
||||
nsGlobalWindow *
|
||||
|
@ -899,7 +760,7 @@ nsJSContext::InitContext()
|
|||
if (!mContext)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
::JS_SetErrorReporter(mContext, NS_ScriptErrorReporter);
|
||||
JS_SetErrorReporter(mContext, xpc::SystemErrorReporter);
|
||||
|
||||
JSOptionChangedCallback(js_options_dot_str, this);
|
||||
|
||||
|
@ -1071,7 +932,7 @@ nsJSContext::AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv)
|
|||
|
||||
p->GetData(data);
|
||||
|
||||
// cast is probably safe since wchar_t and jschar are expected
|
||||
// cast is probably safe since wchar_t and char16_t are expected
|
||||
// to be equivalent; both unsigned 16-bit entities
|
||||
JSString *str =
|
||||
::JS_NewUCStringCopyN(cx, data.get(), data.Length());
|
||||
|
@ -2458,8 +2319,8 @@ NotifyGCEndRunnable::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
const jschar oomMsg[3] = { '{', '}', 0 };
|
||||
const jschar *toSend = mMessage.get() ? mMessage.get() : oomMsg;
|
||||
const char16_t oomMsg[3] = { '{', '}', 0 };
|
||||
const char16_t *toSend = mMessage.get() ? mMessage.get() : oomMsg;
|
||||
observerService->NotifyObservers(nullptr, "garbage-collection-statistics", toSend);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2829,8 +2690,8 @@ NS_DOMStructuredCloneError(JSContext* cx,
|
|||
|
||||
static bool
|
||||
AsmJSCacheOpenEntryForRead(JS::Handle<JSObject*> aGlobal,
|
||||
const jschar* aBegin,
|
||||
const jschar* aLimit,
|
||||
const char16_t* aBegin,
|
||||
const char16_t* aLimit,
|
||||
size_t* aSize,
|
||||
const uint8_t** aMemory,
|
||||
intptr_t *aHandle)
|
||||
|
@ -2844,8 +2705,8 @@ AsmJSCacheOpenEntryForRead(JS::Handle<JSObject*> aGlobal,
|
|||
static bool
|
||||
AsmJSCacheOpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
|
||||
bool aInstalled,
|
||||
const jschar* aBegin,
|
||||
const jschar* aEnd,
|
||||
const char16_t* aBegin,
|
||||
const char16_t* aEnd,
|
||||
size_t aSize,
|
||||
uint8_t** aMemory,
|
||||
intptr_t* aHandle)
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
#include "nsIXPConnect.h"
|
||||
#include "nsIArray.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "xpcpublic.h"
|
||||
|
||||
class nsICycleCollectorListener;
|
||||
class nsIXPConnectJSObjectHolder;
|
||||
|
@ -189,30 +191,18 @@ class AsyncErrorReporter : public nsRunnable
|
|||
{
|
||||
public:
|
||||
// aWindow may be null if this error report is not associated with a window
|
||||
AsyncErrorReporter(JSRuntime* aRuntime,
|
||||
JSErrorReport* aErrorReport,
|
||||
const char* aFallbackMessage,
|
||||
bool aIsChromeError, // To determine category
|
||||
nsPIDOMWindow* aWindow);
|
||||
AsyncErrorReporter(JSRuntime* aRuntime, xpc::ErrorReport* aReport)
|
||||
: mReport(aReport)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
ReportError();
|
||||
mReport->LogToConsole();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Do the actual error reporting
|
||||
void ReportError();
|
||||
|
||||
nsString mErrorMsg;
|
||||
nsString mFileName;
|
||||
nsString mSourceLine;
|
||||
nsCString mCategory;
|
||||
uint32_t mLineNumber;
|
||||
uint32_t mColumn;
|
||||
uint32_t mFlags;
|
||||
uint64_t mInnerWindowID;
|
||||
nsRefPtr<xpc::ErrorReport> mReport;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -238,9 +228,6 @@ public:
|
|||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSArgArray, NS_IJSARGARRAY_IID)
|
||||
|
||||
/* prototypes */
|
||||
void NS_ScriptErrorReporter(JSContext *cx, const char *message, JSErrorReport *report);
|
||||
|
||||
JSObject* NS_DOMReadStructuredClone(JSContext* cx,
|
||||
JSStructuredCloneReader* reader, uint32_t tag,
|
||||
uint32_t data, void* closure);
|
||||
|
|
|
@ -42,8 +42,8 @@ protected:
|
|||
private:
|
||||
// aString is expected to actually be an nsAString*. Should only be
|
||||
// called from StringifyToJSON.
|
||||
static bool AppendJSONToString(const jschar* aJSONData, uint32_t aDataLength,
|
||||
void* aString);
|
||||
static bool AppendJSONToString(const char16_t* aJSONData,
|
||||
uint32_t aDataLength, void* aString);
|
||||
};
|
||||
|
||||
// Struct that serves as a base class for all typed arrays and array buffers and
|
||||
|
|
|
@ -157,7 +157,7 @@ ErrorResult::ReportTypeError(JSContext* aCx)
|
|||
|
||||
Message* message = mMessage;
|
||||
const uint32_t argCount = message->mArgs.Length();
|
||||
const jschar* args[11];
|
||||
const char16_t* args[11];
|
||||
for (uint32_t i = 0; i < argCount; ++i) {
|
||||
args[i] = message->mArgs.ElementAt(i).get();
|
||||
}
|
||||
|
@ -1629,9 +1629,7 @@ DictionaryBase::ParseJSON(JSContext* aCx,
|
|||
if (aJSON.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return JS_ParseJSON(aCx,
|
||||
static_cast<const jschar*>(PromiseFlatString(aJSON).get()),
|
||||
aJSON.Length(), aVal);
|
||||
return JS_ParseJSON(aCx, PromiseFlatString(aJSON).get(), aJSON.Length(), aVal);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1645,18 +1643,15 @@ DictionaryBase::StringifyToJSON(JSContext* aCx,
|
|||
|
||||
/* static */
|
||||
bool
|
||||
DictionaryBase::AppendJSONToString(const jschar* aJSONData,
|
||||
DictionaryBase::AppendJSONToString(const char16_t* aJSONData,
|
||||
uint32_t aDataLength,
|
||||
void* aString)
|
||||
{
|
||||
nsAString* string = static_cast<nsAString*>(aString);
|
||||
string->Append(static_cast<const char16_t*>(aJSONData),
|
||||
aDataLength);
|
||||
string->Append(aJSONData, aDataLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static JSString*
|
||||
ConcatJSString(JSContext* cx, const char* pre, JS::Handle<JSString*> str, const char* post)
|
||||
{
|
||||
|
@ -2244,10 +2239,10 @@ ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
|
|||
// and report the error outside the AutoCheckCannotGC scope.
|
||||
bool foundBadChar = false;
|
||||
size_t badCharIndex;
|
||||
jschar badChar;
|
||||
char16_t badChar;
|
||||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
const jschar* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, s, &length);
|
||||
const char16_t* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, s, &length);
|
||||
if (!chars) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2270,11 +2265,11 @@ ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
|
|||
char index[21];
|
||||
static_assert(sizeof(size_t) <= 8, "index array too small");
|
||||
PR_snprintf(index, sizeof(index), "%d", badCharIndex);
|
||||
// A jschar is 16 bits long. The biggest unsigned 16 bit
|
||||
// A char16_t is 16 bits long. The biggest unsigned 16 bit
|
||||
// number (65,535) has 5 digits, plus one more for the null
|
||||
// terminator.
|
||||
char badCharArray[6];
|
||||
static_assert(sizeof(jschar) <= 2, "badCharArray too small");
|
||||
static_assert(sizeof(char16_t) <= 2, "badCharArray too small");
|
||||
PR_snprintf(badCharArray, sizeof(badCharArray), "%d", badChar);
|
||||
ThrowErrorMessage(cx, MSG_INVALID_BYTESTRING, index, badCharArray);
|
||||
return false;
|
||||
|
|
|
@ -1145,8 +1145,8 @@ FindEnumStringIndex(JSContext* cx, JS::Handle<JS::Value> v, const EnumEntry* val
|
|||
}
|
||||
index = FindEnumStringIndexImpl(chars, length, values);
|
||||
} else {
|
||||
const jschar* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, str,
|
||||
&length);
|
||||
const char16_t* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, str,
|
||||
&length);
|
||||
if (!chars) {
|
||||
*ok = false;
|
||||
return 0;
|
||||
|
|
|
@ -3385,7 +3385,7 @@ class CGIsPermittedMethod(CGAbstractMethod):
|
|||
self.crossOriginSetters = crossOriginSetters
|
||||
self.crossOriginMethods = crossOriginMethods
|
||||
args = [Argument("JSFlatString*", "prop"),
|
||||
Argument("jschar", "propFirstChar"),
|
||||
Argument("char16_t", "propFirstChar"),
|
||||
Argument("bool", "set")]
|
||||
CGAbstractMethod.__init__(self, descriptor, "IsPermitted", "bool", args,
|
||||
inline=True)
|
||||
|
|
|
@ -150,7 +150,7 @@ GetArrayIndexFromId(JSContext* cx, JS::Handle<jsid> id)
|
|||
}
|
||||
if (MOZ_LIKELY(JSID_IS_ATOM(id))) {
|
||||
JSAtom* atom = JSID_TO_ATOM(id);
|
||||
jschar s;
|
||||
char16_t s;
|
||||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
if (js::AtomHasLatin1Chars(atom)) {
|
||||
|
|
|
@ -534,15 +534,29 @@ public:
|
|||
// Allow whatever element types the bindings are willing to pass
|
||||
// us in TexSubImage2D
|
||||
template<class ElementType>
|
||||
void TexSubImage2D(GLenum target, GLint level,
|
||||
void TexSubImage2D(GLenum texImageTarget, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLenum format,
|
||||
GLenum type, ElementType& elt, ErrorResult& rv)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
const GLenum target = TexImageTargetToTexTarget(texImageTarget);
|
||||
if (target == LOCAL_GL_NONE)
|
||||
return ErrorInvalidEnumInfo("texSubImage2D: target", texImageTarget);
|
||||
|
||||
if (!ValidateTexImageFormatAndType(format, type, WebGLTexImageFunc::TexImage))
|
||||
return;
|
||||
|
||||
if (level < 0)
|
||||
return ErrorInvalidValue("texSubImage2D: level is negative");
|
||||
|
||||
const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
|
||||
if (level > maxLevel)
|
||||
return ErrorInvalidValue("texSubImage2D: level %d is too large, max is %d", level, maxLevel);
|
||||
|
||||
// Trying to handle the video by GPU directly first
|
||||
if (TexImageFromVideoElement(target, level, format, format, type, elt)) {
|
||||
if (TexImageFromVideoElement(texImageTarget, level, format, format, type, elt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -556,7 +570,7 @@ public:
|
|||
|
||||
gfx::IntSize size = data->GetSize();
|
||||
uint32_t byteLength = data->Stride() * size.height;
|
||||
return TexSubImage2D_base(target, level, xoffset, yoffset,
|
||||
return TexSubImage2D_base(texImageTarget, level, xoffset, yoffset,
|
||||
size.width, size.height,
|
||||
data->Stride(), format, type,
|
||||
data->GetData(), byteLength,
|
||||
|
|
|
@ -2964,7 +2964,6 @@ WebCryptoTask::CreateUnwrapKeyTask(JSContext* aCx,
|
|||
}
|
||||
|
||||
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -103,7 +103,7 @@ GetJSValFromKeyPathString(JSContext* aCx,
|
|||
|
||||
NS_ASSERTION(!token.IsEmpty(), "Should be a valid keypath");
|
||||
|
||||
const jschar* keyPathChars = token.BeginReading();
|
||||
const char16_t* keyPathChars = token.BeginReading();
|
||||
const size_t keyPathLen = token.Length();
|
||||
|
||||
bool hasProp;
|
||||
|
|
|
@ -651,7 +651,8 @@ ContentParent::GetNewOrPreallocatedAppProcess(mozIApplication* aApp,
|
|||
NS_ERROR("Failed to get manifest URL");
|
||||
return nullptr;
|
||||
}
|
||||
process->TransformPreallocatedIntoApp(manifestURL);
|
||||
process->TransformPreallocatedIntoApp(aOpener,
|
||||
manifestURL);
|
||||
if (aTookPreAllocated) {
|
||||
*aTookPreAllocated = true;
|
||||
}
|
||||
|
@ -799,15 +800,9 @@ ContentParent::GetNewOrUsedBrowserProcess(bool aForBrowserElement,
|
|||
// Try to take and transform the preallocated process into browser.
|
||||
nsRefPtr<ContentParent> p = PreallocatedProcessManager::Take();
|
||||
if (p) {
|
||||
p->TransformPreallocatedIntoBrowser();
|
||||
p->TransformPreallocatedIntoBrowser(aOpener);
|
||||
} else {
|
||||
// Failed in using the preallocated process: fork from the chrome process.
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
if (Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {
|
||||
// Wait until the Nuwa process forks a new process.
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
p = new ContentParent(/* app = */ nullptr,
|
||||
aOpener,
|
||||
aForBrowserElement,
|
||||
|
@ -898,7 +893,10 @@ ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext,
|
|||
}
|
||||
|
||||
if (!cp) {
|
||||
return false;
|
||||
*aId = 0;
|
||||
*aIsForApp = false;
|
||||
*aIsForBrowser = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
*aId = cp->ChildID();
|
||||
|
@ -948,13 +946,15 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
|||
nsRefPtr<nsIContentParent> constructorSender;
|
||||
if (isInContentProcess) {
|
||||
MOZ_ASSERT(aContext.IsBrowserElement());
|
||||
constructorSender = CreateContentBridgeParent(aContext, initialPriority);
|
||||
constructorSender =
|
||||
CreateContentBridgeParent(aContext, initialPriority);
|
||||
} else {
|
||||
if (aOpenerContentParent) {
|
||||
constructorSender = aOpenerContentParent;
|
||||
} else {
|
||||
constructorSender = GetNewOrUsedBrowserProcess(aContext.IsBrowserElement(),
|
||||
initialPriority);
|
||||
constructorSender =
|
||||
GetNewOrUsedBrowserProcess(aContext.IsBrowserElement(),
|
||||
initialPriority);
|
||||
}
|
||||
}
|
||||
if (constructorSender) {
|
||||
|
@ -1149,6 +1149,9 @@ ContentParent::CreateContentBridgeParent(const TabContext& aContext,
|
|||
&isForBrowser)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (id == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!child->CallBridgeToChildProcess(id)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1381,17 +1384,20 @@ TryGetNameFromManifestURL(const nsAString& aManifestURL,
|
|||
}
|
||||
|
||||
void
|
||||
ContentParent::TransformPreallocatedIntoApp(const nsAString& aAppManifestURL)
|
||||
ContentParent::TransformPreallocatedIntoApp(ContentParent* aOpener,
|
||||
const nsAString& aAppManifestURL)
|
||||
{
|
||||
MOZ_ASSERT(IsPreallocated());
|
||||
mOpener = aOpener;
|
||||
mAppManifestURL = aAppManifestURL;
|
||||
TryGetNameFromManifestURL(aAppManifestURL, mAppName);
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::TransformPreallocatedIntoBrowser()
|
||||
ContentParent::TransformPreallocatedIntoBrowser(ContentParent* aOpener)
|
||||
{
|
||||
// Reset mAppManifestURL, mIsForBrowser and mOSPrivileges for browser.
|
||||
mOpener = aOpener;
|
||||
mAppManifestURL.Truncate();
|
||||
mIsForBrowser = true;
|
||||
}
|
||||
|
|
|
@ -363,11 +363,12 @@ private:
|
|||
|
||||
// Transform a pre-allocated app process into a "real" app
|
||||
// process, for the specified manifest URL.
|
||||
void TransformPreallocatedIntoApp(const nsAString& aAppManifestURL);
|
||||
void TransformPreallocatedIntoApp(ContentParent* aOpener,
|
||||
const nsAString& aAppManifestURL);
|
||||
|
||||
// Transform a pre-allocated app process into a browser process. If this
|
||||
// returns false, the child process has died.
|
||||
void TransformPreallocatedIntoBrowser();
|
||||
void TransformPreallocatedIntoBrowser(ContentParent* aOpener);
|
||||
|
||||
/**
|
||||
* Mark this ContentParent as dead for the purposes of Get*().
|
||||
|
|
|
@ -492,7 +492,7 @@ TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName,
|
|||
StructuredCloneData cloneData;
|
||||
JSAutoStructuredCloneBuffer buffer;
|
||||
if (JS_ParseJSON(cx,
|
||||
static_cast<const jschar*>(aJSONData.BeginReading()),
|
||||
static_cast<const char16_t*>(aJSONData.BeginReading()),
|
||||
aJSONData.Length(),
|
||||
&json)) {
|
||||
WriteStructuredClone(cx, json, buffer, cloneData.mClosure);
|
||||
|
@ -747,7 +747,10 @@ TabChild::PreloadSlowThings()
|
|||
{
|
||||
MOZ_ASSERT(!sPreallocatedTab);
|
||||
|
||||
nsRefPtr<TabChild> tab(new TabChild(ContentChild::GetSingleton(),
|
||||
// Pass nullptr to aManager since at this point the TabChild is
|
||||
// not connected to any manager. Any attempt to use the TabChild
|
||||
// in IPC will crash.
|
||||
nsRefPtr<TabChild> tab(new TabChild(nullptr,
|
||||
TabContext(), /* chromeFlags */ 0));
|
||||
if (!NS_SUCCEEDED(tab->Init()) ||
|
||||
!tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) {
|
||||
|
@ -777,7 +780,9 @@ TabChild::PreloadSlowThings()
|
|||
}
|
||||
|
||||
/*static*/ already_AddRefed<TabChild>
|
||||
TabChild::Create(nsIContentChild* aManager, const TabContext &aContext, uint32_t aChromeFlags)
|
||||
TabChild::Create(nsIContentChild* aManager,
|
||||
const TabContext &aContext,
|
||||
uint32_t aChromeFlags)
|
||||
{
|
||||
if (sPreallocatedTab &&
|
||||
sPreallocatedTab->mChromeFlags == aChromeFlags &&
|
||||
|
@ -788,6 +793,7 @@ TabChild::Create(nsIContentChild* aManager, const TabContext &aContext, uint32_t
|
|||
|
||||
MOZ_ASSERT(!child->mTriedBrowserInit);
|
||||
|
||||
child->mManager = aManager;
|
||||
child->SetTabContext(aContext);
|
||||
child->NotifyTabContextUpdated();
|
||||
return child.forget();
|
||||
|
@ -799,7 +805,9 @@ TabChild::Create(nsIContentChild* aManager, const TabContext &aContext, uint32_t
|
|||
}
|
||||
|
||||
|
||||
TabChild::TabChild(nsIContentChild* aManager, const TabContext& aContext, uint32_t aChromeFlags)
|
||||
TabChild::TabChild(nsIContentChild* aManager,
|
||||
const TabContext& aContext,
|
||||
uint32_t aChromeFlags)
|
||||
: TabContext(aContext)
|
||||
, mRemoteFrame(nullptr)
|
||||
, mManager(aManager)
|
||||
|
|
|
@ -67,7 +67,8 @@ nsIContentChild::AllocPBrowserChild(const IPCTabContext& aContext,
|
|||
MOZ_CRASH("Invalid TabContext received from the parent process.");
|
||||
}
|
||||
|
||||
nsRefPtr<TabChild> child = TabChild::Create(this, tc.GetTabContext(), aChromeFlags);
|
||||
nsRefPtr<TabChild> child =
|
||||
TabChild::Create(this, tc.GetTabContext(), aChromeFlags);
|
||||
|
||||
// The ref here is released in DeallocPBrowserChild.
|
||||
return child.forget().take();
|
||||
|
|
|
@ -163,7 +163,7 @@ nsJSON::EncodeToStream(nsIOutputStream *aStream,
|
|||
}
|
||||
|
||||
static bool
|
||||
WriteCallback(const jschar *buf, uint32_t len, void *data)
|
||||
WriteCallback(const char16_t *buf, uint32_t len, void *data)
|
||||
{
|
||||
nsJSONWriter *writer = static_cast<nsJSONWriter*>(data);
|
||||
nsresult rv = writer->Write((const char16_t*)buf, (uint32_t)len);
|
||||
|
@ -389,7 +389,7 @@ NS_IMETHODIMP
|
|||
nsJSON::DecodeToJSVal(const nsAString &str, JSContext *cx,
|
||||
JS::MutableHandle<JS::Value> result)
|
||||
{
|
||||
if (!JS_ParseJSON(cx, static_cast<const jschar*>(PromiseFlatString(str).get()),
|
||||
if (!JS_ParseJSON(cx, static_cast<const char16_t*>(PromiseFlatString(str).get()),
|
||||
str.Length(), result)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
@ -525,7 +525,7 @@ nsJSONListener::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
|
|||
|
||||
JS::Rooted<JS::Value> reviver(mCx, JS::NullValue()), value(mCx);
|
||||
|
||||
JS::ConstTwoByteChars chars(reinterpret_cast<const jschar*>(mBufferedChars.Elements()),
|
||||
JS::ConstTwoByteChars chars(reinterpret_cast<const char16_t*>(mBufferedChars.Elements()),
|
||||
mBufferedChars.Length());
|
||||
bool ok = JS_ParseJSONWithReviver(mCx, chars.get(),
|
||||
uint32_t(mBufferedChars.Length()),
|
||||
|
|
|
@ -505,15 +505,18 @@ public:
|
|||
(aVideoSource ? DOMMediaStream::HINT_CONTENTS_VIDEO : 0);
|
||||
|
||||
nsRefPtr<nsDOMUserMediaStream> stream = new nsDOMUserMediaStream(aListener,
|
||||
aAudioSource);
|
||||
aAudioSource,
|
||||
aVideoSource);
|
||||
stream->InitTrackUnionStream(aWindow, hints);
|
||||
return stream.forget();
|
||||
}
|
||||
|
||||
nsDOMUserMediaStream(GetUserMediaCallbackMediaStreamListener* aListener,
|
||||
MediaEngineSource *aAudioSource) :
|
||||
MediaEngineSource *aAudioSource,
|
||||
MediaEngineSource *aVideoSource) :
|
||||
mListener(aListener),
|
||||
mAudioSource(aAudioSource),
|
||||
mVideoSource(aVideoSource),
|
||||
mEchoOn(true),
|
||||
mAgcOn(false),
|
||||
mNoiseOn(true),
|
||||
|
@ -625,12 +628,32 @@ public:
|
|||
GetStream()->AsProcessedStream()->ForwardTrackEnabled(aID, aEnabled);
|
||||
}
|
||||
|
||||
virtual DOMLocalMediaStream* AsDOMLocalMediaStream()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual MediaEngineSource* GetMediaEngine(TrackID aTrackID)
|
||||
{
|
||||
// MediaEngine supports only one video and on video track now and TrackID is
|
||||
// fixed in MediaEngine.
|
||||
if (aTrackID == kVideoTrack) {
|
||||
return mVideoSource;
|
||||
}
|
||||
else if (aTrackID == kAudioTrack) {
|
||||
return mAudioSource;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The actual MediaStream is a TrackUnionStream. But these resources need to be
|
||||
// explicitly destroyed too.
|
||||
nsRefPtr<SourceMediaStream> mSourceStream;
|
||||
nsRefPtr<MediaInputPort> mPort;
|
||||
nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
|
||||
nsRefPtr<MediaEngineSource> mAudioSource; // so we can turn on AEC
|
||||
nsRefPtr<MediaEngineSource> mVideoSource;
|
||||
bool mEchoOn;
|
||||
bool mAgcOn;
|
||||
bool mNoiseOn;
|
||||
|
|
|
@ -23,8 +23,8 @@ DialogWatcher.prototype.init = function() {
|
|||
this.findWindow = user32.declare("FindWindowW",
|
||||
ctypes.winapi_abi,
|
||||
ctypes.uintptr_t,
|
||||
ctypes.jschar.ptr,
|
||||
ctypes.jschar.ptr);
|
||||
ctypes.char16_t.ptr,
|
||||
ctypes.char16_t.ptr);
|
||||
}
|
||||
if (!this.winEventProcType) {
|
||||
this.winEventProcType = ctypes.FunctionType(ctypes.stdcall_abi,
|
||||
|
@ -94,7 +94,7 @@ DialogWatcher.prototype.init = function() {
|
|||
ctypes.winapi_abi,
|
||||
ctypes.int,
|
||||
ctypes.uintptr_t,
|
||||
ctypes.jschar.ptr,
|
||||
ctypes.char16_t.ptr,
|
||||
ctypes.int);
|
||||
}
|
||||
if (!this.messageBox) {
|
||||
|
@ -103,14 +103,14 @@ DialogWatcher.prototype.init = function() {
|
|||
ctypes.winapi_abi,
|
||||
ctypes.int,
|
||||
ctypes.uintptr_t,
|
||||
ctypes.jschar.ptr,
|
||||
ctypes.jschar.ptr,
|
||||
ctypes.char16_t.ptr,
|
||||
ctypes.char16_t.ptr,
|
||||
ctypes.uint32_t);
|
||||
}
|
||||
};
|
||||
|
||||
DialogWatcher.prototype.getWindowText = function(hwnd) {
|
||||
var bufType = ctypes.ArrayType(ctypes.jschar);
|
||||
var bufType = ctypes.ArrayType(ctypes.char16_t);
|
||||
var buffer = new bufType(256);
|
||||
|
||||
if (this.getWindowTextW(hwnd, buffer, buffer.length)) {
|
||||
|
@ -181,4 +181,3 @@ DialogWatcher.prototype.processWindowEvents = function(timeout) {
|
|||
// Returns true if the hook was successful, something was found, and we never timed out
|
||||
return this.hwnd !== undefined && waitStatus == WAIT_OBJECT_0;
|
||||
};
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@ function initCTypes() {
|
|||
ctypes.winapi_abi,
|
||||
ctypes.int,
|
||||
ctypes.uintptr_t,
|
||||
ctypes.jschar.ptr,
|
||||
ctypes.jschar.ptr,
|
||||
ctypes.char16_t.ptr,
|
||||
ctypes.char16_t.ptr,
|
||||
ctypes.uint32_t);
|
||||
}
|
||||
if (!watcher) {
|
||||
|
|
|
@ -1005,19 +1005,13 @@ Promise::MaybeReportRejected()
|
|||
return;
|
||||
}
|
||||
|
||||
// Remains null in case of worker.
|
||||
nsCOMPtr<nsPIDOMWindow> win;
|
||||
bool isChromeError = false;
|
||||
|
||||
nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
if (MOZ_LIKELY(NS_IsMainThread())) {
|
||||
nsIPrincipal* principal;
|
||||
win = xpc::WindowGlobalOrNull(obj);
|
||||
principal = nsContentUtils::ObjectPrincipal(obj);
|
||||
isChromeError = nsContentUtils::IsSystemPrincipal(principal);
|
||||
nsIGlobalObject* global = xpc::GetNativeForGlobal(js::GetGlobalForObjectCrossCompartment(obj));
|
||||
xpcReport->Init(report.report(), report.message(), global);
|
||||
} else {
|
||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(worker);
|
||||
isChromeError = worker->IsChromeWorker();
|
||||
xpcReport->InitOnWorkerThread(report.report(), report.message(),
|
||||
GetCurrentThreadWorkerPrivate()->IsChromeWorker());
|
||||
}
|
||||
|
||||
// Now post an event to do the real reporting async
|
||||
|
@ -1025,11 +1019,7 @@ Promise::MaybeReportRejected()
|
|||
// AsyncErrorReporter, otherwise if the call to DispatchToMainThread fails, it
|
||||
// will leak. See Bug 958684.
|
||||
nsRefPtr<AsyncErrorReporter> r =
|
||||
new AsyncErrorReporter(CycleCollectedJSRuntime::Get()->Runtime(),
|
||||
report.report(),
|
||||
report.message(),
|
||||
isChromeError,
|
||||
win);
|
||||
new AsyncErrorReporter(CycleCollectedJSRuntime::Get()->Runtime(), xpcReport);
|
||||
NS_DispatchToMainThread(r);
|
||||
}
|
||||
|
||||
|
|
|
@ -363,13 +363,14 @@ MozMtpDatabase::CreateEntryForFile(const nsACString& aPath, DeviceStorageFile* a
|
|||
if (slash == kNotFound) {
|
||||
component.Rebind(aPath, 0, aPath.Length());
|
||||
} else {
|
||||
component.Rebind(aPath, slash, aPath.Length() - slash);
|
||||
component.Rebind(aPath, 0 , slash);
|
||||
}
|
||||
if (doFind) {
|
||||
MtpObjectHandle entryHandle = FindEntryByPath(component);
|
||||
if (entryHandle != 0) {
|
||||
// We found an entry.
|
||||
parent = entryHandle;
|
||||
offset = slash + 1 ;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -408,6 +409,7 @@ MozMtpDatabase::CreateEntryForFile(const nsACString& aPath, DeviceStorageFile* a
|
|||
|
||||
AddEntry(entry);
|
||||
parent = entry->mHandle;
|
||||
offset = slash + 1;
|
||||
} while (slash != kNotFound);
|
||||
|
||||
return parent; // parent will be entry->mHandle
|
||||
|
|
|
@ -163,7 +163,7 @@ void LossyConvertUTF8toUTF16(const char* aInput, uint32_t aLength, nsAString& aO
|
|||
|
||||
char16_t dst[aLength]; // Allocating for worst case.
|
||||
|
||||
// First, count how many jschars need to be in the inflated string.
|
||||
// Count how many char16_t characters are needed in the inflated string.
|
||||
// |i| is the index into |src|, and |j| is the the index into |dst|.
|
||||
size_t srclen = src.length();
|
||||
uint32_t j = 0;
|
||||
|
@ -214,20 +214,20 @@ void LossyConvertUTF8toUTF16(const char* aInput, uint32_t aLength, nsAString& aO
|
|||
if ((src[i + m] & 0xC0) != 0x80)
|
||||
INVALID(ReportInvalidCharacter, i, m);
|
||||
|
||||
// Determine the code unit's length in jschars and act accordingly.
|
||||
// Determine the code unit's length in char16_t units and act accordingly.
|
||||
v = JS::Utf8ToOneUcs4Char((uint8_t *)&src[i], n);
|
||||
if (v < 0x10000) {
|
||||
// The n-byte UTF8 code unit will fit in a single jschar.
|
||||
dst[j] = jschar(v);
|
||||
// The n-byte UTF8 code unit will fit in a single char16_t.
|
||||
dst[j] = char16_t(v);
|
||||
} else {
|
||||
v -= 0x10000;
|
||||
if (v <= 0xFFFFF) {
|
||||
// The n-byte UTF8 code unit will fit in two jschars.
|
||||
dst[j] = jschar((v >> 10) + 0xD800);
|
||||
// The n-byte UTF8 code unit will fit in two char16_t units.
|
||||
dst[j] = char16_t((v >> 10) + 0xD800);
|
||||
j++;
|
||||
dst[j] = jschar((v & 0x3FF) + 0xDC00);
|
||||
dst[j] = char16_t((v & 0x3FF) + 0xDC00);
|
||||
} else {
|
||||
// The n-byte UTF8 code unit won't fit in two jschars.
|
||||
// The n-byte UTF8 code unit won't fit in two char16_t units.
|
||||
INVALID(ReportTooBigCharacter, v, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace {
|
|||
#ifdef BUILD_CTYPES
|
||||
|
||||
char*
|
||||
UnicodeToNative(JSContext* aCx, const jschar* aSource, size_t aSourceLen)
|
||||
UnicodeToNative(JSContext* aCx, const char16_t* aSource, size_t aSourceLen)
|
||||
{
|
||||
nsDependentString unicode(aSource, aSourceLen);
|
||||
|
||||
|
|
|
@ -737,8 +737,8 @@ GetPrincipalForAsmJSCacheOp()
|
|||
|
||||
static bool
|
||||
AsmJSCacheOpenEntryForRead(JS::Handle<JSObject*> aGlobal,
|
||||
const jschar* aBegin,
|
||||
const jschar* aLimit,
|
||||
const char16_t* aBegin,
|
||||
const char16_t* aLimit,
|
||||
size_t* aSize,
|
||||
const uint8_t** aMemory,
|
||||
intptr_t *aHandle)
|
||||
|
@ -755,8 +755,8 @@ AsmJSCacheOpenEntryForRead(JS::Handle<JSObject*> aGlobal,
|
|||
static bool
|
||||
AsmJSCacheOpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
|
||||
bool aInstalled,
|
||||
const jschar* aBegin,
|
||||
const jschar* aEnd,
|
||||
const char16_t* aBegin,
|
||||
const char16_t* aEnd,
|
||||
size_t aSize,
|
||||
uint8_t** aMemory,
|
||||
intptr_t* aHandle)
|
||||
|
|
|
@ -156,7 +156,7 @@ struct ScriptLoadInfo
|
|||
|
||||
nsString mURL;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
jschar* mScriptTextBuf;
|
||||
char16_t* mScriptTextBuf;
|
||||
size_t mScriptTextLength;
|
||||
|
||||
nsresult mLoadResult;
|
||||
|
|
|
@ -337,7 +337,7 @@ nsXBLProtoImpl::UndefineFields(JSContext *cx, JS::Handle<JSObject*> obj) const
|
|||
for (nsXBLProtoImplField* f = mFields; f; f = f->GetNext()) {
|
||||
nsDependentString name(f->GetName());
|
||||
|
||||
const jschar* s = name.get();
|
||||
const char16_t* s = name.get();
|
||||
bool hasProp;
|
||||
if (::JS_AlreadyHasOwnUCProperty(cx, obj, s, name.Length(), &hasProp) &&
|
||||
hasProp) {
|
||||
|
|
|
@ -445,7 +445,7 @@ nsXBLProtoImplField::InstallField(JS::Handle<JSObject*> aBoundNode,
|
|||
nsDependentString name(mName);
|
||||
if (!JS_WrapValue(cx, &result) ||
|
||||
!::JS_DefineUCProperty(cx, aBoundNode,
|
||||
reinterpret_cast<const jschar*>(mName),
|
||||
reinterpret_cast<const char16_t*>(mName),
|
||||
name.Length(), result, mJSAttributes)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ nsXBLProtoImplMethod::InstallMember(JSContext* aCx,
|
|||
NS_ENSURE_TRUE(method, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (!::JS_DefineUCProperty(aCx, aTargetClassObject,
|
||||
static_cast<const jschar*>(mName),
|
||||
static_cast<const char16_t*>(mName),
|
||||
name.Length(), method,
|
||||
JSPROP_ENUMERATE)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
|
|
@ -147,7 +147,7 @@ nsXBLProtoImplProperty::InstallMember(JSContext *aCx,
|
|||
|
||||
nsDependentString name(mName);
|
||||
if (!::JS_DefineUCProperty(aCx, aTargetClassObject,
|
||||
static_cast<const jschar*>(mName),
|
||||
static_cast<const char16_t*>(mName),
|
||||
name.Length(), JS::UndefinedHandleValue, mJSAttributes,
|
||||
JS_DATA_TO_FUNC_PTR(JSPropertyOp, getter.get()),
|
||||
JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, setter.get())))
|
||||
|
|
|
@ -49,12 +49,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=502673
|
|||
}
|
||||
},
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
QueryInterface: SpecialPowers.wrapCallback(function(iid) {
|
||||
if (iid.equals(SpecialPowers.Ci.nsIDocumentStateListener) ||
|
||||
iid.equals(SpecialPowers.Ci.nsISupports))
|
||||
return this;
|
||||
throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
function doTest() {
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
[DEFAULT]
|
||||
skip-if = buildapp == 'b2g'
|
||||
support-files =
|
||||
320x240.ogv
|
||||
bug449141_page.html
|
||||
|
||||
[test_bug449141.html]
|
||||
skip-if = toolkit == 'android'
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче