Compare commits
204
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
254efe6759 | ||
|
|
2e68f35707 | ||
|
|
786dc56351 | ||
|
|
2c4ef2600e | ||
|
|
8c8072860d | ||
|
|
54043a8b0a | ||
|
|
350e9c1879 | ||
|
|
0887abea30 | ||
|
|
cd78019ba6 | ||
|
|
3a26f14966 | ||
|
|
e2714e6938 | ||
|
|
c0b74ce133 | ||
|
|
14b9599104 | ||
|
|
f336312483 | ||
|
|
c7f25b6b9a | ||
|
|
29445ecfbe | ||
|
|
b6925236cc | ||
|
|
3b580c88d3 | ||
|
|
946c79b573 | ||
|
|
44ef435a21 | ||
|
|
9f32e371cb | ||
|
|
c959b55dd0 | ||
|
|
7786fc9d84 | ||
|
|
0e09f19795 | ||
|
|
aae12e5b54 | ||
|
|
5418ade030 | ||
|
|
2b85a07fb9 | ||
|
|
25d668395b | ||
|
|
32dd996cf2 | ||
|
|
4222ca929d | ||
|
|
35a4d4172e | ||
|
|
945e5b88fb | ||
|
|
dcba66d719 | ||
|
|
a64ed8a1db | ||
|
|
5206e5316c | ||
|
|
8f21ccd0a2 | ||
|
|
01a1a8557b | ||
|
|
b2cab55756 | ||
|
|
3ead6cadb6 | ||
|
|
8a4db5fa4b | ||
|
|
a421c7fab4 | ||
|
|
7894ac066c | ||
|
|
1d3c46ea86 | ||
|
|
62a47c35c1 | ||
|
|
a2cb54f93b | ||
|
|
4cc45366d7 | ||
|
|
935d1b9e1b | ||
|
|
c18edb0b67 | ||
|
|
7f93d25967 | ||
|
|
0f007a16d5 | ||
|
|
eacd48cccb | ||
|
|
fc1fe7d0c5 | ||
|
|
92873ead3e | ||
|
|
9fede4a3ba | ||
|
|
dbd5dc9554 | ||
|
|
3f538909ab | ||
|
|
8e4ce9b800 | ||
|
|
edf4210e12 | ||
|
|
5a64fd9657 | ||
|
|
12e9db2481 | ||
|
|
0af6123536 | ||
|
|
e2c94125cc | ||
|
|
723ca48613 | ||
|
|
15514da406 | ||
|
|
04d1e3e53a | ||
|
|
c654c1820f | ||
|
|
39dd9d560a | ||
|
|
032357c053 | ||
|
|
ecacd4a4d9 | ||
|
|
a6bc5962c4 | ||
|
|
12e93be21a | ||
|
|
0aeac02b89 | ||
|
|
1402d8eee6 | ||
|
|
42b3e18a4a | ||
|
|
cabe9ea2d5 | ||
|
|
c57a1eee66 | ||
|
|
a8fbc1dfbe | ||
|
|
1f457514b0 | ||
|
|
acd339fcf7 | ||
|
|
07bb7f379b | ||
|
|
8cabf0bf72 | ||
|
|
178f72365d | ||
|
|
f819937a31 | ||
|
|
114b5265d6 | ||
|
|
8595dc550f | ||
|
|
5b8d28ba4d | ||
|
|
8146ba5a07 | ||
|
|
727b9c9adf | ||
|
|
7056301965 | ||
|
|
dc3c2f3da8 | ||
|
|
baf4c5b6bb | ||
|
|
3575bc580f | ||
|
|
21e49b0a92 | ||
|
|
9d9534cc71 | ||
|
|
993681b010 | ||
|
|
3d29257050 | ||
|
|
7dd9438137 | ||
|
|
44c611aeaf | ||
|
|
7c4cbfd49e | ||
|
|
64bc57fa85 | ||
|
|
c6a82aa32c | ||
|
|
334fe4be6c | ||
|
|
d76e865563 | ||
|
|
ed862e5777 | ||
|
|
719bed3ead | ||
|
|
e1c28ba852 | ||
|
|
ba54621f01 | ||
|
|
9babba6c44 | ||
|
|
5ff9b81126 | ||
|
|
70c32d67f9 | ||
|
|
09a4832168 | ||
|
|
1fd02db477 | ||
|
|
810a054eb5 | ||
|
|
3104055d42 | ||
|
|
0d3d33623f | ||
|
|
3c46251443 | ||
|
|
186c58897b | ||
|
|
bb3405c8b6 | ||
|
|
b82596eb98 | ||
|
|
cf7b3e3a09 | ||
|
|
c9cd25abc5 | ||
|
|
73e0e8bbbe | ||
|
|
0bdb90ab40 | ||
|
|
c0d87ea595 | ||
|
|
11c9b60eba | ||
|
|
f9d1e87756 | ||
|
|
15ad259ac7 | ||
|
|
819c3c990b | ||
|
|
c4d4c9d6de | ||
|
|
903dea4285 | ||
|
|
620a3336eb | ||
|
|
6d20a50b09 | ||
|
|
dc4316132b | ||
|
|
9b375ff678 | ||
|
|
7a0c651c5d | ||
|
|
a653cb9b83 | ||
|
|
4875759e78 | ||
|
|
126b981629 | ||
|
|
103cf524ec | ||
|
|
ea96fed795 | ||
|
|
8c46320564 | ||
|
|
23b2a53d4c | ||
|
|
4616af0c7c | ||
|
|
a873824668 | ||
|
|
e5cec10a4e | ||
|
|
917cac9674 | ||
|
|
be4699e54c | ||
|
|
caaf54a046 | ||
|
|
d3812c1a0e | ||
|
|
729b32a2f0 | ||
|
|
79c8e2e86c | ||
|
|
93b4e6566d | ||
|
|
42a3dffe69 | ||
|
|
b21dd824a2 | ||
|
|
ccd9e8e106 | ||
|
|
eebb25dda0 | ||
|
|
27ce4ea0fa | ||
|
|
fb4ede7d2e | ||
|
|
a09c6b6ce0 | ||
|
|
a8f376aa3b | ||
|
|
e9868fcb47 | ||
|
|
7e49aebcc8 | ||
|
|
1c04829dca | ||
|
|
2379bb29be | ||
|
|
2b2475905e | ||
|
|
f25c809ff0 | ||
|
|
ff9f024589 | ||
|
|
add1037bb8 | ||
|
|
962ca150bd | ||
|
|
b693f60fc7 | ||
|
|
a4cd652b6f | ||
|
|
689cbd7509 | ||
|
|
a3f4272093 | ||
|
|
927173b648 | ||
|
|
c62cc61613 | ||
|
|
b4a50f830c | ||
|
|
5cadc0eee2 | ||
|
|
59431e104c | ||
|
|
47de3819f6 | ||
|
|
037f0ac647 | ||
|
|
b97f03f0c6 | ||
|
|
e3443de36e | ||
|
|
4b1bf3620d | ||
|
|
5d221d0cb2 | ||
|
|
9cca2f22c5 | ||
|
|
8a9955f181 | ||
|
|
90a67a4825 | ||
|
|
4381067d04 | ||
|
|
5457c3711b | ||
|
|
b0f872c919 | ||
|
|
738c6a740a | ||
|
|
b970fc412a | ||
|
|
0886ccfa95 | ||
|
|
f3786e036c | ||
|
|
d8091d3958 | ||
|
|
726452fc88 | ||
|
|
361b76beb2 | ||
|
|
6ca3eb7c98 | ||
|
|
42a208e60c | ||
|
|
c2de359372 | ||
|
|
40016a1bf9 | ||
|
|
e593872f19 | ||
|
|
7dbc24a739 | ||
|
|
27bb48deaf |
No files matched your search
@@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Switching to C++17 requires CLOBBER to pick up compiler conf. (Issue #2281)
|
||||
Clobber for NSS update
|
||||
@@ -19,6 +19,13 @@ If you are interested in the development and building side of things, some
|
||||
information will be available on the [Pale Moon developer site](http://developer.palemoon.org).
|
||||
You are also always welcome to get in touch with our community on the [Pale Moon forum](https://forum.palemoon.org/).
|
||||
|
||||
### Code search
|
||||
|
||||
While our repo has basic code searching capabilities (via `git grep`), you are strongly
|
||||
encouraged to instead use the dedicated code search and cross-referencing site:
|
||||
[https://xref.palemoon.org/](https://xref.palemoon.org/)
|
||||
This repo and a copy of the front-end are amalgamated in the `goanna-central` index.
|
||||
|
||||
### A note about trademarks and branding
|
||||
|
||||
Although this repository is primarily licensed under Mozilla Public License v2.0, the
|
||||
|
||||
@@ -80,7 +80,7 @@ StyleInfo::TextIndent(nsAString& aValue)
|
||||
}
|
||||
|
||||
void
|
||||
StyleInfo::Margin(css::Side aSide, nsAString& aValue)
|
||||
StyleInfo::Margin(Side aSide, nsAString& aValue)
|
||||
{
|
||||
MOZ_ASSERT(mElement->GetPrimaryFrame(), " mElement->GetPrimaryFrame() needs to be valid pointer");
|
||||
aValue.Truncate();
|
||||
|
||||
@@ -340,9 +340,9 @@ this.AccessFu = { // jshint ignore:line
|
||||
case 'remote-browser-shown':
|
||||
case 'inprocess-browser-shown':
|
||||
{
|
||||
// Ignore notifications that aren't from a BrowserOrApp
|
||||
// Ignore notifications that aren't from a Browser
|
||||
let frameLoader = aSubject.QueryInterface(Ci.nsIFrameLoader);
|
||||
if (!frameLoader.ownerIsMozBrowserOrAppFrame) {
|
||||
if (!frameLoader.ownerIsMozBrowserFrame) {
|
||||
return;
|
||||
}
|
||||
this._handleMessageManager(frameLoader.messageManager);
|
||||
|
||||
+19
-7
@@ -560,6 +560,23 @@ BasePrincipal::GetCspJSON(nsAString& outCSPinJSON)
|
||||
return mCSP->ToJSON(outCSPinJSON);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::IsSameOrigin(nsIURI* aURI, bool aIsPrivateWin, bool* aRes) {
|
||||
*aRes = false;
|
||||
nsCOMPtr<nsIURI> prinURI;
|
||||
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
||||
if (NS_FAILED(rv) || !prinURI) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
if (!ssm) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
;
|
||||
}
|
||||
*aRes = NS_SUCCEEDED(ssm->CheckSameOriginURI(prinURI, aURI, aIsPrivateWin));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::GetIsNullPrincipal(bool* aResult)
|
||||
{
|
||||
@@ -607,13 +624,8 @@ BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes)
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::GetAppStatus(uint16_t* aAppStatus)
|
||||
{
|
||||
if (AppId() == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||
NS_WARNING("Asking for app status on a principal with an unknown app id");
|
||||
*aAppStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aAppStatus = nsScriptSecurityManager::AppStatusForPrincipal(this);
|
||||
// TODO: Remove GetAppStatus.
|
||||
*aAppStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -282,6 +282,7 @@ public:
|
||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) final;
|
||||
NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final;
|
||||
NS_IMETHOD GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) final;
|
||||
NS_IMETHOD IsSameOrigin(nsIURI* aURI, bool aIsPrivateWin, bool* aRes) override;
|
||||
|
||||
bool EqualsIgnoringAddonId(nsIPrincipal *aOther);
|
||||
|
||||
|
||||
@@ -223,6 +223,12 @@ interface nsIPrincipal : nsISerializable
|
||||
*/
|
||||
readonly attribute AUTF8String originSuffix;
|
||||
|
||||
/**
|
||||
* Uses NS_Security Compare to determine if the
|
||||
* other URI is same-origin as the uri of the Principal
|
||||
*/
|
||||
bool IsSameOrigin(in nsIURI otherURI, in bool aIsPrivateWin);
|
||||
|
||||
/**
|
||||
* The base domain of the codebase URI to which this principal pertains
|
||||
* (generally the document URI), handling null principals and
|
||||
@@ -297,15 +303,6 @@ interface nsIPrincipal : nsISerializable
|
||||
*/
|
||||
[infallible] readonly attribute unsigned long privateBrowsingId;
|
||||
|
||||
/**
|
||||
* Returns true iff the principal is inside an isolated mozbrowser element.
|
||||
* <iframe mozbrowser mozapp> and <xul:browser> are not considered to be
|
||||
* mozbrowser elements. <iframe mozbrowser noisolation> does not count as
|
||||
* isolated since isolation is disabled. Isolation can only be disabled if
|
||||
* the containing document is chrome.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isInIsolatedMozBrowserElement;
|
||||
|
||||
/**
|
||||
* Returns true if this principal has an unknown appId. This shouldn't
|
||||
* generally be used. We only expose it due to not providing the correct
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
|
||||
#include "nsIAppsService.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
static bool gCodeBasePrincipalSupport = false;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "xpcpublic.h"
|
||||
#include "XPCWrapper.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "nsIInputStreamChannel.h"
|
||||
#include "nsILoadContext.h"
|
||||
#include "nsIServiceManager.h"
|
||||
@@ -55,7 +54,6 @@
|
||||
#include "nsIChromeRegistry.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "mozIApplication.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
@@ -76,6 +74,7 @@ nsIIOService *nsScriptSecurityManager::sIOService = nullptr;
|
||||
nsIStringBundle *nsScriptSecurityManager::sStrBundle = nullptr;
|
||||
JSContext *nsScriptSecurityManager::sContext = nullptr;
|
||||
bool nsScriptSecurityManager::sStrictFileOriginPolicy = true;
|
||||
bool nsScriptSecurityManager::sSameOriginPolicy = true;
|
||||
|
||||
///////////////////////////
|
||||
// Convenience Functions //
|
||||
@@ -239,68 +238,6 @@ nsScriptSecurityManager::SecurityHashURI(nsIURI* aURI)
|
||||
return NS_SecurityHashURI(aURI);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
nsScriptSecurityManager::AppStatusForPrincipal(nsIPrincipal *aPrin)
|
||||
{
|
||||
uint32_t appId = aPrin->GetAppId();
|
||||
|
||||
// After bug 1238160, the principal no longer knows how to answer "is this a
|
||||
// browser element", which is really what this code path wants. Currently,
|
||||
// desktop is the only platform where we intend to disable isolation on a
|
||||
// browser frame, so non-desktop should be able to assume that
|
||||
// inIsolatedMozBrowser is true for all mozbrowser frames. Additionally,
|
||||
// apps are no longer used on desktop, so appId is always NO_APP_ID. We use
|
||||
// a release assertion in nsFrameLoader::OwnerIsIsolatedMozBrowserFrame so
|
||||
// that platforms with apps can assume inIsolatedMozBrowser is true for all
|
||||
// mozbrowser frames.
|
||||
bool inIsolatedMozBrowser = aPrin->GetIsInIsolatedMozBrowserElement();
|
||||
|
||||
NS_WARNING_ASSERTION(
|
||||
appId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
"Asking for app status on a principal with an unknown app id");
|
||||
|
||||
// Installed apps have a valid app id (not NO_APP_ID or UNKNOWN_APP_ID)
|
||||
// and they are not inside a mozbrowser.
|
||||
if (appId == nsIScriptSecurityManager::NO_APP_ID ||
|
||||
appId == nsIScriptSecurityManager::UNKNOWN_APP_ID ||
|
||||
inIsolatedMozBrowser)
|
||||
{
|
||||
return nsIPrincipal::APP_STATUS_NOT_INSTALLED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(appsService, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
|
||||
|
||||
nsCOMPtr<mozIApplication> app;
|
||||
appsService->GetAppByLocalId(appId, getter_AddRefs(app));
|
||||
NS_ENSURE_TRUE(app, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
|
||||
|
||||
uint16_t status = nsIPrincipal::APP_STATUS_INSTALLED;
|
||||
NS_ENSURE_SUCCESS(app->GetAppStatus(&status),
|
||||
nsIPrincipal::APP_STATUS_NOT_INSTALLED);
|
||||
|
||||
nsString appOrigin;
|
||||
NS_ENSURE_SUCCESS(app->GetOrigin(appOrigin),
|
||||
nsIPrincipal::APP_STATUS_NOT_INSTALLED);
|
||||
nsCOMPtr<nsIURI> appURI;
|
||||
NS_ENSURE_SUCCESS(NS_NewURI(getter_AddRefs(appURI), appOrigin),
|
||||
nsIPrincipal::APP_STATUS_NOT_INSTALLED);
|
||||
|
||||
// The app could contain a cross-origin iframe - make sure that the content
|
||||
// is actually same-origin with the app.
|
||||
MOZ_ASSERT(inIsolatedMozBrowser == false, "Checked this above");
|
||||
nsAutoCString suffix;
|
||||
PrincipalOriginAttributes attrs;
|
||||
NS_ENSURE_TRUE(attrs.PopulateFromOrigin(NS_ConvertUTF16toUTF8(appOrigin), suffix),
|
||||
nsIPrincipal::APP_STATUS_NOT_INSTALLED);
|
||||
attrs.mAppId = appId;
|
||||
attrs.mInIsolatedMozBrowser = false;
|
||||
nsCOMPtr<nsIPrincipal> appPrin = BasePrincipal::CreateCodebasePrincipal(appURI, attrs);
|
||||
NS_ENSURE_TRUE(appPrin, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
|
||||
return aPrin->Equals(appPrin) ? status
|
||||
: nsIPrincipal::APP_STATUS_NOT_INSTALLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* GetChannelResultPrincipal will return the principal that the resource
|
||||
* returned by this channel will use. For example, if the resource is in
|
||||
@@ -607,7 +544,7 @@ nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI,
|
||||
nsIURI* aTargetURI,
|
||||
bool reportError)
|
||||
{
|
||||
if (!SecurityCompareURIs(aSourceURI, aTargetURI))
|
||||
if (sSameOriginPolicy && !SecurityCompareURIs(aSourceURI, aTargetURI))
|
||||
{
|
||||
if (reportError) {
|
||||
ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"),
|
||||
@@ -1434,10 +1371,13 @@ nsScriptSecurityManager::CanGetService(JSContext *cx,
|
||||
const char sJSEnabledPrefName[] = "javascript.enabled";
|
||||
const char sFileOriginPolicyPrefName[] =
|
||||
"security.fileuri.strict_origin_policy";
|
||||
const char sSameOriginPolicyPrefName[] =
|
||||
"security.same_origin_policy.enabled";
|
||||
|
||||
static const char* kObservedPrefs[] = {
|
||||
sJSEnabledPrefName,
|
||||
sFileOriginPolicyPrefName,
|
||||
sSameOriginPolicyPrefName,
|
||||
"capability.policy.",
|
||||
nullptr
|
||||
};
|
||||
@@ -1593,6 +1533,8 @@ nsScriptSecurityManager::ScriptSecurityPrefChanged()
|
||||
Preferences::GetBool(sJSEnabledPrefName, mIsJavaScriptEnabled);
|
||||
sStrictFileOriginPolicy =
|
||||
Preferences::GetBool(sFileOriginPolicyPrefName, false);
|
||||
sSameOriginPolicy =
|
||||
Preferences::GetBool(sSameOriginPolicyPrefName, true);
|
||||
mFileURIWhitelist.reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -152,6 +152,7 @@ private:
|
||||
}
|
||||
|
||||
static bool sStrictFileOriginPolicy;
|
||||
static bool sSameOriginPolicy;
|
||||
|
||||
static nsIIOService *sIOService;
|
||||
static nsIStringBundle *sStrBundle;
|
||||
|
||||
@@ -4,7 +4,6 @@ support-files =
|
||||
file_disableScript.html
|
||||
!/js/xpconnect/tests/mochitest/file_empty.html
|
||||
|
||||
[test_app_principal_equality.html]
|
||||
[test_bug246699.html]
|
||||
[test_bug292789.html]
|
||||
[test_bug423375.html]
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=777467
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test app principal's equality</title>
|
||||
<script type="application/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=777467">Mozilla Bug 777467</a>
|
||||
<p id="display"></p>
|
||||
<script>
|
||||
|
||||
/** Test for app principal's equality **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var permissions = new Promise(resolve => {
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ type: "browser", allow: true, context: document },
|
||||
{ type: "embed-apps", allow: true, context: document }],
|
||||
resolve);
|
||||
});
|
||||
|
||||
permissions.then(() => {
|
||||
$('content').innerHTML =
|
||||
'<iframe src="error404"></iframe>\n' +
|
||||
'<iframe mozbrowser src="error404"></iframe>\n' +
|
||||
'<iframe mozapp="http://example.org/manifest.webapp" mozbrowser src="error404"></iframe>';
|
||||
|
||||
var iframes = document.getElementsByTagName("iframe");
|
||||
var promises = []
|
||||
for (var i = 0; i < promises.length; ++i) {
|
||||
promises.push(new Promise(resolve => {
|
||||
iframes[i].addEventListener("load", resolve);
|
||||
}));
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
});
|
||||
|
||||
var prefs = new Promise(resolve => {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ set: [[ "dom.mozBrowserFramesEnabled", true ],
|
||||
[ "dom.ipc.browser_frames.oop_by_default", false ]] },
|
||||
resolve);
|
||||
});
|
||||
</script>
|
||||
<div id="content" style="display: none;">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
function canAccessDocument(win) {
|
||||
var result = true;
|
||||
try {
|
||||
win.document;
|
||||
} catch(e) {
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
var loaded = new Promise(resolve => addLoadEvent(resolve));
|
||||
|
||||
Promise.all([ permissions, prefs, loaded ]).then(runTest);
|
||||
|
||||
function runTest() {
|
||||
// Test the witness frame (we can access same-origin frame).
|
||||
is(canAccessDocument(frames[0]), true,
|
||||
"should be able to access the first frame");
|
||||
|
||||
// Test different app/browserElement frames.
|
||||
for (var i=1; i<frames.length; ++i) {
|
||||
is(canAccessDocument(frames[i]), false,
|
||||
"should not be able to access the other frames");
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -86,6 +86,7 @@ included_inclnames_to_ignore = set([
|
||||
'unicode/uclean.h', # ICU
|
||||
'unicode/ucol.h', # ICU
|
||||
'unicode/udat.h', # ICU
|
||||
'unicode/udateintervalformat.h', # ICU
|
||||
'unicode/udatpg.h', # ICU
|
||||
'unicode/udisplaycontext.h',# ICU
|
||||
'unicode/uenum.h', # ICU
|
||||
|
||||
+1
-1
@@ -152,6 +152,7 @@ sources = [
|
||||
'/intl/icu/source/i18n/ucol_sit.cpp',
|
||||
'/intl/icu/source/i18n/ucoleitr.cpp',
|
||||
'/intl/icu/source/i18n/udat.cpp',
|
||||
'/intl/icu/source/i18n/udateintervalformat.cpp',
|
||||
'/intl/icu/source/i18n/udatpg.cpp',
|
||||
'/intl/icu/source/i18n/ufieldpositer.cpp',
|
||||
'/intl/icu/source/i18n/uitercollationiterator.cpp',
|
||||
@@ -217,7 +218,6 @@ other_sources = [
|
||||
'/intl/icu/source/i18n/transreg.cpp',
|
||||
'/intl/icu/source/i18n/tridpars.cpp',
|
||||
'/intl/icu/source/i18n/ucsdet.cpp',
|
||||
'/intl/icu/source/i18n/udateintervalformat.cpp',
|
||||
'/intl/icu/source/i18n/ulocdata.cpp',
|
||||
'/intl/icu/source/i18n/unesctrn.cpp',
|
||||
'/intl/icu/source/i18n/uni2name.cpp',
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
# Referenced by milestone.py.
|
||||
#--------------------------------------------------------
|
||||
|
||||
6.6.0
|
||||
6.7.0
|
||||
+9
-34
@@ -1,39 +1,14 @@
|
||||
This directory contains source code to
|
||||
This is the SQLite amalgamation.
|
||||
Check sqlite3.h for the version number and source id.
|
||||
|
||||
SQLite: An Embeddable SQL Database Engine
|
||||
See http://www.sqlite.org/ for more info.
|
||||
|
||||
To compile the project, first create a directory in which to place
|
||||
the build products. It is recommended, but not required, that the
|
||||
build directory be separate from the source directory. Cd into the
|
||||
build directory and then from the build directory run the configure
|
||||
script found at the root of the source tree. Then run "make".
|
||||
We have a UXP-specific moz.build in src/ (normally not there) that we
|
||||
use to build. Adfditionally, src/ contains sqlite.symbols which lists
|
||||
all explicitly exported symbols from the library to expose.
|
||||
|
||||
For example:
|
||||
To move to a new version:
|
||||
|
||||
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
|
||||
mkdir bld ;# Build will occur in a sibling directory
|
||||
cd bld ;# Change to the build directory
|
||||
../sqlite/configure ;# Run the configure script
|
||||
make ;# Run the makefile.
|
||||
make install ;# (Optional) Install the build products
|
||||
Copy the sqlite3.h and sqlite3.c files from the amalgamation of sqlite.
|
||||
|
||||
The configure script uses autoconf 2.61 and libtool. If the configure
|
||||
script does not work out for you, there is a generic makefile named
|
||||
"Makefile.linux-gcc" in the top directory of the source tree that you
|
||||
can copy and edit to suit your needs. Comments on the generic makefile
|
||||
show what changes are needed.
|
||||
|
||||
The linux binaries on the website are created using the generic makefile,
|
||||
not the configure script. The windows binaries on the website are created
|
||||
using MinGW32 configured as a cross-compiler running under Linux. For
|
||||
details, see the ./publish.sh script at the top-level of the source tree.
|
||||
The developers do not use teh configure script.
|
||||
|
||||
SQLite does not require TCL to run, but a TCL installation is required
|
||||
by the makefiles. SQLite contains a lot of generated code and TCL is
|
||||
used to do much of that code generation. The makefile also requires
|
||||
AWK.
|
||||
|
||||
Contacts:
|
||||
|
||||
http://www.sqlite.org/
|
||||
Be sure to update SQLITE_VERSION accordingly in $(topsrcdir)/old-configure.in.
|
||||
@@ -1,13 +0,0 @@
|
||||
This is the SQLite amalgamation.
|
||||
Check sqlite3.h for the version number and source id.
|
||||
|
||||
See http://www.sqlite.org/ for more info.
|
||||
|
||||
We have a mozilla-specific Makefile.in in src/ (normally no
|
||||
Makefile.in there) that we use to build.
|
||||
|
||||
To move to a new version:
|
||||
|
||||
Copy the sqlite3.h and sqlite3.c files from the amalgamation of sqlite.
|
||||
|
||||
Be sure to update SQLITE_VERSION accordingly in $(topsrcdir)/configure.in.
|
||||
+18003
-7959
File diff suppressed because it is too large.
Load diff
+450
-93
@@ -146,9 +146,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.42.0"
|
||||
#define SQLITE_VERSION_NUMBER 3042000
|
||||
#define SQLITE_SOURCE_ID "2023-05-16 12:36:15 831d0fb2836b71c9bc51067c49fee4b8f18047814f2ff22d817d25195cf350b0"
|
||||
#define SQLITE_VERSION "3.46.0"
|
||||
#define SQLITE_VERSION_NUMBER 3046000
|
||||
#define SQLITE_SOURCE_ID "2024-05-23 13:25:27 96c92aba00c8375bc32fafcdf12429c58bd8aabfcadab6683e35bbb9cdebf19e"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@@ -420,6 +420,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
|
||||
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
|
||||
** <li> The application must not modify the SQL statement text passed into
|
||||
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
|
||||
** <li> The application must not dereference the arrays or string pointers
|
||||
** passed as the 3rd and 4th callback parameters after it returns.
|
||||
** </ul>
|
||||
*/
|
||||
SQLITE_API int sqlite3_exec(
|
||||
@@ -528,6 +530,7 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
||||
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
|
||||
#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))
|
||||
#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
@@ -761,11 +764,11 @@ struct sqlite3_file {
|
||||
** </ul>
|
||||
** xLock() upgrades the database file lock. In other words, xLock() moves the
|
||||
** database file lock in the direction NONE toward EXCLUSIVE. The argument to
|
||||
** xLock() is always on of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
|
||||
** xLock() is always one of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
|
||||
** SQLITE_LOCK_NONE. If the database file lock is already at or above the
|
||||
** requested lock, then the call to xLock() is a no-op.
|
||||
** xUnlock() downgrades the database file lock to either SHARED or NONE.
|
||||
* If the lock is already at or below the requested lock state, then the call
|
||||
** If the lock is already at or below the requested lock state, then the call
|
||||
** to xUnlock() is a no-op.
|
||||
** The xCheckReservedLock() method checks whether any database connection,
|
||||
** either in this process or in some other process, is holding a RESERVED,
|
||||
@@ -1190,7 +1193,7 @@ struct sqlite3_io_methods {
|
||||
** by clients within the current process, only within other processes.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_CKSM_FILE]]
|
||||
** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use interally by the
|
||||
** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the
|
||||
** [checksum VFS shim] only.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_RESET_CACHE]]
|
||||
@@ -2126,7 +2129,7 @@ struct sqlite3_mem_methods {
|
||||
** is stored in each sorted record and the required column values loaded
|
||||
** from the database as records are returned in sorted order. The default
|
||||
** value for this option is to never use this optimization. Specifying a
|
||||
** negative value for this option restores the default behaviour.
|
||||
** negative value for this option restores the default behavior.
|
||||
** This option is only available if SQLite is compiled with the
|
||||
** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option.
|
||||
**
|
||||
@@ -2140,6 +2143,22 @@ struct sqlite3_mem_methods {
|
||||
** configuration setting is never used, then the default maximum is determined
|
||||
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
|
||||
** compile-time option is not set, then the default maximum is 1073741824.
|
||||
**
|
||||
** [[SQLITE_CONFIG_ROWID_IN_VIEW]]
|
||||
** <dt>SQLITE_CONFIG_ROWID_IN_VIEW
|
||||
** <dd>The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability
|
||||
** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is
|
||||
** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability
|
||||
** defaults to on. This configuration option queries the current setting or
|
||||
** changes the setting to off or on. The argument is a pointer to an integer.
|
||||
** If that integer initially holds a value of 1, then the ability for VIEWs to
|
||||
** have ROWIDs is activated. If the integer initially holds zero, then the
|
||||
** ability is deactivated. Any other initial value for the integer leaves the
|
||||
** setting unchanged. After changes, if any, the integer is written with
|
||||
** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite
|
||||
** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and
|
||||
** recommended case) then the integer is always filled with zero, regardless
|
||||
** if its initial value.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
||||
@@ -2171,6 +2190,7 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
|
||||
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
|
||||
#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
|
||||
#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
@@ -2301,7 +2321,7 @@ struct sqlite3_mem_methods {
|
||||
** database handle, SQLite checks if this will mean that there are now no
|
||||
** connections at all to the database. If so, it performs a checkpoint
|
||||
** operation before closing the connection. This option may be used to
|
||||
** override this behaviour. The first parameter passed to this operation
|
||||
** override this behavior. The first parameter passed to this operation
|
||||
** is an integer - positive to disable checkpoints-on-close, or zero (the
|
||||
** default) to enable them, and negative to leave the setting unchanged.
|
||||
** The second parameter is a pointer to an integer
|
||||
@@ -2454,7 +2474,7 @@ struct sqlite3_mem_methods {
|
||||
** the [VACUUM] command will fail with an obscure error when attempting to
|
||||
** process a table with generated columns and a descending index. This is
|
||||
** not considered a bug since SQLite versions 3.3.0 and earlier do not support
|
||||
** either generated columns or decending indexes.
|
||||
** either generated columns or descending indexes.
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]]
|
||||
@@ -2735,6 +2755,7 @@ SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*);
|
||||
**
|
||||
** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether
|
||||
** or not an interrupt is currently in effect for [database connection] D.
|
||||
** It returns 1 if an interrupt is currently in effect, or 0 otherwise.
|
||||
*/
|
||||
SQLITE_API void sqlite3_interrupt(sqlite3*);
|
||||
SQLITE_API int sqlite3_is_interrupted(sqlite3*);
|
||||
@@ -3284,8 +3305,8 @@ SQLITE_API int sqlite3_set_authorizer(
|
||||
#define SQLITE_RECURSIVE 33 /* NULL NULL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Tracing And Profiling Functions
|
||||
** METHOD: sqlite3
|
||||
** CAPI3REF: Deprecated Tracing And Profiling Functions
|
||||
** DEPRECATED
|
||||
**
|
||||
** These routines are deprecated. Use the [sqlite3_trace_v2()] interface
|
||||
** instead of the routines described here.
|
||||
@@ -3388,8 +3409,10 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
|
||||
** M argument should be the bitwise OR-ed combination of
|
||||
** zero or more [SQLITE_TRACE] constants.
|
||||
**
|
||||
** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides
|
||||
** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2().
|
||||
** ^Each call to either sqlite3_trace(D,X,P) or sqlite3_trace_v2(D,M,X,P)
|
||||
** overrides (cancels) all prior calls to sqlite3_trace(D,X,P) or
|
||||
** sqlite3_trace_v2(D,M,X,P) for the [database connection] D. Each
|
||||
** database connection may have at most one trace callback.
|
||||
**
|
||||
** ^The X callback is invoked whenever any of the events identified by
|
||||
** mask M occur. ^The integer return value from the callback is currently
|
||||
@@ -3758,7 +3781,7 @@ SQLITE_API int sqlite3_open_v2(
|
||||
** as F) must be one of:
|
||||
** <ul>
|
||||
** <li> A database filename pointer created by the SQLite core and
|
||||
** passed into the xOpen() method of a VFS implemention, or
|
||||
** passed into the xOpen() method of a VFS implementation, or
|
||||
** <li> A filename obtained from [sqlite3_db_filename()], or
|
||||
** <li> A new filename constructed using [sqlite3_create_filename()].
|
||||
** </ul>
|
||||
@@ -3871,7 +3894,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
|
||||
/*
|
||||
** CAPI3REF: Create and Destroy VFS Filenames
|
||||
**
|
||||
** These interfces are provided for use by [VFS shim] implementations and
|
||||
** These interfaces are provided for use by [VFS shim] implementations and
|
||||
** are not useful outside of that context.
|
||||
**
|
||||
** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
|
||||
@@ -3950,14 +3973,17 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename);
|
||||
** </ul>
|
||||
**
|
||||
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
|
||||
** text that describes the error, as either UTF-8 or UTF-16 respectively.
|
||||
** text that describes the error, as either UTF-8 or UTF-16 respectively,
|
||||
** or NULL if no error message is available.
|
||||
** (See how SQLite handles [invalid UTF] for exceptions to this rule.)
|
||||
** ^(Memory to hold the error message string is managed internally.
|
||||
** The application does not need to worry about freeing the result.
|
||||
** However, the error string might be overwritten or deallocated by
|
||||
** subsequent calls to other SQLite interface functions.)^
|
||||
**
|
||||
** ^The sqlite3_errstr() interface returns the English-language text
|
||||
** that describes the [result code], as UTF-8.
|
||||
** ^The sqlite3_errstr(E) interface returns the English-language text
|
||||
** that describes the [result code] E, as UTF-8, or NULL if E is not an
|
||||
** result code for which a text error message is available.
|
||||
** ^(Memory to hold the error message string is managed internally
|
||||
** and must not be freed by the application)^.
|
||||
**
|
||||
@@ -4418,6 +4444,41 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
||||
*/
|
||||
SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Change The EXPLAIN Setting For A Prepared Statement
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** The sqlite3_stmt_explain(S,E) interface changes the EXPLAIN
|
||||
** setting for [prepared statement] S. If E is zero, then S becomes
|
||||
** a normal prepared statement. If E is 1, then S behaves as if
|
||||
** its SQL text began with "[EXPLAIN]". If E is 2, then S behaves as if
|
||||
** its SQL text began with "[EXPLAIN QUERY PLAN]".
|
||||
**
|
||||
** Calling sqlite3_stmt_explain(S,E) might cause S to be reprepared.
|
||||
** SQLite tries to avoid a reprepare, but a reprepare might be necessary
|
||||
** on the first transition into EXPLAIN or EXPLAIN QUERY PLAN mode.
|
||||
**
|
||||
** Because of the potential need to reprepare, a call to
|
||||
** sqlite3_stmt_explain(S,E) will fail with SQLITE_ERROR if S cannot be
|
||||
** reprepared because it was created using [sqlite3_prepare()] instead of
|
||||
** the newer [sqlite3_prepare_v2()] or [sqlite3_prepare_v3()] interfaces and
|
||||
** hence has no saved SQL text with which to reprepare.
|
||||
**
|
||||
** Changing the explain setting for a prepared statement does not change
|
||||
** the original SQL text for the statement. Hence, if the SQL text originally
|
||||
** began with EXPLAIN or EXPLAIN QUERY PLAN, but sqlite3_stmt_explain(S,0)
|
||||
** is called to convert the statement into an ordinary statement, the EXPLAIN
|
||||
** or EXPLAIN QUERY PLAN keywords will still appear in the sqlite3_sql(S)
|
||||
** output, even though the statement now acts like a normal SQL statement.
|
||||
**
|
||||
** This routine returns SQLITE_OK if the explain mode is successfully
|
||||
** changed, or an error code if the explain mode could not be changed.
|
||||
** The explain mode cannot be changed while a statement is active.
|
||||
** Hence, it is good practice to call [sqlite3_reset(S)]
|
||||
** immediately prior to calling sqlite3_stmt_explain(S,E).
|
||||
*/
|
||||
SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
|
||||
** METHOD: sqlite3_stmt
|
||||
@@ -4581,7 +4642,7 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** with it may be passed. ^It is called to dispose of the BLOB or string even
|
||||
** if the call to the bind API fails, except the destructor is not called if
|
||||
** the third parameter is a NULL pointer or the fourth parameter is negative.
|
||||
** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
|
||||
** ^ (2) The special constant, [SQLITE_STATIC], may be passed to indicate that
|
||||
** the application remains responsible for disposing of the object. ^In this
|
||||
** case, the object and the provided pointer to it must remain valid until
|
||||
** either the prepared statement is finalized or the same SQL parameter is
|
||||
@@ -5260,20 +5321,33 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
|
||||
** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S
|
||||
** back to the beginning of its program.
|
||||
**
|
||||
** ^If the most recent call to [sqlite3_step(S)] for the
|
||||
** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE],
|
||||
** or if [sqlite3_step(S)] has never before been called on S,
|
||||
** then [sqlite3_reset(S)] returns [SQLITE_OK].
|
||||
** ^The return code from [sqlite3_reset(S)] indicates whether or not
|
||||
** the previous evaluation of prepared statement S completed successfully.
|
||||
** ^If [sqlite3_step(S)] has never before been called on S or if
|
||||
** [sqlite3_step(S)] has not been called since the previous call
|
||||
** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return
|
||||
** [SQLITE_OK].
|
||||
**
|
||||
** ^If the most recent call to [sqlite3_step(S)] for the
|
||||
** [prepared statement] S indicated an error, then
|
||||
** [sqlite3_reset(S)] returns an appropriate [error code].
|
||||
** ^The [sqlite3_reset(S)] interface might also return an [error code]
|
||||
** if there were no prior errors but the process of resetting
|
||||
** the prepared statement caused a new error. ^For example, if an
|
||||
** [INSERT] statement with a [RETURNING] clause is only stepped one time,
|
||||
** that one call to [sqlite3_step(S)] might return SQLITE_ROW but
|
||||
** the overall statement might still fail and the [sqlite3_reset(S)] call
|
||||
** might return SQLITE_BUSY if locking constraints prevent the
|
||||
** database change from committing. Therefore, it is important that
|
||||
** applications check the return code from [sqlite3_reset(S)] even if
|
||||
** no prior call to [sqlite3_step(S)] indicated a problem.
|
||||
**
|
||||
** ^The [sqlite3_reset(S)] interface does not change the values
|
||||
** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
|
||||
*/
|
||||
SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Create Or Redefine SQL Functions
|
||||
** KEYWORDS: {function creation routines}
|
||||
@@ -5484,7 +5558,7 @@ SQLITE_API int sqlite3_create_window_function(
|
||||
** [application-defined SQL function]
|
||||
** that has side-effects or that could potentially leak sensitive information.
|
||||
** This will prevent attacks in which an application is tricked
|
||||
** into using a database file that has had its schema surreptiously
|
||||
** into using a database file that has had its schema surreptitiously
|
||||
** modified to invoke the application-defined function in ways that are
|
||||
** harmful.
|
||||
** <p>
|
||||
@@ -5520,13 +5594,27 @@ SQLITE_API int sqlite3_create_window_function(
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>
|
||||
** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
|
||||
** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call
|
||||
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
|
||||
** Specifying this flag makes no difference for scalar or aggregate user
|
||||
** functions. However, if it is not specified for a user-defined window
|
||||
** function, then any sub-types belonging to arguments passed to the window
|
||||
** function may be discarded before the window function is called (i.e.
|
||||
** sqlite3_value_subtype() will always return 0).
|
||||
** This flag instructs SQLite to omit some corner-case optimizations that
|
||||
** might disrupt the operation of the [sqlite3_value_subtype()] function,
|
||||
** causing it to return zero rather than the correct subtype().
|
||||
** SQL functions that invokes [sqlite3_value_subtype()] should have this
|
||||
** property. If the SQLITE_SUBTYPE property is omitted, then the return
|
||||
** value from [sqlite3_value_subtype()] might sometimes be zero even though
|
||||
** a non-zero subtype was specified by the function argument expression.
|
||||
**
|
||||
** [[SQLITE_RESULT_SUBTYPE]] <dt>SQLITE_RESULT_SUBTYPE</dt><dd>
|
||||
** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call
|
||||
** [sqlite3_result_subtype()] to cause a sub-type to be associated with its
|
||||
** result.
|
||||
** Every function that invokes [sqlite3_result_subtype()] should have this
|
||||
** property. If it does not, then the call to [sqlite3_result_subtype()]
|
||||
** might become a no-op if the function is used as term in an
|
||||
** [expression index]. On the other hand, SQL functions that never invoke
|
||||
** [sqlite3_result_subtype()] should avoid setting this property, as the
|
||||
** purpose of this property is to disable certain optimizations that are
|
||||
** incompatible with subtypes.
|
||||
** </dd>
|
||||
** </dl>
|
||||
*/
|
||||
@@ -5534,6 +5622,7 @@ SQLITE_API int sqlite3_create_window_function(
|
||||
#define SQLITE_DIRECTONLY 0x000080000
|
||||
#define SQLITE_SUBTYPE 0x000100000
|
||||
#define SQLITE_INNOCUOUS 0x000200000
|
||||
#define SQLITE_RESULT_SUBTYPE 0x001000000
|
||||
|
||||
/*
|
||||
** CAPI3REF: Deprecated Functions
|
||||
@@ -5730,6 +5819,12 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*);
|
||||
** information can be used to pass a limited amount of context from
|
||||
** one SQL function to another. Use the [sqlite3_result_subtype()]
|
||||
** routine to set the subtype for the return value of an SQL function.
|
||||
**
|
||||
** Every [application-defined SQL function] that invoke this interface
|
||||
** should include the [SQLITE_SUBTYPE] property in the text
|
||||
** encoding argument when the function is [sqlite3_create_function|registered].
|
||||
** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
|
||||
** might return zero instead of the upstream subtype in some corner cases.
|
||||
*/
|
||||
SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);
|
||||
|
||||
@@ -5828,48 +5923,56 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
|
||||
** METHOD: sqlite3_context
|
||||
**
|
||||
** These functions may be used by (non-aggregate) SQL functions to
|
||||
** associate metadata with argument values. If the same value is passed to
|
||||
** multiple invocations of the same SQL function during query execution, under
|
||||
** some circumstances the associated metadata may be preserved. An example
|
||||
** of where this might be useful is in a regular-expression matching
|
||||
** function. The compiled version of the regular expression can be stored as
|
||||
** metadata associated with the pattern string.
|
||||
** associate auxiliary data with argument values. If the same argument
|
||||
** value is passed to multiple invocations of the same SQL function during
|
||||
** query execution, under some circumstances the associated auxiliary data
|
||||
** might be preserved. An example of where this might be useful is in a
|
||||
** regular-expression matching function. The compiled version of the regular
|
||||
** expression can be stored as auxiliary data associated with the pattern string.
|
||||
** Then as long as the pattern string remains the same,
|
||||
** the compiled regular expression can be reused on multiple
|
||||
** invocations of the same function.
|
||||
**
|
||||
** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata
|
||||
** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data
|
||||
** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument
|
||||
** value to the application-defined function. ^N is zero for the left-most
|
||||
** function argument. ^If there is no metadata
|
||||
** function argument. ^If there is no auxiliary data
|
||||
** associated with the function argument, the sqlite3_get_auxdata(C,N) interface
|
||||
** returns a NULL pointer.
|
||||
**
|
||||
** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
|
||||
** argument of the application-defined function. ^Subsequent
|
||||
** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the
|
||||
** N-th argument of the application-defined function. ^Subsequent
|
||||
** calls to sqlite3_get_auxdata(C,N) return P from the most recent
|
||||
** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
|
||||
** NULL if the metadata has been discarded.
|
||||
** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or
|
||||
** NULL if the auxiliary data has been discarded.
|
||||
** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
|
||||
** SQLite will invoke the destructor function X with parameter P exactly
|
||||
** once, when the metadata is discarded.
|
||||
** SQLite is free to discard the metadata at any time, including: <ul>
|
||||
** once, when the auxiliary data is discarded.
|
||||
** SQLite is free to discard the auxiliary data at any time, including: <ul>
|
||||
** <li> ^(when the corresponding function parameter changes)^, or
|
||||
** <li> ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
|
||||
** SQL statement)^, or
|
||||
** <li> ^(when sqlite3_set_auxdata() is invoked again on the same
|
||||
** parameter)^, or
|
||||
** <li> ^(during the original sqlite3_set_auxdata() call when a memory
|
||||
** allocation error occurs.)^ </ul>
|
||||
** allocation error occurs.)^
|
||||
** <li> ^(during the original sqlite3_set_auxdata() call if the function
|
||||
** is evaluated during query planning instead of during query execution,
|
||||
** as sometimes happens with [SQLITE_ENABLE_STAT4].)^ </ul>
|
||||
**
|
||||
** Note the last bullet in particular. The destructor X in
|
||||
** Note the last two bullets in particular. The destructor X in
|
||||
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
|
||||
** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
|
||||
** should be called near the end of the function implementation and the
|
||||
** function implementation should not make any use of P after
|
||||
** sqlite3_set_auxdata() has been called.
|
||||
** sqlite3_set_auxdata() has been called. Furthermore, a call to
|
||||
** sqlite3_get_auxdata() that occurs immediately after a corresponding call
|
||||
** to sqlite3_set_auxdata() might still return NULL if an out-of-memory
|
||||
** condition occurred during the sqlite3_set_auxdata() call or if the
|
||||
** function is being evaluated during query planning rather than during
|
||||
** query execution.
|
||||
**
|
||||
** ^(In practice, metadata is preserved between function calls for
|
||||
** ^(In practice, auxiliary data is preserved between function calls for
|
||||
** function parameters that are compile-time constants, including literal
|
||||
** values and [parameters] and expressions composed from the same.)^
|
||||
**
|
||||
@@ -5879,10 +5982,67 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
|
||||
**
|
||||
** These routines must be called from the same thread in which
|
||||
** the SQL function is running.
|
||||
**
|
||||
** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()].
|
||||
*/
|
||||
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
|
||||
SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Client Data
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** These functions are used to associate one or more named pointers
|
||||
** with a [database connection].
|
||||
** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P
|
||||
** to be attached to [database connection] D using name N. Subsequent
|
||||
** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P
|
||||
** or a NULL pointer if there were no prior calls to
|
||||
** sqlite3_set_clientdata() with the same values of D and N.
|
||||
** Names are compared using strcmp() and are thus case sensitive.
|
||||
**
|
||||
** If P and X are both non-NULL, then the destructor X is invoked with
|
||||
** argument P on the first of the following occurrences:
|
||||
** <ul>
|
||||
** <li> An out-of-memory error occurs during the call to
|
||||
** sqlite3_set_clientdata() which attempts to register pointer P.
|
||||
** <li> A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made
|
||||
** with the same D and N parameters.
|
||||
** <li> The database connection closes. SQLite does not make any guarantees
|
||||
** about the order in which destructors are called, only that all
|
||||
** destructors will be called exactly once at some point during the
|
||||
** database connection closing process.
|
||||
** </ul>
|
||||
**
|
||||
** SQLite does not do anything with client data other than invoke
|
||||
** destructors on the client data at the appropriate time. The intended
|
||||
** use for client data is to provide a mechanism for wrapper libraries
|
||||
** to store additional information about an SQLite database connection.
|
||||
**
|
||||
** There is no limit (other than available memory) on the number of different
|
||||
** client data pointers (with different names) that can be attached to a
|
||||
** single database connection. However, the implementation is optimized
|
||||
** for the case of having only one or two different client data names.
|
||||
** Applications and wrapper libraries are discouraged from using more than
|
||||
** one client data name each.
|
||||
**
|
||||
** There is no way to enumerate the client data pointers
|
||||
** associated with a database connection. The N parameter can be thought
|
||||
** of as a secret key such that only code that knows the secret key is able
|
||||
** to access the associated data.
|
||||
**
|
||||
** Security Warning: These interfaces should not be exposed in scripting
|
||||
** languages or in other circumstances where it might be possible for an
|
||||
** an attacker to invoke them. Any agent that can invoke these interfaces
|
||||
** can probably also take control of the process.
|
||||
**
|
||||
** Database connection client data is only available for SQLite
|
||||
** version 3.44.0 ([dateof:3.44.0]) and later.
|
||||
**
|
||||
** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()].
|
||||
*/
|
||||
SQLITE_API void *sqlite3_get_clientdata(sqlite3*,const char*);
|
||||
SQLITE_API int sqlite3_set_clientdata(sqlite3*, const char*, void*, void(*)(void*));
|
||||
|
||||
/*
|
||||
** CAPI3REF: Constants Defining Special Destructor Behavior
|
||||
@@ -6084,6 +6244,20 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
|
||||
** higher order bits are discarded.
|
||||
** The number of subtype bytes preserved by SQLite might increase
|
||||
** in future releases of SQLite.
|
||||
**
|
||||
** Every [application-defined SQL function] that invokes this interface
|
||||
** should include the [SQLITE_RESULT_SUBTYPE] property in its
|
||||
** text encoding argument when the SQL function is
|
||||
** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE]
|
||||
** property is omitted from the function that invokes sqlite3_result_subtype(),
|
||||
** then in some cases the sqlite3_result_subtype() might fail to set
|
||||
** the result subtype.
|
||||
**
|
||||
** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any
|
||||
** SQL function that invokes the sqlite3_result_subtype() interface
|
||||
** and that does not have the SQLITE_RESULT_SUBTYPE property will raise
|
||||
** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1
|
||||
** by default.
|
||||
*/
|
||||
SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
|
||||
|
||||
@@ -6515,7 +6689,7 @@ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
|
||||
SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
|
||||
** CAPI3REF: Allowed return values from sqlite3_txn_state()
|
||||
** KEYWORDS: {transaction state}
|
||||
**
|
||||
** These constants define the current transaction state of a database file.
|
||||
@@ -6647,7 +6821,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
|
||||
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
|
||||
** previous invocations for that database connection. ^If the callback
|
||||
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
|
||||
** then the autovacuum steps callback is cancelled. The return value
|
||||
** then the autovacuum steps callback is canceled. The return value
|
||||
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
|
||||
** be some other error code if something goes wrong. The current
|
||||
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
|
||||
@@ -6713,6 +6887,12 @@ SQLITE_API int sqlite3_autovacuum_pages(
|
||||
** The exceptions defined in this paragraph might change in a future
|
||||
** release of SQLite.
|
||||
**
|
||||
** Whether the update hook is invoked before or after the
|
||||
** corresponding change is currently unspecified and may differ
|
||||
** depending on the type of change. Do not rely on the order of the
|
||||
** hook call with regards to the final result of the operation which
|
||||
** triggers the hook.
|
||||
**
|
||||
** The update hook implementation must not do anything that will modify
|
||||
** the database connection that invoked the update hook. Any actions
|
||||
** to modify the database connection must be deferred until after the
|
||||
@@ -7166,6 +7346,10 @@ struct sqlite3_module {
|
||||
/* The methods above are in versions 1 and 2 of the sqlite_module object.
|
||||
** Those below are for version 3 and greater. */
|
||||
int (*xShadowName)(const char*);
|
||||
/* The methods above are in versions 1 through 3 of the sqlite_module object.
|
||||
** Those below are for version 4 and greater. */
|
||||
int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema,
|
||||
const char *zTabName, int mFlags, char **pzErr);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -7653,7 +7837,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
|
||||
** code is returned and the transaction rolled back.
|
||||
**
|
||||
** Calling this function with an argument that is not a NULL pointer or an
|
||||
** open blob handle results in undefined behaviour. ^Calling this routine
|
||||
** open blob handle results in undefined behavior. ^Calling this routine
|
||||
** with a null pointer (such as would be returned by a failed call to
|
||||
** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function
|
||||
** is passed a valid open blob handle, the values returned by the
|
||||
@@ -7880,9 +8064,11 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
|
||||
**
|
||||
** ^(Some systems (for example, Windows 95) do not support the operation
|
||||
** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try()
|
||||
** will always return SQLITE_BUSY. The SQLite core only ever uses
|
||||
** sqlite3_mutex_try() as an optimization so this is acceptable
|
||||
** behavior.)^
|
||||
** will always return SQLITE_BUSY. In most cases the SQLite core only uses
|
||||
** sqlite3_mutex_try() as an optimization, so this is acceptable
|
||||
** behavior. The exceptions are unix builds that set the
|
||||
** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working
|
||||
** sqlite3_mutex_try() is required.)^
|
||||
**
|
||||
** ^The sqlite3_mutex_leave() routine exits a mutex that was
|
||||
** previously entered by the same thread. The behavior
|
||||
@@ -8133,6 +8319,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_PRNG_SAVE 5
|
||||
#define SQLITE_TESTCTRL_PRNG_RESTORE 6
|
||||
#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_FK_NO_ACTION 7
|
||||
#define SQLITE_TESTCTRL_BITVEC_TEST 8
|
||||
#define SQLITE_TESTCTRL_FAULT_INSTALL 9
|
||||
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
|
||||
@@ -8140,6 +8327,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_ASSERT 12
|
||||
#define SQLITE_TESTCTRL_ALWAYS 13
|
||||
#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_JSON_SELFCHECK 14
|
||||
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
|
||||
@@ -8161,7 +8349,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_TRACEFLAGS 31
|
||||
#define SQLITE_TESTCTRL_TUNE 32
|
||||
#define SQLITE_TESTCTRL_LOGEST 33
|
||||
#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */
|
||||
#define SQLITE_TESTCTRL_USELONGDOUBLE 34
|
||||
#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Keyword Checking
|
||||
@@ -8174,7 +8363,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
** The sqlite3_keyword_count() interface returns the number of distinct
|
||||
** keywords understood by SQLite.
|
||||
**
|
||||
** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
|
||||
** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
|
||||
** makes *Z point to that keyword expressed as UTF8 and writes the number
|
||||
** of bytes in the keyword into *L. The string that *Z points to is not
|
||||
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
|
||||
@@ -9617,7 +9806,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
|
||||
** [[SQLITE_VTAB_DIRECTONLY]]<dt>SQLITE_VTAB_DIRECTONLY</dt>
|
||||
** <dd>Calls of the form
|
||||
** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the
|
||||
** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
|
||||
** the [xConnect] or [xCreate] methods of a [virtual table] implementation
|
||||
** prohibits that virtual table from being used from within triggers and
|
||||
** views.
|
||||
** </dd>
|
||||
@@ -9753,24 +9942,45 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
||||
** <li value="2"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
|
||||
** that the query planner does not need the rows returned in any particular
|
||||
** order, as long as rows with the same values in all "aOrderBy" columns
|
||||
** are adjacent.)^ ^(Furthermore, only a single row for each particular
|
||||
** combination of values in the columns identified by the "aOrderBy" field
|
||||
** needs to be returned.)^ ^It is always ok for two or more rows with the same
|
||||
** values in all "aOrderBy" columns to be returned, as long as all such rows
|
||||
** are adjacent. ^The virtual table may, if it chooses, omit extra rows
|
||||
** that have the same value for all columns identified by "aOrderBy".
|
||||
** ^However omitting the extra rows is optional.
|
||||
** order, as long as rows with the same values in all columns identified
|
||||
** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows
|
||||
** contain the same values for all columns identified by "colUsed", all but
|
||||
** one such row may optionally be omitted from the result.)^
|
||||
** The virtual table is not required to omit rows that are duplicates
|
||||
** over the "colUsed" columns, but if the virtual table can do that without
|
||||
** too much extra effort, it could potentially help the query to run faster.
|
||||
** This mode is used for a DISTINCT query.
|
||||
** <li value="3"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 3, that means
|
||||
** that the query planner needs only distinct rows but it does need the
|
||||
** rows to be sorted.)^ ^The virtual table implementation is free to omit
|
||||
** rows that are identical in all aOrderBy columns, if it wants to, but
|
||||
** it is not required to omit any rows. This mode is used for queries
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the
|
||||
** virtual table must return rows in the order defined by "aOrderBy" as
|
||||
** if the sqlite3_vtab_distinct() interface had returned 0. However if
|
||||
** two or more rows in the result have the same values for all columns
|
||||
** identified by "colUsed", then all but one such row may optionally be
|
||||
** omitted.)^ Like when the return value is 2, the virtual table
|
||||
** is not required to omit rows that are duplicates over the "colUsed"
|
||||
** columns, but if the virtual table can do that without
|
||||
** too much extra effort, it could potentially help the query to run faster.
|
||||
** This mode is used for queries
|
||||
** that have both DISTINCT and ORDER BY clauses.
|
||||
** </ol>
|
||||
**
|
||||
** <p>The following table summarizes the conditions under which the
|
||||
** virtual table is allowed to set the "orderByConsumed" flag based on
|
||||
** the value returned by sqlite3_vtab_distinct(). This table is a
|
||||
** restatement of the previous four paragraphs:
|
||||
**
|
||||
** <table border=1 cellspacing=0 cellpadding=10 width="90%">
|
||||
** <tr>
|
||||
** <td valign="top">sqlite3_vtab_distinct() return value
|
||||
** <td valign="top">Rows are returned in aOrderBy order
|
||||
** <td valign="top">Rows with the same value in all aOrderBy columns are adjacent
|
||||
** <td valign="top">Duplicates over all colUsed columns may be omitted
|
||||
** <tr><td>0<td>yes<td>yes<td>no
|
||||
** <tr><td>1<td>no<td>yes<td>no
|
||||
** <tr><td>2<td>no<td>yes<td>yes
|
||||
** <tr><td>3<td>yes<td>yes<td>yes
|
||||
** </table>
|
||||
**
|
||||
** ^For the purposes of comparing virtual table output values to see if the
|
||||
** values are same value for sorting purposes, two NULL values are considered
|
||||
** to be the same. In other words, the comparison operator is "IS"
|
||||
@@ -9807,7 +10017,7 @@ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*);
|
||||
** communicated to the xBestIndex method as a
|
||||
** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use
|
||||
** this constraint, it must set the corresponding
|
||||
** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under
|
||||
** aConstraintUsage[].argvIndex to a positive integer. ^(Then, under
|
||||
** the usual mode of handling IN operators, SQLite generates [bytecode]
|
||||
** that invokes the [xFilter|xFilter() method] once for each value
|
||||
** on the right-hand side of the IN operator.)^ Thus the virtual table
|
||||
@@ -10236,7 +10446,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
|
||||
** When the [sqlite3_blob_write()] API is used to update a blob column,
|
||||
** the pre-update hook is invoked with SQLITE_DELETE. This is because the
|
||||
** in this case the new values are not available. In this case, when a
|
||||
** callback made with op==SQLITE_DELETE is actuall a write using the
|
||||
** callback made with op==SQLITE_DELETE is actually a write using the
|
||||
** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
|
||||
** the index of the column being written. In other cases, where the
|
||||
** pre-update hook is being invoked for some other reason, including a
|
||||
@@ -10497,6 +10707,13 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
|
||||
** of the database exists.
|
||||
**
|
||||
** After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set,
|
||||
** the returned buffer content will remain accessible and unchanged
|
||||
** until either the next write operation on the connection or when
|
||||
** the connection is closed, and applications must not modify the
|
||||
** buffer. If the bit had been clear, the returned buffer will not
|
||||
** be accessed by SQLite after the call.
|
||||
**
|
||||
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
|
||||
** allocation error occurs.
|
||||
@@ -10545,6 +10762,9 @@ SQLITE_API unsigned char *sqlite3_serialize(
|
||||
** SQLite will try to increase the buffer size using sqlite3_realloc64()
|
||||
** if writes on the database cause it to grow larger than M bytes.
|
||||
**
|
||||
** Applications must not modify the buffer P or invalidate it before
|
||||
** the database connection D is closed.
|
||||
**
|
||||
** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
|
||||
** database is currently in a read transaction or is involved in a backup
|
||||
** operation.
|
||||
@@ -10553,6 +10773,13 @@ SQLITE_API unsigned char *sqlite3_serialize(
|
||||
** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
|
||||
** function returns SQLITE_ERROR.
|
||||
**
|
||||
** The deserialized database should not be in [WAL mode]. If the database
|
||||
** is in WAL mode, then any attempt to use the database file will result
|
||||
** in an [SQLITE_CANTOPEN] error. The application can set the
|
||||
** [file format version numbers] (bytes 18 and 19) of the input database P
|
||||
** to 0x01 prior to invoking sqlite3_deserialize(D,S,P,N,M,F) to force the
|
||||
** database file into rollback mode and work around this limitation.
|
||||
**
|
||||
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
|
||||
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
|
||||
** [sqlite3_free()] is invoked on argument P prior to returning.
|
||||
@@ -11625,6 +11852,18 @@ SQLITE_API int sqlite3changeset_concat(
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Upgrade the Schema of a Changeset/Patchset
|
||||
*/
|
||||
SQLITE_API int sqlite3changeset_upgrade(
|
||||
sqlite3 *db,
|
||||
const char *zDb,
|
||||
int nIn, const void *pIn, /* Input changeset */
|
||||
int *pnOut, void **ppOut /* OUT: Inverse of input */
|
||||
);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Changegroup Handle
|
||||
**
|
||||
@@ -11671,6 +11910,38 @@ typedef struct sqlite3_changegroup sqlite3_changegroup;
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add a Schema to a Changegroup
|
||||
** METHOD: sqlite3_changegroup_schema
|
||||
**
|
||||
** This method may be used to optionally enforce the rule that the changesets
|
||||
** added to the changegroup handle must match the schema of database zDb
|
||||
** ("main", "temp", or the name of an attached database). If
|
||||
** sqlite3changegroup_add() is called to add a changeset that is not compatible
|
||||
** with the configured schema, SQLITE_SCHEMA is returned and the changegroup
|
||||
** object is left in an undefined state.
|
||||
**
|
||||
** A changeset schema is considered compatible with the database schema in
|
||||
** the same way as for sqlite3changeset_apply(). Specifically, for each
|
||||
** table in the changeset, there exists a database table with:
|
||||
**
|
||||
** <ul>
|
||||
** <li> The name identified by the changeset, and
|
||||
** <li> at least as many columns as recorded in the changeset, and
|
||||
** <li> the primary key columns in the same position as recorded in
|
||||
** the changeset.
|
||||
** </ul>
|
||||
**
|
||||
** The output of the changegroup object always has the same schema as the
|
||||
** database nominated using this function. In cases where changesets passed
|
||||
** to sqlite3changegroup_add() have fewer columns than the corresponding table
|
||||
** in the database schema, these are filled in using the default column
|
||||
** values from the database schema. This makes it possible to combined
|
||||
** changesets that have different numbers of columns for a single table
|
||||
** within a changegroup, provided that they are otherwise compatible.
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add A Changeset To A Changegroup
|
||||
** METHOD: sqlite3_changegroup
|
||||
@@ -11739,16 +12010,45 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
|
||||
** If the new changeset contains changes to a table that is already present
|
||||
** in the changegroup, then the number of columns and the position of the
|
||||
** primary key columns for the table must be consistent. If this is not the
|
||||
** case, this function fails with SQLITE_SCHEMA. If the input changeset
|
||||
** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
|
||||
** returned. Or, if an out-of-memory condition occurs during processing, this
|
||||
** function returns SQLITE_NOMEM. In all cases, if an error occurs the state
|
||||
** of the final contents of the changegroup is undefined.
|
||||
** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup
|
||||
** object has been configured with a database schema using the
|
||||
** sqlite3changegroup_schema() API, then it is possible to combine changesets
|
||||
** with different numbers of columns for a single table, provided that
|
||||
** they are otherwise compatible.
|
||||
**
|
||||
** If no error occurs, SQLITE_OK is returned.
|
||||
** If the input changeset appears to be corrupt and the corruption is
|
||||
** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition
|
||||
** occurs during processing, this function returns SQLITE_NOMEM.
|
||||
**
|
||||
** In all cases, if an error occurs the state of the final contents of the
|
||||
** changegroup is undefined. If no error occurs, SQLITE_OK is returned.
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add A Single Change To A Changegroup
|
||||
** METHOD: sqlite3_changegroup
|
||||
**
|
||||
** This function adds the single change currently indicated by the iterator
|
||||
** passed as the second argument to the changegroup object. The rules for
|
||||
** adding the change are just as described for [sqlite3changegroup_add()].
|
||||
**
|
||||
** If the change is successfully added to the changegroup, SQLITE_OK is
|
||||
** returned. Otherwise, an SQLite error code is returned.
|
||||
**
|
||||
** The iterator must point to a valid entry when this function is called.
|
||||
** If it does not, SQLITE_ERROR is returned and no change is added to the
|
||||
** changegroup. Additionally, the iterator must not have been opened with
|
||||
** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also
|
||||
** returned.
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_add_change(
|
||||
sqlite3_changegroup*,
|
||||
sqlite3_changeset_iter*
|
||||
);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
|
||||
** METHOD: sqlite3_changegroup
|
||||
@@ -12010,10 +12310,17 @@ SQLITE_API int sqlite3changeset_apply_v2(
|
||||
** <li>an insert change if all fields of the conflicting row match
|
||||
** the row being inserted.
|
||||
** </ul>
|
||||
**
|
||||
** <dt>SQLITE_CHANGESETAPPLY_FKNOACTION <dd>
|
||||
** If this flag it set, then all foreign key constraints in the target
|
||||
** database behave as if they were declared with "ON UPDATE NO ACTION ON
|
||||
** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
|
||||
** or SET DEFAULT.
|
||||
*/
|
||||
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
|
||||
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
|
||||
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
|
||||
#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
|
||||
|
||||
/*
|
||||
** CAPI3REF: Constants Passed To The Conflict Handler
|
||||
@@ -12546,8 +12853,8 @@ struct Fts5PhraseIter {
|
||||
** EXTENSION API FUNCTIONS
|
||||
**
|
||||
** xUserData(pFts):
|
||||
** Return a copy of the context pointer the extension function was
|
||||
** registered with.
|
||||
** Return a copy of the pUserData pointer passed to the xCreateFunction()
|
||||
** API when the extension function was registered.
|
||||
**
|
||||
** xColumnTotalSize(pFts, iCol, pnToken):
|
||||
** If parameter iCol is less than zero, set output variable *pnToken
|
||||
@@ -12579,8 +12886,11 @@ struct Fts5PhraseIter {
|
||||
** created with the "columnsize=0" option.
|
||||
**
|
||||
** xColumnText:
|
||||
** This function attempts to retrieve the text of column iCol of the
|
||||
** current document. If successful, (*pz) is set to point to a buffer
|
||||
** If parameter iCol is less than zero, or greater than or equal to the
|
||||
** number of columns in the table, SQLITE_RANGE is returned.
|
||||
**
|
||||
** Otherwise, this function attempts to retrieve the text of column iCol of
|
||||
** the current document. If successful, (*pz) is set to point to a buffer
|
||||
** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
|
||||
** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
|
||||
** if an error occurs, an SQLite error code is returned and the final values
|
||||
@@ -12590,8 +12900,10 @@ struct Fts5PhraseIter {
|
||||
** Returns the number of phrases in the current query expression.
|
||||
**
|
||||
** xPhraseSize:
|
||||
** Returns the number of tokens in phrase iPhrase of the query. Phrases
|
||||
** are numbered starting from zero.
|
||||
** If parameter iCol is less than zero, or greater than or equal to the
|
||||
** number of phrases in the current query, as returned by xPhraseCount,
|
||||
** 0 is returned. Otherwise, this function returns the number of tokens in
|
||||
** phrase iPhrase of the query. Phrases are numbered starting from zero.
|
||||
**
|
||||
** xInstCount:
|
||||
** Set *pnInst to the total number of occurrences of all phrases within
|
||||
@@ -12607,12 +12919,13 @@ struct Fts5PhraseIter {
|
||||
** Query for the details of phrase match iIdx within the current row.
|
||||
** Phrase matches are numbered starting from zero, so the iIdx argument
|
||||
** should be greater than or equal to zero and smaller than the value
|
||||
** output by xInstCount().
|
||||
** output by xInstCount(). If iIdx is less than zero or greater than
|
||||
** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned.
|
||||
**
|
||||
** Usually, output parameter *piPhrase is set to the phrase number, *piCol
|
||||
** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol
|
||||
** to the column in which it occurs and *piOff the token offset of the
|
||||
** first token of the phrase. Returns SQLITE_OK if successful, or an error
|
||||
** code (i.e. SQLITE_NOMEM) if an error occurs.
|
||||
** first token of the phrase. SQLITE_OK is returned if successful, or an
|
||||
** error code (i.e. SQLITE_NOMEM) if an error occurs.
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "detail=none" or "detail=column" option.
|
||||
@@ -12638,6 +12951,10 @@ struct Fts5PhraseIter {
|
||||
** Invoking Api.xUserData() returns a copy of the pointer passed as
|
||||
** the third argument to pUserData.
|
||||
**
|
||||
** If parameter iPhrase is less than zero, or greater than or equal to
|
||||
** the number of phrases in the query, as returned by xPhraseCount(),
|
||||
** this function returns SQLITE_RANGE.
|
||||
**
|
||||
** If the callback function returns any value other than SQLITE_OK, the
|
||||
** query is abandoned and the xQueryPhrase function returns immediately.
|
||||
** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
|
||||
@@ -12752,6 +13069,39 @@ struct Fts5PhraseIter {
|
||||
**
|
||||
** xPhraseNextColumn()
|
||||
** See xPhraseFirstColumn above.
|
||||
**
|
||||
** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken)
|
||||
** This is used to access token iToken of phrase iPhrase of the current
|
||||
** query. Before returning, output parameter *ppToken is set to point
|
||||
** to a buffer containing the requested token, and *pnToken to the
|
||||
** size of this buffer in bytes.
|
||||
**
|
||||
** If iPhrase or iToken are less than zero, or if iPhrase is greater than
|
||||
** or equal to the number of phrases in the query as reported by
|
||||
** xPhraseCount(), or if iToken is equal to or greater than the number of
|
||||
** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken
|
||||
are both zeroed.
|
||||
**
|
||||
** The output text is not a copy of the query text that specified the
|
||||
** token. It is the output of the tokenizer module. For tokendata=1
|
||||
** tables, this includes any embedded 0x00 and trailing data.
|
||||
**
|
||||
** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken)
|
||||
** This is used to access token iToken of phrase hit iIdx within the
|
||||
** current row. If iIdx is less than zero or greater than or equal to the
|
||||
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
|
||||
** output variable (*ppToken) is set to point to a buffer containing the
|
||||
** matching document token, and (*pnToken) to the size of that buffer in
|
||||
** bytes. This API is not available if the specified token matches a
|
||||
** prefix query term. In that case both output variables are always set
|
||||
** to 0.
|
||||
**
|
||||
** The output text is not a copy of the document text that was tokenized.
|
||||
** It is the output of the tokenizer module. For tokendata=1 tables, this
|
||||
** includes any embedded 0x00 and trailing data.
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "detail=none" or "detail=column" option.
|
||||
*/
|
||||
struct Fts5ExtensionApi {
|
||||
int iVersion; /* Currently always set to 3 */
|
||||
@@ -12789,6 +13139,13 @@ struct Fts5ExtensionApi {
|
||||
|
||||
int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
|
||||
void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
|
||||
|
||||
/* Below this point are iVersion>=3 only */
|
||||
int (*xQueryToken)(Fts5Context*,
|
||||
int iPhrase, int iToken,
|
||||
const char **ppToken, int *pnToken
|
||||
);
|
||||
int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -12983,8 +13340,8 @@ struct Fts5ExtensionApi {
|
||||
** as separate queries of the FTS index are required for each synonym.
|
||||
**
|
||||
** When using methods (2) or (3), it is important that the tokenizer only
|
||||
** provide synonyms when tokenizing document text (method (2)) or query
|
||||
** text (method (3)), not both. Doing so will not cause any errors, but is
|
||||
** provide synonyms when tokenizing document text (method (3)) or query
|
||||
** text (method (2)), not both. Doing so will not cause any errors, but is
|
||||
** inefficient.
|
||||
*/
|
||||
typedef struct Fts5Tokenizer Fts5Tokenizer;
|
||||
@@ -13032,7 +13389,7 @@ struct fts5_api {
|
||||
int (*xCreateTokenizer)(
|
||||
fts5_api *pApi,
|
||||
const char *zName,
|
||||
void *pContext,
|
||||
void *pUserData,
|
||||
fts5_tokenizer *pTokenizer,
|
||||
void (*xDestroy)(void*)
|
||||
);
|
||||
@@ -13041,7 +13398,7 @@ struct fts5_api {
|
||||
int (*xFindTokenizer)(
|
||||
fts5_api *pApi,
|
||||
const char *zName,
|
||||
void **ppContext,
|
||||
void **ppUserData,
|
||||
fts5_tokenizer *pTokenizer
|
||||
);
|
||||
|
||||
@@ -13049,7 +13406,7 @@ struct fts5_api {
|
||||
int (*xCreateFunction)(
|
||||
fts5_api *pApi,
|
||||
const char *zName,
|
||||
void *pContext,
|
||||
void *pUserData,
|
||||
fts5_extension_function xFunction,
|
||||
void (*xDestroy)(void*)
|
||||
);
|
||||
|
||||
@@ -209,6 +209,9 @@ SplitView.prototype = {
|
||||
this._nav.appendChild(aSummary);
|
||||
|
||||
aSummary.addEventListener("click", (aEvent) => {
|
||||
if (aEvent.button != 0) {
|
||||
return;
|
||||
}
|
||||
aEvent.stopPropagation();
|
||||
this.activeSummary = aSummary;
|
||||
}, false);
|
||||
|
||||
@@ -97,6 +97,9 @@ AutocompletePopup.prototype = {
|
||||
},
|
||||
|
||||
onClick: function (e) {
|
||||
if (e.button != 0) {
|
||||
return;
|
||||
}
|
||||
let item = e.target.closest(".autocomplete-item");
|
||||
if (item && typeof item.dataset.index !== "undefined") {
|
||||
this.selectedIndex = parseInt(item.dataset.index, 10);
|
||||
|
||||
@@ -240,6 +240,9 @@ Spectrum.prototype = {
|
||||
},
|
||||
|
||||
onElementClick: function (e) {
|
||||
if (e.button != 0) {
|
||||
return;
|
||||
}
|
||||
e.stopPropagation();
|
||||
},
|
||||
|
||||
|
||||
@@ -1480,6 +1480,9 @@ Column.prototype = {
|
||||
* for sorting.
|
||||
*/
|
||||
onClick: function (event) {
|
||||
if (event.button != 0) {
|
||||
return;
|
||||
}
|
||||
let target = event.originalTarget;
|
||||
|
||||
if (target.nodeType !== target.ELEMENT_NODE || target == this.column) {
|
||||
|
||||
@@ -174,7 +174,10 @@ StyleEditorUI.prototype = {
|
||||
|
||||
this._view = new SplitView(viewRoot);
|
||||
|
||||
wire(this._view.rootElement, ".style-editor-newButton", () =>{
|
||||
wire(this._view.rootElement, ".style-editor-newButton", (e) =>{
|
||||
if (e.button != 0) {
|
||||
return;
|
||||
}
|
||||
this._debuggee.addStyleSheet(null);
|
||||
});
|
||||
|
||||
|
||||
@@ -569,11 +569,9 @@ WebConsoleActor.prototype =
|
||||
|
||||
let startedListeners = [];
|
||||
let window = !this.parentActor.isRootActor ? this.window : null;
|
||||
let appId = null;
|
||||
let messageManager = null;
|
||||
|
||||
if (this._parentIsContentActor) {
|
||||
appId = this.parentActor.docShell.appId;
|
||||
messageManager = this.parentActor.messageManager;
|
||||
}
|
||||
|
||||
@@ -604,16 +602,16 @@ WebConsoleActor.prototype =
|
||||
// Create a StackTraceCollector that's going to be shared both by the
|
||||
// NetworkMonitorChild (getting messages about requests from parent) and
|
||||
// by the NetworkMonitor that directly watches service workers requests.
|
||||
this.stackTraceCollector = new StackTraceCollector({ window, appId });
|
||||
this.stackTraceCollector = new StackTraceCollector({ window });
|
||||
this.stackTraceCollector.init();
|
||||
|
||||
let processBoundary = Services.appinfo.processType !=
|
||||
Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||
if ((appId || messageManager) && processBoundary) {
|
||||
if (messageManager && processBoundary) {
|
||||
// Start a network monitor in the parent process to listen to
|
||||
// most requests than happen in parent
|
||||
this.networkMonitor =
|
||||
new NetworkMonitorChild(appId, this.parentActor.outerWindowID,
|
||||
new NetworkMonitorChild(this.parentActor.outerWindowID,
|
||||
messageManager, this.conn, this);
|
||||
this.networkMonitor.init();
|
||||
// Spawn also one in the child to listen to service workers
|
||||
|
||||
@@ -37,12 +37,12 @@ function getTopWindow(win) {
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
|
||||
if (!docShell.isMozBrowserOrApp) {
|
||||
if (!docShell.isMozBrowser) {
|
||||
return win.top;
|
||||
}
|
||||
|
||||
let topDocShell =
|
||||
docShell.getSameTypeRootTreeItemIgnoreBrowserAndAppBoundaries();
|
||||
docShell.getSameTypeRootTreeItemIgnoreBrowserBoundaries();
|
||||
|
||||
return topDocShell
|
||||
? topDocShell.contentViewer.DOMDocument.defaultView
|
||||
@@ -98,12 +98,12 @@ function getParentWindow(win) {
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
|
||||
if (!docShell.isMozBrowserOrApp) {
|
||||
if (!docShell.isMozBrowser) {
|
||||
return win.parent;
|
||||
}
|
||||
|
||||
let parentDocShell =
|
||||
docShell.getSameTypeParentIgnoreBrowserAndAppBoundaries();
|
||||
docShell.getSameTypeParentIgnoreBrowserBoundaries();
|
||||
|
||||
return parentDocShell
|
||||
? parentDocShell.contentViewer.DOMDocument.defaultView
|
||||
|
||||
@@ -1551,8 +1551,6 @@ NetworkMonitor.prototype = {
|
||||
* data to the WebConsoleActor or to a NetworkEventActor.
|
||||
*
|
||||
* @constructor
|
||||
* @param number appId
|
||||
* The web appId of the child process.
|
||||
* @param number outerWindowID
|
||||
* The outerWindowID of the TabActor's main window.
|
||||
* @param nsIMessageManager messageManager
|
||||
@@ -1562,8 +1560,7 @@ NetworkMonitor.prototype = {
|
||||
* @param object owner
|
||||
* The WebConsoleActor that is listening for the network requests.
|
||||
*/
|
||||
function NetworkMonitorChild(appId, outerWindowID, messageManager, conn, owner) {
|
||||
this.appId = appId;
|
||||
function NetworkMonitorChild(outerWindowID, messageManager, conn, owner) {
|
||||
this.outerWindowID = outerWindowID;
|
||||
this.conn = conn;
|
||||
this.owner = owner;
|
||||
@@ -1577,7 +1574,6 @@ function NetworkMonitorChild(appId, outerWindowID, messageManager, conn, owner)
|
||||
exports.NetworkMonitorChild = NetworkMonitorChild;
|
||||
|
||||
NetworkMonitorChild.prototype = {
|
||||
appId: null,
|
||||
owner: null,
|
||||
_netEvents: null,
|
||||
_saveRequestAndResponseBodies: true,
|
||||
@@ -1623,7 +1619,6 @@ NetworkMonitorChild.prototype = {
|
||||
mm.addMessageListener(`${this._msgName}:newEvent`, this._onNewEvent);
|
||||
mm.addMessageListener(`${this._msgName}:updateEvent`, this._onUpdateEvent);
|
||||
mm.sendAsyncMessage(this._msgName, {
|
||||
appId: this.appId,
|
||||
outerWindowID: this.outerWindowID,
|
||||
action: "start",
|
||||
});
|
||||
|
||||
@@ -157,28 +157,6 @@ LoadContext::SetRemoteTabs(bool aUseRemoteTabs)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadContext::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement)
|
||||
{
|
||||
MOZ_ASSERT(mIsNotNull);
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aIsInIsolatedMozBrowserElement);
|
||||
|
||||
*aIsInIsolatedMozBrowserElement = mOriginAttributes.mInIsolatedMozBrowser;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadContext::GetAppId(uint32_t* aAppId)
|
||||
{
|
||||
MOZ_ASSERT(mIsNotNull);
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aAppId);
|
||||
|
||||
*aAppId = mOriginAttributes.mAppId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadContext::GetOriginAttributes(JS::MutableHandleValue aAttrs)
|
||||
{
|
||||
|
||||
@@ -38,8 +38,6 @@ public:
|
||||
NS_DECL_NSILOADCONTEXT
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
// appId/inIsolatedMozBrowser arguments override those in SerializedLoadContext
|
||||
// provided by child process.
|
||||
LoadContext(const IPC::SerializedLoadContext& aToCopy,
|
||||
dom::Element* aTopFrameElement,
|
||||
DocShellOriginAttributes& aAttrs)
|
||||
@@ -54,8 +52,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
// appId/inIsolatedMozBrowser arguments override those in SerializedLoadContext
|
||||
// provided by child process.
|
||||
LoadContext(const IPC::SerializedLoadContext& aToCopy,
|
||||
uint64_t aNestedFrameId,
|
||||
DocShellOriginAttributes& aAttrs)
|
||||
|
||||
@@ -334,7 +334,7 @@ nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
|
||||
curDocShellItem->GetParent(getter_AddRefs(parentDocShellItem))) &&
|
||||
parentDocShellItem) {
|
||||
nsCOMPtr<nsIDocShell> curDocShell = do_QueryInterface(curDocShellItem);
|
||||
if (curDocShell && curDocShell->GetIsMozBrowserOrApp()) {
|
||||
if (curDocShell && curDocShell->GetIsMozBrowser()) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -427,6 +427,7 @@ ShouldIgnoreFrameOptions(nsIChannel* aChannel, nsIPrincipal* aPrincipal)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// log warning to console that xfo is ignored because of CSP
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
||||
uint64_t innerWindowID = loadInfo ? loadInfo->GetInnerWindowID() : 0;
|
||||
@@ -440,7 +441,7 @@ ShouldIgnoreFrameOptions(nsIChannel* aChannel, nsIPrincipal* aPrincipal)
|
||||
0, // no columnnumber
|
||||
nsIScriptError::warningFlag,
|
||||
"CSP", innerWindowID);
|
||||
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+18
-103
@@ -193,7 +193,6 @@
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "nsDSURIContentListener.h"
|
||||
#include "nsDocShellLoadTypes.h"
|
||||
#include "nsDocShellTransferableHooks.h"
|
||||
@@ -2564,7 +2563,7 @@ nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetFullscreenAllowed(bool aFullscreenAllowed)
|
||||
{
|
||||
if (!nsIDocShell::GetIsMozBrowserOrApp()) {
|
||||
if (!nsIDocShell::GetIsMozBrowser()) {
|
||||
// Only allow setting of fullscreenAllowed on content/process boundaries.
|
||||
// At non-boundaries the fullscreenAllowed attribute is calculated based on
|
||||
// whether all enclosing frames have the "mozFullscreenAllowed" attribute
|
||||
@@ -3396,7 +3395,7 @@ nsDocShell::GetSameTypeParent(nsIDocShellTreeItem** aParent)
|
||||
NS_ENSURE_ARG_POINTER(aParent);
|
||||
*aParent = nullptr;
|
||||
|
||||
if (nsIDocShell::GetIsMozBrowserOrApp()) {
|
||||
if (nsIDocShell::GetIsMozBrowser()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -3413,7 +3412,7 @@ nsDocShell::GetSameTypeParent(nsIDocShellTreeItem** aParent)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetSameTypeParentIgnoreBrowserAndAppBoundaries(nsIDocShell** aParent)
|
||||
nsDocShell::GetSameTypeParentIgnoreBrowserBoundaries(nsIDocShell** aParent)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aParent);
|
||||
*aParent = nullptr;
|
||||
@@ -3467,18 +3466,18 @@ nsDocShell::GetSameTypeRootTreeItem(nsIDocShellTreeItem** aRootTreeItem)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetSameTypeRootTreeItemIgnoreBrowserAndAppBoundaries(nsIDocShell ** aRootTreeItem)
|
||||
nsDocShell::GetSameTypeRootTreeItemIgnoreBrowserBoundaries(nsIDocShell ** aRootTreeItem)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRootTreeItem);
|
||||
*aRootTreeItem = static_cast<nsIDocShell *>(this);
|
||||
|
||||
nsCOMPtr<nsIDocShell> parent;
|
||||
NS_ENSURE_SUCCESS(GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent)),
|
||||
NS_ENSURE_SUCCESS(GetSameTypeParentIgnoreBrowserBoundaries(getter_AddRefs(parent)),
|
||||
NS_ERROR_FAILURE);
|
||||
while (parent) {
|
||||
*aRootTreeItem = parent;
|
||||
NS_ENSURE_SUCCESS((*aRootTreeItem)->
|
||||
GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent)),
|
||||
GetSameTypeParentIgnoreBrowserBoundaries(getter_AddRefs(parent)),
|
||||
NS_ERROR_FAILURE);
|
||||
}
|
||||
NS_ADDREF(*aRootTreeItem);
|
||||
@@ -3532,12 +3531,6 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (targetDS->GetIsInIsolatedMozBrowserElement() !=
|
||||
accessingDS->GetIsInIsolatedMozBrowserElement() ||
|
||||
targetDS->GetAppId() != accessingDS->GetAppId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> accessingRoot;
|
||||
aAccessingItem->GetSameTypeRootTreeItem(getter_AddRefs(accessingRoot));
|
||||
nsCOMPtr<nsIDocShell> accessingRootDS = do_QueryInterface(accessingRoot);
|
||||
@@ -3558,7 +3551,7 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem,
|
||||
if (OriginAttributes::IsFirstPartyEnabled()) {
|
||||
if (accessingDS == accessingRootDS &&
|
||||
aAccessingItem->ItemType() == nsIDocShellTreeItem::typeContent &&
|
||||
!accessingDS->GetIsMozBrowserOrApp()) {
|
||||
!accessingDS->GetIsMozBrowser()) {
|
||||
|
||||
nsCOMPtr<nsIDocument> accessingDoc = aAccessingItem->GetDocument();
|
||||
|
||||
@@ -3572,7 +3565,7 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem,
|
||||
|
||||
if (targetDS == targetRootDS &&
|
||||
aTargetItem->ItemType() == nsIDocShellTreeItem::typeContent &&
|
||||
!targetDS->GetIsMozBrowserOrApp()) {
|
||||
!targetDS->GetIsMozBrowser()) {
|
||||
|
||||
nsCOMPtr<nsIDocument> targetDoc = aAccessingItem->GetDocument();
|
||||
|
||||
@@ -3769,7 +3762,7 @@ nsDocShell::DoFindItemWithName(const nsAString& aName,
|
||||
|
||||
// If we have a same-type parent, respecting browser and app boundaries.
|
||||
// NOTE: Could use GetSameTypeParent if the issues described in bug 1310344 are fixed.
|
||||
if (!GetIsMozBrowserOrApp() && parentAsTreeItem->ItemType() == mItemType) {
|
||||
if (!GetIsMozBrowser() && parentAsTreeItem->ItemType() == mItemType) {
|
||||
return parentAsTreeItem->FindItemWithName(
|
||||
aName,
|
||||
static_cast<nsIDocShellTreeItem*>(this),
|
||||
@@ -5282,16 +5275,6 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
|
||||
errorPageUrl.AppendLiteral("&f=");
|
||||
errorPageUrl.AppendASCII(frameType.get());
|
||||
|
||||
// Append the manifest URL if the error comes from an app.
|
||||
nsString manifestURL;
|
||||
nsresult rv = GetAppManifestURL(manifestURL);
|
||||
if (manifestURL.Length() > 0) {
|
||||
nsCString manifestParam;
|
||||
SAFE_ESCAPE(manifestParam, NS_ConvertUTF16toUTF8(manifestURL), url_Path);
|
||||
errorPageUrl.AppendLiteral("&m=");
|
||||
errorPageUrl.AppendASCII(manifestParam.get());
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID);
|
||||
int32_t cpsState;
|
||||
if (cps && NS_SUCCEEDED(cps->GetState(&cpsState)) &&
|
||||
@@ -5305,7 +5288,7 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
|
||||
errorPageUrl.AppendASCII(escapedDescription.get());
|
||||
|
||||
nsCOMPtr<nsIURI> errorPageURI;
|
||||
rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return InternalLoad(errorPageURI, nullptr, false, false,
|
||||
@@ -6190,9 +6173,7 @@ nsDocShell::SetIsActive(bool aIsActive)
|
||||
mScriptGlobal->SetIsBackground(!aIsActive);
|
||||
if (nsCOMPtr<nsIDocument> doc = mScriptGlobal->GetExtantDoc()) {
|
||||
// Update orientation when the top-level browsing context becomes active.
|
||||
// We make an exception for apps because they currently rely on
|
||||
// orientation locks persisting across browsing contexts.
|
||||
if (aIsActive && !GetIsApp()) {
|
||||
if (aIsActive) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> parent;
|
||||
GetSameTypeParent(getter_AddRefs(parent));
|
||||
if (!parent) {
|
||||
@@ -6229,7 +6210,7 @@ nsDocShell::SetIsActive(bool aIsActive)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!docshell->GetIsMozBrowserOrApp()) {
|
||||
if (!docshell->GetIsMozBrowser()) {
|
||||
docshell->SetIsActive(aIsActive);
|
||||
}
|
||||
}
|
||||
@@ -10565,9 +10546,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
// lock the orientation of the document to the document's default
|
||||
// orientation. We don't explicitly check for a top-level browsing context
|
||||
// here because orientation is only set on top-level browsing contexts.
|
||||
// We make an exception for apps because they currently rely on
|
||||
// orientation locks persisting across browsing contexts.
|
||||
if (OrientationLock() != eScreenOrientation_None && !GetIsApp()) {
|
||||
if (OrientationLock() != eScreenOrientation_None) {
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIDocShellTreeItem> parent;
|
||||
GetSameTypeParent(getter_AddRefs(parent));
|
||||
@@ -10950,7 +10929,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||
NeckoOriginAttributes neckoAttrs;
|
||||
bool isTopLevelDoc = aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT &&
|
||||
mItemType == typeContent &&
|
||||
!GetIsMozBrowserOrApp();
|
||||
!GetIsMozBrowser();
|
||||
neckoAttrs.InheritFromDocShellToNecko(GetOriginAttributes(), isTopLevelDoc, aURI);
|
||||
rv = loadInfo->SetOriginAttributes(neckoAttrs);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@@ -14387,16 +14366,9 @@ nsDocShell::GetFrameType(uint32_t* aFrameType)
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsApp(bool* aIsApp)
|
||||
nsDocShell::GetIsMozBrowser(bool* aIsMozBrowser)
|
||||
{
|
||||
*aIsApp = (mFrameType == FRAME_TYPE_APP);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsMozBrowserOrApp(bool* aIsMozBrowserOrApp)
|
||||
{
|
||||
*aIsMozBrowserOrApp = (mFrameType != FRAME_TYPE_REGULAR);
|
||||
*aIsMozBrowser = (mFrameType == FRAME_TYPE_BROWSER);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -14419,30 +14391,9 @@ nsDocShell::GetInheritedFrameType()
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsIsolatedMozBrowserElement(bool* aIsIsolatedMozBrowserElement)
|
||||
nsDocShell::GetIsInMozBrowser(bool* aIsInMozBrowser)
|
||||
{
|
||||
bool result = mFrameType == FRAME_TYPE_BROWSER &&
|
||||
mOriginAttributes.mInIsolatedMozBrowser;
|
||||
*aIsIsolatedMozBrowserElement = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement)
|
||||
{
|
||||
MOZ_ASSERT(!mOriginAttributes.mInIsolatedMozBrowser ||
|
||||
(GetInheritedFrameType() == FRAME_TYPE_BROWSER),
|
||||
"Isolated mozbrowser should only be true inside browser frames");
|
||||
bool result = (GetInheritedFrameType() == FRAME_TYPE_BROWSER) &&
|
||||
mOriginAttributes.mInIsolatedMozBrowser;
|
||||
*aIsInIsolatedMozBrowserElement = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsInMozBrowserOrApp(bool* aIsInMozBrowserOrApp)
|
||||
{
|
||||
*aIsInMozBrowserOrApp = (GetInheritedFrameType() != FRAME_TYPE_REGULAR);
|
||||
*aIsInMozBrowser = (GetInheritedFrameType() == FRAME_TYPE_BROWSER);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -14460,25 +14411,6 @@ nsDocShell::GetIsTopLevelContentDocShell(bool* aIsTopLevelContentDocShell)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetAppId(uint32_t* aAppId)
|
||||
{
|
||||
if (mOriginAttributes.mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||
*aAppId = mOriginAttributes.mAppId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> parent;
|
||||
GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent));
|
||||
|
||||
if (!parent) {
|
||||
*aAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return parent->GetAppId(aAppId);
|
||||
}
|
||||
|
||||
// Implements nsILoadContext.originAttributes
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetOriginAttributes(JS::MutableHandle<JS::Value> aVal)
|
||||
@@ -14587,23 +14519,6 @@ nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
|
||||
return SetOriginAttributes(attrs);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetAppManifestURL(nsAString& aAppManifestURL)
|
||||
{
|
||||
uint32_t appId = nsIDocShell::GetAppId();
|
||||
if (appId != nsIScriptSecurityManager::NO_APP_ID &&
|
||||
appId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||
nsCOMPtr<nsIAppsService> appsService =
|
||||
do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
NS_ASSERTION(appsService, "No AppsService available");
|
||||
appsService->GetManifestURLByLocalId(appId, aAppManifestURL);
|
||||
} else {
|
||||
aAppManifestURL.SetLength(0);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetAsyncPanZoomEnabled(bool* aOut)
|
||||
{
|
||||
|
||||
@@ -786,8 +786,6 @@ protected:
|
||||
static const nsCString FrameTypeToString(uint32_t aFrameType)
|
||||
{
|
||||
switch (aFrameType) {
|
||||
case FRAME_TYPE_APP:
|
||||
return NS_LITERAL_CSTRING("app");
|
||||
case FRAME_TYPE_BROWSER:
|
||||
return NS_LITERAL_CSTRING("browser");
|
||||
case FRAME_TYPE_REGULAR:
|
||||
|
||||
@@ -827,109 +827,50 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
*/
|
||||
[noscript] void notifyScrollObservers();
|
||||
|
||||
/**
|
||||
* Returns true iff the docshell corresponds to an <iframe mozapp>.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isApp;
|
||||
|
||||
/**
|
||||
* The type of iframe that this docshell lives.
|
||||
*/
|
||||
const unsigned long FRAME_TYPE_REGULAR = 0;
|
||||
const unsigned long FRAME_TYPE_BROWSER = 1;
|
||||
const unsigned long FRAME_TYPE_APP = 2;
|
||||
|
||||
[infallible] attribute unsigned long frameType;
|
||||
|
||||
/**
|
||||
* Returns true if this docshell corresponds to an <iframe mozbrowser> or
|
||||
* <iframe mozapp>. <xul:browser> returns false here.
|
||||
* Returns true if this docshell corresponds to an <iframe mozbrowser>.
|
||||
* <xul:browser> returns false here.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isMozBrowserOrApp;
|
||||
[infallible] readonly attribute boolean isMozBrowser;
|
||||
|
||||
/**
|
||||
* Returns true if this docshell corresponds to an isolated <iframe
|
||||
* mozbrowser>.
|
||||
*
|
||||
* <iframe mozbrowser mozapp> and <xul:browser> are not considered to be
|
||||
* mozbrowser elements. <iframe mozbrowser noisolation> does not count as
|
||||
* isolated since isolation is disabled. Isolation can only be disabled if
|
||||
* the containing document is chrome.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isIsolatedMozBrowserElement;
|
||||
|
||||
/**
|
||||
* Returns true if this docshell corresponds to an isolated <iframe
|
||||
* mozbrowser> or if the docshell is contained in an isolated <iframe
|
||||
* mozbrowser>.
|
||||
*
|
||||
* <iframe mozbrowser mozapp> and <xul:browser> are not considered to be
|
||||
* mozbrowser elements. <iframe mozbrowser noisolation> does not count as
|
||||
* isolated since isolation is disabled. Isolation can only be disabled if
|
||||
* the containing document is chrome.
|
||||
*
|
||||
* Our notion here of "contained in" means: Walk up the docshell hierarchy in
|
||||
* this process until we hit an <iframe mozapp> or <iframe mozbrowser> (or
|
||||
* until the hierarchy ends). Return true iff the docshell we stopped on has
|
||||
* isIsolatedMozBrowserElement == true.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isInIsolatedMozBrowserElement;
|
||||
|
||||
/**
|
||||
* Returns true if this docshell corresponds to an <iframe mozbrowser> or
|
||||
* <iframe mozapp>, or if this docshell is contained in an <iframe mozbrowser>
|
||||
* or <iframe mozapp>. <xul:browser> returns false here.
|
||||
* Returns true if this docshell corresponds to an <iframe mozbrowser>, or
|
||||
* if this docshell is contained in an <iframe mozbrowser>. <xul:browser>
|
||||
* returns false here.
|
||||
*
|
||||
* To compute this value, we walk up the docshell hierarchy. If we encounter
|
||||
* a docshell with isMozBrowserOrApp before we hit the end of the hierarchy,
|
||||
* a docshell with isMozBrowser before we hit the end of the hierarchy,
|
||||
* we return true. Otherwise, we return false.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isInMozBrowserOrApp;
|
||||
[infallible] readonly attribute boolean isInMozBrowser;
|
||||
|
||||
/**
|
||||
* Returns true if this docshell is the top level content docshell.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isTopLevelContentDocShell;
|
||||
|
||||
/**
|
||||
* Returns the id of the app associated with this docshell. If this docshell
|
||||
* is an <iframe mozbrowser> inside an <iframe mozapp>, we return the app's
|
||||
* appId.
|
||||
*
|
||||
* We compute this value by walking up the docshell hierarchy until we find a
|
||||
* docshell on which origin attributes was set. (ignoring those docshells
|
||||
* where x == UNKNOWN_APP_ID). We return the app id x.
|
||||
*
|
||||
* If we don't find a docshell with an associated app id in our hierarchy, we
|
||||
* return NO_APP_ID. We never return UNKNOWN_APP_ID.
|
||||
*
|
||||
* Notice that a docshell may have an associated app even if it returns true
|
||||
* for isBrowserElement!
|
||||
*/
|
||||
[infallible] readonly attribute unsigned long appId;
|
||||
|
||||
/**
|
||||
* Return the manifest URL of the app associated with this docshell.
|
||||
*
|
||||
* If there is no associated app in our hierarchy, we return empty string.
|
||||
*/
|
||||
readonly attribute DOMString appManifestURL;
|
||||
|
||||
/**
|
||||
* Like nsIDocShellTreeItem::GetSameTypeParent, except this ignores <iframe
|
||||
* mozbrowser> and <iframe mozapp> boundaries.
|
||||
* mozbrowser> boundaries.
|
||||
*/
|
||||
nsIDocShell getSameTypeParentIgnoreBrowserAndAppBoundaries();
|
||||
nsIDocShell getSameTypeParentIgnoreBrowserBoundaries();
|
||||
|
||||
/**
|
||||
* Like nsIDocShellTreeItem::GetSameTypeRootTreeItem, except this ignores
|
||||
* <iframe mozbrowser> and <iframe mozapp> boundaries.
|
||||
* <iframe mozbrowser> boundaries.
|
||||
*/
|
||||
nsIDocShell getSameTypeRootTreeItemIgnoreBrowserAndAppBoundaries();
|
||||
nsIDocShell getSameTypeRootTreeItemIgnoreBrowserBoundaries();
|
||||
|
||||
/**
|
||||
* True iff asynchronous panning and zooming is enabled for this
|
||||
* docshell.
|
||||
* True if asynchronous panning and zooming is enabled for this docshell.
|
||||
*/
|
||||
readonly attribute bool asyncPanZoomEnabled;
|
||||
|
||||
|
||||
@@ -57,10 +57,9 @@ interface nsIDocShellTreeItem : nsISupports
|
||||
|
||||
/*
|
||||
This getter returns the same thing parent does however if the parent
|
||||
is of a different itemType, or if the parent is an <iframe mozbrowser>
|
||||
or <iframe mozapp>, it will instead return nullptr. This call is a
|
||||
convience function for those wishing to not cross the boundaries at
|
||||
which item types change.
|
||||
is of a different itemType, or if the parent is an <iframe mozbrowser>.
|
||||
It will instead return nullptr. This call is a convience function for
|
||||
Ithose wishing to not cross the boundaries at which item types change.
|
||||
*/
|
||||
readonly attribute nsIDocShellTreeItem sameTypeParent;
|
||||
|
||||
|
||||
@@ -104,21 +104,6 @@ interface nsILoadContext : nsISupports
|
||||
*/
|
||||
[noscript] void SetRemoteTabs(in boolean aUseRemoteTabs);
|
||||
|
||||
/**
|
||||
* Returns true iff the load is occurring inside an isolated mozbrowser
|
||||
* element. <iframe mozbrowser mozapp> and <xul:browser> are not considered to
|
||||
* be mozbrowser elements. <iframe mozbrowser noisolation> does not count as
|
||||
* isolated since isolation is disabled. Isolation can only be disabled if
|
||||
* the containing document is chrome.
|
||||
*/
|
||||
readonly attribute boolean isInIsolatedMozBrowserElement;
|
||||
|
||||
/**
|
||||
* Returns the app id of the app the load is occurring is in. Returns
|
||||
* nsIScriptSecurityManager::NO_APP_ID if the load is not part of an app.
|
||||
*/
|
||||
readonly attribute unsigned long appId;
|
||||
|
||||
/**
|
||||
* A dictionary of the non-default origin attributes associated with this
|
||||
* nsILoadContext.
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict"
|
||||
|
||||
function debug(s) {
|
||||
//dump("-*- AppsService.js: " + s + "\n");
|
||||
}
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
const APPS_SERVICE_CID = Components.ID("{05072afa-92fe-45bf-ae22-39b69c117058}");
|
||||
|
||||
function AppsService()
|
||||
{
|
||||
debug("AppsService Constructor");
|
||||
this.inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
|
||||
.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||
debug("inParent: " + this.inParent);
|
||||
if (!this.inParent) {
|
||||
Cu.import("resource://gre/modules/AppsServiceChild.jsm");
|
||||
}
|
||||
}
|
||||
|
||||
AppsService.prototype = {
|
||||
|
||||
isInvalidId: function(localId) {
|
||||
return (localId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
|
||||
localId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID);
|
||||
},
|
||||
|
||||
getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
|
||||
debug("GetAppByManifestURL( " + aManifestURL + " )");
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
getManifestFor: function getManifestFor(aManifestURL) {
|
||||
debug("getManifestFor(" + aManifestURL + ")");
|
||||
if (this.inParent) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
} else {
|
||||
return Promise.reject(
|
||||
new Error("Calling getManifestFor() from child is not supported"));
|
||||
}
|
||||
},
|
||||
|
||||
getAppLocalIdByManifestURL: function getAppLocalIdByManifestURL(aManifestURL) {
|
||||
debug("getAppLocalIdByManifestURL( " + aManifestURL + " )");
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
getAppLocalIdByStoreId: function getAppLocalIdByStoreId(aStoreId) {
|
||||
debug("getAppLocalIdByStoreId( " + aStoreId + " )");
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
getAppByLocalId: function getAppByLocalId(aLocalId) {
|
||||
debug("getAppByLocalId( " + aLocalId + " )");
|
||||
if (this.isInvalidId(aLocalId)) {
|
||||
return null;
|
||||
}
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
getManifestURLByLocalId: function getManifestURLByLocalId(aLocalId) {
|
||||
debug("getManifestURLByLocalId( " + aLocalId + " )");
|
||||
if (this.isInvalidId(aLocalId)) {
|
||||
return null;
|
||||
}
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
getCoreAppsBasePath: function getCoreAppsBasePath() {
|
||||
debug("getCoreAppsBasePath()");
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
getWebAppsBasePath: function getWebAppsBasePath() {
|
||||
debug("getWebAppsBasePath()");
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
areAnyAppsInstalled: function() {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
getAppInfo: function getAppInfo(aAppId) {
|
||||
debug("getAppInfo()");
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
getScopeByLocalId: function(aLocalId) {
|
||||
debug("getScopeByLocalId( " + aLocalId + " )");
|
||||
if (this.isInvalidId(aLocalId)) {
|
||||
return null;
|
||||
}
|
||||
// TODO : implement properly!
|
||||
// We just return null for now to not break PushService.jsm
|
||||
return null;
|
||||
},
|
||||
|
||||
classID : APPS_SERVICE_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIAppsService])
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AppsService])
|
||||
@@ -1,2 +0,0 @@
|
||||
component {05072afa-92fe-45bf-ae22-39b69c117058} AppsService.js
|
||||
contract @mozilla.org/AppsService;1 {05072afa-92fe-45bf-ae22-39b69c117058}
|
||||
@@ -1,408 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
// This module exposes a subset of the functionalities of the parent DOM
|
||||
// Registry to content processes, to be used from the AppsService component.
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DOMApplicationRegistry", "WrappedManifestCache"];
|
||||
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function debug(s) {
|
||||
//dump("-*- AppsServiceChild.jsm: " + s + "\n");
|
||||
}
|
||||
|
||||
const APPS_IPC_MSG_NAMES = [
|
||||
"Webapps:AddApp",
|
||||
"Webapps:RemoveApp",
|
||||
"Webapps:UpdateApp",
|
||||
"Webapps:CheckForUpdate:Return:KO",
|
||||
"Webapps:FireEvent",
|
||||
"Webapps:UpdateState"
|
||||
];
|
||||
|
||||
// A simple cache for the wrapped manifests.
|
||||
this.WrappedManifestCache = {
|
||||
_cache: { },
|
||||
|
||||
// Gets an entry from the cache, and populates the cache if needed.
|
||||
get: function mcache_get(aManifestURL, aManifest, aWindow, aInnerWindowID) {
|
||||
if (!aManifest) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(aManifestURL in this._cache)) {
|
||||
this._cache[aManifestURL] = { };
|
||||
}
|
||||
|
||||
let winObjs = this._cache[aManifestURL];
|
||||
if (!(aInnerWindowID in winObjs)) {
|
||||
winObjs[aInnerWindowID] = Cu.cloneInto(aManifest, aWindow);
|
||||
}
|
||||
|
||||
return winObjs[aInnerWindowID];
|
||||
},
|
||||
|
||||
// Invalidates an entry in the cache.
|
||||
evict: function mcache_evict(aManifestURL, aInnerWindowID) {
|
||||
debug("Evicting manifest " + aManifestURL + " window ID " +
|
||||
aInnerWindowID);
|
||||
if (aManifestURL in this._cache) {
|
||||
let winObjs = this._cache[aManifestURL];
|
||||
if (aInnerWindowID in winObjs) {
|
||||
delete winObjs[aInnerWindowID];
|
||||
}
|
||||
|
||||
if (Object.keys(winObjs).length == 0) {
|
||||
delete this._cache[aManifestURL];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
// Clear the cache on memory pressure.
|
||||
this._cache = { };
|
||||
Cu.forceGC();
|
||||
},
|
||||
|
||||
init: function() {
|
||||
Services.obs.addObserver(this, "memory-pressure", false);
|
||||
}
|
||||
};
|
||||
|
||||
this.WrappedManifestCache.init();
|
||||
|
||||
|
||||
// DOMApplicationRegistry keeps a cache containing a list of apps in the device.
|
||||
// This information is updated with the data received from the main process and
|
||||
// it is queried by the DOM objects to set their state.
|
||||
// This module handle all the messages broadcasted from the parent process,
|
||||
// including DOM events, which are dispatched to the corresponding DOM objects.
|
||||
|
||||
this.DOMApplicationRegistry = {
|
||||
// DOMApps will hold a list of arrays of weak references to
|
||||
// mozIDOMApplication objects indexed by manifest URL.
|
||||
DOMApps: {},
|
||||
|
||||
ready: false,
|
||||
webapps: null,
|
||||
|
||||
init: function init() {
|
||||
this.cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
|
||||
.getService(Ci.nsISyncMessageSender);
|
||||
|
||||
APPS_IPC_MSG_NAMES.forEach((function(aMsgName) {
|
||||
this.cpmm.addMessageListener(aMsgName, this);
|
||||
}).bind(this));
|
||||
|
||||
this.webapps = { };
|
||||
// We need a fast mapping from localId -> app, so we add an index.
|
||||
// We also add the manifest to the app object.
|
||||
this.localIdIndex = { };
|
||||
for (let id in this.webapps) {
|
||||
let app = this.webapps[id];
|
||||
this.localIdIndex[app.localId] = app;
|
||||
app.manifest = list.manifests[id];
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
// cpmm.addMessageListener causes the DOMApplicationRegistry object to
|
||||
// live forever if we don't clean up properly.
|
||||
this.webapps = null;
|
||||
this.DOMApps = null;
|
||||
|
||||
APPS_IPC_MSG_NAMES.forEach((aMsgName) => {
|
||||
this.cpmm.removeMessageListener(aMsgName, this);
|
||||
});
|
||||
},
|
||||
|
||||
receiveMessage: function receiveMessage(aMessage) {
|
||||
debug("Received " + aMessage.name + " message.");
|
||||
let msg = aMessage.data;
|
||||
switch (aMessage.name) {
|
||||
case "Webapps:AddApp":
|
||||
this.webapps[msg.id] = msg.app;
|
||||
this.localIdIndex[msg.app.localId] = msg.app;
|
||||
if (msg.manifest) {
|
||||
this.webapps[msg.id].manifest = msg.manifest;
|
||||
}
|
||||
break;
|
||||
case "Webapps:RemoveApp":
|
||||
delete this.DOMApps[this.webapps[msg.id].manifestURL];
|
||||
delete this.localIdIndex[this.webapps[msg.id].localId];
|
||||
delete this.webapps[msg.id];
|
||||
break;
|
||||
case "Webapps:UpdateApp":
|
||||
let app = this.webapps[msg.oldId];
|
||||
if (!app) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.app) {
|
||||
for (let prop in msg.app) {
|
||||
app[prop] = msg.app[prop];
|
||||
}
|
||||
}
|
||||
|
||||
this.webapps[msg.newId] = app;
|
||||
this.localIdIndex[app.localId] = app;
|
||||
delete this.webapps[msg.oldId];
|
||||
|
||||
let apps = this.DOMApps[msg.app.manifestURL];
|
||||
if (!apps) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < apps.length; i++) {
|
||||
let domApp = apps[i].get();
|
||||
if (!domApp || domApp._window === null) {
|
||||
apps.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
domApp._proxy = new Proxy(domApp, {
|
||||
get: function(target, prop) {
|
||||
if (!DOMApplicationRegistry.webapps[msg.newId]) {
|
||||
return;
|
||||
}
|
||||
return DOMApplicationRegistry.webapps[msg.newId][prop];
|
||||
},
|
||||
set: function(target, prop, val) {
|
||||
if (!DOMApplicationRegistry.webapps[msg.newId]) {
|
||||
return;
|
||||
}
|
||||
DOMApplicationRegistry.webapps[msg.newId][prop] = val;
|
||||
return;
|
||||
},
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "Webapps:FireEvent":
|
||||
this._fireEvent(aMessage);
|
||||
break;
|
||||
case "Webapps:UpdateState":
|
||||
this._updateState(msg);
|
||||
break;
|
||||
case "Webapps:CheckForUpdate:Return:KO":
|
||||
let DOMApps = this.DOMApps[msg.manifestURL];
|
||||
if (!DOMApps || !msg.requestID) {
|
||||
return;
|
||||
}
|
||||
DOMApps.forEach((DOMApp) => {
|
||||
let domApp = DOMApp.get();
|
||||
if (domApp && msg.requestID) {
|
||||
domApp._fireRequestResult(aMessage, true /* aIsError */);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* mozIDOMApplication management
|
||||
*/
|
||||
|
||||
// Every time a DOM app is created, we save a weak reference to it that will
|
||||
// be used to dispatch events and fire request results.
|
||||
addDOMApp: function(aApp, aManifestURL, aId) {
|
||||
let weakRef = Cu.getWeakReference(aApp);
|
||||
|
||||
if (!this.DOMApps[aManifestURL]) {
|
||||
this.DOMApps[aManifestURL] = [];
|
||||
}
|
||||
|
||||
let apps = this.DOMApps[aManifestURL];
|
||||
|
||||
// Get rid of dead weak references.
|
||||
for (let i = 0; i < apps.length; i++) {
|
||||
let app = apps[i].get();
|
||||
if (!app || app._window === null) {
|
||||
apps.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
apps.push(weakRef);
|
||||
|
||||
// Each DOM app contains a proxy object used to build their state. We
|
||||
// return the handler for this proxy object with traps to get and set
|
||||
// app properties kept in the DOMApplicationRegistry app cache.
|
||||
return {
|
||||
get: function(target, prop) {
|
||||
if (!DOMApplicationRegistry.webapps[aId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop in DOMApplicationRegistry.webapps[aId]) {
|
||||
return DOMApplicationRegistry.webapps[aId][prop];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
set: function(target, prop, val) {
|
||||
if (!DOMApplicationRegistry.webapps[aId]) {
|
||||
return;
|
||||
}
|
||||
DOMApplicationRegistry.webapps[aId][prop] = val;
|
||||
return;
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
_fireEvent: function(aMessage) {
|
||||
let msg = aMessage.data;
|
||||
debug("_fireEvent " + JSON.stringify(msg));
|
||||
if (!this.DOMApps || !msg.manifestURL || !msg.eventType) {
|
||||
return;
|
||||
}
|
||||
|
||||
let DOMApps = this.DOMApps[msg.manifestURL];
|
||||
if (!DOMApps) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The parent might ask childs to trigger more than one event in one
|
||||
// shot, so in order to avoid needless IPC we allow an array for the
|
||||
// 'eventType' IPC message field.
|
||||
if (!Array.isArray(msg.eventType)) {
|
||||
msg.eventType = [msg.eventType];
|
||||
}
|
||||
|
||||
DOMApps.forEach((DOMApp) => {
|
||||
let domApp = DOMApp.get();
|
||||
if (!domApp) {
|
||||
return;
|
||||
}
|
||||
msg.eventType.forEach((aEventType) => {
|
||||
if ('on' + aEventType in domApp) {
|
||||
domApp._fireEvent(aEventType);
|
||||
}
|
||||
});
|
||||
|
||||
if (msg.requestID) {
|
||||
aMessage.data.result = msg.manifestURL;
|
||||
domApp._fireRequestResult(aMessage);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_updateState: function(aMessage) {
|
||||
if (!this.DOMApps || !aMessage.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let app = this.webapps[aMessage.id];
|
||||
if (!app) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aMessage.app) {
|
||||
for (let prop in aMessage.app) {
|
||||
app[prop] = aMessage.app[prop];
|
||||
}
|
||||
}
|
||||
|
||||
if ("error" in aMessage) {
|
||||
app.downloadError = aMessage.error;
|
||||
}
|
||||
|
||||
if (aMessage.manifest) {
|
||||
app.manifest = aMessage.manifest;
|
||||
// Evict the wrapped manifest cache for all the affected DOM objects.
|
||||
let DOMApps = this.DOMApps[app.manifestURL];
|
||||
if (!DOMApps) {
|
||||
return;
|
||||
}
|
||||
DOMApps.forEach((DOMApp) => {
|
||||
let domApp = DOMApp.get();
|
||||
if (!domApp) {
|
||||
return;
|
||||
}
|
||||
WrappedManifestCache.evict(app.manifestURL, domApp.innerWindowID);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
getAll: function(aCallback) {
|
||||
debug("getAll()\n");
|
||||
if (!aCallback || typeof aCallback !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
let res = [];
|
||||
for (let id in this.webapps) {
|
||||
res.push(this.webapps[id]);
|
||||
}
|
||||
aCallback(res);
|
||||
},
|
||||
|
||||
getAdditionalLanguages: function(aManifestURL) {
|
||||
for (let id in this.webapps) {
|
||||
if (this.webapps[id].manifestURL == aManifestURL) {
|
||||
return this.webapps[id].additionalLanguages || {};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIAppsService API
|
||||
*/
|
||||
getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
|
||||
debug("getAppByManifestURL " + aManifestURL);
|
||||
return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);
|
||||
},
|
||||
|
||||
getAppLocalIdByManifestURL: function getAppLocalIdByManifestURL(aManifestURL) {
|
||||
debug("getAppLocalIdByManifestURL " + aManifestURL);
|
||||
return AppsUtils.getAppLocalIdByManifestURL(this.webapps, aManifestURL);
|
||||
},
|
||||
|
||||
getAppLocalIdByStoreId: function(aStoreId) {
|
||||
debug("getAppLocalIdByStoreId:" + aStoreId);
|
||||
return AppsUtils.getAppLocalIdByStoreId(this.webapps, aStoreId);
|
||||
},
|
||||
|
||||
getAppByLocalId: function getAppByLocalId(aLocalId) {
|
||||
debug("getAppByLocalId " + aLocalId + " - ready: " + this.ready);
|
||||
let app = this.localIdIndex[aLocalId];
|
||||
if (!app) {
|
||||
debug("Ouch, No app!");
|
||||
return null;
|
||||
}
|
||||
|
||||
return new mozIApplication(app);
|
||||
},
|
||||
|
||||
getManifestURLByLocalId: function getManifestURLByLocalId(aLocalId) {
|
||||
debug("getManifestURLByLocalId " + aLocalId);
|
||||
return AppsUtils.getManifestURLByLocalId(this.webapps, aLocalId);
|
||||
},
|
||||
|
||||
getCoreAppsBasePath: function getCoreAppsBasePath() {
|
||||
debug("getCoreAppsBasePath() not yet supported on child!");
|
||||
return null;
|
||||
},
|
||||
|
||||
getWebAppsBasePath: function getWebAppsBasePath() {
|
||||
debug("getWebAppsBasePath() not yet supported on child!");
|
||||
return null;
|
||||
},
|
||||
|
||||
areAnyAppsInstalled: function() {
|
||||
return AppsUtils.areAnyAppsInstalled(this.webapps);
|
||||
},
|
||||
|
||||
getAppInfo: function getAppInfo(aAppId) {
|
||||
return AppsUtils.getAppInfo(this.webapps, aAppId);
|
||||
}
|
||||
}
|
||||
|
||||
DOMApplicationRegistry.init();
|
||||
+2
-81
@@ -19,14 +19,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "appsService",
|
||||
"@mozilla.org/AppsService;1",
|
||||
"nsIAppsService");
|
||||
|
||||
// Shared code for AppsServiceChild.jsm, Webapps.jsm and Webapps.js
|
||||
// Shared code for Webapps.jsm and Webapps.js
|
||||
|
||||
this.EXPORTED_SYMBOLS =
|
||||
["AppsUtils", "ManifestHelper", "isAbsoluteURI", "mozIApplication"];
|
||||
["AppsUtils", "ManifestHelper", "isAbsoluteURI"];
|
||||
|
||||
function debug(s) {
|
||||
//dump("-*- AppsUtils.jsm: " + s + "\n");
|
||||
@@ -39,46 +35,6 @@ this.isAbsoluteURI = function(aURI) {
|
||||
Services.io.newURI(aURI, null, bar).prePath != bar.prePath;
|
||||
}
|
||||
|
||||
this.mozIApplication = function(aApp) {
|
||||
_setAppProperties(this, aApp);
|
||||
}
|
||||
|
||||
mozIApplication.prototype = {
|
||||
hasPermission: function(aPermission) {
|
||||
// This helper checks an URI inside |aApp|'s origin and part of |aApp| has a
|
||||
// specific permission. It is not checking if browsers inside |aApp| have such
|
||||
// permission.
|
||||
let perm = Services.perms.testExactPermissionFromPrincipal(this.principal,
|
||||
aPermission);
|
||||
return (perm === Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
},
|
||||
|
||||
get principal() {
|
||||
if (this._principal) {
|
||||
return this._principal;
|
||||
}
|
||||
|
||||
this._principal = null;
|
||||
|
||||
try {
|
||||
this._principal = Services.scriptSecurityManager.createCodebasePrincipal(
|
||||
Services.io.newURI(this.origin, null, null),
|
||||
{appId: this.localId});
|
||||
} catch(e) {
|
||||
dump("Could not create app principal " + e + "\n");
|
||||
}
|
||||
|
||||
return this._principal;
|
||||
},
|
||||
|
||||
QueryInterface: function(aIID) {
|
||||
if (aIID.equals(Ci.mozIApplication) ||
|
||||
aIID.equals(Ci.nsISupports))
|
||||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
function _setAppProperties(aObj, aApp) {
|
||||
aObj.name = aApp.name;
|
||||
aObj.csp = aApp.csp;
|
||||
@@ -217,21 +173,6 @@ this.AppsUtils = {
|
||||
return aPagePath.substr(pathPos, pathLen);
|
||||
},
|
||||
|
||||
getAppByManifestURL: function getAppByManifestURL(aApps, aManifestURL) {
|
||||
debug("getAppByManifestURL " + aManifestURL);
|
||||
// This could be O(1) if |webapps| was a dictionary indexed on manifestURL
|
||||
// which should be the unique app identifier.
|
||||
// It's currently O(n).
|
||||
for (let id in aApps) {
|
||||
let app = aApps[id];
|
||||
if (app.manifestURL == aManifestURL) {
|
||||
return new mozIApplication(app);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
getManifestFor: function getManifestFor(aManifestURL) {
|
||||
debug("getManifestFor(" + aManifestURL + ")");
|
||||
return DOMApplicationRegistry.getManifestFor(aManifestURL);
|
||||
@@ -259,18 +200,6 @@ this.AppsUtils = {
|
||||
return Ci.nsIScriptSecurityManager.NO_APP_ID;
|
||||
},
|
||||
|
||||
getAppByLocalId: function getAppByLocalId(aApps, aLocalId) {
|
||||
debug("getAppByLocalId " + aLocalId);
|
||||
for (let id in aApps) {
|
||||
let app = aApps[id];
|
||||
if (app.localId == aLocalId) {
|
||||
return new mozIApplication(app);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
getManifestURLByLocalId: function getManifestURLByLocalId(aApps, aLocalId) {
|
||||
debug("getManifestURLByLocalId " + aLocalId);
|
||||
for (let id in aApps) {
|
||||
@@ -697,14 +626,6 @@ this.AppsUtils = {
|
||||
return this.computeHash(JSON.stringify(aObject));
|
||||
},
|
||||
|
||||
getAppManifestURLFromWindow: function(aWindow) {
|
||||
let appId = aWindow.document.nodePrincipal.appId;
|
||||
if (appId === Ci.nsIScriptSecurityManager.NO_APP_ID) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return appsService.getManifestURLByLocalId(appId);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -233,11 +233,6 @@ this.PermissionsTable = { geolocation: {
|
||||
privileged: DENY_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
"embed-apps": {
|
||||
app: DENY_ACTION,
|
||||
privileged: DENY_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
"background-sensors": {
|
||||
app: DENY_ACTION,
|
||||
privileged: DENY_ACTION,
|
||||
|
||||
@@ -5,13 +5,7 @@
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'AppsService.js',
|
||||
'AppsService.manifest',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'AppsServiceChild.jsm',
|
||||
'AppsUtils.jsm',
|
||||
'PermissionsInstaller.jsm',
|
||||
'PermissionsTable.jsm',
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource:///modules/AppsUtils.jsm");
|
||||
|
||||
add_test(() => {
|
||||
let app = {
|
||||
name: "TestApp",
|
||||
csp: "aCsp",
|
||||
installOrigin: "http://installorigin.com",
|
||||
origin: "http://www.example.com",
|
||||
installTime: Date.now(),
|
||||
manifestURL: "http://www.example.com/manifest.webapp",
|
||||
appStatus: Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED,
|
||||
removable: false,
|
||||
id: 123,
|
||||
localId: 123,
|
||||
basePath: "/",
|
||||
progress: 1.0,
|
||||
installState: "installed",
|
||||
downloadAvailable: false,
|
||||
downloading: false,
|
||||
lastUpdateCheck: Date.now(),
|
||||
updateTime: Date.now(),
|
||||
etag: "aEtag",
|
||||
packageEtag: "aPackageEtag",
|
||||
manifestHash: "aManifestHash",
|
||||
packageHash: "aPackageHash",
|
||||
staged: false,
|
||||
installerAppId: 345,
|
||||
installerIsBrowser: false,
|
||||
storeId: "aStoreId",
|
||||
storeVersion: 1,
|
||||
role: "aRole",
|
||||
kind: "aKind",
|
||||
enabled: true,
|
||||
sideloaded: false
|
||||
};
|
||||
|
||||
let mozapp = new mozIApplication(app);
|
||||
|
||||
Object.keys(app).forEach((key) => {
|
||||
if (key == "principal") {
|
||||
return;
|
||||
}
|
||||
Assert.equal(app[key], mozapp[key],
|
||||
"app[" + key + "] should be equal to mozapp[" + key + "]");
|
||||
});
|
||||
|
||||
Assert.ok(mozapp.principal, "app principal should exist");
|
||||
let expectedPrincipalOrigin = app.origin + "^appId=" + app.localId;
|
||||
Assert.equal(mozapp.principal.origin, expectedPrincipalOrigin,
|
||||
"app principal origin ok");
|
||||
Assert.equal(mozapp.principal.appId, app.localId, "app principal appId ok");
|
||||
Assert.equal(mozapp.principal.isInIsolatedMozBrowserElement, false,
|
||||
"app principal isInIsolatedMozBrowserElement ok");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
@@ -2,4 +2,3 @@
|
||||
|
||||
[test_manifestSanitizer.js]
|
||||
[test_manifestHelper.js]
|
||||
[test_moziapplication.js]
|
||||
+40
-150
@@ -30,7 +30,6 @@
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIIPCBackgroundChildCreateCallback.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
@@ -443,11 +442,9 @@ public:
|
||||
mPrincipalInfo(aPrincipalInfo),
|
||||
mOpenMode(aOpenMode),
|
||||
mWriteParams(aWriteParams),
|
||||
mPersistence(quota::PERSISTENCE_TYPE_INVALID),
|
||||
mState(eInitial),
|
||||
mResult(JS::AsmJSCache_InternalError),
|
||||
mIsApp(false),
|
||||
mEnforcingQuota(true),
|
||||
mDeleteReceived(false),
|
||||
mActorDestroyed(false),
|
||||
mOpened(false)
|
||||
{
|
||||
@@ -488,31 +485,6 @@ private:
|
||||
MOZ_ASSERT(!IsOnOwningThread());
|
||||
}
|
||||
|
||||
// This method is called on the owning thread when no cache entry was found
|
||||
// to open. If we just tried a lookup in persistent storage then we might
|
||||
// still get a hit in temporary storage (for an asm.js module that wasn't
|
||||
// compiled at install-time).
|
||||
void
|
||||
CacheMiss()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState == eFailedToReadMetadata ||
|
||||
mState == eWaitingToOpenCacheFileForRead);
|
||||
MOZ_ASSERT(mOpenMode == eOpenForRead);
|
||||
|
||||
if (mPersistence == quota::PERSISTENCE_TYPE_TEMPORARY) {
|
||||
Fail();
|
||||
return;
|
||||
}
|
||||
|
||||
// Try again with a clean slate. InitOnMainThread will see that mPersistence
|
||||
// is initialized and switch to temporary storage.
|
||||
MOZ_ASSERT(mPersistence == quota::PERSISTENCE_TYPE_PERSISTENT);
|
||||
FinishOnOwningThread();
|
||||
mState = eInitial;
|
||||
NS_DispatchToMainThread(this);
|
||||
}
|
||||
|
||||
// This method is called on the owning thread when the JS engine is finished
|
||||
// reading/writing the cache entry.
|
||||
void
|
||||
@@ -542,7 +514,7 @@ private:
|
||||
|
||||
FinishOnOwningThread();
|
||||
|
||||
if (!mActorDestroyed) {
|
||||
if (!mDeleteReceived && !mActorDestroyed) {
|
||||
Unused << Send__delete__(this, mResult);
|
||||
}
|
||||
}
|
||||
@@ -561,9 +533,6 @@ private:
|
||||
MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(this, NS_DISPATCH_NORMAL));
|
||||
}
|
||||
|
||||
void
|
||||
InitPersistenceType();
|
||||
|
||||
nsresult
|
||||
InitOnMainThread();
|
||||
|
||||
@@ -615,6 +584,10 @@ private:
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState != eFinished);
|
||||
|
||||
MOZ_ASSERT(!mDeleteReceived);
|
||||
|
||||
mDeleteReceived = true;
|
||||
|
||||
if (mOpened) {
|
||||
Close();
|
||||
} else {
|
||||
@@ -666,23 +639,12 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
RecvCacheMiss() override
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
CacheMiss();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEventTarget> mOwningThread;
|
||||
const PrincipalInfo mPrincipalInfo;
|
||||
const OpenMode mOpenMode;
|
||||
const WriteParams mWriteParams;
|
||||
|
||||
// State initialized during eInitial:
|
||||
quota::PersistenceType mPersistence;
|
||||
nsCString mSuffix;
|
||||
nsCString mGroup;
|
||||
nsCString mOrigin;
|
||||
@@ -702,7 +664,6 @@ private:
|
||||
eWaitingToOpenDirectory, // Waiting to open directory
|
||||
eWaitingToOpenMetadata, // Waiting to be called back from OpenDirectory
|
||||
eReadyToReadMetadata, // Waiting to read the metadata file on the IO thread
|
||||
eFailedToReadMetadata, // Waiting to be dispatched to owning thread after fail
|
||||
eSendingMetadataForRead, // Waiting to send OnOpenMetadataForRead
|
||||
eWaitingToOpenCacheFileForRead, // Waiting to hear back from child
|
||||
eReadyToOpenCacheFileForRead, // Waiting to open cache file for read
|
||||
@@ -714,58 +675,11 @@ private:
|
||||
State mState;
|
||||
JS::AsmJSCacheResult mResult;
|
||||
|
||||
bool mIsApp;
|
||||
bool mEnforcingQuota;
|
||||
bool mDeleteReceived;
|
||||
bool mActorDestroyed;
|
||||
bool mOpened;
|
||||
};
|
||||
|
||||
void
|
||||
ParentRunnable::InitPersistenceType()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mState == eInitial);
|
||||
|
||||
if (mOpenMode == eOpenForWrite) {
|
||||
MOZ_ASSERT(mPersistence == quota::PERSISTENCE_TYPE_INVALID);
|
||||
|
||||
// If we are performing install-time caching of an app, we'd like to store
|
||||
// the cache entry in persistent storage so the entry is never evicted,
|
||||
// but we need to check that quota is not enforced for the app.
|
||||
// That justifies us in skipping all quota checks when storing the cache
|
||||
// entry and avoids all the issues around the persistent quota prompt.
|
||||
// If quota is enforced for the app, then we can still cache in temporary
|
||||
// for a likely good first-run experience.
|
||||
|
||||
MOZ_ASSERT_IF(mWriteParams.mInstalled, mIsApp);
|
||||
|
||||
if (mWriteParams.mInstalled &&
|
||||
!QuotaManager::IsQuotaEnforced(quota::PERSISTENCE_TYPE_PERSISTENT,
|
||||
mOrigin, mIsApp)) {
|
||||
mPersistence = quota::PERSISTENCE_TYPE_PERSISTENT;
|
||||
} else {
|
||||
mPersistence = quota::PERSISTENCE_TYPE_TEMPORARY;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// For the reasons described above, apps may have cache entries in both
|
||||
// persistent and temporary storage. At lookup time we don't know how and
|
||||
// where the given script was cached, so start the search in persistent
|
||||
// storage and, if that fails, search in temporary storage. (Non-apps can
|
||||
// only be stored in temporary storage.)
|
||||
|
||||
MOZ_ASSERT_IF(mPersistence != quota::PERSISTENCE_TYPE_INVALID,
|
||||
mIsApp && mPersistence == quota::PERSISTENCE_TYPE_PERSISTENT);
|
||||
|
||||
if (mPersistence == quota::PERSISTENCE_TYPE_INVALID && mIsApp) {
|
||||
mPersistence = quota::PERSISTENCE_TYPE_PERSISTENT;
|
||||
} else {
|
||||
mPersistence = quota::PERSISTENCE_TYPE_TEMPORARY;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
ParentRunnable::InitOnMainThread()
|
||||
{
|
||||
@@ -780,15 +694,9 @@ ParentRunnable::InitOnMainThread()
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = QuotaManager::GetInfoFromPrincipal(principal, &mSuffix, &mGroup,
|
||||
&mOrigin, &mIsApp);
|
||||
rv = QuotaManager::GetInfoFromPrincipal(principal, &mSuffix, &mGroup, &mOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
InitPersistenceType();
|
||||
|
||||
mEnforcingQuota =
|
||||
QuotaManager::IsQuotaEnforced(mPersistence, mOrigin, mIsApp);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -803,10 +711,9 @@ ParentRunnable::OpenDirectory()
|
||||
mState = eWaitingToOpenMetadata;
|
||||
|
||||
// XXX The exclusive lock shouldn't be needed for read operations.
|
||||
QuotaManager::Get()->OpenDirectory(mPersistence,
|
||||
QuotaManager::Get()->OpenDirectory(quota::PERSISTENCE_TYPE_TEMPORARY,
|
||||
mGroup,
|
||||
mOrigin,
|
||||
mIsApp,
|
||||
quota::Client::ASMJS,
|
||||
/* aExclusive */ true,
|
||||
this);
|
||||
@@ -822,8 +729,11 @@ ParentRunnable::ReadMetadata()
|
||||
MOZ_ASSERT(qm, "We are on the QuotaManager's IO thread");
|
||||
|
||||
nsresult rv =
|
||||
qm->EnsureOriginIsInitialized(mPersistence, mSuffix, mGroup, mOrigin,
|
||||
mIsApp, getter_AddRefs(mDirectory));
|
||||
qm->EnsureOriginIsInitialized(quota::PERSISTENCE_TYPE_TEMPORARY,
|
||||
mSuffix,
|
||||
mGroup,
|
||||
mOrigin,
|
||||
getter_AddRefs(mDirectory));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mResult = JS::AsmJSCache_StorageInitFailure;
|
||||
return rv;
|
||||
@@ -894,25 +804,23 @@ ParentRunnable::OpenCacheFileForWrite()
|
||||
QuotaManager* qm = QuotaManager::Get();
|
||||
MOZ_ASSERT(qm, "We are on the QuotaManager's IO thread");
|
||||
|
||||
if (mEnforcingQuota) {
|
||||
// Create the QuotaObject before all file IO and keep it alive until caching
|
||||
// completes to get maximum assertion coverage in QuotaManager against
|
||||
// concurrent removal, etc.
|
||||
mQuotaObject = qm->GetQuotaObject(mPersistence, mGroup, mOrigin, file);
|
||||
NS_ENSURE_STATE(mQuotaObject);
|
||||
// Create the QuotaObject before all file IO and keep it alive until caching
|
||||
// completes to get maximum assertion coverage in QuotaManager against
|
||||
// concurrent removal, etc.
|
||||
mQuotaObject = qm->GetQuotaObject(quota::PERSISTENCE_TYPE_TEMPORARY, mGroup, mOrigin, file);
|
||||
NS_ENSURE_STATE(mQuotaObject);
|
||||
|
||||
if (!mQuotaObject->MaybeUpdateSize(mWriteParams.mSize,
|
||||
/* aTruncate */ false)) {
|
||||
// If the request fails, it might be because mOrigin is using too much
|
||||
// space (MaybeUpdateSize will not evict our own origin since it is
|
||||
// active). Try to make some space by evicting LRU entries until there is
|
||||
// enough space.
|
||||
EvictEntries(mDirectory, mGroup, mOrigin, mWriteParams.mSize, mMetadata);
|
||||
if (!mQuotaObject->MaybeUpdateSize(mWriteParams.mSize,
|
||||
/* aTruncate */ false)) {
|
||||
// If the request fails, it might be because mOrigin is using too much
|
||||
// space (MaybeUpdateSize will not evict our own origin since it is
|
||||
// active). Try to make some space by evicting LRU entries until there is
|
||||
// enough space.
|
||||
EvictEntries(mDirectory, mGroup, mOrigin, mWriteParams.mSize, mMetadata);
|
||||
if (!mQuotaObject->MaybeUpdateSize(mWriteParams.mSize,
|
||||
/* aTruncate */ false)) {
|
||||
mResult = JS::AsmJSCache_QuotaExceeded;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mResult = JS::AsmJSCache_QuotaExceeded;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -948,13 +856,11 @@ ParentRunnable::OpenCacheFileForRead()
|
||||
QuotaManager* qm = QuotaManager::Get();
|
||||
MOZ_ASSERT(qm, "We are on the QuotaManager's IO thread");
|
||||
|
||||
if (mEnforcingQuota) {
|
||||
// Even though it's not strictly necessary, create the QuotaObject before
|
||||
// all file IO and keep it alive until caching completes to get maximum
|
||||
// assertion coverage in QuotaManager against concurrent removal, etc.
|
||||
mQuotaObject = qm->GetQuotaObject(mPersistence, mGroup, mOrigin, file);
|
||||
NS_ENSURE_STATE(mQuotaObject);
|
||||
}
|
||||
// Even though it's not strictly necessary, create the QuotaObject before
|
||||
// all file IO and keep it alive until caching completes to get maximum
|
||||
// assertion coverage in QuotaManager against concurrent removal, etc.
|
||||
mQuotaObject = qm->GetQuotaObject(quota::PERSISTENCE_TYPE_TEMPORARY, mGroup, mOrigin, file);
|
||||
NS_ENSURE_STATE(mQuotaObject);
|
||||
|
||||
rv = file->GetFileSize(&mFileSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@@ -1058,8 +964,7 @@ ParentRunnable::Run()
|
||||
|
||||
rv = ReadMetadata();
|
||||
if (NS_FAILED(rv)) {
|
||||
mState = eFailedToReadMetadata;
|
||||
MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(this, NS_DISPATCH_NORMAL));
|
||||
FailOnNonOwningThread();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1081,18 +986,6 @@ ParentRunnable::Run()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case eFailedToReadMetadata: {
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (mOpenMode == eOpenForRead) {
|
||||
CacheMiss();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Fail();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case eSendingMetadataForRead: {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mOpenMode == eOpenForRead);
|
||||
@@ -1404,11 +1297,13 @@ private:
|
||||
MOZ_ASSERT(mState == eOpening);
|
||||
|
||||
uint32_t moduleIndex;
|
||||
if (FindHashMatch(aMetadata, mReadParams, &moduleIndex)) {
|
||||
return SendSelectCacheFileToRead(moduleIndex);
|
||||
if (!FindHashMatch(aMetadata, mReadParams, &moduleIndex)) {
|
||||
Fail(JS::AsmJSCache_InternalError);
|
||||
Send__delete__(this, JS::AsmJSCache_InternalError);
|
||||
return true;
|
||||
}
|
||||
|
||||
return SendCacheMiss();
|
||||
return SendSelectCacheFileToRead(moduleIndex);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1760,7 +1655,6 @@ CloseEntryForRead(size_t aSize,
|
||||
|
||||
JS::AsmJSCacheResult
|
||||
OpenEntryForWrite(nsIPrincipal* aPrincipal,
|
||||
bool aInstalled,
|
||||
const char16_t* aBegin,
|
||||
const char16_t* aEnd,
|
||||
size_t aSize,
|
||||
@@ -1777,7 +1671,6 @@ OpenEntryForWrite(nsIPrincipal* aPrincipal,
|
||||
static_assert(sNumFastHashChars < sMinCachedModuleLength, "HashString safe");
|
||||
|
||||
WriteParams writeParams;
|
||||
writeParams.mInstalled = aInstalled;
|
||||
writeParams.mSize = aSize;
|
||||
writeParams.mFastHash = HashString(aBegin, sNumFastHashChars);
|
||||
writeParams.mNumChars = aEnd - aBegin;
|
||||
@@ -2043,7 +1936,6 @@ ParamTraits<WriteParams>::Write(Message* aMsg, const paramType& aParam)
|
||||
WriteParam(aMsg, aParam.mFastHash);
|
||||
WriteParam(aMsg, aParam.mNumChars);
|
||||
WriteParam(aMsg, aParam.mFullHash);
|
||||
WriteParam(aMsg, aParam.mInstalled);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -2053,8 +1945,7 @@ ParamTraits<WriteParams>::Read(const Message* aMsg, PickleIterator* aIter,
|
||||
return ReadParam(aMsg, aIter, &aResult->mSize) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFastHash) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mNumChars) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFullHash) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mInstalled);
|
||||
ReadParam(aMsg, aIter, &aResult->mFullHash);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2064,7 +1955,6 @@ ParamTraits<WriteParams>::Log(const paramType& aParam, std::wstring* aLog)
|
||||
LogParam(aParam.mFastHash, aLog);
|
||||
LogParam(aParam.mNumChars, aLog);
|
||||
LogParam(aParam.mFullHash, aLog);
|
||||
LogParam(aParam.mInstalled, aLog);
|
||||
}
|
||||
|
||||
} // namespace IPC
|
||||
@@ -72,14 +72,12 @@ struct WriteParams
|
||||
int64_t mFastHash;
|
||||
int64_t mNumChars;
|
||||
int64_t mFullHash;
|
||||
bool mInstalled;
|
||||
|
||||
WriteParams()
|
||||
: mSize(0),
|
||||
mFastHash(0),
|
||||
mNumChars(0),
|
||||
mFullHash(0),
|
||||
mInstalled(false)
|
||||
: mSize(0)
|
||||
, mFastHash(0)
|
||||
, mNumChars(0)
|
||||
, mFullHash(0)
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -90,8 +88,8 @@ struct ReadParams
|
||||
const char16_t* mLimit;
|
||||
|
||||
ReadParams()
|
||||
: mBegin(nullptr),
|
||||
mLimit(nullptr)
|
||||
: mBegin(nullptr)
|
||||
, mLimit(nullptr)
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -120,7 +118,6 @@ CloseEntryForRead(size_t aSize,
|
||||
intptr_t aHandle);
|
||||
JS::AsmJSCacheResult
|
||||
OpenEntryForWrite(nsIPrincipal* aPrincipal,
|
||||
bool aInstalled,
|
||||
const char16_t* aBegin,
|
||||
const char16_t* aEnd,
|
||||
size_t aSize,
|
||||
|
||||
@@ -22,7 +22,6 @@ child:
|
||||
async OnOpenMetadataForRead(Metadata metadata);
|
||||
parent:
|
||||
async SelectCacheFileToRead(uint32_t moduleIndex);
|
||||
async CacheMiss();
|
||||
|
||||
child:
|
||||
// Once the cache file has been opened, the child is notified and sent an
|
||||
|
||||
@@ -340,7 +340,7 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time
|
||||
|
||||
nsMargin rootMargin;
|
||||
NS_FOR_CSS_SIDES(side) {
|
||||
nscoord basis = side == NS_SIDE_TOP || side == NS_SIDE_BOTTOM ?
|
||||
nscoord basis = side == eSideTop || side == eSideBottom ?
|
||||
rootRect.height : rootRect.width;
|
||||
nsCSSValue value = mRootMargin.*nsCSSRect::sides[side];
|
||||
nsStyleCoord coord;
|
||||
|
||||
@@ -129,17 +129,12 @@ DOMMatrixReadOnly::SetDataFromMatrix2DInit(const DOMMatrix2DInit& aMatrixInit) {
|
||||
}
|
||||
|
||||
void
|
||||
DOMMatrixReadOnly::SetDataFromMatrixInit(DOMMatrixInit& aMatrixInit)
|
||||
DOMMatrixReadOnly::SetDataFromMatrixInit(const DOMMatrixInit& aMatrixInit)
|
||||
{
|
||||
const bool is2D = aMatrixInit.mIs2D.Value();
|
||||
MOZ_ASSERT(is2D == Is2D());
|
||||
if (is2D) {
|
||||
mMatrix2D->_11 = aMatrixInit.mM11.Value();
|
||||
mMatrix2D->_12 = aMatrixInit.mM12.Value();
|
||||
mMatrix2D->_21 = aMatrixInit.mM21.Value();
|
||||
mMatrix2D->_22 = aMatrixInit.mM22.Value();
|
||||
mMatrix2D->_31 = aMatrixInit.mM41.Value();
|
||||
mMatrix2D->_32 = aMatrixInit.mM42.Value();
|
||||
SetDataFromMatrix2DInit(aMatrixInit);
|
||||
} else {
|
||||
mMatrix3D->_11 = aMatrixInit.mM11.Value();
|
||||
mMatrix3D->_12 = aMatrixInit.mM12.Value();
|
||||
|
||||
+10
-1
@@ -52,6 +52,11 @@ public:
|
||||
mMatrix3D = new gfx::Matrix4x4(aMatrix);
|
||||
}
|
||||
|
||||
DOMMatrixReadOnly(nsISupports* aParent, const gfx::Matrix& aMatrix)
|
||||
: mParent(aParent) {
|
||||
mMatrix2D = new gfx::Matrix(aMatrix);
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DOMMatrixReadOnly)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(DOMMatrixReadOnly)
|
||||
|
||||
@@ -234,7 +239,7 @@ protected:
|
||||
* The init dictionary's dimension must match the matrix one.
|
||||
*/
|
||||
void SetDataFromMatrix2DInit(const DOMMatrix2DInit& aMatrixInit);
|
||||
void SetDataFromMatrixInit(DOMMatrixInit& aMatrixInit);
|
||||
void SetDataFromMatrixInit(const DOMMatrixInit& aMatrixInit);
|
||||
|
||||
DOMMatrixReadOnly* SetMatrixValue(const nsAString& aTransformList, ErrorResult& aRv);
|
||||
void Ensure3DMatrix();
|
||||
@@ -268,6 +273,10 @@ public:
|
||||
: DOMMatrixReadOnly(aParent, aMatrix)
|
||||
{}
|
||||
|
||||
DOMMatrix(nsISupports* aParent, const gfx::Matrix& aMatrix)
|
||||
: DOMMatrixReadOnly(aParent, aMatrix)
|
||||
{}
|
||||
|
||||
static already_AddRefed<DOMMatrix>
|
||||
FromMatrix(nsISupports* aParent, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv);
|
||||
static already_AddRefed<DOMMatrix>
|
||||
|
||||
@@ -64,8 +64,6 @@
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "TimeManager.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "mozIApplication.h"
|
||||
#include "WidgetUtils.h"
|
||||
#include "mozilla/dom/MediaDevices.h"
|
||||
#include "MediaManager.h"
|
||||
@@ -1519,5 +1517,13 @@ Navigator::Clipboard()
|
||||
return mClipboard;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
Navigator::Webdriver()
|
||||
{
|
||||
// We don't support Selenium or marionette, so this is always false.
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -220,6 +220,8 @@ public:
|
||||
|
||||
dom::Clipboard* Clipboard();
|
||||
|
||||
static bool Webdriver();
|
||||
|
||||
void GetLanguages(nsTArray<nsString>& aLanguages);
|
||||
|
||||
StorageManager* Storage();
|
||||
|
||||
@@ -32,16 +32,14 @@ PostMessageEvent::PostMessageEvent(nsGlobalWindow* aSource,
|
||||
const nsAString& aCallerOrigin,
|
||||
nsGlobalWindow* aTargetWindow,
|
||||
nsIPrincipal* aProvidedPrincipal,
|
||||
nsIDocument* aSourceDocument,
|
||||
bool aTrustedCaller)
|
||||
: StructuredCloneHolder(CloningSupported, TransferringSupported,
|
||||
StructuredCloneScope::SameProcessSameThread),
|
||||
mSource(aSource),
|
||||
mCallerOrigin(aCallerOrigin),
|
||||
mTargetWindow(aTargetWindow),
|
||||
mProvidedPrincipal(aProvidedPrincipal),
|
||||
mSourceDocument(aSourceDocument),
|
||||
mTrustedCaller(aTrustedCaller)
|
||||
nsIDocument* aSourceDocument)
|
||||
: StructuredCloneHolder(CloningSupported, TransferringSupported,
|
||||
StructuredCloneScope::SameProcessSameThread)
|
||||
, mSource(aSource)
|
||||
, mCallerOrigin(aCallerOrigin)
|
||||
, mTargetWindow(aTargetWindow)
|
||||
, mProvidedPrincipal(aProvidedPrincipal)
|
||||
, mSourceDocument(aSourceDocument)
|
||||
{
|
||||
MOZ_COUNT_CTOR(PostMessageEvent);
|
||||
}
|
||||
@@ -169,7 +167,7 @@ PostMessageEvent::Run()
|
||||
if (shell)
|
||||
presContext = shell->GetPresContext();
|
||||
|
||||
event->SetTrusted(mTrustedCaller);
|
||||
event->SetTrusted(true);
|
||||
WidgetEvent* internalEvent = event->WidgetEventPtr();
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
|
||||
@@ -33,8 +33,7 @@ public:
|
||||
const nsAString& aCallerOrigin,
|
||||
nsGlobalWindow* aTargetWindow,
|
||||
nsIPrincipal* aProvidedPrincipal,
|
||||
nsIDocument* aSourceDocument,
|
||||
bool aTrustedCaller);
|
||||
nsIDocument* aSourceDocument);
|
||||
|
||||
private:
|
||||
~PostMessageEvent();
|
||||
@@ -44,7 +43,6 @@ private:
|
||||
RefPtr<nsGlobalWindow> mTargetWindow;
|
||||
nsCOMPtr<nsIPrincipal> mProvidedPrincipal;
|
||||
nsCOMPtr<nsIDocument> mSourceDocument;
|
||||
bool mTrustedCaller;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "nsIURI.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(ThirdPartyUtil, mozIThirdPartyUtil)
|
||||
|
||||
@@ -145,7 +146,7 @@ ThirdPartyUtil::IsThirdPartyWindow(mozIDOMWindowProxy* aWindow,
|
||||
nsCOMPtr<nsIURI> parentURI;
|
||||
do {
|
||||
// We use GetScriptableParent rather than GetParent because we consider
|
||||
// <iframe mozbrowser/mozapp> to be a top-level frame.
|
||||
// <iframe mozbrowser> to be a top-level frame.
|
||||
parent = current->GetScriptableParent();
|
||||
if (SameCOMIdentity(parent, current)) {
|
||||
// We're at the topmost content window. We already know the answer.
|
||||
|
||||
@@ -1598,12 +1598,12 @@ nsAttrValue::ParsePositiveIntValue(const nsAString& aString)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsAttrValue::SetColorValue(nscolor aColor, const nsAString& aString)
|
||||
{
|
||||
nsStringBuffer* buf = GetStringBuffer(aString).take();
|
||||
if (!buf) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
MiscContainer* cont = EnsureEmptyMiscContainer();
|
||||
@@ -1612,6 +1612,7 @@ nsAttrValue::SetColorValue(nscolor aColor, const nsAString& aString)
|
||||
|
||||
// Save the literal string we were passed for round-tripping.
|
||||
cont->mStringBits = reinterpret_cast<uintptr_t>(buf) | eStringBase;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1635,13 +1636,11 @@ nsAttrValue::ParseColor(const nsAString& aString)
|
||||
if (colorStr.First() == '#') {
|
||||
nsDependentString withoutHash(colorStr.get() + 1, colorStr.Length() - 1);
|
||||
if (NS_HexToRGBA(withoutHash, nsHexColorType::NoAlpha, &color)) {
|
||||
SetColorValue(color, aString);
|
||||
return true;
|
||||
return SetColorValue(color, aString);
|
||||
}
|
||||
} else {
|
||||
if (NS_ColorNameToRGB(colorStr, &color)) {
|
||||
SetColorValue(color, aString);
|
||||
return true;
|
||||
return SetColorValue(color, aString);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1652,8 +1651,7 @@ nsAttrValue::ParseColor(const nsAString& aString)
|
||||
|
||||
// Use NS_LooseHexToRGB as a fallback if nothing above worked.
|
||||
if (NS_LooseHexToRGB(colorStr, &color)) {
|
||||
SetColorValue(color, aString);
|
||||
return true;
|
||||
return SetColorValue(color, aString);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -463,7 +463,7 @@ private:
|
||||
inline void SetPtrValueAndType(void* aValue, ValueBaseType aType);
|
||||
void SetIntValueAndType(int32_t aValue, ValueType aType,
|
||||
const nsAString* aStringValue);
|
||||
void SetColorValue(nscolor aColor, const nsAString& aString);
|
||||
bool SetColorValue(nscolor aColor, const nsAString& aString);
|
||||
void SetMiscAtomOrString(const nsAString* aValue);
|
||||
void ResetMiscAtomOrString();
|
||||
void SetSVGType(ValueType aType, const void* aValue,
|
||||
|
||||
@@ -472,6 +472,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
|
||||
nsAutoString media;
|
||||
nsAutoString anchor;
|
||||
nsAutoString crossOrigin;
|
||||
nsAutoString referrerPolicy;
|
||||
nsAutoString destination;
|
||||
|
||||
crossOrigin.SetIsVoid(true);
|
||||
@@ -660,6 +661,15 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
|
||||
destination = value;
|
||||
destination.StripWhitespace();
|
||||
}
|
||||
} else if (attr.LowerCaseEqualsLiteral("referrerpolicy")) {
|
||||
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#referrer-policy-attribute
|
||||
// The spec says that the referrer policy attribute is an enumerated attribute,
|
||||
// case insensitive and includes the empty string.
|
||||
// We will parse the value with AttributeReferrerPolicyFromString
|
||||
// later, which will handle parsing it as an enumerated attribute.
|
||||
if (referrerPolicy.IsEmpty()) {
|
||||
referrerPolicy = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -673,7 +683,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
|
||||
rv = ProcessLink(anchor, href, rel,
|
||||
// prefer RFC 5987 variant over non-I18zed version
|
||||
titleStar.IsEmpty() ? title : titleStar,
|
||||
type, media, crossOrigin, destination);
|
||||
type, media, crossOrigin, referrerPolicy, destination);
|
||||
}
|
||||
|
||||
href.Truncate();
|
||||
@@ -682,6 +692,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
|
||||
type.Truncate();
|
||||
media.Truncate();
|
||||
anchor.Truncate();
|
||||
referrerPolicy.Truncate();
|
||||
crossOrigin.SetIsVoid(true);
|
||||
destination.Truncate();
|
||||
|
||||
@@ -696,7 +707,7 @@ nsContentSink::ProcessLinkHeader(const nsAString& aLinkData)
|
||||
rv = ProcessLink(anchor, href, rel,
|
||||
// prefer RFC 5987 variant over non-I18zed version
|
||||
titleStar.IsEmpty() ? title : titleStar,
|
||||
type, media, crossOrigin, destination);
|
||||
type, media, crossOrigin, referrerPolicy, destination);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@@ -708,6 +719,7 @@ nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
|
||||
const nsSubstring& aRel, const nsSubstring& aTitle,
|
||||
const nsSubstring& aType, const nsSubstring& aMedia,
|
||||
const nsSubstring& aCrossOrigin,
|
||||
const nsAString& aReferrerPolicy,
|
||||
const nsSubstring& aDestination)
|
||||
{
|
||||
uint32_t linkTypes =
|
||||
@@ -749,7 +761,7 @@ nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
|
||||
|
||||
bool isAlternate = linkTypes & nsStyleLinkElement::eALTERNATE;
|
||||
return ProcessStyleLink(nullptr, aHref, isAlternate, aTitle, aType,
|
||||
aMedia);
|
||||
aMedia, aReferrerPolicy);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@@ -758,7 +770,8 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement,
|
||||
bool aAlternate,
|
||||
const nsSubstring& aTitle,
|
||||
const nsSubstring& aType,
|
||||
const nsSubstring& aMedia)
|
||||
const nsSubstring& aMedia,
|
||||
const nsSubstring& aReferrerPolicy)
|
||||
{
|
||||
if (aAlternate && aTitle.IsEmpty()) {
|
||||
// alternates must have title return without error, for now
|
||||
@@ -797,13 +810,18 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement,
|
||||
("nsContentSink::ProcessStyleLink, integrity=%s",
|
||||
NS_ConvertUTF16toUTF8(integrity).get()));
|
||||
}
|
||||
mozilla::net::ReferrerPolicy referrerPolicy =
|
||||
mozilla::net::AttributeReferrerPolicyFromString(aReferrerPolicy);
|
||||
if (referrerPolicy == net::RP_Unset) {
|
||||
referrerPolicy = mDocument->GetReferrerPolicy();
|
||||
}
|
||||
|
||||
// If this is a fragment parser, we don't want to observe.
|
||||
// We don't support CORS for processing instructions
|
||||
bool isAlternate;
|
||||
bool isExplicitlyEnabled;
|
||||
rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate,
|
||||
CORS_NONE, mDocument->GetReferrerPolicy(),
|
||||
CORS_NONE, referrerPolicy,
|
||||
integrity, mRunsToCompletion ? nullptr : this,
|
||||
&isAlternate, &isExplicitlyEnabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@@ -154,6 +154,7 @@ protected:
|
||||
const nsSubstring& aHref, const nsSubstring& aRel,
|
||||
const nsSubstring& aTitle, const nsSubstring& aType,
|
||||
const nsSubstring& aMedia, const nsSubstring& aCrossOrigin,
|
||||
const nsSubstring& aReferrerPolicy,
|
||||
const nsSubstring& aDestination);
|
||||
|
||||
virtual nsresult ProcessStyleLink(nsIContent* aElement,
|
||||
@@ -161,7 +162,8 @@ protected:
|
||||
bool aAlternate,
|
||||
const nsSubstring& aTitle,
|
||||
const nsSubstring& aType,
|
||||
const nsSubstring& aMedia);
|
||||
const nsSubstring& aMedia,
|
||||
const nsSubstring& aReferrerPolicy);
|
||||
|
||||
void PrefetchOrPreloadHref(const nsAString &aHref,
|
||||
nsINode *aSource,
|
||||
|
||||
@@ -6616,7 +6616,7 @@ nsContentUtils::IsUserFocusIgnored(nsINode* aNode)
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(aNode);
|
||||
if (browserFrame &&
|
||||
aNode->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::ignoreuserfocus) &&
|
||||
browserFrame->GetReallyIsBrowserOrApp()) {
|
||||
browserFrame->GetReallyIsBrowser()) {
|
||||
return true;
|
||||
}
|
||||
nsPIDOMWindowOuter* win = aNode->OwnerDoc()->GetWindow();
|
||||
@@ -8868,10 +8868,8 @@ nsContentUtils::SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal,
|
||||
referrerURI = principalURI;
|
||||
}
|
||||
|
||||
net::ReferrerPolicy referrerPolicy = aReferrerPolicy;
|
||||
if (referrerPolicy == net::RP_Default) {
|
||||
referrerPolicy = aDoc->GetReferrerPolicy();
|
||||
}
|
||||
net::ReferrerPolicy referrerPolicy = (aReferrerPolicy != net::RP_Unset) ?
|
||||
aReferrerPolicy : net::RP_Default;
|
||||
return aChannel->SetReferrerWithPolicy(referrerURI, referrerPolicy);
|
||||
}
|
||||
|
||||
|
||||
@@ -3026,8 +3026,7 @@ nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName, int64_t aId,
|
||||
|
||||
nsCString origin;
|
||||
nsresult rv =
|
||||
quota::QuotaManager::GetInfoFromWindow(window, nullptr, nullptr, &origin,
|
||||
nullptr);
|
||||
quota::QuotaManager::GetInfoFromWindow(window, nullptr, nullptr, &origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
IDBOpenDBOptions options;
|
||||
|
||||
@@ -2802,20 +2802,9 @@ nsDocument::GetPrincipal()
|
||||
return NodePrincipal();
|
||||
}
|
||||
|
||||
extern bool sDisablePrefetchHTTPSPref;
|
||||
|
||||
void
|
||||
nsDocument::SetPrincipal(nsIPrincipal *aNewPrincipal)
|
||||
{
|
||||
if (aNewPrincipal && mAllowDNSPrefetch && sDisablePrefetchHTTPSPref) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aNewPrincipal->GetURI(getter_AddRefs(uri));
|
||||
bool isHTTPS;
|
||||
if (!uri || NS_FAILED(uri->SchemeIs("https", &isHTTPS)) ||
|
||||
isHTTPS) {
|
||||
mAllowDNSPrefetch = false;
|
||||
}
|
||||
}
|
||||
mNodeInfoManager->SetDocumentPrincipal(aNewPrincipal);
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -7250,11 +7239,6 @@ nsDocument::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
aVisitor.mCanHandle = true;
|
||||
// Middle/right click shouldn't dispatch click event, use auxclick to instead.
|
||||
Element* docElement = GetRootElement();
|
||||
if (docElement && docElement->IsXULElement()) {
|
||||
// FIXME! This is a hack to make middle mouse paste working also in Editor.
|
||||
// Bug 329119
|
||||
aVisitor.mForceContentDispatch = true;
|
||||
}
|
||||
|
||||
// Load events must not propagate to |window| object, see bug 335251.
|
||||
if (aVisitor.mEvent->mMessage != eLoad) {
|
||||
|
||||
+23
-164
@@ -12,9 +12,7 @@
|
||||
|
||||
#include "prenv.h"
|
||||
|
||||
#include "mozIApplication.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "nsIDOMHTMLIFrameElement.h"
|
||||
#include "nsIDOMHTMLFrameElement.h"
|
||||
#include "nsIDOMMozBrowserFrame.h"
|
||||
@@ -90,7 +88,6 @@
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
||||
#include "mozilla/layout/RenderFrameParent.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
@@ -1071,12 +1068,6 @@ nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (mRemoteBrowser->IsIsolatedMozBrowserElement() !=
|
||||
aOther->mRemoteBrowser->IsIsolatedMozBrowserElement() ||
|
||||
mRemoteBrowser->HasOwnApp() != aOther->mRemoteBrowser->HasOwnApp()) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// When we swap docShells, maybe we have to deal with a new page created just
|
||||
// for this operation. In this case, the browser code should already have set
|
||||
// the correct userContextId attribute value in the owning XULElement, but our
|
||||
@@ -1145,10 +1136,10 @@ nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
|
||||
}
|
||||
|
||||
// Destroy browser frame scripts for content leaving a frame with browser API
|
||||
if (OwnerIsMozBrowserOrAppFrame() && !aOther->OwnerIsMozBrowserOrAppFrame()) {
|
||||
if (OwnerIsMozBrowserFrame() && !aOther->OwnerIsMozBrowserFrame()) {
|
||||
DestroyBrowserFrameScripts();
|
||||
}
|
||||
if (!OwnerIsMozBrowserOrAppFrame() && aOther->OwnerIsMozBrowserOrAppFrame()) {
|
||||
if (!OwnerIsMozBrowserFrame() && aOther->OwnerIsMozBrowserFrame()) {
|
||||
aOther->DestroyBrowserFrameScripts();
|
||||
}
|
||||
|
||||
@@ -1322,12 +1313,12 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
|
||||
bool ourFullscreenAllowed =
|
||||
ourContent->IsXULElement() ||
|
||||
(OwnerIsMozBrowserOrAppFrame() &&
|
||||
(OwnerIsMozBrowserFrame() &&
|
||||
(ourContent->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
|
||||
ourContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)));
|
||||
bool otherFullscreenAllowed =
|
||||
otherContent->IsXULElement() ||
|
||||
(aOther->OwnerIsMozBrowserOrAppFrame() &&
|
||||
(aOther->OwnerIsMozBrowserFrame() &&
|
||||
(otherContent->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
|
||||
otherContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)));
|
||||
if (ourFullscreenAllowed != otherFullscreenAllowed) {
|
||||
@@ -1472,12 +1463,6 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (ourDocshell->GetIsIsolatedMozBrowserElement() !=
|
||||
otherDocshell->GetIsIsolatedMozBrowserElement() ||
|
||||
ourDocshell->GetIsApp() != otherDocshell->GetIsApp()) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// When we swap docShells, maybe we have to deal with a new page created just
|
||||
// for this operation. In this case, the browser code should already have set
|
||||
// the correct userContextId attribute value in the owning XULElement, but our
|
||||
@@ -1524,10 +1509,10 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
}
|
||||
|
||||
// Destroy browser frame scripts for content leaving a frame with browser API
|
||||
if (OwnerIsMozBrowserOrAppFrame() && !aOther->OwnerIsMozBrowserOrAppFrame()) {
|
||||
if (OwnerIsMozBrowserFrame() && !aOther->OwnerIsMozBrowserFrame()) {
|
||||
DestroyBrowserFrameScripts();
|
||||
}
|
||||
if (!OwnerIsMozBrowserOrAppFrame() && aOther->OwnerIsMozBrowserOrAppFrame()) {
|
||||
if (!OwnerIsMozBrowserFrame() && aOther->OwnerIsMozBrowserFrame()) {
|
||||
aOther->DestroyBrowserFrameScripts();
|
||||
}
|
||||
|
||||
@@ -1886,102 +1871,20 @@ nsFrameLoader::SetOwnerContent(Element* aContent)
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::OwnerIsMozBrowserOrAppFrame()
|
||||
nsFrameLoader::OwnerIsMozBrowserFrame()
|
||||
{
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
||||
return browserFrame ? browserFrame->GetReallyIsBrowserOrApp() : false;
|
||||
return browserFrame ? browserFrame->GetReallyIsBrowser() : false;
|
||||
}
|
||||
|
||||
// The xpcom getter version
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::GetOwnerIsMozBrowserOrAppFrame(bool* aResult)
|
||||
nsFrameLoader::GetOwnerIsMozBrowserFrame(bool* aResult)
|
||||
{
|
||||
*aResult = OwnerIsMozBrowserOrAppFrame();
|
||||
*aResult = OwnerIsMozBrowserFrame();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::OwnerIsAppFrame()
|
||||
{
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
||||
return browserFrame ? browserFrame->GetReallyIsApp() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::OwnerIsMozBrowserFrame()
|
||||
{
|
||||
return OwnerIsMozBrowserOrAppFrame() && !OwnerIsAppFrame();
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::OwnerIsIsolatedMozBrowserFrame()
|
||||
{
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
||||
if (!browserFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!OwnerIsMozBrowserFrame()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isolated = browserFrame->GetIsolated();
|
||||
if (isolated) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::GetOwnerAppManifestURL(nsAString& aOut)
|
||||
{
|
||||
aOut.Truncate();
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
||||
if (browserFrame) {
|
||||
browserFrame->GetAppManifestURL(aOut);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
nsFrameLoader::GetOwnApp()
|
||||
{
|
||||
nsAutoString manifest;
|
||||
GetOwnerAppManifestURL(manifest);
|
||||
if (manifest.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(appsService, nullptr);
|
||||
|
||||
nsCOMPtr<mozIApplication> app;
|
||||
appsService->GetAppByManifestURL(manifest, getter_AddRefs(app));
|
||||
|
||||
return app.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
nsFrameLoader::GetContainingApp()
|
||||
{
|
||||
// See if our owner content's principal has an associated app.
|
||||
uint32_t appId = mOwnerContent->NodePrincipal()->GetAppId();
|
||||
MOZ_ASSERT(appId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||
|
||||
if (appId == nsIScriptSecurityManager::NO_APP_ID ||
|
||||
appId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(appsService, nullptr);
|
||||
|
||||
nsCOMPtr<mozIApplication> app;
|
||||
appsService->GetAppByLocalId(appId, getter_AddRefs(app));
|
||||
|
||||
return app.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::ShouldUseRemoteProcess()
|
||||
{
|
||||
@@ -2005,7 +1908,7 @@ nsFrameLoader::ShouldUseRemoteProcess()
|
||||
|
||||
// If we're an <iframe mozbrowser> and we don't have a "remote" attribute,
|
||||
// fall back to the default.
|
||||
if (OwnerIsMozBrowserOrAppFrame() &&
|
||||
if (OwnerIsMozBrowserFrame() &&
|
||||
!mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::Remote)) {
|
||||
|
||||
return Preferences::GetBool("dom.ipc.browser_frames.oop_by_default", false);
|
||||
@@ -2013,7 +1916,7 @@ nsFrameLoader::ShouldUseRemoteProcess()
|
||||
|
||||
// Otherwise, we're remote if we have "remote=true" and we're either a
|
||||
// browser frame or a XUL element.
|
||||
return (OwnerIsMozBrowserOrAppFrame() ||
|
||||
return (OwnerIsMozBrowserFrame() ||
|
||||
mOwnerContent->GetNameSpaceID() == kNameSpaceID_XUL) &&
|
||||
mOwnerContent->AttrValueIs(kNameSpaceID_None,
|
||||
nsGkAtoms::Remote,
|
||||
@@ -2191,13 +2094,13 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
// Inherit origin attributes from parent document if
|
||||
// 1. It's in a content docshell.
|
||||
// 2. its nodePrincipal is not a SystemPrincipal.
|
||||
// 3. It's not a mozbrowser nor mozapp frame.
|
||||
// 3. It's not a mozbrowser frame.
|
||||
//
|
||||
// For example, firstPartyDomain is computed from top-level document, it
|
||||
// doesn't exist in the top-level docshell.
|
||||
if (parentType == nsIDocShellTreeItem::typeContent &&
|
||||
!nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()) &&
|
||||
!OwnerIsMozBrowserOrAppFrame()) {
|
||||
!OwnerIsMozBrowserFrame()) {
|
||||
PrincipalOriginAttributes poa = BasePrincipal::Cast(doc->NodePrincipal())->OriginAttributesRef();
|
||||
|
||||
// Assert on the firstPartyDomain from top-level docshell should be empty
|
||||
@@ -2212,42 +2115,14 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
"docshell and document should have the same appId attribute.");
|
||||
MOZ_ASSERT(attrs.mUserContextId == poa.mUserContextId,
|
||||
"docshell and document should have the same userContextId attribute.");
|
||||
MOZ_ASSERT(attrs.mInIsolatedMozBrowser == poa.mInIsolatedMozBrowser,
|
||||
"docshell and document should have the same inIsolatedMozBrowser attribute.");
|
||||
MOZ_ASSERT(attrs.mPrivateBrowsingId == poa.mPrivateBrowsingId,
|
||||
"docshell and document should have the same privateBrowsingId attribute.");
|
||||
|
||||
attrs.InheritFromDocToChildDocShell(poa);
|
||||
}
|
||||
|
||||
if (OwnerIsAppFrame()) {
|
||||
// You can't be both an app and a browser frame.
|
||||
MOZ_ASSERT(!OwnerIsMozBrowserFrame());
|
||||
|
||||
nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
|
||||
MOZ_ASSERT(ownApp);
|
||||
uint32_t ownAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
if (ownApp) {
|
||||
NS_ENSURE_SUCCESS(ownApp->GetLocalId(&ownAppId), NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
attrs.mAppId = ownAppId;
|
||||
mDocShell->SetFrameType(nsIDocShell::FRAME_TYPE_APP);
|
||||
}
|
||||
|
||||
if (OwnerIsMozBrowserFrame()) {
|
||||
// You can't be both a browser and an app frame.
|
||||
MOZ_ASSERT(!OwnerIsAppFrame());
|
||||
|
||||
nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
|
||||
uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
if (containingApp) {
|
||||
NS_ENSURE_SUCCESS(containingApp->GetLocalId(&containingAppId),
|
||||
NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
attrs.mAppId = containingAppId;
|
||||
attrs.mInIsolatedMozBrowser = OwnerIsIsolatedMozBrowserFrame();
|
||||
attrs.mAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
mDocShell->SetFrameType(nsIDocShell::FRAME_TYPE_BROWSER);
|
||||
}
|
||||
|
||||
@@ -2278,7 +2153,7 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
}
|
||||
attrs.SyncAttributesWithPrivateBrowsing(isPrivate);
|
||||
|
||||
if (OwnerIsMozBrowserOrAppFrame()) {
|
||||
if (OwnerIsMozBrowserFrame()) {
|
||||
// For inproc frames, set the docshell properties.
|
||||
nsAutoString name;
|
||||
if (mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name)) {
|
||||
@@ -2677,7 +2552,7 @@ nsFrameLoader::TryRemoteBrowser()
|
||||
}
|
||||
|
||||
// <iframe mozbrowser> gets to skip these checks.
|
||||
if (!OwnerIsMozBrowserOrAppFrame()) {
|
||||
if (!OwnerIsMozBrowserFrame()) {
|
||||
if (parentDocShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
|
||||
return false;
|
||||
}
|
||||
@@ -2718,8 +2593,8 @@ nsFrameLoader::TryRemoteBrowser()
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsCOMPtr<Element> ownerElement = mOwnerContent;
|
||||
mRemoteBrowser = ContentParent::CreateBrowserOrApp(context, ownerElement,
|
||||
openerContentParent, mFreshProcess);
|
||||
mRemoteBrowser = ContentParent::CreateBrowser(context, ownerElement,
|
||||
openerContentParent, mFreshProcess);
|
||||
if (!mRemoteBrowser) {
|
||||
return false;
|
||||
}
|
||||
@@ -2982,7 +2857,7 @@ nsFrameLoader::EnsureMessageManager()
|
||||
}
|
||||
|
||||
if (!mIsTopLevelContent &&
|
||||
!OwnerIsMozBrowserOrAppFrame() &&
|
||||
!OwnerIsMozBrowserFrame() &&
|
||||
!IsRemoteFrame() &&
|
||||
!(mOwnerContent->IsXULElement() &&
|
||||
mOwnerContent->AttrValueIs(kNameSpaceID_None,
|
||||
@@ -3287,7 +3162,7 @@ nsFrameLoader::GetLoadContext(nsILoadContext** aLoadContext)
|
||||
void
|
||||
nsFrameLoader::InitializeBrowserAPI()
|
||||
{
|
||||
if (!OwnerIsMozBrowserOrAppFrame()) {
|
||||
if (!OwnerIsMozBrowserFrame()) {
|
||||
return;
|
||||
}
|
||||
if (!IsRemoteFrame()) {
|
||||
@@ -3311,7 +3186,7 @@ nsFrameLoader::InitializeBrowserAPI()
|
||||
void
|
||||
nsFrameLoader::DestroyBrowserFrameScripts()
|
||||
{
|
||||
if (!OwnerIsMozBrowserOrAppFrame()) {
|
||||
if (!OwnerIsMozBrowserFrame()) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
||||
@@ -3392,24 +3267,10 @@ nsresult
|
||||
nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
|
||||
nsIURI* aURI)
|
||||
{
|
||||
nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
|
||||
nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
|
||||
DocShellOriginAttributes attrs;
|
||||
attrs.mInIsolatedMozBrowser = OwnerIsIsolatedMozBrowserFrame();
|
||||
nsresult rv;
|
||||
|
||||
// Get the AppId from ownApp
|
||||
uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
if (ownApp) {
|
||||
rv = ownApp->GetLocalId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_STATE(appId != nsIScriptSecurityManager::NO_APP_ID);
|
||||
} else if (containingApp) {
|
||||
rv = containingApp->GetLocalId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_STATE(appId != nsIScriptSecurityManager::NO_APP_ID);
|
||||
}
|
||||
attrs.mAppId = appId;
|
||||
attrs.mAppId = nsIScriptSecurityManager::NO_APP_ID; // No longer used...
|
||||
|
||||
// set the userContextId on the attrs before we pass them into
|
||||
// the tab context
|
||||
@@ -3439,8 +3300,6 @@ nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
|
||||
bool tabContextUpdated =
|
||||
aTabContext->SetTabContext(OwnerIsMozBrowserFrame(),
|
||||
mIsPrerendered,
|
||||
ownApp,
|
||||
containingApp,
|
||||
showAccelerators,
|
||||
showFocusRings,
|
||||
attrs);
|
||||
|
||||
@@ -241,53 +241,18 @@ private:
|
||||
*/
|
||||
bool IsRemoteFrame();
|
||||
|
||||
/**
|
||||
* Is this a frameloader for a bona fide <iframe mozbrowser> or
|
||||
* <iframe mozapp>? (I.e., does the frame return true for
|
||||
* nsIMozBrowserFrame::GetReallyIsBrowserOrApp()?)
|
||||
* <xul:browser> is not a mozbrowser or app, so this is false for that case.
|
||||
*/
|
||||
bool OwnerIsMozBrowserOrAppFrame();
|
||||
|
||||
/**
|
||||
* Is this a frameloader for a bona fide <iframe mozapp>? (I.e., does the
|
||||
* frame return true for nsIMozBrowserFrame::GetReallyIsApp()?)
|
||||
*/
|
||||
bool OwnerIsAppFrame();
|
||||
|
||||
/**
|
||||
* Is this a frame loader for a bona fide <iframe mozbrowser>?
|
||||
* <xul:browser> is not a mozbrowser, so this is false for that case.
|
||||
*/
|
||||
bool OwnerIsMozBrowserFrame();
|
||||
|
||||
/**
|
||||
* Is this a frame loader for an isolated <iframe mozbrowser>?
|
||||
*
|
||||
* By default, mozbrowser frames are isolated. Isolation can be disabled by
|
||||
* setting the frame's noisolation attribute. Disabling isolation is
|
||||
* only allowed if the containing document is chrome.
|
||||
*/
|
||||
bool OwnerIsIsolatedMozBrowserFrame();
|
||||
|
||||
/**
|
||||
* Get our owning element's app manifest URL, or return the empty string if
|
||||
* our owning element doesn't have an app manifest URL.
|
||||
*/
|
||||
void GetOwnerAppManifestURL(nsAString& aOut);
|
||||
|
||||
/**
|
||||
* Get the app for our frame. This is the app whose manifest is returned by
|
||||
* GetOwnerAppManifestURL.
|
||||
*/
|
||||
already_AddRefed<mozIApplication> GetOwnApp();
|
||||
|
||||
/**
|
||||
* Get the app which contains this frame. This is the app associated with
|
||||
* the frame element's principal.
|
||||
*/
|
||||
already_AddRefed<mozIApplication> GetContainingApp();
|
||||
|
||||
/**
|
||||
* If we are an IPC frame, set mRemoteFrame. Otherwise, create and
|
||||
* initialize mDocShell.
|
||||
|
||||
@@ -101,7 +101,6 @@ GK_ATOM(animations, "animations")
|
||||
GK_ATOM(anonid, "anonid")
|
||||
GK_ATOM(anonlocation, "anonlocation")
|
||||
GK_ATOM(any, "any")
|
||||
GK_ATOM(mozapp, "mozapp")
|
||||
GK_ATOM(applet, "applet")
|
||||
GK_ATOM(applyImports, "apply-imports")
|
||||
GK_ATOM(applyTemplates, "apply-templates")
|
||||
@@ -664,7 +663,6 @@ GK_ATOM(nodeSet, "node-set")
|
||||
GK_ATOM(noembed, "noembed")
|
||||
GK_ATOM(noframes, "noframes")
|
||||
GK_ATOM(nohref, "nohref")
|
||||
GK_ATOM(noisolation, "noisolation")
|
||||
GK_ATOM(nomodule, "nomodule")
|
||||
GK_ATOM(nonce, "nonce")
|
||||
GK_ATOM(none, "none")
|
||||
@@ -1002,7 +1000,6 @@ GK_ATOM(panel, "panel")
|
||||
GK_ATOM(param, "param")
|
||||
GK_ATOM(parameter, "parameter")
|
||||
GK_ATOM(parent, "parent")
|
||||
GK_ATOM(parentapp, "parentapp")
|
||||
GK_ATOM(parentfocused, "parentfocused")
|
||||
GK_ATOM(parsetype, "parsetype")
|
||||
GK_ATOM(password, "password")
|
||||
|
||||
+14
-54
@@ -2300,13 +2300,11 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
nsGlobalWindow::RiskyUnlink()
|
||||
{
|
||||
NS_CYCLE_COLLECTION_INNERNAME.Unlink(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindow)
|
||||
if (tmp->mCachedXBLPrototypeHandlers) {
|
||||
@@ -3542,12 +3540,6 @@ nsGlobalWindow::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
EventMessage msg = aVisitor.mEvent->mMessage;
|
||||
|
||||
aVisitor.mCanHandle = true;
|
||||
// Middle/right click shouldn't dispatch click event, use auxclick to instead.
|
||||
// Note: mDoc should always exist here, but check just in case someone yanked
|
||||
// it out from under us.
|
||||
if (mDoc && mDoc->IsXULDocument()) {
|
||||
aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
|
||||
}
|
||||
if (msg == eResize && aVisitor.mEvent->IsTrusted()) {
|
||||
// QIing to window so that we can keep the old behavior also in case
|
||||
// a child window is handling resize.
|
||||
@@ -4491,7 +4483,7 @@ nsGlobalWindow::GetParentOuter()
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> parent;
|
||||
if (mDocShell->GetIsMozBrowserOrApp()) {
|
||||
if (mDocShell->GetIsMozBrowser()) {
|
||||
parent = AsOuter();
|
||||
} else {
|
||||
parent = GetParent();
|
||||
@@ -4549,7 +4541,7 @@ nsGlobalWindow::GetParent()
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> parent;
|
||||
mDocShell->GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent));
|
||||
mDocShell->GetSameTypeParentIgnoreBrowserBoundaries(getter_AddRefs(parent));
|
||||
|
||||
if (parent) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = parent->GetWindow();
|
||||
@@ -4668,9 +4660,9 @@ nsGlobalWindow::GetContentInternal(ErrorResult& aError, bool aUnprivilegedCaller
|
||||
return domWindow.forget();
|
||||
}
|
||||
|
||||
// If we're contained in <iframe mozbrowser> or <iframe mozapp>, then
|
||||
// GetContent is the same as window.top.
|
||||
if (mDocShell && mDocShell->GetIsInMozBrowserOrApp()) {
|
||||
// If we're contained in <iframe mozbrowser>, then GetContent is the same as
|
||||
// window.top.
|
||||
if (mDocShell && mDocShell->GetIsInMozBrowser()) {
|
||||
return GetTopOuter();
|
||||
}
|
||||
|
||||
@@ -7994,7 +7986,7 @@ nsGlobalWindow::ResizeToOuter(int32_t aWidth, int32_t aHeight, ErrorResult& aErr
|
||||
* If caller is a browser-element then dispatch a resize event to
|
||||
* the embedder.
|
||||
*/
|
||||
if (mDocShell && mDocShell->GetIsMozBrowserOrApp()) {
|
||||
if (mDocShell && mDocShell->GetIsMozBrowser()) {
|
||||
CSSIntSize size(aWidth, aHeight);
|
||||
if (!DispatchResizeEvent(size)) {
|
||||
// The embedder chose to prevent the default action for this
|
||||
@@ -8044,7 +8036,7 @@ nsGlobalWindow::ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif,
|
||||
* If caller is a browser-element then dispatch a resize event to
|
||||
* parent.
|
||||
*/
|
||||
if (mDocShell && mDocShell->GetIsMozBrowserOrApp()) {
|
||||
if (mDocShell && mDocShell->GetIsMozBrowser()) {
|
||||
CSSIntSize size;
|
||||
if (NS_FAILED(GetInnerSize(size))) {
|
||||
return;
|
||||
@@ -8879,8 +8871,7 @@ nsGlobalWindow::PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessa
|
||||
providedPrincipal,
|
||||
callerInnerWin
|
||||
? callerInnerWin->GetDoc()
|
||||
: nullptr,
|
||||
nsContentUtils::IsCallerChrome());
|
||||
: nullptr);
|
||||
|
||||
JS::Rooted<JS::Value> message(aCx, aMessage);
|
||||
JS::Rooted<JS::Value> transfer(aCx, aTransfer);
|
||||
@@ -9016,7 +9007,7 @@ nsGlobalWindow::CloseOuter(bool aTrustedCaller)
|
||||
MOZ_RELEASE_ASSERT(IsOuterWindow());
|
||||
|
||||
if (!mDocShell || IsInModalState() ||
|
||||
(IsFrame() && !mDocShell->GetIsMozBrowserOrApp())) {
|
||||
(IsFrame() && !mDocShell->GetIsMozBrowser())) {
|
||||
// window.close() is called on a frame in a frameset, on a window
|
||||
// that's already closed, or on a window for which there's
|
||||
// currently a modal dialog open. Ignore such calls.
|
||||
@@ -9037,14 +9028,13 @@ nsGlobalWindow::CloseOuter(bool aTrustedCaller)
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't allow scripts from content to close non-app or non-neterror
|
||||
// windows that were not opened by script.
|
||||
// Don't allow scripts from content to close non-neterror windows that
|
||||
// were not opened by script.
|
||||
nsAutoString url;
|
||||
nsresult rv = mDoc->GetURL(url);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
if (!mDocShell->GetIsApp() &&
|
||||
!StringBeginsWith(url, NS_LITERAL_STRING("about:neterror")) &&
|
||||
if (!StringBeginsWith(url, NS_LITERAL_STRING("about:neterror")) &&
|
||||
!mHadOriginalOpener && !aTrustedCaller) {
|
||||
bool allowClose = mAllowScriptsToClose ||
|
||||
Preferences::GetBool("dom.allow_scripts_to_close_windows", true);
|
||||
@@ -9492,7 +9482,7 @@ nsGlobalWindow::GetFrameElementOuter(nsIPrincipal& aSubjectPrincipal)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(IsOuterWindow());
|
||||
|
||||
if (!mDocShell || mDocShell->GetIsMozBrowserOrApp()) {
|
||||
if (!mDocShell || mDocShell->GetIsMozBrowser()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -9527,7 +9517,7 @@ nsGlobalWindow::GetRealFrameElementOuter()
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> parent;
|
||||
mDocShell->GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent));
|
||||
mDocShell->GetSameTypeParentIgnoreBrowserBoundaries(getter_AddRefs(parent));
|
||||
|
||||
if (!parent || parent == mDocShell) {
|
||||
// We're at a chrome boundary, don't expose the chrome iframe
|
||||
@@ -14601,11 +14591,6 @@ already_AddRefed<Promise>
|
||||
nsGlobalWindow::CreateImageBitmap(const ImageBitmapSource& aImage,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ImageBitmap::Create(this, aImage, Nothing(), aRv);
|
||||
}
|
||||
|
||||
@@ -14614,34 +14599,9 @@ nsGlobalWindow::CreateImageBitmap(const ImageBitmapSource& aImage,
|
||||
int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ImageBitmap::Create(this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::dom::Promise>
|
||||
nsGlobalWindow::CreateImageBitmap(const ImageBitmapSource& aImage,
|
||||
int32_t aOffset, int32_t aLength,
|
||||
ImageBitmapFormat aFormat,
|
||||
const Sequence<ChannelPixelLayout>& aLayout,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!ImageBitmap::ExtensionsEnabled(nullptr, nullptr)) {
|
||||
aRv.Throw(NS_ERROR_TYPE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
|
||||
return ImageBitmap::Create(this, aImage, aOffset, aLength, aFormat, aLayout,
|
||||
aRv);
|
||||
} else {
|
||||
aRv.Throw(NS_ERROR_TYPE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#structured-cloning
|
||||
void
|
||||
nsGlobalWindow::StructuredClone(JSContext* aCx,
|
||||
|
||||
@@ -597,11 +597,9 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsGlobalWindow,
|
||||
nsIDOMEventTarget)
|
||||
|
||||
#ifdef DEBUG
|
||||
// Call Unlink on this window. This may cause bad things to happen, so use
|
||||
// with caution.
|
||||
void RiskyUnlink();
|
||||
#endif
|
||||
|
||||
virtual JSObject*
|
||||
GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey) override;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface mozIApplication;
|
||||
interface nsFrameLoader;
|
||||
interface nsIDocShell;
|
||||
interface nsIURI;
|
||||
@@ -216,11 +215,10 @@ interface nsIFrameLoader : nsISupports
|
||||
[infallible] attribute boolean visible;
|
||||
|
||||
/**
|
||||
* Find out whether the owner content really is a mozbrowser or app frame
|
||||
* Especially, a widget frame is regarded as an app frame. <xul:browser> is
|
||||
* not considered to be a mozbrowser frame.
|
||||
* Find out whether the owner content really is a mozbrowser. <xul:browser>
|
||||
* is not considered to be a mozbrowser frame.
|
||||
*/
|
||||
readonly attribute boolean ownerIsMozBrowserOrAppFrame;
|
||||
readonly attribute boolean ownerIsMozBrowserFrame;
|
||||
|
||||
/**
|
||||
* The last known width of the frame. Reading this property will not trigger
|
||||
@@ -265,12 +263,6 @@ interface nsIFrameLoaderOwner : nsISupports
|
||||
[binaryname(FrameLoaderXPCOM)] readonly attribute nsIFrameLoader frameLoader;
|
||||
[noscript, notxpcom] alreadyAddRefed_nsFrameLoader GetFrameLoader();
|
||||
|
||||
/**
|
||||
* The principal of parent mozIApplication in case of nested mozbrowser
|
||||
* iframes.
|
||||
*/
|
||||
readonly attribute mozIApplication parentApplication;
|
||||
|
||||
/**
|
||||
* Puts the FrameLoaderOwner in prerendering mode.
|
||||
*/
|
||||
|
||||
@@ -88,21 +88,24 @@ nsInProcessTabChildGlobal::DoSendAsyncMessage(JSContext* aCx,
|
||||
nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
|
||||
nsIContent* aOwner,
|
||||
nsFrameMessageManager* aChrome)
|
||||
: mDocShell(aShell), mInitialized(false), mLoadingScript(false),
|
||||
mPreventEventsEscaping(false),
|
||||
mOwner(aOwner), mChromeMessageManager(aChrome)
|
||||
: mDocShell(aShell)
|
||||
, mInitialized(false)
|
||||
, mLoadingScript(false)
|
||||
, mPreventEventsEscaping(false)
|
||||
, mOwner(aOwner)
|
||||
, mChromeMessageManager(aChrome)
|
||||
{
|
||||
SetIsNotDOMBinding();
|
||||
mozilla::HoldJSObjects(this);
|
||||
|
||||
// If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll
|
||||
// If owner corresponds to an <iframe mozbrowser>, we'll have to tweak our
|
||||
// GetEventTargetParent implementation.
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner);
|
||||
if (browserFrame) {
|
||||
mIsBrowserOrAppFrame = browserFrame->GetReallyIsBrowserOrApp();
|
||||
mIsBrowserFrame = browserFrame->GetReallyIsBrowser();
|
||||
}
|
||||
else {
|
||||
mIsBrowserOrAppFrame = false;
|
||||
mIsBrowserFrame = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +255,6 @@ nsInProcessTabChildGlobal::GetOwnerContent()
|
||||
nsresult
|
||||
nsInProcessTabChildGlobal::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
aVisitor.mForceContentDispatch = true;
|
||||
aVisitor.mCanHandle = true;
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -273,7 +275,7 @@ nsInProcessTabChildGlobal::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mIsBrowserOrAppFrame &&
|
||||
if (mIsBrowserFrame &&
|
||||
(!mOwner || !nsContentUtils::IsInChromeDocshell(mOwner->OwnerDoc()))) {
|
||||
if (mOwner) {
|
||||
if (nsPIDOMWindowInner* innerWindow = mOwner->OwnerDoc()->GetInnerWindow()) {
|
||||
|
||||
@@ -165,10 +165,9 @@ protected:
|
||||
bool mInitialized;
|
||||
bool mLoadingScript;
|
||||
|
||||
// Is this the message manager for an in-process <iframe mozbrowser> or
|
||||
// <iframe mozapp>? This affects where events get sent, so it affects
|
||||
// GetEventTargetParent.
|
||||
bool mIsBrowserOrAppFrame;
|
||||
// Is this the message manager for an in-process <iframe mozbrowser>? This
|
||||
// affects where events get sent, so it affects GetEventTargetParent.
|
||||
bool mIsBrowserFrame;
|
||||
bool mPreventEventsEscaping;
|
||||
|
||||
// We keep a strong reference to the frameloader after we've started
|
||||
|
||||
@@ -2265,7 +2265,6 @@ AsmJSCacheOpenEntryForRead(JS::Handle<JSObject*> aGlobal,
|
||||
|
||||
static JS::AsmJSCacheResult
|
||||
AsmJSCacheOpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
|
||||
bool aInstalled,
|
||||
const char16_t* aBegin,
|
||||
const char16_t* aEnd,
|
||||
size_t aSize,
|
||||
@@ -2274,8 +2273,7 @@ AsmJSCacheOpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
|
||||
{
|
||||
nsIPrincipal* principal =
|
||||
nsJSPrincipals::get(JS_GetCompartmentPrincipals(js::GetObjectCompartment(aGlobal)));
|
||||
return asmjscache::OpenEntryForWrite(principal, aInstalled, aBegin, aEnd,
|
||||
aSize, aMemory, aHandle);
|
||||
return asmjscache::OpenEntryForWrite(principal, aBegin, aEnd, aSize, aMemory, aHandle);
|
||||
}
|
||||
|
||||
class AsyncTaskRunnable final : public Runnable
|
||||
|
||||
@@ -1253,17 +1253,6 @@ nsObjectLoadingContent::GetFrameLoader()
|
||||
return loader.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::GetParentApplication(mozIApplication** aApplication)
|
||||
{
|
||||
if (!aApplication) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aApplication = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectLoadingContent::PresetOpenerWindow(mozIDOMWindowProxy* aWindow, mozilla::ErrorResult& aRv)
|
||||
{
|
||||
|
||||
@@ -411,6 +411,16 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
||||
|
||||
bool doneLoading = false;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Load the link's referrerpolicy attribute. If the link does not provide a
|
||||
// referrerpolicy attribute, ignore this and use the document's referrer
|
||||
// policy
|
||||
|
||||
net::ReferrerPolicy referrerPolicy = GetLinkReferrerPolicy();
|
||||
if (referrerPolicy == net::RP_Unset) {
|
||||
referrerPolicy = doc->GetReferrerPolicy();
|
||||
}
|
||||
|
||||
if (isInline) {
|
||||
nsAutoString text;
|
||||
if (!nsContentUtils::GetNodeTextContent(thisContent, false, text, fallible)) {
|
||||
@@ -429,7 +439,7 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
||||
|
||||
// Parse the style sheet.
|
||||
rv = doc->CSSLoader()->
|
||||
LoadInlineStyle(thisContent, text, mLineNumber, title, media,
|
||||
LoadInlineStyle(thisContent, text, mLineNumber, title, media, referrerPolicy,
|
||||
scopeElement, aObserver, &doneLoading, &isAlternate, &isExplicitlyEnabled);
|
||||
} else {
|
||||
nsAutoString integrity;
|
||||
@@ -440,15 +450,6 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
||||
NS_ConvertUTF16toUTF8(integrity).get()));
|
||||
}
|
||||
|
||||
// if referrer attributes are enabled in preferences, load the link's referrer
|
||||
// attribute. If the link does not provide a referrer attribute, ignore this
|
||||
// and use the document's referrer policy
|
||||
|
||||
net::ReferrerPolicy referrerPolicy = GetLinkReferrerPolicy();
|
||||
if (referrerPolicy == net::RP_Unset) {
|
||||
referrerPolicy = doc->GetReferrerPolicy();
|
||||
}
|
||||
|
||||
// XXXbz clone the URI here to work around content policies modifying URIs.
|
||||
nsCOMPtr<nsIURI> clonedURI;
|
||||
uri->Clone(getter_AddRefs(clonedURI));
|
||||
|
||||
@@ -829,7 +829,6 @@ nsWindowMemoryReporter::KillCheckTimer()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* static */ void
|
||||
nsWindowMemoryReporter::UnlinkGhostWindows()
|
||||
{
|
||||
@@ -866,4 +865,3 @@ nsWindowMemoryReporter::UnlinkGhostWindows()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -150,13 +150,11 @@ public:
|
||||
|
||||
static void Init();
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Unlink all known ghost windows, to enable investigating what caused them
|
||||
* to become ghost windows in the first place.
|
||||
*/
|
||||
static void UnlinkGhostWindows();
|
||||
#endif
|
||||
|
||||
static nsWindowMemoryReporter* Get();
|
||||
void ObserveDOMWindowDetached(nsGlobalWindow* aWindow);
|
||||
|
||||
@@ -179,7 +179,6 @@ nsresult
|
||||
nsWindowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
aVisitor.mCanHandle = true;
|
||||
aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
|
||||
// To keep mWindow alive
|
||||
aVisitor.mItemData = static_cast<nsISupports *>(mWindow);
|
||||
aVisitor.SetParentTarget(mParent, false);
|
||||
|
||||
@@ -220,6 +220,16 @@ DOMInterfaces = {
|
||||
'headerFile': 'nsCSSRules.h',
|
||||
},
|
||||
|
||||
'CSSLayerBlockRule': {
|
||||
'nativeType': 'mozilla::CSSLayerBlockRule',
|
||||
'headerFile': 'nsCSSRules.h',
|
||||
},
|
||||
|
||||
'CSSLayerStatementRule': {
|
||||
'nativeType': 'mozilla::CSSLayerStatementRule',
|
||||
'headerFile': 'nsCSSRules.h',
|
||||
},
|
||||
|
||||
'CSSLexer': {
|
||||
'wrapperCache': False
|
||||
},
|
||||
@@ -545,10 +555,6 @@ DOMInterfaces = {
|
||||
'headerFile': 'xpcjsid.h',
|
||||
},
|
||||
|
||||
'ImageBitmap': {
|
||||
'implicitJSContext': [ 'mapDataInto' ],
|
||||
},
|
||||
|
||||
'ImageCapture': {
|
||||
'binaryNames': { 'videoStreamTrack': 'GetVideoStreamTrack' }
|
||||
},
|
||||
|
||||
@@ -4888,6 +4888,16 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
raise WebIDLError("StaticClassOverride can be applied to static"
|
||||
" methods on JS-implemented classes only.",
|
||||
[self.location])
|
||||
if self.getExtendedAttribute("LenientFloat"):
|
||||
assert len(self.signatures()) >= 1
|
||||
found = False
|
||||
for sig in self.signatures():
|
||||
if any(arg.type.includesRestrictedFloat() for arg in sig[1]):
|
||||
found = True
|
||||
if not found:
|
||||
raise WebIDLError("[LenientFloat] used on an operation with no "
|
||||
"restricted float type arguments",
|
||||
[self.location])
|
||||
|
||||
def overloadsForArgCount(self, argc):
|
||||
return [overload for overload in self._overloads if
|
||||
@@ -4966,10 +4976,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
if not sig[0].isVoid():
|
||||
raise WebIDLError("[LenientFloat] used on a non-void method",
|
||||
[attr.location, self.location])
|
||||
if not any(arg.type.includesRestrictedFloat() for arg in sig[1]):
|
||||
raise WebIDLError("[LenientFloat] used on an operation with no "
|
||||
"restricted float type arguments",
|
||||
[attr.location, self.location])
|
||||
elif identifier == "Exposed":
|
||||
convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames)
|
||||
elif (identifier == "CrossOriginCallable" or
|
||||
|
||||
@@ -26,7 +26,7 @@ function parentDocShell(docshell) {
|
||||
function isTopBrowserElement(docShell) {
|
||||
while (docShell) {
|
||||
docShell = parentDocShell(docShell);
|
||||
if (docShell && docShell.isMozBrowserOrApp) {
|
||||
if (docShell && docShell.isMozBrowser) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ var CopyPasteAssistent = {
|
||||
let targetDocShell = currentWindow
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation);
|
||||
if(targetDocShell.isMozBrowserOrApp) {
|
||||
if(targetDocShell.isMozBrowser) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,23 +54,6 @@ CreateIframe(Element* aOpenerFrameElement, const nsAString& aName, bool aRemote)
|
||||
|
||||
popupFrameElement->SetMozbrowser(true);
|
||||
|
||||
// Copy the opener frame's mozapp attribute to the popup frame.
|
||||
if (aOpenerFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozapp)) {
|
||||
nsAutoString mozapp;
|
||||
aOpenerFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::mozapp, mozapp);
|
||||
popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::mozapp,
|
||||
mozapp, /* aNotify = */ false);
|
||||
}
|
||||
|
||||
// Copy the opener frame's parentApp attribute to the popup frame.
|
||||
if (aOpenerFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::parentapp)) {
|
||||
nsAutoString parentApp;
|
||||
aOpenerFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::parentapp,
|
||||
parentApp);
|
||||
popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::parentapp,
|
||||
parentApp, /* aNotify = */ false);
|
||||
}
|
||||
|
||||
// Copy the window name onto the iframe.
|
||||
popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::name,
|
||||
aName, /* aNotify = */ false);
|
||||
|
||||
@@ -8,27 +8,6 @@
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
|
||||
// We'll need to get the appId from the current document,
|
||||
// it's either SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID when
|
||||
// we are not running inside an app (e.g. Firefox Desktop),
|
||||
// or the appId of Mochitest app when we are running inside that app
|
||||
// (e.g. Emulator).
|
||||
var currentAppId = SpecialPowers.wrap(document).nodePrincipal.appId;
|
||||
var inApp =
|
||||
currentAppId !== SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID;
|
||||
// We will also need the manifest URL and set it on iframes.
|
||||
var currentAppManifestURL;
|
||||
|
||||
if (inApp) {
|
||||
let appsService = SpecialPowers.Cc["@mozilla.org/AppsService;1"]
|
||||
.getService(SpecialPowers.Ci.nsIAppsService);
|
||||
|
||||
currentAppManifestURL = appsService.getManifestURLByLocalId(currentAppId);
|
||||
};
|
||||
|
||||
info('appId=' + currentAppId);
|
||||
info('manifestURL=' + currentAppManifestURL);
|
||||
|
||||
function setup() {
|
||||
let appInfo = SpecialPowers.Cc['@mozilla.org/xre/app-info;1']
|
||||
.getService(SpecialPowers.Ci.nsIXULAppInfo);
|
||||
@@ -73,9 +52,6 @@ function createFrames() {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
let frame = gInputMethodFrames[i] = document.createElement('iframe');
|
||||
frame.setAttribute('mozbrowser', 'true');
|
||||
if (currentAppManifestURL) {
|
||||
frame.setAttribute('mozapp', currentAppManifestURL);
|
||||
}
|
||||
frame.addEventListener('mozbrowserloadend', countLoadend);
|
||||
frame.src = 'file_empty.html#' + i;
|
||||
document.body.appendChild(frame);
|
||||
@@ -88,20 +64,10 @@ function setPermissions() {
|
||||
allow: true,
|
||||
context: {
|
||||
url: SimpleTest.getTestFileURL('/file_empty.html'),
|
||||
originAttributes: {
|
||||
appId: currentAppId,
|
||||
inIsolatedMozBrowser: true
|
||||
}
|
||||
originAttributes: {}
|
||||
}
|
||||
}];
|
||||
|
||||
if (inApp) {
|
||||
// The current document would also need to be given access for IPC to
|
||||
// recognize our permission (why)?
|
||||
permissions.push({
|
||||
type: 'input', allow: true, context: document });
|
||||
}
|
||||
|
||||
SpecialPowers.pushPermissions(permissions,
|
||||
SimpleTest.waitForFocus.bind(SimpleTest, startTest));
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
// set 'remote' to true here will make the the iframe remote in _inproc_
|
||||
// test and in-process in _oop_ test.
|
||||
iframe.setAttribute('remote', 'true');
|
||||
iframe.setAttribute('mozapp', 'http://example.org/manifest.webapp');
|
||||
|
||||
iframe.addEventListener('mozbrowserloadend', function(e) {
|
||||
ok("mute" in iframe, "iframe.mute exists");
|
||||
|
||||
@@ -13,7 +13,5 @@ support-files =
|
||||
|
||||
[test_Simple.html]
|
||||
[test_HighPriority.html]
|
||||
[test_Preallocated.html]
|
||||
disabled = bug 968604, bug 987164
|
||||
[test_WebGLContextLost.html]
|
||||
disabled = bug 865844
|
||||
@@ -1,71 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test that the preallocated process starts up with priority BACKGROUND.
|
||||
-->
|
||||
<head>
|
||||
<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>
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
browserElementTestHelpers.enableProcessPriorityManager();
|
||||
|
||||
var preallocationEnabledPref = null;
|
||||
try {
|
||||
preallocationEnabledPref = SpecialPowers.getBoolPref('dom.ipc.processPrelaunch.enabled');
|
||||
}
|
||||
catch(e) {
|
||||
preallocationEnabledPref = null;
|
||||
}
|
||||
|
||||
var childID = null;
|
||||
|
||||
var cleanedUp = false;
|
||||
function cleanUp()
|
||||
{
|
||||
if (cleanedUp) {
|
||||
return;
|
||||
}
|
||||
|
||||
cleanedUp = true;
|
||||
}
|
||||
|
||||
// Even if this test times out, we still want to run cleanUp so as to set the
|
||||
// pref back.
|
||||
addEventListener('unload', cleanUp);
|
||||
|
||||
function runTest()
|
||||
{
|
||||
if (preallocationEnabledPref) {
|
||||
ok(false, "dom.ipc.processPrelaunch.enabled must be " +
|
||||
"false for this test to work.");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that the preallocated process initially gets BACKGROUND priority.
|
||||
// That's it.
|
||||
expectProcessCreated('PREALLOC').then(function() {
|
||||
// We need to set the pref asynchoronously or the preallocated process won't
|
||||
// be shut down.
|
||||
SimpleTest.executeSoon(function(){
|
||||
cleanUp();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
// Setting this pref to true should cause us to prelaunch a process.
|
||||
addEventListener('testready', function() {
|
||||
SpecialPowers.pushPrefEnv({'set':[["dom.ipc.processPrelaunch.enabled",true]]},runTest);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Vendored
+1
-4
@@ -259,7 +259,6 @@ Context::QuotaInitRunnable::OpenDirectory()
|
||||
QuotaManager::Get()->OpenDirectory(PERSISTENCE_TYPE_DEFAULT,
|
||||
mQuotaInfo.mGroup,
|
||||
mQuotaInfo.mOrigin,
|
||||
mQuotaInfo.mIsApp,
|
||||
quota::Client::DOMCACHE,
|
||||
/* aExclusive */ false,
|
||||
this);
|
||||
@@ -376,8 +375,7 @@ Context::QuotaInitRunnable::Run()
|
||||
nsresult rv = QuotaManager::GetInfoFromPrincipal(principal,
|
||||
&mQuotaInfo.mSuffix,
|
||||
&mQuotaInfo.mGroup,
|
||||
&mQuotaInfo.mOrigin,
|
||||
&mQuotaInfo.mIsApp);
|
||||
&mQuotaInfo.mOrigin);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
resolver->Resolve(rv);
|
||||
break;
|
||||
@@ -436,7 +434,6 @@ Context::QuotaInitRunnable::Run()
|
||||
mQuotaInfo.mSuffix,
|
||||
mQuotaInfo.mGroup,
|
||||
mQuotaInfo.mOrigin,
|
||||
mQuotaInfo.mIsApp,
|
||||
getter_AddRefs(mQuotaInfo.mDir));
|
||||
if (NS_FAILED(rv)) {
|
||||
resolver->Resolve(rv);
|
||||
|
||||
Vendored
+4
-1
@@ -196,7 +196,10 @@ static_assert(int(ReferrerPolicy::_empty) == 0 &&
|
||||
int(ReferrerPolicy::Origin) == 3 &&
|
||||
int(ReferrerPolicy::Origin_when_cross_origin) == 4 &&
|
||||
int(ReferrerPolicy::Unsafe_url) == 5 &&
|
||||
int(ReferrerPolicy::EndGuard_) == 6,
|
||||
int(ReferrerPolicy::Same_origin) == 6 &&
|
||||
int(ReferrerPolicy::Strict_origin) == 7 &&
|
||||
int(ReferrerPolicy::Strict_origin_when_cross_origin) == 8 &&
|
||||
int(ReferrerPolicy::EndGuard_) == 9,
|
||||
"ReferrerPolicy values are as expected");
|
||||
static_assert(int(RequestMode::Same_origin) == 0 &&
|
||||
int(RequestMode::No_cors) == 1 &&
|
||||
|
||||
Vendored
+1
-2
@@ -29,8 +29,7 @@ ManagerId::Create(nsIPrincipal* aPrincipal, ManagerId** aManagerIdOut)
|
||||
nsresult rv = QuotaManager::GetInfoFromPrincipal(aPrincipal,
|
||||
nullptr, // suffix
|
||||
nullptr, // group
|
||||
"aOrigin,
|
||||
nullptr); // is app
|
||||
"aOrigin);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
RefPtr<ManagerId> ref = new ManagerId(aPrincipal, quotaOrigin);
|
||||
|
||||
Vendored
-2
@@ -28,12 +28,10 @@ static const CacheId INVALID_CACHE_ID = -1;
|
||||
|
||||
struct QuotaInfo
|
||||
{
|
||||
QuotaInfo() : mIsApp(false) { }
|
||||
nsCOMPtr<nsIFile> mDir;
|
||||
nsCString mSuffix;
|
||||
nsCString mGroup;
|
||||
nsCString mOrigin;
|
||||
bool mIsApp;
|
||||
};
|
||||
|
||||
} // namespace cache
|
||||
|
||||
@@ -2229,6 +2229,18 @@ CanvasRenderingContext2D::Transform(double aM11, double aM12, double aM21,
|
||||
SetTransformInternal(newMatrix);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMMatrix>
|
||||
CanvasRenderingContext2D::GetTransform(ErrorResult& aError) {
|
||||
EnsureTarget();
|
||||
if (!IsTargetValid()) {
|
||||
aError.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<DOMMatrix> matrix =
|
||||
new DOMMatrix(GetParentObject(), mTarget->GetTransform());
|
||||
return matrix.forget();
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::SetTransform(double aM11, double aM12,
|
||||
double aM21, double aM22,
|
||||
@@ -2244,6 +2256,22 @@ CanvasRenderingContext2D::SetTransform(double aM11, double aM12,
|
||||
SetTransformInternal(Matrix(aM11, aM12, aM21, aM22, aDx, aDy));
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::SetTransform(const DOMMatrix2DInit& aInit,
|
||||
ErrorResult& aError) {
|
||||
TransformWillUpdate();
|
||||
if (!IsTargetValid()) {
|
||||
aError.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<DOMMatrixReadOnly> matrix =
|
||||
DOMMatrixReadOnly::FromMatrix(GetParentObject(), aInit, aError);
|
||||
if (!aError.Failed()) {
|
||||
SetTransformInternal(Matrix(*(matrix->GetInternal2D())));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::SetTransformInternal(const Matrix& aTransform)
|
||||
{
|
||||
|
||||
@@ -57,6 +57,10 @@ class CanvasRenderingContext2DUserData;
|
||||
class CanvasDrawObserver;
|
||||
class CanvasShutdownObserver;
|
||||
|
||||
class DOMMatrix;
|
||||
class DOMMatrixReadOnly;
|
||||
struct DOMMatrix2DInit;
|
||||
|
||||
/**
|
||||
** CanvasRenderingContext2D
|
||||
**/
|
||||
@@ -88,8 +92,10 @@ public:
|
||||
void Translate(double aX, double aY, mozilla::ErrorResult& aError);
|
||||
void Transform(double aM11, double aM12, double aM21, double aM22, double aDx,
|
||||
double aDy, mozilla::ErrorResult& aError);
|
||||
already_AddRefed<DOMMatrix> GetTransform(mozilla::ErrorResult& aError);
|
||||
void SetTransform(double aM11, double aM12, double aM21, double aM22, double aDx,
|
||||
double aDy, mozilla::ErrorResult& aError);
|
||||
void SetTransform(const DOMMatrix2DInit& aInit, mozilla::ErrorResult& aError);
|
||||
void ResetTransform(mozilla::ErrorResult& aError);
|
||||
|
||||
double GlobalAlpha()
|
||||
|
||||
+2
-613
@@ -412,7 +412,6 @@ ImageBitmap::ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData,
|
||||
, mDataWrapper(new ImageUtils(mData))
|
||||
, mPictureRect(0, 0, aData->GetSize().width, aData->GetSize().height)
|
||||
, mIsPremultipliedAlpha(aIsPremultipliedAlpha)
|
||||
, mIsCroppingAreaOutSideOfSourceImage(false)
|
||||
, mWriteOnly(aWriteOnly)
|
||||
{
|
||||
MOZ_ASSERT(aData, "aData is null in ImageBitmap constructor.");
|
||||
@@ -442,23 +441,6 @@ ImageBitmap::SetPictureRect(const IntRect& aRect, ErrorResult& aRv)
|
||||
mPictureRect = FixUpNegativeDimension(aRect, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
ImageBitmap::SetIsCroppingAreaOutSideOfSourceImage(const IntSize& aSourceSize,
|
||||
const Maybe<IntRect>& aCroppingRect)
|
||||
{
|
||||
// No cropping at all.
|
||||
if (aCroppingRect.isNothing()) {
|
||||
mIsCroppingAreaOutSideOfSourceImage = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (aCroppingRect->X() < 0 || aCroppingRect->Y() < 0 ||
|
||||
aCroppingRect->Width() > aSourceSize.width ||
|
||||
aCroppingRect->Height() > aSourceSize.height) {
|
||||
mIsCroppingAreaOutSideOfSourceImage = true;
|
||||
}
|
||||
}
|
||||
|
||||
static already_AddRefed<SourceSurface>
|
||||
ConvertColorFormatIfNeeded(RefPtr<SourceSurface> aSurface)
|
||||
{
|
||||
@@ -702,7 +684,6 @@ ImageBitmap::ToCloneData() const
|
||||
UniquePtr<ImageBitmapCloneData> result(new ImageBitmapCloneData());
|
||||
result->mPictureRect = mPictureRect;
|
||||
result->mIsPremultipliedAlpha = mIsPremultipliedAlpha;
|
||||
result->mIsCroppingAreaOutSideOfSourceImage = mIsCroppingAreaOutSideOfSourceImage;
|
||||
RefPtr<SourceSurface> surface = mData->GetAsSourceSurface();
|
||||
result->mSurface = surface->GetDataSurface();
|
||||
MOZ_ASSERT(result->mSurface);
|
||||
@@ -720,9 +701,6 @@ ImageBitmap::CreateFromCloneData(nsIGlobalObject* aGlobal,
|
||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aData->mWriteOnly,
|
||||
aData->mIsPremultipliedAlpha);
|
||||
|
||||
ret->mIsCroppingAreaOutSideOfSourceImage =
|
||||
aData->mIsCroppingAreaOutSideOfSourceImage;
|
||||
|
||||
ErrorResult rv;
|
||||
ret->SetPictureRect(aData->mPictureRect, rv);
|
||||
return ret.forget();
|
||||
@@ -796,9 +774,6 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl
|
||||
ret->SetPictureRect(aCropRect.ref(), aRv);
|
||||
}
|
||||
|
||||
// Set mIsCroppingAreaOutSideOfSourceImage.
|
||||
ret->SetIsCroppingAreaOutSideOfSourceImage(surface->GetSize(), aCropRect);
|
||||
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
@@ -850,9 +825,6 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLVideoElement& aVideoEl
|
||||
ret->SetPictureRect(aCropRect.ref(), aRv);
|
||||
}
|
||||
|
||||
// Set mIsCroppingAreaOutSideOfSourceImage.
|
||||
ret->SetIsCroppingAreaOutSideOfSourceImage(data->GetSize(), aCropRect);
|
||||
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
@@ -918,9 +890,6 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvas
|
||||
ret->SetPictureRect(cropRect, aRv);
|
||||
}
|
||||
|
||||
// Set mIsCroppingAreaOutSideOfSourceImage.
|
||||
ret->SetIsCroppingAreaOutSideOfSourceImage(surface->GetSize(), aCropRect);
|
||||
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
@@ -986,9 +955,6 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageData& aImageData,
|
||||
// The cropping information has been handled in the CreateImageFromRawData()
|
||||
// function.
|
||||
|
||||
// Set mIsCroppingAreaOutSideOfSourceImage.
|
||||
ret->SetIsCroppingAreaOutSideOfSourceImage(imageSize, aCropRect);
|
||||
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
@@ -1026,9 +992,6 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, CanvasRenderingContext2D&
|
||||
ret->SetPictureRect(aCropRect.ref(), aRv);
|
||||
}
|
||||
|
||||
// Set mIsCroppingAreaOutSideOfSourceImage.
|
||||
ret->SetIsCroppingAreaOutSideOfSourceImage(surface->GetSize(), aCropRect);
|
||||
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
@@ -1052,14 +1015,6 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageBitmap& aImageBitmap,
|
||||
ret->SetPictureRect(aCropRect.ref(), aRv);
|
||||
}
|
||||
|
||||
// Set mIsCroppingAreaOutSideOfSourceImage.
|
||||
if (aImageBitmap.mIsCroppingAreaOutSideOfSourceImage == true) {
|
||||
ret->mIsCroppingAreaOutSideOfSourceImage = true;
|
||||
} else {
|
||||
ret->SetIsCroppingAreaOutSideOfSourceImage(aImageBitmap.mPictureRect.Size(),
|
||||
aCropRect);
|
||||
}
|
||||
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
@@ -1318,9 +1273,6 @@ private:
|
||||
// Create ImageBitmap object.
|
||||
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(mGlobalObject, data, false /* write-only */);
|
||||
|
||||
// Set mIsCroppingAreaOutSideOfSourceImage.
|
||||
imageBitmap->SetIsCroppingAreaOutSideOfSourceImage(sourceSize, originalCropRect);
|
||||
|
||||
return imageBitmap.forget();
|
||||
}
|
||||
};
|
||||
@@ -1414,9 +1366,6 @@ private:
|
||||
// Create ImageBitmap object.
|
||||
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(mGlobalObject, data, false /* write-only */);
|
||||
|
||||
// Set mIsCroppingAreaOutSideOfSourceImage.
|
||||
imageBitmap->SetIsCroppingAreaOutSideOfSourceImage(sourceSize, originalCropRect);
|
||||
|
||||
return imageBitmap.forget();
|
||||
}
|
||||
|
||||
@@ -1506,20 +1455,17 @@ ImageBitmap::ReadStructuredClone(JSContext* aCx,
|
||||
uint32_t picRectWidth_;
|
||||
uint32_t picRectHeight_;
|
||||
uint32_t isPremultipliedAlpha_;
|
||||
uint32_t isCroppingAreaOutSideOfSourceImage_;
|
||||
uint32_t writeOnly;
|
||||
uint32_t dummy;
|
||||
|
||||
if (!JS_ReadUint32Pair(aReader, &picRectX_, &picRectY_) ||
|
||||
!JS_ReadUint32Pair(aReader, &picRectWidth_, &picRectHeight_) ||
|
||||
!JS_ReadUint32Pair(aReader, &isPremultipliedAlpha_,
|
||||
&isCroppingAreaOutSideOfSourceImage_) ||
|
||||
&dummy) ||
|
||||
!JS_ReadUint32Pair(aReader, &writeOnly, &dummy)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(dummy == 0);
|
||||
|
||||
int32_t picRectX = BitwiseCast<int32_t>(picRectX_);
|
||||
int32_t picRectY = BitwiseCast<int32_t>(picRectY_);
|
||||
int32_t picRectWidth = BitwiseCast<int32_t>(picRectWidth_);
|
||||
@@ -1540,9 +1486,6 @@ ImageBitmap::ReadStructuredClone(JSContext* aCx,
|
||||
RefPtr<ImageBitmap> imageBitmap =
|
||||
new ImageBitmap(aParent, img, !!writeOnly, isPremultipliedAlpha_);
|
||||
|
||||
imageBitmap->mIsCroppingAreaOutSideOfSourceImage =
|
||||
isCroppingAreaOutSideOfSourceImage_;
|
||||
|
||||
ErrorResult error;
|
||||
imageBitmap->SetPictureRect(IntRect(picRectX, picRectY,
|
||||
picRectWidth, picRectHeight), error);
|
||||
@@ -1572,7 +1515,6 @@ ImageBitmap::WriteStructuredClone(JSStructuredCloneWriter* aWriter,
|
||||
const uint32_t picRectWidth = BitwiseCast<uint32_t>(aImageBitmap->mPictureRect.width);
|
||||
const uint32_t picRectHeight = BitwiseCast<uint32_t>(aImageBitmap->mPictureRect.height);
|
||||
const uint32_t isPremultipliedAlpha = aImageBitmap->mIsPremultipliedAlpha ? 1 : 0;
|
||||
const uint32_t isCroppingAreaOutSideOfSourceImage = aImageBitmap->mIsCroppingAreaOutSideOfSourceImage ? 1 : 0;
|
||||
const uint32_t isWriteOnly = aImageBitmap->mWriteOnly ? 1 : 0;
|
||||
|
||||
// Indexing the cloned surfaces and send the index to the receiver.
|
||||
@@ -1581,8 +1523,7 @@ ImageBitmap::WriteStructuredClone(JSStructuredCloneWriter* aWriter,
|
||||
if (NS_WARN_IF(!JS_WriteUint32Pair(aWriter, SCTAG_DOM_IMAGEBITMAP, index)) ||
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, picRectX, picRectY)) ||
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, picRectWidth, picRectHeight)) ||
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, isPremultipliedAlpha,
|
||||
isCroppingAreaOutSideOfSourceImage)) ||
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, isPremultipliedAlpha, 0)) ||
|
||||
NS_WARN_IF(!JS_WriteUint32Pair(aWriter, isWriteOnly, 0))) {
|
||||
return false;
|
||||
}
|
||||
@@ -1608,557 +1549,5 @@ ImageBitmap::WriteStructuredClone(JSStructuredCloneWriter* aWriter,
|
||||
return true;
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
ImageBitmap::ExtensionsEnabled(JSContext* aCx, JSObject*)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
return Preferences::GetBool("canvas.imagebitmap_extensions.enabled");
|
||||
} else {
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
return workerPrivate->ImageBitmapExtensionsEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
// ImageBitmap extensions.
|
||||
ImageBitmapFormat
|
||||
ImageBitmap::FindOptimalFormat(const Optional<Sequence<ImageBitmapFormat>>& aPossibleFormats,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(mDataWrapper, "No ImageBitmapFormatUtils functionalities.");
|
||||
|
||||
ImageBitmapFormat platformFormat = mDataWrapper->GetFormat();
|
||||
|
||||
if (!aPossibleFormats.WasPassed() ||
|
||||
aPossibleFormats.Value().Contains(platformFormat)) {
|
||||
return platformFormat;
|
||||
} else {
|
||||
// If no matching is found, FindBestMatchingFromat() returns
|
||||
// ImageBitmapFormat::EndGuard_ and we throw an exception.
|
||||
ImageBitmapFormat optimalFormat =
|
||||
FindBestMatchingFromat(platformFormat, aPossibleFormats.Value());
|
||||
|
||||
if (optimalFormat == ImageBitmapFormat::EndGuard_) {
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
return optimalFormat;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
ImageBitmap::MappedDataLength(ImageBitmapFormat aFormat, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(mDataWrapper, "No ImageBitmapFormatUtils functionalities.");
|
||||
|
||||
if (aFormat == mDataWrapper->GetFormat()) {
|
||||
return mDataWrapper->GetBufferLength();
|
||||
} else {
|
||||
return CalculateImageBufferSize(aFormat, Width(), Height());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class MapDataIntoBufferSource
|
||||
{
|
||||
protected:
|
||||
MapDataIntoBufferSource(JSContext* aCx,
|
||||
Promise *aPromise,
|
||||
ImageBitmap *aImageBitmap,
|
||||
const T& aBuffer,
|
||||
int32_t aOffset,
|
||||
ImageBitmapFormat aFormat)
|
||||
: mPromise(aPromise)
|
||||
, mImageBitmap(aImageBitmap)
|
||||
, mBuffer(aCx, aBuffer.Obj())
|
||||
, mOffset(aOffset)
|
||||
, mFormat(aFormat)
|
||||
{
|
||||
MOZ_ASSERT(mPromise);
|
||||
MOZ_ASSERT(JS_IsArrayBufferObject(mBuffer) ||
|
||||
JS_IsArrayBufferViewObject(mBuffer));
|
||||
}
|
||||
|
||||
virtual ~MapDataIntoBufferSource() = default;
|
||||
|
||||
void DoMapDataIntoBufferSource()
|
||||
{
|
||||
ErrorResult error;
|
||||
|
||||
// Prepare destination buffer.
|
||||
uint8_t* bufferData = nullptr;
|
||||
uint32_t bufferLength = 0;
|
||||
bool isSharedMemory = false;
|
||||
if (JS_IsArrayBufferObject(mBuffer)) {
|
||||
js::GetArrayBufferLengthAndData(mBuffer, &bufferLength, &isSharedMemory, &bufferData);
|
||||
} else if (JS_IsArrayBufferViewObject(mBuffer)) {
|
||||
js::GetArrayBufferViewLengthAndData(mBuffer, &bufferLength, &isSharedMemory, &bufferData);
|
||||
} else {
|
||||
error.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
mPromise->MaybeReject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!bufferData) || NS_WARN_IF(!bufferLength)) {
|
||||
error.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
mPromise->MaybeReject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check length.
|
||||
const int32_t neededBufferLength =
|
||||
mImageBitmap->MappedDataLength(mFormat, error);
|
||||
|
||||
if (((int32_t)bufferLength - mOffset) < neededBufferLength) {
|
||||
error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
mPromise->MaybeReject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Call ImageBitmapFormatUtils.
|
||||
UniquePtr<ImagePixelLayout> layout =
|
||||
mImageBitmap->mDataWrapper->MapDataInto(bufferData,
|
||||
mOffset,
|
||||
bufferLength,
|
||||
mFormat,
|
||||
error);
|
||||
|
||||
if (NS_WARN_IF(!layout)) {
|
||||
mPromise->MaybeReject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
mPromise->MaybeResolve(*layout);
|
||||
}
|
||||
|
||||
RefPtr<Promise> mPromise;
|
||||
RefPtr<ImageBitmap> mImageBitmap;
|
||||
JS::PersistentRooted<JSObject*> mBuffer;
|
||||
int32_t mOffset;
|
||||
ImageBitmapFormat mFormat;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class MapDataIntoBufferSourceTask final : public Runnable,
|
||||
public MapDataIntoBufferSource<T>
|
||||
{
|
||||
public:
|
||||
MapDataIntoBufferSourceTask(JSContext* aCx,
|
||||
Promise *aPromise,
|
||||
ImageBitmap *aImageBitmap,
|
||||
const T& aBuffer,
|
||||
int32_t aOffset,
|
||||
ImageBitmapFormat aFormat)
|
||||
: MapDataIntoBufferSource<T>(aCx, aPromise, aImageBitmap, aBuffer, aOffset, aFormat)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~MapDataIntoBufferSourceTask() = default;
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MapDataIntoBufferSource<T>::DoMapDataIntoBufferSource();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class MapDataIntoBufferSourceWorkerTask final : public WorkerSameThreadRunnable,
|
||||
public MapDataIntoBufferSource<T>
|
||||
{
|
||||
public:
|
||||
MapDataIntoBufferSourceWorkerTask(JSContext* aCx,
|
||||
Promise *aPromise,
|
||||
ImageBitmap *aImageBitmap,
|
||||
const T& aBuffer,
|
||||
int32_t aOffset,
|
||||
ImageBitmapFormat aFormat)
|
||||
: WorkerSameThreadRunnable(GetCurrentThreadWorkerPrivate()),
|
||||
MapDataIntoBufferSource<T>(aCx, aPromise, aImageBitmap, aBuffer, aOffset, aFormat)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~MapDataIntoBufferSourceWorkerTask() = default;
|
||||
|
||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
MapDataIntoBufferSource<T>::DoMapDataIntoBufferSource();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void AsyncMapDataIntoBufferSource(JSContext* aCx,
|
||||
Promise *aPromise,
|
||||
ImageBitmap *aImageBitmap,
|
||||
const ArrayBufferViewOrArrayBuffer& aBuffer,
|
||||
int32_t aOffset,
|
||||
ImageBitmapFormat aFormat)
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_ASSERT(aImageBitmap);
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIRunnable> task;
|
||||
|
||||
if (aBuffer.IsArrayBuffer()) {
|
||||
const ArrayBuffer& buffer = aBuffer.GetAsArrayBuffer();
|
||||
task = new MapDataIntoBufferSourceTask<ArrayBuffer>(aCx, aPromise, aImageBitmap, buffer, aOffset, aFormat);
|
||||
} else if (aBuffer.IsArrayBufferView()) {
|
||||
const ArrayBufferView& bufferView = aBuffer.GetAsArrayBufferView();
|
||||
task = new MapDataIntoBufferSourceTask<ArrayBufferView>(aCx, aPromise, aImageBitmap, bufferView, aOffset, aFormat);
|
||||
}
|
||||
|
||||
NS_DispatchToCurrentThread(task); // Actually, to the main-thread.
|
||||
} else {
|
||||
RefPtr<WorkerSameThreadRunnable> task;
|
||||
|
||||
if (aBuffer.IsArrayBuffer()) {
|
||||
const ArrayBuffer& buffer = aBuffer.GetAsArrayBuffer();
|
||||
task = new MapDataIntoBufferSourceWorkerTask<ArrayBuffer>(aCx, aPromise, aImageBitmap, buffer, aOffset, aFormat);
|
||||
} else if (aBuffer.IsArrayBufferView()) {
|
||||
const ArrayBufferView& bufferView = aBuffer.GetAsArrayBufferView();
|
||||
task = new MapDataIntoBufferSourceWorkerTask<ArrayBufferView>(aCx, aPromise, aImageBitmap, bufferView, aOffset, aFormat);
|
||||
}
|
||||
|
||||
task->Dispatch(); // Actually, to the current worker-thread.
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ImageBitmap::MapDataInto(JSContext* aCx,
|
||||
ImageBitmapFormat aFormat,
|
||||
const ArrayBufferViewOrArrayBuffer& aBuffer,
|
||||
int32_t aOffset, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(mDataWrapper, "No ImageBitmapFormatUtils functionalities.");
|
||||
MOZ_ASSERT(aCx, "No JSContext while calling ImageBitmap::MapDataInto().");
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(mParent, aRv);
|
||||
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check for cases that should throws.
|
||||
// Case 1:
|
||||
// If image bitmap was cropped to the source rectangle so that it contains any
|
||||
// transparent black pixels (cropping area is outside of the source image),
|
||||
// then reject promise with IndexSizeError and abort these steps.
|
||||
if (mIsCroppingAreaOutSideOfSourceImage) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Case 2:
|
||||
// If the image bitmap is going to be accessed in YUV422/YUV422 series with a
|
||||
// cropping area starts at an odd x or y coordinate.
|
||||
if (aFormat == ImageBitmapFormat::YUV422P ||
|
||||
aFormat == ImageBitmapFormat::YUV420P ||
|
||||
aFormat == ImageBitmapFormat::YUV420SP_NV12 ||
|
||||
aFormat == ImageBitmapFormat::YUV420SP_NV21) {
|
||||
if ((mPictureRect.x & 1) || (mPictureRect.y & 1)) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
}
|
||||
|
||||
AsyncMapDataIntoBufferSource(aCx, promise, this, aBuffer, aOffset, aFormat);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// ImageBitmapFactories extensions.
|
||||
static SurfaceFormat
|
||||
ImageFormatToSurfaceFromat(mozilla::dom::ImageBitmapFormat aFormat)
|
||||
{
|
||||
switch(aFormat) {
|
||||
case ImageBitmapFormat::RGBA32:
|
||||
return SurfaceFormat::R8G8B8A8;
|
||||
case ImageBitmapFormat::BGRA32:
|
||||
return SurfaceFormat::B8G8R8A8;
|
||||
case ImageBitmapFormat::RGB24:
|
||||
return SurfaceFormat::R8G8B8;
|
||||
case ImageBitmapFormat::BGR24:
|
||||
return SurfaceFormat::B8G8R8;
|
||||
case ImageBitmapFormat::GRAY8:
|
||||
return SurfaceFormat::A8;
|
||||
case ImageBitmapFormat::HSV:
|
||||
return SurfaceFormat::HSV;
|
||||
case ImageBitmapFormat::Lab:
|
||||
return SurfaceFormat::Lab;
|
||||
case ImageBitmapFormat::DEPTH:
|
||||
return SurfaceFormat::Depth;
|
||||
default:
|
||||
return SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static already_AddRefed<layers::Image>
|
||||
CreateImageFromBufferSourceRawData(const uint8_t*aBufferData,
|
||||
uint32_t aBufferLength,
|
||||
mozilla::dom::ImageBitmapFormat aFormat,
|
||||
const Sequence<ChannelPixelLayout>& aLayout)
|
||||
{
|
||||
MOZ_ASSERT(aBufferData);
|
||||
MOZ_ASSERT(aBufferLength > 0);
|
||||
|
||||
switch(aFormat) {
|
||||
case ImageBitmapFormat::RGBA32:
|
||||
case ImageBitmapFormat::BGRA32:
|
||||
case ImageBitmapFormat::RGB24:
|
||||
case ImageBitmapFormat::BGR24:
|
||||
case ImageBitmapFormat::GRAY8:
|
||||
case ImageBitmapFormat::HSV:
|
||||
case ImageBitmapFormat::Lab:
|
||||
case ImageBitmapFormat::DEPTH:
|
||||
{
|
||||
const nsTArray<ChannelPixelLayout>& channels = aLayout;
|
||||
MOZ_ASSERT(channels.Length() != 0, "Empty Channels.");
|
||||
|
||||
const SurfaceFormat srcFormat = ImageFormatToSurfaceFromat(aFormat);
|
||||
const uint32_t srcStride = channels[0].mStride;
|
||||
const IntSize srcSize(channels[0].mWidth, channels[0].mHeight);
|
||||
|
||||
RefPtr<DataSourceSurface> dstDataSurface =
|
||||
Factory::CreateDataSourceSurfaceWithStride(srcSize, srcFormat, srcStride);
|
||||
|
||||
if (NS_WARN_IF(!dstDataSurface)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Copy the raw data into the newly created DataSourceSurface.
|
||||
DataSourceSurface::ScopedMap dstMap(dstDataSurface, DataSourceSurface::WRITE);
|
||||
if (NS_WARN_IF(!dstMap.IsMapped())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const uint8_t* srcBufferPtr = aBufferData;
|
||||
uint8_t* dstBufferPtr = dstMap.GetData();
|
||||
|
||||
for (int i = 0; i < srcSize.height; ++i) {
|
||||
memcpy(dstBufferPtr, srcBufferPtr, srcStride);
|
||||
srcBufferPtr += srcStride;
|
||||
dstBufferPtr += dstMap.GetStride();
|
||||
}
|
||||
|
||||
// Create an Image from the BGRA SourceSurface.
|
||||
RefPtr<SourceSurface> surface = dstDataSurface;
|
||||
RefPtr<layers::Image> image = CreateImageFromSurface(surface);
|
||||
|
||||
if (NS_WARN_IF(!image)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return image.forget();
|
||||
}
|
||||
case ImageBitmapFormat::YUV444P:
|
||||
case ImageBitmapFormat::YUV422P:
|
||||
case ImageBitmapFormat::YUV420P:
|
||||
case ImageBitmapFormat::YUV420SP_NV12:
|
||||
case ImageBitmapFormat::YUV420SP_NV21:
|
||||
{
|
||||
// Prepare the PlanarYCbCrData.
|
||||
const ChannelPixelLayout& yLayout = aLayout[0];
|
||||
const ChannelPixelLayout& uLayout = aFormat != ImageBitmapFormat::YUV420SP_NV21 ? aLayout[1] : aLayout[2];
|
||||
const ChannelPixelLayout& vLayout = aFormat != ImageBitmapFormat::YUV420SP_NV21 ? aLayout[2] : aLayout[1];
|
||||
|
||||
layers::PlanarYCbCrData data;
|
||||
|
||||
// Luminance buffer
|
||||
data.mYChannel = const_cast<uint8_t*>(aBufferData + yLayout.mOffset);
|
||||
data.mYStride = yLayout.mStride;
|
||||
data.mYSize = gfx::IntSize(yLayout.mWidth, yLayout.mHeight);
|
||||
data.mYSkip = yLayout.mSkip;
|
||||
|
||||
// Chroma buffers
|
||||
data.mCbChannel = const_cast<uint8_t*>(aBufferData + uLayout.mOffset);
|
||||
data.mCrChannel = const_cast<uint8_t*>(aBufferData + vLayout.mOffset);
|
||||
data.mCbCrStride = uLayout.mStride;
|
||||
data.mCbCrSize = gfx::IntSize(uLayout.mWidth, uLayout.mHeight);
|
||||
data.mCbSkip = uLayout.mSkip;
|
||||
data.mCrSkip = vLayout.mSkip;
|
||||
|
||||
// Picture rectangle.
|
||||
// We set the picture rectangle to exactly the size of the source image to
|
||||
// keep the full original data.
|
||||
data.mPicX = 0;
|
||||
data.mPicY = 0;
|
||||
data.mPicSize = data.mYSize;
|
||||
|
||||
// Create a layers::Image and set data.
|
||||
if (aFormat == ImageBitmapFormat::YUV444P ||
|
||||
aFormat == ImageBitmapFormat::YUV422P ||
|
||||
aFormat == ImageBitmapFormat::YUV420P) {
|
||||
RefPtr<layers::PlanarYCbCrImage> image =
|
||||
new layers::RecyclingPlanarYCbCrImage(new layers::BufferRecycleBin());
|
||||
|
||||
if (NS_WARN_IF(!image)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set Data.
|
||||
if (NS_WARN_IF(!image->CopyData(data))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return image.forget();
|
||||
} else {
|
||||
RefPtr<layers::NVImage>image = new layers::NVImage();
|
||||
|
||||
if (NS_WARN_IF(!image)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set Data.
|
||||
if (NS_WARN_IF(!image->SetData(data))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return image.forget();
|
||||
}
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a synchronous task.
|
||||
* This class is used to create a layers::CairoImage from raw data in the main
|
||||
* thread. While creating an ImageBitmap from an BufferSource, we need to create
|
||||
* a SouceSurface from the BufferSource raw data and then set the SourceSurface
|
||||
* into a layers::CairoImage. However, the layers::CairoImage asserts the
|
||||
* setting operation in the main thread, so if we are going to create an
|
||||
* ImageBitmap from an BufferSource off the main thread, we post an event to the
|
||||
* main thread to create a layers::CairoImage from an BufferSource raw data.
|
||||
*
|
||||
* TODO: Once the layers::CairoImage is constructible off the main thread, which
|
||||
* means the SouceSurface could be released anywhere, we do not need this
|
||||
* task anymore.
|
||||
*/
|
||||
class CreateImageFromBufferSourceRawDataInMainThreadSyncTask final :
|
||||
public WorkerMainThreadRunnable
|
||||
{
|
||||
public:
|
||||
CreateImageFromBufferSourceRawDataInMainThreadSyncTask(const uint8_t* aBuffer,
|
||||
uint32_t aBufferLength,
|
||||
mozilla::dom::ImageBitmapFormat aFormat,
|
||||
const Sequence<ChannelPixelLayout>& aLayout,
|
||||
/*output*/ layers::Image** aImage)
|
||||
: WorkerMainThreadRunnable(GetCurrentThreadWorkerPrivate(),
|
||||
NS_LITERAL_CSTRING("ImageBitmap-extensions :: Create Image from BufferSource Raw Data"))
|
||||
, mImage(aImage)
|
||||
, mBuffer(aBuffer)
|
||||
, mBufferLength(aBufferLength)
|
||||
, mFormat(aFormat)
|
||||
, mLayout(aLayout)
|
||||
{
|
||||
MOZ_ASSERT(!(*aImage), "Don't pass an existing Image into CreateImageFromBufferSourceRawDataInMainThreadSyncTask.");
|
||||
}
|
||||
|
||||
bool MainThreadRun() override
|
||||
{
|
||||
RefPtr<layers::Image> image =
|
||||
CreateImageFromBufferSourceRawData(mBuffer, mBufferLength, mFormat, mLayout);
|
||||
|
||||
if (NS_WARN_IF(!image)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
image.forget(mImage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
layers::Image** mImage;
|
||||
const uint8_t* mBuffer;
|
||||
uint32_t mBufferLength;
|
||||
mozilla::dom::ImageBitmapFormat mFormat;
|
||||
const Sequence<ChannelPixelLayout>& mLayout;
|
||||
};
|
||||
|
||||
/*static*/ already_AddRefed<Promise>
|
||||
ImageBitmap::Create(nsIGlobalObject* aGlobal,
|
||||
const ImageBitmapSource& aBuffer,
|
||||
int32_t aOffset, int32_t aLength,
|
||||
mozilla::dom::ImageBitmapFormat aFormat,
|
||||
const Sequence<ChannelPixelLayout>& aLayout,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(aGlobal, aRv);
|
||||
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t* bufferData = nullptr;
|
||||
uint32_t bufferLength = 0;
|
||||
|
||||
if (aBuffer.IsArrayBuffer()) {
|
||||
const ArrayBuffer& buffer = aBuffer.GetAsArrayBuffer();
|
||||
buffer.ComputeLengthAndData();
|
||||
bufferData = buffer.Data();
|
||||
bufferLength = buffer.Length();
|
||||
} else if (aBuffer.IsArrayBufferView()) {
|
||||
const ArrayBufferView& bufferView = aBuffer.GetAsArrayBufferView();
|
||||
bufferView.ComputeLengthAndData();
|
||||
bufferData = bufferView.Data();
|
||||
bufferLength = bufferView.Length();
|
||||
} else {
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(bufferData && bufferLength > 0, "Cannot read data from BufferSource.");
|
||||
|
||||
// Check the buffer.
|
||||
if (((uint32_t)(aOffset + aLength) > bufferLength)) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Create and Crop the raw data into a layers::Image
|
||||
RefPtr<layers::Image> data;
|
||||
if (NS_IsMainThread()) {
|
||||
data = CreateImageFromBufferSourceRawData(bufferData + aOffset, bufferLength,
|
||||
aFormat, aLayout);
|
||||
} else {
|
||||
RefPtr<CreateImageFromBufferSourceRawDataInMainThreadSyncTask> task =
|
||||
new CreateImageFromBufferSourceRawDataInMainThreadSyncTask(bufferData + aOffset,
|
||||
bufferLength,
|
||||
aFormat,
|
||||
aLayout,
|
||||
getter_AddRefs(data));
|
||||
task->Dispatch(Terminating, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return promise.forget();
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!data)) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Create an ImageBimtap.
|
||||
// Assume the data from an external buffer is not alpha-premultiplied.
|
||||
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(aGlobal, data, false);
|
||||
|
||||
// We don't need to call SetPictureRect() here because there is no cropping
|
||||
// supported and the ImageBitmap's mPictureRect is the size of the source
|
||||
// image in default
|
||||
|
||||
// We don't need to set mIsCroppingAreaOutSideOfSourceImage here because there
|
||||
// is no cropping supported and the mIsCroppingAreaOutSideOfSourceImage is
|
||||
// false in default.
|
||||
|
||||
AsyncFulfillImageBitmapPromise(promise, imageBitmap);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -45,7 +45,6 @@ class WorkerStructuredCloneClosure;
|
||||
|
||||
class ArrayBufferViewOrArrayBuffer;
|
||||
class CanvasRenderingContext2D;
|
||||
struct ChannelPixelLayout;
|
||||
class CreateImageBitmapFromBlob;
|
||||
class CreateImageBitmapFromBlobTask;
|
||||
class CreateImageBitmapFromBlobWorkerTask;
|
||||
@@ -56,7 +55,6 @@ class HTMLVideoElement;
|
||||
enum class ImageBitmapFormat : uint32_t;
|
||||
class ImageData;
|
||||
class ImageUtils;
|
||||
template<typename T> class MapDataIntoBufferSource;
|
||||
class Promise;
|
||||
class PostMessageEvent; // For StructuredClone between windows.
|
||||
|
||||
@@ -65,7 +63,6 @@ struct ImageBitmapCloneData final
|
||||
RefPtr<gfx::DataSourceSurface> mSurface;
|
||||
gfx::IntRect mPictureRect;
|
||||
bool mIsPremultipliedAlpha;
|
||||
bool mIsCroppingAreaOutSideOfSourceImage;
|
||||
bool mWriteOnly;
|
||||
};
|
||||
|
||||
@@ -133,14 +130,6 @@ public:
|
||||
Create(nsIGlobalObject* aGlobal, const ImageBitmapSource& aSrc,
|
||||
const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Promise>
|
||||
Create(nsIGlobalObject* aGlobal,
|
||||
const ImageBitmapSource& aBuffer,
|
||||
int32_t aOffset, int32_t aLength,
|
||||
mozilla::dom::ImageBitmapFormat aFormat,
|
||||
const Sequence<mozilla::dom::ChannelPixelLayout>& aLayout,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static JSObject*
|
||||
ReadStructuredClone(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
@@ -153,34 +142,14 @@ public:
|
||||
nsTArray<RefPtr<gfx::DataSourceSurface>>& aClonedSurfaces,
|
||||
ImageBitmap* aImageBitmap);
|
||||
|
||||
// Mozilla Extensions
|
||||
static bool ExtensionsEnabled(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
friend CreateImageBitmapFromBlob;
|
||||
friend CreateImageBitmapFromBlobTask;
|
||||
friend CreateImageBitmapFromBlobWorkerTask;
|
||||
|
||||
template<typename T>
|
||||
friend class MapDataIntoBufferSource;
|
||||
|
||||
bool IsWriteOnly() const {
|
||||
return mWriteOnly;
|
||||
}
|
||||
|
||||
// Mozilla Extensions
|
||||
ImageBitmapFormat
|
||||
FindOptimalFormat(const Optional<Sequence<ImageBitmapFormat>>& aPossibleFormats,
|
||||
ErrorResult& aRv);
|
||||
|
||||
int32_t
|
||||
MappedDataLength(ImageBitmapFormat aFormat, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MapDataInto(JSContext* aCx,
|
||||
ImageBitmapFormat aFormat,
|
||||
const ArrayBufferViewOrArrayBuffer& aBuffer,
|
||||
int32_t aOffset, ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
@@ -210,9 +179,6 @@ protected:
|
||||
|
||||
void SetPictureRect(const gfx::IntRect& aRect, ErrorResult& aRv);
|
||||
|
||||
void SetIsCroppingAreaOutSideOfSourceImage(const gfx::IntSize& aSourceSize,
|
||||
const Maybe<gfx::IntRect>& aCroppingRect);
|
||||
|
||||
static already_AddRefed<ImageBitmap>
|
||||
CreateInternal(nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl,
|
||||
const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
|
||||
@@ -278,15 +244,6 @@ protected:
|
||||
|
||||
const bool mIsPremultipliedAlpha;
|
||||
|
||||
/*
|
||||
* Set mIsCroppingAreaOutSideOfSourceImage if image bitmap was cropped to the
|
||||
* source rectangle so that it contains any transparent black pixels (cropping
|
||||
* area is outside of the source image).
|
||||
* This is used in mapDataInto() to check if we should reject promise with
|
||||
* IndexSizeError.
|
||||
*/
|
||||
bool mIsCroppingAreaOutSideOfSourceImage;
|
||||
|
||||
/*
|
||||
* Write-Only flag is set to true if this image has been generated from a
|
||||
* cross-origin source. This is the opposite of what is called 'origin-clean'
|
||||
|
||||
@@ -10,9 +10,8 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// So we don't have to forward declare this elsewhere.
|
||||
class HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrCanvasRenderingContext2DOrImageBitmapOrArrayBufferViewOrArrayBuffer;
|
||||
typedef HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrCanvasRenderingContext2DOrImageBitmapOrArrayBufferViewOrArrayBuffer
|
||||
ImageBitmapSource;
|
||||
class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmapOrBlobOrCanvasRenderingContext2DOrImageData;
|
||||
typedef HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmapOrBlobOrCanvasRenderingContext2DOrImageData ImageBitmapSource;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2728,16 +2728,6 @@ GetChannelCountOfImageFormat(ImageBitmapFormat aFormat)
|
||||
return format->GetChannelCount();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
CalculateImageBufferSize(ImageBitmapFormat aFormat,
|
||||
uint32_t aWidth, uint32_t aHeight)
|
||||
{
|
||||
UtilsUniquePtr format = Utils::GetUtils(aFormat);
|
||||
MOZ_ASSERT(format, "Cannot get a valid ImageBitmapFormatUtils instance.");
|
||||
|
||||
return format->NeededBufferSize(aWidth, aHeight);
|
||||
}
|
||||
|
||||
UniquePtr<ImagePixelLayout>
|
||||
CopyAndConvertImageData(ImageBitmapFormat aSrcFormat,
|
||||
const uint8_t* aSrcBuffer,
|
||||
|
||||
@@ -48,14 +48,6 @@ CreatePixelLayoutFromPlanarYCbCrData(const layers::PlanarYCbCrData* aData);
|
||||
uint8_t
|
||||
GetChannelCountOfImageFormat(ImageBitmapFormat aFormat);
|
||||
|
||||
/*
|
||||
* Get the needed buffer size to store the image data in the given
|
||||
* ImageBitmapFormat with the given width and height.
|
||||
*/
|
||||
uint32_t
|
||||
CalculateImageBufferSize(ImageBitmapFormat aFormat,
|
||||
uint32_t aWidth, uint32_t aHeight);
|
||||
|
||||
/*
|
||||
* This function always copies the image data in _aSrcBuffer_ into _aDstBuffer_
|
||||
* and it also performs color conversion if the _aSrcFormat_ and the
|
||||
|
||||
@@ -118,38 +118,6 @@ public:
|
||||
return (uint32_t)(size.height * stride);
|
||||
}
|
||||
|
||||
virtual UniquePtr<ImagePixelLayout>
|
||||
MapDataInto(uint8_t* aBuffer,
|
||||
uint32_t aOffset,
|
||||
uint32_t aBufferLength,
|
||||
ImageBitmapFormat aFormat,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
DataSourceSurface::ScopedMap map(Surface(), DataSourceSurface::READ);
|
||||
if (!map.IsMapped()) {
|
||||
aRv.Throw(NS_ERROR_ILLEGAL_VALUE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Copy or convert data.
|
||||
UniquePtr<ImagePixelLayout> srcLayout =
|
||||
CreateDefaultPixelLayout(GetFormat(), Surface()->GetSize().width,
|
||||
Surface()->GetSize().height, map.GetStride());
|
||||
|
||||
// Prepare destination buffer.
|
||||
uint8_t* dstBuffer = aBuffer + aOffset;
|
||||
UniquePtr<ImagePixelLayout> dstLayout =
|
||||
CopyAndConvertImageData(GetFormat(), map.GetData(), srcLayout.get(),
|
||||
aFormat, dstBuffer);
|
||||
|
||||
if (!dstLayout) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dstLayout;
|
||||
}
|
||||
|
||||
protected:
|
||||
Impl() {}
|
||||
|
||||
@@ -197,32 +165,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
UniquePtr<ImagePixelLayout>
|
||||
MapDataInto(uint8_t* aBuffer,
|
||||
uint32_t aOffset,
|
||||
uint32_t aBufferLength,
|
||||
ImageBitmapFormat aFormat,
|
||||
ErrorResult& aRv) const override
|
||||
{
|
||||
// Prepare source buffer and pixel layout.
|
||||
const PlanarYCbCrData* data = GetPlanarYCbCrData();
|
||||
|
||||
UniquePtr<ImagePixelLayout> srcLayout =
|
||||
CreatePixelLayoutFromPlanarYCbCrData(data);
|
||||
|
||||
// Do conversion.
|
||||
UniquePtr<ImagePixelLayout> dstLayout =
|
||||
CopyAndConvertImageData(GetFormat(), data->mYChannel, srcLayout.get(),
|
||||
aFormat, aBuffer+aOffset);
|
||||
|
||||
if (!dstLayout) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dstLayout;
|
||||
}
|
||||
|
||||
private:
|
||||
const PlanarYCbCrData* GetPlanarYCbCrData() const
|
||||
{
|
||||
@@ -274,17 +216,5 @@ ImageUtils::GetBufferLength() const
|
||||
return mImpl->GetBufferLength();
|
||||
}
|
||||
|
||||
UniquePtr<ImagePixelLayout>
|
||||
ImageUtils::MapDataInto(uint8_t* aBuffer,
|
||||
uint32_t aOffset,
|
||||
uint32_t aBufferLength,
|
||||
ImageBitmapFormat aFormat,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
MOZ_ASSERT(mImpl);
|
||||
MOZ_ASSERT(aBuffer, "Map data into a null buffer.");
|
||||
return mImpl->MapDataInto(aBuffer, aOffset, aBufferLength, aFormat, aRv);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -31,10 +31,6 @@ typedef nsTArray<ChannelPixelLayout> ImagePixelLayout;
|
||||
* (1) GetFormat() converts the image's format into ImageBitmapFormat enum.
|
||||
* (2) GetBufferLength() returns the number of bytes that are used to store
|
||||
* the image's underlying raw data.
|
||||
* (3) MapDataInto() writes the image's underlying raw data into a given
|
||||
* ArrayBuffer in the given format. (If the given format is different from
|
||||
* the existing format, the ImageUtils uses the ImageBitmapFormatUtils to
|
||||
* performa color conversion.)
|
||||
*
|
||||
* In theory, the functionalities of this class could be merged into the
|
||||
* interface of layers::Image. However, this is designed as a isolated wrapper
|
||||
@@ -58,10 +54,6 @@ public:
|
||||
|
||||
uint32_t GetBufferLength() const;
|
||||
|
||||
UniquePtr<ImagePixelLayout>
|
||||
MapDataInto(uint8_t* aBuffer, uint32_t aOffset, uint32_t aBufferLength,
|
||||
ImageBitmapFormat aFormat, ErrorResult& aRv) const;
|
||||
|
||||
protected:
|
||||
Impl* mImpl;
|
||||
};
|
||||
|
||||
@@ -1824,7 +1824,9 @@ WebGLContext::UpdateContextLossStatus()
|
||||
void
|
||||
WebGLContext::ForceLoseContext(bool simulateLosing)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf_stderr("WebGL(%p)::ForceLoseContext\n", this);
|
||||
#endif
|
||||
MOZ_ASSERT(!IsContextLost());
|
||||
mContextStatus = ContextLostAwaitingEvent;
|
||||
mContextLostErrorSet = false;
|
||||
@@ -1840,7 +1842,9 @@ WebGLContext::ForceLoseContext(bool simulateLosing)
|
||||
void
|
||||
WebGLContext::ForceRestoreContext()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf_stderr("WebGL(%p)::ForceRestoreContext\n", this);
|
||||
#endif
|
||||
mContextStatus = ContextLostAwaitingRestore;
|
||||
mAllowContextRestore = true; // Hey, you did say 'force'.
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<head>
|
||||
<title>Test ImageBitmap Extensions (Bug 1141979)</title>
|
||||
<meta charset="utf-8">
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<script src="imagebitmap_extensions_prepareSources.js"></script>
|
||||
<script src="imagebitmap_extensions_data.js"></script>
|
||||
<script src="imagebitmap_extensions.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
runTests();
|
||||
|
||||
function ok(expect, msg) {
|
||||
window.parent.postMessage({"type": "status", status: !!expect, msg: msg}, "*");
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
|
||||
prepareSources().
|
||||
then( function() { return Promise.all([testAccessing_randomTest("Video", gVideo, 20), // video might use slightly different frames
|
||||
testAccessing_randomTest("Image", gImage, 0),
|
||||
testAccessing_randomTest("Canvas", gCanvas, 0),
|
||||
testAccessing_randomTest("Ctx", gCtx, 0),
|
||||
testAccessing_randomTest("ImageData", gImageData, 0),
|
||||
testAccessing_randomTest("ImageBitmap", gImageBitmap, 0),
|
||||
testAccessing_randomTest("PNG", gPNGBlob, 0),
|
||||
testAccessing_randomTest("JPEG", gJPEGBlob, 10) // JPEG loses information
|
||||
]); }).
|
||||
then( function() { return Promise.all([testCreateFromArrayBffer_randomTest("Video", gVideo, 20), // video might use slightly different frames
|
||||
testCreateFromArrayBffer_randomTest("Image", gImage, 0),
|
||||
testCreateFromArrayBffer_randomTest("Canvas", gCanvas, 0),
|
||||
testCreateFromArrayBffer_randomTest("Ctx", gCtx, 0),
|
||||
testCreateFromArrayBffer_randomTest("ImageData", gImageData, 0),
|
||||
testCreateFromArrayBffer_randomTest("ImageBitmap", gImageBitmap, 0),
|
||||
testCreateFromArrayBffer_randomTest("PNG", gPNGBlob, 0),
|
||||
testCreateFromArrayBffer_randomTest("JPEG", gJPEGBlob, 10) // JPEG loses information
|
||||
]); }).
|
||||
then(testDraw()).
|
||||
then(testExceptions).
|
||||
then(testColorConversions()).
|
||||
then(function() { return testInvalidAccess([gVideo, gImage, gCanvas, gCtx, gImageData, gImageBitmap, gPNGBlob, gJPEGBlob]); } ).
|
||||
then(function() {window.parent.postMessage({"type": "finish"}, "*");}, function(ev) { failed(ev); window.parent.postMessage({"type": "finish"}, "*"); });
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
@@ -1,526 +0,0 @@
|
||||
function failed(ex) {
|
||||
ok(false, "Promise failure: " + ex);
|
||||
}
|
||||
|
||||
function isPixel(sourceType, bitmapFormat, imageData, bitmapImageData, x, y, tolerance) {
|
||||
if (imageData.width != bitmapImageData.width ||
|
||||
imageData.height != bitmapImageData.height) {
|
||||
ok(false, "Wrong dimension");
|
||||
}
|
||||
|
||||
var index = 4 * (y * imageData.width + x);
|
||||
|
||||
var pr = imageData.data[index+0],
|
||||
pg = imageData.data[index+1],
|
||||
pb = imageData.data[index+2],
|
||||
pa = imageData.data[index+3];
|
||||
|
||||
if (bitmapFormat == "RGBA32" || bitmapFormat == "RGBX32") {
|
||||
var bpr = bitmapImageData.data[index+0],
|
||||
bpg = bitmapImageData.data[index+1],
|
||||
bpb = bitmapImageData.data[index+2],
|
||||
bpa = bitmapImageData.data[index+3];
|
||||
}
|
||||
else if (bitmapFormat == "BGRA32" || bitmapFormat == "BGRX32") {
|
||||
var bpb = bitmapImageData.data[index+0],
|
||||
bpg = bitmapImageData.data[index+1],
|
||||
bpr = bitmapImageData.data[index+2],
|
||||
bpa = bitmapImageData.data[index+3];
|
||||
}
|
||||
else {
|
||||
// format might be one of the followings: "R5G6B5", "A8", "YUV", ""
|
||||
ok(false, "Not supported ImageFormat: " + bitmapFormat);
|
||||
}
|
||||
|
||||
ok(pr - tolerance <= bpr && bpr <= pr + tolerance &&
|
||||
pg - tolerance <= bpg && bpg <= pg + tolerance &&
|
||||
pb - tolerance <= bpb && bpb <= pb + tolerance &&
|
||||
pa - tolerance <= bpa && bpa <= pa + tolerance,
|
||||
"pixel[" + x + "][" + y + "]: " + sourceType + " is "+pr+","+pg+","+pb+","+pa+"; ImageBitmap is "+ bpr + "," + bpg + "," + bpb + "," + bpa);
|
||||
}
|
||||
|
||||
function promiseThrows(p, name) {
|
||||
var didThrow;
|
||||
return p.then(function() { didThrow = false; },
|
||||
function() { didThrow = true; })
|
||||
.then(function() { ok(didThrow, name); });
|
||||
}
|
||||
|
||||
function testExceptions() {
|
||||
return Promise.all([
|
||||
promiseThrows(testColorConversion("GRAY8", "RGBA32", undefined, true), "[Exception] Cannot convert from GRAY8 to RGBA32"),
|
||||
promiseThrows(testColorConversion("GRAY8", "BGRA32", undefined, true), "[Exception] Cannot convert from GRAY8 to BGRA32"),
|
||||
promiseThrows(testColorConversion("GRAY8", "RGB24", undefined, true), "[Exception] Cannot convert from GRAY8 to RGB24"),
|
||||
promiseThrows(testColorConversion("GRAY8", "BGR24", undefined, true), "[Exception] Cannot convert from GRAY8 to BGR24"),
|
||||
promiseThrows(testColorConversion("GRAY8", "YUV444P", undefined, true), "[Exception] Cannot convert from GRAY8 to YUV444P"),
|
||||
promiseThrows(testColorConversion("GRAY8", "YUV422P", undefined, true), "[Exception] Cannot convert from GRAY8 to YUV422P"),
|
||||
promiseThrows(testColorConversion("GRAY8", "YUV420P", undefined, true), "[Exception] Cannot convert from GRAY8 to YUV420P"),
|
||||
promiseThrows(testColorConversion("GRAY8", "YUV420SP_NV12", undefined, true), "[Exception] Cannot convert from GRAY8 to YUV420SP_NV12"),
|
||||
promiseThrows(testColorConversion("GRAY8", "YUV420SP_NV21", undefined, true), "[Exception] Cannot convert from GRAY8 to YUV420SP_NV21"),
|
||||
promiseThrows(testColorConversion("GRAY8", "HSV", undefined, true), "[Exception] Cannot convert from GRAY8 to HSV"),
|
||||
promiseThrows(testColorConversion("GRAY8", "Lab", undefined, true), "[Exception] Cannot convert from GRAY8 to Lab"),
|
||||
promiseThrows(testColorConversion("GRAY8", "DEPTH", undefined, true), "[Exception] Cannot convert from GRAY8 to DEPTH"),
|
||||
|
||||
promiseThrows(testColorConversion("DEPTH", "RGBA32", undefined, true), "[Exception] Cannot convert from DEPTH to RGBA32"),
|
||||
promiseThrows(testColorConversion("DEPTH", "BGRA32", undefined, true), "[Exception] Cannot convert from DEPTH to BGRA32"),
|
||||
promiseThrows(testColorConversion("DEPTH", "RGB24", undefined, true), "[Exception] Cannot convert from DEPTH to RGB24"),
|
||||
promiseThrows(testColorConversion("DEPTH", "BGR24", undefined, true), "[Exception] Cannot convert from DEPTH to BGR24"),
|
||||
promiseThrows(testColorConversion("DEPTH", "GRAY8", undefined, true), "[Exception] Cannot convert from DEPTH to GRAY8"),
|
||||
promiseThrows(testColorConversion("DEPTH", "YUV444P", undefined, true), "[Exception] Cannot convert from DEPTH to YUV444P"),
|
||||
promiseThrows(testColorConversion("DEPTH", "YUV422P", undefined, true), "[Exception] Cannot convert from DEPTH to YUV422P"),
|
||||
promiseThrows(testColorConversion("DEPTH", "YUV420P", undefined, true), "[Exception] Cannot convert from DEPTH to YUV420P"),
|
||||
promiseThrows(testColorConversion("DEPTH", "YUV420SP_NV12", undefined, true), "[Exception] Cannot convert from DEPTH to YUV420SP_NV12"),
|
||||
promiseThrows(testColorConversion("DEPTH", "YUV420SP_NV21", undefined, true), "[Exception] Cannot convert from DEPTH to YUV420SP_NV21"),
|
||||
promiseThrows(testColorConversion("DEPTH", "HSV", undefined, true), "[Exception] Cannot convert from DEPTH to HSV"),
|
||||
promiseThrows(testColorConversion("DEPTH", "Lab", undefined, true), "[Exception] Cannot convert from DEPTH to Lab"),
|
||||
|
||||
promiseThrows(testColorConversion("RGBA32", "DEPTH", undefined, true), "[Exception] Cannot convert from RGBA32 to DEPTH"),
|
||||
promiseThrows(testColorConversion("BGRA32", "DEPTH", undefined, true), "[Exception] Cannot convert from BGRA32 to DEPTH"),
|
||||
promiseThrows(testColorConversion("RGB24", "DEPTH", undefined, true), "[Exception] Cannot convert from RGB24 to DEPTH"),
|
||||
promiseThrows(testColorConversion("BGR24", "DEPTH", undefined, true), "[Exception] Cannot convert from BGR24 to DEPTH"),
|
||||
promiseThrows(testColorConversion("YUV444P", "DEPTH", undefined, true), "[Exception] Cannot convert from YUV444P to DEPTH"),
|
||||
promiseThrows(testColorConversion("YUV422P", "DEPTH", undefined, true), "[Exception] Cannot convert from YUV422P to DEPTH"),
|
||||
promiseThrows(testColorConversion("YUV420P", "DEPTH", undefined, true), "[Exception] Cannot convert from YUV420P to DEPTH"),
|
||||
promiseThrows(testColorConversion("YUV420SP_NV12", "DEPTH", undefined, true), "[Exception] Cannot convert from YUV420SP_NV12 to DEPTH"),
|
||||
promiseThrows(testColorConversion("YUV420SP_NV21", "DEPTH", undefined, true), "[Exception] Cannot convert from YUV420SP_NV21 to DEPTH"),
|
||||
promiseThrows(testColorConversion("HSV", "DEPTH", undefined, true), "[Exception] Cannot convert from HSV to DEPTH"),
|
||||
promiseThrows(testColorConversion("Lab", "DEPTH", undefined, true), "[Exception] Cannot convert from Lab to DEPTH"),
|
||||
]);
|
||||
}
|
||||
|
||||
function testInvalidAccess(sources) {
|
||||
|
||||
function callMapDataIntoWithImageBitmapCroppedOutSideOfTheSourceImage(source) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var p = createImageBitmap(source, -1, -1, 2, 2);
|
||||
p.then(
|
||||
function(bitmap) {
|
||||
var format = bitmap.findOptimalFormat();
|
||||
var length = bitmap.mappedDataLength(format);
|
||||
var buffer = new ArrayBuffer(length);
|
||||
bitmap.mapDataInto(format, buffer, 0).then(
|
||||
function(layout) { resolve(); },
|
||||
function(error) { reject(error); }
|
||||
);
|
||||
},
|
||||
function() { resolve(); });
|
||||
});
|
||||
};
|
||||
|
||||
var testCases = sources.map( function(source) {
|
||||
return promiseThrows(callMapDataIntoWithImageBitmapCroppedOutSideOfTheSourceImage(source),
|
||||
"[Exception] mapDataInto() should throw with transparent black."); });
|
||||
|
||||
return Promise.all(testCases);
|
||||
}
|
||||
|
||||
function testColorConversions() {
|
||||
return Promise.all([// From RGBA32
|
||||
testColorConversion("RGBA32", "RGBA32"),
|
||||
testColorConversion("RGBA32", "BGRA32"),
|
||||
testColorConversion("RGBA32", "RGB24"),
|
||||
testColorConversion("RGBA32", "BGR24"),
|
||||
testColorConversion("RGBA32", "GRAY8"),
|
||||
testColorConversion("RGBA32", "YUV444P"),
|
||||
testColorConversion("RGBA32", "YUV422P"),
|
||||
testColorConversion("RGBA32", "YUV420P", 2),
|
||||
testColorConversion("RGBA32", "YUV420SP_NV12"),
|
||||
testColorConversion("RGBA32", "YUV420SP_NV21"),
|
||||
testColorConversion("RGBA32", "HSV", 0.01),
|
||||
testColorConversion("RGBA32", "Lab", 0.5),
|
||||
|
||||
// From BGRA32
|
||||
testColorConversion("BGRA32", "RGBA32"),
|
||||
testColorConversion("BGRA32", "BGRA32"),
|
||||
testColorConversion("BGRA32", "RGB24"),
|
||||
testColorConversion("BGRA32", "BGR24"),
|
||||
testColorConversion("BGRA32", "GRAY8"),
|
||||
testColorConversion("BGRA32", "YUV444P", 3),
|
||||
testColorConversion("BGRA32", "YUV422P", 2),
|
||||
testColorConversion("BGRA32", "YUV420P", 2),
|
||||
testColorConversion("BGRA32", "YUV420SP_NV12", 2),
|
||||
testColorConversion("BGRA32", "YUV420SP_NV21", 2),
|
||||
testColorConversion("BGRA32", "HSV", 0.01),
|
||||
testColorConversion("BGRA32", "Lab", 0.5),
|
||||
|
||||
// From RGB24
|
||||
testColorConversion("RGB24", "RGBA32"),
|
||||
testColorConversion("RGB24", "BGRA32"),
|
||||
testColorConversion("RGB24", "RGB24"),
|
||||
testColorConversion("RGB24", "BGR24"),
|
||||
testColorConversion("RGB24", "GRAY8"),
|
||||
testColorConversion("RGB24", "YUV444P"),
|
||||
testColorConversion("RGB24", "YUV422P"),
|
||||
testColorConversion("RGB24", "YUV420P"),
|
||||
testColorConversion("RGB24", "YUV420SP_NV12"),
|
||||
testColorConversion("RGB24", "YUV420SP_NV21"),
|
||||
testColorConversion("RGB24", "HSV", 0.01),
|
||||
testColorConversion("RGB24", "Lab", 0.5),
|
||||
|
||||
// From BGR24
|
||||
testColorConversion("BGR24", "RGBA32"),
|
||||
testColorConversion("BGR24", "BGRA32"),
|
||||
testColorConversion("BGR24", "RGB24"),
|
||||
testColorConversion("BGR24", "BGR24"),
|
||||
testColorConversion("BGR24", "GRAY8"),
|
||||
testColorConversion("BGR24", "YUV444P"),
|
||||
testColorConversion("BGR24", "YUV422P"),
|
||||
testColorConversion("BGR24", "YUV420P"),
|
||||
testColorConversion("BGR24", "YUV420SP_NV12"),
|
||||
testColorConversion("BGR24", "YUV420SP_NV21"),
|
||||
testColorConversion("BGR24", "HSV", 0.01),
|
||||
testColorConversion("BGR24", "Lab", 0.5),
|
||||
|
||||
// From YUV444P
|
||||
testColorConversion("YUV444P", "RGBA32"),
|
||||
testColorConversion("YUV444P", "BGRA32"),
|
||||
testColorConversion("YUV444P", "RGB24"),
|
||||
testColorConversion("YUV444P", "BGR24"),
|
||||
testColorConversion("YUV444P", "GRAY8"),
|
||||
testColorConversion("YUV444P", "YUV444P"),
|
||||
testColorConversion("YUV444P", "YUV422P", 4),
|
||||
testColorConversion("YUV444P", "YUV420P", 3),
|
||||
testColorConversion("YUV444P", "YUV420SP_NV12", 3),
|
||||
testColorConversion("YUV444P", "YUV420SP_NV21", 3),
|
||||
testColorConversion("YUV444P", "HSV", 0.01),
|
||||
testColorConversion("YUV444P", "Lab", 0.01),
|
||||
|
||||
// From YUV422P
|
||||
testColorConversion("YUV422P", "RGBA32"),
|
||||
testColorConversion("YUV422P", "BGRA32", 2),
|
||||
testColorConversion("YUV422P", "RGB24"),
|
||||
testColorConversion("YUV422P", "BGR24"),
|
||||
testColorConversion("YUV422P", "GRAY8"),
|
||||
testColorConversion("YUV422P", "YUV444P", 3),
|
||||
testColorConversion("YUV422P", "YUV422P"),
|
||||
testColorConversion("YUV422P", "YUV420P"),
|
||||
testColorConversion("YUV422P", "YUV420SP_NV12"),
|
||||
testColorConversion("YUV422P", "YUV420SP_NV21"),
|
||||
testColorConversion("YUV422P", "HSV", 0.01),
|
||||
testColorConversion("YUV422P", "Lab", 0.01),
|
||||
|
||||
// From YUV420P
|
||||
testColorConversion("YUV420P", "RGBA32", 2),
|
||||
testColorConversion("YUV420P", "BGRA32", 2),
|
||||
testColorConversion("YUV420P", "RGB24"),
|
||||
testColorConversion("YUV420P", "BGR24"),
|
||||
testColorConversion("YUV420P", "GRAY8"),
|
||||
testColorConversion("YUV420P", "YUV444P", 3),
|
||||
testColorConversion("YUV420P", "YUV422P", 1),
|
||||
testColorConversion("YUV420P", "YUV420P"),
|
||||
testColorConversion("YUV420P", "YUV420SP_NV12"),
|
||||
testColorConversion("YUV420P", "YUV420SP_NV21"),
|
||||
testColorConversion("YUV420P", "HSV", 0.01),
|
||||
testColorConversion("YUV420P", "Lab", 0.01),
|
||||
|
||||
// From NV12
|
||||
testColorConversion("YUV420SP_NV12", "RGBA32"),
|
||||
testColorConversion("YUV420SP_NV12", "BGRA32", 2),
|
||||
testColorConversion("YUV420SP_NV12", "RGB24"),
|
||||
testColorConversion("YUV420SP_NV12", "BGR24"),
|
||||
testColorConversion("YUV420SP_NV12", "GRAY8"),
|
||||
testColorConversion("YUV420SP_NV12", "YUV444P", 3),
|
||||
testColorConversion("YUV420SP_NV12", "YUV422P", 1),
|
||||
testColorConversion("YUV420SP_NV12", "YUV420P"),
|
||||
testColorConversion("YUV420SP_NV12", "YUV420SP_NV12"),
|
||||
testColorConversion("YUV420SP_NV12", "YUV420SP_NV21"),
|
||||
testColorConversion("YUV420SP_NV12", "HSV", 0.01),
|
||||
testColorConversion("YUV420SP_NV12", "Lab", 0.01),
|
||||
|
||||
// From NV21
|
||||
testColorConversion("YUV420SP_NV21", "RGBA32"),
|
||||
testColorConversion("YUV420SP_NV21", "BGRA32", 2),
|
||||
testColorConversion("YUV420SP_NV21", "RGB24"),
|
||||
testColorConversion("YUV420SP_NV21", "BGR24"),
|
||||
testColorConversion("YUV420SP_NV21", "GRAY8"),
|
||||
testColorConversion("YUV420SP_NV21", "YUV444P", 3),
|
||||
testColorConversion("YUV420SP_NV21", "YUV422P", 1),
|
||||
testColorConversion("YUV420SP_NV21", "YUV420P"),
|
||||
testColorConversion("YUV420SP_NV21", "YUV420SP_NV12"),
|
||||
testColorConversion("YUV420SP_NV21", "YUV420SP_NV21"),
|
||||
testColorConversion("YUV420SP_NV21", "HSV", 0.01),
|
||||
testColorConversion("YUV420SP_NV21", "Lab", 0.01),
|
||||
|
||||
// From HSV
|
||||
testColorConversion("HSV", "RGBA32"),
|
||||
testColorConversion("HSV", "BGRA32"),
|
||||
testColorConversion("HSV", "RGB24"),
|
||||
testColorConversion("HSV", "BGR24"),
|
||||
testColorConversion("HSV", "GRAY8"),
|
||||
testColorConversion("HSV", "YUV444P"),
|
||||
testColorConversion("HSV", "YUV422P"),
|
||||
testColorConversion("HSV", "YUV420P"),
|
||||
testColorConversion("HSV", "YUV420SP_NV12"),
|
||||
testColorConversion("HSV", "YUV420SP_NV21"),
|
||||
testColorConversion("HSV", "HSV", 0),
|
||||
testColorConversion("HSV", "Lab", 0.5),
|
||||
|
||||
// From Lab
|
||||
testColorConversion("Lab", "RGBA32", 1),
|
||||
testColorConversion("Lab", "BGRA32", 1),
|
||||
testColorConversion("Lab", "RGB24", 1),
|
||||
testColorConversion("Lab", "BGR24", 1),
|
||||
testColorConversion("Lab", "GRAY8", 1),
|
||||
testColorConversion("Lab", "YUV444P", 1),
|
||||
testColorConversion("Lab", "YUV422P", 1),
|
||||
testColorConversion("Lab", "YUV420P", 1),
|
||||
testColorConversion("Lab", "YUV420SP_NV12", 1),
|
||||
testColorConversion("Lab", "YUV420SP_NV21", 1),
|
||||
testColorConversion("Lab", "HSV", 0.5),
|
||||
testColorConversion("Lab", "Lab", 0),
|
||||
|
||||
// From GRAY8
|
||||
testColorConversion("GRAY8", "GRAY8"),
|
||||
|
||||
// From DEPTH
|
||||
testColorConversion("DEPTH", "DEPTH", 0, Uint16Array),
|
||||
]);
|
||||
}
|
||||
|
||||
function testDraw() {
|
||||
return Promise.all([doOneDrawTest("RGB24"),
|
||||
doOneDrawTest("BGR24"),
|
||||
doOneDrawTest("YUV444P", 5),
|
||||
doOneDrawTest("YUV422P", 2),
|
||||
doOneDrawTest("YUV420P", 2),
|
||||
doOneDrawTest("YUV420SP_NV12", 2),
|
||||
doOneDrawTest("YUV420SP_NV21", 2),
|
||||
doOneDrawTest("HSV", 2),
|
||||
doOneDrawTest("Lab", 2)]);
|
||||
}
|
||||
|
||||
// Create an ImageBitmap, _bitmap_, from the _source_.
|
||||
// Read the underlying data of _bitmap_ into _bitmapBuffer_.
|
||||
// Compare the _bitmapBuffer_ with gGroundTruthImageData.
|
||||
function testAccessing_randomTest(sourceType, source, duration) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var p = createImageBitmap(source);
|
||||
p.then(
|
||||
function(bitmap) {
|
||||
bitmapFormat = "RGBA32";
|
||||
var bitmapBufferLength = bitmap.mappedDataLength(bitmapFormat);
|
||||
|
||||
var bitmapBuffer = new ArrayBuffer(bitmapBufferLength);
|
||||
var bitmapBufferView = new Uint8ClampedArray(bitmapBuffer, 0, bitmapBufferLength);
|
||||
var promise = bitmap.mapDataInto(bitmapFormat, bitmapBuffer, 0);
|
||||
promise.then(
|
||||
function(bitmapPixelLayout) {
|
||||
// Prepare.
|
||||
bitmapImageData = new ImageData(bitmapBufferView, bitmap.width, bitmap.height);
|
||||
|
||||
// Test.
|
||||
for (var t = 0; t < 50; ++t) {
|
||||
var randomX = Math.floor(Math.random() * 240);
|
||||
var randomY = Math.floor(Math.random() * 175);
|
||||
isPixel(sourceType, "RGBA32", gGroundTruthImageData, bitmapImageData, randomX, randomY, duration);
|
||||
}
|
||||
|
||||
resolve();
|
||||
},
|
||||
function(ev) { failed(ev); reject(); });
|
||||
},
|
||||
function(ev) { failed(ev); reject(); });
|
||||
});
|
||||
}
|
||||
|
||||
// Create an ImageBitmap, _bitmap_, from the _source_.
|
||||
// Read the underlying data of _bitmap_ into _bitmapBuffer_.
|
||||
// Create another ImageBitmap, _bitmap2_, from _bitmapBuffer_.
|
||||
// Read the underlying data of _bitmap2_ into _bitmapBuffer2_.
|
||||
// Compare the _bitmapBuffer2_ with gGroundTruthImageData.
|
||||
function testCreateFromArrayBffer_randomTest(sourceType, source, duration) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var p = createImageBitmap(source);
|
||||
p.then(
|
||||
function(bitmap) {
|
||||
bitmapFormat = "RGBA32";
|
||||
var bitmapBufferLength = bitmap.mappedDataLength(bitmapFormat);
|
||||
|
||||
var bitmapBuffer = new ArrayBuffer(bitmapBufferLength);
|
||||
var bitmapBufferView = new Uint8ClampedArray(bitmapBuffer, 0, bitmapBufferLength);
|
||||
var promiseMapDataInto = bitmap.mapDataInto(bitmapFormat, bitmapBuffer, 0);
|
||||
promiseMapDataInto.then(
|
||||
function(bitmapPixelLayout) {
|
||||
// Create a new ImageBitmap from an ArrayBuffer.
|
||||
var p2 = createImageBitmap(bitmapBufferView,
|
||||
0,
|
||||
bitmapBufferLength,
|
||||
bitmapFormat,
|
||||
bitmapPixelLayout);
|
||||
|
||||
p2.then(
|
||||
function(bitmap2) {
|
||||
bitmapFormat2 = "RGBA32";
|
||||
var bitmapBufferLength2 = bitmap2.mappedDataLength(bitmapFormat2);
|
||||
|
||||
var bitmapBuffer2 = new ArrayBuffer(bitmapBufferLength2);
|
||||
var bitmapBufferView2 = new Uint8ClampedArray(bitmapBuffer2, 0, bitmapBufferLength2);
|
||||
var promise2 = bitmap2.mapDataInto(bitmapFormat2, bitmapBuffer2, 0);
|
||||
promise2.then(
|
||||
function(bitmapPixelLayout2) {
|
||||
// Prepare.
|
||||
var bitmapImageData2 = new ImageData(bitmapBufferView2, bitmap2.width, bitmap2.height);
|
||||
|
||||
// Test.
|
||||
for (var t = 0; t < 50; ++t) {
|
||||
var randomX = Math.floor(Math.random() * 240);
|
||||
var randomY = Math.floor(Math.random() * 175);
|
||||
isPixel(sourceType, "RGBA32", gGroundTruthImageData, bitmapImageData2, randomX, randomY, duration);
|
||||
}
|
||||
|
||||
resolve();
|
||||
},
|
||||
function(ev) { failed(ev); reject(); });
|
||||
},
|
||||
function(ev) { console.log("p2 rejected!"); failed(ev); reject(); });
|
||||
},
|
||||
function(ev) { console.log("promiseMapDataInto rejected!"); failed(ev); reject(); });
|
||||
},
|
||||
function(ev) { failed(ev); reject(); });
|
||||
});
|
||||
}
|
||||
|
||||
function testColorConversion(sourceFromat, destinationFormat, tolerance, shouldThrow) {
|
||||
|
||||
tolerance = tolerance || 0;
|
||||
shouldThrow = shouldThrow || false;
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
var [srcData, dstData] = getTestData(sourceFromat, destinationFormat);
|
||||
|
||||
ok(!!srcData, "Get valid srcData of type:" + sourceFromat);
|
||||
ok(!!dstData, "Get valid dstData of type:" + destinationFormat);
|
||||
|
||||
// printInfo(sourceFromat, srcData);
|
||||
// printInfo(destinationFormat, dstData);
|
||||
|
||||
// Create a new ImageBitmap from an ArrayBuffer.
|
||||
var p = createImageBitmap(srcData.buffer,
|
||||
0,
|
||||
srcData.bufferLength,
|
||||
srcData.format,
|
||||
srcData.pixelLayout);
|
||||
|
||||
p.then(
|
||||
function(srcBitmap) {
|
||||
ok(!!srcBitmap, "Should get a valid srcBitmap.");
|
||||
ok(srcBitmap.findOptimalFormat() == sourceFromat, "srcBitmap.findOptimalFormat():" + srcBitmap.findOptimalFormat() +
|
||||
" should equal to sourceFromat:" + sourceFromat);
|
||||
|
||||
var dstBufferLength = srcBitmap.mappedDataLength(destinationFormat);
|
||||
var dstBuffer = new ArrayBuffer(dstBufferLength);
|
||||
var dstBufferView = new dstData.ArrayType(dstBuffer, 0, dstBufferLength / dstData.ArrayType.BYTES_PER_ELEMENT);
|
||||
|
||||
// Do color conversion here.
|
||||
var p2 = srcBitmap.mapDataInto(destinationFormat, dstBuffer, 0);
|
||||
p2.then(
|
||||
function(dstPixelLayout) {
|
||||
var dataPixalLayout = dstData.pixelLayout;
|
||||
|
||||
// Check pixel layout.
|
||||
ok(dstPixelLayout.length == dstData.channelCount, "dstPixelLayout.length:" + dstPixelLayout.length +
|
||||
" should equal to dstData.channelCount:" + dstData.channelCount);
|
||||
|
||||
for (var c = 0; c < dstData.channelCount; ++c) {
|
||||
var dstChannelLayout = dstPixelLayout[c];
|
||||
var dataChannelLayout = dataPixalLayout[c];
|
||||
ok(dstChannelLayout.width == dataChannelLayout.width, "channel[" + c + "] dstChannelLayout.width:" + dstChannelLayout.width + " should equal to dataChannelLayout.width:" + dataChannelLayout.width);
|
||||
ok(dstChannelLayout.height == dataChannelLayout.height, "channel[" + c + "] dstChannelLayout.height:" + dstChannelLayout.height + " should equal to dataChannelLayout.height:" + dataChannelLayout.height);
|
||||
ok(dstChannelLayout.skip == dataChannelLayout.skip, "channel[" + c + "] dstChannelLayout.skip:" + dstChannelLayout.skip + " should equal to dataChannelLayout.skip:" + dataChannelLayout.skip);
|
||||
|
||||
for (var i = 0; i < dstChannelLayout.height; ++i) {
|
||||
for (var j = 0; j < dstChannelLayout.width; ++j) {
|
||||
var byteOffset = dstChannelLayout.offset + i * dstChannelLayout.stride + j * (dstChannelLayout.skip + 1) * dstData.ArrayType.BYTES_PER_ELEMENT;
|
||||
var view = new dstData.ArrayType(dstBuffer, byteOffset, 1);
|
||||
var dstBufferViewValue = view[0];
|
||||
var dstDataValue = dstData.getPixelValue(i, j, c);
|
||||
ok(Math.abs(dstBufferViewValue - dstDataValue) <= tolerance,
|
||||
"[" + sourceFromat + " -> " + destinationFormat + "] pixel(" + i + "," + j + ") channnel(" + c +
|
||||
"): dstBufferViewValue:" + dstBufferViewValue +
|
||||
" should equal to dstDataValue:" + dstDataValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolve();
|
||||
},
|
||||
function(ev) {
|
||||
// If the "mapDataInto" throws, the flow goes here.
|
||||
if (!shouldThrow) { failed(ev); }
|
||||
reject();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(ev) {
|
||||
reject(ev);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function doOneDrawTest(sourceFromat, tolerance) {
|
||||
tolerance = tolerance || 0;
|
||||
var destinationFormat = "RGBA32";
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
|
||||
var [srcData, dstData] = getTestData(sourceFromat, destinationFormat);
|
||||
ok(!!srcData, "Get valid srcData of type:" + sourceFromat);
|
||||
ok(!!dstData, "Get valid dstData of type:" + destinationFormat);
|
||||
|
||||
var p = createImageBitmap(srcData.buffer,
|
||||
0,
|
||||
srcData.bufferLength,
|
||||
srcData.format,
|
||||
srcData.pixelLayout);
|
||||
|
||||
p.then(
|
||||
function(srcBitmap) {
|
||||
ok(!!srcBitmap, "Should get a valid srcBitmap.");
|
||||
ok(srcBitmap.findOptimalFormat() == sourceFromat, "srcBitmap.findOptimalFormat():" + srcBitmap.findOptimalFormat() +
|
||||
" should equal to sourceFromat:" + sourceFromat);
|
||||
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = srcBitmap.width;
|
||||
canvas.height = srcBitmap.height;
|
||||
var ctx = canvas.getContext("2d");
|
||||
|
||||
ctx.drawImage(srcBitmap, 0, 0, srcBitmap.width, srcBitmap.height);
|
||||
|
||||
// Get an ImageData from the canvas.
|
||||
var imageData = ctx.getImageData(0, 0, srcBitmap.width, srcBitmap.height);
|
||||
|
||||
for (var i = 0; i < srcBitmap.height; ++i) {
|
||||
for (var j = 0; j < srcBitmap.width; ++j) {
|
||||
var pixelOffset = i * srcBitmap.width * dstData.channelCount + j * dstData.channelCount;
|
||||
var dstImageDataValue_R = imageData.data[pixelOffset + 0];
|
||||
var dstImageDataValue_G = imageData.data[pixelOffset + 1];
|
||||
var dstImageDataValue_B = imageData.data[pixelOffset + 2];
|
||||
var dstImageDataValue_A = imageData.data[pixelOffset + 3];
|
||||
|
||||
var logPrefix = "[" + sourceFromat + " -> " + destinationFormat + "] pixel(" + i + "," + j + ")";
|
||||
|
||||
var dstDataValue_R = dstData.getPixelValue(i, j, 0);
|
||||
var dstDataValue_G = dstData.getPixelValue(i, j, 1);
|
||||
var dstDataValue_B = dstData.getPixelValue(i, j, 2);
|
||||
var dstDataValue_A = dstData.getPixelValue(i, j, 3);
|
||||
ok(Math.abs(dstImageDataValue_R - dstDataValue_R) <= tolerance,
|
||||
logPrefix + "channnel(R): dstImageDataValue:" + dstImageDataValue_R + " should equal to dstDataValue_R: " + dstDataValue_R);
|
||||
ok(Math.abs(dstImageDataValue_G - dstDataValue_G) <= tolerance,
|
||||
logPrefix + "channnel(G): dstImageDataValue:" + dstImageDataValue_G + " should equal to dstDataValue_G: " + dstDataValue_G);
|
||||
ok(Math.abs(dstImageDataValue_B - dstDataValue_B) <= tolerance,
|
||||
logPrefix + "channnel(B): dstImageDataValue:" + dstImageDataValue_B + " should equal to dstDataValue_B: " + dstDataValue_B);
|
||||
ok(Math.abs(dstImageDataValue_A - dstDataValue_A) <= tolerance,
|
||||
logPrefix + "channnel(A): dstImageDataValue:" + dstImageDataValue_A + " should equal to dstDataValue_A: " + dstDataValue_A);
|
||||
}
|
||||
}
|
||||
|
||||
resolve();
|
||||
},
|
||||
function(ev) {
|
||||
failed(ev);
|
||||
reject(ev);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
Loaded 100 of 728 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user