зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to f-t, a=release to defeat a buggy hook
This commit is contained in:
Коммит
f425a31459
|
@ -166,7 +166,8 @@ ProcessGlobal.prototype = {
|
|||
let args = message.arguments;
|
||||
let stackTrace = '';
|
||||
|
||||
if (message.level == 'assert' || message.level == 'error' || message.level == 'trace') {
|
||||
if (message.stacktrace &&
|
||||
(message.level == 'assert' || message.level == 'error' || message.level == 'trace')) {
|
||||
stackTrace = Array.map(message.stacktrace, formatStackFrame).join('\n');
|
||||
} else {
|
||||
stackTrace = formatStackFrame(message);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16383ec2bf3ed46f893b15b3fab2892e9fadc4e7"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e370e6beecd28785beef8c7ff299cf788693f0cc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="16383ec2bf3ed46f893b15b3fab2892e9fadc4e7"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e370e6beecd28785beef8c7ff299cf788693f0cc"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16383ec2bf3ed46f893b15b3fab2892e9fadc4e7"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e370e6beecd28785beef8c7ff299cf788693f0cc"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b1d86462d3150dceacff927536ded9fcc168419"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16383ec2bf3ed46f893b15b3fab2892e9fadc4e7"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e370e6beecd28785beef8c7ff299cf788693f0cc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16383ec2bf3ed46f893b15b3fab2892e9fadc4e7"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e370e6beecd28785beef8c7ff299cf788693f0cc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="16383ec2bf3ed46f893b15b3fab2892e9fadc4e7"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e370e6beecd28785beef8c7ff299cf788693f0cc"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16383ec2bf3ed46f893b15b3fab2892e9fadc4e7"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e370e6beecd28785beef8c7ff299cf788693f0cc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16383ec2bf3ed46f893b15b3fab2892e9fadc4e7"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e370e6beecd28785beef8c7ff299cf788693f0cc"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b1d86462d3150dceacff927536ded9fcc168419"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "16383ec2bf3ed46f893b15b3fab2892e9fadc4e7",
|
||||
"git_revision": "e370e6beecd28785beef8c7ff299cf788693f0cc",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "2b1fea55c45ae4b59eb077840bfe5361ecd48d54",
|
||||
"revision": "e4abf3a2e6a68bafbeec52cdc2a388ff7b9adf3d",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16383ec2bf3ed46f893b15b3fab2892e9fadc4e7"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e370e6beecd28785beef8c7ff299cf788693f0cc"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b1d86462d3150dceacff927536ded9fcc168419"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16383ec2bf3ed46f893b15b3fab2892e9fadc4e7"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e370e6beecd28785beef8c7ff299cf788693f0cc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -2982,6 +2982,14 @@
|
|||
<gfxBlacklistEntry blockID="g511"> <os>WINNT 5.1</os> <vendor>0x8086</vendor> <feature>DIRECT3D_9_LAYERS, WEBGL_ANGLE</feature> <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus> <driverVersion>6.14.10.5218</driverVersion> <driverVersionComparator>LESS_THAN</driverVersionComparator> </gfxBlacklistEntry>
|
||||
</gfxItems>
|
||||
|
||||
<certItems>
|
||||
<certItem issuerName="MIGQMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDE2MDQGA1UEAxMtQ09NT0RPIFJTQSBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB">
|
||||
<serialNumber>D9UltDPl4XVfSSqQOvdiwQ==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MDIxCzAJBgNVBAYTAkNOMQ4wDAYDVQQKEwVDTk5JQzETMBEGA1UEAxMKQ05OSUMgUk9PVA==">
|
||||
<serialNumber>STMAjg==</serialNumber>
|
||||
</certItem>
|
||||
</certItems>
|
||||
|
||||
|
||||
</blocklist>
|
|
@ -54,6 +54,8 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
|
|||
[test_signed_pkg_install.html]
|
||||
[test_uninstall_errors.html]
|
||||
[test_theme_role.html]
|
||||
[test_third_party_homescreen.html]
|
||||
skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app
|
||||
[test_web_app_install.html]
|
||||
[test_widget.html]
|
||||
skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id={1097468}
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug {1097468}</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={1097468}">Mozilla Bug {1097468}</a>
|
||||
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
var gManifestURL = "http://test/tests/dom/apps/tests/file_app.sjs?apptype=hosted&getmanifest=true";
|
||||
var gGenerator = runTest();
|
||||
|
||||
const { Services } = SpecialPowers.Cu.import('resource://gre/modules/Services.jsm', {});
|
||||
|
||||
function runApp(aApp, aCallback) {
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', aApp.manifestURL);
|
||||
ifr.src = Services.io.newURI(aApp.manifestURL, null, null)
|
||||
.resolve(aApp.manifest.launch_path);
|
||||
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', function onAlert(e) {
|
||||
var message = e.detail.message;
|
||||
info("Got message " + message);
|
||||
|
||||
if (message.startsWith("OK: ")) {
|
||||
ok(true, message.substring(4, message.length));
|
||||
} else if (message.startsWith("ERROR: ")) {
|
||||
ok(false, message.substring(7, message.length));
|
||||
} else if (message == "DONE") {
|
||||
ifr.removeEventListener('mozbrowsershowmodalprompt', onAlert, false);
|
||||
loadFrameScript(mm);
|
||||
}
|
||||
}, false);
|
||||
|
||||
document.body.appendChild(ifr);
|
||||
|
||||
var mm = SpecialPowers.getBrowserFrameMessageManager(ifr);
|
||||
ok(mm, "mm is not null");
|
||||
mm.addMessageListener('OK', function(msg) {
|
||||
ok(true, "Message from app: " + SpecialPowers.wrap(msg).json);
|
||||
});
|
||||
mm.addMessageListener('KO', function(msg) {
|
||||
ok(false, "Message from app: " + SpecialPowers.wrap(msg).json);
|
||||
});
|
||||
mm.addMessageListener('DONE', function() {
|
||||
ok(true, "Message from app: complete");
|
||||
document.body.removeChild(ifr);
|
||||
aCallback();
|
||||
});
|
||||
|
||||
// Test permission |homescreen-webapps-manage|
|
||||
function frameScript()
|
||||
{
|
||||
function ok(p, msg) {
|
||||
if (p) {
|
||||
sendAsyncMessage("OK", msg);
|
||||
} else {
|
||||
sendAsyncMessage("KO", msg);
|
||||
}
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
if (a == b) {
|
||||
sendAsyncMessage("OK", a + " == " + b + " - " + msg);
|
||||
} else {
|
||||
sendAsyncMessage("KO", a + " != " + b + " - " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
function finish() {
|
||||
sendAsyncMessage("DONE", "");
|
||||
}
|
||||
|
||||
if ('mgmt' in content.window.navigator.mozApps) {
|
||||
ok(true, "get mgmt");
|
||||
var mgmt = content.window.navigator.mozApps.mgmt;
|
||||
is(typeof mgmt.getAll, "function", "get getAll");
|
||||
is(typeof mgmt.uninstall, "function", "get uninstall");
|
||||
is(typeof mgmt.oninstall, "object", "get oninstall");
|
||||
is(typeof mgmt.onuninstall, "object", "get onuninstall");
|
||||
is(typeof mgmt.onenabledstatechange, "object", "get onenabledstatechange");
|
||||
|
||||
[
|
||||
"getNotInstalled",
|
||||
"applyDownload",
|
||||
"import",
|
||||
"extractManifest",
|
||||
"setEnabled"
|
||||
].forEach(function(func) {
|
||||
is(typeof mgmt[func], "undefined", "shouldn't get" + func);
|
||||
});
|
||||
} else {
|
||||
ok(false, "can not get mgmt");
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
function loadFrameScript(mm) {
|
||||
var script = "data:,(" + frameScript.toString() + ")();";
|
||||
mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
|
||||
}
|
||||
}
|
||||
|
||||
function go() {
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ "type": "webapps-manage", "allow": 1, "context": document },
|
||||
{ "type": "browser", "allow": 1, "context": document },
|
||||
{ "type": "embed-apps", "allow": 1, "context": document }],
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({'set': [["dom.mozBrowserFramesEnabled", true],
|
||||
["dom.mozApps.homescreenURL",
|
||||
gManifestURL]]}, continueTest)});
|
||||
}
|
||||
|
||||
function continueTest() {
|
||||
try {
|
||||
gGenerator.next();
|
||||
} catch (e if e instanceof StopIteration) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function cbError(aEvent) {
|
||||
ok(false, "Error callback invoked " +
|
||||
aEvent.target.error.name + " " + aEvent.target.error.message);
|
||||
finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/**
|
||||
* Test third-party homescreen (permission |homescreen-webapps-manage|)
|
||||
*/
|
||||
function runTest() {
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
// Install a app.
|
||||
var request = navigator.mozApps.install(gManifestURL, { });
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
yield undefined;
|
||||
|
||||
var app = request.result;
|
||||
ok(app, "App is non-null");
|
||||
is(app.manifestURL, gManifestURL, "App manifest url is correct.");
|
||||
|
||||
var context = {"manifestURL": app.manifestURL, "isInBrowserElement": false};
|
||||
|
||||
SpecialPowers.pushPermissions([{"type": "homescreen-webapps-manage",
|
||||
"allow": 1,
|
||||
"context": context}], continueTest);
|
||||
yield undefined;
|
||||
|
||||
// Launch the app.
|
||||
info("Running " + app.manifestURL);
|
||||
runApp(app, continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.popPermissions(continueTest);
|
||||
yield undefined;
|
||||
|
||||
// Uninstall the app to cleanup after ourself.
|
||||
navigator.mozApps.mgmt.onuninstall = function(event) {
|
||||
var app = event.application;
|
||||
is(app.manifestURL, gManifestURL, "App uninstall event ok.");
|
||||
is(app.manifest.name, "Really Rapid Release (hosted)",
|
||||
"App uninstall manifest ok.");
|
||||
continueTest();
|
||||
}
|
||||
request = navigator.mozApps.mgmt.uninstall(app);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
yield undefined;
|
||||
yield undefined;
|
||||
is(request.result, gManifestURL, "App uninstalled.");
|
||||
navigator.mozApps.mgmt.onuninstall = null;
|
||||
}
|
||||
|
||||
addLoadEvent(go);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -23,6 +23,7 @@
|
|||
#include "xpcprivate.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
#include "nsIConsoleAPIStorage.h"
|
||||
#include "nsIDOMWindowUtils.h"
|
||||
|
@ -152,6 +153,8 @@ static const JSStructuredCloneCallbacks gConsoleCallbacks = {
|
|||
class ConsoleCallData final
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ConsoleCallData)
|
||||
|
||||
ConsoleCallData()
|
||||
: mMethodName(Console::MethodLog)
|
||||
, mPrivate(false)
|
||||
|
@ -238,6 +241,10 @@ public:
|
|||
Maybe<ConsoleStackEntry> mTopStackFrame;
|
||||
Maybe<nsTArray<ConsoleStackEntry>> mReifiedStack;
|
||||
nsCOMPtr<nsIStackFrame> mStack;
|
||||
|
||||
private:
|
||||
~ConsoleCallData()
|
||||
{ }
|
||||
};
|
||||
|
||||
// This class is used to clear any exception at the end of this method.
|
||||
|
@ -284,16 +291,13 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
AutoSyncLoopHolder syncLoop(mWorkerPrivate);
|
||||
mSyncLoopTarget = syncLoop.EventTarget();
|
||||
|
||||
if (NS_FAILED(NS_DispatchToMainThread(this))) {
|
||||
JS_ReportError(cx,
|
||||
"Failed to dispatch to main thread for the Console API!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return syncLoop.Run();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -314,14 +318,6 @@ private:
|
|||
RunWithWindow(window);
|
||||
}
|
||||
|
||||
nsRefPtr<MainThreadStopSyncLoopRunnable> response =
|
||||
new MainThreadStopSyncLoopRunnable(mWorkerPrivate,
|
||||
mSyncLoopTarget.forget(),
|
||||
true);
|
||||
if (!response->Dispatch(nullptr)) {
|
||||
NS_WARNING("Failed to dispatch response!");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -388,9 +384,6 @@ protected:
|
|||
// Raw pointer because this method is async and this object is kept alive by
|
||||
// the caller.
|
||||
Console* mConsole;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIEventTarget> mSyncLoopTarget;
|
||||
};
|
||||
|
||||
// This runnable appends a CallData object into the Console queue running on
|
||||
|
@ -406,7 +399,30 @@ public:
|
|||
|
||||
private:
|
||||
~ConsoleCallDataRunnable()
|
||||
{ }
|
||||
{
|
||||
class ReleaseCallData final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit ReleaseCallData(nsRefPtr<ConsoleCallData>& aCallData)
|
||||
{
|
||||
mCallData.swap(aCallData);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
mCallData = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<ConsoleCallData> mCallData;
|
||||
};
|
||||
|
||||
nsRefPtr<ReleaseCallData> runnable = new ReleaseCallData(mCallData);
|
||||
if(NS_FAILED(NS_DispatchToMainThread(runnable))) {
|
||||
NS_WARNING("Failed to dispatch a ReleaseCallData runnable. Leaking.");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PreDispatch(JSContext* aCx) override
|
||||
|
@ -514,7 +530,7 @@ private:
|
|||
mConsole->ProcessCallData(mCallData);
|
||||
}
|
||||
|
||||
ConsoleCallData* mCallData;
|
||||
nsRefPtr<ConsoleCallData> mCallData;
|
||||
|
||||
JSAutoStructuredCloneBuffer mArguments;
|
||||
ConsoleStructuredCloneData mData;
|
||||
|
@ -566,6 +582,7 @@ private:
|
|||
return false;
|
||||
}
|
||||
|
||||
mArguments.Clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -959,7 +976,7 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
|
|||
const nsAString& aMethodString,
|
||||
const Sequence<JS::Value>& aData)
|
||||
{
|
||||
nsAutoPtr<ConsoleCallData> callData(new ConsoleCallData());
|
||||
nsRefPtr<ConsoleCallData> callData(new ConsoleCallData());
|
||||
|
||||
ClearException ce(aCx);
|
||||
|
||||
|
@ -1078,8 +1095,6 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
|
|||
return;
|
||||
}
|
||||
|
||||
// Note: we can pass the reference of callData because this runnable calls
|
||||
// ProcessCallData() synchronously.
|
||||
nsRefPtr<ConsoleCallDataRunnable> runnable =
|
||||
new ConsoleCallDataRunnable(this, callData);
|
||||
runnable->Dispatch();
|
||||
|
|
|
@ -80,6 +80,17 @@ public:
|
|||
Serialize(aRetval);
|
||||
}
|
||||
|
||||
typedef void (*ParamFunc)(const nsString& aName, const nsString& aValue,
|
||||
void* aClosure);
|
||||
|
||||
void
|
||||
ForEach(ParamFunc aFunc, void* aClosure)
|
||||
{
|
||||
for (uint32_t i = 0; i < mSearchParams.Length(); ++i) {
|
||||
aFunc(mSearchParams[i].mKey, mSearchParams[i].mValue, aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void AppendInternal(const nsAString& aName, const nsAString& aValue);
|
||||
|
||||
|
|
|
@ -17,11 +17,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345339
|
|||
src="http://mochi.test:8888/tests/dom/base/test/345339_iframe.html">
|
||||
</iframe>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
<script class="testbody" type="text/javascript;version=1.7">
|
||||
/** Test for Bug 345339 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var filePath;
|
||||
const testData = "Test data\n";
|
||||
let file = new File([testData],
|
||||
"345339_test.file",
|
||||
{ type: "text/plain" });
|
||||
|
||||
function afterLoad() {
|
||||
var iframeDoc = $("testframe").contentDocument;
|
||||
|
@ -32,15 +35,7 @@ function afterLoad() {
|
|||
iframeDoc.getElementById("password").value = "123456";
|
||||
iframeDoc.getElementById("hidden").value = "gecko";
|
||||
|
||||
var file = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIProperties)
|
||||
.get("TmpD", SpecialPowers.Ci.nsILocalFile);
|
||||
file.append("345339_test.file");
|
||||
// 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;
|
||||
SpecialPowers.wrap(iframeDoc).getElementById("file").mozSetFileArray([file]);
|
||||
|
||||
/* Reload the page */
|
||||
$("testframe").setAttribute("onload", "afterReload()");
|
||||
|
@ -62,10 +57,26 @@ function afterReload() {
|
|||
"password field value forgotten");
|
||||
is(iframeDoc.getElementById("hidden").value, "gecko",
|
||||
"hidden field value preserved");
|
||||
is(SpecialPowers.wrap(iframeDoc).getElementById("file").value, filePath,
|
||||
"file field value preserved");
|
||||
|
||||
SimpleTest.finish();
|
||||
// The new file object isn't ===, but it's extensionally equal:
|
||||
let newFile = iframeDoc.getElementById("file").files[0];
|
||||
for (let prop of ["name", "lastModified", "size", "type"]) {
|
||||
is(newFile[prop], file[prop],
|
||||
"file field " + prop + " property preserved");
|
||||
}
|
||||
let reader = new FileReader();
|
||||
reader.onloadend = function() {
|
||||
SimpleTest.finish();
|
||||
};
|
||||
reader.onload = function() {
|
||||
is(reader.result, testData,
|
||||
"file field contents preserved")
|
||||
};
|
||||
reader.onerror = function() {
|
||||
is(reader.error, null,
|
||||
"FileReader error");
|
||||
};
|
||||
reader.readAsText(newFile);
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -73,3 +73,4 @@ MSG_DEF(MSG_INVALID_RESPONSE_STATUSCODE_ERROR, 0, JSEXN_RANGEERR, "Invalid respo
|
|||
MSG_DEF(MSG_INVALID_REDIRECT_STATUSCODE_ERROR, 0, JSEXN_RANGEERR, "Invalid redirect status code.")
|
||||
MSG_DEF(MSG_INVALID_URL_SCHEME, 2, JSEXN_TYPEERR, "{0} URL {1} must be either http:// or https://.")
|
||||
MSG_DEF(MSG_RESPONSE_URL_IS_NULL, 0, JSEXN_TYPEERR, "Cannot set Response.finalURL when Response.url is null.")
|
||||
MSG_DEF(MSG_BAD_FORMDATA, 0, JSEXN_TYPEERR, "Could not parse content as FormData.")
|
||||
|
|
|
@ -176,6 +176,16 @@ BluetoothProfileController::SetupProfiles(bool aAssignServiceClass)
|
|||
bool isRemoteControl = IS_REMOTE_CONTROL(mTarget.cod);
|
||||
bool isKeyboard = IS_KEYBOARD(mTarget.cod);
|
||||
bool isPointingDevice = IS_POINTING_DEVICE(mTarget.cod);
|
||||
bool isInvalid = IS_INVALID_COD(mTarget.cod);
|
||||
|
||||
// The value of CoD is invalid. Since the device didn't declare its class of
|
||||
// device properly, we assume the device may support all of these profiles.
|
||||
if (isInvalid) {
|
||||
AddProfile(BluetoothHfpManager::Get());
|
||||
AddProfile(BluetoothA2dpManager::Get());
|
||||
AddProfile(BluetoothHidManager::Get());
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE_VOID(hasAudio || hasRendering || isPeripheral);
|
||||
|
||||
|
|
|
@ -53,6 +53,17 @@ BEGIN_BLUETOOTH_NAMESPACE
|
|||
// Pointing device: sub-field of minor device class (Bit 7)
|
||||
#define IS_POINTING_DEVICE(cod) ((GET_MINOR_DEVICE_CLASS(cod) & 0x20) >> 5)
|
||||
|
||||
/**
|
||||
* Check whether the value of CoD is invalid. (i.e. Bit 31 ~ Bit 24 != 0x0)
|
||||
*
|
||||
* According to Bluetooth core spec v4.1. Vol 2, Sec. 7.3, the data length of
|
||||
* CoD (class of device) is 3 bytes. The two least significant bits are used to
|
||||
* indicate 'format type'. The following 22 bits are used to indicate category
|
||||
* of service class and device type. The remaining 8 bits (Bit 31 ~ Bit 24)
|
||||
* should be unassigned bits, since BlueDroid uses uint32_t to store CoD.
|
||||
*/
|
||||
#define IS_INVALID_COD(cod) (cod >> 24)
|
||||
|
||||
class BluetoothProfileManagerBase;
|
||||
class BluetoothReplyRunnable;
|
||||
typedef void (*BluetoothProfileControllerCallback)();
|
||||
|
|
|
@ -173,6 +173,16 @@ BluetoothProfileController::SetupProfiles(bool aAssignServiceClass)
|
|||
bool isRemoteControl = IS_REMOTE_CONTROL(mTarget.cod);
|
||||
bool isKeyboard = IS_KEYBOARD(mTarget.cod);
|
||||
bool isPointingDevice = IS_POINTING_DEVICE(mTarget.cod);
|
||||
bool isInvalid = IS_INVALID_COD(mTarget.cod);
|
||||
|
||||
// The value of CoD is invalid. Since the device didn't declare its class of
|
||||
// device properly, we assume the device may support all of these profiles.
|
||||
if (isInvalid) {
|
||||
AddProfile(BluetoothHfpManager::Get());
|
||||
AddProfile(BluetoothA2dpManager::Get());
|
||||
AddProfile(BluetoothHidManager::Get());
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE_VOID(hasAudio || hasRendering || isPeripheral);
|
||||
|
||||
|
|
|
@ -53,6 +53,17 @@ BEGIN_BLUETOOTH_NAMESPACE
|
|||
// Pointing device: sub-field of minor device class (Bit 7)
|
||||
#define IS_POINTING_DEVICE(cod) ((GET_MINOR_DEVICE_CLASS(cod) & 0x20) >> 5)
|
||||
|
||||
/**
|
||||
* Check whether the value of CoD is invalid. (i.e. Bit 31 ~ Bit 24 != 0x0)
|
||||
*
|
||||
* According to Bluetooth core spec v4.1. Vol 2, Sec. 7.3, the data length of
|
||||
* CoD (class of device) is 3 bytes. The two least significant bits are used to
|
||||
* indicate 'format type'. The following 22 bits are used to indicate category
|
||||
* of service class and device type. The remaining 8 bits (Bit 31 ~ Bit 24)
|
||||
* should be unassigned bits, since BlueDroid uses uint32_t to store CoD.
|
||||
*/
|
||||
#define IS_INVALID_COD(cod) (cod >> 24)
|
||||
|
||||
class BluetoothProfileManagerBase;
|
||||
class BluetoothReplyRunnable;
|
||||
typedef void (*BluetoothProfileControllerCallback)();
|
||||
|
|
|
@ -56,53 +56,68 @@ GetOrigin(nsIPrincipal* aPrincipal, nsAString& aOrigin, ErrorResult& aRv)
|
|||
{
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
|
||||
uint16_t appStatus = aPrincipal->GetAppStatus();
|
||||
bool unknownAppId;
|
||||
aRv = aPrincipal->GetUnknownAppId(&unknownAppId);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (appStatus == nsIPrincipal::APP_STATUS_NOT_INSTALLED) {
|
||||
nsAutoString tmp;
|
||||
aRv = nsContentUtils::GetUTFOrigin(aPrincipal, tmp);
|
||||
if (!unknownAppId) {
|
||||
uint32_t appId;
|
||||
aRv = aPrincipal->GetAppId(&appId);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
aOrigin = tmp;
|
||||
if (aOrigin.EqualsASCII("null")) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aRv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
if (appId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
// If we are in "app code", use manifest URL as unique origin since
|
||||
// multiple apps can share the same origin but not same broadcast
|
||||
// messages.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIAppsService> appsService =
|
||||
do_GetService("@mozilla.org/AppsService;1", &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!uri)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString spec;
|
||||
aRv = uri->GetSpec(spec);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
aOrigin = NS_ConvertUTF8toUTF16(spec);
|
||||
appsService->GetManifestURLByLocalId(appId, aOrigin);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString tmp;
|
||||
aRv = nsContentUtils::GetUTFOrigin(aPrincipal, tmp);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t appId = aPrincipal->GetAppId();
|
||||
// 'null' means an unknown origin (it can be chrome code or it can be some
|
||||
// about: page).
|
||||
|
||||
// If we are in "app code", use manifest URL as unique origin since
|
||||
// multiple apps can share the same origin but not same broadcast messages.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIAppsService> appsService =
|
||||
do_GetService("@mozilla.org/AppsService;1", &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(rv);
|
||||
aOrigin = tmp;
|
||||
if (!aOrigin.EqualsASCII("null")) {
|
||||
return;
|
||||
}
|
||||
|
||||
appsService->GetManifestURLByLocalId(appId, aOrigin);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aRv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!uri)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString spec;
|
||||
aRv = uri->GetSpec(spec);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
aOrigin = NS_ConvertUTF8toUTF16(spec);
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[DEFAULT]
|
||||
skip-if = buildapp == 'b2g'
|
||||
skip-if = e10s || buildapp == 'b2g'
|
||||
support-files =
|
||||
blank.html
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>MozBrowser iframe</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.src = 'http://mochi.test:8888/tests/dom/broadcastchannel/tests/iframe_mozbrowser.html';
|
||||
ifr.onload = function() { alert('DONE'); }
|
||||
|
||||
var domParent = document.getElementById('container');
|
||||
domParent.appendChild(ifr);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>MozBrowser iframe</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', true);
|
||||
ifr.src = 'http://mochi.test:8888/tests/dom/broadcastchannel/tests/iframe_mozbrowser2.html';
|
||||
ifr.onload = function() { alert('DONE'); }
|
||||
|
||||
var domParent = document.getElementById('container');
|
||||
domParent.appendChild(ifr);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>MozBrowser iframe</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var bc = new BroadcastChannel('foobar');
|
||||
bc.postMessage('This is wrong!');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>MozBrowser iframe</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var bc = new BroadcastChannel('foobar');
|
||||
bc.postMessage('This is wrong!');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "BroadcastChannel",
|
||||
"description": "BroadcastChannel app",
|
||||
"launch_path": "/tests/dom/broadcastchannel/tests/TESTTOKEN",
|
||||
"icons": { "128": "default_icon" }
|
||||
}
|
|
@ -6,6 +6,12 @@ support-files =
|
|||
broadcastchannel_worker.js
|
||||
broadcastchannel_worker_alive.js
|
||||
broadcastchannel_worker_any.js
|
||||
file_mozbrowser.html
|
||||
file_mozbrowser2.html
|
||||
iframe_mozbrowser.html
|
||||
iframe_mozbrowser2.html
|
||||
server.sjs
|
||||
manifest.webapp
|
||||
|
||||
[test_broadcastchannel_any.html]
|
||||
[test_broadcastchannel_basic.html]
|
||||
|
@ -15,3 +21,7 @@ support-files =
|
|||
[test_broadcastchannel_sharedWorker.html]
|
||||
[test_broadcastchannel_worker.html]
|
||||
[test_broadcastchannel_worker_alive.html]
|
||||
[test_broadcastchannel_mozbrowser.html]
|
||||
skip-if = e10s || buildapp == 'b2g'
|
||||
[test_broadcastchannel_mozbrowser2.html]
|
||||
skip-if = e10s || buildapp == 'b2g'
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
var gBasePath = "tests/dom/broadcastchannel/tests/";
|
||||
|
||||
function handleRequest(request, response) {
|
||||
var query = getQuery(request);
|
||||
|
||||
var testToken = '';
|
||||
if ('testToken' in query) {
|
||||
testToken = query.testToken;
|
||||
}
|
||||
|
||||
var template = 'manifest.webapp';
|
||||
if ('template' in query) {
|
||||
template = query.template;
|
||||
}
|
||||
var template = gBasePath + template;
|
||||
response.setHeader("Content-Type", "application/x-web-app-manifest+json", false);
|
||||
response.write(readTemplate(template).replace(/TESTTOKEN/g, testToken));
|
||||
}
|
||||
|
||||
// Copy-pasted incantations. There ought to be a better way to synchronously read
|
||||
// a file into a string, but I guess we're trying to discourage that.
|
||||
function readTemplate(path) {
|
||||
var file = Components.classes["@mozilla.org/file/directory_service;1"].
|
||||
getService(Components.interfaces.nsIProperties).
|
||||
get("CurWorkD", Components.interfaces.nsILocalFile);
|
||||
var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
|
||||
createInstance(Components.interfaces.nsIFileInputStream);
|
||||
var cis = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
|
||||
createInstance(Components.interfaces.nsIConverterInputStream);
|
||||
var split = path.split("/");
|
||||
for(var i = 0; i < split.length; ++i) {
|
||||
file.append(split[i]);
|
||||
}
|
||||
fis.init(file, -1, -1, false);
|
||||
cis.init(fis, "UTF-8", 0, 0);
|
||||
|
||||
var data = "";
|
||||
let str = {};
|
||||
let read = 0;
|
||||
do {
|
||||
read = cis.readString(0xffffffff, str); // read as much as we can and put it in str.value
|
||||
data += str.value;
|
||||
} while (read != 0);
|
||||
cis.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
function getQuery(request) {
|
||||
var query = {};
|
||||
request.queryString.split('&').forEach(function (val) {
|
||||
var [name, value] = val.split('=');
|
||||
query[name] = unescape(value);
|
||||
});
|
||||
return query;
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for BroadcastChannel - iframe mozbrowser</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="container"></div>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
var gHostedManifestURL = 'http://test/tests/dom/broadcastchannel/tests/server.sjs?testToken=file_mozbrowser.html';
|
||||
var gApp;
|
||||
|
||||
function cbError() {
|
||||
ok(false, "Error callback invoked");
|
||||
finish();
|
||||
}
|
||||
|
||||
function createBC() {
|
||||
var bc = new BroadcastChannel('foobar');
|
||||
bc.onmessage = function(e) {
|
||||
is(e.data, "Done!", "A message has been received!");
|
||||
nextStep();
|
||||
}
|
||||
|
||||
nextStep();
|
||||
}
|
||||
|
||||
function completeOperation() {
|
||||
var bc = new BroadcastChannel('foobar');
|
||||
bc.postMessage("Done!");
|
||||
}
|
||||
|
||||
function installApp() {
|
||||
var request = navigator.mozApps.install(gHostedManifestURL);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
gApp = request.result;
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
function uninstallApp() {
|
||||
// Uninstall the app.
|
||||
var request = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
// All done.
|
||||
info("All done");
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
function testApp() {
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', gApp.manifestURL);
|
||||
ifr.setAttribute('src', gApp.manifest.launch_path);
|
||||
var domParent = document.getElementById('container');
|
||||
|
||||
// Set us up to listen for messages from the app.
|
||||
var listener = function(e) {
|
||||
ok(true, "Messaging from app complete");
|
||||
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
domParent.removeChild(ifr);
|
||||
nextStep();
|
||||
}
|
||||
|
||||
// This event is triggered when the app calls "alert".
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
|
||||
domParent.appendChild(ifr);
|
||||
}
|
||||
|
||||
var steps = [
|
||||
// Permissions
|
||||
function() {
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ "type": "browser", "allow": 1, "context": document },
|
||||
{ "type": "embed-apps", "allow": 1, "context": document },
|
||||
{ "type": "webapps-manage", "allow": 1, "context": document }], nextStep);
|
||||
},
|
||||
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true],
|
||||
["network.disable.ipc.security", true],
|
||||
["browser.pagethumbnails.capturing_disabled", true],
|
||||
["dom.mozBrowserFramesEnabled", true],
|
||||
["dom.ipc.browser_frames.oop_by_default", false],
|
||||
["dom.ipc.tabs.disabled", false],
|
||||
["dom.testing.ignore_ipc_principal", true],
|
||||
["security.mixed_content.block_active_content", false]]},
|
||||
nextStep);
|
||||
},
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(nextStep));
|
||||
},
|
||||
|
||||
createBC,
|
||||
|
||||
// Installing the app
|
||||
installApp,
|
||||
|
||||
// Run tests in app
|
||||
testApp,
|
||||
|
||||
// Uninstall the app
|
||||
uninstallApp,
|
||||
|
||||
// finish
|
||||
completeOperation
|
||||
];
|
||||
|
||||
function finish() {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function nextStep() {
|
||||
if (!steps.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var step = steps.shift();
|
||||
step();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
nextStep();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,137 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for BroadcastChannel - iframe mozbrowser</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="container"></div>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
var gHostedManifestURL = 'http://test/tests/dom/broadcastchannel/tests/server.sjs?testToken=file_mozbrowser2.html';
|
||||
var gApp;
|
||||
|
||||
function cbError() {
|
||||
ok(false, "Error callback invoked");
|
||||
finish();
|
||||
}
|
||||
|
||||
function createBC() {
|
||||
var bc = new BroadcastChannel('foobar');
|
||||
bc.onmessage = function(e) {
|
||||
is(e.data, "Done!", "A message has been received!");
|
||||
nextStep();
|
||||
}
|
||||
|
||||
nextStep();
|
||||
}
|
||||
|
||||
function completeOperation() {
|
||||
var bc = new BroadcastChannel('foobar');
|
||||
bc.postMessage("Done!");
|
||||
}
|
||||
|
||||
function installApp() {
|
||||
var request = navigator.mozApps.install(gHostedManifestURL);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
gApp = request.result;
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
function uninstallApp() {
|
||||
// Uninstall the app.
|
||||
var request = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
// All done.
|
||||
info("All done");
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
function testApp() {
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', gApp.manifestURL);
|
||||
ifr.setAttribute('src', gApp.manifest.launch_path);
|
||||
var domParent = document.getElementById('container');
|
||||
|
||||
// Set us up to listen for messages from the app.
|
||||
var listener = function(e) {
|
||||
ok(true, "Messaging from app complete");
|
||||
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
domParent.removeChild(ifr);
|
||||
nextStep();
|
||||
}
|
||||
|
||||
// This event is triggered when the app calls "alert".
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
|
||||
domParent.appendChild(ifr);
|
||||
}
|
||||
|
||||
var steps = [
|
||||
// Permissions
|
||||
function() {
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ "type": "browser", "allow": 1, "context": document },
|
||||
{ "type": "embed-apps", "allow": 1, "context": document },
|
||||
{ "type": "webapps-manage", "allow": 1, "context": document }], nextStep);
|
||||
},
|
||||
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true],
|
||||
["network.disable.ipc.security", true],
|
||||
["browser.pagethumbnails.capturing_disabled", true],
|
||||
["dom.mozBrowserFramesEnabled", true],
|
||||
["dom.ipc.browser_frames.oop_by_default", false],
|
||||
["dom.ipc.tabs.disabled", false],
|
||||
["dom.testing.ignore_ipc_principal", true],
|
||||
["security.mixed_content.block_active_content", false]]},
|
||||
nextStep);
|
||||
},
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(nextStep));
|
||||
},
|
||||
|
||||
createBC,
|
||||
|
||||
// Installing the app
|
||||
installApp,
|
||||
|
||||
// Run tests in app
|
||||
testApp,
|
||||
|
||||
// Uninstall the app
|
||||
uninstallApp,
|
||||
|
||||
// finish
|
||||
completeOperation
|
||||
];
|
||||
|
||||
function finish() {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function nextStep() {
|
||||
if (!steps.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var step = steps.shift();
|
||||
step();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
nextStep();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -172,6 +172,11 @@ BrowserElementChild.prototype = {
|
|||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
addEventListener('click',
|
||||
this._ClickHandler.bind(this),
|
||||
/* useCapture = */ false,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
// This listens to unload events from our message manager, but /not/ from
|
||||
// the |content| window. That's because the window's unload event doesn't
|
||||
// bubble, and we're not using a capturing listener. If we'd used
|
||||
|
@ -579,6 +584,18 @@ BrowserElementChild.prototype = {
|
|||
sendAsyncMsg('scrollviewchange', detail);
|
||||
},
|
||||
|
||||
_ClickHandler: function(e) {
|
||||
let elem = e.target;
|
||||
if (elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) {
|
||||
// Open in a new tab if middle click or ctrl/cmd-click.
|
||||
if ((Services.appinfo.OS == 'Darwin' && e.metaKey) ||
|
||||
(Services.appinfo.OS != 'Darwin' && e.ctrlKey) ||
|
||||
e.button == 1) {
|
||||
sendAsyncMsg('opentab', {url: elem.href});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_selectionStateChangedHandler: function(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
|
@ -1085,7 +1102,7 @@ BrowserElementChild.prototype = {
|
|||
|
||||
_updateVisibility: function() {
|
||||
var visible = this._forcedVisible && this._ownerVisible;
|
||||
if (docShell.isActive !== visible) {
|
||||
if (docShell && docShell.isActive !== visible) {
|
||||
docShell.isActive = visible;
|
||||
sendAsyncMsg('visibilitychange', {visible: visible});
|
||||
}
|
||||
|
|
|
@ -214,7 +214,8 @@ BrowserElementParent.prototype = {
|
|||
"metachange": this._fireEventFromMsg,
|
||||
"resize": this._fireEventFromMsg,
|
||||
"activitydone": this._fireEventFromMsg,
|
||||
"scroll": this._fireEventFromMsg
|
||||
"scroll": this._fireEventFromMsg,
|
||||
"opentab": this._fireEventFromMsg
|
||||
};
|
||||
|
||||
this._mm.addMessageListener('browser-element-api:call', function(aMsg) {
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/* Any copyright is dedicated to the public domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Bug 1144015 - test middle/ctrl/cmd-click on a link.
|
||||
|
||||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
function runTest() {
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
let x = 2;
|
||||
let y = 2;
|
||||
// First we force a reflow so that getChildProcessOffset actually returns
|
||||
// meaningful data.
|
||||
iframe.getBoundingClientRect();
|
||||
// We need to make sure the event coordinates are actually inside the iframe,
|
||||
// relative to the chome window.
|
||||
let tabParent = SpecialPowers.wrap(iframe)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader.tabParent;
|
||||
if (tabParent) {
|
||||
let offsetX = {};
|
||||
let offsetY = {};
|
||||
tabParent.getChildProcessOffset(offsetX, offsetY);
|
||||
x -= offsetX.value;
|
||||
y -= offsetY.value;
|
||||
}
|
||||
|
||||
let sendCtrlClick = () => {
|
||||
let nsIDOMWindowUtils = SpecialPowers.Ci.nsIDOMWindowUtils;
|
||||
let mod = nsIDOMWindowUtils.MODIFIER_META |
|
||||
nsIDOMWindowUtils.MODIFIER_CONTROL;
|
||||
iframe.sendMouseEvent('mousedown', x, y, 0, 1, mod);
|
||||
iframe.sendMouseEvent('mouseup', x, y, 0, 1, mod);
|
||||
}
|
||||
|
||||
let onCtrlClick = e => {
|
||||
is(e.detail.url, 'http://example.com/', 'URL matches');
|
||||
iframe.removeEventListener('mozbrowseropentab', onCtrlClick);
|
||||
iframe.addEventListener('mozbrowseropentab', onMiddleClick);
|
||||
sendMiddleClick();
|
||||
}
|
||||
|
||||
let sendMiddleClick = () => {
|
||||
iframe.sendMouseEvent('mousedown', x, y, 1, 1, 0);
|
||||
iframe.sendMouseEvent('mouseup', x, y, 1, 1, 0);
|
||||
}
|
||||
|
||||
let onMiddleClick= e => {
|
||||
is(e.detail.url, 'http://example.com/', 'URL matches');
|
||||
iframe.removeEventListener('mozbrowseropentab', onMiddleClick);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
iframe.addEventListener('mozbrowserloadend', e => {
|
||||
iframe.addEventListener('mozbrowseropentab', onCtrlClick);
|
||||
sendCtrlClick();
|
||||
});
|
||||
|
||||
|
||||
iframe.src = 'data:text/html,<body style="margin:0"><a href="http://example.com">click here</a></body>';
|
||||
}
|
||||
|
||||
addEventListener('testready', runTest);
|
|
@ -7,6 +7,7 @@ skip-if = os == "android" || (toolkit == "cocoa" && debug) || buildapp == 'mulet
|
|||
support-files =
|
||||
browserElement_OpenMixedProcess.js
|
||||
file_browserElement_OpenMixedProcess.html
|
||||
browserElement_OpenTab.js
|
||||
|
||||
[test_browserElement_oop_ThemeColor.html]
|
||||
[test_browserElement_inproc_ErrorSecurity.html]
|
||||
|
@ -60,6 +61,8 @@ skip-if = (toolkit == 'gonk' && !debug)
|
|||
[test_browserElement_oop_OpenWindowRejected.html]
|
||||
skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_browserElement_oop_Opensearch.html]
|
||||
[test_browserElement_oop_OpenTab.html]
|
||||
skip-if = (toolkit == 'gonk') # Disabled on emulator. See bug 1144015 comment 8
|
||||
[test_browserElement_oop_PrivateBrowsing.html]
|
||||
[test_browserElement_oop_PromptCheck.html]
|
||||
[test_browserElement_oop_PromptConfirm.html]
|
||||
|
|
|
@ -38,6 +38,7 @@ support-files =
|
|||
browserElement_Metachange.js
|
||||
browserElement_NextPaint.js
|
||||
browserElement_OpenNamed.js
|
||||
browserElement_OpenTab.js
|
||||
browserElement_OpenWindow.js
|
||||
browserElement_OpenWindowDifferentOrigin.js
|
||||
browserElement_OpenWindowInFrame.js
|
||||
|
@ -168,6 +169,8 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
|
|||
[test_browserElement_inproc_NextPaint.html]
|
||||
[test_browserElement_inproc_OpenNamed.html]
|
||||
skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_browserElement_inproc_OpenTab.html]
|
||||
disabled = won't work as Firefox desktop will intercept ctrl-click
|
||||
[test_browserElement_inproc_OpenWindow.html]
|
||||
skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_browserElement_inproc_OpenWindowDifferentOrigin.html]
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1144015
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1144015</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1144015">Mozilla Bug 1144015</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src="browserElement_OpenTab.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1144015
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1144015</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1144015">Mozilla Bug 1144015</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src="browserElement_OpenTab.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -113,6 +113,7 @@
|
|||
#include "nsSVGLength2.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "Units.h"
|
||||
|
||||
#undef free // apparently defined by some windows header, clashing with a free()
|
||||
// method in SkTypes.h
|
||||
|
@ -1349,7 +1350,9 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
|||
}
|
||||
|
||||
if (layerManager) {
|
||||
if (mode == RenderingMode::OpenGLBackendMode && CheckSizeForSkiaGL(size)) {
|
||||
if (mode == RenderingMode::OpenGLBackendMode &&
|
||||
gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas() &&
|
||||
CheckSizeForSkiaGL(size)) {
|
||||
DemoteOldestContextIfNecessary();
|
||||
|
||||
#if USE_SKIA_GPU
|
||||
|
@ -4461,7 +4464,8 @@ CanvasRenderingContext2D::DrawDirectlyToCanvas(
|
|||
// FLAG_CLAMP is added for increased performance, since we never tile here.
|
||||
uint32_t modifiedFlags = image.mDrawingFlags | imgIContainer::FLAG_CLAMP;
|
||||
|
||||
SVGImageContext svgContext(scaledImageSize, Nothing(), CurrentState().globalAlpha);
|
||||
CSSIntSize sz(scaledImageSize.width, scaledImageSize.height); // XXX hmm is scaledImageSize really in CSS pixels?
|
||||
SVGImageContext svgContext(sz, Nothing(), CurrentState().globalAlpha);
|
||||
|
||||
auto result = image.mImgContainer->
|
||||
Draw(context, scaledImageSize,
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
#include "nsIUnicodeDecoder.h"
|
||||
#include "nsIUnicodeEncoder.h"
|
||||
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsDOMString.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsStringStream.h"
|
||||
|
||||
|
@ -515,6 +517,382 @@ ExtractFromURLSearchParams(const URLSearchParams& aParams,
|
|||
aContentType = NS_LITERAL_CSTRING("application/x-www-form-urlencoded;charset=UTF-8");
|
||||
return NS_NewStringInputStream(aStream, serialized);
|
||||
}
|
||||
|
||||
void
|
||||
FillFormData(const nsString& aName, const nsString& aValue, void* aFormData)
|
||||
{
|
||||
MOZ_ASSERT(aFormData);
|
||||
nsFormData* fd = static_cast<nsFormData*>(aFormData);
|
||||
fd->Append(aName, aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple multipart/form-data parser as defined in RFC 2388 and RFC 2046.
|
||||
* This does not respect any encoding specified per entry, using UTF-8
|
||||
* throughout. This is as the Fetch spec states in the consume body algorithm.
|
||||
* Borrows some things from Necko's nsMultiMixedConv, but is simpler since
|
||||
* unlike Necko we do not have to deal with receiving incomplete chunks of data.
|
||||
*
|
||||
* This parser will fail the entire parse on any invalid entry, so it will
|
||||
* never return a partially filled FormData.
|
||||
* The content-disposition header is used to figure out the name and filename
|
||||
* entries. The inclusion of the filename parameter decides if the entry is
|
||||
* inserted into the nsFormData as a string or a File.
|
||||
*
|
||||
* File blobs are copies of the underlying data string since we cannot adopt
|
||||
* char* chunks embedded within the larger body without significant effort.
|
||||
* FIXME(nsm): Bug 1127552 - We should add telemetry to calls to formData() and
|
||||
* friends to figure out if Fetch ends up copying big blobs to see if this is
|
||||
* worth optimizing.
|
||||
*/
|
||||
class MOZ_STACK_CLASS FormDataParser
|
||||
{
|
||||
private:
|
||||
nsRefPtr<nsFormData> mFormData;
|
||||
nsCString mMimeType;
|
||||
nsCString mData;
|
||||
|
||||
// Entry state, reset in START_PART.
|
||||
nsCString mName;
|
||||
nsCString mFilename;
|
||||
nsCString mContentType;
|
||||
|
||||
enum
|
||||
{
|
||||
START_PART,
|
||||
PARSE_HEADER,
|
||||
PARSE_BODY,
|
||||
} mState;
|
||||
|
||||
nsIGlobalObject* mParentObject;
|
||||
|
||||
// Reads over a boundary and sets start to the position after the end of the
|
||||
// boundary. Returns false if no boundary is found immediately.
|
||||
bool
|
||||
PushOverBoundary(const nsACString& aBoundaryString,
|
||||
nsACString::const_iterator& aStart,
|
||||
nsACString::const_iterator& aEnd)
|
||||
{
|
||||
// We copy the end iterator to keep the original pointing to the real end
|
||||
// of the string.
|
||||
nsACString::const_iterator end(aEnd);
|
||||
const char* beginning = aStart.get();
|
||||
if (FindInReadable(aBoundaryString, aStart, end)) {
|
||||
// We either should find the body immediately, or after 2 chars with the
|
||||
// 2 chars being '-', everything else is failure.
|
||||
if ((aStart.get() - beginning) == 0) {
|
||||
aStart.advance(aBoundaryString.Length());
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((aStart.get() - beginning) == 2) {
|
||||
if (*(--aStart) == '-' && *(--aStart) == '-') {
|
||||
aStart.advance(aBoundaryString.Length() + 2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reads over a CRLF and positions start after it.
|
||||
bool
|
||||
PushOverLine(nsACString::const_iterator& aStart)
|
||||
{
|
||||
if (*aStart == nsCRT::CR && (aStart.size_forward() > 1) && *(++aStart) == nsCRT::LF) {
|
||||
++aStart; // advance to after CRLF
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
FindCRLF(nsACString::const_iterator& aStart,
|
||||
nsACString::const_iterator& aEnd)
|
||||
{
|
||||
nsACString::const_iterator end(aEnd);
|
||||
return FindInReadable(NS_LITERAL_CSTRING("\r\n"), aStart, end);
|
||||
}
|
||||
|
||||
bool
|
||||
ParseHeader(nsACString::const_iterator& aStart,
|
||||
nsACString::const_iterator& aEnd,
|
||||
bool* aWasEmptyHeader)
|
||||
{
|
||||
MOZ_ASSERT(aWasEmptyHeader);
|
||||
// Set it to a valid value here so we don't forget later.
|
||||
*aWasEmptyHeader = false;
|
||||
|
||||
const char* beginning = aStart.get();
|
||||
nsACString::const_iterator end(aEnd);
|
||||
if (!FindCRLF(aStart, end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aStart.get() == beginning) {
|
||||
*aWasEmptyHeader = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
nsAutoCString header(beginning, aStart.get() - beginning);
|
||||
|
||||
nsACString::const_iterator headerStart, headerEnd;
|
||||
header.BeginReading(headerStart);
|
||||
header.EndReading(headerEnd);
|
||||
if (!FindCharInReadable(':', headerStart, headerEnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString headerName(StringHead(header, headerStart.size_backward()));
|
||||
headerName.CompressWhitespace();
|
||||
if (!NS_IsValidHTTPToken(headerName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString headerValue(Substring(++headerStart, headerEnd));
|
||||
if (!NS_IsReasonableHTTPHeaderValue(headerValue)) {
|
||||
return false;
|
||||
}
|
||||
headerValue.CompressWhitespace();
|
||||
|
||||
if (headerName.LowerCaseEqualsLiteral("content-disposition")) {
|
||||
nsCCharSeparatedTokenizer tokenizer(headerValue, ';');
|
||||
bool seenFormData = false;
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsDependentCSubstring& token = tokenizer.nextToken();
|
||||
if (token.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token.EqualsLiteral("form-data")) {
|
||||
seenFormData = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (seenFormData &&
|
||||
StringBeginsWith(token, NS_LITERAL_CSTRING("name="))) {
|
||||
mName = StringTail(token, token.Length() - 5);
|
||||
mName.Trim(" \"");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (seenFormData &&
|
||||
StringBeginsWith(token, NS_LITERAL_CSTRING("filename="))) {
|
||||
mFilename = StringTail(token, token.Length() - 9);
|
||||
mFilename.Trim(" \"");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (mName.IsVoid()) {
|
||||
// Could not parse a valid entry name.
|
||||
return false;
|
||||
}
|
||||
} else if (headerName.LowerCaseEqualsLiteral("content-type")) {
|
||||
mContentType = headerValue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// The end of a body is marked by a CRLF followed by the boundary. So the
|
||||
// CRLF is part of the boundary and not the body, but any prior CRLFs are
|
||||
// part of the body. This will position the iterator at the beginning of the
|
||||
// boundary (after the CRLF).
|
||||
bool
|
||||
ParseBody(const nsACString& aBoundaryString,
|
||||
nsACString::const_iterator& aStart,
|
||||
nsACString::const_iterator& aEnd)
|
||||
{
|
||||
const char* beginning = aStart.get();
|
||||
|
||||
// Find the boundary marking the end of the body.
|
||||
nsACString::const_iterator end(aEnd);
|
||||
if (!FindInReadable(aBoundaryString, aStart, end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We found a boundary, strip the just prior CRLF, and consider
|
||||
// everything else the body section.
|
||||
if (aStart.get() - beginning < 2) {
|
||||
// Only the first entry can have a boundary right at the beginning. Even
|
||||
// an empty body will have a CRLF before the boundary. So this is
|
||||
// a failure.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that there is a CRLF right before the boundary.
|
||||
aStart.advance(-2);
|
||||
|
||||
// Skip optional hyphens.
|
||||
if (*aStart == '-' && *(aStart.get()+1) == '-') {
|
||||
if (aStart.get() - beginning < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aStart.advance(-2);
|
||||
}
|
||||
|
||||
if (*aStart != nsCRT::CR || *(aStart.get()+1) != nsCRT::LF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString body(beginning, aStart.get() - beginning);
|
||||
|
||||
// Restore iterator to after the \r\n as we promised.
|
||||
// We do not need to handle the extra hyphens case since our boundary
|
||||
// parser in PushOverBoundary()
|
||||
aStart.advance(2);
|
||||
|
||||
if (!mFormData) {
|
||||
mFormData = new nsFormData();
|
||||
}
|
||||
|
||||
NS_ConvertUTF8toUTF16 name(mName);
|
||||
|
||||
if (mFilename.IsVoid()) {
|
||||
mFormData->Append(name, NS_ConvertUTF8toUTF16(body));
|
||||
} else {
|
||||
// Unfortunately we've to copy the data first since all our strings are
|
||||
// going to free it. We also need fallible alloc, so we can't just use
|
||||
// ToNewCString().
|
||||
char* copy = static_cast<char*>(NS_Alloc(body.Length()));
|
||||
if (!copy) {
|
||||
NS_WARNING("Failed to copy File entry body.");
|
||||
return false;
|
||||
}
|
||||
nsCString::const_iterator bodyIter, bodyEnd;
|
||||
body.BeginReading(bodyIter);
|
||||
body.EndReading(bodyEnd);
|
||||
char *p = copy;
|
||||
while (bodyIter != bodyEnd) {
|
||||
*p++ = *bodyIter++;
|
||||
}
|
||||
p = nullptr;
|
||||
|
||||
nsRefPtr<File> file =
|
||||
File::CreateMemoryFile(mParentObject,
|
||||
reinterpret_cast<void *>(copy), body.Length(),
|
||||
NS_ConvertUTF8toUTF16(mFilename),
|
||||
NS_ConvertUTF8toUTF16(mContentType), /* aLastModifiedDate */ 0);
|
||||
Optional<nsAString> dummy;
|
||||
mFormData->Append(name, *file, dummy);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
FormDataParser(const nsACString& aMimeType, const nsACString& aData, nsIGlobalObject* aParent)
|
||||
: mMimeType(aMimeType), mData(aData), mState(START_PART), mParentObject(aParent)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Parse()
|
||||
{
|
||||
// Determine boundary from mimetype.
|
||||
const char* boundaryId = nullptr;
|
||||
boundaryId = strstr(mMimeType.BeginWriting(), "boundary");
|
||||
if (!boundaryId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boundaryId = strchr(boundaryId, '=');
|
||||
if (!boundaryId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip over '='.
|
||||
boundaryId++;
|
||||
|
||||
char *attrib = (char *) strchr(boundaryId, ';');
|
||||
if (attrib) *attrib = '\0';
|
||||
|
||||
nsAutoCString boundaryString(boundaryId);
|
||||
if (attrib) *attrib = ';';
|
||||
|
||||
boundaryString.Trim(" \"");
|
||||
|
||||
if (boundaryString.Length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsACString::const_iterator start, end;
|
||||
mData.BeginReading(start);
|
||||
// This should ALWAYS point to the end of data.
|
||||
// Helpers make copies.
|
||||
mData.EndReading(end);
|
||||
|
||||
while (start != end) {
|
||||
switch(mState) {
|
||||
case START_PART:
|
||||
mName.SetIsVoid(true);
|
||||
mFilename.SetIsVoid(true);
|
||||
mContentType = NS_LITERAL_CSTRING("text/plain");
|
||||
|
||||
// MUST start with boundary.
|
||||
if (!PushOverBoundary(boundaryString, start, end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (start != end && *start == '-') {
|
||||
// End of data.
|
||||
if (!mFormData) {
|
||||
mFormData = new nsFormData();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!PushOverLine(start)) {
|
||||
return false;
|
||||
}
|
||||
mState = PARSE_HEADER;
|
||||
break;
|
||||
|
||||
case PARSE_HEADER:
|
||||
bool emptyHeader;
|
||||
if (!ParseHeader(start, end, &emptyHeader)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PushOverLine(start)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mState = emptyHeader ? PARSE_BODY : PARSE_HEADER;
|
||||
break;
|
||||
|
||||
case PARSE_BODY:
|
||||
if (mName.IsVoid()) {
|
||||
NS_WARNING("No content-disposition header with a valid name was "
|
||||
"found. Failing at body parse.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ParseBody(boundaryString, start, end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mState = START_PART;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Invalid case");
|
||||
}
|
||||
}
|
||||
|
||||
NS_NOTREACHED("Should never reach here.");
|
||||
return false;
|
||||
}
|
||||
|
||||
already_AddRefed<nsFormData> FormData()
|
||||
{
|
||||
return mFormData.forget();
|
||||
}
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
nsresult
|
||||
|
@ -1142,6 +1520,56 @@ FetchBody<Derived>::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength
|
|||
autoFree.Reset();
|
||||
return;
|
||||
}
|
||||
case CONSUME_FORMDATA: {
|
||||
nsCString data;
|
||||
data.Adopt(reinterpret_cast<char*>(aResult), aResultLength);
|
||||
autoFree.Reset();
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(formDataMimeType, NS_LITERAL_CSTRING("multipart/form-data"));
|
||||
|
||||
// Allow semicolon separated boundary/encoding suffix like multipart/form-data; boundary=
|
||||
// but disallow multipart/form-datafoobar.
|
||||
bool isValidFormDataMimeType = StringBeginsWith(mMimeType, formDataMimeType);
|
||||
|
||||
if (isValidFormDataMimeType && mMimeType.Length() > formDataMimeType.Length()) {
|
||||
isValidFormDataMimeType = mMimeType[formDataMimeType.Length()] == ';';
|
||||
}
|
||||
|
||||
if (isValidFormDataMimeType) {
|
||||
FormDataParser parser(mMimeType, data, DerivedClass()->GetParentObject());
|
||||
if (!parser.Parse()) {
|
||||
ErrorResult result;
|
||||
result.ThrowTypeError(MSG_BAD_FORMDATA);
|
||||
localPromise->MaybeReject(result);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<nsFormData> fd = parser.FormData();
|
||||
MOZ_ASSERT(fd);
|
||||
localPromise->MaybeResolve(fd);
|
||||
} else {
|
||||
NS_NAMED_LITERAL_CSTRING(urlDataMimeType, NS_LITERAL_CSTRING("application/x-www-form-urlencoded"));
|
||||
bool isValidUrlEncodedMimeType = StringBeginsWith(mMimeType, urlDataMimeType);
|
||||
|
||||
if (isValidUrlEncodedMimeType && mMimeType.Length() > urlDataMimeType.Length()) {
|
||||
isValidUrlEncodedMimeType = mMimeType[urlDataMimeType.Length()] == ';';
|
||||
}
|
||||
|
||||
if (isValidUrlEncodedMimeType) {
|
||||
nsRefPtr<URLSearchParams> params = new URLSearchParams();
|
||||
params->ParseInput(data, /* aObserver */ nullptr);
|
||||
|
||||
nsRefPtr<nsFormData> fd = new nsFormData(DerivedClass()->GetParentObject());
|
||||
params->ForEach(FillFormData, static_cast<void*>(fd));
|
||||
localPromise->MaybeResolve(fd);
|
||||
} else {
|
||||
ErrorResult result;
|
||||
result.ThrowTypeError(MSG_BAD_FORMDATA);
|
||||
localPromise->MaybeReject(result);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case CONSUME_TEXT:
|
||||
// fall through handles early exit.
|
||||
case CONSUME_JSON: {
|
||||
|
@ -1216,15 +1644,15 @@ FetchBody<Response>::ConsumeBody(ConsumeType aType, ErrorResult& aRv);
|
|||
|
||||
template <class Derived>
|
||||
void
|
||||
FetchBody<Derived>::SetMimeType(ErrorResult& aRv)
|
||||
FetchBody<Derived>::SetMimeType()
|
||||
{
|
||||
// Extract mime type.
|
||||
ErrorResult result;
|
||||
nsTArray<nsCString> contentTypeValues;
|
||||
MOZ_ASSERT(DerivedClass()->GetInternalHeaders());
|
||||
DerivedClass()->GetInternalHeaders()->GetAll(NS_LITERAL_CSTRING("Content-Type"), contentTypeValues, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
DerivedClass()->GetInternalHeaders()->GetAll(NS_LITERAL_CSTRING("Content-Type"),
|
||||
contentTypeValues, result);
|
||||
MOZ_ALWAYS_TRUE(!result.Failed());
|
||||
|
||||
// HTTP ABNF states Content-Type may have only one value.
|
||||
// This is from the "parse a header value" of the fetch spec.
|
||||
|
@ -1236,10 +1664,10 @@ FetchBody<Derived>::SetMimeType(ErrorResult& aRv)
|
|||
|
||||
template
|
||||
void
|
||||
FetchBody<Request>::SetMimeType(ErrorResult& aRv);
|
||||
FetchBody<Request>::SetMimeType();
|
||||
|
||||
template
|
||||
void
|
||||
FetchBody<Response>::SetMimeType(ErrorResult& aRv);
|
||||
FetchBody<Response>::SetMimeType();
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -113,6 +113,12 @@ public:
|
|||
return ConsumeBody(CONSUME_BLOB, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
FormData(ErrorResult& aRv)
|
||||
{
|
||||
return ConsumeBody(CONSUME_FORMDATA, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Json(ErrorResult& aRv)
|
||||
{
|
||||
|
@ -154,13 +160,13 @@ protected:
|
|||
virtual ~FetchBody();
|
||||
|
||||
void
|
||||
SetMimeType(ErrorResult& aRv);
|
||||
SetMimeType();
|
||||
private:
|
||||
enum ConsumeType
|
||||
{
|
||||
CONSUME_ARRAYBUFFER,
|
||||
CONSUME_BLOB,
|
||||
// FormData not supported right now,
|
||||
CONSUME_FORMDATA,
|
||||
CONSUME_JSON,
|
||||
CONSUME_TEXT,
|
||||
};
|
||||
|
|
|
@ -34,6 +34,7 @@ Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest)
|
|||
, mOwner(aOwner)
|
||||
, mRequest(aRequest)
|
||||
{
|
||||
SetMimeType();
|
||||
}
|
||||
|
||||
Request::~Request()
|
||||
|
@ -264,7 +265,7 @@ Request::Constructor(const GlobalObject& aGlobal,
|
|||
}
|
||||
|
||||
nsRefPtr<Request> domRequest = new Request(global, request);
|
||||
domRequest->SetMimeType(aRv);
|
||||
domRequest->SetMimeType();
|
||||
return domRequest.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ Response::Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse
|
|||
, mOwner(aGlobal)
|
||||
, mInternalResponse(aInternalResponse)
|
||||
{
|
||||
SetMimeType();
|
||||
}
|
||||
|
||||
Response::~Response()
|
||||
|
@ -188,7 +189,7 @@ Response::Constructor(const GlobalObject& aGlobal,
|
|||
}
|
||||
}
|
||||
|
||||
r->SetMimeType(aRv);
|
||||
r->SetMimeType();
|
||||
return r.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -1831,7 +1831,7 @@ HTMLInputElement::SetValue(const nsAString& aValue, ErrorResult& aRv)
|
|||
}
|
||||
Sequence<nsString> list;
|
||||
list.AppendElement(aValue);
|
||||
MozSetFileNameArray(list);
|
||||
MozSetFileNameArray(list, aRv);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
@ -2352,8 +2352,13 @@ HTMLInputElement::MozSetFileArray(const Sequence<OwningNonNull<File>>& aFiles)
|
|||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames)
|
||||
HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames, ErrorResult& aRv)
|
||||
{
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<File>> files;
|
||||
for (uint32_t i = 0; i < aFileNames.Length(); ++i) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
|
@ -2397,8 +2402,9 @@ HTMLInputElement::MozSetFileNameArray(const char16_t** aFileNames, uint32_t aLen
|
|||
list.AppendElement(nsDependentString(aFileNames[i]));
|
||||
}
|
||||
|
||||
MozSetFileNameArray(list);
|
||||
return NS_OK;
|
||||
ErrorResult rv;
|
||||
MozSetFileNameArray(list, rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2445,8 +2451,9 @@ HTMLInputElement::SetUserInput(const nsAString& aValue)
|
|||
{
|
||||
Sequence<nsString> list;
|
||||
list.AppendElement(aValue);
|
||||
MozSetFileNameArray(list);
|
||||
return NS_OK;
|
||||
ErrorResult rv;
|
||||
MozSetFileNameArray(list, rv);
|
||||
return rv.ErrorCode();
|
||||
} else {
|
||||
nsresult rv = SetValueInternal(aValue, true, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -715,7 +715,7 @@ public:
|
|||
|
||||
void MozGetFileNameArray(nsTArray< nsString >& aFileNames);
|
||||
|
||||
void MozSetFileNameArray(const Sequence< nsString >& aFileNames);
|
||||
void MozSetFileNameArray(const Sequence< nsString >& aFileNames, ErrorResult& aRv);
|
||||
void MozSetFileArray(const Sequence<OwningNonNull<File>>& aFiles);
|
||||
|
||||
HTMLInputElement* GetOwnerNumberControl();
|
||||
|
|
|
@ -39,7 +39,7 @@ skip-if(Android||B2G) == 649134-2.html 649134-2-ref.html
|
|||
# (Fuzzy necessary due to pixel-wise comparison of different JPEGs.
|
||||
# The vast majority of the fuzziness comes from Linux and WinXP.)
|
||||
fuzzy(1,149) == bug917595-iframe-1.html bug917595-1-ref.html
|
||||
skip-if(B2G) fuzzy-if(!B2G,3,640) == bug917595-exif-rotated.jpg bug917595-pixel-rotated.jpg # bug 1060869
|
||||
skip-if(B2G||Mulet) fuzzy-if((!B2G&&!Mulet),3,640) == bug917595-exif-rotated.jpg bug917595-pixel-rotated.jpg # bug 1060869 # Bug 1150490 disabling on Mulet as on B2G
|
||||
|
||||
# Test support for SVG-as-image in <picture> elements.
|
||||
pref(dom.image.picture.enabled,true) pref(dom.image.srcset.enabled,true) == bug1106522-1.html bug1106522-ref.html
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
Cu.importGlobalProperties(["File"]);
|
||||
|
||||
addMessageListener("files.open", function (message) {
|
||||
sendAsyncMessage("files.opened", message.map(path => new File(path)));
|
||||
});
|
|
@ -68,12 +68,10 @@ skip-if = buildapp == 'mulet'
|
|||
[test_label_control_attribute.html]
|
||||
[test_label_input_controls.html]
|
||||
[test_max_attribute.html]
|
||||
skip-if = e10s
|
||||
[test_maxlength_attribute.html]
|
||||
[test_meter_element.html]
|
||||
[test_meter_pseudo-classes.html]
|
||||
[test_min_attribute.html]
|
||||
skip-if = e10s
|
||||
[test_mozistextfield.html]
|
||||
[test_novalidate_attribute.html]
|
||||
[test_option_disabled.html]
|
||||
|
@ -85,14 +83,12 @@ skip-if = e10s
|
|||
[test_radio_in_label.html]
|
||||
[test_radio_radionodelist.html]
|
||||
[test_required_attribute.html]
|
||||
skip-if = e10s
|
||||
[test_restore_form_elements.html]
|
||||
[test_save_restore_radio_groups.html]
|
||||
[test_select_selectedOptions.html]
|
||||
[test_select_validation.html]
|
||||
[test_set_range_text.html]
|
||||
[test_step_attribute.html]
|
||||
skip-if = e10s
|
||||
[test_stepup_stepdown.html]
|
||||
[test_textarea_attributes_reflection.html]
|
||||
[test_validation.html]
|
||||
|
|
|
@ -175,14 +175,9 @@ for (var test of data) {
|
|||
checkValidity(input, true, apply, apply);
|
||||
break;
|
||||
case 'file':
|
||||
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIProperties);
|
||||
var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
|
||||
file.append('635499_file');
|
||||
// Only the file's path is used, so it doesn't need to be created.
|
||||
// See also bug 1058977.
|
||||
var file = new File([''], '635499_file');
|
||||
|
||||
SpecialPowers.wrap(input).value = file.path;
|
||||
SpecialPowers.wrap(input).mozSetFileArray([file]);
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
break;
|
||||
|
|
|
@ -173,14 +173,9 @@ for (var test of data) {
|
|||
checkValidity(input, true, apply, apply);
|
||||
break;
|
||||
case 'file':
|
||||
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIProperties);
|
||||
var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
|
||||
file.append('635499_file');
|
||||
// Only the file's path is used, so it doesn't need to be created.
|
||||
// See also bug 1058977.
|
||||
var file = new File([''], '635499_file');
|
||||
|
||||
SpecialPowers.wrap(input).value = file.path;
|
||||
SpecialPowers.wrap(input).mozSetFileArray([file]);
|
||||
checkValidity(input, true, apply, apply);
|
||||
|
||||
break;
|
||||
|
|
|
@ -41,9 +41,12 @@ function completeValidityCheck(element, alwaysValid, isBarred)
|
|||
} else if (element.type == 'url') {
|
||||
element.pattern = "http://.*\\.com$";
|
||||
element.value = "http://mozilla.com";
|
||||
} else if (element.type == 'file') {
|
||||
element.pattern = "foo";
|
||||
SpecialPowers.wrap(element).mozSetFileArray([new File(["foo"], "foo")]);
|
||||
} else {
|
||||
element.pattern = "foo";
|
||||
SpecialPowers.wrap(element).value = "foo";
|
||||
element.value = "foo";
|
||||
}
|
||||
|
||||
checkValidPattern(element, true, isBarred);
|
||||
|
@ -56,9 +59,12 @@ function completeValidityCheck(element, alwaysValid, isBarred)
|
|||
} else if (element.type == 'url') {
|
||||
element.pattern = "http://.*\\.com$";
|
||||
element.value = "http://mozilla.org";
|
||||
} else if (element.type == 'file') {
|
||||
element.pattern = "foo";
|
||||
SpecialPowers.wrap(element).mozSetFileArray([new File(["bar"], "bar")]);
|
||||
} else {
|
||||
element.pattern = "foo";
|
||||
SpecialPowers.wrap(element).value = "bar";
|
||||
element.value = "bar";
|
||||
}
|
||||
|
||||
if (!alwaysValid) {
|
||||
|
|
|
@ -314,18 +314,7 @@ function checkInputRequiredValidityForFile()
|
|||
element.type = 'file'
|
||||
document.forms[0].appendChild(element);
|
||||
|
||||
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);
|
||||
// Only the file's path is used, so it doesn't need to be created.
|
||||
// See also bug 1058977.
|
||||
|
||||
return testFile;
|
||||
}
|
||||
|
||||
var file = createFile("345822_file");
|
||||
var file = new File([""], "345822_file");
|
||||
|
||||
SpecialPowers.wrap(element).value = "";
|
||||
element.required = false;
|
||||
|
@ -334,7 +323,7 @@ function checkInputRequiredValidityForFile()
|
|||
element.required = true;
|
||||
checkSufferingFromBeingMissing(element, true);
|
||||
|
||||
SpecialPowers.wrap(element).value = file.path;
|
||||
SpecialPowers.wrap(element).mozSetFileArray([file]);
|
||||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
SpecialPowers.wrap(element).value = "";
|
||||
|
@ -344,7 +333,7 @@ function checkInputRequiredValidityForFile()
|
|||
checkNotSufferingFromBeingMissing(element);
|
||||
|
||||
element.focus();
|
||||
SpecialPowers.wrap(element).value = file.path;
|
||||
SpecialPowers.wrap(element).mozSetFileArray([file]);
|
||||
element.required = true;
|
||||
element.blur();
|
||||
element.form.reset();
|
||||
|
|
|
@ -128,14 +128,9 @@ for (var test of data) {
|
|||
checkValidity(input, true, apply);
|
||||
break;
|
||||
case 'file':
|
||||
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIProperties);
|
||||
var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
|
||||
file.append('635499_file');
|
||||
// Only the file's path is used, so it doesn't need to be created.
|
||||
// See also bug 1058977.
|
||||
var file = new File([''], '635499_file');
|
||||
|
||||
SpecialPowers.wrap(input).value = file.path;
|
||||
SpecialPowers.wrap(input).mozSetFileArray([file]);
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
break;
|
||||
|
|
|
@ -178,6 +178,7 @@ support-files =
|
|||
file_srcdoc.html
|
||||
file_window_open_close_outer.html
|
||||
file_window_open_close_inner.html
|
||||
formSubmission_chrome.js
|
||||
form_submit_server.sjs
|
||||
formData_worker.js
|
||||
formData_test.js
|
||||
|
@ -459,7 +460,7 @@ skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only failure
|
|||
[test_embed_attributes_reflection.html]
|
||||
[test_formData.html]
|
||||
[test_formSubmission.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT # b2g(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) b2g-debug(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) b2g-desktop(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) b2g-debug(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) b2g-desktop(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
|
||||
[test_formSubmission2.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_formelements.html]
|
||||
|
|
|
@ -18,49 +18,53 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=143220
|
|||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
<script class="testbody" type="text/javascript;version=1.7">
|
||||
|
||||
/** Test for Bug 143220 **/
|
||||
var leafName;
|
||||
var fullPath;
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
const helperURL = SimpleTest.getTestFileURL("simpleFileOpener.js");
|
||||
const helper = SpecialPowers.loadChromeScript(helperURL);
|
||||
helper.addMessageListener("fail", function onFail(message) {
|
||||
is(message, null, "chrome script failed");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
helper.addMessageListener("file.opened", onFileOpened);
|
||||
helper.sendAsyncMessage("file.open", "test_bug143220.txt");
|
||||
|
||||
function onFileOpened(message) {
|
||||
const { leafName, fullPath, domFile } = message;
|
||||
|
||||
function initVals() {
|
||||
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIProperties);
|
||||
var file = dirSvc.get("XpcomLib", SpecialPowers.Ci.nsILocalFile);
|
||||
isnot(file, null, "Must have file here");
|
||||
function initControl1() {
|
||||
SpecialPowers.wrap($("i1")).mozSetFileArray([domFile]);
|
||||
}
|
||||
|
||||
leafName = file.leafName;
|
||||
fullPath = file.path;
|
||||
function initControl2() {
|
||||
SpecialPowers.wrap($("i2")).mozSetFileArray([domFile]);
|
||||
}
|
||||
|
||||
// Check that we can't just set the value
|
||||
try {
|
||||
$("i1").value = fullPath;
|
||||
is(0, 1, "Should have thrown exception on set!");
|
||||
} catch(e) {
|
||||
is($("i1").value, "", "Shouldn't have value here");
|
||||
}
|
||||
|
||||
initControl1();
|
||||
initControl2();
|
||||
|
||||
is($("i1").value, leafName, "Leaking full value?");
|
||||
is($("i2").value, leafName, "Leaking full value?");
|
||||
|
||||
helper.addMessageListener("file.removed", onFileRemoved);
|
||||
helper.sendAsyncMessage("file.remove", null);
|
||||
}
|
||||
|
||||
function initControl1() {
|
||||
SpecialPowers.wrap($("i1")).value = fullPath;
|
||||
is(SpecialPowers.wrap($("i1")).value, fullPath, "Should have set full path 1");
|
||||
function onFileRemoved() {
|
||||
helper.destroy();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function initControl2() {
|
||||
SpecialPowers.wrap($("i2")).value = fullPath;
|
||||
is(SpecialPowers.wrap($("i2")).value, fullPath, "Should have set full path 2");
|
||||
}
|
||||
|
||||
initVals();
|
||||
|
||||
// Check that we can't just set the value
|
||||
try {
|
||||
$("i1").value = fullPath;
|
||||
is(0, 1, "Should have thrown exception on set!");
|
||||
} catch(e) {
|
||||
is($("i1").value, "", "Shouldn't have value here");
|
||||
}
|
||||
|
||||
initControl1();
|
||||
initControl2();
|
||||
|
||||
is($("i1").value, leafName, "Leaking full value?");
|
||||
is($("i2").value, leafName, "Leaking full value?");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -399,41 +399,59 @@ t_6_v</textarea>
|
|||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var myFile1, myFile2, emptyFile;
|
||||
const placeholder_myFile1 = {};
|
||||
const placeholder_myFile2 = {};
|
||||
const placeholder_emptyFile = {};
|
||||
|
||||
(function setFileNames() {
|
||||
var myFile1, myFile2, emptyFile;
|
||||
let openerURL = SimpleTest.getTestFileURL("formSubmission_chrome.js");
|
||||
let opener = SpecialPowers.loadChromeScript(openerURL);
|
||||
|
||||
{
|
||||
let xhr = new XMLHttpRequest;
|
||||
xhr.open("GET", "/dynamic/getMyDirectory.sjs", false);
|
||||
xhr.send();
|
||||
var basePath = xhr.responseText;
|
||||
let basePath = xhr.responseText;
|
||||
|
||||
singleFile = basePath + "file_formSubmission_text.txt";
|
||||
multiFile = [basePath + "file_formSubmission_text.txt",
|
||||
basePath + "file_formSubmission_img.jpg"];
|
||||
opener.addMessageListener("files.opened", onFilesOpened);
|
||||
opener.sendAsyncMessage("files.open", [
|
||||
basePath + "file_formSubmission_text.txt",
|
||||
basePath + "file_formSubmission_img.jpg",
|
||||
]);
|
||||
}
|
||||
|
||||
function onFilesOpened(files) {
|
||||
let [textFile, imageFile] = files;
|
||||
opener.destroy();
|
||||
|
||||
let singleFile = textFile;
|
||||
let multiFile = [textFile, imageFile];
|
||||
|
||||
var addList = document.getElementsByClassName("setfile");
|
||||
let i = 0;
|
||||
var input;
|
||||
while (input = addList[i++]) {
|
||||
if (input.classList.contains("multi")) {
|
||||
SpecialPowers.wrap(input).mozSetFileNameArray(multiFile, multiFile.length);
|
||||
SpecialPowers.wrap(input).mozSetFileArray(multiFile);
|
||||
}
|
||||
else {
|
||||
SpecialPowers.wrap(input).value = singleFile;
|
||||
SpecialPowers.wrap(input).mozSetFileArray([singleFile]);
|
||||
}
|
||||
}
|
||||
|
||||
input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.multiple = true;
|
||||
SpecialPowers.wrap(input).mozSetFileNameArray(multiFile, multiFile.length);
|
||||
SpecialPowers.wrap(input).mozSetFileArray(multiFile);
|
||||
myFile1 = input.files[0];
|
||||
myFile2 = input.files[1];
|
||||
is(myFile1.size, 20, "File1 size");
|
||||
is(myFile2.size, 2711, "File2 size");
|
||||
emptyFile = { name: "", type: "application/octet-stream" };
|
||||
})();
|
||||
|
||||
// Now, actually run the tests; see below.
|
||||
onFilesSet();
|
||||
};
|
||||
|
||||
var expectedSub = [
|
||||
// Default input
|
||||
|
@ -495,13 +513,13 @@ var expectedSub = [
|
|||
// Reset button
|
||||
// Unknown button
|
||||
// File
|
||||
{ name: "file_1", value: myFile1 },
|
||||
{ name: "file_2", value: emptyFile },
|
||||
{ name: "file_1", value: placeholder_myFile1 },
|
||||
{ name: "file_2", value: placeholder_emptyFile },
|
||||
// Multiple file
|
||||
{ name: "file_3", value: myFile1 },
|
||||
{ name: "file_4", value: myFile1 },
|
||||
{ name: "file_4", value: myFile2 },
|
||||
{ name: "file_5", value: emptyFile },
|
||||
{ name: "file_3", value: placeholder_myFile1 },
|
||||
{ name: "file_4", value: placeholder_myFile1 },
|
||||
{ name: "file_4", value: placeholder_myFile2 },
|
||||
{ name: "file_5", value: placeholder_emptyFile },
|
||||
// Textarea
|
||||
{ name: "t1", value: "t_1_v" },
|
||||
{ name: "t2", value: "" },
|
||||
|
@ -562,12 +580,12 @@ var expectedSub = [
|
|||
{ name: "msel_31", value: "msel_31_v1" },
|
||||
];
|
||||
|
||||
expectedAugment = [
|
||||
var expectedAugment = [
|
||||
{ name: "aName", value: "aValue" },
|
||||
//{ name: "aNameBool", value: "false" },
|
||||
{ name: "aNameNum", value: "9.2" },
|
||||
{ name: "aNameFile1", value: myFile1 },
|
||||
{ name: "aNameFile2", value: myFile2 },
|
||||
{ name: "aNameFile1", value: placeholder_myFile1 },
|
||||
{ name: "aNameFile2", value: placeholder_myFile2 },
|
||||
//{ name: "aNameObj", value: "[object XMLHttpRequest]" },
|
||||
//{ name: "aNameNull", value: "null" },
|
||||
//{ name: "aNameUndef", value: "undefined" },
|
||||
|
@ -661,10 +679,13 @@ function setDisabled(list, state) {
|
|||
});
|
||||
}
|
||||
|
||||
var gen = runTest();
|
||||
addLoadEvent(function() {
|
||||
gen.next();
|
||||
});
|
||||
var gen;
|
||||
function onFilesSet() {
|
||||
gen = runTest();
|
||||
addLoadEvent(function() {
|
||||
gen.next();
|
||||
});
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// Set up the expectedSub array
|
||||
|
@ -676,17 +697,17 @@ function runTest() {
|
|||
yield undefined; // Wait for both FileReaders. We don't care which order they finish.
|
||||
yield undefined;
|
||||
function fileFixup(o) {
|
||||
if (o.value == myFile1) {
|
||||
if (o.value === placeholder_myFile1) {
|
||||
o.value = fileReader1.result;
|
||||
o.fileName = myFile1.name;
|
||||
o.contentType = myFile1.type;
|
||||
}
|
||||
else if (o.value == myFile2) {
|
||||
else if (o.value === placeholder_myFile2) {
|
||||
o.value = fileReader2.result;
|
||||
o.fileName = myFile2.name;
|
||||
o.contentType = myFile2.type;
|
||||
}
|
||||
else if (o.value == emptyFile) {
|
||||
else if (o.value === placeholder_emptyFile) {
|
||||
o.value = "";
|
||||
o.fileName = emptyFile.name;
|
||||
o.contentType = emptyFile.type;
|
||||
|
|
|
@ -1235,13 +1235,14 @@ StartMacOSContentSandbox()
|
|||
|
||||
MacSandboxInfo info;
|
||||
info.type = MacSandboxType_Content;
|
||||
info.appPath.Assign(appPath);
|
||||
info.appBinaryPath.Assign(appBinaryPath);
|
||||
info.appDir.Assign(appDir);
|
||||
info.level = Preferences::GetInt("security.sandbox.content.level");
|
||||
info.appPath.assign(appPath.get());
|
||||
info.appBinaryPath.assign(appBinaryPath.get());
|
||||
info.appDir.assign(appDir.get());
|
||||
|
||||
nsAutoCString err;
|
||||
std::string err;
|
||||
if (!mozilla::StartMacSandbox(info, err)) {
|
||||
NS_WARNING(err.get());
|
||||
NS_WARNING(err.c_str());
|
||||
MOZ_CRASH("sandbox_init() failed");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1579,13 +1579,14 @@ TabParent::RecvNotifyIMEFocus(const bool& aFocus,
|
|||
nsIMEUpdatePreference* aPreference,
|
||||
uint32_t* aSeqno)
|
||||
{
|
||||
*aSeqno = mIMESeqno;
|
||||
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget) {
|
||||
*aPreference = nsIMEUpdatePreference();
|
||||
return true;
|
||||
}
|
||||
|
||||
*aSeqno = mIMESeqno;
|
||||
mIMETabParent = aFocus ? this : nullptr;
|
||||
mIMESelectionAnchor = 0;
|
||||
mIMESelectionFocus = 0;
|
||||
|
|
|
@ -111,6 +111,12 @@ FAIL_ON_WARNINGS = True
|
|||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Darwin':
|
||||
USE_LIBS += [
|
||||
'mozsandbox',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/caps',
|
||||
'/chrome',
|
||||
|
|
|
@ -228,32 +228,31 @@ GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GMPChild::StartMacSandbox()
|
||||
bool
|
||||
GMPChild::SetMacSandboxInfo()
|
||||
{
|
||||
if (!mGMPLoader) {
|
||||
return false;
|
||||
}
|
||||
nsAutoCString pluginDirectoryPath, pluginFilePath;
|
||||
if (!GetPluginPaths(mPluginPath, pluginDirectoryPath, pluginFilePath)) {
|
||||
MOZ_CRASH("Error scanning plugin path");
|
||||
return false;
|
||||
}
|
||||
nsAutoCString appPath, appBinaryPath;
|
||||
if (!GetAppPaths(appPath, appBinaryPath)) {
|
||||
MOZ_CRASH("Error resolving child process path");
|
||||
return false;
|
||||
}
|
||||
|
||||
MacSandboxInfo info;
|
||||
info.type = MacSandboxType_Plugin;
|
||||
info.pluginInfo.type = MacSandboxPluginType_GMPlugin_Default;
|
||||
info.pluginInfo.pluginPath.Assign(pluginDirectoryPath);
|
||||
mPluginBinaryPath.Assign(pluginFilePath);
|
||||
info.pluginInfo.pluginBinaryPath.Assign(pluginFilePath);
|
||||
info.appPath.Assign(appPath);
|
||||
info.appBinaryPath.Assign(appBinaryPath);
|
||||
info.pluginInfo.pluginPath.assign(pluginDirectoryPath.get());
|
||||
info.pluginInfo.pluginBinaryPath.assign(pluginFilePath.get());
|
||||
info.appPath.assign(appPath.get());
|
||||
info.appBinaryPath.assign(appBinaryPath.get());
|
||||
|
||||
nsAutoCString err;
|
||||
if (!mozilla::StartMacSandbox(info, err)) {
|
||||
NS_WARNING(err.get());
|
||||
MOZ_CRASH("sandbox_init() failed");
|
||||
}
|
||||
mGMPLoader->SetSandboxInfo(&info);
|
||||
return true;
|
||||
}
|
||||
#endif // XP_MACOSX && MOZ_GMP_SANDBOX
|
||||
|
||||
|
@ -364,24 +363,6 @@ GMPChild::PreLoadLibraries(const std::string& aPluginPath)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_GMP_SANDBOX)
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
class MacOSXSandboxStarter : public SandboxStarter {
|
||||
public:
|
||||
explicit MacOSXSandboxStarter(GMPChild* aGMPChild)
|
||||
: mGMPChild(aGMPChild)
|
||||
{}
|
||||
virtual void Start(const char* aLibPath) override {
|
||||
mGMPChild->StartMacSandbox();
|
||||
}
|
||||
private:
|
||||
GMPChild* mGMPChild;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // MOZ_GMP_SANDBOX
|
||||
|
||||
bool
|
||||
GMPChild::GetLibPath(nsACString& aOutLibPath)
|
||||
{
|
||||
|
@ -427,8 +408,10 @@ GMPChild::RecvStartPlugin()
|
|||
}
|
||||
|
||||
#if defined(MOZ_GMP_SANDBOX) && defined(XP_MACOSX)
|
||||
nsAutoPtr<SandboxStarter> starter(new MacOSXSandboxStarter(this));
|
||||
mGMPLoader->SetStartSandboxStarter(starter);
|
||||
if (!SetMacSandboxInfo()) {
|
||||
NS_WARNING("Failed to set Mac GMP sandbox info");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!mGMPLoader->Load(libPath.get(),
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
void ShutdownComplete() override;
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
|
||||
void StartMacSandbox();
|
||||
bool SetMacSandboxInfo();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -89,9 +89,6 @@ private:
|
|||
MessageLoop* mGMPMessageLoop;
|
||||
std::string mPluginPath;
|
||||
std::string mVoucherPath;
|
||||
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
|
||||
nsCString mPluginBinaryPath;
|
||||
#endif
|
||||
std::string mNodeId;
|
||||
GMPLoader* mGMPLoader;
|
||||
nsTArray<uint8_t> mPluginVoucher;
|
||||
|
|
|
@ -80,10 +80,8 @@ public:
|
|||
|
||||
virtual void Shutdown() override;
|
||||
|
||||
#ifdef SANDBOX_NOT_STATICALLY_LINKED_INTO_PLUGIN_CONTAINER
|
||||
virtual void SetStartSandboxStarter(SandboxStarter* aStarter) override {
|
||||
mSandboxStarter = aStarter;
|
||||
}
|
||||
#if defined(XP_MACOSX)
|
||||
virtual void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -220,8 +218,8 @@ GMPLoaderImpl::Load(const char* aLibPath,
|
|||
// Start the sandbox now that we've generated the device bound node id.
|
||||
// This must happen after the node id is bound to the device id, as
|
||||
// generating the device id requires privileges.
|
||||
if (mSandboxStarter) {
|
||||
mSandboxStarter->Start(aLibPath);
|
||||
if (mSandboxStarter && !mSandboxStarter->Start(aLibPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the GMP.
|
||||
|
@ -277,6 +275,15 @@ GMPLoaderImpl::Shutdown()
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
void
|
||||
GMPLoaderImpl::SetSandboxInfo(MacSandboxInfo* aSandboxInfo)
|
||||
{
|
||||
if (mSandboxStarter) {
|
||||
mSandboxStarter->SetSandboxInfo(aSandboxInfo);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // namespace gmp
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -10,18 +10,24 @@
|
|||
#include <stdint.h>
|
||||
#include "gmp-entrypoints.h"
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
#include "mozilla/Sandbox.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
||||
class SandboxStarter {
|
||||
public:
|
||||
virtual ~SandboxStarter() {}
|
||||
virtual void Start(const char* aLibPath) = 0;
|
||||
};
|
||||
|
||||
virtual bool Start(const char* aLibPath) = 0;
|
||||
#if defined(XP_MACOSX)
|
||||
#define SANDBOX_NOT_STATICALLY_LINKED_INTO_PLUGIN_CONTAINER 1
|
||||
// On OS X we need to set Mac-specific sandbox info just before we start the
|
||||
// sandbox, which we don't yet know when the GMPLoader and SandboxStarter
|
||||
// objects are created.
|
||||
virtual void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Encapsulates generating the device-bound node id, activating the sandbox,
|
||||
// loading the GMP, and passing the node id to the GMP (in that order).
|
||||
|
@ -59,10 +65,11 @@ public:
|
|||
// plugin library.
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
#ifdef SANDBOX_NOT_STATICALLY_LINKED_INTO_PLUGIN_CONTAINER
|
||||
// Encapsulates starting the sandbox on Linux and MacOSX.
|
||||
// TODO: Remove this, and put sandbox in plugin-container on all platforms.
|
||||
virtual void SetStartSandboxStarter(SandboxStarter* aStarter) = 0;
|
||||
#if defined(XP_MACOSX)
|
||||
// On OS X we need to set Mac-specific sandbox info just before we start the
|
||||
// sandbox, which we don't yet know when the GMPLoader and SandboxStarter
|
||||
// objects are created.
|
||||
virtual void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -144,9 +144,6 @@ GetStrokeDashData(SVGContentUtils::AutoStrokeOptions* aStrokeOptions,
|
|||
// stroke to essentially be continuous or to be nonexistent in which case
|
||||
// we can avoid expensive stroking operations (the underlying platform
|
||||
// graphics libraries don't seem to optimize for this).
|
||||
if (totalLengthOfDashes <= 0 && totalLengthOfGaps <= 0) {
|
||||
return eNoStroke;
|
||||
}
|
||||
if (totalLengthOfGaps <= 0) {
|
||||
return eContinuousStroke;
|
||||
}
|
||||
|
|
|
@ -992,14 +992,39 @@ void NetworkUtils::removeDefaultRoute(CommandChain* aChain,
|
|||
CommandCallback aCallback,
|
||||
NetworkResultOptions& aResult)
|
||||
{
|
||||
char command[MAX_COMMAND_SIZE];
|
||||
// FIXME: (Bug 1121795) We only remove the first gateway to the default route.
|
||||
// For dual stack (ipv4/ipv6) device, one of the gateway would
|
||||
// not be added to the default route.
|
||||
snprintf(command, MAX_COMMAND_SIZE - 1, "network route remove %d %s 0.0.0.0/0 %s",
|
||||
GET_FIELD(mNetId), GET_CHAR(mIfname), GET_CHAR(mGateways[0]));
|
||||
if (GET_FIELD(mLoopIndex) >= GET_FIELD(mGateways).Length()) {
|
||||
aCallback(aChain, false, aResult);
|
||||
return;
|
||||
}
|
||||
|
||||
doCommand(command, aChain, aCallback);
|
||||
char command[MAX_COMMAND_SIZE];
|
||||
nsTArray<nsString>& gateways = GET_FIELD(mGateways);
|
||||
NS_ConvertUTF16toUTF8 autoGateway(gateways[GET_FIELD(mLoopIndex)]);
|
||||
|
||||
int type = getIpType(autoGateway.get());
|
||||
snprintf(command, MAX_COMMAND_SIZE - 1, "network route remove %d %s %s/0 %s",
|
||||
GET_FIELD(mNetId), GET_CHAR(mIfname),
|
||||
type == AF_INET6 ? "::" : "0.0.0.0", autoGateway.get());
|
||||
|
||||
struct MyCallback {
|
||||
static void callback(CommandCallback::CallbackType aOriginalCallback,
|
||||
CommandChain* aChain,
|
||||
bool aError,
|
||||
mozilla::dom::NetworkResultOptions& aResult)
|
||||
{
|
||||
NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
|
||||
NU_DBG("removeDefaultRoute's reason: %s", reason.get());
|
||||
if (aError && !reason.EqualsASCII("removeRoute() failed (No such process)")) {
|
||||
return aOriginalCallback(aChain, aError, aResult);
|
||||
}
|
||||
|
||||
GET_FIELD(mLoopIndex)++;
|
||||
return removeDefaultRoute(aChain, aOriginalCallback, aResult);
|
||||
}
|
||||
};
|
||||
|
||||
CommandCallback wrappedCallback(MyCallback::callback, aCallback);
|
||||
doCommand(command, aChain, wrappedCallback);
|
||||
}
|
||||
|
||||
void NetworkUtils::setInterfaceDns(CommandChain* aChain,
|
||||
|
@ -1147,13 +1172,19 @@ void NetworkUtils::addDefaultRouteToNetwork(CommandChain* aChain,
|
|||
CommandCallback aCallback,
|
||||
NetworkResultOptions& aResult)
|
||||
{
|
||||
char command[MAX_COMMAND_SIZE];
|
||||
if (GET_FIELD(mLoopIndex) >= GET_FIELD(mGateways).Length()) {
|
||||
aCallback(aChain, false, aResult);
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: (Bug 1121795) We only add the first gateway to the default route.
|
||||
// For dual stack (ipv4/ipv6) device, one of the gateway would
|
||||
// not be added to the default route.
|
||||
snprintf(command, MAX_COMMAND_SIZE - 1, "network route add %d %s 0.0.0.0/0 %s",
|
||||
GET_FIELD(mNetId), GET_CHAR(mIfname), GET_CHAR(mGateways[0]));
|
||||
char command[MAX_COMMAND_SIZE];
|
||||
nsTArray<nsString>& gateways = GET_FIELD(mGateways);
|
||||
NS_ConvertUTF16toUTF8 autoGateway(gateways[GET_FIELD(mLoopIndex)]);
|
||||
|
||||
int type = getIpType(autoGateway.get());
|
||||
snprintf(command, MAX_COMMAND_SIZE - 1, "network route add %d %s %s/0 %s",
|
||||
GET_FIELD(mNetId), GET_CHAR(mIfname),
|
||||
type == AF_INET6 ? "::" : "0.0.0.0", autoGateway.get());
|
||||
|
||||
struct MyCallback {
|
||||
static void callback(CommandCallback::CallbackType aOriginalCallback,
|
||||
|
@ -1163,11 +1194,12 @@ void NetworkUtils::addDefaultRouteToNetwork(CommandChain* aChain,
|
|||
{
|
||||
NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
|
||||
NU_DBG("addDefaultRouteToNetwork's reason: %s", reason.get());
|
||||
if (aError && reason.EqualsASCII("addRoute() failed (File exists)")) {
|
||||
NU_DBG("Ignore \"File exists\" error when adding host route.");
|
||||
return aOriginalCallback(aChain, false, aResult);
|
||||
if (aError && !reason.EqualsASCII("addRoute() failed (File exists)")) {
|
||||
return aOriginalCallback(aChain, aError, aResult);
|
||||
}
|
||||
aOriginalCallback(aChain, aError, aResult);
|
||||
|
||||
GET_FIELD(mLoopIndex)++;
|
||||
return addDefaultRouteToNetwork(aChain, aOriginalCallback, aResult);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1810,8 +1842,9 @@ CommandResult NetworkUtils::setDefaultRoute(NetworkParams& aOptions)
|
|||
}
|
||||
|
||||
aOptions.mNetId = netIdInfo.mNetId;
|
||||
|
||||
aOptions.mLoopIndex = 0;
|
||||
runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
|
||||
|
||||
return CommandResult::Pending();
|
||||
}
|
||||
|
||||
|
@ -1893,6 +1926,7 @@ CommandResult NetworkUtils::removeDefaultRoute(NetworkParams& aOptions)
|
|||
NU_DBG("Obtained netid %d for interface %s", netIdInfo.mNetId, GET_CHAR(mIfname));
|
||||
|
||||
aOptions.mNetId = netIdInfo.mNetId;
|
||||
aOptions.mLoopIndex = 0;
|
||||
runChain(aOptions, COMMAND_CHAIN, defaultAsyncFailureHandler);
|
||||
|
||||
return CommandResult::Pending();
|
||||
|
|
|
@ -146,6 +146,8 @@ public:
|
|||
COPY_OPT_FIELD(mDns1_long, 0)
|
||||
COPY_OPT_FIELD(mDns2_long, 0)
|
||||
|
||||
mLoopIndex = 0;
|
||||
|
||||
#undef COPY_SEQUENCE_FIELD
|
||||
#undef COPY_OPT_STRING_FIELD
|
||||
#undef COPY_OPT_FIELD
|
||||
|
@ -198,7 +200,8 @@ public:
|
|||
long mDns2_long;
|
||||
|
||||
// Auxiliary information required to carry accros command chain.
|
||||
int mNetId; // A locally defined id per interface.
|
||||
int mNetId; // A locally defined id per interface.
|
||||
uint32_t mLoopIndex; // Loop index for adding/removing multiple gateways.
|
||||
};
|
||||
|
||||
// CommandChain store the necessary information to execute command one by one.
|
||||
|
|
|
@ -47,40 +47,3 @@ function testScript(script) {
|
|||
});
|
||||
}
|
||||
|
||||
// Utilities
|
||||
// =========
|
||||
|
||||
// Helper that uses FileReader or FileReaderSync based on context and returns
|
||||
// a Promise that resolves with the text or rejects with error.
|
||||
function readAsText(blob) {
|
||||
if (typeof FileReader !== "undefined") {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var fs = new FileReader();
|
||||
fs.onload = function() {
|
||||
resolve(fs.result);
|
||||
}
|
||||
fs.onerror = reject;
|
||||
fs.readAsText(blob);
|
||||
});
|
||||
} else {
|
||||
var fs = new FileReaderSync();
|
||||
return Promise.resolve(fs.readAsText(blob));
|
||||
}
|
||||
}
|
||||
|
||||
function readAsArrayBuffer(blob) {
|
||||
if (typeof FileReader !== "undefined") {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var fs = new FileReader();
|
||||
fs.onload = function() {
|
||||
resolve(fs.result);
|
||||
}
|
||||
fs.onerror = reject;
|
||||
fs.readAsArrayBuffer(blob);
|
||||
});
|
||||
} else {
|
||||
var fs = new FileReaderSync();
|
||||
return Promise.resolve(fs.readAsArrayBuffer(blob));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,11 @@ support-files =
|
|||
test_fetch_basic.js
|
||||
test_fetch_basic_http.js
|
||||
test_fetch_cors.js
|
||||
test_formdataparsing.js
|
||||
test_headers_common.js
|
||||
test_request.js
|
||||
test_response.js
|
||||
utils.js
|
||||
worker_wrapper.js
|
||||
|
||||
[test_headers.html]
|
||||
|
@ -14,5 +16,6 @@ support-files =
|
|||
[test_fetch_basic.html]
|
||||
[test_fetch_basic_http.html]
|
||||
[test_fetch_cors.html]
|
||||
[test_formdataparsing.html]
|
||||
[test_request.html]
|
||||
[test_response.html]
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script type="text/javascript" src="utils.js"> </script>
|
||||
<script type="text/javascript" src="fetch_test_framework.js"> </script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
testScript("test_fetch_basic.js");
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script type="text/javascript" src="utils.js"> </script>
|
||||
<script type="text/javascript" src="fetch_test_framework.js"> </script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
testScript("test_fetch_basic_http.js");
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script type="text/javascript" src="utils.js"> </script>
|
||||
<script type="text/javascript" src="fetch_test_framework.js"> </script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
testScript("test_fetch_cors.js");
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1109751 - Test FormData parsing</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script type="text/javascript" src="utils.js"> </script>
|
||||
<script type="text/javascript" src="fetch_test_framework.js"> </script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
testScript("test_formdataparsing.js");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,283 @@
|
|||
var boundary = "1234567891011121314151617";
|
||||
|
||||
// fn(body) should create a Body subclass with content body treated as
|
||||
// FormData and return it.
|
||||
function testFormDataParsing(fn) {
|
||||
|
||||
function makeTest(shouldPass, input, testFn) {
|
||||
var obj = fn(input);
|
||||
return obj.formData().then(function(fd) {
|
||||
ok(shouldPass, "Expected test to be valid FormData for " + input);
|
||||
if (testFn) {
|
||||
return testFn(fd);
|
||||
}
|
||||
}, function(e) {
|
||||
if (shouldPass) {
|
||||
ok(false, "Expected test to pass for " + input);
|
||||
} else {
|
||||
ok(e.name == "TypeError", "Error should be a TypeError.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// [shouldPass?, input, testFn]
|
||||
var tests =
|
||||
[
|
||||
[ true,
|
||||
|
||||
boundary +
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
|
||||
function(fd) {
|
||||
is(fd.get("greeting"), '"hello"');
|
||||
}
|
||||
],
|
||||
[ false,
|
||||
|
||||
// Invalid disposition.
|
||||
boundary +
|
||||
'\r\nContent-Disposition: form-datafoobar; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ true,
|
||||
|
||||
'--' +
|
||||
boundary +
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
|
||||
function(fd) {
|
||||
is(fd.get("greeting"), '"hello"');
|
||||
}
|
||||
],
|
||||
[ false,
|
||||
boundary + "\r\n\r\n" + boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
// No valid ending.
|
||||
boundary + "\r\n\r\n" + boundary,
|
||||
],
|
||||
[ false,
|
||||
|
||||
// One '-' prefix is not allowed. 2 or none.
|
||||
'-' +
|
||||
boundary +
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
'invalid' +
|
||||
boundary +
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
boundary + 'suffix' +
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
boundary + 'suffix' +
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
// Partial boundary
|
||||
boundary.substr(3) +
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
boundary +
|
||||
// Missing '\n' at beginning.
|
||||
'\rContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
boundary +
|
||||
// No form-data.
|
||||
'\r\nContent-Disposition: mixed; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
boundary +
|
||||
// No headers.
|
||||
'\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
boundary +
|
||||
// No content-disposition.
|
||||
'\r\nContent-Dispositypo: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
boundary +
|
||||
// No name.
|
||||
'\r\nContent-Disposition: form-data;\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
boundary +
|
||||
// Missing empty line between headers and body.
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
// Empty entry followed by valid entry.
|
||||
boundary + "\r\n\r\n" + boundary +
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
|
||||
boundary +
|
||||
// Header followed by empty line, but empty body not followed by
|
||||
// newline.
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ true,
|
||||
|
||||
boundary +
|
||||
// Empty body followed by newline.
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n\r\n' +
|
||||
boundary + '-',
|
||||
|
||||
function(fd) {
|
||||
is(fd.get("greeting"), "", "Empty value is allowed.");
|
||||
}
|
||||
],
|
||||
[ false,
|
||||
boundary +
|
||||
// Value is boundary itself.
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n' +
|
||||
boundary + '\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ false,
|
||||
boundary +
|
||||
// Variant of above with no valid ending boundary.
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n' +
|
||||
boundary
|
||||
],
|
||||
[ true,
|
||||
boundary +
|
||||
// Unquoted filename with empty body.
|
||||
'\r\nContent-Disposition: form-data; name="file"; filename=file1.txt\r\n\r\n\r\n' +
|
||||
boundary + '-',
|
||||
|
||||
function(fd) {
|
||||
var f = fd.get("file");
|
||||
ok(f instanceof File, "Entry with filename attribute should be read as File.");
|
||||
is(f.name, "file1.txt", "Filename should match.");
|
||||
is(f.type, "text/plain", "Default content-type should be text/plain.");
|
||||
return readAsText(f).then(function(text) {
|
||||
is(text, "", "File should be empty.");
|
||||
});
|
||||
}
|
||||
],
|
||||
[ true,
|
||||
boundary +
|
||||
// Quoted filename with empty body.
|
||||
'\r\nContent-Disposition: form-data; name="file"; filename="file1.txt"\r\n\r\n\r\n' +
|
||||
boundary + '-',
|
||||
|
||||
function(fd) {
|
||||
var f = fd.get("file");
|
||||
ok(f instanceof File, "Entry with filename attribute should be read as File.");
|
||||
is(f.name, "file1.txt", "Filename should match.");
|
||||
is(f.type, "text/plain", "Default content-type should be text/plain.");
|
||||
return readAsText(f).then(function(text) {
|
||||
is(text, "", "File should be empty.");
|
||||
});
|
||||
}
|
||||
],
|
||||
[ false,
|
||||
boundary +
|
||||
// Invalid filename
|
||||
'\r\nContent-Disposition: form-data; name="file"; filename="[\n@;xt"\r\n\r\n\r\n' +
|
||||
boundary + '-',
|
||||
],
|
||||
[ true,
|
||||
boundary +
|
||||
'\r\nContent-Disposition: form-data; name="file"; filename="[@;xt"\r\n\r\n\r\n' +
|
||||
boundary + '-',
|
||||
|
||||
function(fd) {
|
||||
var f = fd.get("file");
|
||||
ok(f instanceof File, "Entry with filename attribute should be read as File.");
|
||||
is(f.name, "[@", "Filename should match.");
|
||||
}
|
||||
],
|
||||
[ true,
|
||||
boundary +
|
||||
'\r\nContent-Disposition: form-data; name="file"; filename="file with spaces"\r\n\r\n\r\n' +
|
||||
boundary + '-',
|
||||
|
||||
function(fd) {
|
||||
var f = fd.get("file");
|
||||
ok(f instanceof File, "Entry with filename attribute should be read as File.");
|
||||
is(f.name, "file with spaces", "Filename should match.");
|
||||
}
|
||||
],
|
||||
[ true,
|
||||
boundary + '\r\n' +
|
||||
'Content-Disposition: form-data; name="file"; filename="xml.txt"\r\n' +
|
||||
'content-type : application/xml\r\n' +
|
||||
'\r\n' +
|
||||
'<body>foobar\r\n\r\n</body>\r\n' +
|
||||
boundary + '-',
|
||||
|
||||
function(fd) {
|
||||
var f = fd.get("file");
|
||||
ok(f instanceof File, "Entry with filename attribute should be read as File.");
|
||||
is(f.name, "xml.txt", "Filename should match.");
|
||||
is(f.type, "application/xml", "content-type should be application/xml.");
|
||||
return readAsText(f).then(function(text) {
|
||||
is(text, "<body>foobar\r\n\r\n</body>", "File should have correct text.");
|
||||
});
|
||||
}
|
||||
],
|
||||
];
|
||||
|
||||
var promises = [];
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var test = tests[i];
|
||||
promises.push(makeTest(test[0], test[1], test[2]));
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
function makeRequest(body) {
|
||||
var req = new Request("", { method: 'post', body: body,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data; boundary=' + boundary
|
||||
}});
|
||||
return req;
|
||||
}
|
||||
|
||||
function makeResponse(body) {
|
||||
var res = new Response(body, { headers: {
|
||||
'Content-Type': 'multipart/form-data; boundary=' + boundary
|
||||
}});
|
||||
return res;
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
return Promise.all([testFormDataParsing(makeRequest),
|
||||
testFormDataParsing(makeResponse)]);
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="utils.js"> </script>
|
||||
<script type="text/javascript" src="fetch_test_framework.js"> </script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
testScript("test_headers_common.js");
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script type="text/javascript" src="utils.js"> </script>
|
||||
<script type="text/javascript" src="fetch_test_framework.js"> </script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
testScript("test_request.js");
|
||||
|
|
|
@ -220,8 +220,8 @@ function testBodyUsed() {
|
|||
});
|
||||
}
|
||||
|
||||
var text = "κόσμε";
|
||||
function testBodyCreation() {
|
||||
var text = "κόσμε";
|
||||
var req1 = new Request("", { method: 'post', body: text });
|
||||
var p1 = req1.text().then(function(v) {
|
||||
ok(typeof v === "string", "Should resolve to string");
|
||||
|
@ -243,6 +243,8 @@ function testBodyCreation() {
|
|||
is(v, text, "Extracted string should match");
|
||||
});
|
||||
|
||||
// FormData has its own function since it has blobs and files.
|
||||
|
||||
var params = new URLSearchParams();
|
||||
params.append("item", "Geckos");
|
||||
params.append("feature", "stickyfeet");
|
||||
|
@ -258,6 +260,39 @@ function testBodyCreation() {
|
|||
return Promise.all([p1, p2, p2b, pblob, p3]);
|
||||
}
|
||||
|
||||
function testFormDataBodyCreation() {
|
||||
var f1 = new FormData();
|
||||
f1.append("key", "value");
|
||||
f1.append("foo", "bar");
|
||||
|
||||
var r1 = new Request("", { method: 'post', body: f1 })
|
||||
// Since f1 is serialized immediately, later additions should not show up.
|
||||
f1.append("more", "stuff");
|
||||
var p1 = r1.formData().then(function(fd) {
|
||||
ok(fd instanceof FormData, "Valid FormData extracted.");
|
||||
ok(fd.has("key"), "key should exist.");
|
||||
ok(fd.has("foo"), "foo should exist.");
|
||||
ok(!fd.has("more"), "more should not exist.");
|
||||
});
|
||||
|
||||
f1.append("blob", new Blob([text]));
|
||||
var r2 = new Request("", { method: 'post', body: f1 });
|
||||
f1.delete("key");
|
||||
var p2 = r2.formData().then(function(fd) {
|
||||
ok(fd instanceof FormData, "Valid FormData extracted.");
|
||||
ok(fd.has("more"), "more should exist.");
|
||||
|
||||
var b = fd.get("blob");
|
||||
ok(b instanceof Blob, "blob entry should be a Blob.");
|
||||
|
||||
return readAsText(b).then(function(output) {
|
||||
is(output, text, "Blob contents should match.");
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all([p1, p2]);
|
||||
}
|
||||
|
||||
function testBodyExtraction() {
|
||||
var text = "κόσμε";
|
||||
var newReq = function() { return new Request("", { method: 'post', body: text }); }
|
||||
|
@ -283,7 +318,92 @@ function testBodyExtraction() {
|
|||
var dec = new TextDecoder();
|
||||
is(dec.decode(new Uint8Array(v)), text, "UTF-8 decoded ArrayBuffer should match original");
|
||||
});
|
||||
})
|
||||
}).then(function() {
|
||||
return newReq().formData().then(function(v) {
|
||||
ok(false, "invalid FormData read should fail.");
|
||||
}, function(e) {
|
||||
ok(e.name == "TypeError", "invalid FormData read should fail.");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testFormDataBodyExtraction() {
|
||||
// URLSearchParams translates to application/x-www-form-urlencoded.
|
||||
var params = new URLSearchParams();
|
||||
params.append("item", "Geckos");
|
||||
params.append("feature", "stickyfeet");
|
||||
params.append("quantity", "700");
|
||||
params.append("quantity", "800");
|
||||
|
||||
var req = new Request("", { method: 'POST', body: params });
|
||||
var p1 = req.formData().then(function(fd) {
|
||||
ok(fd.has("item"), "Has entry 'item'.");
|
||||
ok(fd.has("feature"), "Has entry 'feature'.");
|
||||
var entries = fd.getAll("quantity");
|
||||
is(entries.length, 2, "Entries with same name are correctly handled.");
|
||||
is(entries[0], "700", "Entries with same name are correctly handled.");
|
||||
is(entries[1], "800", "Entries with same name are correctly handled.");
|
||||
});
|
||||
|
||||
var f1 = new FormData();
|
||||
f1.append("key", "value");
|
||||
f1.append("foo", "bar");
|
||||
f1.append("blob", new Blob([text]));
|
||||
var r2 = new Request("", { method: 'post', body: f1 });
|
||||
var p2 = r2.formData().then(function(fd) {
|
||||
ok(fd.has("key"), "Has entry 'key'.");
|
||||
ok(fd.has("foo"), "Has entry 'foo'.");
|
||||
ok(fd.has("blob"), "Has entry 'blob'.");
|
||||
var entries = fd.getAll("blob");
|
||||
is(entries.length, 1, "getAll returns all items.");
|
||||
is(entries[0].name, "blob", "Filename should be blob.");
|
||||
});
|
||||
|
||||
var ws = "\r\n\r\n\r\n\r\n";
|
||||
f1.set("key", new File([ws], 'file name has spaces.txt', { type: 'new/lines' }));
|
||||
var r3 = new Request("", { method: 'post', body: f1 });
|
||||
var p3 = r3.formData().then(function(fd) {
|
||||
ok(fd.has("foo"), "Has entry 'foo'.");
|
||||
ok(fd.has("blob"), "Has entry 'blob'.");
|
||||
var entries = fd.getAll("blob");
|
||||
is(entries.length, 1, "getAll returns all items.");
|
||||
is(entries[0].name, "blob", "Filename should be blob.");
|
||||
|
||||
ok(fd.has("key"), "Has entry 'key'.");
|
||||
var f = fd.get("key");
|
||||
ok(f instanceof File, "entry should be a File.");
|
||||
is(f.name, "file name has spaces.txt", "File name should match.");
|
||||
is(f.type, "new/lines", "File type should match.");
|
||||
is(f.size, ws.length, "File size should match.");
|
||||
return readAsText(f).then(function(text) {
|
||||
is(text, ws, "File contents should match.");
|
||||
});
|
||||
});
|
||||
|
||||
// Override header and ensure parse fails.
|
||||
var boundary = "1234567891011121314151617";
|
||||
var body = boundary +
|
||||
'\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
|
||||
boundary + '-';
|
||||
|
||||
var r4 = new Request("", { method: 'post', body: body, headers: {
|
||||
"Content-Type": "multipart/form-datafoobar; boundary="+boundary,
|
||||
}});
|
||||
var p4 = r4.formData().then(function() {
|
||||
ok(false, "Invalid mimetype should fail.");
|
||||
}, function() {
|
||||
ok(true, "Invalid mimetype should fail.");
|
||||
});
|
||||
|
||||
var r5 = new Request("", { method: 'POST', body: params, headers: {
|
||||
"Content-Type": "application/x-www-form-urlencodedfoobar",
|
||||
}});
|
||||
var p5 = r5.formData().then(function() {
|
||||
ok(false, "Invalid mimetype should fail.");
|
||||
}, function() {
|
||||
ok(true, "Invalid mimetype should fail.");
|
||||
});
|
||||
return Promise.all([p1, p2, p3, p4]);
|
||||
}
|
||||
|
||||
// mode cannot be set to "CORS-with-forced-preflight" from javascript.
|
||||
|
@ -320,6 +440,8 @@ function runTest() {
|
|||
.then(testBodyCreation)
|
||||
.then(testBodyUsed)
|
||||
.then(testBodyExtraction)
|
||||
.then(testFormDataBodyCreation)
|
||||
.then(testFormDataBodyExtraction)
|
||||
.then(testUsedRequest)
|
||||
.then(testClone())
|
||||
// Put more promise based tests here.
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script type="text/javascript" src="utils.js"> </script>
|
||||
<script type="text/javascript" src="fetch_test_framework.js"> </script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
testScript("test_response.js");
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// Utilities
|
||||
// =========
|
||||
|
||||
// Helper that uses FileReader or FileReaderSync based on context and returns
|
||||
// a Promise that resolves with the text or rejects with error.
|
||||
function readAsText(blob) {
|
||||
if (typeof FileReader !== "undefined") {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var fs = new FileReader();
|
||||
fs.onload = function() {
|
||||
resolve(fs.result);
|
||||
}
|
||||
fs.onerror = reject;
|
||||
fs.readAsText(blob);
|
||||
});
|
||||
} else {
|
||||
var fs = new FileReaderSync();
|
||||
return Promise.resolve(fs.readAsText(blob));
|
||||
}
|
||||
}
|
||||
|
||||
function readAsArrayBuffer(blob) {
|
||||
if (typeof FileReader !== "undefined") {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var fs = new FileReader();
|
||||
fs.onload = function() {
|
||||
resolve(fs.result);
|
||||
}
|
||||
fs.onerror = reject;
|
||||
fs.readAsArrayBuffer(blob);
|
||||
});
|
||||
} else {
|
||||
var fs = new FileReaderSync();
|
||||
return Promise.resolve(fs.readAsArrayBuffer(blob));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
importScripts("utils.js");
|
||||
|
||||
function ok(a, msg) {
|
||||
postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ enum LocaleResourceType {
|
|||
[NoInterfaceObject, NavigatorProperty="mozApps",
|
||||
JSImplementation="@mozilla.org/webapps;1"]
|
||||
interface DOMApplicationsRegistry {
|
||||
[CheckPermissions="webapps-manage"]
|
||||
[CheckPermissions="webapps-manage homescreen-webapps-manage"]
|
||||
readonly attribute DOMApplicationsManager mgmt;
|
||||
DOMRequest install(DOMString url, optional InstallParameters params);
|
||||
DOMRequest installPackage(DOMString url, optional InstallParameters params);
|
||||
|
@ -116,16 +116,22 @@ interface DOMApplication : EventTarget {
|
|||
|
||||
[JSImplementation="@mozilla.org/webapps/manager;1",
|
||||
ChromeOnly,
|
||||
CheckPermissions="webapps-manage"]
|
||||
CheckPermissions="webapps-manage homescreen-webapps-manage"]
|
||||
interface DOMApplicationsManager : EventTarget {
|
||||
DOMRequest getAll();
|
||||
|
||||
[CheckPermissions="webapps-manage"]
|
||||
DOMRequest getNotInstalled();
|
||||
[CheckPermissions="webapps-manage"]
|
||||
void applyDownload(DOMApplication app);
|
||||
DOMRequest uninstall(DOMApplication app);
|
||||
|
||||
[CheckPermissions="webapps-manage"]
|
||||
Promise<DOMApplication> import(Blob blob);
|
||||
[CheckPermissions="webapps-manage"]
|
||||
Promise<any> extractManifest(Blob blob);
|
||||
|
||||
[CheckPermissions="webapps-manage"]
|
||||
void setEnabled(DOMApplication app, boolean state);
|
||||
Promise<Blob> getIcon(DOMApplication app, DOMString iconID,
|
||||
optional DOMString entryPoint);
|
||||
|
|
|
@ -17,8 +17,8 @@ interface Body {
|
|||
Promise<ArrayBuffer> arrayBuffer();
|
||||
[Throws]
|
||||
Promise<Blob> blob();
|
||||
// FIXME(nsm): Bug 739173 FormData is not supported in workers.
|
||||
// Promise<FormData> formData();
|
||||
[Throws]
|
||||
Promise<FormData> formData();
|
||||
[Throws]
|
||||
Promise<JSON> json();
|
||||
[Throws]
|
||||
|
|
|
@ -151,7 +151,7 @@ partial interface HTMLInputElement {
|
|||
[ChromeOnly]
|
||||
sequence<DOMString> mozGetFileNameArray();
|
||||
|
||||
[ChromeOnly]
|
||||
[ChromeOnly, Throws]
|
||||
void mozSetFileNameArray(sequence<DOMString> fileNames);
|
||||
|
||||
[ChromeOnly]
|
||||
|
|
|
@ -216,7 +216,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(XULContentSinkImpl)
|
|||
//----------------------------------------------------------------------
|
||||
// nsIContentSink interface
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::WillBuildModel(nsDTDMode aDTDMode)
|
||||
{
|
||||
#if FIXME
|
||||
|
@ -230,7 +230,7 @@ XULContentSinkImpl::WillBuildModel(nsDTDMode aDTDMode)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::DidBuildModel(bool aTerminated)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
||||
|
@ -245,21 +245,21 @@ XULContentSinkImpl::DidBuildModel(bool aTerminated)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::WillInterrupt(void)
|
||||
{
|
||||
// XXX Notify the docshell, if necessary
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::WillResume(void)
|
||||
{
|
||||
// XXX Notify the docshell, if necessary
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::SetParser(nsParserBase* aParser)
|
||||
{
|
||||
NS_IF_RELEASE(mParser);
|
||||
|
@ -268,14 +268,14 @@ XULContentSinkImpl::SetParser(nsParserBase* aParser)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::SetDocumentCharset(nsACString& aCharset)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
||||
if (doc) {
|
||||
doc->SetDocumentCharacterSet(aCharset);
|
||||
}
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -283,7 +283,7 @@ nsISupports *
|
|||
XULContentSinkImpl::GetTarget()
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
||||
return doc;
|
||||
return doc;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -295,7 +295,7 @@ XULContentSinkImpl::Init(nsIDocument* aDocument,
|
|||
NS_PRECONDITION(aDocument != nullptr, "null ptr");
|
||||
if (! aDocument)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
|
||||
nsresult rv;
|
||||
|
||||
mDocument = do_GetWeakReference(aDocument);
|
||||
|
@ -444,19 +444,19 @@ XULContentSinkImpl::CreateElement(mozilla::dom::NodeInfo *aNodeInfo,
|
|||
/**** BEGIN NEW APIs ****/
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::HandleStartElement(const char16_t *aName,
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::HandleStartElement(const char16_t *aName,
|
||||
const char16_t **aAtts,
|
||||
uint32_t aAttsCount,
|
||||
uint32_t aAttsCount,
|
||||
uint32_t aLineNumber)
|
||||
{
|
||||
{
|
||||
// XXX Hopefully the parser will flag this before we get here. If
|
||||
// we're in the epilog, there should be no new elements
|
||||
NS_PRECONDITION(mState != eInEpilog, "tag in XUL doc epilog");
|
||||
NS_PRECONDITION(aAttsCount % 2 == 0, "incorrect aAttsCount");
|
||||
// Adjust aAttsCount so it's the actual number of attributes
|
||||
aAttsCount /= 2;
|
||||
|
||||
|
||||
if (mState == eInEpilog)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
|
@ -472,7 +472,7 @@ XULContentSinkImpl::HandleStartElement(const char16_t *aName,
|
|||
nsRefPtr<mozilla::dom::NodeInfo> nodeInfo;
|
||||
nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
|
||||
nsIDOMNode::ELEMENT_NODE);
|
||||
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
switch (mState) {
|
||||
case eInProlog:
|
||||
|
@ -496,7 +496,7 @@ XULContentSinkImpl::HandleStartElement(const char16_t *aName,
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::HandleEndElement(const char16_t *aName)
|
||||
{
|
||||
// Never EVER return anything but NS_OK or
|
||||
|
@ -583,32 +583,32 @@ XULContentSinkImpl::HandleEndElement(const char16_t *aName)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::HandleComment(const char16_t *aName)
|
||||
{
|
||||
FlushText();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::HandleCDataSection(const char16_t *aData, uint32_t aLength)
|
||||
{
|
||||
FlushText();
|
||||
return AddText(aData, aLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::HandleDoctypeDecl(const nsAString & aSubset,
|
||||
const nsAString & aName,
|
||||
const nsAString & aSystemId,
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::HandleDoctypeDecl(const nsAString & aSubset,
|
||||
const nsAString & aName,
|
||||
const nsAString & aSystemId,
|
||||
const nsAString & aPublicId,
|
||||
nsISupports* aCatalogData)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::HandleCharacterData(const char16_t *aData,
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::HandleCharacterData(const char16_t *aData,
|
||||
uint32_t aLength)
|
||||
{
|
||||
if (aData && mState != eInProlog && mState != eInEpilog) {
|
||||
|
@ -617,8 +617,8 @@ XULContentSinkImpl::HandleCharacterData(const char16_t *aData,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::HandleProcessingInstruction(const char16_t *aTarget,
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::HandleProcessingInstruction(const char16_t *aTarget,
|
||||
const char16_t *aData)
|
||||
{
|
||||
FlushText();
|
||||
|
@ -661,7 +661,7 @@ XULContentSinkImpl::HandleXMLDeclaration(const char16_t *aVersion,
|
|||
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULContentSinkImpl::ReportError(const char16_t* aErrorText,
|
||||
XULContentSinkImpl::ReportError(const char16_t* aErrorText,
|
||||
const char16_t* aSourceText,
|
||||
nsIScriptError *aError,
|
||||
bool *_retval)
|
||||
|
@ -698,26 +698,26 @@ XULContentSinkImpl::ReportError(const char16_t* aErrorText,
|
|||
nsAutoString parsererror(errorNs);
|
||||
parsererror.Append((char16_t)0xFFFF);
|
||||
parsererror.AppendLiteral("parsererror");
|
||||
|
||||
|
||||
rv = HandleStartElement(parsererror.get(), noAtts, 0, 0);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = HandleCharacterData(aErrorText, NS_strlen(aErrorText));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsAutoString sourcetext(errorNs);
|
||||
sourcetext.Append((char16_t)0xFFFF);
|
||||
sourcetext.AppendLiteral("sourcetext");
|
||||
|
||||
rv = HandleStartElement(sourcetext.get(), noAtts, 0, 0);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
|
||||
rv = HandleCharacterData(aSourceText, NS_strlen(aSourceText));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
|
||||
rv = HandleEndElement(sourcetext.get());
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = HandleEndElement(parsererror.get());
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
|
@ -725,8 +725,8 @@ XULContentSinkImpl::ReportError(const char16_t* aErrorText,
|
|||
}
|
||||
|
||||
nsresult
|
||||
XULContentSinkImpl::OpenRoot(const char16_t** aAttributes,
|
||||
const uint32_t aAttrLen,
|
||||
XULContentSinkImpl::OpenRoot(const char16_t** aAttributes,
|
||||
const uint32_t aAttrLen,
|
||||
mozilla::dom::NodeInfo *aNodeInfo)
|
||||
{
|
||||
NS_ASSERTION(mState == eInProlog, "how'd we get here?");
|
||||
|
@ -735,7 +735,7 @@ XULContentSinkImpl::OpenRoot(const char16_t** aAttributes,
|
|||
|
||||
nsresult rv;
|
||||
|
||||
if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) ||
|
||||
if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) ||
|
||||
aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XUL)) {
|
||||
PR_LOG(gContentSinkLog, PR_LOG_ERROR,
|
||||
("xul: script tag not allowed as root content element"));
|
||||
|
@ -779,7 +779,7 @@ XULContentSinkImpl::OpenRoot(const char16_t** aAttributes,
|
|||
}
|
||||
|
||||
nsresult
|
||||
XULContentSinkImpl::OpenTag(const char16_t** aAttributes,
|
||||
XULContentSinkImpl::OpenTag(const char16_t** aAttributes,
|
||||
const uint32_t aAttrLen,
|
||||
const uint32_t aLineNumber,
|
||||
mozilla::dom::NodeInfo *aNodeInfo)
|
||||
|
@ -819,7 +819,7 @@ XULContentSinkImpl::OpenTag(const char16_t** aAttributes,
|
|||
|
||||
children->AppendElement(element);
|
||||
|
||||
if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) ||
|
||||
if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) ||
|
||||
aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XUL)) {
|
||||
// Do scripty things now
|
||||
rv = OpenScript(aAttributes, aLineNumber);
|
||||
|
@ -828,7 +828,7 @@ XULContentSinkImpl::OpenTag(const char16_t** aAttributes,
|
|||
NS_ASSERTION(mState == eInScript || mState == eInDocumentElement,
|
||||
"Unexpected state");
|
||||
if (mState == eInScript) {
|
||||
// OpenScript has pushed the nsPrototypeScriptElement onto the
|
||||
// OpenScript has pushed the nsPrototypeScriptElement onto the
|
||||
// stack, so we're done.
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -964,8 +964,8 @@ XULContentSinkImpl::OpenScript(const char16_t** aAttributes,
|
|||
}
|
||||
|
||||
nsresult
|
||||
XULContentSinkImpl::AddAttributes(const char16_t** aAttributes,
|
||||
const uint32_t aAttrLen,
|
||||
XULContentSinkImpl::AddAttributes(const char16_t** aAttributes,
|
||||
const uint32_t aAttrLen,
|
||||
nsXULPrototypeElement* aElement)
|
||||
{
|
||||
// Add tag attributes to the element
|
||||
|
@ -1013,7 +1013,7 @@ XULContentSinkImpl::AddAttributes(const char16_t** aAttributes,
|
|||
}
|
||||
|
||||
nsresult
|
||||
XULContentSinkImpl::AddText(const char16_t* aText,
|
||||
XULContentSinkImpl::AddText(const char16_t* aText,
|
||||
int32_t aLength)
|
||||
{
|
||||
// Create buffer when we first need it
|
||||
|
@ -1047,7 +1047,7 @@ XULContentSinkImpl::AddText(const char16_t* aText,
|
|||
}
|
||||
}
|
||||
memcpy(&mText[mTextLength],aText + offset, sizeof(char16_t) * amount);
|
||||
|
||||
|
||||
mTextLength += amount;
|
||||
offset += amount;
|
||||
aLength -= amount;
|
||||
|
|
|
@ -156,6 +156,12 @@ public:
|
|||
SetLayer(aLayer);
|
||||
mAttached = true;
|
||||
mKeepAttached = aFlags & KEEP_ATTACHED;
|
||||
|
||||
// If we already have a textureHost before, use that in this moment.
|
||||
RefPtr<TextureHost> frontBuffer = GetAsTextureHost();
|
||||
if (frontBuffer) {
|
||||
UseTextureHost(frontBuffer);
|
||||
}
|
||||
}
|
||||
// Detach this compositable host from its layer.
|
||||
// If we are used for async video, then it is not safe to blindly detach since
|
||||
|
|
|
@ -345,7 +345,7 @@ UnclipViewport(const SVGImageContext& aOldContext,
|
|||
|
||||
// Map the viewport to the inner image. (Note that we don't take the aSize
|
||||
// parameter of Draw into account, just the clipping region.)
|
||||
nsIntSize vSize(aOldContext.GetViewportSize());
|
||||
CSSIntSize vSize(aOldContext.GetViewportSize());
|
||||
vSize.width = ceil(vSize.width * double(innerSize.width) / clipSize.width);
|
||||
vSize.height = ceil(vSize.height * double(innerSize.height) / clipSize.height);
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ static SVGImageContext
|
|||
OrientViewport(const SVGImageContext& aOldContext,
|
||||
const Orientation& aOrientation)
|
||||
{
|
||||
nsIntSize viewportSize(aOldContext.GetViewportSize());
|
||||
CSSIntSize viewportSize(aOldContext.GetViewportSize());
|
||||
if (aOrientation.SwapsWidthAndHeight()) {
|
||||
swap(viewportSize.width, viewportSize.height);
|
||||
}
|
||||
|
|
|
@ -719,11 +719,16 @@ struct SVGDrawingParameters
|
|||
, region(aRegion)
|
||||
, filter(aFilter)
|
||||
, svgContext(aSVGContext)
|
||||
, viewportSize(aSVGContext ? aSVGContext->GetViewportSize() : aSize)
|
||||
, viewportSize(aSize)
|
||||
, animationTime(aAnimationTime)
|
||||
, flags(aFlags)
|
||||
, opacity(aSVGContext ? aSVGContext->GetGlobalOpacity() : 1.0)
|
||||
{ }
|
||||
{
|
||||
if (aSVGContext) {
|
||||
CSSIntSize sz = aSVGContext->GetViewportSize();
|
||||
viewportSize = nsIntSize(sz.width, sz.height); // XXX losing unit
|
||||
}
|
||||
}
|
||||
|
||||
gfxContext* context;
|
||||
IntSize size;
|
||||
|
|
|
@ -73,6 +73,11 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Linux':
|
|||
if '-flto' in CONFIG['OS_CXXFLAGS'] and not CONFIG['CLANG_CXX']:
|
||||
LDFLAGS += ['--param lto-partitions=1']
|
||||
|
||||
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Darwin':
|
||||
USE_LIBS += [
|
||||
'mozsandbox',
|
||||
]
|
||||
|
||||
if CONFIG['_MSC_VER']:
|
||||
# Always enter a Windows program through wmain, whether or not we're
|
||||
# a console application.
|
||||
|
|
|
@ -80,10 +80,11 @@ static bool gIsSandboxEnabled = false;
|
|||
|
||||
class WinSandboxStarter : public mozilla::gmp::SandboxStarter {
|
||||
public:
|
||||
virtual void Start(const char *aLibPath) override {
|
||||
virtual bool Start(const char *aLibPath) override {
|
||||
if (gIsSandboxEnabled) {
|
||||
sandbox::SandboxFactory::GetTargetServices()->LowerToken();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
@ -101,23 +102,41 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
virtual void Start(const char *aLibPath) override {
|
||||
virtual bool Start(const char *aLibPath) override {
|
||||
mozilla::SetMediaPluginSandbox(aLibPath);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
|
||||
class MacSandboxStarter : public mozilla::gmp::SandboxStarter {
|
||||
public:
|
||||
virtual bool Start(const char *aLibPath) override {
|
||||
std::string err;
|
||||
bool rv = mozilla::StartMacSandbox(mInfo, err);
|
||||
if (!rv) {
|
||||
fprintf(stderr, "sandbox_init() failed! Error \"%s\"\n", err.c_str());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
virtual void SetSandboxInfo(MacSandboxInfo* aSandboxInfo) override {
|
||||
mInfo = *aSandboxInfo;
|
||||
}
|
||||
private:
|
||||
MacSandboxInfo mInfo;
|
||||
};
|
||||
#endif
|
||||
|
||||
mozilla::gmp::SandboxStarter*
|
||||
MakeSandboxStarter()
|
||||
{
|
||||
// Note: MacOSX creates its SandboxStarter inside xul code; it
|
||||
// needs to change to statically link its sandbox code into
|
||||
// plugin-container. Once it does that, we can create the
|
||||
// SandboxStarter for it here.
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
return new WinSandboxStarter();
|
||||
#elif defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
|
||||
return LinuxSandboxStarter::Make();
|
||||
#elif defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
|
||||
return new MacSandboxStarter();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
|
|
|
@ -134,12 +134,12 @@ AsmJSModule::trace(JSTracer* trc)
|
|||
globals_[i].trace(trc);
|
||||
for (unsigned i = 0; i < exits_.length(); i++) {
|
||||
if (exitIndexToGlobalDatum(i).fun)
|
||||
MarkObject(trc, &exitIndexToGlobalDatum(i).fun, "asm.js imported function");
|
||||
TraceEdge(trc, &exitIndexToGlobalDatum(i).fun, "asm.js imported function");
|
||||
}
|
||||
for (unsigned i = 0; i < exports_.length(); i++)
|
||||
exports_[i].trace(trc);
|
||||
for (unsigned i = 0; i < names_.length(); i++)
|
||||
MarkStringUnbarriered(trc, &names_[i].name(), "asm.js module function name");
|
||||
TraceManuallyBarrieredEdge(trc, &names_[i].name(), "asm.js module function name");
|
||||
#if defined(MOZ_VTUNE) || defined(JS_ION_PERF)
|
||||
for (unsigned i = 0; i < profiledFunctions_.length(); i++)
|
||||
profiledFunctions_[i].trace(trc);
|
||||
|
@ -149,13 +149,13 @@ AsmJSModule::trace(JSTracer* trc)
|
|||
perfProfiledBlocksFunctions_[i].trace(trc);
|
||||
#endif
|
||||
if (globalArgumentName_)
|
||||
MarkStringUnbarriered(trc, &globalArgumentName_, "asm.js global argument name");
|
||||
TraceManuallyBarrieredEdge(trc, &globalArgumentName_, "asm.js global argument name");
|
||||
if (importArgumentName_)
|
||||
MarkStringUnbarriered(trc, &importArgumentName_, "asm.js import argument name");
|
||||
TraceManuallyBarrieredEdge(trc, &importArgumentName_, "asm.js import argument name");
|
||||
if (bufferArgumentName_)
|
||||
MarkStringUnbarriered(trc, &bufferArgumentName_, "asm.js buffer argument name");
|
||||
TraceManuallyBarrieredEdge(trc, &bufferArgumentName_, "asm.js buffer argument name");
|
||||
if (maybeHeap_)
|
||||
gc::MarkObject(trc, &maybeHeap_, "asm.js heap");
|
||||
TraceEdge(trc, &maybeHeap_, "asm.js heap");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -258,7 +258,7 @@ class AsmJSModule
|
|||
|
||||
void trace(JSTracer* trc) {
|
||||
if (name_)
|
||||
MarkStringUnbarriered(trc, &name_, "asm.js global name");
|
||||
TraceManuallyBarrieredEdge(trc, &name_, "asm.js global name");
|
||||
MOZ_ASSERT_IF(pod.which_ == Variable && pod.u.var.initKind_ == InitConstant,
|
||||
!pod.u.var.u.numLit_.scalarValue().isMarkable());
|
||||
}
|
||||
|
@ -476,9 +476,9 @@ class AsmJSModule
|
|||
}
|
||||
|
||||
void trace(JSTracer* trc) {
|
||||
MarkStringUnbarriered(trc, &name_, "asm.js export name");
|
||||
TraceManuallyBarrieredEdge(trc, &name_, "asm.js export name");
|
||||
if (maybeFieldName_)
|
||||
MarkStringUnbarriered(trc, &maybeFieldName_, "asm.js export field");
|
||||
TraceManuallyBarrieredEdge(trc, &maybeFieldName_, "asm.js export field");
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -680,7 +680,7 @@ class AsmJSModule
|
|||
|
||||
void trace(JSTracer* trc) {
|
||||
if (name)
|
||||
MarkStringUnbarriered(trc, &name, "asm.js profiled function name");
|
||||
TraceManuallyBarrieredEdge(trc, &name, "asm.js profiled function name");
|
||||
}
|
||||
|
||||
size_t serializedSize() const;
|
||||
|
|
|
@ -1628,7 +1628,7 @@ OutlineTypedObject::obj_trace(JSTracer* trc, JSObject* object)
|
|||
{
|
||||
OutlineTypedObject& typedObj = object->as<OutlineTypedObject>();
|
||||
|
||||
MarkShape(trc, &typedObj.shape_, "OutlineTypedObject_shape");
|
||||
TraceEdge(trc, &typedObj.shape_, "OutlineTypedObject_shape");
|
||||
|
||||
if (!typedObj.owner_)
|
||||
return;
|
||||
|
@ -1641,7 +1641,7 @@ OutlineTypedObject::obj_trace(JSTracer* trc, JSObject* object)
|
|||
|
||||
// Mark the owner, watching in case it is moved by the tracer.
|
||||
JSObject* oldOwner = typedObj.owner_;
|
||||
gc::MarkObjectUnbarriered(trc, &typedObj.owner_, "typed object owner");
|
||||
TraceManuallyBarrieredEdge(trc, &typedObj.owner_, "typed object owner");
|
||||
JSObject* owner = typedObj.owner_;
|
||||
|
||||
uint8_t* oldData = typedObj.outOfLineTypedMem();
|
||||
|
@ -2141,7 +2141,7 @@ InlineTypedObject::obj_trace(JSTracer* trc, JSObject* object)
|
|||
{
|
||||
InlineTypedObject& typedObj = object->as<InlineTypedObject>();
|
||||
|
||||
MarkShape(trc, &typedObj.shape_, "InlineTypedObject_shape");
|
||||
TraceEdge(trc, &typedObj.shape_, "InlineTypedObject_shape");
|
||||
|
||||
// Inline transparent objects do not have references and do not need more
|
||||
// tracing. If there is an entry in the compartment's LazyArrayBufferTable,
|
||||
|
@ -2946,7 +2946,7 @@ MemoryTracingVisitor::visitReference(ReferenceTypeDescr& descr, uint8_t* mem)
|
|||
{
|
||||
HeapPtrObject* objectPtr = reinterpret_cast<js::HeapPtrObject*>(mem);
|
||||
if (*objectPtr)
|
||||
gc::MarkObject(trace_, objectPtr, "reference-obj");
|
||||
TraceEdge(trace_, objectPtr, "reference-obj");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2954,7 +2954,7 @@ MemoryTracingVisitor::visitReference(ReferenceTypeDescr& descr, uint8_t* mem)
|
|||
{
|
||||
HeapPtrString* stringPtr = reinterpret_cast<js::HeapPtrString*>(mem);
|
||||
if (*stringPtr)
|
||||
gc::MarkString(trace_, stringPtr, "reference-str");
|
||||
TraceEdge(trace_, stringPtr, "reference-str");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1128,7 +1128,7 @@ ObjectBox::trace(JSTracer* trc)
|
|||
{
|
||||
ObjectBox* box = this;
|
||||
while (box) {
|
||||
MarkObjectRoot(trc, &box->object, "parser.object");
|
||||
TraceRoot(trc, &box->object, "parser.object");
|
||||
if (box->isFunctionBox())
|
||||
box->asFunctionBox()->bindings.trace(trc);
|
||||
box = box->traceLink;
|
||||
|
|
|
@ -231,16 +231,10 @@ template <> struct MapTypeToTraceKind<UnownedBaseShape> { static const JSGCTrace
|
|||
template <> struct MapTypeToTraceKind<jit::JitCode> { static const JSGCTraceKind kind = JSTRACE_JITCODE; };
|
||||
template <> struct MapTypeToTraceKind<ObjectGroup> { static const JSGCTraceKind kind = JSTRACE_OBJECT_GROUP; };
|
||||
|
||||
// Direct value access used by the write barriers and the jits.
|
||||
void
|
||||
MarkValueForBarrier(JSTracer* trc, Value* v, const char* name);
|
||||
|
||||
// These three declarations are also present in gc/Marking.h, via the DeclMarker
|
||||
// macro. Not great, but hard to avoid.
|
||||
void
|
||||
MarkStringUnbarriered(JSTracer* trc, JSString** str, const char* name);
|
||||
void
|
||||
MarkSymbolUnbarriered(JSTracer* trc, JS::Symbol** sym, const char* name);
|
||||
// Marking.h depends on these barrier definitions, so we need a separate
|
||||
// entry point for marking to implement the pre-barrier.
|
||||
void MarkValueForBarrier(JSTracer* trc, Value* v, const char* name);
|
||||
void MarkIdForBarrier(JSTracer* trc, jsid* idp, const char* name);
|
||||
|
||||
} // namespace gc
|
||||
|
||||
|
@ -283,6 +277,13 @@ ZoneOfValueFromAnyThread(const JS::Value& value)
|
|||
return js::gc::TenuredCell::fromPointer(value.toGCThing())->zoneFromAnyThread();
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE JS::Zone*
|
||||
ZoneOfIdFromAnyThread(const jsid& id)
|
||||
{
|
||||
MOZ_ASSERT(JSID_IS_GCTHING(id));
|
||||
return js::gc::TenuredCell::fromPointer(JSID_TO_GCTHING(id).asCell())->zoneFromAnyThread();
|
||||
}
|
||||
|
||||
void
|
||||
ValueReadBarrier(const Value& value);
|
||||
|
||||
|
@ -387,19 +388,13 @@ struct InternalGCMethods<jsid>
|
|||
static bool isMarkable(jsid id) { return JSID_IS_STRING(id) || JSID_IS_SYMBOL(id); }
|
||||
|
||||
static void preBarrier(jsid id) {
|
||||
if (JSID_IS_STRING(id)) {
|
||||
JSString* str = JSID_TO_STRING(id);
|
||||
JS::shadow::Zone* shadowZone = ShadowZoneOfStringFromAnyThread(str);
|
||||
if (JSID_IS_GCTHING(id)) {
|
||||
JS::Zone* zone = ZoneOfIdFromAnyThread(id);
|
||||
JS::shadow::Zone* shadowZone = JS::shadow::Zone::asShadowZone(zone);
|
||||
if (shadowZone->needsIncrementalBarrier()) {
|
||||
js::gc::MarkStringUnbarriered(shadowZone->barrierTracer(), &str, "write barrier");
|
||||
MOZ_ASSERT(str == JSID_TO_STRING(id));
|
||||
}
|
||||
} else if (JSID_IS_SYMBOL(id)) {
|
||||
JS::Symbol* sym = JSID_TO_SYMBOL(id);
|
||||
JS::shadow::Zone* shadowZone = ShadowZoneOfSymbolFromAnyThread(sym);
|
||||
if (shadowZone->needsIncrementalBarrier()) {
|
||||
js::gc::MarkSymbolUnbarriered(shadowZone->barrierTracer(), &sym, "write barrier");
|
||||
MOZ_ASSERT(sym == JSID_TO_SYMBOL(id));
|
||||
jsid tmp(id);
|
||||
js::gc::MarkIdForBarrier(shadowZone->barrierTracer(), &tmp, "id write barrier");
|
||||
MOZ_ASSERT(tmp == id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -292,13 +292,6 @@ SetMaybeAliveFlag(JSObject* thing)
|
|||
thing->compartment()->maybeAlive = true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
SetMaybeAliveFlag(NativeObject* thing)
|
||||
{
|
||||
thing->compartment()->maybeAlive = true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
SetMaybeAliveFlag(JSScript* thing)
|
||||
|
@ -342,6 +335,7 @@ FOR_EACH_GC_LAYOUT(NAMES)
|
|||
D(PlainObject*) \
|
||||
D(SavedFrame*) \
|
||||
D(ScopeObject*) \
|
||||
D(ScriptSourceObject*) \
|
||||
D(SharedArrayBufferObject*) \
|
||||
D(SharedTypedArrayObject*) \
|
||||
D(JSScript*) \
|
||||
|
@ -394,6 +388,13 @@ template <> struct PtrBaseGCType<Value> { typedef Value type; };
|
|||
template <> struct PtrBaseGCType<jsid> { typedef jsid type; };
|
||||
template <typename T> struct PtrBaseGCType<T*> { typedef typename BaseGCType<T>::type* type; };
|
||||
|
||||
template <typename T>
|
||||
typename PtrBaseGCType<T>::type*
|
||||
ConvertToBase(T* thingp)
|
||||
{
|
||||
return reinterpret_cast<typename PtrBaseGCType<T>::type*>(thingp);
|
||||
}
|
||||
|
||||
template <typename T> void DispatchToTracer(JSTracer* trc, T* thingp, const char* name, size_t i);
|
||||
template <typename T> void DoTracing(JS::CallbackTracer* trc, T* thingp, const char* name, size_t i);
|
||||
template <typename T> void DoMarking(GCMarker* gcmarker, T thing);
|
||||
|
@ -404,16 +405,14 @@ template <typename T>
|
|||
void
|
||||
js::TraceEdge(JSTracer* trc, BarrieredBase<T>* thingp, const char* name)
|
||||
{
|
||||
auto layout = reinterpret_cast<typename PtrBaseGCType<T>::type*>(thingp->unsafeGet());
|
||||
DispatchToTracer(trc, layout, name, JSTracer::InvalidIndex);
|
||||
DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name, JSTracer::InvalidIndex);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
js::TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name)
|
||||
{
|
||||
auto layout = reinterpret_cast<typename PtrBaseGCType<T>::type*>(thingp);
|
||||
DispatchToTracer(trc, layout, name, JSTracer::InvalidIndex);
|
||||
DispatchToTracer(trc, ConvertToBase(thingp), name, JSTracer::InvalidIndex);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -421,28 +420,27 @@ void
|
|||
js::TraceRoot(JSTracer* trc, T* thingp, const char* name)
|
||||
{
|
||||
JS_ROOT_MARKING_ASSERT(trc);
|
||||
auto layout = reinterpret_cast<typename PtrBaseGCType<T>::type*>(thingp);
|
||||
DispatchToTracer(trc, layout, name, JSTracer::InvalidIndex);
|
||||
DispatchToTracer(trc, ConvertToBase(thingp), name, JSTracer::InvalidIndex);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
js::TraceRange(JSTracer* trc, size_t len, BarrieredBase<T>* thingp, const char* name)
|
||||
js::TraceRange(JSTracer* trc, size_t len, BarrieredBase<T>* vec, const char* name)
|
||||
{
|
||||
for (auto i : MakeRange(len)) {
|
||||
auto layout = reinterpret_cast<typename PtrBaseGCType<T>::type*>(&thingp[i]);
|
||||
DispatchToTracer(trc, layout, name, i);
|
||||
if (InternalGCMethods<T>::isMarkable(vec[i].get()))
|
||||
DispatchToTracer(trc, ConvertToBase(vec[i].unsafeGet()), name, i);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
js::TraceRootRange(JSTracer* trc, size_t len, T* thingp, const char* name)
|
||||
js::TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name)
|
||||
{
|
||||
JS_ROOT_MARKING_ASSERT(trc);
|
||||
for (auto i : MakeRange(len)) {
|
||||
auto layout = reinterpret_cast<typename PtrBaseGCType<T>::type*>(&thingp[i]);
|
||||
DispatchToTracer(trc, layout, name, i);
|
||||
if (InternalGCMethods<T>::isMarkable(vec[i]))
|
||||
DispatchToTracer(trc, ConvertToBase(&vec[i]), name, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -797,8 +795,14 @@ namespace gc {
|
|||
|
||||
template <typename T>
|
||||
static inline void
|
||||
CheckIsMarkedThing(T** thingp)
|
||||
CheckIsMarkedThing(T* thingp)
|
||||
{
|
||||
#define IS_SAME_TYPE_OR(name, type) mozilla::IsSame<type*, T>::value ||
|
||||
static_assert(
|
||||
FOR_EACH_GC_LAYOUT(IS_SAME_TYPE_OR)
|
||||
false, "Only the base cell layout types are allowed into marking/tracing internals");
|
||||
#undef IS_SAME_TYPE_OR
|
||||
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(thingp);
|
||||
MOZ_ASSERT(*thingp);
|
||||
|
@ -811,7 +815,7 @@ CheckIsMarkedThing(T** thingp)
|
|||
|
||||
template <typename T>
|
||||
static bool
|
||||
IsMarked(T** thingp)
|
||||
IsMarkedInternal(T* thingp)
|
||||
{
|
||||
CheckIsMarkedThing(thingp);
|
||||
JSRuntime* rt = (*thingp)->runtimeFromAnyThread();
|
||||
|
@ -829,12 +833,50 @@ IsMarked(T** thingp)
|
|||
return (*thingp)->asTenured().isMarked();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
IsMarkedInternal<Value>(Value* valuep)
|
||||
{
|
||||
bool rv = true; // Non-markable types are always live.
|
||||
if (valuep->isString()) {
|
||||
JSString* str = valuep->toString();
|
||||
rv = IsMarkedInternal(&str);
|
||||
valuep->setString(str);
|
||||
} else if (valuep->isObject()) {
|
||||
JSObject* obj = &valuep->toObject();
|
||||
rv = IsMarkedInternal(&obj);
|
||||
valuep->setObject(*obj);
|
||||
} else if (valuep->isSymbol()) {
|
||||
JS::Symbol* sym = valuep->toSymbol();
|
||||
rv = IsMarkedInternal(&sym);
|
||||
valuep->setSymbol(sym);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
IsMarkedInternal<jsid>(jsid* idp)
|
||||
{
|
||||
bool rv = true; // Non-markable types are always live.
|
||||
if (JSID_IS_STRING(*idp)) {
|
||||
JSString* str = JSID_TO_STRING(*idp);
|
||||
rv = IsMarkedInternal(&str);
|
||||
*idp = NON_INTEGER_ATOM_TO_JSID(reinterpret_cast<JSAtom*>(str));
|
||||
} else if (JSID_IS_SYMBOL(*idp)) {
|
||||
JS::Symbol* sym = JSID_TO_SYMBOL(*idp);
|
||||
rv = IsMarkedInternal(&sym);
|
||||
*idp = SYMBOL_TO_JSID(sym);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool
|
||||
IsAboutToBeFinalized(T** thingp)
|
||||
IsAboutToBeFinalizedInternal(T* thingp)
|
||||
{
|
||||
CheckIsMarkedThing(thingp);
|
||||
T* thing = *thingp;
|
||||
T thing = *thingp;
|
||||
JSRuntime* rt = thing->runtimeFromAnyThread();
|
||||
|
||||
/* Permanent atoms are never finalized by non-owning runtimes. */
|
||||
|
@ -863,6 +905,97 @@ IsAboutToBeFinalized(T** thingp)
|
|||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
IsAboutToBeFinalizedInternal<Value>(Value* valuep)
|
||||
{
|
||||
bool rv = false; // Non-markable types are always live.
|
||||
if (valuep->isString()) {
|
||||
JSString* str = (JSString*)valuep->toGCThing();
|
||||
rv = IsAboutToBeFinalizedInternal(&str);
|
||||
valuep->setString(str);
|
||||
} else if (valuep->isObject()) {
|
||||
JSObject* obj = (JSObject*)valuep->toGCThing();
|
||||
rv = IsAboutToBeFinalizedInternal(&obj);
|
||||
valuep->setObject(*obj);
|
||||
} else if (valuep->isSymbol()) {
|
||||
JS::Symbol* sym = valuep->toSymbol();
|
||||
rv = IsAboutToBeFinalizedInternal(&sym);
|
||||
valuep->setSymbol(sym);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
IsAboutToBeFinalizedInternal<jsid>(jsid* idp)
|
||||
{
|
||||
bool rv = false; // Non-markable types are always live.
|
||||
if (JSID_IS_STRING(*idp)) {
|
||||
JSString* str = JSID_TO_STRING(*idp);
|
||||
rv = IsAboutToBeFinalizedInternal(&str);
|
||||
*idp = NON_INTEGER_ATOM_TO_JSID(reinterpret_cast<JSAtom*>(str));
|
||||
} else if (JSID_IS_SYMBOL(*idp)) {
|
||||
JS::Symbol* sym = JSID_TO_SYMBOL(*idp);
|
||||
rv = IsAboutToBeFinalizedInternal(&sym);
|
||||
*idp = SYMBOL_TO_JSID(sym);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
IsMarkedUnbarriered(T* thingp)
|
||||
{
|
||||
return IsMarkedInternal(ConvertToBase(thingp));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
IsMarked(BarrieredBase<T>* thingp)
|
||||
{
|
||||
return IsMarkedInternal(ConvertToBase(thingp->unsafeGet()));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
IsMarked(ReadBarriered<T>* thingp)
|
||||
{
|
||||
return IsMarkedInternal(ConvertToBase(thingp->unsafeGet()));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
IsAboutToBeFinalizedUnbarriered(T* thingp)
|
||||
{
|
||||
return IsAboutToBeFinalizedInternal(ConvertToBase(thingp));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
IsAboutToBeFinalized(BarrieredBase<T>* thingp)
|
||||
{
|
||||
return IsAboutToBeFinalizedInternal(ConvertToBase(thingp->unsafeGet()));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
IsAboutToBeFinalized(ReadBarriered<T>* thingp)
|
||||
{
|
||||
return IsAboutToBeFinalizedInternal(ConvertToBase(thingp->unsafeGet()));
|
||||
}
|
||||
|
||||
// Instantiate a copy of the Tracing templates for each derived type.
|
||||
#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(type) \
|
||||
template bool IsMarkedUnbarriered<type>(type*); \
|
||||
template bool IsMarked<type>(BarrieredBase<type>*); \
|
||||
template bool IsMarked<type>(ReadBarriered<type>*); \
|
||||
template bool IsAboutToBeFinalizedUnbarriered<type>(type*); \
|
||||
template bool IsAboutToBeFinalized<type>(BarrieredBase<type>*); \
|
||||
template bool IsAboutToBeFinalized<type>(ReadBarriered<type>*);
|
||||
FOR_EACH_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS)
|
||||
#undef INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS
|
||||
|
||||
template <typename T>
|
||||
T*
|
||||
UpdateIfRelocated(JSRuntime* rt, T** thingp)
|
||||
|
@ -922,25 +1055,25 @@ Mark##base##RootRange(JSTracer* trc, size_t len, type** vec, const char* name)
|
|||
bool \
|
||||
Is##base##Marked(type** thingp) \
|
||||
{ \
|
||||
return IsMarked<type>(thingp); \
|
||||
return IsMarkedUnbarriered<type*>(thingp); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
Is##base##Marked(BarrieredBase<type*>* thingp) \
|
||||
{ \
|
||||
return IsMarked<type>(thingp->unsafeGet()); \
|
||||
return IsMarked<type*>(thingp); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
Is##base##AboutToBeFinalized(type** thingp) \
|
||||
{ \
|
||||
return IsAboutToBeFinalized<type>(thingp); \
|
||||
return IsAboutToBeFinalizedUnbarriered<type*>(thingp); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
Is##base##AboutToBeFinalized(BarrieredBase<type*>* thingp) \
|
||||
{ \
|
||||
return IsAboutToBeFinalized<type>(thingp->unsafeGet()); \
|
||||
return IsAboutToBeFinalized<type*>(thingp); \
|
||||
} \
|
||||
\
|
||||
type * \
|
||||
|
@ -955,37 +1088,6 @@ Update##base##IfRelocated(JSRuntime* rt, type** thingp)
|
|||
return UpdateIfRelocated<type>(rt, thingp); \
|
||||
}
|
||||
|
||||
|
||||
DeclMarkerImpl(BaseShape, BaseShape)
|
||||
DeclMarkerImpl(BaseShape, UnownedBaseShape)
|
||||
DeclMarkerImpl(JitCode, jit::JitCode)
|
||||
DeclMarkerImpl(Object, NativeObject)
|
||||
DeclMarkerImpl(Object, ArrayObject)
|
||||
DeclMarkerImpl(Object, ArgumentsObject)
|
||||
DeclMarkerImpl(Object, ArrayBufferObject)
|
||||
DeclMarkerImpl(Object, ArrayBufferObjectMaybeShared)
|
||||
DeclMarkerImpl(Object, ArrayBufferViewObject)
|
||||
DeclMarkerImpl(Object, DebugScopeObject)
|
||||
DeclMarkerImpl(Object, GlobalObject)
|
||||
DeclMarkerImpl(Object, JSObject)
|
||||
DeclMarkerImpl(Object, JSFunction)
|
||||
DeclMarkerImpl(Object, NestedScopeObject)
|
||||
DeclMarkerImpl(Object, PlainObject)
|
||||
DeclMarkerImpl(Object, SavedFrame)
|
||||
DeclMarkerImpl(Object, ScopeObject)
|
||||
DeclMarkerImpl(Object, SharedArrayBufferObject)
|
||||
DeclMarkerImpl(Object, SharedTypedArrayObject)
|
||||
DeclMarkerImpl(Script, JSScript)
|
||||
DeclMarkerImpl(LazyScript, LazyScript)
|
||||
DeclMarkerImpl(Shape, Shape)
|
||||
DeclMarkerImpl(String, JSAtom)
|
||||
DeclMarkerImpl(String, JSString)
|
||||
DeclMarkerImpl(String, JSFlatString)
|
||||
DeclMarkerImpl(String, JSLinearString)
|
||||
DeclMarkerImpl(String, PropertyName)
|
||||
DeclMarkerImpl(Symbol, JS::Symbol)
|
||||
DeclMarkerImpl(ObjectGroup, js::ObjectGroup)
|
||||
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
||||
|
@ -1087,50 +1189,6 @@ MarkValueInternal(JSTracer* trc, Value* v)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
gc::IsValueMarked(Value* v)
|
||||
{
|
||||
MOZ_ASSERT(v->isMarkable());
|
||||
bool rv;
|
||||
if (v->isString()) {
|
||||
JSString* str = (JSString*)v->toGCThing();
|
||||
rv = IsMarked<JSString>(&str);
|
||||
v->setString(str);
|
||||
} else if (v->isObject()) {
|
||||
JSObject* obj = (JSObject*)v->toGCThing();
|
||||
rv = IsMarked<JSObject>(&obj);
|
||||
v->setObject(*obj);
|
||||
} else {
|
||||
MOZ_ASSERT(v->isSymbol());
|
||||
JS::Symbol* sym = v->toSymbol();
|
||||
rv = IsMarked<JS::Symbol>(&sym);
|
||||
v->setSymbol(sym);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool
|
||||
gc::IsValueAboutToBeFinalized(Value* v)
|
||||
{
|
||||
MOZ_ASSERT(v->isMarkable());
|
||||
bool rv;
|
||||
if (v->isString()) {
|
||||
JSString* str = (JSString*)v->toGCThing();
|
||||
rv = IsAboutToBeFinalized<JSString>(&str);
|
||||
v->setString(str);
|
||||
} else if (v->isObject()) {
|
||||
JSObject* obj = (JSObject*)v->toGCThing();
|
||||
rv = IsAboutToBeFinalized<JSObject>(&obj);
|
||||
v->setObject(*obj);
|
||||
} else {
|
||||
MOZ_ASSERT(v->isSymbol());
|
||||
JS::Symbol* sym = v->toSymbol();
|
||||
rv = IsAboutToBeFinalized<JS::Symbol>(&sym);
|
||||
v->setSymbol(sym);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*** Type Marking ***/
|
||||
|
||||
void
|
||||
|
@ -1157,12 +1215,6 @@ TypeSet::MarkTypeUnbarriered(JSTracer* trc, TypeSet::Type* v, const char* name)
|
|||
|
||||
/*** Slot Marking ***/
|
||||
|
||||
bool
|
||||
gc::IsSlotMarked(HeapSlot* s)
|
||||
{
|
||||
return IsMarked(s);
|
||||
}
|
||||
|
||||
void
|
||||
gc::MarkObjectSlots(JSTracer* trc, NativeObject* obj, uint32_t start, uint32_t nslots)
|
||||
{
|
||||
|
@ -1226,10 +1278,16 @@ ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Value val)
|
|||
/*** Special Marking ***/
|
||||
|
||||
void
|
||||
gc::MarkValueForBarrier(JSTracer* trc, Value* v, const char* name)
|
||||
gc::MarkValueForBarrier(JSTracer* trc, Value* valuep, const char* name)
|
||||
{
|
||||
MOZ_ASSERT(!trc->runtime()->isHeapBusy());
|
||||
TraceManuallyBarrieredEdge(trc, v, name);
|
||||
TraceManuallyBarrieredEdge(trc, valuep, name);
|
||||
}
|
||||
|
||||
void
|
||||
gc::MarkIdForBarrier(JSTracer* trc, jsid* idp, const char* name)
|
||||
{
|
||||
TraceManuallyBarrieredEdge(trc, idp, name);
|
||||
}
|
||||
|
||||
/*** Push Mark Stack ***/
|
||||
|
@ -1271,11 +1329,11 @@ void
|
|||
BaseShape::markChildren(JSTracer* trc)
|
||||
{
|
||||
if (isOwned())
|
||||
gc::MarkBaseShape(trc, &unowned_, "base");
|
||||
TraceEdge(trc, &unowned_, "base");
|
||||
|
||||
JSObject* global = compartment()->unsafeUnbarrieredMaybeGlobal();
|
||||
if (global)
|
||||
MarkObjectUnbarriered(trc, &global, "global");
|
||||
TraceManuallyBarrieredEdge(trc, &global, "global");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1476,7 +1534,7 @@ gc::MarkCycleCollectorChildren(JSTracer* trc, Shape* shape)
|
|||
*/
|
||||
JSObject* global = shape->compartment()->unsafeUnbarrieredMaybeGlobal();
|
||||
MOZ_ASSERT(global);
|
||||
MarkObjectUnbarriered(trc, &global, "global");
|
||||
TraceManuallyBarrieredEdge(trc, &global, "global");
|
||||
|
||||
do {
|
||||
MOZ_ASSERT(global == shape->compartment()->unsafeUnbarrieredMaybeGlobal());
|
||||
|
@ -1488,13 +1546,13 @@ gc::MarkCycleCollectorChildren(JSTracer* trc, Shape* shape)
|
|||
|
||||
if (shape->hasGetterObject()) {
|
||||
JSObject* tmp = shape->getterObject();
|
||||
MarkObjectUnbarriered(trc, &tmp, "getter");
|
||||
TraceManuallyBarrieredEdge(trc, &tmp, "getter");
|
||||
MOZ_ASSERT(tmp == shape->getterObject());
|
||||
}
|
||||
|
||||
if (shape->hasSetterObject()) {
|
||||
JSObject* tmp = shape->setterObject();
|
||||
MarkObjectUnbarriered(trc, &tmp, "setter");
|
||||
TraceManuallyBarrieredEdge(trc, &tmp, "setter");
|
||||
MOZ_ASSERT(tmp == shape->setterObject());
|
||||
}
|
||||
|
||||
|
@ -1548,7 +1606,7 @@ gc::MarkChildren(JSTracer* trc, ObjectGroup* group)
|
|||
}
|
||||
|
||||
if (group->proto().isObject())
|
||||
MarkObject(trc, &group->protoRaw(), "group_proto");
|
||||
TraceEdge(trc, &group->protoRaw(), "group_proto");
|
||||
|
||||
if (group->newScript())
|
||||
group->newScript()->trace(trc);
|
||||
|
@ -1560,17 +1618,17 @@ gc::MarkChildren(JSTracer* trc, ObjectGroup* group)
|
|||
group->unboxedLayout().trace(trc);
|
||||
|
||||
if (ObjectGroup* unboxedGroup = group->maybeOriginalUnboxedGroup()) {
|
||||
MarkObjectGroupUnbarriered(trc, &unboxedGroup, "group_original_unboxed_group");
|
||||
TraceManuallyBarrieredEdge(trc, &unboxedGroup, "group_original_unboxed_group");
|
||||
group->setOriginalUnboxedGroup(unboxedGroup);
|
||||
}
|
||||
|
||||
if (JSObject* descr = group->maybeTypeDescr()) {
|
||||
MarkObjectUnbarriered(trc, &descr, "group_type_descr");
|
||||
TraceManuallyBarrieredEdge(trc, &descr, "group_type_descr");
|
||||
group->setTypeDescr(&descr->as<TypeDescr>());
|
||||
}
|
||||
|
||||
if (JSObject* fun = group->maybeInterpretedFunction()) {
|
||||
MarkObjectUnbarriered(trc, &fun, "group_function");
|
||||
TraceManuallyBarrieredEdge(trc, &fun, "group_function");
|
||||
group->setInterpretedFunction(&fun->as<JSFunction>());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,12 +62,12 @@ TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name);
|
|||
// Trace all edges contained in the given array.
|
||||
template <typename T>
|
||||
void
|
||||
TraceRange(JSTracer* trc, size_t len, BarrieredBase<T>* thingp, const char* name);
|
||||
TraceRange(JSTracer* trc, size_t len, BarrieredBase<T>* vec, const char* name);
|
||||
|
||||
// Trace all root edges in the given array.
|
||||
template <typename T>
|
||||
void
|
||||
TraceRootRange(JSTracer* trc, size_t len, T* thingp, const char* name);
|
||||
TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name);
|
||||
|
||||
// Trace an edge that crosses compartment boundaries. If the compartment of the
|
||||
// destination thing is not being GC'd, then the edge will not be traced.
|
||||
|
@ -142,37 +142,6 @@ bool Is##base##AboutToBeFinalized(type** thingp);
|
|||
bool Is##base##AboutToBeFinalized(BarrieredBase<type*>* thingp); \
|
||||
type* Update##base##IfRelocated(JSRuntime* rt, BarrieredBase<type*>* thingp); \
|
||||
type* Update##base##IfRelocated(JSRuntime* rt, type** thingp);
|
||||
|
||||
DeclMarker(BaseShape, BaseShape)
|
||||
DeclMarker(BaseShape, UnownedBaseShape)
|
||||
DeclMarker(JitCode, jit::JitCode)
|
||||
DeclMarker(Object, NativeObject)
|
||||
DeclMarker(Object, ArrayObject)
|
||||
DeclMarker(Object, ArgumentsObject)
|
||||
DeclMarker(Object, ArrayBufferObject)
|
||||
DeclMarker(Object, ArrayBufferObjectMaybeShared)
|
||||
DeclMarker(Object, ArrayBufferViewObject)
|
||||
DeclMarker(Object, DebugScopeObject)
|
||||
DeclMarker(Object, GlobalObject)
|
||||
DeclMarker(Object, JSObject)
|
||||
DeclMarker(Object, JSFunction)
|
||||
DeclMarker(Object, NestedScopeObject)
|
||||
DeclMarker(Object, PlainObject)
|
||||
DeclMarker(Object, SavedFrame)
|
||||
DeclMarker(Object, ScopeObject)
|
||||
DeclMarker(Object, SharedArrayBufferObject)
|
||||
DeclMarker(Object, SharedTypedArrayObject)
|
||||
DeclMarker(Script, JSScript)
|
||||
DeclMarker(LazyScript, LazyScript)
|
||||
DeclMarker(Shape, Shape)
|
||||
DeclMarker(String, JSAtom)
|
||||
DeclMarker(String, JSString)
|
||||
DeclMarker(String, JSFlatString)
|
||||
DeclMarker(String, JSLinearString)
|
||||
DeclMarker(String, PropertyName)
|
||||
DeclMarker(Symbol, JS::Symbol)
|
||||
DeclMarker(ObjectGroup, ObjectGroup)
|
||||
|
||||
#undef DeclMarker
|
||||
|
||||
void
|
||||
|
@ -206,19 +175,8 @@ MarkGCThingRoot(JSTracer* trc, void** thingp, const char* name);
|
|||
void
|
||||
MarkGCThingUnbarriered(JSTracer* trc, void** thingp, const char* name);
|
||||
|
||||
/*** Value Marking ***/
|
||||
|
||||
bool
|
||||
IsValueMarked(Value* v);
|
||||
|
||||
bool
|
||||
IsValueAboutToBeFinalized(Value* v);
|
||||
|
||||
/*** Slot Marking ***/
|
||||
|
||||
bool
|
||||
IsSlotMarked(HeapSlot* s);
|
||||
|
||||
void
|
||||
MarkObjectSlots(JSTracer* trc, NativeObject* obj, uint32_t start, uint32_t nslots);
|
||||
|
||||
|
@ -238,48 +196,28 @@ PushArena(GCMarker* gcmarker, ArenaHeader* aheader);
|
|||
/*** Generic ***/
|
||||
|
||||
template <typename T>
|
||||
static bool
|
||||
IsMarked(T** thingp);
|
||||
bool
|
||||
IsMarkedUnbarriered(T* thingp);
|
||||
|
||||
inline bool
|
||||
IsMarked(BarrieredBase<Value>* v)
|
||||
{
|
||||
if (!v->isMarkable())
|
||||
return true;
|
||||
return IsValueMarked(v->unsafeGet());
|
||||
}
|
||||
template <typename T>
|
||||
bool
|
||||
IsMarked(BarrieredBase<T>* thingp);
|
||||
|
||||
inline bool
|
||||
IsMarked(BarrieredBase<JSObject*>* objp)
|
||||
{
|
||||
return IsObjectMarked(objp);
|
||||
}
|
||||
template <typename T>
|
||||
bool
|
||||
IsMarked(ReadBarriered<T>* thingp);
|
||||
|
||||
inline bool
|
||||
IsMarked(BarrieredBase<JSScript*>* scriptp)
|
||||
{
|
||||
return IsScriptMarked(scriptp);
|
||||
}
|
||||
template <typename T>
|
||||
bool
|
||||
IsAboutToBeFinalizedUnbarriered(T* thingp);
|
||||
|
||||
inline bool
|
||||
IsAboutToBeFinalized(BarrieredBase<Value>* v)
|
||||
{
|
||||
if (!v->isMarkable())
|
||||
return false;
|
||||
return IsValueAboutToBeFinalized(v->unsafeGet());
|
||||
}
|
||||
template <typename T>
|
||||
bool
|
||||
IsAboutToBeFinalized(BarrieredBase<T>* thingp);
|
||||
|
||||
inline bool
|
||||
IsAboutToBeFinalized(BarrieredBase<JSObject*>* objp)
|
||||
{
|
||||
return IsObjectAboutToBeFinalized(objp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsAboutToBeFinalized(BarrieredBase<JSScript*>* scriptp)
|
||||
{
|
||||
return IsScriptAboutToBeFinalized(scriptp);
|
||||
}
|
||||
template <typename T>
|
||||
bool
|
||||
IsAboutToBeFinalized(ReadBarriered<T>* thingp);
|
||||
|
||||
inline bool
|
||||
IsAboutToBeFinalized(const js::jit::VMFunction** vmfunc)
|
||||
|
@ -291,12 +229,6 @@ IsAboutToBeFinalized(const js::jit::VMFunction** vmfunc)
|
|||
return false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsAboutToBeFinalized(ReadBarrieredJitCode code)
|
||||
{
|
||||
return IsJitCodeAboutToBeFinalized(code.unsafeGet());
|
||||
}
|
||||
|
||||
inline Cell*
|
||||
ToMarkable(const Value& v)
|
||||
{
|
||||
|
|
|
@ -94,16 +94,16 @@ template<class T>
|
|||
static void
|
||||
MarkExactStackRootsAcrossTypes(T context, JSTracer* trc)
|
||||
{
|
||||
MarkExactStackRootList<JSObject*, MarkObjectRoot>(trc, context, "exact-object");
|
||||
MarkExactStackRootList<Shape*, MarkShapeRoot>(trc, context, "exact-shape");
|
||||
MarkExactStackRootList<BaseShape*, MarkBaseShapeRoot>(trc, context, "exact-baseshape");
|
||||
MarkExactStackRootList<ObjectGroup*, MarkObjectGroupRoot>(
|
||||
MarkExactStackRootList<JSObject*, TraceRoot>(trc, context, "exact-object");
|
||||
MarkExactStackRootList<Shape*, TraceRoot>(trc, context, "exact-shape");
|
||||
MarkExactStackRootList<BaseShape*, TraceRoot>(trc, context, "exact-baseshape");
|
||||
MarkExactStackRootList<ObjectGroup*, TraceRoot>(
|
||||
trc, context, "exact-objectgroup");
|
||||
MarkExactStackRootList<JSString*, MarkStringRoot>(trc, context, "exact-string");
|
||||
MarkExactStackRootList<JS::Symbol*, MarkSymbolRoot>(trc, context, "exact-symbol");
|
||||
MarkExactStackRootList<jit::JitCode*, MarkJitCodeRoot>(trc, context, "exact-jitcode");
|
||||
MarkExactStackRootList<JSScript*, MarkScriptRoot>(trc, context, "exact-script");
|
||||
MarkExactStackRootList<LazyScript*, MarkLazyScriptRoot>(trc, context, "exact-lazy-script");
|
||||
MarkExactStackRootList<JSString*, TraceRoot>(trc, context, "exact-string");
|
||||
MarkExactStackRootList<JS::Symbol*, TraceRoot>(trc, context, "exact-symbol");
|
||||
MarkExactStackRootList<jit::JitCode*, TraceRoot>(trc, context, "exact-jitcode");
|
||||
MarkExactStackRootList<JSScript*, TraceRoot>(trc, context, "exact-script");
|
||||
MarkExactStackRootList<LazyScript*, TraceRoot>(trc, context, "exact-lazy-script");
|
||||
MarkExactStackRootList<jsid, TraceRoot>(trc, context, "exact-id");
|
||||
MarkExactStackRootList<Value, TraceRoot>(trc, context, "exact-value");
|
||||
MarkExactStackRootList<TypeSet::Type, TypeSet::MarkTypeRoot>(trc, context, "TypeSet::Type");
|
||||
|
@ -172,32 +172,32 @@ AutoGCRooter::trace(JSTracer* trc)
|
|||
|
||||
case SHAPEVECTOR: {
|
||||
AutoShapeVector::VectorImpl& vector = static_cast<js::AutoShapeVector*>(this)->vector;
|
||||
MarkShapeRootRange(trc, vector.length(), const_cast<Shape**>(vector.begin()),
|
||||
"js::AutoShapeVector.vector");
|
||||
TraceRootRange(trc, vector.length(), const_cast<Shape**>(vector.begin()),
|
||||
"js::AutoShapeVector.vector");
|
||||
return;
|
||||
}
|
||||
|
||||
case OBJVECTOR: {
|
||||
AutoObjectVector::VectorImpl& vector = static_cast<AutoObjectVector*>(this)->vector;
|
||||
MarkObjectRootRange(trc, vector.length(), vector.begin(), "js::AutoObjectVector.vector");
|
||||
TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoObjectVector.vector");
|
||||
return;
|
||||
}
|
||||
|
||||
case FUNVECTOR: {
|
||||
AutoFunctionVector::VectorImpl& vector = static_cast<AutoFunctionVector*>(this)->vector;
|
||||
MarkObjectRootRange(trc, vector.length(), vector.begin(), "js::AutoFunctionVector.vector");
|
||||
TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoFunctionVector.vector");
|
||||
return;
|
||||
}
|
||||
|
||||
case STRINGVECTOR: {
|
||||
AutoStringVector::VectorImpl& vector = static_cast<AutoStringVector*>(this)->vector;
|
||||
MarkStringRootRange(trc, vector.length(), vector.begin(), "js::AutoStringVector.vector");
|
||||
TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoStringVector.vector");
|
||||
return;
|
||||
}
|
||||
|
||||
case NAMEVECTOR: {
|
||||
AutoNameVector::VectorImpl& vector = static_cast<AutoNameVector*>(this)->vector;
|
||||
MarkStringRootRange(trc, vector.length(), vector.begin(), "js::AutoNameVector.vector");
|
||||
TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoNameVector.vector");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -213,17 +213,17 @@ AutoGCRooter::trace(JSTracer* trc)
|
|||
|
||||
case SCRIPTVECTOR: {
|
||||
AutoScriptVector::VectorImpl& vector = static_cast<AutoScriptVector*>(this)->vector;
|
||||
MarkScriptRootRange(trc, vector.length(), vector.begin(), "js::AutoScriptVector.vector");
|
||||
TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoScriptVector.vector");
|
||||
return;
|
||||
}
|
||||
|
||||
case OBJOBJHASHMAP: {
|
||||
AutoObjectObjectHashMap::HashMapImpl& map = static_cast<AutoObjectObjectHashMap*>(this)->map;
|
||||
for (AutoObjectObjectHashMap::Enum e(map); !e.empty(); e.popFront()) {
|
||||
MarkObjectRoot(trc, &e.front().value(), "AutoObjectObjectHashMap value");
|
||||
TraceRoot(trc, &e.front().value(), "AutoObjectObjectHashMap value");
|
||||
trc->setTracingLocation((void*)&e.front().key());
|
||||
JSObject* key = e.front().key();
|
||||
MarkObjectRoot(trc, &key, "AutoObjectObjectHashMap key");
|
||||
TraceRoot(trc, &key, "AutoObjectObjectHashMap key");
|
||||
if (key != e.front().key())
|
||||
e.rekeyFront(key);
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ AutoGCRooter::trace(JSTracer* trc)
|
|||
AutoObjectUnsigned32HashMap::HashMapImpl& map = self->map;
|
||||
for (AutoObjectUnsigned32HashMap::Enum e(map); !e.empty(); e.popFront()) {
|
||||
JSObject* key = e.front().key();
|
||||
MarkObjectRoot(trc, &key, "AutoObjectUnsignedHashMap key");
|
||||
TraceRoot(trc, &key, "AutoObjectUnsignedHashMap key");
|
||||
if (key != e.front().key())
|
||||
e.rekeyFront(key);
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ AutoGCRooter::trace(JSTracer* trc)
|
|||
AutoObjectHashSet::HashSetImpl& set = self->set;
|
||||
for (AutoObjectHashSet::Enum e(set); !e.empty(); e.popFront()) {
|
||||
JSObject* obj = e.front();
|
||||
MarkObjectRoot(trc, &obj, "AutoObjectHashSet value");
|
||||
TraceRoot(trc, &obj, "AutoObjectHashSet value");
|
||||
if (obj != e.front())
|
||||
e.rekeyFront(obj);
|
||||
}
|
||||
|
@ -330,31 +330,31 @@ void
|
|||
StackShape::trace(JSTracer* trc)
|
||||
{
|
||||
if (base)
|
||||
MarkBaseShapeRoot(trc, (BaseShape**) &base, "StackShape base");
|
||||
TraceRoot(trc, &base, "StackShape base");
|
||||
|
||||
TraceRoot(trc, (jsid*) &propid, "StackShape id");
|
||||
|
||||
if ((attrs & JSPROP_GETTER) && rawGetter)
|
||||
MarkObjectRoot(trc, (JSObject**)&rawGetter, "StackShape getter");
|
||||
TraceRoot(trc, (JSObject**)&rawGetter, "StackShape getter");
|
||||
|
||||
if ((attrs & JSPROP_SETTER) && rawSetter)
|
||||
MarkObjectRoot(trc, (JSObject**)&rawSetter, "StackShape setter");
|
||||
TraceRoot(trc, (JSObject**)&rawSetter, "StackShape setter");
|
||||
}
|
||||
|
||||
void
|
||||
JSPropertyDescriptor::trace(JSTracer* trc)
|
||||
{
|
||||
if (obj)
|
||||
MarkObjectRoot(trc, &obj, "Descriptor::obj");
|
||||
TraceRoot(trc, &obj, "Descriptor::obj");
|
||||
TraceRoot(trc, &value, "Descriptor::value");
|
||||
if ((attrs & JSPROP_GETTER) && getter) {
|
||||
JSObject* tmp = JS_FUNC_TO_DATA_PTR(JSObject*, getter);
|
||||
MarkObjectRoot(trc, &tmp, "Descriptor::get");
|
||||
TraceRoot(trc, &tmp, "Descriptor::get");
|
||||
getter = JS_DATA_TO_FUNC_PTR(JSGetterOp, tmp);
|
||||
}
|
||||
if ((attrs & JSPROP_SETTER) && setter) {
|
||||
JSObject* tmp = JS_FUNC_TO_DATA_PTR(JSObject*, setter);
|
||||
MarkObjectRoot(trc, &tmp, "Descriptor::set");
|
||||
TraceRoot(trc, &tmp, "Descriptor::set");
|
||||
setter = JS_DATA_TO_FUNC_PTR(JSSetterOp, tmp);
|
||||
}
|
||||
}
|
||||
|
@ -369,22 +369,20 @@ struct PersistentRootedMarker
|
|||
typedef mozilla::LinkedList<Element> List;
|
||||
typedef void (*MarkFunc)(JSTracer* trc, T* ref, const char* name);
|
||||
|
||||
template <MarkFunc Mark>
|
||||
static void
|
||||
markChainIfNotNull(JSTracer* trc, List& list, const char* name)
|
||||
{
|
||||
for (Element* r = list.getFirst(); r; r = r->getNext()) {
|
||||
if (r->get())
|
||||
Mark(trc, r->address(), name);
|
||||
TraceRoot(trc, r->address(), name);
|
||||
}
|
||||
}
|
||||
|
||||
template <MarkFunc Mark>
|
||||
static void
|
||||
markChain(JSTracer* trc, List& list, const char* name)
|
||||
{
|
||||
for (Element* r = list.getFirst(); r; r = r->getNext())
|
||||
Mark(trc, r->address(), name);
|
||||
TraceRoot(trc, r->address(), name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -396,20 +394,20 @@ js::gc::MarkPersistentRootedChains(JSTracer* trc)
|
|||
JSRuntime* rt = trc->runtime();
|
||||
|
||||
// Mark the PersistentRooted chains of types that may be null.
|
||||
PersistentRootedMarker<JSFunction*>::markChainIfNotNull<MarkObjectRoot>(
|
||||
trc, rt->functionPersistentRooteds, "PersistentRooted<JSFunction*>");
|
||||
PersistentRootedMarker<JSObject*>::markChainIfNotNull<MarkObjectRoot>(
|
||||
trc, rt->objectPersistentRooteds, "PersistentRooted<JSObject*>");
|
||||
PersistentRootedMarker<JSScript*>::markChainIfNotNull<MarkScriptRoot>(
|
||||
trc, rt->scriptPersistentRooteds, "PersistentRooted<JSScript*>");
|
||||
PersistentRootedMarker<JSString*>::markChainIfNotNull<MarkStringRoot>(
|
||||
trc, rt->stringPersistentRooteds, "PersistentRooted<JSString*>");
|
||||
PersistentRootedMarker<JSFunction*>::markChainIfNotNull(trc, rt->functionPersistentRooteds,
|
||||
"PersistentRooted<JSFunction*>");
|
||||
PersistentRootedMarker<JSObject*>::markChainIfNotNull(trc, rt->objectPersistentRooteds,
|
||||
"PersistentRooted<JSObject*>");
|
||||
PersistentRootedMarker<JSScript*>::markChainIfNotNull(trc, rt->scriptPersistentRooteds,
|
||||
"PersistentRooted<JSScript*>");
|
||||
PersistentRootedMarker<JSString*>::markChainIfNotNull(trc, rt->stringPersistentRooteds,
|
||||
"PersistentRooted<JSString*>");
|
||||
|
||||
// Mark the PersistentRooted chains of types that are never null.
|
||||
PersistentRootedMarker<jsid>::markChain<TraceRoot>(trc, rt->idPersistentRooteds,
|
||||
"PersistentRooted<jsid>");
|
||||
PersistentRootedMarker<Value>::markChain<TraceRoot>(trc, rt->valuePersistentRooteds,
|
||||
"PersistentRooted<Value>");
|
||||
PersistentRootedMarker<jsid>::markChain(trc, rt->idPersistentRooteds,
|
||||
"PersistentRooted<jsid>");
|
||||
PersistentRootedMarker<Value>::markChain(trc, rt->valuePersistentRooteds,
|
||||
"PersistentRooted<Value>");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -453,17 +451,15 @@ js::gc::GCRuntime::markRuntime(JSTracer* trc,
|
|||
}
|
||||
|
||||
if (rt->asyncStackForNewActivations)
|
||||
MarkObjectRoot(trc, &rt->asyncStackForNewActivations,
|
||||
"asyncStackForNewActivations");
|
||||
TraceRoot(trc, &rt->asyncStackForNewActivations, "asyncStackForNewActivations");
|
||||
|
||||
if (rt->asyncCauseForNewActivations)
|
||||
MarkStringRoot(trc, &rt->asyncCauseForNewActivations,
|
||||
"asyncCauseForNewActivations");
|
||||
TraceRoot(trc, &rt->asyncCauseForNewActivations, "asyncCauseForNewActivations");
|
||||
|
||||
if (rt->scriptAndCountsVector) {
|
||||
ScriptAndCountsVector& vec = *rt->scriptAndCountsVector;
|
||||
for (size_t i = 0; i < vec.length(); i++)
|
||||
MarkScriptRoot(trc, &vec[i].script, "scriptAndCountsVector");
|
||||
TraceRoot(trc, &vec[i].script, "scriptAndCountsVector");
|
||||
}
|
||||
|
||||
if (!rt->isBeingDestroyed() && !trc->runtime()->isHeapMinorCollecting()) {
|
||||
|
@ -489,7 +485,7 @@ js::gc::GCRuntime::markRuntime(JSTracer* trc,
|
|||
for (ZoneCellIterUnderGC i(zone, AllocKind::SCRIPT); !i.done(); i.next()) {
|
||||
JSScript* script = i.get<JSScript>();
|
||||
if (script->hasScriptCounts()) {
|
||||
MarkScriptRoot(trc, &script, "profilingScripts");
|
||||
TraceRoot(trc, &script, "profilingScripts");
|
||||
MOZ_ASSERT(script == i.get<JSScript>());
|
||||
}
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче