зеркало из https://github.com/mozilla/gecko-dev.git
Bug 785884 - Implement support for temporary storage (aka shared pool). r=ehsan, r=bent
--HG-- rename : caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html => caps/tests/mochitest/test_principal_jarprefix_origin_appid_appstatus.html rename : dom/quota/UsageRunnable.h => dom/quota/UsageInfo.h
This commit is contained in:
Родитель
67b05683bd
Коммит
e9492bcd36
|
@ -61,7 +61,7 @@ let DomStorage = {
|
||||||
// Check if we're allowed to store sessionStorage data.
|
// Check if we're allowed to store sessionStorage data.
|
||||||
let isHTTPS = principal.URI && principal.URI.schemeIs("https");
|
let isHTTPS = principal.URI && principal.URI.schemeIs("https");
|
||||||
if (aFullData || SessionStore.checkPrivacyLevel(isHTTPS, isPinned)) {
|
if (aFullData || SessionStore.checkPrivacyLevel(isHTTPS, isPinned)) {
|
||||||
let origin = principal.extendedOrigin;
|
let origin = principal.jarPrefix + principal.origin;
|
||||||
|
|
||||||
// Don't read a host twice.
|
// Don't read a host twice.
|
||||||
if (!(origin in data)) {
|
if (!(origin in data)) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ interface nsIContentSecurityPolicy;
|
||||||
[ptr] native JSPrincipals(JSPrincipals);
|
[ptr] native JSPrincipals(JSPrincipals);
|
||||||
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
|
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(dbda8bb0-3023-4aec-ad98-8e9931a29d70)]
|
[scriptable, builtinclass, uuid(551bf53d-203c-4ac4-8c0b-40aa7b5f1ad6)]
|
||||||
interface nsIPrincipal : nsISerializable
|
interface nsIPrincipal : nsISerializable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -162,19 +162,19 @@ interface nsIPrincipal : nsISerializable
|
||||||
[noscript] attribute nsIContentSecurityPolicy csp;
|
[noscript] attribute nsIContentSecurityPolicy csp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the extended origin of the principal.
|
* Returns the jar prefix of the principal.
|
||||||
* The extended origin is a string that has more information than the origin
|
* The jar prefix is a string that can be used to isolate data or
|
||||||
* and can be used to isolate data or permissions between different
|
* permissions between different principals while taking into account
|
||||||
* principals while taking into account parameters like the app id or the
|
* parameters like the app id or the fact that the principal is embedded in
|
||||||
* fact that the principal is embedded in a mozbrowser.
|
* a mozbrowser.
|
||||||
* Some principals will return the origin for extendedOrigin.
|
* Some principals will return an empty string.
|
||||||
* Some principals will assert if you try to access the extendedOrigin.
|
* Some principals will assert if you try to access the jarPrefix.
|
||||||
*
|
*
|
||||||
* The extendedOrigin is intended to be an opaque identifier. It is
|
* The jarPrefix is intended to be an opaque identifier. It is currently
|
||||||
* currently "human-readable" but no callers should assume it will stay
|
* "human-readable" but no callers should assume it will stay as is and
|
||||||
* as is and it might be crypto-hashed at some point.
|
* it might be crypto-hashed at some point.
|
||||||
*/
|
*/
|
||||||
readonly attribute AUTF8String extendedOrigin;
|
readonly attribute AUTF8String jarPrefix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base domain of the codebase URI to which this principal pertains
|
* The base domain of the codebase URI to which this principal pertains
|
||||||
|
|
|
@ -10,7 +10,7 @@ interface nsIURI;
|
||||||
interface nsIChannel;
|
interface nsIChannel;
|
||||||
interface nsIDocShell;
|
interface nsIDocShell;
|
||||||
|
|
||||||
[scriptable, uuid(ae486501-ec57-4ec8-a565-6880ca4ae6c4)]
|
[scriptable, uuid(d6475e53-9ece-4dc0-940c-095ac3d85363)]
|
||||||
interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
||||||
{
|
{
|
||||||
///////////////// Security Checks //////////////////
|
///////////////// Security Checks //////////////////
|
||||||
|
@ -229,13 +229,12 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
||||||
const unsigned long UNKNOWN_APP_ID = 4294967295; // UINT32_MAX
|
const unsigned long UNKNOWN_APP_ID = 4294967295; // UINT32_MAX
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the extended origin for the uri.
|
* Returns the jar prefix for the app.
|
||||||
* appId can be NO_APP_ID or a valid app id. appId should not be
|
* appId can be NO_APP_ID or a valid app id. appId should not be
|
||||||
* UNKNOWN_APP_ID.
|
* UNKNOWN_APP_ID.
|
||||||
* inMozBrowser has to be true if the uri is inside a mozbrowser iframe.
|
* inMozBrowser has to be true if the app is inside a mozbrowser iframe.
|
||||||
*/
|
*/
|
||||||
AUTF8String getExtendedOrigin(in nsIURI uri, in unsigned long appId,
|
AUTF8String getJarPrefix(in unsigned long appId, in boolean inMozBrowser);
|
||||||
in boolean inMozBrowser);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
%{C++
|
%{C++
|
||||||
|
|
|
@ -65,7 +65,7 @@ public:
|
||||||
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
|
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
|
||||||
NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
|
NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
|
||||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
|
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
|
||||||
NS_IMETHOD GetExtendedOrigin(nsACString& aExtendedOrigin);
|
NS_IMETHOD GetJarPrefix(nsACString& aJarPrefix);
|
||||||
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus);
|
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus);
|
||||||
NS_IMETHOD GetAppId(uint32_t* aAppStatus);
|
NS_IMETHOD GetAppId(uint32_t* aAppStatus);
|
||||||
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
|
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
|
||||||
|
@ -148,7 +148,7 @@ public:
|
||||||
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
|
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
|
||||||
NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
|
NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
|
||||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
|
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
|
||||||
NS_IMETHOD GetExtendedOrigin(nsACString& aExtendedOrigin);
|
NS_IMETHOD GetJarPrefix(nsACString& aJarPrefix);
|
||||||
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus);
|
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus);
|
||||||
NS_IMETHOD GetAppId(uint32_t* aAppStatus);
|
NS_IMETHOD GetAppId(uint32_t* aAppStatus);
|
||||||
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
|
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
|
||||||
|
|
|
@ -526,9 +526,9 @@ public:
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
void
|
void
|
||||||
GetExtendedOrigin(nsIURI* aURI, uint32_t aAppid,
|
GetJarPrefix(uint32_t aAppid,
|
||||||
bool aInMozBrowser,
|
bool aInMozBrowser,
|
||||||
nsACString& aExtendedOrigin);
|
nsACString& aJarPrefix);
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
|
|
@ -259,9 +259,10 @@ nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsP
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNullPrincipal::GetExtendedOrigin(nsACString& aExtendedOrigin)
|
nsNullPrincipal::GetJarPrefix(nsACString& aJarPrefix)
|
||||||
{
|
{
|
||||||
return GetOrigin(getter_Copies(aExtendedOrigin));
|
aJarPrefix.Truncate();
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
@ -424,11 +424,11 @@ nsPrincipal::SetDomain(nsIURI* aDomain)
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsPrincipal::GetExtendedOrigin(nsACString& aExtendedOrigin)
|
nsPrincipal::GetJarPrefix(nsACString& aJarPrefix)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
MOZ_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||||
|
|
||||||
mozilla::GetExtendedOrigin(mCodebase, mAppId, mInMozBrowser, aExtendedOrigin);
|
mozilla::GetJarPrefix(mAppId, mInMozBrowser, aJarPrefix);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,9 +773,10 @@ nsExpandedPrincipal::GetWhiteList(nsTArray<nsCOMPtr<nsIPrincipal> >** aWhiteList
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsExpandedPrincipal::GetExtendedOrigin(nsACString& aExtendedOrigin)
|
nsExpandedPrincipal::GetJarPrefix(nsACString& aJarPrefix)
|
||||||
{
|
{
|
||||||
return GetOrigin(getter_Copies(aExtendedOrigin));
|
aJarPrefix.Truncate();
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
@ -2778,32 +2778,26 @@ nsScriptSecurityManager::InitPrefs()
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
void
|
void
|
||||||
GetExtendedOrigin(nsIURI* aURI, uint32_t aAppId, bool aInMozBrowser,
|
GetJarPrefix(uint32_t aAppId, bool aInMozBrowser, nsACString& aJarPrefix)
|
||||||
nsACString& aExtendedOrigin)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aURI);
|
|
||||||
MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||||
|
|
||||||
if (aAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
if (aAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||||
aAppId = nsIScriptSecurityManager::NO_APP_ID;
|
aAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoCString origin;
|
aJarPrefix.Truncate();
|
||||||
nsPrincipal::GetOriginForURI(aURI, getter_Copies(origin));
|
|
||||||
|
|
||||||
// Fallback.
|
// Fallback.
|
||||||
if (aAppId == nsIScriptSecurityManager::NO_APP_ID && !aInMozBrowser) {
|
if (aAppId == nsIScriptSecurityManager::NO_APP_ID && !aInMozBrowser) {
|
||||||
aExtendedOrigin.Assign(origin);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// aExtendedOrigin = appId + "+" + { 't', 'f' } "+" + origin;
|
// aJarPrefix = appId + "+" + { 't', 'f' } + "+";
|
||||||
aExtendedOrigin.Truncate();
|
aJarPrefix.AppendInt(aAppId);
|
||||||
aExtendedOrigin.AppendInt(aAppId);
|
aJarPrefix.Append('+');
|
||||||
aExtendedOrigin.Append('+');
|
aJarPrefix.Append(aInMozBrowser ? 't' : 'f');
|
||||||
aExtendedOrigin.Append(aInMozBrowser ? 't' : 'f');
|
aJarPrefix.Append('+');
|
||||||
aExtendedOrigin.Append('+');
|
|
||||||
aExtendedOrigin.Append(origin);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2811,13 +2805,12 @@ GetExtendedOrigin(nsIURI* aURI, uint32_t aAppId, bool aInMozBrowser,
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsScriptSecurityManager::GetExtendedOrigin(nsIURI* aURI,
|
nsScriptSecurityManager::GetJarPrefix(uint32_t aAppId,
|
||||||
uint32_t aAppId,
|
bool aInMozBrowser,
|
||||||
bool aInMozBrowser,
|
nsACString& aJarPrefix)
|
||||||
nsACString& aExtendedOrigin)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||||
|
|
||||||
mozilla::GetExtendedOrigin(aURI, aAppId, aInMozBrowser, aExtendedOrigin);
|
mozilla::GetJarPrefix(aAppId, aInMozBrowser, aJarPrefix);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,9 +166,10 @@ nsSystemPrincipal::SetSecurityPolicy(void* aSecurityPolicy)
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsSystemPrincipal::GetExtendedOrigin(nsACString& aExtendedOrigin)
|
nsSystemPrincipal::GetJarPrefix(nsACString& aJarPrefix)
|
||||||
{
|
{
|
||||||
return GetOrigin(getter_Copies(aExtendedOrigin));
|
aJarPrefix.Truncate();
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
@ -11,8 +11,8 @@ MOCHITEST_FILES = test_bug423375.html \
|
||||||
test_app_principal_equality.html \
|
test_app_principal_equality.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# extendedOrigin test doesn't work on Windows, see bug 776296.
|
# jarPrefix test doesn't work on Windows, see bug 776296.
|
||||||
ifneq ($(OS_ARCH),WINNT)
|
ifneq ($(OS_ARCH),WINNT)
|
||||||
MOCHITEST_CHROME_FILES = test_principal_extendedorigin_appid_appstatus.html \
|
MOCHITEST_CHROME_FILES = test_principal_jarprefix_origin_appid_appstatus.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -5,7 +5,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=758258
|
||||||
-->
|
-->
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Test for nsIPrincipal extendedOrigin, appStatus and appId</title>
|
<title>Test for nsIPrincipal jarPrefix, origin, appStatus and appId</title>
|
||||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||||
</head>
|
</head>
|
||||||
|
@ -294,20 +294,20 @@ function checkIFrame(aFrame, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.isapp && !data.browser) {
|
if (!data.isapp && !data.browser) {
|
||||||
is(principal.extendedOrigin, principal.origin,
|
is(principal.jarPrefix, "",
|
||||||
'extendedOrigin should return the origin for non-app and non-browsers principals');
|
'jarPrefix should return an empty string for non-app and non-browsers principals');
|
||||||
} else {
|
} else {
|
||||||
isnot(principal.extendedOrigin, principal.origin,
|
isnot(principal.jarPrefix, "",
|
||||||
'extendedOrigin should not return the origin for apps or mozbrowsers');
|
'jarPrefix should not return an empty string for apps or mozbrowsers');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.test.indexOf("eo-unique") != -1) {
|
if (data.test.indexOf("eo-unique") != -1) {
|
||||||
is(eoList.indexOf(principal.extendedOrigin), -1,
|
is(eoList.indexOf(principal.jarPrefix + principal.origin), -1,
|
||||||
"extendedOrigin should be unique");
|
"extended origin should be unique");
|
||||||
}
|
}
|
||||||
if (data.test.indexOf("eo-as-last") != -1) {
|
if (data.test.indexOf("eo-as-last") != -1) {
|
||||||
is(principal.extendedOrigin, eoList[eoList.length-1],
|
is(principal.jarPrefix + principal.origin, eoList[eoList.length-1],
|
||||||
"extendedOrigin should be the same as the last inserted one");
|
"extended origin should be the same as the last inserted one");
|
||||||
}
|
}
|
||||||
|
|
||||||
is(principal.isInBrowserElement, !!data.browser,
|
is(principal.isInBrowserElement, !!data.browser,
|
||||||
|
@ -325,17 +325,19 @@ function checkIFrame(aFrame, data) {
|
||||||
"check childPrincipal.isInBrowserElement");
|
"check childPrincipal.isInBrowserElement");
|
||||||
|
|
||||||
if (data.test.indexOf("child-has-same-eo") != -1) {
|
if (data.test.indexOf("child-has-same-eo") != -1) {
|
||||||
is(childPrincipal.extendedOrigin, principal.extendedOrigin,
|
is(childPrincipal.jarPrefix + childPrincipal.origin,
|
||||||
"child should have the same extendedOrigin as parent");
|
principal.jarPrefix + principal.origin,
|
||||||
|
"child should have the same extended origin as parent");
|
||||||
is(childPrincipal.appStatus, principal.appStatus,
|
is(childPrincipal.appStatus, principal.appStatus,
|
||||||
"child should have the same appStatus if it has the same extendedOrigin");
|
"child should have the same appStatus if it has the same extended origin");
|
||||||
is(childPrincipal.appId, principal.appId,
|
is(childPrincipal.appId, principal.appId,
|
||||||
"child should have the same appId if it has the same extendedOrigin");
|
"child should have the same appId if it has the same extended origin");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.test.indexOf("child-has-different-eo") != -1) {
|
if (data.test.indexOf("child-has-different-eo") != -1) {
|
||||||
isnot(childPrincipal.extendedOrigin, principal.extendedOrigin,
|
isnot(childPrincipal.jarPrefix + childPrincipal.origin,
|
||||||
"child should not have the same extendedOrigin as parent");
|
principal.jarPrefix + principal.origin,
|
||||||
|
"child should not have the same extended origin as parent");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.test.indexOf("child-has-same-appstatus") != -1) {
|
if (data.test.indexOf("child-has-same-appstatus") != -1) {
|
||||||
|
@ -359,7 +361,7 @@ function checkIFrame(aFrame, data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eoList.push(principal.extendedOrigin);
|
eoList.push(principal.jarPrefix + principal.origin);
|
||||||
|
|
||||||
checkedCount++;
|
checkedCount++;
|
||||||
if (checkedCount == checksTodo) {
|
if (checkedCount == checksTodo) {
|
||||||
|
@ -373,8 +375,10 @@ function checkIFrame(aFrame, data) {
|
||||||
|
|
||||||
is('appStatus' in document.nodePrincipal, true,
|
is('appStatus' in document.nodePrincipal, true,
|
||||||
'appStatus should be present in nsIPrincipal');
|
'appStatus should be present in nsIPrincipal');
|
||||||
is('extendedOrigin' in document.nodePrincipal, true,
|
is('jarPrefix' in document.nodePrincipal, true,
|
||||||
'extendedOrigin should be present in nsIPrincipal');
|
'jarPrefix should be present in nsIPrincipal');
|
||||||
|
is('origin' in document.nodePrincipal, true,
|
||||||
|
'origin should be present in nsIPrincipal');
|
||||||
is('appId' in document.nodePrincipal, true,
|
is('appId' in document.nodePrincipal, true,
|
||||||
'appId should be present in nsIPrincipal');
|
'appId should be present in nsIPrincipal');
|
||||||
|
|
|
@ -228,7 +228,8 @@ this.PermissionsTable = { geolocation: {
|
||||||
substitute: [
|
substitute: [
|
||||||
"indexedDB-unlimited",
|
"indexedDB-unlimited",
|
||||||
"offline-app",
|
"offline-app",
|
||||||
"pin-app"
|
"pin-app",
|
||||||
|
"default-persistent-storage"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"background-sensors": {
|
"background-sensors": {
|
||||||
|
|
|
@ -459,7 +459,7 @@ this.DOMApplicationRegistry = {
|
||||||
debug("Fixing indexedDb folder names");
|
debug("Fixing indexedDb folder names");
|
||||||
let idbDir = FileUtils.getDir("indexedDBPDir", ["indexedDB"]);
|
let idbDir = FileUtils.getDir("indexedDBPDir", ["indexedDB"]);
|
||||||
|
|
||||||
if (!idbDir.isDirectory()) {
|
if (!idbDir.exists() || !idbDir.isDirectory()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,9 @@
|
||||||
#include "mozilla/layers/ShadowLayers.h"
|
#include "mozilla/layers/ShadowLayers.h"
|
||||||
|
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
|
#include "mozilla/dom/IDBFactoryBinding.h"
|
||||||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
||||||
|
#include "mozilla/dom/quota/PersistenceType.h"
|
||||||
#include "mozilla/dom/quota/QuotaManager.h"
|
#include "mozilla/dom/quota/QuotaManager.h"
|
||||||
#include "nsDOMBlobBuilder.h"
|
#include "nsDOMBlobBuilder.h"
|
||||||
#include "nsIDOMFileHandle.h"
|
#include "nsIDOMFileHandle.h"
|
||||||
|
@ -2826,9 +2828,10 @@ nsDOMWindowUtils::GetFileId(const JS::Value& aFile, JSContext* aCx,
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName,
|
nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName, int64_t aId,
|
||||||
int64_t aId, int32_t* aRefCnt,
|
const jsval& aOptions,
|
||||||
int32_t* aDBRefCnt, int32_t* aSliceRefCnt,
|
int32_t* aRefCnt, int32_t* aDBRefCnt,
|
||||||
|
int32_t* aSliceRefCnt, JSContext* aCx,
|
||||||
bool* aResult)
|
bool* aResult)
|
||||||
{
|
{
|
||||||
if (!nsContentUtils::IsCallerChrome()) {
|
if (!nsContentUtils::IsCallerChrome()) {
|
||||||
|
@ -2839,15 +2842,28 @@ nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName,
|
||||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
nsCString origin;
|
nsCString origin;
|
||||||
nsresult rv = quota::QuotaManager::GetASCIIOriginFromWindow(window, origin);
|
quota::PersistenceType defaultPersistenceType;
|
||||||
|
nsresult rv =
|
||||||
|
quota::QuotaManager::GetInfoFromWindow(window, nullptr, &origin, nullptr,
|
||||||
|
&defaultPersistenceType);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
IDBOpenDBOptions options;
|
||||||
|
JS::Rooted<JS::Value> optionsVal(aCx, aOptions);
|
||||||
|
if (!options.Init(aCx, optionsVal)) {
|
||||||
|
return NS_ERROR_TYPE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
quota::PersistenceType persistenceType =
|
||||||
|
quota::PersistenceTypeFromStorage(options.mStorage, defaultPersistenceType);
|
||||||
|
|
||||||
nsRefPtr<indexedDB::IndexedDatabaseManager> mgr =
|
nsRefPtr<indexedDB::IndexedDatabaseManager> mgr =
|
||||||
indexedDB::IndexedDatabaseManager::Get();
|
indexedDB::IndexedDatabaseManager::Get();
|
||||||
|
|
||||||
if (mgr) {
|
if (mgr) {
|
||||||
rv = mgr->BlockAndGetFileReferences(origin, aDatabaseName, aId, aRefCnt,
|
rv = mgr->BlockAndGetFileReferences(persistenceType, origin, aDatabaseName,
|
||||||
aDBRefCnt, aSliceRefCnt, aResult);
|
aId, aRefCnt, aDBRefCnt, aSliceRefCnt,
|
||||||
|
aResult);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -64,6 +64,28 @@ public:
|
||||||
return mIsNull;
|
return mIsNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Equals(const Nullable<T>& aOtherNullable) const
|
||||||
|
{
|
||||||
|
return (mIsNull && aOtherNullable.mIsNull) ||
|
||||||
|
(!mIsNull && !aOtherNullable.mIsNull &&
|
||||||
|
mValue == aOtherNullable.mValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Nullable<T>& aOtherNullable) const
|
||||||
|
{
|
||||||
|
return Equals(aOtherNullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Nullable<T>& aOtherNullable) const
|
||||||
|
{
|
||||||
|
return !Equals(aOtherNullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool() const
|
||||||
|
{
|
||||||
|
return !mIsNull;
|
||||||
|
}
|
||||||
|
|
||||||
// Make it possible to use a const Nullable of an array type with other
|
// Make it possible to use a const Nullable of an array type with other
|
||||||
// array types.
|
// array types.
|
||||||
template<typename U>
|
template<typename U>
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "mozilla/dom/quota/QuotaManager.h"
|
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
|
|
||||||
|
@ -165,10 +164,7 @@ CheckPermissionsHelper::Run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
|
return helper->DispatchToIOThread();
|
||||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
|
||||||
|
|
||||||
return helper->Dispatch(quotaManager->IOThread());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_ASSERTION(permission == PERMISSION_PROMPT ||
|
NS_ASSERTION(permission == PERMISSION_PROMPT ||
|
||||||
|
|
|
@ -30,17 +30,18 @@ public:
|
||||||
NS_DECL_NSIOBSERVER
|
NS_DECL_NSIOBSERVER
|
||||||
|
|
||||||
CheckPermissionsHelper(OpenDatabaseHelper* aHelper,
|
CheckPermissionsHelper(OpenDatabaseHelper* aHelper,
|
||||||
nsIDOMWindow* aWindow,
|
nsIDOMWindow* aWindow)
|
||||||
bool aForDeletion)
|
|
||||||
: mHelper(aHelper),
|
: mHelper(aHelper),
|
||||||
mWindow(aWindow),
|
mWindow(aWindow),
|
||||||
// If we're trying to delete the database, we should never prompt the user.
|
// If we're trying to delete the database, we should never prompt the user.
|
||||||
// Anything that would prompt is translated to denied.
|
// Anything that would prompt is translated to denied.
|
||||||
mPromptAllowed(!aForDeletion),
|
mPromptAllowed(!aHelper->mForDeletion),
|
||||||
mHasPrompted(false),
|
mHasPrompted(false),
|
||||||
mPromptResult(0)
|
mPromptResult(0)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aHelper, "Null pointer!");
|
NS_ASSERTION(aHelper, "Null pointer!");
|
||||||
|
NS_ASSERTION(aHelper->mPersistenceType == quota::PERSISTENCE_TYPE_PERSISTENT,
|
||||||
|
"Checking permission for non persistent databases?!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
|
|
||||||
#include "mozilla/dom/quota/QuotaManager.h"
|
#include "mozilla/dom/quota/QuotaManager.h"
|
||||||
#include "mozilla/dom/quota/UsageRunnable.h"
|
#include "mozilla/dom/quota/UsageInfo.h"
|
||||||
#include "mozilla/dom/quota/Utilities.h"
|
#include "mozilla/dom/quota/Utilities.h"
|
||||||
|
|
||||||
#include "IDBDatabase.h"
|
#include "IDBDatabase.h"
|
||||||
|
@ -45,12 +45,14 @@ NS_IMPL_ADDREF(mozilla::dom::indexedDB::Client)
|
||||||
NS_IMPL_RELEASE(mozilla::dom::indexedDB::Client)
|
NS_IMPL_RELEASE(mozilla::dom::indexedDB::Client)
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
Client::InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable)
|
Client::InitOrigin(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin, UsageInfo* aUsageInfo)
|
||||||
{
|
{
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> directory;
|
nsCOMPtr<nsIFile> directory;
|
||||||
nsresult rv = GetDirectory(aOrigin, getter_AddRefs(directory));
|
nsresult rv =
|
||||||
|
GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// We need to see if there are any files in the directory already. If they
|
// We need to see if there are any files in the directory already. If they
|
||||||
|
@ -67,7 +69,7 @@ Client::InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable)
|
||||||
|
|
||||||
bool hasMore;
|
bool hasMore;
|
||||||
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
|
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
|
||||||
hasMore && (!aUsageRunnable || !aUsageRunnable->Canceled())) {
|
hasMore && (!aUsageInfo || !aUsageInfo->Canceled())) {
|
||||||
nsCOMPtr<nsISupports> entry;
|
nsCOMPtr<nsISupports> entry;
|
||||||
rv = entries->GetNext(getter_AddRefs(entry));
|
rv = entries->GetNext(getter_AddRefs(entry));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
@ -83,11 +85,9 @@ Client::InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
|
||||||
if (leafName.EqualsLiteral(DSSTORE_FILE_NAME)) {
|
if (leafName.EqualsLiteral(DSSTORE_FILE_NAME)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool isDirectory;
|
bool isDirectory;
|
||||||
rv = file->IsDirectory(&isDirectory);
|
rv = file->IsDirectory(&isDirectory);
|
||||||
|
@ -113,21 +113,24 @@ Client::InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable)
|
||||||
rv = fmDirectory->Append(dbBaseFilename);
|
rv = fmDirectory->Append(dbBaseFilename);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = FileManager::InitDirectory(fmDirectory, file, aOrigin);
|
rv = FileManager::InitDirectory(fmDirectory, file, aPersistenceType, aGroup,
|
||||||
|
aOrigin);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (aUsageRunnable) {
|
if (aUsageInfo) {
|
||||||
int64_t fileSize;
|
int64_t fileSize;
|
||||||
rv = file->GetFileSize(&fileSize);
|
rv = file->GetFileSize(&fileSize);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
aUsageRunnable->AppendToDatabaseUsage(uint64_t(fileSize));
|
NS_ASSERTION(fileSize >= 0, "Negative size?!");
|
||||||
|
|
||||||
|
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
|
||||||
|
|
||||||
uint64_t usage;
|
uint64_t usage;
|
||||||
rv = FileManager::GetUsage(fmDirectory, &usage);
|
rv = FileManager::GetUsage(fmDirectory, &usage);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
aUsageRunnable->AppendToFileUsage(usage);
|
aUsageInfo->AppendToFileUsage(usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
validSubdirs.PutEntry(dbBaseFilename);
|
validSubdirs.PutEntry(dbBaseFilename);
|
||||||
|
@ -167,30 +170,33 @@ Client::InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
Client::GetUsageForOrigin(const nsACString& aOrigin,
|
Client::GetUsageForOrigin(PersistenceType aPersistenceType,
|
||||||
UsageRunnable* aUsageRunnable)
|
const nsACString& aGroup, const nsACString& aOrigin,
|
||||||
|
UsageInfo* aUsageInfo)
|
||||||
{
|
{
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
NS_ASSERTION(aUsageRunnable, "Null pointer!");
|
NS_ASSERTION(aUsageInfo, "Null pointer!");
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> directory;
|
nsCOMPtr<nsIFile> directory;
|
||||||
nsresult rv = GetDirectory(aOrigin, getter_AddRefs(directory));
|
nsresult rv =
|
||||||
|
GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = GetUsageForDirectoryInternal(directory, aUsageRunnable, true);
|
rv = GetUsageForDirectoryInternal(directory, aUsageInfo, true);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Client::OnOriginClearCompleted(const nsACString& aPattern)
|
Client::OnOriginClearCompleted(PersistenceType aPersistenceType,
|
||||||
|
const OriginOrPatternString& aOriginOrPattern)
|
||||||
{
|
{
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
|
|
||||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||||
if (mgr) {
|
if (mgr) {
|
||||||
mgr->InvalidateFileManagersForPattern(aPattern);
|
mgr->InvalidateFileManagers(aPersistenceType, aOriginOrPattern);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,14 +281,15 @@ Client::ShutdownTransactionService()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
Client::GetDirectory(const nsACString& aOrigin, nsIFile** aDirectory)
|
Client::GetDirectory(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aOrigin, nsIFile** aDirectory)
|
||||||
{
|
{
|
||||||
QuotaManager* quotaManager = QuotaManager::Get();
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
NS_ASSERTION(quotaManager, "This should never fail!");
|
NS_ASSERTION(quotaManager, "This should never fail!");
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> directory;
|
nsCOMPtr<nsIFile> directory;
|
||||||
nsresult rv =
|
nsresult rv = quotaManager->GetDirectoryForOrigin(aPersistenceType, aOrigin,
|
||||||
quotaManager->GetDirectoryForOrigin(aOrigin, getter_AddRefs(directory));
|
getter_AddRefs(directory));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
NS_ASSERTION(directory, "What?");
|
NS_ASSERTION(directory, "What?");
|
||||||
|
@ -296,11 +303,11 @@ Client::GetDirectory(const nsACString& aOrigin, nsIFile** aDirectory)
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
Client::GetUsageForDirectoryInternal(nsIFile* aDirectory,
|
Client::GetUsageForDirectoryInternal(nsIFile* aDirectory,
|
||||||
UsageRunnable* aUsageRunnable,
|
UsageInfo* aUsageInfo,
|
||||||
bool aDatabaseFiles)
|
bool aDatabaseFiles)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aDirectory, "Null pointer!");
|
NS_ASSERTION(aDirectory, "Null pointer!");
|
||||||
NS_ASSERTION(aUsageRunnable, "Null pointer!");
|
NS_ASSERTION(aUsageInfo, "Null pointer!");
|
||||||
|
|
||||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||||
nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
|
nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
|
||||||
|
@ -312,7 +319,7 @@ Client::GetUsageForDirectoryInternal(nsIFile* aDirectory,
|
||||||
|
|
||||||
bool hasMore;
|
bool hasMore;
|
||||||
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
|
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
|
||||||
hasMore && !aUsageRunnable->Canceled()) {
|
hasMore && !aUsageInfo->Canceled()) {
|
||||||
nsCOMPtr<nsISupports> entry;
|
nsCOMPtr<nsISupports> entry;
|
||||||
rv = entries->GetNext(getter_AddRefs(entry));
|
rv = entries->GetNext(getter_AddRefs(entry));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
@ -326,7 +333,7 @@ Client::GetUsageForDirectoryInternal(nsIFile* aDirectory,
|
||||||
|
|
||||||
if (isDirectory) {
|
if (isDirectory) {
|
||||||
if (aDatabaseFiles) {
|
if (aDatabaseFiles) {
|
||||||
rv = GetUsageForDirectoryInternal(file, aUsageRunnable, false);
|
rv = GetUsageForDirectoryInternal(file, aUsageInfo, false);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -349,10 +356,10 @@ Client::GetUsageForDirectoryInternal(nsIFile* aDirectory,
|
||||||
NS_ASSERTION(fileSize >= 0, "Negative size?!");
|
NS_ASSERTION(fileSize >= 0, "Negative size?!");
|
||||||
|
|
||||||
if (aDatabaseFiles) {
|
if (aDatabaseFiles) {
|
||||||
aUsageRunnable->AppendToDatabaseUsage(uint64_t(fileSize));
|
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
aUsageRunnable->AppendToFileUsage(uint64_t(fileSize));
|
aUsageInfo->AppendToFileUsage(uint64_t(fileSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
|
@ -18,7 +18,9 @@ BEGIN_INDEXEDDB_NAMESPACE
|
||||||
|
|
||||||
class Client : public mozilla::dom::quota::Client
|
class Client : public mozilla::dom::quota::Client
|
||||||
{
|
{
|
||||||
typedef mozilla::dom::quota::UsageRunnable UsageRunnable;
|
typedef mozilla::dom::quota::OriginOrPatternString OriginOrPatternString;
|
||||||
|
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||||
|
typedef mozilla::dom::quota::UsageInfo UsageInfo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NS_IMETHOD_(nsrefcnt)
|
NS_IMETHOD_(nsrefcnt)
|
||||||
|
@ -34,15 +36,21 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual nsresult
|
virtual nsresult
|
||||||
InitOrigin(const nsACString& aOrigin,
|
InitOrigin(PersistenceType aPersistenceType,
|
||||||
UsageRunnable* aUsageRunnable) MOZ_OVERRIDE;
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin,
|
||||||
|
UsageInfo* aUsageInfo) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual nsresult
|
virtual nsresult
|
||||||
GetUsageForOrigin(const nsACString& aOrigin,
|
GetUsageForOrigin(PersistenceType aPersistenceType,
|
||||||
UsageRunnable* aUsageRunnable) MOZ_OVERRIDE;
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin,
|
||||||
|
UsageInfo* aUsageInfo) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
OnOriginClearCompleted(const nsACString& aPattern) MOZ_OVERRIDE;
|
OnOriginClearCompleted(PersistenceType aPersistenceType,
|
||||||
|
const OriginOrPatternString& aOriginOrPattern)
|
||||||
|
MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
ReleaseIOThreadObjects() MOZ_OVERRIDE;
|
ReleaseIOThreadObjects() MOZ_OVERRIDE;
|
||||||
|
@ -71,11 +79,12 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsresult
|
nsresult
|
||||||
GetDirectory(const nsACString& aOrigin, nsIFile** aDirectory);
|
GetDirectory(PersistenceType aPersistenceType, const nsACString& aOrigin,
|
||||||
|
nsIFile** aDirectory);
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
GetUsageForDirectoryInternal(nsIFile* aDirectory,
|
GetUsageForDirectoryInternal(nsIFile* aDirectory,
|
||||||
UsageRunnable* aUsageRunnable,
|
UsageInfo* aUsageInfo,
|
||||||
bool aDatabaseFiles);
|
bool aDatabaseFiles);
|
||||||
|
|
||||||
nsAutoRefCnt mRefCnt;
|
nsAutoRefCnt mRefCnt;
|
||||||
|
|
|
@ -250,8 +250,10 @@ DatabaseInfo::Clone()
|
||||||
|
|
||||||
dbInfo->cloned = true;
|
dbInfo->cloned = true;
|
||||||
dbInfo->name = name;
|
dbInfo->name = name;
|
||||||
|
dbInfo->group = group;
|
||||||
dbInfo->origin = origin;
|
dbInfo->origin = origin;
|
||||||
dbInfo->version = version;
|
dbInfo->version = version;
|
||||||
|
dbInfo->persistenceType = persistenceType;
|
||||||
dbInfo->id = id;
|
dbInfo->id = id;
|
||||||
dbInfo->filePath = filePath;
|
dbInfo->filePath = filePath;
|
||||||
dbInfo->nextObjectStoreId = nextObjectStoreId;
|
dbInfo->nextObjectStoreId = nextObjectStoreId;
|
||||||
|
|
|
@ -9,13 +9,14 @@
|
||||||
|
|
||||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/quota/PersistenceType.h"
|
||||||
|
#include "nsRefPtrHashtable.h"
|
||||||
|
#include "nsHashKeys.h"
|
||||||
|
|
||||||
#include "mozilla/dom/indexedDB/Key.h"
|
#include "mozilla/dom/indexedDB/Key.h"
|
||||||
#include "mozilla/dom/indexedDB/KeyPath.h"
|
#include "mozilla/dom/indexedDB/KeyPath.h"
|
||||||
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
|
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
|
||||||
|
|
||||||
#include "nsRefPtrHashtable.h"
|
|
||||||
#include "nsHashKeys.h"
|
|
||||||
|
|
||||||
BEGIN_INDEXEDDB_NAMESPACE
|
BEGIN_INDEXEDDB_NAMESPACE
|
||||||
|
|
||||||
class IndexedDBDatabaseChild;
|
class IndexedDBDatabaseChild;
|
||||||
|
@ -26,6 +27,8 @@ typedef nsRefPtrHashtable<nsStringHashKey, ObjectStoreInfo>
|
||||||
|
|
||||||
struct DatabaseInfoGuts
|
struct DatabaseInfoGuts
|
||||||
{
|
{
|
||||||
|
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||||
|
|
||||||
DatabaseInfoGuts()
|
DatabaseInfoGuts()
|
||||||
: nextObjectStoreId(1), nextIndexId(1)
|
: nextObjectStoreId(1), nextIndexId(1)
|
||||||
{ }
|
{ }
|
||||||
|
@ -33,16 +36,20 @@ struct DatabaseInfoGuts
|
||||||
bool operator==(const DatabaseInfoGuts& aOther) const
|
bool operator==(const DatabaseInfoGuts& aOther) const
|
||||||
{
|
{
|
||||||
return this->name == aOther.name &&
|
return this->name == aOther.name &&
|
||||||
|
this->group == aOther.group &&
|
||||||
this->origin == aOther.origin &&
|
this->origin == aOther.origin &&
|
||||||
this->version == aOther.version &&
|
this->version == aOther.version &&
|
||||||
|
this->persistenceType == aOther.persistenceType &&
|
||||||
this->nextObjectStoreId == aOther.nextObjectStoreId &&
|
this->nextObjectStoreId == aOther.nextObjectStoreId &&
|
||||||
this->nextIndexId == aOther.nextIndexId;
|
this->nextIndexId == aOther.nextIndexId;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make sure to update ipc/SerializationHelpers.h when changing members here!
|
// Make sure to update ipc/SerializationHelpers.h when changing members here!
|
||||||
nsString name;
|
nsString name;
|
||||||
|
nsCString group;
|
||||||
nsCString origin;
|
nsCString origin;
|
||||||
uint64_t version;
|
uint64_t version;
|
||||||
|
PersistenceType persistenceType;
|
||||||
int64_t nextObjectStoreId;
|
int64_t nextObjectStoreId;
|
||||||
int64_t nextIndexId;
|
int64_t nextIndexId;
|
||||||
};
|
};
|
||||||
|
|
|
@ -266,6 +266,8 @@ FileManager::GetFileForId(nsIFile* aDirectory, int64_t aId)
|
||||||
nsresult
|
nsresult
|
||||||
FileManager::InitDirectory(nsIFile* aDirectory,
|
FileManager::InitDirectory(nsIFile* aDirectory,
|
||||||
nsIFile* aDatabaseFile,
|
nsIFile* aDatabaseFile,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
const nsACString& aOrigin)
|
const nsACString& aOrigin)
|
||||||
{
|
{
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
|
@ -311,7 +313,8 @@ FileManager::InitDirectory(nsIFile* aDirectory,
|
||||||
if (hasElements) {
|
if (hasElements) {
|
||||||
nsCOMPtr<mozIStorageConnection> connection;
|
nsCOMPtr<mozIStorageConnection> connection;
|
||||||
rv = OpenDatabaseHelper::CreateDatabaseConnection(aDatabaseFile,
|
rv = OpenDatabaseHelper::CreateDatabaseConnection(aDatabaseFile,
|
||||||
aDirectory, NullString(), aOrigin, getter_AddRefs(connection));
|
aDirectory, NullString(), aPersistenceType, aGroup, aOrigin,
|
||||||
|
getter_AddRefs(connection));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
mozStorageTransaction transaction(connection, false);
|
mozStorageTransaction transaction(connection, false);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "nsIDOMFile.h"
|
#include "nsIDOMFile.h"
|
||||||
#include "nsIFile.h"
|
#include "nsIFile.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/quota/PersistenceType.h"
|
||||||
#include "mozilla/dom/quota/StoragePrivilege.h"
|
#include "mozilla/dom/quota/StoragePrivilege.h"
|
||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
|
|
||||||
|
@ -25,13 +26,16 @@ class FileManager
|
||||||
{
|
{
|
||||||
friend class FileInfo;
|
friend class FileInfo;
|
||||||
|
|
||||||
|
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||||
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
|
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileManager(const nsACString& aOrigin, StoragePrivilege aPrivilege,
|
FileManager(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin, StoragePrivilege aPrivilege,
|
||||||
const nsAString& aDatabaseName)
|
const nsAString& aDatabaseName)
|
||||||
: mOrigin(aOrigin), mPrivilege(aPrivilege), mDatabaseName(aDatabaseName),
|
: mPersistenceType(aPersistenceType), mGroup(aGroup), mOrigin(aOrigin),
|
||||||
mLastFileId(0), mInvalidated(false)
|
mPrivilege(aPrivilege), mDatabaseName(aDatabaseName), mLastFileId(0),
|
||||||
|
mInvalidated(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~FileManager()
|
~FileManager()
|
||||||
|
@ -39,6 +43,16 @@ public:
|
||||||
|
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FileManager)
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FileManager)
|
||||||
|
|
||||||
|
PersistenceType Type()
|
||||||
|
{
|
||||||
|
return mPersistenceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nsACString& Group() const
|
||||||
|
{
|
||||||
|
return mGroup;
|
||||||
|
}
|
||||||
|
|
||||||
const nsACString& Origin() const
|
const nsACString& Origin() const
|
||||||
{
|
{
|
||||||
return mOrigin;
|
return mOrigin;
|
||||||
|
@ -79,11 +93,15 @@ public:
|
||||||
|
|
||||||
static nsresult InitDirectory(nsIFile* aDirectory,
|
static nsresult InitDirectory(nsIFile* aDirectory,
|
||||||
nsIFile* aDatabaseFile,
|
nsIFile* aDatabaseFile,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
const nsACString& aOrigin);
|
const nsACString& aOrigin);
|
||||||
|
|
||||||
static nsresult GetUsage(nsIFile* aDirectory, uint64_t* aUsage);
|
static nsresult GetUsage(nsIFile* aDirectory, uint64_t* aUsage);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
PersistenceType mPersistenceType;
|
||||||
|
nsCString mGroup;
|
||||||
nsCString mOrigin;
|
nsCString mOrigin;
|
||||||
StoragePrivilege mPrivilege;
|
StoragePrivilege mPrivilege;
|
||||||
nsString mDatabaseName;
|
nsString mDatabaseName;
|
||||||
|
|
|
@ -197,6 +197,8 @@ IDBDatabase::Create(IDBWrapperCache* aOwnerCache,
|
||||||
db->mDatabaseId = databaseInfo->id;
|
db->mDatabaseId = databaseInfo->id;
|
||||||
db->mName = databaseInfo->name;
|
db->mName = databaseInfo->name;
|
||||||
db->mFilePath = databaseInfo->filePath;
|
db->mFilePath = databaseInfo->filePath;
|
||||||
|
db->mPersistenceType = databaseInfo->persistenceType;
|
||||||
|
db->mGroup = databaseInfo->group;
|
||||||
databaseInfo.swap(db->mDatabaseInfo);
|
databaseInfo.swap(db->mDatabaseInfo);
|
||||||
db->mASCIIOrigin = aASCIIOrigin;
|
db->mASCIIOrigin = aASCIIOrigin;
|
||||||
db->mFileManager = aFileManager;
|
db->mFileManager = aFileManager;
|
||||||
|
@ -227,8 +229,7 @@ IDBDatabase::FromStorage(nsIOfflineStorage* aStorage)
|
||||||
}
|
}
|
||||||
|
|
||||||
IDBDatabase::IDBDatabase()
|
IDBDatabase::IDBDatabase()
|
||||||
: mDatabaseId(0),
|
: mActorChild(nullptr),
|
||||||
mActorChild(nullptr),
|
|
||||||
mActorParent(nullptr),
|
mActorParent(nullptr),
|
||||||
mContentParent(nullptr),
|
mContentParent(nullptr),
|
||||||
mInvalidated(false),
|
mInvalidated(false),
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/dom/IDBObjectStoreBinding.h"
|
#include "mozilla/dom/IDBObjectStoreBinding.h"
|
||||||
#include "mozilla/dom/IDBTransactionBinding.h"
|
#include "mozilla/dom/IDBTransactionBinding.h"
|
||||||
|
#include "mozilla/dom/quota/PersistenceType.h"
|
||||||
#include "nsDOMEventTargetHelper.h"
|
#include "nsDOMEventTargetHelper.h"
|
||||||
|
|
||||||
#include "mozilla/dom/indexedDB/FileManager.h"
|
#include "mozilla/dom/indexedDB/FileManager.h"
|
||||||
|
@ -210,6 +211,12 @@ public:
|
||||||
IMPL_EVENT_HANDLER(error)
|
IMPL_EVENT_HANDLER(error)
|
||||||
IMPL_EVENT_HANDLER(versionchange)
|
IMPL_EVENT_HANDLER(versionchange)
|
||||||
|
|
||||||
|
mozilla::dom::StorageType
|
||||||
|
Storage() const
|
||||||
|
{
|
||||||
|
return PersistenceTypeToStorage(mPersistenceType);
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<IDBRequest>
|
already_AddRefed<IDBRequest>
|
||||||
MozCreateFileHandle(const nsAString& aName, const Optional<nsAString>& aType,
|
MozCreateFileHandle(const nsAString& aName, const Optional<nsAString>& aType,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "nsIFile.h"
|
#include "nsIFile.h"
|
||||||
#include "nsIPrincipal.h"
|
#include "nsIPrincipal.h"
|
||||||
#include "nsIScriptContext.h"
|
#include "nsIScriptContext.h"
|
||||||
|
#include "nsIScriptSecurityManager.h"
|
||||||
#include "nsIXPConnect.h"
|
#include "nsIXPConnect.h"
|
||||||
#include "nsIXPCScriptable.h"
|
#include "nsIXPCScriptable.h"
|
||||||
|
|
||||||
|
@ -22,7 +23,6 @@
|
||||||
#include "mozilla/dom/TabChild.h"
|
#include "mozilla/dom/TabChild.h"
|
||||||
#include "mozilla/storage.h"
|
#include "mozilla/storage.h"
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
#include "nsIScriptSecurityManager.h"
|
|
||||||
#include "nsCharSeparatedTokenizer.h"
|
#include "nsCharSeparatedTokenizer.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsCxPusher.h"
|
#include "nsCxPusher.h"
|
||||||
|
@ -51,6 +51,7 @@ USING_QUOTA_NAMESPACE
|
||||||
|
|
||||||
using mozilla::dom::ContentChild;
|
using mozilla::dom::ContentChild;
|
||||||
using mozilla::dom::ContentParent;
|
using mozilla::dom::ContentParent;
|
||||||
|
using mozilla::dom::IDBOpenDBOptions;
|
||||||
using mozilla::dom::NonNull;
|
using mozilla::dom::NonNull;
|
||||||
using mozilla::dom::Optional;
|
using mozilla::dom::Optional;
|
||||||
using mozilla::dom::TabChild;
|
using mozilla::dom::TabChild;
|
||||||
|
@ -70,7 +71,8 @@ struct ObjectStoreInfoMap
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
IDBFactory::IDBFactory()
|
IDBFactory::IDBFactory()
|
||||||
: mOwningObject(nullptr), mActorChild(nullptr), mActorParent(nullptr),
|
: mPrivilege(Content), mDefaultPersistenceType(PERSISTENCE_TYPE_TEMPORARY),
|
||||||
|
mOwningObject(nullptr), mActorChild(nullptr), mActorParent(nullptr),
|
||||||
mContentParent(nullptr), mRootedOwningObject(false)
|
mContentParent(nullptr), mRootedOwningObject(false)
|
||||||
{
|
{
|
||||||
SetIsDOMBinding();
|
SetIsDOMBinding();
|
||||||
|
@ -93,6 +95,7 @@ IDBFactory::~IDBFactory()
|
||||||
// static
|
// static
|
||||||
nsresult
|
nsresult
|
||||||
IDBFactory::Create(nsPIDOMWindow* aWindow,
|
IDBFactory::Create(nsPIDOMWindow* aWindow,
|
||||||
|
const nsACString& aGroup,
|
||||||
const nsACString& aASCIIOrigin,
|
const nsACString& aASCIIOrigin,
|
||||||
ContentParent* aContentParent,
|
ContentParent* aContentParent,
|
||||||
IDBFactory** aFactory)
|
IDBFactory** aFactory)
|
||||||
|
@ -116,18 +119,31 @@ IDBFactory::Create(nsPIDOMWindow* aWindow,
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
|
nsCString group(aGroup);
|
||||||
nsCString origin(aASCIIOrigin);
|
nsCString origin(aASCIIOrigin);
|
||||||
|
StoragePrivilege privilege;
|
||||||
|
PersistenceType defaultPersistenceType;
|
||||||
if (origin.IsEmpty()) {
|
if (origin.IsEmpty()) {
|
||||||
rv = QuotaManager::GetASCIIOriginFromWindow(aWindow, origin);
|
NS_ASSERTION(aGroup.IsEmpty(), "Should be empty too!");
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
// Not allowed.
|
rv = QuotaManager::GetInfoFromWindow(aWindow, &group, &origin, &privilege,
|
||||||
*aFactory = nullptr;
|
&defaultPersistenceType);
|
||||||
return NS_OK;
|
}
|
||||||
}
|
else {
|
||||||
|
rv = QuotaManager::GetInfoFromWindow(aWindow, nullptr, nullptr, &privilege,
|
||||||
|
&defaultPersistenceType);
|
||||||
|
}
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
// Not allowed.
|
||||||
|
*aFactory = nullptr;
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<IDBFactory> factory = new IDBFactory();
|
nsRefPtr<IDBFactory> factory = new IDBFactory();
|
||||||
|
factory->mGroup = group;
|
||||||
factory->mASCIIOrigin = origin;
|
factory->mASCIIOrigin = origin;
|
||||||
|
factory->mPrivilege = privilege;
|
||||||
|
factory->mDefaultPersistenceType = defaultPersistenceType;
|
||||||
factory->mWindow = aWindow;
|
factory->mWindow = aWindow;
|
||||||
factory->mContentParent = aContentParent;
|
factory->mContentParent = aContentParent;
|
||||||
|
|
||||||
|
@ -138,7 +154,7 @@ IDBFactory::Create(nsPIDOMWindow* aWindow,
|
||||||
IndexedDBChild* actor = new IndexedDBChild(origin);
|
IndexedDBChild* actor = new IndexedDBChild(origin);
|
||||||
|
|
||||||
bool allowed;
|
bool allowed;
|
||||||
tabChild->SendPIndexedDBConstructor(actor, origin, &allowed);
|
tabChild->SendPIndexedDBConstructor(actor, group, origin, &allowed);
|
||||||
|
|
||||||
if (!allowed) {
|
if (!allowed) {
|
||||||
actor->Send__delete__(actor);
|
actor->Send__delete__(actor);
|
||||||
|
@ -167,12 +183,20 @@ IDBFactory::Create(JSContext* aCx,
|
||||||
"Not a global object!");
|
"Not a global object!");
|
||||||
NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!");
|
NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!");
|
||||||
|
|
||||||
|
nsCString group;
|
||||||
nsCString origin;
|
nsCString origin;
|
||||||
nsresult rv = QuotaManager::GetASCIIOriginFromWindow(nullptr, origin);
|
StoragePrivilege privilege;
|
||||||
|
PersistenceType defaultPersistenceType;
|
||||||
|
nsresult rv =
|
||||||
|
QuotaManager::GetInfoFromWindow(nullptr, &group, &origin, &privilege,
|
||||||
|
&defaultPersistenceType);
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
nsRefPtr<IDBFactory> factory = new IDBFactory();
|
nsRefPtr<IDBFactory> factory = new IDBFactory();
|
||||||
|
factory->mGroup = group;
|
||||||
factory->mASCIIOrigin = origin;
|
factory->mASCIIOrigin = origin;
|
||||||
|
factory->mPrivilege = privilege;
|
||||||
|
factory->mDefaultPersistenceType = defaultPersistenceType;
|
||||||
factory->mOwningObject = aOwningObject;
|
factory->mOwningObject = aOwningObject;
|
||||||
factory->mContentParent = aContentParent;
|
factory->mContentParent = aContentParent;
|
||||||
|
|
||||||
|
@ -238,7 +262,10 @@ IDBFactory::Create(ContentParent* aContentParent,
|
||||||
|
|
||||||
// static
|
// static
|
||||||
already_AddRefed<nsIFileURL>
|
already_AddRefed<nsIFileURL>
|
||||||
IDBFactory::GetDatabaseFileURL(nsIFile* aDatabaseFile, const nsACString& aOrigin)
|
IDBFactory::GetDatabaseFileURL(nsIFile* aDatabaseFile,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIURI> uri;
|
nsCOMPtr<nsIURI> uri;
|
||||||
nsresult rv = NS_NewFileURI(getter_AddRefs(uri), aDatabaseFile);
|
nsresult rv = NS_NewFileURI(getter_AddRefs(uri), aDatabaseFile);
|
||||||
|
@ -247,7 +274,12 @@ IDBFactory::GetDatabaseFileURL(nsIFile* aDatabaseFile, const nsACString& aOrigin
|
||||||
nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(uri);
|
nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(uri);
|
||||||
NS_ASSERTION(fileUrl, "This should always succeed!");
|
NS_ASSERTION(fileUrl, "This should always succeed!");
|
||||||
|
|
||||||
rv = fileUrl->SetQuery(NS_LITERAL_CSTRING("origin=") + aOrigin);
|
nsAutoCString type;
|
||||||
|
PersistenceTypeToText(aPersistenceType, type);
|
||||||
|
|
||||||
|
rv = fileUrl->SetQuery(NS_LITERAL_CSTRING("persistenceType=") + type +
|
||||||
|
NS_LITERAL_CSTRING("&group=") + aGroup +
|
||||||
|
NS_LITERAL_CSTRING("&origin=") + aOrigin);
|
||||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||||
|
|
||||||
return fileUrl.forget();
|
return fileUrl.forget();
|
||||||
|
@ -256,6 +288,8 @@ IDBFactory::GetDatabaseFileURL(nsIFile* aDatabaseFile, const nsACString& aOrigin
|
||||||
// static
|
// static
|
||||||
already_AddRefed<mozIStorageConnection>
|
already_AddRefed<mozIStorageConnection>
|
||||||
IDBFactory::GetConnection(const nsAString& aDatabaseFilePath,
|
IDBFactory::GetConnection(const nsAString& aDatabaseFilePath,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
const nsACString& aOrigin)
|
const nsACString& aOrigin)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
||||||
|
@ -273,7 +307,8 @@ IDBFactory::GetConnection(const nsAString& aDatabaseFilePath,
|
||||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||||
NS_ENSURE_TRUE(exists, nullptr);
|
NS_ENSURE_TRUE(exists, nullptr);
|
||||||
|
|
||||||
nsCOMPtr<nsIFileURL> dbFileUrl = GetDatabaseFileURL(dbFile, aOrigin);
|
nsCOMPtr<nsIFileURL> dbFileUrl =
|
||||||
|
GetDatabaseFileURL(dbFile, aPersistenceType, aGroup, aOrigin);
|
||||||
NS_ENSURE_TRUE(dbFileUrl, nullptr);
|
NS_ENSURE_TRUE(dbFileUrl, nullptr);
|
||||||
|
|
||||||
nsCOMPtr<mozIStorageService> ss =
|
nsCOMPtr<mozIStorageService> ss =
|
||||||
|
@ -524,7 +559,10 @@ DOMCI_DATA(IDBFactory, IDBFactory)
|
||||||
nsresult
|
nsresult
|
||||||
IDBFactory::OpenInternal(const nsAString& aName,
|
IDBFactory::OpenInternal(const nsAString& aName,
|
||||||
int64_t aVersion,
|
int64_t aVersion,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
const nsACString& aASCIIOrigin,
|
const nsACString& aASCIIOrigin,
|
||||||
|
StoragePrivilege aPrivilege,
|
||||||
bool aDeleting,
|
bool aDeleting,
|
||||||
IDBOpenDBRequest** _retval)
|
IDBOpenDBRequest** _retval)
|
||||||
{
|
{
|
||||||
|
@ -534,17 +572,19 @@ IDBFactory::OpenInternal(const nsAString& aName,
|
||||||
AutoJSContext cx;
|
AutoJSContext cx;
|
||||||
nsCOMPtr<nsPIDOMWindow> window;
|
nsCOMPtr<nsPIDOMWindow> window;
|
||||||
JS::Rooted<JSObject*> scriptOwner(cx);
|
JS::Rooted<JSObject*> scriptOwner(cx);
|
||||||
StoragePrivilege privilege;
|
|
||||||
|
|
||||||
if (mWindow) {
|
if (mWindow) {
|
||||||
window = mWindow;
|
window = mWindow;
|
||||||
scriptOwner =
|
scriptOwner =
|
||||||
static_cast<nsGlobalWindow*>(window.get())->FastGetGlobalJSObject();
|
static_cast<nsGlobalWindow*>(window.get())->FastGetGlobalJSObject();
|
||||||
privilege = Content;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
scriptOwner = mOwningObject;
|
scriptOwner = mOwningObject;
|
||||||
privilege = Chrome;
|
}
|
||||||
|
|
||||||
|
if (aPrivilege == Chrome) {
|
||||||
|
// Chrome privilege, ignore the persistence type parameter.
|
||||||
|
aPersistenceType = PERSISTENCE_TYPE_PERSISTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<IDBOpenDBRequest> request =
|
nsRefPtr<IDBOpenDBRequest> request =
|
||||||
|
@ -555,40 +595,51 @@ IDBFactory::OpenInternal(const nsAString& aName,
|
||||||
|
|
||||||
if (IndexedDatabaseManager::IsMainProcess()) {
|
if (IndexedDatabaseManager::IsMainProcess()) {
|
||||||
nsRefPtr<OpenDatabaseHelper> openHelper =
|
nsRefPtr<OpenDatabaseHelper> openHelper =
|
||||||
new OpenDatabaseHelper(request, aName, aASCIIOrigin, aVersion, aDeleting,
|
new OpenDatabaseHelper(request, aName, aGroup, aASCIIOrigin, aVersion,
|
||||||
mContentParent, privilege);
|
aPersistenceType, aDeleting, mContentParent,
|
||||||
|
aPrivilege);
|
||||||
|
|
||||||
rv = openHelper->Init();
|
rv = openHelper->Init();
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
nsRefPtr<CheckPermissionsHelper> permissionHelper =
|
if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
|
||||||
new CheckPermissionsHelper(openHelper, window, aDeleting);
|
nsRefPtr<CheckPermissionsHelper> permissionHelper =
|
||||||
|
new CheckPermissionsHelper(openHelper, window);
|
||||||
|
|
||||||
QuotaManager* quotaManager = QuotaManager::Get();
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||||
|
|
||||||
rv = quotaManager->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(
|
rv = quotaManager->
|
||||||
aASCIIOrigin), openHelper->Id(),
|
WaitForOpenAllowed(OriginOrPatternString::FromOrigin(aASCIIOrigin),
|
||||||
permissionHelper);
|
Nullable<PersistenceType>(aPersistenceType),
|
||||||
|
openHelper->Id(), permissionHelper);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NS_ASSERTION(aPersistenceType == PERSISTENCE_TYPE_TEMPORARY, "Huh?");
|
||||||
|
|
||||||
|
rv = openHelper->WaitForOpenAllowed();
|
||||||
|
}
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
}
|
}
|
||||||
else if (aDeleting) {
|
else if (aDeleting) {
|
||||||
nsCOMPtr<nsIAtom> databaseId =
|
nsCOMPtr<nsIAtom> databaseId =
|
||||||
QuotaManager::GetStorageId(aASCIIOrigin, aName);
|
QuotaManager::GetStorageId(aPersistenceType, aASCIIOrigin, aName);
|
||||||
NS_ENSURE_TRUE(databaseId, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_TRUE(databaseId, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
IndexedDBDeleteDatabaseRequestChild* actor =
|
IndexedDBDeleteDatabaseRequestChild* actor =
|
||||||
new IndexedDBDeleteDatabaseRequestChild(this, request, databaseId);
|
new IndexedDBDeleteDatabaseRequestChild(this, request, databaseId);
|
||||||
|
|
||||||
mActorChild->SendPIndexedDBDeleteDatabaseRequestConstructor(
|
mActorChild->SendPIndexedDBDeleteDatabaseRequestConstructor(
|
||||||
actor,
|
actor,
|
||||||
nsString(aName));
|
nsString(aName),
|
||||||
|
aPersistenceType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
IndexedDBDatabaseChild* dbActor =
|
IndexedDBDatabaseChild* dbActor =
|
||||||
static_cast<IndexedDBDatabaseChild*>(
|
static_cast<IndexedDBDatabaseChild*>(
|
||||||
mActorChild->SendPIndexedDBDatabaseConstructor(nsString(aName),
|
mActorChild->SendPIndexedDBDatabaseConstructor(nsString(aName),
|
||||||
aVersion));
|
aVersion,
|
||||||
|
aPersistenceType));
|
||||||
|
|
||||||
dbActor->SetRequest(request);
|
dbActor->SetRequest(request);
|
||||||
}
|
}
|
||||||
|
@ -620,6 +671,22 @@ IDBFactory::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||||
return IDBFactoryBinding::Wrap(aCx, aScope, this);
|
return IDBFactoryBinding::Wrap(aCx, aScope, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
|
IDBFactory::Open(const nsAString& aName, const IDBOpenDBOptions& aOptions,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
return Open(nullptr, aName, aOptions.mVersion, aOptions.mStorage, false, aRv);
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
|
IDBFactory::DeleteDatabase(const nsAString& aName,
|
||||||
|
const IDBOpenDBOptions& aOptions,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
return Open(nullptr, aName, Optional<uint64_t>(), aOptions.mStorage, true,
|
||||||
|
aRv);
|
||||||
|
}
|
||||||
|
|
||||||
int16_t
|
int16_t
|
||||||
IDBFactory::Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
|
IDBFactory::Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
|
||||||
JS::Handle<JS::Value> aSecond, ErrorResult& aRv)
|
JS::Handle<JS::Value> aSecond, ErrorResult& aRv)
|
||||||
|
@ -646,22 +713,34 @@ IDBFactory::Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<IDBOpenDBRequest>
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
IDBFactory::OpenForPrincipal(nsIPrincipal* aPrincipal,
|
IDBFactory::OpenForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||||
const nsAString& aName,
|
uint64_t aVersion, ErrorResult& aRv)
|
||||||
const Optional<uint64_t>& aVersion,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
{
|
||||||
// Just to be on the extra-safe side
|
// Just to be on the extra-safe side
|
||||||
if (!nsContentUtils::IsCallerChrome()) {
|
if (!nsContentUtils::IsCallerChrome()) {
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Open(aPrincipal, aName, aVersion, false, aRv);
|
return Open(aPrincipal, aName, Optional<uint64_t>(aVersion),
|
||||||
|
Optional<mozilla::dom::StorageType>(), false, aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<IDBOpenDBRequest>
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
IDBFactory::DeleteForPrincipal(nsIPrincipal* aPrincipal,
|
IDBFactory::OpenForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||||
const nsAString& aName,
|
const IDBOpenDBOptions& aOptions, ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
// Just to be on the extra-safe side
|
||||||
|
if (!nsContentUtils::IsCallerChrome()) {
|
||||||
|
MOZ_CRASH();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Open(aPrincipal, aName, aOptions.mVersion, aOptions.mStorage, false,
|
||||||
|
aRv);
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
|
IDBFactory::DeleteForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||||
|
const IDBOpenDBOptions& aOptions,
|
||||||
ErrorResult& aRv)
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
// Just to be on the extra-safe side
|
// Just to be on the extra-safe side
|
||||||
|
@ -669,43 +748,53 @@ IDBFactory::DeleteForPrincipal(nsIPrincipal* aPrincipal,
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Open(aPrincipal, aName, Optional<uint64_t>(), true, aRv);
|
return Open(aPrincipal, aName, Optional<uint64_t>(), aOptions.mStorage, true,
|
||||||
|
aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<IDBOpenDBRequest>
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
IDBFactory::Open(nsIPrincipal* aPrincipal,
|
IDBFactory::Open(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||||
const nsAString& aName, const Optional<uint64_t>& aVersion,
|
const Optional<uint64_t>& aVersion,
|
||||||
|
const Optional<mozilla::dom::StorageType>& aStorageType,
|
||||||
bool aDelete, ErrorResult& aRv)
|
bool aDelete, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
|
nsCString group;
|
||||||
nsCString origin;
|
nsCString origin;
|
||||||
|
StoragePrivilege privilege;
|
||||||
|
PersistenceType defaultPersistenceType;
|
||||||
if (aPrincipal) {
|
if (aPrincipal) {
|
||||||
rv = QuotaManager::GetASCIIOriginFromPrincipal(aPrincipal, origin);
|
rv = QuotaManager::GetInfoFromPrincipal(aPrincipal, &group, &origin,
|
||||||
|
&privilege,
|
||||||
|
&defaultPersistenceType);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
aRv.Throw(rv);
|
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
group = mGroup;
|
||||||
origin = mASCIIOrigin;
|
origin = mASCIIOrigin;
|
||||||
|
privilege = mPrivilege;
|
||||||
|
defaultPersistenceType = mDefaultPersistenceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t version;
|
uint64_t version = 0;
|
||||||
if (!aDelete && aVersion.WasPassed()) {
|
if (!aDelete && aVersion.WasPassed()) {
|
||||||
version = aVersion.Value();
|
if (aVersion.Value() < 1) {
|
||||||
if (version < 1) {
|
|
||||||
aRv.ThrowTypeError(MSG_INVALID_VERSION);
|
aRv.ThrowTypeError(MSG_INVALID_VERSION);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
version = aVersion.Value();
|
||||||
else {
|
|
||||||
version = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PersistenceType persistenceType =
|
||||||
|
PersistenceTypeFromStorage(aStorageType, defaultPersistenceType);
|
||||||
|
|
||||||
nsRefPtr<IDBOpenDBRequest> request;
|
nsRefPtr<IDBOpenDBRequest> request;
|
||||||
rv = OpenInternal(aName, version, origin, aDelete,
|
rv = OpenInternal(aName, version, persistenceType, group, origin, privilege,
|
||||||
getter_AddRefs(request));
|
aDelete, getter_AddRefs(request));
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
aRv.Throw(rv);
|
aRv.Throw(rv);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
#define mozilla_dom_indexeddb_idbfactory_h__
|
#define mozilla_dom_indexeddb_idbfactory_h__
|
||||||
|
|
||||||
#include "mozilla/dom/BindingDeclarations.h" // for Optional
|
#include "mozilla/dom/BindingDeclarations.h" // for Optional
|
||||||
|
#include "mozilla/dom/StorageTypeBinding.h"
|
||||||
|
#include "mozilla/dom/quota/PersistenceType.h"
|
||||||
|
#include "mozilla/dom/quota/StoragePrivilege.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
#include "nsWrapperCache.h"
|
#include "nsWrapperCache.h"
|
||||||
|
@ -25,6 +28,7 @@ class ErrorResult;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class ContentParent;
|
class ContentParent;
|
||||||
|
class IDBOpenDBOptions;
|
||||||
|
|
||||||
namespace indexedDB {
|
namespace indexedDB {
|
||||||
|
|
||||||
|
@ -40,7 +44,9 @@ class IDBFactory MOZ_FINAL : public nsISupports,
|
||||||
public nsWrapperCache
|
public nsWrapperCache
|
||||||
{
|
{
|
||||||
typedef mozilla::dom::ContentParent ContentParent;
|
typedef mozilla::dom::ContentParent ContentParent;
|
||||||
|
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||||
typedef nsTArray<nsRefPtr<ObjectStoreInfo> > ObjectStoreInfoArray;
|
typedef nsTArray<nsRefPtr<ObjectStoreInfo> > ObjectStoreInfoArray;
|
||||||
|
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
@ -48,6 +54,7 @@ public:
|
||||||
|
|
||||||
// Called when using IndexedDB from a window in a different process.
|
// Called when using IndexedDB from a window in a different process.
|
||||||
static nsresult Create(nsPIDOMWindow* aWindow,
|
static nsresult Create(nsPIDOMWindow* aWindow,
|
||||||
|
const nsACString& aGroup,
|
||||||
const nsACString& aASCIIOrigin,
|
const nsACString& aASCIIOrigin,
|
||||||
ContentParent* aContentParent,
|
ContentParent* aContentParent,
|
||||||
IDBFactory** aFactory);
|
IDBFactory** aFactory);
|
||||||
|
@ -57,7 +64,8 @@ public:
|
||||||
ContentParent* aContentParent,
|
ContentParent* aContentParent,
|
||||||
IDBFactory** aFactory)
|
IDBFactory** aFactory)
|
||||||
{
|
{
|
||||||
return Create(aWindow, EmptyCString(), aContentParent, aFactory);
|
return Create(aWindow, EmptyCString(), EmptyCString(), aContentParent,
|
||||||
|
aFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when using IndexedDB from a JS component or a JSM in the current
|
// Called when using IndexedDB from a JS component or a JSM in the current
|
||||||
|
@ -73,10 +81,15 @@ public:
|
||||||
IDBFactory** aFactory);
|
IDBFactory** aFactory);
|
||||||
|
|
||||||
static already_AddRefed<nsIFileURL>
|
static already_AddRefed<nsIFileURL>
|
||||||
GetDatabaseFileURL(nsIFile* aDatabaseFile, const nsACString& aOrigin);
|
GetDatabaseFileURL(nsIFile* aDatabaseFile,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin);
|
||||||
|
|
||||||
static already_AddRefed<mozIStorageConnection>
|
static already_AddRefed<mozIStorageConnection>
|
||||||
GetConnection(const nsAString& aDatabaseFilePath,
|
GetConnection(const nsAString& aDatabaseFilePath,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
const nsACString& aOrigin);
|
const nsACString& aOrigin);
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
|
@ -96,17 +109,22 @@ public:
|
||||||
nsresult
|
nsresult
|
||||||
OpenInternal(const nsAString& aName,
|
OpenInternal(const nsAString& aName,
|
||||||
int64_t aVersion,
|
int64_t aVersion,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
const nsACString& aASCIIOrigin,
|
const nsACString& aASCIIOrigin,
|
||||||
|
StoragePrivilege aStoragePrivilege,
|
||||||
bool aDeleting,
|
bool aDeleting,
|
||||||
IDBOpenDBRequest** _retval);
|
IDBOpenDBRequest** _retval);
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
OpenInternal(const nsAString& aName,
|
OpenInternal(const nsAString& aName,
|
||||||
int64_t aVersion,
|
int64_t aVersion,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
bool aDeleting,
|
bool aDeleting,
|
||||||
IDBOpenDBRequest** _retval)
|
IDBOpenDBRequest** _retval)
|
||||||
{
|
{
|
||||||
return OpenInternal(aName, aVersion, mASCIIOrigin, aDeleting, _retval);
|
return OpenInternal(aName, aVersion, aPersistenceType, mGroup, mASCIIOrigin,
|
||||||
|
mPrivilege, aDeleting, _retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -129,28 +147,31 @@ public:
|
||||||
return mASCIIOrigin;
|
return mASCIIOrigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
// WrapperCache
|
// nsWrapperCache
|
||||||
nsPIDOMWindow* GetParentObject() const
|
virtual JSObject*
|
||||||
|
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
// WebIDL
|
||||||
|
nsPIDOMWindow*
|
||||||
|
GetParentObject() const
|
||||||
{
|
{
|
||||||
return mWindow;
|
return mWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
// WebIDL
|
|
||||||
already_AddRefed<IDBOpenDBRequest>
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
Open(const nsAString& aName, const Optional<uint64_t>& aVersion,
|
Open(const nsAString& aName, uint64_t aVersion, ErrorResult& aRv)
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
{
|
||||||
return Open(nullptr, aName, aVersion, false, aRv);
|
return Open(nullptr, aName, Optional<uint64_t>(aVersion),
|
||||||
|
Optional<mozilla::dom::StorageType>(), false, aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<IDBOpenDBRequest>
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
DeleteDatabase(const nsAString& aName, ErrorResult& aRv)
|
Open(const nsAString& aName, const IDBOpenDBOptions& aOptions,
|
||||||
{
|
ErrorResult& aRv);
|
||||||
return Open(nullptr, aName, Optional<uint64_t>(), true, aRv);
|
|
||||||
}
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
|
DeleteDatabase(const nsAString& aName, const IDBOpenDBOptions& aOptions,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
int16_t
|
int16_t
|
||||||
Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
|
Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
|
||||||
|
@ -158,11 +179,15 @@ public:
|
||||||
|
|
||||||
already_AddRefed<IDBOpenDBRequest>
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
OpenForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
|
OpenForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||||
const Optional<uint64_t>& aVersion, ErrorResult& aRv);
|
uint64_t aVersion, ErrorResult& aRv);
|
||||||
|
|
||||||
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
|
OpenForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||||
|
const IDBOpenDBOptions& aOptions, ErrorResult& aRv);
|
||||||
|
|
||||||
already_AddRefed<IDBOpenDBRequest>
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
DeleteForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
|
DeleteForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||||
ErrorResult& aRv);
|
const IDBOpenDBOptions& aOptions, ErrorResult& aRv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IDBFactory();
|
IDBFactory();
|
||||||
|
@ -170,9 +195,14 @@ private:
|
||||||
|
|
||||||
already_AddRefed<IDBOpenDBRequest>
|
already_AddRefed<IDBOpenDBRequest>
|
||||||
Open(nsIPrincipal* aPrincipal, const nsAString& aName,
|
Open(nsIPrincipal* aPrincipal, const nsAString& aName,
|
||||||
const Optional<uint64_t>& aVersion, bool aDelete, ErrorResult& aRv);
|
const Optional<uint64_t>& aVersion,
|
||||||
|
const Optional<mozilla::dom::StorageType>& aStorageType, bool aDelete,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
nsCString mGroup;
|
||||||
nsCString mASCIIOrigin;
|
nsCString mASCIIOrigin;
|
||||||
|
StoragePrivilege mPrivilege;
|
||||||
|
PersistenceType mDefaultPersistenceType;
|
||||||
|
|
||||||
// If this factory lives on a window then mWindow must be non-null. Otherwise
|
// If this factory lives on a window then mWindow must be non-null. Otherwise
|
||||||
// mOwningObject must be non-null.
|
// mOwningObject must be non-null.
|
||||||
|
|
|
@ -77,18 +77,22 @@ IDBFileHandle::CreateStream(nsIFile* aFile, bool aReadOnly)
|
||||||
nsCOMPtr<nsIOfflineStorage> storage = do_QueryInterface(mFileStorage);
|
nsCOMPtr<nsIOfflineStorage> storage = do_QueryInterface(mFileStorage);
|
||||||
NS_ASSERTION(storage, "This should always succeed!");
|
NS_ASSERTION(storage, "This should always succeed!");
|
||||||
|
|
||||||
|
PersistenceType persistenceType = storage->Type();
|
||||||
|
const nsACString& group = storage->Group();
|
||||||
const nsACString& origin = storage->Origin();
|
const nsACString& origin = storage->Origin();
|
||||||
|
|
||||||
nsCOMPtr<nsISupports> result;
|
nsCOMPtr<nsISupports> result;
|
||||||
|
|
||||||
if (aReadOnly) {
|
if (aReadOnly) {
|
||||||
nsRefPtr<FileInputStream> stream = FileInputStream::Create(
|
nsRefPtr<FileInputStream> stream =
|
||||||
origin, aFile, -1, -1, nsIFileInputStream::DEFER_OPEN);
|
FileInputStream::Create(persistenceType, group, origin, aFile, -1, -1,
|
||||||
|
nsIFileInputStream::DEFER_OPEN);
|
||||||
result = NS_ISUPPORTS_CAST(nsIFileInputStream*, stream);
|
result = NS_ISUPPORTS_CAST(nsIFileInputStream*, stream);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nsRefPtr<FileStream> stream = FileStream::Create(
|
nsRefPtr<FileStream> stream =
|
||||||
origin, aFile, -1, -1, nsIFileStream::DEFER_OPEN);
|
FileStream::Create(persistenceType, group, origin, aFile, -1, -1,
|
||||||
|
nsIFileStream::DEFER_OPEN);
|
||||||
result = NS_ISUPPORTS_CAST(nsIFileStream*, stream);
|
result = NS_ISUPPORTS_CAST(nsIFileStream*, stream);
|
||||||
}
|
}
|
||||||
NS_ENSURE_TRUE(result, nullptr);
|
NS_ENSURE_TRUE(result, nullptr);
|
||||||
|
|
|
@ -3015,8 +3015,10 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||||
nativeFile = fileManager->GetFileForId(directory, id);
|
nativeFile = fileManager->GetFileForId(directory, id);
|
||||||
NS_ENSURE_TRUE(nativeFile, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_TRUE(nativeFile, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
nsRefPtr<FileOutputStream> outputStream = FileOutputStream::Create(
|
IDBDatabase* database = mObjectStore->Transaction()->Database();
|
||||||
mObjectStore->Transaction()->Database()->Origin(), nativeFile);
|
nsRefPtr<FileOutputStream> outputStream =
|
||||||
|
FileOutputStream::Create(database->Type(), database->Group(),
|
||||||
|
database->Origin(), nativeFile);
|
||||||
NS_ENSURE_TRUE(outputStream, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_TRUE(outputStream, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
rv = CopyData(inputStream, outputStream);
|
rv = CopyData(inputStream, outputStream);
|
||||||
|
|
|
@ -361,8 +361,8 @@ IDBTransaction::GetOrCreateConnection(mozIStorageConnection** aResult)
|
||||||
|
|
||||||
if (!mConnection) {
|
if (!mConnection) {
|
||||||
nsCOMPtr<mozIStorageConnection> connection =
|
nsCOMPtr<mozIStorageConnection> connection =
|
||||||
IDBFactory::GetConnection(mDatabase->FilePath(),
|
IDBFactory::GetConnection(mDatabase->FilePath(), mDatabase->Type(),
|
||||||
mDatabase->Origin());
|
mDatabase->Group(), mDatabase->Origin());
|
||||||
NS_ENSURE_TRUE(connection, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(connection, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/CondVar.h"
|
#include "mozilla/CondVar.h"
|
||||||
|
#include "mozilla/dom/quota/OriginOrPatternString.h"
|
||||||
#include "mozilla/dom/quota/QuotaManager.h"
|
#include "mozilla/dom/quota/QuotaManager.h"
|
||||||
#include "mozilla/dom/quota/Utilities.h"
|
#include "mozilla/dom/quota/Utilities.h"
|
||||||
#include "mozilla/dom/TabContext.h"
|
#include "mozilla/dom/TabContext.h"
|
||||||
|
@ -41,6 +42,53 @@ USING_QUOTA_NAMESPACE
|
||||||
|
|
||||||
static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||||
|
|
||||||
|
BEGIN_INDEXEDDB_NAMESPACE
|
||||||
|
|
||||||
|
class FileManagerInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
already_AddRefed<FileManager>
|
||||||
|
GetFileManager(PersistenceType aPersistenceType,
|
||||||
|
const nsAString& aName) const;
|
||||||
|
|
||||||
|
void
|
||||||
|
AddFileManager(FileManager* aFileManager);
|
||||||
|
|
||||||
|
bool
|
||||||
|
HasFileManagers() const
|
||||||
|
{
|
||||||
|
AssertIsOnIOThread();
|
||||||
|
|
||||||
|
return !mPersistentStorageFileManagers.IsEmpty() ||
|
||||||
|
!mTemporaryStorageFileManagers.IsEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
InvalidateAllFileManagers() const;
|
||||||
|
|
||||||
|
void
|
||||||
|
InvalidateAndRemoveFileManagers(PersistenceType aPersistenceType);
|
||||||
|
|
||||||
|
void
|
||||||
|
InvalidateAndRemoveFileManager(PersistenceType aPersistenceType,
|
||||||
|
const nsAString& aName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsTArray<nsRefPtr<FileManager> >&
|
||||||
|
GetArray(PersistenceType aPersistenceType);
|
||||||
|
|
||||||
|
const nsTArray<nsRefPtr<FileManager> >&
|
||||||
|
GetImmutableArray(PersistenceType aPersistenceType) const
|
||||||
|
{
|
||||||
|
return const_cast<FileManagerInfo*>(this)->GetArray(aPersistenceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<nsRefPtr<FileManager> > mPersistentStorageFileManagers;
|
||||||
|
nsTArray<nsRefPtr<FileManager> > mTemporaryStorageFileManagers;
|
||||||
|
};
|
||||||
|
|
||||||
|
END_INDEXEDDB_NAMESPACE
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
mozilla::StaticRefPtr<IndexedDatabaseManager> gInstance;
|
mozilla::StaticRefPtr<IndexedDatabaseManager> gInstance;
|
||||||
|
@ -67,10 +115,14 @@ public:
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
NS_DECL_NSIRUNNABLE
|
NS_DECL_NSIRUNNABLE
|
||||||
|
|
||||||
GetFileReferencesHelper(const nsACString& aOrigin,
|
GetFileReferencesHelper(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aOrigin,
|
||||||
const nsAString& aDatabaseName,
|
const nsAString& aDatabaseName,
|
||||||
int64_t aFileId)
|
int64_t aFileId)
|
||||||
: mOrigin(aOrigin), mDatabaseName(aDatabaseName), mFileId(aFileId),
|
: mPersistenceType(aPersistenceType),
|
||||||
|
mOrigin(aOrigin),
|
||||||
|
mDatabaseName(aDatabaseName),
|
||||||
|
mFileId(aFileId),
|
||||||
mMutex(IndexedDatabaseManager::FileMutex()),
|
mMutex(IndexedDatabaseManager::FileMutex()),
|
||||||
mCondVar(mMutex, "GetFileReferencesHelper::mCondVar"),
|
mCondVar(mMutex, "GetFileReferencesHelper::mCondVar"),
|
||||||
mMemRefCnt(-1),
|
mMemRefCnt(-1),
|
||||||
|
@ -87,6 +139,7 @@ public:
|
||||||
bool* aResult);
|
bool* aResult);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
PersistenceType mPersistenceType;
|
||||||
nsCString mOrigin;
|
nsCString mOrigin;
|
||||||
nsString mDatabaseName;
|
nsString mDatabaseName;
|
||||||
int64_t mFileId;
|
int64_t mFileId;
|
||||||
|
@ -100,29 +153,15 @@ private:
|
||||||
bool mWaiting;
|
bool mWaiting;
|
||||||
};
|
};
|
||||||
|
|
||||||
PLDHashOperator
|
struct MOZ_STACK_CLASS InvalidateInfo
|
||||||
InvalidateAndRemoveFileManagers(
|
|
||||||
const nsACString& aKey,
|
|
||||||
nsAutoPtr<nsTArray<nsRefPtr<FileManager> > >& aValue,
|
|
||||||
void* aUserArg)
|
|
||||||
{
|
{
|
||||||
AssertIsOnIOThread();
|
InvalidateInfo(PersistenceType aPersistenceType, const nsACString& aPattern)
|
||||||
NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
|
: persistenceType(aPersistenceType), pattern(aPattern)
|
||||||
NS_ASSERTION(aValue, "Null pointer!");
|
{ }
|
||||||
|
|
||||||
const nsACString* pattern =
|
PersistenceType persistenceType;
|
||||||
static_cast<const nsACString*>(aUserArg);
|
const nsACString& pattern;
|
||||||
|
};
|
||||||
if (!pattern || PatternMatchesOrigin(*pattern, aKey)) {
|
|
||||||
for (uint32_t i = 0; i < aValue->Length(); i++) {
|
|
||||||
nsRefPtr<FileManager>& fileManager = aValue->ElementAt(i);
|
|
||||||
fileManager->Invalidate();
|
|
||||||
}
|
|
||||||
return PL_DHASH_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PL_DHASH_NEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
@ -381,26 +420,21 @@ IndexedDatabaseManager::InLowDiskSpaceMode()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
already_AddRefed<FileManager>
|
already_AddRefed<FileManager>
|
||||||
IndexedDatabaseManager::GetFileManager(const nsACString& aOrigin,
|
IndexedDatabaseManager::GetFileManager(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aOrigin,
|
||||||
const nsAString& aDatabaseName)
|
const nsAString& aDatabaseName)
|
||||||
{
|
{
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
|
|
||||||
nsTArray<nsRefPtr<FileManager> >* array;
|
FileManagerInfo* info;
|
||||||
if (!mFileManagers.Get(aOrigin, &array)) {
|
if (!mFileManagerInfos.Get(aOrigin, &info)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
nsRefPtr<FileManager> fileManager =
|
||||||
nsRefPtr<FileManager>& fileManager = array->ElementAt(i);
|
info->GetFileManager(aPersistenceType, aDatabaseName);
|
||||||
|
|
||||||
if (fileManager->DatabaseName().Equals(aDatabaseName)) {
|
return fileManager.forget();
|
||||||
nsRefPtr<FileManager> result = fileManager;
|
|
||||||
return result.forget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -409,13 +443,42 @@ IndexedDatabaseManager::AddFileManager(FileManager* aFileManager)
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
NS_ASSERTION(aFileManager, "Null file manager!");
|
NS_ASSERTION(aFileManager, "Null file manager!");
|
||||||
|
|
||||||
nsTArray<nsRefPtr<FileManager> >* array;
|
FileManagerInfo* info;
|
||||||
if (!mFileManagers.Get(aFileManager->Origin(), &array)) {
|
if (!mFileManagerInfos.Get(aFileManager->Origin(), &info)) {
|
||||||
array = new nsTArray<nsRefPtr<FileManager> >();
|
info = new FileManagerInfo();
|
||||||
mFileManagers.Put(aFileManager->Origin(), array);
|
mFileManagerInfos.Put(aFileManager->Origin(), info);
|
||||||
}
|
}
|
||||||
|
|
||||||
array->AppendElement(aFileManager);
|
info->AddFileManager(aFileManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
PLDHashOperator
|
||||||
|
IndexedDatabaseManager::InvalidateAndRemoveFileManagers(
|
||||||
|
const nsACString& aKey,
|
||||||
|
nsAutoPtr<FileManagerInfo>& aValue,
|
||||||
|
void* aUserArg)
|
||||||
|
{
|
||||||
|
AssertIsOnIOThread();
|
||||||
|
NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
|
||||||
|
NS_ASSERTION(aValue, "Null pointer!");
|
||||||
|
|
||||||
|
if (!aUserArg) {
|
||||||
|
aValue->InvalidateAllFileManagers();
|
||||||
|
return PL_DHASH_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
InvalidateInfo* info = static_cast<InvalidateInfo*>(aUserArg);
|
||||||
|
|
||||||
|
if (PatternMatchesOrigin(info->pattern, aKey)) {
|
||||||
|
aValue->InvalidateAndRemoveFileManagers(info->persistenceType);
|
||||||
|
|
||||||
|
if (!aValue->HasFileManagers()) {
|
||||||
|
return PL_DHASH_REMOVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -423,43 +486,51 @@ IndexedDatabaseManager::InvalidateAllFileManagers()
|
||||||
{
|
{
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
|
|
||||||
mFileManagers.Enumerate(InvalidateAndRemoveFileManagers, nullptr);
|
mFileManagerInfos.Enumerate(InvalidateAndRemoveFileManagers, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
IndexedDatabaseManager::InvalidateFileManagersForPattern(
|
IndexedDatabaseManager::InvalidateFileManagers(
|
||||||
const nsACString& aPattern)
|
PersistenceType aPersistenceType,
|
||||||
|
const OriginOrPatternString& aOriginOrPattern)
|
||||||
{
|
{
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
NS_ASSERTION(!aPattern.IsEmpty(), "Empty pattern!");
|
NS_ASSERTION(!aOriginOrPattern.IsEmpty(), "Empty pattern!");
|
||||||
|
|
||||||
mFileManagers.Enumerate(InvalidateAndRemoveFileManagers,
|
if (aOriginOrPattern.IsOrigin()) {
|
||||||
const_cast<nsACString*>(&aPattern));
|
FileManagerInfo* info;
|
||||||
|
if (!mFileManagerInfos.Get(aOriginOrPattern, &info)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->InvalidateAndRemoveFileManagers(aPersistenceType);
|
||||||
|
|
||||||
|
if (!info->HasFileManagers()) {
|
||||||
|
mFileManagerInfos.Remove(aOriginOrPattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
InvalidateInfo info(aPersistenceType, aOriginOrPattern);
|
||||||
|
mFileManagerInfos.Enumerate(InvalidateAndRemoveFileManagers, &info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
IndexedDatabaseManager::InvalidateFileManager(const nsACString& aOrigin,
|
IndexedDatabaseManager::InvalidateFileManager(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aOrigin,
|
||||||
const nsAString& aDatabaseName)
|
const nsAString& aDatabaseName)
|
||||||
{
|
{
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
|
|
||||||
nsTArray<nsRefPtr<FileManager> >* array;
|
FileManagerInfo* info;
|
||||||
if (!mFileManagers.Get(aOrigin, &array)) {
|
if (!mFileManagerInfos.Get(aOrigin, &info)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
info->InvalidateAndRemoveFileManager(aPersistenceType, aDatabaseName);
|
||||||
nsRefPtr<FileManager> fileManager = array->ElementAt(i);
|
|
||||||
if (fileManager->DatabaseName().Equals(aDatabaseName)) {
|
|
||||||
fileManager->Invalidate();
|
|
||||||
array->RemoveElementAt(i);
|
|
||||||
|
|
||||||
if (array->IsEmpty()) {
|
if (!info->HasFileManagers()) {
|
||||||
mFileManagers.Remove(aOrigin);
|
mFileManagerInfos.Remove(aOrigin);
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,16 +563,18 @@ IndexedDatabaseManager::AsyncDeleteFile(FileManager* aFileManager,
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
IndexedDatabaseManager::BlockAndGetFileReferences(
|
IndexedDatabaseManager::BlockAndGetFileReferences(
|
||||||
const nsACString& aOrigin,
|
PersistenceType aPersistenceType,
|
||||||
const nsAString& aDatabaseName,
|
const nsACString& aOrigin,
|
||||||
int64_t aFileId,
|
const nsAString& aDatabaseName,
|
||||||
int32_t* aRefCnt,
|
int64_t aFileId,
|
||||||
int32_t* aDBRefCnt,
|
int32_t* aRefCnt,
|
||||||
int32_t* aSliceRefCnt,
|
int32_t* aDBRefCnt,
|
||||||
bool* aResult)
|
int32_t* aSliceRefCnt,
|
||||||
|
bool* aResult)
|
||||||
{
|
{
|
||||||
nsRefPtr<GetFileReferencesHelper> helper =
|
nsRefPtr<GetFileReferencesHelper> helper =
|
||||||
new GetFileReferencesHelper(aOrigin, aDatabaseName, aFileId);
|
new GetFileReferencesHelper(aPersistenceType, aOrigin, aDatabaseName,
|
||||||
|
aFileId);
|
||||||
|
|
||||||
nsresult rv = helper->DispatchAndReturnFileReferences(aRefCnt, aDBRefCnt,
|
nsresult rv = helper->DispatchAndReturnFileReferences(aRefCnt, aDBRefCnt,
|
||||||
aSliceRefCnt, aResult);
|
aSliceRefCnt, aResult);
|
||||||
|
@ -602,6 +675,105 @@ IndexedDatabaseManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<FileManager>
|
||||||
|
FileManagerInfo::GetFileManager(PersistenceType aPersistenceType,
|
||||||
|
const nsAString& aName) const
|
||||||
|
{
|
||||||
|
AssertIsOnIOThread();
|
||||||
|
|
||||||
|
const nsTArray<nsRefPtr<FileManager> >& managers =
|
||||||
|
GetImmutableArray(aPersistenceType);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < managers.Length(); i++) {
|
||||||
|
const nsRefPtr<FileManager>& fileManager = managers[i];
|
||||||
|
|
||||||
|
if (fileManager->DatabaseName() == aName) {
|
||||||
|
nsRefPtr<FileManager> result = fileManager;
|
||||||
|
return result.forget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FileManagerInfo::AddFileManager(FileManager* aFileManager)
|
||||||
|
{
|
||||||
|
AssertIsOnIOThread();
|
||||||
|
|
||||||
|
nsTArray<nsRefPtr<FileManager> >& managers = GetArray(aFileManager->Type());
|
||||||
|
|
||||||
|
NS_ASSERTION(!managers.Contains(aFileManager), "Adding more than once?!");
|
||||||
|
|
||||||
|
managers.AppendElement(aFileManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FileManagerInfo::InvalidateAllFileManagers() const
|
||||||
|
{
|
||||||
|
AssertIsOnIOThread();
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < mPersistentStorageFileManagers.Length(); i++) {
|
||||||
|
mPersistentStorageFileManagers[i]->Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < mTemporaryStorageFileManagers.Length(); i++) {
|
||||||
|
mTemporaryStorageFileManagers[i]->Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FileManagerInfo::InvalidateAndRemoveFileManagers(
|
||||||
|
PersistenceType aPersistenceType)
|
||||||
|
{
|
||||||
|
AssertIsOnIOThread();
|
||||||
|
|
||||||
|
nsTArray<nsRefPtr<FileManager > >& managers = GetArray(aPersistenceType);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < managers.Length(); i++) {
|
||||||
|
managers[i]->Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
managers.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FileManagerInfo::InvalidateAndRemoveFileManager(
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
|
const nsAString& aName)
|
||||||
|
{
|
||||||
|
AssertIsOnIOThread();
|
||||||
|
|
||||||
|
nsTArray<nsRefPtr<FileManager > >& managers = GetArray(aPersistenceType);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < managers.Length(); i++) {
|
||||||
|
nsRefPtr<FileManager>& fileManager = managers[i];
|
||||||
|
if (fileManager->DatabaseName() == aName) {
|
||||||
|
fileManager->Invalidate();
|
||||||
|
managers.RemoveElementAt(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<nsRefPtr<FileManager> >&
|
||||||
|
FileManagerInfo::GetArray(PersistenceType aPersistenceType)
|
||||||
|
{
|
||||||
|
switch (aPersistenceType) {
|
||||||
|
case PERSISTENCE_TYPE_PERSISTENT:
|
||||||
|
return mPersistentStorageFileManagers;
|
||||||
|
case PERSISTENCE_TYPE_TEMPORARY:
|
||||||
|
return mTemporaryStorageFileManagers;
|
||||||
|
|
||||||
|
case PERSISTENCE_TYPE_INVALID:
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("Bad storage type value!");
|
||||||
|
return mPersistentStorageFileManagers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AsyncDeleteFileRunnable::AsyncDeleteFileRunnable(FileManager* aFileManager,
|
AsyncDeleteFileRunnable::AsyncDeleteFileRunnable(FileManager* aFileManager,
|
||||||
int64_t aFileId)
|
int64_t aFileId)
|
||||||
: mFileManager(aFileManager), mFileId(aFileId)
|
: mFileManager(aFileManager), mFileId(aFileId)
|
||||||
|
@ -637,7 +809,9 @@ AsyncDeleteFileRunnable::Run()
|
||||||
QuotaManager* quotaManager = QuotaManager::Get();
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||||
|
|
||||||
quotaManager->DecreaseUsageForOrigin(mFileManager->Origin(), fileSize);
|
quotaManager->DecreaseUsageForOrigin(mFileManager->Type(),
|
||||||
|
mFileManager->Group(),
|
||||||
|
mFileManager->Origin(), fileSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
directory = mFileManager->GetJournalDirectory();
|
directory = mFileManager->GetJournalDirectory();
|
||||||
|
@ -692,7 +866,7 @@ GetFileReferencesHelper::Run()
|
||||||
NS_ASSERTION(mgr, "This should never fail!");
|
NS_ASSERTION(mgr, "This should never fail!");
|
||||||
|
|
||||||
nsRefPtr<FileManager> fileManager =
|
nsRefPtr<FileManager> fileManager =
|
||||||
mgr->GetFileManager(mOrigin, mDatabaseName);
|
mgr->GetFileManager(mPersistenceType, mOrigin, mDatabaseName);
|
||||||
|
|
||||||
if (fileManager) {
|
if (fileManager) {
|
||||||
nsRefPtr<FileInfo> fileInfo = fileManager->GetFileInfo(mFileId);
|
nsRefPtr<FileInfo> fileInfo = fileManager->GetFileInfo(mFileId);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
|
|
||||||
#include "mozilla/Atomics.h"
|
#include "mozilla/Atomics.h"
|
||||||
|
#include "mozilla/dom/quota/PersistenceType.h"
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
#include "nsClassHashtable.h"
|
#include "nsClassHashtable.h"
|
||||||
#include "nsHashKeys.h"
|
#include "nsHashKeys.h"
|
||||||
|
@ -26,16 +27,23 @@ class nsEventChainPostVisitor;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class TabContext;
|
class TabContext;
|
||||||
|
namespace quota {
|
||||||
|
class OriginOrPatternString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BEGIN_INDEXEDDB_NAMESPACE
|
BEGIN_INDEXEDDB_NAMESPACE
|
||||||
|
|
||||||
class FileManager;
|
class FileManager;
|
||||||
|
class FileManagerInfo;
|
||||||
|
|
||||||
class IndexedDatabaseManager MOZ_FINAL : public nsIIndexedDatabaseManager,
|
class IndexedDatabaseManager MOZ_FINAL : public nsIIndexedDatabaseManager,
|
||||||
public nsIObserver
|
public nsIObserver
|
||||||
{
|
{
|
||||||
|
typedef mozilla::dom::quota::OriginOrPatternString OriginOrPatternString;
|
||||||
|
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
NS_DECL_NSIINDEXEDDATABASEMANAGER
|
NS_DECL_NSIINDEXEDDATABASEMANAGER
|
||||||
|
@ -77,7 +85,8 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
already_AddRefed<FileManager>
|
already_AddRefed<FileManager>
|
||||||
GetFileManager(const nsACString& aOrigin,
|
GetFileManager(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aOrigin,
|
||||||
const nsAString& aDatabaseName);
|
const nsAString& aDatabaseName);
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -87,10 +96,12 @@ public:
|
||||||
InvalidateAllFileManagers();
|
InvalidateAllFileManagers();
|
||||||
|
|
||||||
void
|
void
|
||||||
InvalidateFileManagersForPattern(const nsACString& aPattern);
|
InvalidateFileManagers(PersistenceType aPersistenceType,
|
||||||
|
const OriginOrPatternString& aOriginOrPattern);
|
||||||
|
|
||||||
void
|
void
|
||||||
InvalidateFileManager(const nsACString& aOrigin,
|
InvalidateFileManager(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aOrigin,
|
||||||
const nsAString& aDatabaseName);
|
const nsAString& aDatabaseName);
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -101,7 +112,8 @@ public:
|
||||||
// It is intended to be used by mochitests to test correctness of the special
|
// It is intended to be used by mochitests to test correctness of the special
|
||||||
// reference counting of stored blobs/files.
|
// reference counting of stored blobs/files.
|
||||||
nsresult
|
nsresult
|
||||||
BlockAndGetFileReferences(const nsACString& aOrigin,
|
BlockAndGetFileReferences(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aOrigin,
|
||||||
const nsAString& aDatabaseName,
|
const nsAString& aDatabaseName,
|
||||||
int64_t aFileId,
|
int64_t aFileId,
|
||||||
int32_t* aRefCnt,
|
int32_t* aRefCnt,
|
||||||
|
@ -136,10 +148,14 @@ private:
|
||||||
void
|
void
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
InvalidateAndRemoveFileManagers(const nsACString& aKey,
|
||||||
|
nsAutoPtr<FileManagerInfo>& aValue,
|
||||||
|
void* aUserArg);
|
||||||
|
|
||||||
// Maintains a list of all file managers per origin. This list isn't
|
// Maintains a list of all file managers per origin. This list isn't
|
||||||
// protected by any mutex but it is only ever touched on the IO thread.
|
// protected by any mutex but it is only ever touched on the IO thread.
|
||||||
nsClassHashtable<nsCStringHashKey,
|
nsClassHashtable<nsCStringHashKey, FileManagerInfo> mFileManagerInfos;
|
||||||
nsTArray<nsRefPtr<FileManager> > > mFileManagers;
|
|
||||||
|
|
||||||
// Lock protecting FileManager.mFileInfos and nsDOMFileBase.mFileInfos
|
// Lock protecting FileManager.mFileInfos and nsDOMFileBase.mFileInfos
|
||||||
// It's s also used to atomically update FileInfo.mRefCnt, FileInfo.mDBRefCnt
|
// It's s also used to atomically update FileInfo.mRefCnt, FileInfo.mDBRefCnt
|
||||||
|
|
|
@ -1504,11 +1504,14 @@ public:
|
||||||
OpenDatabaseHelper* aHelper,
|
OpenDatabaseHelper* aHelper,
|
||||||
uint64_t aCurrentVersion,
|
uint64_t aCurrentVersion,
|
||||||
const nsAString& aName,
|
const nsAString& aName,
|
||||||
const nsACString& aASCIIOrigin)
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aASCIIOrigin,
|
||||||
|
PersistenceType aPersistenceType)
|
||||||
: AsyncConnectionHelper(static_cast<IDBDatabase*>(nullptr), aRequest),
|
: AsyncConnectionHelper(static_cast<IDBDatabase*>(nullptr), aRequest),
|
||||||
mOpenHelper(aHelper), mOpenRequest(aRequest),
|
mOpenHelper(aHelper), mOpenRequest(aRequest),
|
||||||
mCurrentVersion(aCurrentVersion), mName(aName),
|
mCurrentVersion(aCurrentVersion), mName(aName),
|
||||||
mASCIIOrigin(aASCIIOrigin)
|
mGroup(aGroup), mASCIIOrigin(aASCIIOrigin),
|
||||||
|
mPersistenceType(aPersistenceType)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
@ -1567,7 +1570,9 @@ private:
|
||||||
nsRefPtr<IDBOpenDBRequest> mOpenRequest;
|
nsRefPtr<IDBOpenDBRequest> mOpenRequest;
|
||||||
uint64_t mCurrentVersion;
|
uint64_t mCurrentVersion;
|
||||||
nsString mName;
|
nsString mName;
|
||||||
|
nsCString mGroup;
|
||||||
nsCString mASCIIOrigin;
|
nsCString mASCIIOrigin;
|
||||||
|
PersistenceType mPersistenceType;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Responsible for firing "versionchange" events at all live and non-closed
|
// Responsible for firing "versionchange" events at all live and non-closed
|
||||||
|
@ -1685,21 +1690,50 @@ NS_IMPL_ISUPPORTS1(OpenDatabaseHelper, nsIRunnable)
|
||||||
nsresult
|
nsresult
|
||||||
OpenDatabaseHelper::Init()
|
OpenDatabaseHelper::Init()
|
||||||
{
|
{
|
||||||
mDatabaseId = QuotaManager::GetStorageId(mASCIIOrigin, mName);
|
mDatabaseId =
|
||||||
|
QuotaManager::GetStorageId(mPersistenceType, mASCIIOrigin, mName);
|
||||||
NS_ENSURE_TRUE(mDatabaseId, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(mDatabaseId, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
OpenDatabaseHelper::Dispatch(nsIEventTarget* aTarget)
|
OpenDatabaseHelper::WaitForOpenAllowed()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(mState == eCreated, "We've already been dispatched?");
|
NS_ASSERTION(mState == eCreated, "We've already been dispatched?");
|
||||||
|
NS_ASSERTION(NS_IsMainThread(), "All hell is about to break lose!");
|
||||||
|
|
||||||
|
mState = eOpenPending;
|
||||||
|
|
||||||
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
|
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||||
|
|
||||||
|
return quotaManager->
|
||||||
|
WaitForOpenAllowed(OriginOrPatternString::FromOrigin(mASCIIOrigin),
|
||||||
|
Nullable<PersistenceType>(mPersistenceType), mDatabaseId,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
OpenDatabaseHelper::Dispatch(nsIEventTarget* aTarget)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(mState == eCreated || mState == eOpenPending,
|
||||||
|
"We've already been dispatched?");
|
||||||
|
|
||||||
mState = eDBWork;
|
mState = eDBWork;
|
||||||
|
|
||||||
return aTarget->Dispatch(this, NS_DISPATCH_NORMAL);
|
return aTarget->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
OpenDatabaseHelper::DispatchToIOThread()
|
||||||
|
{
|
||||||
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
|
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||||
|
|
||||||
|
return Dispatch(quotaManager->IOThread());
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
OpenDatabaseHelper::RunImmediately()
|
OpenDatabaseHelper::RunImmediately()
|
||||||
{
|
{
|
||||||
|
@ -1709,6 +1743,7 @@ OpenDatabaseHelper::RunImmediately()
|
||||||
NS_ASSERTION(NS_IsMainThread(), "All hell is about to break lose!");
|
NS_ASSERTION(NS_IsMainThread(), "All hell is about to break lose!");
|
||||||
|
|
||||||
mState = eFiringEvents;
|
mState = eFiringEvents;
|
||||||
|
|
||||||
return this->Run();
|
return this->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1739,8 +1774,8 @@ OpenDatabaseHelper::DoDatabaseWork()
|
||||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||||
|
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
quotaManager->EnsureOriginIsInitialized(mASCIIOrigin,
|
quotaManager->EnsureOriginIsInitialized(mPersistenceType, mGroup,
|
||||||
mTrackingQuota,
|
mASCIIOrigin, mTrackingQuota,
|
||||||
getter_AddRefs(dbDirectory));
|
getter_AddRefs(dbDirectory));
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
|
@ -1785,7 +1820,8 @@ OpenDatabaseHelper::DoDatabaseWork()
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
nsCOMPtr<mozIStorageConnection> connection;
|
nsCOMPtr<mozIStorageConnection> connection;
|
||||||
rv = CreateDatabaseConnection(dbFile, fmDirectory, mName, mASCIIOrigin,
|
rv = CreateDatabaseConnection(dbFile, fmDirectory, mName, mPersistenceType,
|
||||||
|
mGroup, mASCIIOrigin,
|
||||||
getter_AddRefs(connection));
|
getter_AddRefs(connection));
|
||||||
if (NS_FAILED(rv) &&
|
if (NS_FAILED(rv) &&
|
||||||
NS_ERROR_GET_MODULE(rv) != NS_ERROR_MODULE_DOM_INDEXEDDB) {
|
NS_ERROR_GET_MODULE(rv) != NS_ERROR_MODULE_DOM_INDEXEDDB) {
|
||||||
|
@ -1837,9 +1873,11 @@ OpenDatabaseHelper::DoDatabaseWork()
|
||||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||||
NS_ASSERTION(mgr, "This should never be null!");
|
NS_ASSERTION(mgr, "This should never be null!");
|
||||||
|
|
||||||
nsRefPtr<FileManager> fileManager = mgr->GetFileManager(mASCIIOrigin, mName);
|
nsRefPtr<FileManager> fileManager =
|
||||||
|
mgr->GetFileManager(mPersistenceType, mASCIIOrigin, mName);
|
||||||
if (!fileManager) {
|
if (!fileManager) {
|
||||||
fileManager = new FileManager(mASCIIOrigin, mPrivilege, mName);
|
fileManager = new FileManager(mPersistenceType, mGroup, mASCIIOrigin,
|
||||||
|
mPrivilege, mName);
|
||||||
|
|
||||||
rv = fileManager->Init(fmDirectory, connection);
|
rv = fileManager->Init(fmDirectory, connection);
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
@ -1858,6 +1896,8 @@ OpenDatabaseHelper::CreateDatabaseConnection(
|
||||||
nsIFile* aDBFile,
|
nsIFile* aDBFile,
|
||||||
nsIFile* aFMDirectory,
|
nsIFile* aFMDirectory,
|
||||||
const nsAString& aName,
|
const nsAString& aName,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
const nsACString& aOrigin,
|
const nsACString& aOrigin,
|
||||||
mozIStorageConnection** aConnection)
|
mozIStorageConnection** aConnection)
|
||||||
{
|
{
|
||||||
|
@ -1880,7 +1920,7 @@ OpenDatabaseHelper::CreateDatabaseConnection(
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIFileURL> dbFileUrl =
|
nsCOMPtr<nsIFileURL> dbFileUrl =
|
||||||
IDBFactory::GetDatabaseFileURL(aDBFile, aOrigin);
|
IDBFactory::GetDatabaseFileURL(aDBFile, aPersistenceType, aGroup, aOrigin);
|
||||||
NS_ENSURE_TRUE(dbFileUrl, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(dbFileUrl, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
nsCOMPtr<mozIStorageService> ss =
|
nsCOMPtr<mozIStorageService> ss =
|
||||||
|
@ -1950,7 +1990,12 @@ OpenDatabaseHelper::CreateDatabaseConnection(
|
||||||
// Turn on auto_vacuum mode to reclaim disk space on mobile devices.
|
// Turn on auto_vacuum mode to reclaim disk space on mobile devices.
|
||||||
"PRAGMA auto_vacuum = FULL; "
|
"PRAGMA auto_vacuum = FULL; "
|
||||||
));
|
));
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
if (rv == NS_ERROR_FILE_NO_DEVICE_SPACE) {
|
||||||
|
// mozstorage translates SQLITE_FULL to NS_ERROR_FILE_NO_DEVICE_SPACE,
|
||||||
|
// which we know better as NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR.
|
||||||
|
rv = NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
|
||||||
|
}
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2097,7 +2142,7 @@ OpenDatabaseHelper::StartDelete()
|
||||||
|
|
||||||
nsRefPtr<DeleteDatabaseHelper> helper =
|
nsRefPtr<DeleteDatabaseHelper> helper =
|
||||||
new DeleteDatabaseHelper(mOpenDBRequest, this, mCurrentVersion, mName,
|
new DeleteDatabaseHelper(mOpenDBRequest, this, mCurrentVersion, mName,
|
||||||
mASCIIOrigin);
|
mGroup, mASCIIOrigin, mPersistenceType);
|
||||||
|
|
||||||
QuotaManager* quotaManager = QuotaManager::Get();
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||||
|
@ -2122,6 +2167,10 @@ OpenDatabaseHelper::Run()
|
||||||
if (NS_IsMainThread()) {
|
if (NS_IsMainThread()) {
|
||||||
PROFILER_MAIN_THREAD_LABEL("IndexedDB", "OpenDatabaseHelper::Run");
|
PROFILER_MAIN_THREAD_LABEL("IndexedDB", "OpenDatabaseHelper::Run");
|
||||||
|
|
||||||
|
if (mState == eOpenPending) {
|
||||||
|
return DispatchToIOThread();
|
||||||
|
}
|
||||||
|
|
||||||
// If we need to queue up a SetVersionHelper, do that here.
|
// If we need to queue up a SetVersionHelper, do that here.
|
||||||
if (mState == eSetVersionPending) {
|
if (mState == eSetVersionPending) {
|
||||||
nsresult rv = StartSetVersion();
|
nsresult rv = StartSetVersion();
|
||||||
|
@ -2199,9 +2248,10 @@ OpenDatabaseHelper::Run()
|
||||||
QuotaManager* quotaManager = QuotaManager::Get();
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||||
|
|
||||||
quotaManager->AllowNextSynchronizedOp(
|
quotaManager->
|
||||||
OriginOrPatternString::FromOrigin(mASCIIOrigin),
|
AllowNextSynchronizedOp(OriginOrPatternString::FromOrigin(mASCIIOrigin),
|
||||||
mDatabaseId);
|
Nullable<PersistenceType>(mPersistenceType),
|
||||||
|
mDatabaseId);
|
||||||
|
|
||||||
ReleaseMainThreadObjects();
|
ReleaseMainThreadObjects();
|
||||||
|
|
||||||
|
@ -2242,6 +2292,7 @@ OpenDatabaseHelper::EnsureSuccessResult()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(dbInfo->name == mName &&
|
NS_ASSERTION(dbInfo->name == mName &&
|
||||||
dbInfo->version == mCurrentVersion &&
|
dbInfo->version == mCurrentVersion &&
|
||||||
|
dbInfo->persistenceType == mPersistenceType &&
|
||||||
dbInfo->id == mDatabaseId &&
|
dbInfo->id == mDatabaseId &&
|
||||||
dbInfo->filePath == mDatabaseFilePath,
|
dbInfo->filePath == mDatabaseFilePath,
|
||||||
"Metadata mismatch!");
|
"Metadata mismatch!");
|
||||||
|
@ -2284,7 +2335,9 @@ OpenDatabaseHelper::EnsureSuccessResult()
|
||||||
nsRefPtr<DatabaseInfo> newInfo(new DatabaseInfo());
|
nsRefPtr<DatabaseInfo> newInfo(new DatabaseInfo());
|
||||||
|
|
||||||
newInfo->name = mName;
|
newInfo->name = mName;
|
||||||
|
newInfo->group = mGroup;
|
||||||
newInfo->origin = mASCIIOrigin;
|
newInfo->origin = mASCIIOrigin;
|
||||||
|
newInfo->persistenceType = mPersistenceType;
|
||||||
newInfo->id = mDatabaseId;
|
newInfo->id = mDatabaseId;
|
||||||
newInfo->filePath = mDatabaseFilePath;
|
newInfo->filePath = mDatabaseFilePath;
|
||||||
|
|
||||||
|
@ -2576,7 +2629,8 @@ DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||||
NS_ASSERTION(quotaManager, "This should never fail!");
|
NS_ASSERTION(quotaManager, "This should never fail!");
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> directory;
|
nsCOMPtr<nsIFile> directory;
|
||||||
nsresult rv = quotaManager->GetDirectoryForOrigin(mASCIIOrigin,
|
nsresult rv = quotaManager->GetDirectoryForOrigin(mPersistenceType,
|
||||||
|
mASCIIOrigin,
|
||||||
getter_AddRefs(directory));
|
getter_AddRefs(directory));
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
|
@ -2615,7 +2669,8 @@ DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||||
QuotaManager* quotaManager = QuotaManager::Get();
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||||
|
|
||||||
quotaManager->DecreaseUsageForOrigin(mASCIIOrigin, fileSize);
|
quotaManager->DecreaseUsageForOrigin(mPersistenceType, mGroup,
|
||||||
|
mASCIIOrigin, fileSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2664,14 +2719,15 @@ DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||||
QuotaManager* quotaManager = QuotaManager::Get();
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||||
|
|
||||||
quotaManager->DecreaseUsageForOrigin(mASCIIOrigin, usage);
|
quotaManager->DecreaseUsageForOrigin(mPersistenceType, mGroup,
|
||||||
|
mASCIIOrigin, usage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||||
NS_ASSERTION(mgr, "This should never fail!");
|
NS_ASSERTION(mgr, "This should never fail!");
|
||||||
|
|
||||||
mgr->InvalidateFileManager(mASCIIOrigin, mName);
|
mgr->InvalidateFileManager(mPersistenceType, mASCIIOrigin, mName);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,18 +31,22 @@ class OpenDatabaseHelper : public HelperBase
|
||||||
{
|
{
|
||||||
friend class CheckPermissionsHelper;
|
friend class CheckPermissionsHelper;
|
||||||
|
|
||||||
|
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||||
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
|
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpenDatabaseHelper(IDBOpenDBRequest* aRequest,
|
OpenDatabaseHelper(IDBOpenDBRequest* aRequest,
|
||||||
const nsAString& aName,
|
const nsAString& aName,
|
||||||
|
const nsACString& aGroup,
|
||||||
const nsACString& aASCIIOrigin,
|
const nsACString& aASCIIOrigin,
|
||||||
uint64_t aRequestedVersion,
|
uint64_t aRequestedVersion,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
bool aForDeletion,
|
bool aForDeletion,
|
||||||
mozilla::dom::ContentParent* aContentParent,
|
mozilla::dom::ContentParent* aContentParent,
|
||||||
StoragePrivilege aPrivilege)
|
StoragePrivilege aPrivilege)
|
||||||
: HelperBase(aRequest), mOpenDBRequest(aRequest), mName(aName),
|
: HelperBase(aRequest), mOpenDBRequest(aRequest), mName(aName),
|
||||||
mASCIIOrigin(aASCIIOrigin), mRequestedVersion(aRequestedVersion),
|
mGroup(aGroup), mASCIIOrigin(aASCIIOrigin),
|
||||||
|
mRequestedVersion(aRequestedVersion), mPersistenceType(aPersistenceType),
|
||||||
mForDeletion(aForDeletion), mPrivilege(aPrivilege), mDatabaseId(nullptr),
|
mForDeletion(aForDeletion), mPrivilege(aPrivilege), mDatabaseId(nullptr),
|
||||||
mContentParent(aContentParent), mCurrentVersion(0), mLastObjectStoreId(0),
|
mContentParent(aContentParent), mCurrentVersion(0), mLastObjectStoreId(0),
|
||||||
mLastIndexId(0), mState(eCreated), mResultCode(NS_OK),
|
mLastIndexId(0), mState(eCreated), mResultCode(NS_OK),
|
||||||
|
@ -58,7 +62,9 @@ public:
|
||||||
|
|
||||||
nsresult Init();
|
nsresult Init();
|
||||||
|
|
||||||
|
nsresult WaitForOpenAllowed();
|
||||||
nsresult Dispatch(nsIEventTarget* aDatabaseThread);
|
nsresult Dispatch(nsIEventTarget* aDatabaseThread);
|
||||||
|
nsresult DispatchToIOThread();
|
||||||
nsresult RunImmediately();
|
nsresult RunImmediately();
|
||||||
|
|
||||||
void SetError(nsresult rv)
|
void SetError(nsresult rv)
|
||||||
|
@ -96,6 +102,8 @@ public:
|
||||||
nsresult CreateDatabaseConnection(nsIFile* aDBFile,
|
nsresult CreateDatabaseConnection(nsIFile* aDBFile,
|
||||||
nsIFile* aFMDirectory,
|
nsIFile* aFMDirectory,
|
||||||
const nsAString& aName,
|
const nsAString& aName,
|
||||||
|
PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
const nsACString& aOrigin,
|
const nsACString& aOrigin,
|
||||||
mozIStorageConnection** aConnection);
|
mozIStorageConnection** aConnection);
|
||||||
|
|
||||||
|
@ -122,8 +130,10 @@ protected:
|
||||||
// In-params.
|
// In-params.
|
||||||
nsRefPtr<IDBOpenDBRequest> mOpenDBRequest;
|
nsRefPtr<IDBOpenDBRequest> mOpenDBRequest;
|
||||||
nsString mName;
|
nsString mName;
|
||||||
|
nsCString mGroup;
|
||||||
nsCString mASCIIOrigin;
|
nsCString mASCIIOrigin;
|
||||||
uint64_t mRequestedVersion;
|
uint64_t mRequestedVersion;
|
||||||
|
PersistenceType mPersistenceType;
|
||||||
bool mForDeletion;
|
bool mForDeletion;
|
||||||
StoragePrivilege mPrivilege;
|
StoragePrivilege mPrivilege;
|
||||||
nsCOMPtr<nsIAtom> mDatabaseId;
|
nsCOMPtr<nsIAtom> mDatabaseId;
|
||||||
|
@ -140,6 +150,7 @@ protected:
|
||||||
// State variables
|
// State variables
|
||||||
enum OpenDatabaseState {
|
enum OpenDatabaseState {
|
||||||
eCreated = 0, // Not yet dispatched to the DB thread
|
eCreated = 0, // Not yet dispatched to the DB thread
|
||||||
|
eOpenPending, // Waiting for open allowed/open allowed
|
||||||
eDBWork, // Waiting to do/doing work on the DB thread
|
eDBWork, // Waiting to do/doing work on the DB thread
|
||||||
eFiringEvents, // Waiting to fire/firing events on the main thread
|
eFiringEvents, // Waiting to fire/firing events on the main thread
|
||||||
eSetVersionPending, // Waiting on a SetVersionHelper
|
eSetVersionPending, // Waiting on a SetVersionHelper
|
||||||
|
|
|
@ -210,8 +210,10 @@ IndexedDBChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||||
}
|
}
|
||||||
|
|
||||||
PIndexedDBDatabaseChild*
|
PIndexedDBDatabaseChild*
|
||||||
IndexedDBChild::AllocPIndexedDBDatabaseChild(const nsString& aName,
|
IndexedDBChild::AllocPIndexedDBDatabaseChild(
|
||||||
const uint64_t& aVersion)
|
const nsString& aName,
|
||||||
|
const uint64_t& aVersion,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
{
|
{
|
||||||
return new IndexedDBDatabaseChild(aName, aVersion);
|
return new IndexedDBDatabaseChild(aName, aVersion);
|
||||||
}
|
}
|
||||||
|
@ -224,7 +226,9 @@ IndexedDBChild::DeallocPIndexedDBDatabaseChild(PIndexedDBDatabaseChild* aActor)
|
||||||
}
|
}
|
||||||
|
|
||||||
PIndexedDBDeleteDatabaseRequestChild*
|
PIndexedDBDeleteDatabaseRequestChild*
|
||||||
IndexedDBChild::AllocPIndexedDBDeleteDatabaseRequestChild(const nsString& aName)
|
IndexedDBChild::AllocPIndexedDBDeleteDatabaseRequestChild(
|
||||||
|
const nsString& aName,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
{
|
{
|
||||||
MOZ_CRASH("Caller is supposed to manually construct a request!");
|
MOZ_CRASH("Caller is supposed to manually construct a request!");
|
||||||
}
|
}
|
||||||
|
@ -285,7 +289,8 @@ IndexedDBDatabaseChild::EnsureDatabase(
|
||||||
databaseId = mDatabase->Id();
|
databaseId = mDatabase->Id();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
databaseId = QuotaManager::GetStorageId(aDBInfo.origin, aDBInfo.name);
|
databaseId = QuotaManager::GetStorageId(aDBInfo.persistenceType,
|
||||||
|
aDBInfo.origin, aDBInfo.name);
|
||||||
}
|
}
|
||||||
NS_ENSURE_TRUE(databaseId, false);
|
NS_ENSURE_TRUE(databaseId, false);
|
||||||
|
|
||||||
|
|
|
@ -65,14 +65,18 @@ protected:
|
||||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual PIndexedDBDatabaseChild*
|
virtual PIndexedDBDatabaseChild*
|
||||||
AllocPIndexedDBDatabaseChild(const nsString& aName, const uint64_t& aVersion)
|
AllocPIndexedDBDatabaseChild(const nsString& aName, const uint64_t& aVersion,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
MOZ_OVERRIDE;
|
MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
DeallocPIndexedDBDatabaseChild(PIndexedDBDatabaseChild* aActor) MOZ_OVERRIDE;
|
DeallocPIndexedDBDatabaseChild(PIndexedDBDatabaseChild* aActor) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual PIndexedDBDeleteDatabaseRequestChild*
|
virtual PIndexedDBDeleteDatabaseRequestChild*
|
||||||
AllocPIndexedDBDeleteDatabaseRequestChild(const nsString& aName) MOZ_OVERRIDE;
|
AllocPIndexedDBDeleteDatabaseRequestChild(
|
||||||
|
const nsString& aName,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
|
MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
DeallocPIndexedDBDeleteDatabaseRequestChild(
|
DeallocPIndexedDBDeleteDatabaseRequestChild(
|
||||||
|
|
|
@ -144,9 +144,10 @@ IndexedDBParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IndexedDBParent::RecvPIndexedDBDatabaseConstructor(
|
IndexedDBParent::RecvPIndexedDBDatabaseConstructor(
|
||||||
PIndexedDBDatabaseParent* aActor,
|
PIndexedDBDatabaseParent* aActor,
|
||||||
const nsString& aName,
|
const nsString& aName,
|
||||||
const uint64_t& aVersion)
|
const uint64_t& aVersion,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
{
|
{
|
||||||
if (!CheckReadPermission(aName)) {
|
if (!CheckReadPermission(aName)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -162,8 +163,8 @@ IndexedDBParent::RecvPIndexedDBDatabaseConstructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<IDBOpenDBRequest> request;
|
nsRefPtr<IDBOpenDBRequest> request;
|
||||||
nsresult rv =
|
nsresult rv = mFactory->OpenInternal(aName, aVersion, aPersistenceType, false,
|
||||||
mFactory->OpenInternal(aName, aVersion, false, getter_AddRefs(request));
|
getter_AddRefs(request));
|
||||||
NS_ENSURE_SUCCESS(rv, false);
|
NS_ENSURE_SUCCESS(rv, false);
|
||||||
|
|
||||||
IndexedDBDatabaseParent* actor =
|
IndexedDBDatabaseParent* actor =
|
||||||
|
@ -178,7 +179,8 @@ IndexedDBParent::RecvPIndexedDBDatabaseConstructor(
|
||||||
bool
|
bool
|
||||||
IndexedDBParent::RecvPIndexedDBDeleteDatabaseRequestConstructor(
|
IndexedDBParent::RecvPIndexedDBDeleteDatabaseRequestConstructor(
|
||||||
PIndexedDBDeleteDatabaseRequestParent* aActor,
|
PIndexedDBDeleteDatabaseRequestParent* aActor,
|
||||||
const nsString& aName)
|
const nsString& aName,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
{
|
{
|
||||||
if (!CheckWritePermission(aName)) {
|
if (!CheckWritePermission(aName)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -198,8 +200,8 @@ IndexedDBParent::RecvPIndexedDBDeleteDatabaseRequestConstructor(
|
||||||
|
|
||||||
nsRefPtr<IDBOpenDBRequest> request;
|
nsRefPtr<IDBOpenDBRequest> request;
|
||||||
|
|
||||||
nsresult rv =
|
nsresult rv = mFactory->OpenInternal(aName, 0, aPersistenceType, true,
|
||||||
mFactory->OpenInternal(aName, 0, true, getter_AddRefs(request));
|
getter_AddRefs(request));
|
||||||
NS_ENSURE_SUCCESS(rv, false);
|
NS_ENSURE_SUCCESS(rv, false);
|
||||||
|
|
||||||
rv = actor->SetOpenRequest(request);
|
rv = actor->SetOpenRequest(request);
|
||||||
|
@ -209,8 +211,10 @@ IndexedDBParent::RecvPIndexedDBDeleteDatabaseRequestConstructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
PIndexedDBDatabaseParent*
|
PIndexedDBDatabaseParent*
|
||||||
IndexedDBParent::AllocPIndexedDBDatabaseParent(const nsString& aName,
|
IndexedDBParent::AllocPIndexedDBDatabaseParent(
|
||||||
const uint64_t& aVersion)
|
const nsString& aName,
|
||||||
|
const uint64_t& aVersion,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
{
|
{
|
||||||
return new IndexedDBDatabaseParent();
|
return new IndexedDBDatabaseParent();
|
||||||
}
|
}
|
||||||
|
@ -223,7 +227,9 @@ IndexedDBParent::DeallocPIndexedDBDatabaseParent(PIndexedDBDatabaseParent* aActo
|
||||||
}
|
}
|
||||||
|
|
||||||
PIndexedDBDeleteDatabaseRequestParent*
|
PIndexedDBDeleteDatabaseRequestParent*
|
||||||
IndexedDBParent::AllocPIndexedDBDeleteDatabaseRequestParent(const nsString& aName)
|
IndexedDBParent::AllocPIndexedDBDeleteDatabaseRequestParent(
|
||||||
|
const nsString& aName,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
{
|
{
|
||||||
return new IndexedDBDeleteDatabaseRequestParent(mFactory);
|
return new IndexedDBDeleteDatabaseRequestParent(mFactory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,22 +205,30 @@ protected:
|
||||||
virtual bool
|
virtual bool
|
||||||
RecvPIndexedDBDatabaseConstructor(PIndexedDBDatabaseParent* aActor,
|
RecvPIndexedDBDatabaseConstructor(PIndexedDBDatabaseParent* aActor,
|
||||||
const nsString& aName,
|
const nsString& aName,
|
||||||
const uint64_t& aVersion) MOZ_OVERRIDE;
|
const uint64_t& aVersion,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
|
MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
RecvPIndexedDBDeleteDatabaseRequestConstructor(
|
RecvPIndexedDBDeleteDatabaseRequestConstructor(
|
||||||
PIndexedDBDeleteDatabaseRequestParent* aActor,
|
PIndexedDBDeleteDatabaseRequestParent* aActor,
|
||||||
const nsString& aName) MOZ_OVERRIDE;
|
const nsString& aName,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
|
MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual PIndexedDBDatabaseParent*
|
virtual PIndexedDBDatabaseParent*
|
||||||
AllocPIndexedDBDatabaseParent(const nsString& aName, const uint64_t& aVersion)
|
AllocPIndexedDBDatabaseParent(const nsString& aName, const uint64_t& aVersion,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
MOZ_OVERRIDE;
|
MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
DeallocPIndexedDBDatabaseParent(PIndexedDBDatabaseParent* aActor) MOZ_OVERRIDE;
|
DeallocPIndexedDBDatabaseParent(PIndexedDBDatabaseParent* aActor) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual PIndexedDBDeleteDatabaseRequestParent*
|
virtual PIndexedDBDeleteDatabaseRequestParent*
|
||||||
AllocPIndexedDBDeleteDatabaseRequestParent(const nsString& aName) MOZ_OVERRIDE;
|
AllocPIndexedDBDeleteDatabaseRequestParent(
|
||||||
|
const nsString& aName,
|
||||||
|
const PersistenceType& aPersistenceType)
|
||||||
|
MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
DeallocPIndexedDBDeleteDatabaseRequestParent(
|
DeallocPIndexedDBDeleteDatabaseRequestParent(
|
||||||
|
|
|
@ -7,6 +7,10 @@ include protocol PContent;
|
||||||
include protocol PIndexedDBDatabase;
|
include protocol PIndexedDBDatabase;
|
||||||
include protocol PIndexedDBDeleteDatabaseRequest;
|
include protocol PIndexedDBDeleteDatabaseRequest;
|
||||||
|
|
||||||
|
include "mozilla/dom/indexedDB/SerializationHelpers.h";
|
||||||
|
|
||||||
|
using mozilla::dom::quota::PersistenceType;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
namespace indexedDB {
|
namespace indexedDB {
|
||||||
|
@ -21,9 +25,11 @@ protocol PIndexedDB
|
||||||
parent:
|
parent:
|
||||||
__delete__();
|
__delete__();
|
||||||
|
|
||||||
PIndexedDBDatabase(nsString name, uint64_t version);
|
PIndexedDBDatabase(nsString name, uint64_t version,
|
||||||
|
PersistenceType persistenceType);
|
||||||
|
|
||||||
PIndexedDBDeleteDatabaseRequest(nsString name);
|
PIndexedDBDeleteDatabaseRequest(nsString name,
|
||||||
|
PersistenceType persistenceType);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace indexedDB
|
} // namespace indexedDB
|
||||||
|
|
|
@ -15,6 +15,13 @@
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ParamTraits<mozilla::dom::quota::PersistenceType> :
|
||||||
|
public EnumSerializer<mozilla::dom::quota::PersistenceType,
|
||||||
|
mozilla::dom::quota::PERSISTENCE_TYPE_PERSISTENT,
|
||||||
|
mozilla::dom::quota::PERSISTENCE_TYPE_INVALID>
|
||||||
|
{ };
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct ParamTraits<mozilla::dom::indexedDB::Key>
|
struct ParamTraits<mozilla::dom::indexedDB::Key>
|
||||||
{
|
{
|
||||||
|
@ -154,8 +161,10 @@ struct ParamTraits<mozilla::dom::indexedDB::DatabaseInfoGuts>
|
||||||
static void Write(Message* aMsg, const paramType& aParam)
|
static void Write(Message* aMsg, const paramType& aParam)
|
||||||
{
|
{
|
||||||
WriteParam(aMsg, aParam.name);
|
WriteParam(aMsg, aParam.name);
|
||||||
|
WriteParam(aMsg, aParam.group);
|
||||||
WriteParam(aMsg, aParam.origin);
|
WriteParam(aMsg, aParam.origin);
|
||||||
WriteParam(aMsg, aParam.version);
|
WriteParam(aMsg, aParam.version);
|
||||||
|
WriteParam(aMsg, aParam.persistenceType);
|
||||||
WriteParam(aMsg, aParam.nextObjectStoreId);
|
WriteParam(aMsg, aParam.nextObjectStoreId);
|
||||||
WriteParam(aMsg, aParam.nextIndexId);
|
WriteParam(aMsg, aParam.nextIndexId);
|
||||||
}
|
}
|
||||||
|
@ -163,8 +172,10 @@ struct ParamTraits<mozilla::dom::indexedDB::DatabaseInfoGuts>
|
||||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||||
{
|
{
|
||||||
return ReadParam(aMsg, aIter, &aResult->name) &&
|
return ReadParam(aMsg, aIter, &aResult->name) &&
|
||||||
|
ReadParam(aMsg, aIter, &aResult->group) &&
|
||||||
ReadParam(aMsg, aIter, &aResult->origin) &&
|
ReadParam(aMsg, aIter, &aResult->origin) &&
|
||||||
ReadParam(aMsg, aIter, &aResult->version) &&
|
ReadParam(aMsg, aIter, &aResult->version) &&
|
||||||
|
ReadParam(aMsg, aIter, &aResult->persistenceType) &&
|
||||||
ReadParam(aMsg, aIter, &aResult->nextObjectStoreId) &&
|
ReadParam(aMsg, aIter, &aResult->nextObjectStoreId) &&
|
||||||
ReadParam(aMsg, aIter, &aResult->nextIndexId);
|
ReadParam(aMsg, aIter, &aResult->nextIndexId);
|
||||||
}
|
}
|
||||||
|
@ -172,6 +183,7 @@ struct ParamTraits<mozilla::dom::indexedDB::DatabaseInfoGuts>
|
||||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||||
{
|
{
|
||||||
LogParam(aParam.name, aLog);
|
LogParam(aParam.name, aLog);
|
||||||
|
LogParam(aParam.group, aLog);
|
||||||
LogParam(aParam.origin, aLog);
|
LogParam(aParam.origin, aLog);
|
||||||
LogParam(aParam.version, aLog);
|
LogParam(aParam.version, aLog);
|
||||||
LogParam(aParam.nextObjectStoreId, aLog);
|
LogParam(aParam.nextObjectStoreId, aLog);
|
||||||
|
|
|
@ -79,6 +79,7 @@ MOCHITEST_FILES = \
|
||||||
test_open_objectStore.html \
|
test_open_objectStore.html \
|
||||||
test_optionalArguments.html \
|
test_optionalArguments.html \
|
||||||
test_overlapping_transactions.html \
|
test_overlapping_transactions.html \
|
||||||
|
test_persistenceType.html \
|
||||||
test_put_get_values.html \
|
test_put_get_values.html \
|
||||||
test_put_get_values_autoIncrement.html \
|
test_put_get_values_autoIncrement.html \
|
||||||
test_readonly_transactions.html \
|
test_readonly_transactions.html \
|
||||||
|
|
|
@ -190,11 +190,6 @@ function getUsage(usageHandler)
|
||||||
quotaManager.getUsageForURI(uri, cb);
|
quotaManager.getUsageForURI(uri, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
function scheduleGC()
|
|
||||||
{
|
|
||||||
SpecialPowers.exactGC(window, continueToNextStep);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFileId(file)
|
function getFileId(file)
|
||||||
{
|
{
|
||||||
return utils.getFileId(file);
|
return utils.getFileId(file);
|
||||||
|
@ -208,13 +203,13 @@ function hasFileInfo(name, id)
|
||||||
function getFileRefCount(name, id)
|
function getFileRefCount(name, id)
|
||||||
{
|
{
|
||||||
let count = {};
|
let count = {};
|
||||||
utils.getFileReferences(name, id, count);
|
utils.getFileReferences(name, id, null, count);
|
||||||
return count.value;
|
return count.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFileDBRefCount(name, id)
|
function getFileDBRefCount(name, id)
|
||||||
{
|
{
|
||||||
let count = {};
|
let count = {};
|
||||||
utils.getFileReferences(name, id, {}, count);
|
utils.getFileReferences(name, id, null, {}, count);
|
||||||
return count.value;
|
return count.value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@ if (!window.runTest) {
|
||||||
allowUnlimitedQuota();
|
allowUnlimitedQuota();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enableExperimental();
|
||||||
enableArchiveReader();
|
enableArchiveReader();
|
||||||
|
|
||||||
clearAllDatabases(function () { testGenerator.next(); });
|
clearAllDatabases(function () { testGenerator.next(); });
|
||||||
|
@ -93,6 +94,7 @@ if (!window.runTest) {
|
||||||
function finishTest()
|
function finishTest()
|
||||||
{
|
{
|
||||||
resetUnlimitedQuota();
|
resetUnlimitedQuota();
|
||||||
|
resetExperimental();
|
||||||
resetArchiveReader();
|
resetArchiveReader();
|
||||||
SpecialPowers.notifyObserversInParentProcess(null, "disk-space-watcher",
|
SpecialPowers.notifyObserversInParentProcess(null, "disk-space-watcher",
|
||||||
"free");
|
"free");
|
||||||
|
@ -253,8 +255,23 @@ function resetArchiveReader()
|
||||||
SpecialPowers.setBoolPref("dom.archivereader.enabled", archiveReaderEnabled);
|
SpecialPowers.setBoolPref("dom.archivereader.enabled", archiveReaderEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function enableExperimental()
|
||||||
|
{
|
||||||
|
SpecialPowers.setBoolPref("dom.indexedDB.experimental", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetExperimental()
|
||||||
|
{
|
||||||
|
SpecialPowers.clearUserPref("dom.indexedDB.experimental");
|
||||||
|
}
|
||||||
|
|
||||||
function gc()
|
function gc()
|
||||||
{
|
{
|
||||||
SpecialPowers.forceGC();
|
SpecialPowers.forceGC();
|
||||||
SpecialPowers.forceCC();
|
SpecialPowers.forceCC();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function scheduleGC()
|
||||||
|
{
|
||||||
|
SpecialPowers.exactGC(window, continueToNextStep);
|
||||||
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
for (let id = 1; id <= 100; id++) {
|
for (let id = 1; id <= 100; id++) {
|
||||||
let refs = {};
|
let refs = {};
|
||||||
let dbRefs = {};
|
let dbRefs = {};
|
||||||
let hasFileInfo = utils.getFileReferences(name, id, refs, dbRefs);
|
let hasFileInfo = utils.getFileReferences(name, id, null, refs, dbRefs);
|
||||||
ok(hasFileInfo, "Has file info");
|
ok(hasFileInfo, "Has file info");
|
||||||
is(refs.value, 1, "Correct ref count");
|
is(refs.value, 1, "Correct ref count");
|
||||||
is(dbRefs.value, id / 100 >> 0, "Correct db ref count");
|
is(dbRefs.value, id / 100 >> 0, "Correct db ref count");
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Indexed Database Property Test</title>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
|
||||||
|
<script type="text/javascript;version=1.7">
|
||||||
|
function testSteps()
|
||||||
|
{
|
||||||
|
const name = window.location.pathname;
|
||||||
|
const version = 1;
|
||||||
|
|
||||||
|
const objectStoreName = "Foo";
|
||||||
|
const data = { key: 1, value: "bar" };
|
||||||
|
|
||||||
|
try {
|
||||||
|
indexedDB.open(name, { version: version, storage: "unknown" });
|
||||||
|
ok(false, "Should have thrown!");
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
ok(e instanceof TypeError, "Got TypeError.");
|
||||||
|
is(e.name, "TypeError", "Good error name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let request = indexedDB.open(name, { version: version,
|
||||||
|
storage: "persistent" });
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
let event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "upgradeneeded", "Got correct event type");
|
||||||
|
|
||||||
|
let db = event.target.result;
|
||||||
|
db.onerror = errorHandler;
|
||||||
|
|
||||||
|
let objectStore = db.createObjectStore(objectStoreName, { });
|
||||||
|
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "success", "Got correct event type");
|
||||||
|
|
||||||
|
is(db.name, name, "Correct name");
|
||||||
|
is(db.version, version, "Correct version");
|
||||||
|
is(db.storage, "persistent", "Correct persistence type");
|
||||||
|
|
||||||
|
objectStore = db.transaction([objectStoreName], "readwrite")
|
||||||
|
.objectStore(objectStoreName);
|
||||||
|
|
||||||
|
request = objectStore.get(data.key);
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.target.result, null, "Got no data");
|
||||||
|
|
||||||
|
request = objectStore.add(data.value, data.key);
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.target.result, data.key, "Got correct key");
|
||||||
|
|
||||||
|
request = indexedDB.open(name, { version: version,
|
||||||
|
storage: "temporary" });
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
let event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "upgradeneeded", "Got correct event type");
|
||||||
|
|
||||||
|
db = event.target.result;
|
||||||
|
db.onerror = errorHandler;
|
||||||
|
|
||||||
|
objectStore = db.createObjectStore(objectStoreName, { });
|
||||||
|
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "success", "Got correct event type");
|
||||||
|
|
||||||
|
is(db.name, name, "Correct name");
|
||||||
|
is(db.version, version, "Correct version");
|
||||||
|
is(db.storage, "temporary", "Correct persistence type");
|
||||||
|
|
||||||
|
objectStore = db.transaction([objectStoreName])
|
||||||
|
.objectStore(objectStoreName);
|
||||||
|
|
||||||
|
request = objectStore.get(data.key);
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.target.result, null, "Got no data");
|
||||||
|
|
||||||
|
finishTest();
|
||||||
|
yield undefined;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="runTest();"></body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -46,6 +46,7 @@ MOCHITEST_FILES = \
|
||||||
test_open_objectStore.js \
|
test_open_objectStore.js \
|
||||||
test_optionalArguments.js \
|
test_optionalArguments.js \
|
||||||
test_overlapping_transactions.js \
|
test_overlapping_transactions.js \
|
||||||
|
test_persistenceType.js \
|
||||||
test_put_get_values.js \
|
test_put_get_values.js \
|
||||||
test_put_get_values_autoIncrement.js \
|
test_put_get_values_autoIncrement.js \
|
||||||
test_readonly_transactions.js \
|
test_readonly_transactions.js \
|
||||||
|
@ -57,6 +58,7 @@ MOCHITEST_FILES = \
|
||||||
test_setVersion_events.js \
|
test_setVersion_events.js \
|
||||||
test_setVersion_exclusion.js \
|
test_setVersion_exclusion.js \
|
||||||
test_success_events_after_abort.js \
|
test_success_events_after_abort.js \
|
||||||
|
test_temporary_storage.js \
|
||||||
test_traffic_jam.js \
|
test_traffic_jam.js \
|
||||||
test_transaction_abort.js \
|
test_transaction_abort.js \
|
||||||
test_transaction_abort_hang.js \
|
test_transaction_abort_hang.js \
|
||||||
|
|
|
@ -47,16 +47,20 @@ function runTest()
|
||||||
getService(Ci.nsIIndexedDatabaseManager);
|
getService(Ci.nsIIndexedDatabaseManager);
|
||||||
idbManager.initWindowless(this);
|
idbManager.initWindowless(this);
|
||||||
|
|
||||||
|
enableExperimental();
|
||||||
|
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
testGenerator.next();
|
testGenerator.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
function finishTest()
|
function finishTest()
|
||||||
{
|
{
|
||||||
|
resetExperimental();
|
||||||
|
SpecialPowers.notifyObserversInParentProcess(null, "disk-space-watcher",
|
||||||
|
"free");
|
||||||
|
|
||||||
do_execute_soon(function(){
|
do_execute_soon(function(){
|
||||||
testGenerator.close();
|
testGenerator.close();
|
||||||
SpecialPowers.notifyObserversInParentProcess(null, "disk-space-watcher",
|
|
||||||
"free");
|
|
||||||
do_test_finished();
|
do_test_finished();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -179,12 +183,27 @@ function disallowUnlimitedQuota(url)
|
||||||
throw "disallowUnlimitedQuota";
|
throw "disallowUnlimitedQuota";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function enableExperimental()
|
||||||
|
{
|
||||||
|
SpecialPowers.setBoolPref("dom.indexedDB.experimental", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetExperimental()
|
||||||
|
{
|
||||||
|
SpecialPowers.clearUserPref("dom.indexedDB.experimental");
|
||||||
|
}
|
||||||
|
|
||||||
function gc()
|
function gc()
|
||||||
{
|
{
|
||||||
Components.utils.forceGC();
|
Components.utils.forceGC();
|
||||||
Components.utils.forceCC();
|
Components.utils.forceCC();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function scheduleGC()
|
||||||
|
{
|
||||||
|
SpecialPowers.exactGC(null, continueToNextStep);
|
||||||
|
}
|
||||||
|
|
||||||
function setTimeout(fun, timeout) {
|
function setTimeout(fun, timeout) {
|
||||||
let timer = Components.classes["@mozilla.org/timer;1"]
|
let timer = Components.classes["@mozilla.org/timer;1"]
|
||||||
.createInstance(Components.interfaces.nsITimer);
|
.createInstance(Components.interfaces.nsITimer);
|
||||||
|
@ -214,5 +233,43 @@ var SpecialPowers = {
|
||||||
throw new Error("Can't send subject to another process!");
|
throw new Error("Can't send subject to another process!");
|
||||||
}
|
}
|
||||||
return this.notifyObservers(subject, topic, data);
|
return this.notifyObservers(subject, topic, data);
|
||||||
|
},
|
||||||
|
getBoolPref: function(prefName) {
|
||||||
|
return this._getPrefs().getBoolPref(prefName);
|
||||||
|
},
|
||||||
|
setBoolPref: function(prefName, value) {
|
||||||
|
this._getPrefs().setBoolPref(prefName, value);
|
||||||
|
},
|
||||||
|
setIntPref: function(prefName, value) {
|
||||||
|
this._getPrefs().setIntPref(prefName, value);
|
||||||
|
},
|
||||||
|
clearUserPref: function(prefName) {
|
||||||
|
this._getPrefs().clearUserPref(prefName);
|
||||||
|
},
|
||||||
|
// Copied (and slightly adjusted) from specialpowersAPI.js
|
||||||
|
exactGC: function(win, callback) {
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
function doPreciseGCandCC() {
|
||||||
|
function scheduledGCCallback() {
|
||||||
|
Components.utils.forceCC();
|
||||||
|
|
||||||
|
if (++count < 2) {
|
||||||
|
doPreciseGCandCC();
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Components.utils.schedulePreciseGC(scheduledGCCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
doPreciseGCandCC();
|
||||||
|
},
|
||||||
|
|
||||||
|
_getPrefs: function() {
|
||||||
|
var prefService =
|
||||||
|
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
|
||||||
|
return prefService.getBranch(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,24 @@ function testSteps()
|
||||||
is(e.name, "TypeError", "Good error name.");
|
is(e.name, "TypeError", "Good error name.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
indexedDB.open(name, { version: 0 });
|
||||||
|
ok(false, "Should have thrown!");
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
ok(e instanceof TypeError, "Got TypeError.");
|
||||||
|
is(e.name, "TypeError", "Good error name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
indexedDB.open(name, { version: -1 });
|
||||||
|
ok(false, "Should have thrown!");
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
ok(e instanceof TypeError, "Got TypeError.");
|
||||||
|
is(e.name, "TypeError", "Good error name.");
|
||||||
|
}
|
||||||
|
|
||||||
finishTest();
|
finishTest();
|
||||||
yield undefined;
|
yield undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/**
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
var testGenerator = testSteps();
|
||||||
|
|
||||||
|
function testSteps()
|
||||||
|
{
|
||||||
|
const name = "Splendid Test";
|
||||||
|
const version = 1;
|
||||||
|
|
||||||
|
const objectStoreName = "Foo";
|
||||||
|
const data = { key: 1, value: "bar" };
|
||||||
|
|
||||||
|
try {
|
||||||
|
indexedDB.open(name, { version: version, storage: "unknown" });
|
||||||
|
ok(false, "Should have thrown!");
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
ok(e instanceof TypeError, "Got TypeError.");
|
||||||
|
is(e.name, "TypeError", "Good error name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let request = indexedDB.open(name, { version: version,
|
||||||
|
storage: "persistent" });
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
let event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "upgradeneeded", "Got correct event type");
|
||||||
|
|
||||||
|
let db = event.target.result;
|
||||||
|
db.onerror = errorHandler;
|
||||||
|
|
||||||
|
let objectStore = db.createObjectStore(objectStoreName, { });
|
||||||
|
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "success", "Got correct event type");
|
||||||
|
|
||||||
|
is(db.name, name, "Correct name");
|
||||||
|
is(db.version, version, "Correct version");
|
||||||
|
is(db.storage, "persistent", "Correct persistence type");
|
||||||
|
|
||||||
|
objectStore = db.transaction([objectStoreName], "readwrite")
|
||||||
|
.objectStore(objectStoreName);
|
||||||
|
|
||||||
|
request = objectStore.get(data.key);
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.target.result, null, "Got no data");
|
||||||
|
|
||||||
|
request = objectStore.add(data.value, data.key);
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.target.result, data.key, "Got correct key");
|
||||||
|
|
||||||
|
request = indexedDB.open(name, { version: version,
|
||||||
|
storage: "temporary" });
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
let event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "success", "Got correct event type");
|
||||||
|
|
||||||
|
is(db.name, name, "Correct name");
|
||||||
|
is(db.version, version, "Correct version");
|
||||||
|
is(db.storage, "persistent", "Correct persistence type");
|
||||||
|
|
||||||
|
objectStore = db.transaction([objectStoreName])
|
||||||
|
.objectStore(objectStoreName);
|
||||||
|
|
||||||
|
request = objectStore.get(data.key);
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.target.result, data.value, "Got correct data");
|
||||||
|
|
||||||
|
finishTest();
|
||||||
|
yield undefined;
|
||||||
|
}
|
|
@ -0,0 +1,225 @@
|
||||||
|
/**
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
var testGenerator = testSteps();
|
||||||
|
|
||||||
|
function testSteps()
|
||||||
|
{
|
||||||
|
const name = this.window ? window.location.pathname : "Splendid Test";
|
||||||
|
|
||||||
|
const urls = [
|
||||||
|
{ url: "http://www.alpha.com", flags: [true, true, false, false] },
|
||||||
|
{ url: "http://www.beta.com", flags: [true, false, false, false] },
|
||||||
|
{ url: "http://www.gamma.com", flags: [true, true, false, false] },
|
||||||
|
{ url: "http://www.delta.com", flags: [true, true, false, false] },
|
||||||
|
{ url: "http://www.epsilon.com", flags: [true, true, false, false] },
|
||||||
|
{ url: "http://www2.alpha.com", flags: [true, true, false, false] },
|
||||||
|
{ url: "http://www2.beta.com", flags: [true, true, false, false] },
|
||||||
|
{ url: "http://www2.gamma.com", flags: [true, true, true, false] },
|
||||||
|
{ url: "http://www2.delta.com", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://www2.epsilon.com", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://joe.blog.alpha.com", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://joe.blog.beta.com", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://joe.blog.gamma.com", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://joe.blog.delta.com", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://joe.blog.epsilon.com", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://www.rudolf.org", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://www.pauline.org", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://www.marie.org", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://www.john.org", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://www.ema.org", flags: [true, true, true, true] },
|
||||||
|
{ url: "http://www.trigger.com", flags: [false, true, true, true] }
|
||||||
|
];
|
||||||
|
const lastIndex = urls.length - 1;
|
||||||
|
const lastUrl = urls[lastIndex].url;
|
||||||
|
|
||||||
|
let quotaManager =
|
||||||
|
Components.classes["@mozilla.org/dom/quota/manager;1"]
|
||||||
|
.getService(Components.interfaces.nsIQuotaManager);
|
||||||
|
|
||||||
|
let ioService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||||
|
.getService(Components.interfaces.nsIIOService);
|
||||||
|
|
||||||
|
let dbSize = 0;
|
||||||
|
|
||||||
|
let databases = [];
|
||||||
|
|
||||||
|
function setLimit(limit) {
|
||||||
|
if (limit) {
|
||||||
|
SpecialPowers.setIntPref("dom.quotaManager.temporaryStorage.fixedLimit",
|
||||||
|
limit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SpecialPowers.clearUserPref("dom.quotaManager.temporaryStorage.fixedLimit");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPrincipal(url) {
|
||||||
|
let uri = ioService.newURI(url, null, null);
|
||||||
|
return Components.classes["@mozilla.org/scriptsecuritymanager;1"]
|
||||||
|
.getService(Components.interfaces.nsIScriptSecurityManager)
|
||||||
|
.getNoAppCodebasePrincipal(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUsageForUrl(url, usageHandler) {
|
||||||
|
let uri = ioService.newURI(url, null, null);
|
||||||
|
function callback(uri, usage, fileUsage) {
|
||||||
|
usageHandler(usage, fileUsage);
|
||||||
|
}
|
||||||
|
quotaManager.getUsageForURI(uri, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function grabUsageAndContinueHandler(usage, fileUsage) {
|
||||||
|
testGenerator.send(usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkUsage(stageIndex) {
|
||||||
|
let handledIndex = 0;
|
||||||
|
|
||||||
|
function usageHandler(usage, fileUsage) {
|
||||||
|
if (urls[handledIndex].flags[stageIndex - 1]) {
|
||||||
|
ok(usage > 0, "Correct usage");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ok(usage == 0, "Correct usage");
|
||||||
|
}
|
||||||
|
if (++handledIndex == urls.length) {
|
||||||
|
continueToNextStep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < urls.length; i++) {
|
||||||
|
getUsageForUrl(urls[i].url, usageHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable clear() and test()
|
||||||
|
let testingEnabled =
|
||||||
|
SpecialPowers.getBoolPref("dom.quotaManager.testing");
|
||||||
|
SpecialPowers.setBoolPref("dom.quotaManager.testing", true)
|
||||||
|
|
||||||
|
// Calibration
|
||||||
|
let request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name,
|
||||||
|
{ storage: "temporary" });
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
let event = yield undefined;
|
||||||
|
|
||||||
|
getUsageForUrl(lastUrl, grabUsageAndContinueHandler);
|
||||||
|
dbSize = yield undefined;
|
||||||
|
|
||||||
|
setLimit(lastIndex * dbSize / 1024);
|
||||||
|
quotaManager.clear();
|
||||||
|
|
||||||
|
// Stage 1
|
||||||
|
for (let i = 0; i < lastIndex; i++) {
|
||||||
|
let data = urls[i];
|
||||||
|
|
||||||
|
request = indexedDB.openForPrincipal(getPrincipal(data.url), name,
|
||||||
|
{ storage: "temporary" });
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "upgradeneeded", "Got correct event type");
|
||||||
|
|
||||||
|
let db = event.target.result;
|
||||||
|
db.createObjectStore("foo", { });
|
||||||
|
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "success", "Got correct event type");
|
||||||
|
|
||||||
|
databases.push(event.target.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name,
|
||||||
|
{ storage: "temporary" });
|
||||||
|
request.addEventListener("error", new ExpectError("QuotaExceededError"));
|
||||||
|
request.onsuccess = unexpectedSuccessHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
checkUsage(1);
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
// Stage 2
|
||||||
|
for (let i = 1; i < urls.length; i++) {
|
||||||
|
databases[i] = null;
|
||||||
|
|
||||||
|
scheduleGC();
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
// The origin access time is set to the current system time when the first
|
||||||
|
// database for an origin is registered or the last one is unregistered.
|
||||||
|
// The registration happens when the database object is being created and
|
||||||
|
// the unregistration when it is unlinked/garbage collected.
|
||||||
|
// Some older windows systems have the system time limited to a maximum
|
||||||
|
// resolution of 10 or 15 milliseconds, so without a pause here we would
|
||||||
|
// end up with origins with the same access time which would cause random
|
||||||
|
// failures.
|
||||||
|
setTimeout(function() { testGenerator.next(); }, 20);
|
||||||
|
yield undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name,
|
||||||
|
{ storage: "temporary" });
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "upgradeneeded", "Got correct event type");
|
||||||
|
|
||||||
|
let db = event.target.result;
|
||||||
|
db.createObjectStore("foo", { });
|
||||||
|
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "success", "Got correct event type");
|
||||||
|
|
||||||
|
checkUsage(2);
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
// Stage 3
|
||||||
|
setLimit(14 * dbSize / 1024);
|
||||||
|
quotaManager.reset();
|
||||||
|
|
||||||
|
request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name,
|
||||||
|
{ storage: "temporary" });
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
is(event.type, "success", "Got correct event type");
|
||||||
|
|
||||||
|
let db = event.target.result;
|
||||||
|
|
||||||
|
checkUsage(3);
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
// Stage 4
|
||||||
|
let trans = db.transaction(["foo"], "readwrite");
|
||||||
|
|
||||||
|
let blob = Blob(["bar"]);
|
||||||
|
request = trans.objectStore("foo").add(blob, 42);
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
trans.oncomplete = grabEventAndContinueHandler;
|
||||||
|
event = yield undefined;
|
||||||
|
|
||||||
|
checkUsage(4);
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
setLimit();
|
||||||
|
quotaManager.reset();
|
||||||
|
|
||||||
|
SpecialPowers.setBoolPref("dom.quotaManager.testing", testingEnabled);
|
||||||
|
|
||||||
|
finishTest();
|
||||||
|
yield undefined;
|
||||||
|
}
|
|
@ -47,6 +47,7 @@ tail =
|
||||||
[test_open_objectStore.js]
|
[test_open_objectStore.js]
|
||||||
[test_optionalArguments.js]
|
[test_optionalArguments.js]
|
||||||
[test_overlapping_transactions.js]
|
[test_overlapping_transactions.js]
|
||||||
|
[test_persistenceType.js]
|
||||||
[test_put_get_values.js]
|
[test_put_get_values.js]
|
||||||
[test_put_get_values_autoIncrement.js]
|
[test_put_get_values_autoIncrement.js]
|
||||||
[test_readonly_transactions.js]
|
[test_readonly_transactions.js]
|
||||||
|
@ -58,6 +59,7 @@ tail =
|
||||||
[test_setVersion_events.js]
|
[test_setVersion_events.js]
|
||||||
[test_setVersion_exclusion.js]
|
[test_setVersion_exclusion.js]
|
||||||
[test_success_events_after_abort.js]
|
[test_success_events_after_abort.js]
|
||||||
|
[test_temporary_storage.js]
|
||||||
[test_traffic_jam.js]
|
[test_traffic_jam.js]
|
||||||
[test_transaction_abort.js]
|
[test_transaction_abort.js]
|
||||||
[test_transaction_abort_hang.js]
|
[test_transaction_abort_hang.js]
|
||||||
|
|
|
@ -42,7 +42,7 @@ interface nsIURI;
|
||||||
interface nsIDOMEventTarget;
|
interface nsIDOMEventTarget;
|
||||||
interface nsIRunnable;
|
interface nsIRunnable;
|
||||||
|
|
||||||
[scriptable, uuid(d6e733ef-492b-4e67-b723-28571c2959f0)]
|
[scriptable, uuid(d18a8d69-7609-4165-ae20-af8aead36833)]
|
||||||
interface nsIDOMWindowUtils : nsISupports {
|
interface nsIDOMWindowUtils : nsISupports {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1229,7 +1229,9 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||||
* Get file ref count info for given database and file id.
|
* Get file ref count info for given database and file id.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
[implicit_jscontext]
|
||||||
boolean getFileReferences(in AString aDatabaseName, in long long aId,
|
boolean getFileReferences(in AString aDatabaseName, in long long aId,
|
||||||
|
[optional] in jsval aOptions,
|
||||||
[optional] out long aRefCnt,
|
[optional] out long aRefCnt,
|
||||||
[optional] out long aDBRefCnt,
|
[optional] out long aDBRefCnt,
|
||||||
[optional] out long aSliceRefCnt);
|
[optional] out long aSliceRefCnt);
|
||||||
|
|
|
@ -251,7 +251,7 @@ parent:
|
||||||
POfflineCacheUpdate(URIParams manifestURI, URIParams documentURI,
|
POfflineCacheUpdate(URIParams manifestURI, URIParams documentURI,
|
||||||
bool stickDocument);
|
bool stickDocument);
|
||||||
|
|
||||||
sync PIndexedDB(nsCString asciiOrigin)
|
sync PIndexedDB(nsCString group, nsCString asciiOrigin)
|
||||||
returns (bool allowed);
|
returns (bool allowed);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2445,7 +2445,9 @@ TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
PIndexedDBChild*
|
PIndexedDBChild*
|
||||||
TabChild::AllocPIndexedDBChild(const nsCString& aASCIIOrigin, bool* /* aAllowed */)
|
TabChild::AllocPIndexedDBChild(
|
||||||
|
const nsCString& aGroup,
|
||||||
|
const nsCString& aASCIIOrigin, bool* /* aAllowed */)
|
||||||
{
|
{
|
||||||
NS_NOTREACHED("Should never get here!");
|
NS_NOTREACHED("Should never get here!");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -351,7 +351,8 @@ protected:
|
||||||
|
|
||||||
nsEventStatus DispatchWidgetEvent(nsGUIEvent& event);
|
nsEventStatus DispatchWidgetEvent(nsGUIEvent& event);
|
||||||
|
|
||||||
virtual PIndexedDBChild* AllocPIndexedDBChild(const nsCString& aASCIIOrigin,
|
virtual PIndexedDBChild* AllocPIndexedDBChild(const nsCString& aGroup,
|
||||||
|
const nsCString& aASCIIOrigin,
|
||||||
bool* /* aAllowed */);
|
bool* /* aAllowed */);
|
||||||
|
|
||||||
virtual bool DeallocPIndexedDBChild(PIndexedDBChild* aActor);
|
virtual bool DeallocPIndexedDBChild(PIndexedDBChild* aActor);
|
||||||
|
|
|
@ -1195,7 +1195,9 @@ TabParent::ReceiveMessage(const nsString& aMessage,
|
||||||
}
|
}
|
||||||
|
|
||||||
PIndexedDBParent*
|
PIndexedDBParent*
|
||||||
TabParent::AllocPIndexedDBParent(const nsCString& aASCIIOrigin, bool* /* aAllowed */)
|
TabParent::AllocPIndexedDBParent(
|
||||||
|
const nsCString& aGroup,
|
||||||
|
const nsCString& aASCIIOrigin, bool* /* aAllowed */)
|
||||||
{
|
{
|
||||||
return new IndexedDBParent(this);
|
return new IndexedDBParent(this);
|
||||||
}
|
}
|
||||||
|
@ -1209,6 +1211,7 @@ TabParent::DeallocPIndexedDBParent(PIndexedDBParent* aActor)
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
|
TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
|
||||||
|
const nsCString& aGroup,
|
||||||
const nsCString& aASCIIOrigin,
|
const nsCString& aASCIIOrigin,
|
||||||
bool* aAllowed)
|
bool* aAllowed)
|
||||||
{
|
{
|
||||||
|
@ -1263,7 +1266,7 @@ TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
|
||||||
NS_ASSERTION(contentParent, "Null manager?!");
|
NS_ASSERTION(contentParent, "Null manager?!");
|
||||||
|
|
||||||
nsRefPtr<IDBFactory> factory;
|
nsRefPtr<IDBFactory> factory;
|
||||||
rv = IDBFactory::Create(window, aASCIIOrigin, contentParent,
|
rv = IDBFactory::Create(window, aGroup, aASCIIOrigin, contentParent,
|
||||||
getter_AddRefs(factory));
|
getter_AddRefs(factory));
|
||||||
NS_ENSURE_SUCCESS(rv, false);
|
NS_ENSURE_SUCCESS(rv, false);
|
||||||
|
|
||||||
|
|
|
@ -248,13 +248,16 @@ protected:
|
||||||
|
|
||||||
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
|
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual PIndexedDBParent* AllocPIndexedDBParent(const nsCString& aASCIIOrigin,
|
virtual PIndexedDBParent* AllocPIndexedDBParent(
|
||||||
bool* /* aAllowed */);
|
const nsCString& aGroup,
|
||||||
|
const nsCString& aASCIIOrigin,
|
||||||
|
bool* /* aAllowed */);
|
||||||
|
|
||||||
virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor);
|
virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor);
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
|
RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
|
||||||
|
const nsCString& aGroup,
|
||||||
const nsCString& aASCIIOrigin,
|
const nsCString& aASCIIOrigin,
|
||||||
bool* aAllowed);
|
bool* aAllowed);
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,8 @@ var gData = [
|
||||||
// test substitute
|
// test substitute
|
||||||
{
|
{
|
||||||
permission: "storage",
|
permission: "storage",
|
||||||
expected: ["indexedDB-unlimited", "offline-app", "pin-app"]
|
expected: ["indexedDB-unlimited", "offline-app", "pin-app",
|
||||||
|
"default-persistent-storage"]
|
||||||
},
|
},
|
||||||
// test unknown access
|
// test unknown access
|
||||||
{
|
{
|
||||||
|
|
|
@ -120,9 +120,8 @@ CheckQuotaHelper::GetQuotaPermission(nsIPrincipal* aPrincipal)
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
NS_ASSERTION(aPrincipal, "Null principal!");
|
NS_ASSERTION(aPrincipal, "Null principal!");
|
||||||
|
|
||||||
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
|
NS_ASSERTION(!nsContentUtils::IsSystemPrincipal(aPrincipal),
|
||||||
return nsIPermissionManager::ALLOW_ACTION;
|
"Chrome windows shouldn't track quota!");
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPermissionManager> pm =
|
nsCOMPtr<nsIPermissionManager> pm =
|
||||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||||
|
@ -200,7 +199,7 @@ CheckQuotaHelper::Run()
|
||||||
|
|
||||||
NS_ASSERTION(mWaiting, "Huh?!");
|
NS_ASSERTION(mWaiting, "Huh?!");
|
||||||
|
|
||||||
// This should never be used again.
|
// This should never be used again.
|
||||||
mWindow = nullptr;
|
mWindow = nullptr;
|
||||||
|
|
||||||
mWaiting = false;
|
mWaiting = false;
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
#include "nsIRunnable.h"
|
#include "nsIRunnable.h"
|
||||||
|
|
||||||
#include "mozilla/Mutex.h"
|
|
||||||
#include "mozilla/CondVar.h"
|
#include "mozilla/CondVar.h"
|
||||||
|
#include "mozilla/Mutex.h"
|
||||||
|
|
||||||
class nsIPrincipal;
|
class nsIPrincipal;
|
||||||
class nsPIDOMWindow;
|
class nsPIDOMWindow;
|
||||||
|
@ -34,11 +34,14 @@ public:
|
||||||
CheckQuotaHelper(nsPIDOMWindow* aWindow,
|
CheckQuotaHelper(nsPIDOMWindow* aWindow,
|
||||||
mozilla::Mutex& aMutex);
|
mozilla::Mutex& aMutex);
|
||||||
|
|
||||||
bool PromptAndReturnQuotaIsDisabled();
|
bool
|
||||||
|
PromptAndReturnQuotaIsDisabled();
|
||||||
|
|
||||||
void Cancel();
|
void
|
||||||
|
Cancel();
|
||||||
|
|
||||||
static uint32_t GetQuotaPermission(nsIPrincipal* aPrincipal);
|
static uint32_t
|
||||||
|
GetQuotaPermission(nsIPrincipal* aPrincipal);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsPIDOMWindow* mWindow;
|
nsPIDOMWindow* mWindow;
|
||||||
|
|
|
@ -9,12 +9,15 @@
|
||||||
|
|
||||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||||
|
|
||||||
|
#include "PersistenceType.h"
|
||||||
|
|
||||||
class nsIOfflineStorage;
|
class nsIOfflineStorage;
|
||||||
class nsIRunnable;
|
class nsIRunnable;
|
||||||
|
|
||||||
BEGIN_QUOTA_NAMESPACE
|
BEGIN_QUOTA_NAMESPACE
|
||||||
|
|
||||||
class UsageRunnable;
|
class OriginOrPatternString;
|
||||||
|
class UsageInfo;
|
||||||
|
|
||||||
// An abstract interface for quota manager clients.
|
// An abstract interface for quota manager clients.
|
||||||
// Each storage API must provide an implementation of this interface in order
|
// Each storage API must provide an implementation of this interface in order
|
||||||
|
@ -70,14 +73,20 @@ public:
|
||||||
|
|
||||||
// Methods which are called on the IO thred.
|
// Methods which are called on the IO thred.
|
||||||
virtual nsresult
|
virtual nsresult
|
||||||
InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable) = 0;
|
InitOrigin(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin,
|
||||||
|
UsageInfo* aUsageInfo) = 0;
|
||||||
|
|
||||||
virtual nsresult
|
virtual nsresult
|
||||||
GetUsageForOrigin(const nsACString& aOrigin,
|
GetUsageForOrigin(PersistenceType aPersistenceType,
|
||||||
UsageRunnable* aUsageRunnable) = 0;
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin,
|
||||||
|
UsageInfo* aUsageInfo) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
OnOriginClearCompleted(const nsACString& aPattern) = 0;
|
OnOriginClearCompleted(PersistenceType aPersistenceType,
|
||||||
|
const OriginOrPatternString& aOriginOrPattern) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
ReleaseIOThreadObjects() = 0;
|
ReleaseIOThreadObjects() = 0;
|
||||||
|
|
|
@ -48,7 +48,7 @@ FileQuotaStream<FileStreamBase>::DoOpen()
|
||||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||||
|
|
||||||
NS_ASSERTION(!mQuotaObject, "Creating quota object more than once?");
|
NS_ASSERTION(!mQuotaObject, "Creating quota object more than once?");
|
||||||
mQuotaObject = quotaManager->GetQuotaObject(mOrigin,
|
mQuotaObject = quotaManager->GetQuotaObject(mPersistenceType, mGroup, mOrigin,
|
||||||
FileStreamBase::mOpenParams.localFile);
|
FileStreamBase::mOpenParams.localFile);
|
||||||
|
|
||||||
nsresult rv = FileStreamBase::DoOpen();
|
nsresult rv = FileStreamBase::DoOpen();
|
||||||
|
@ -89,11 +89,13 @@ FileQuotaStreamWithWrite<FileStreamBase>::Write(const char* aBuf,
|
||||||
NS_IMPL_ISUPPORTS_INHERITED0(FileInputStream, nsFileInputStream)
|
NS_IMPL_ISUPPORTS_INHERITED0(FileInputStream, nsFileInputStream)
|
||||||
|
|
||||||
already_AddRefed<FileInputStream>
|
already_AddRefed<FileInputStream>
|
||||||
FileInputStream::Create(const nsACString& aOrigin, nsIFile* aFile,
|
FileInputStream::Create(PersistenceType aPersistenceType,
|
||||||
int32_t aIOFlags, int32_t aPerm,
|
const nsACString& aGroup, const nsACString& aOrigin,
|
||||||
|
nsIFile* aFile, int32_t aIOFlags, int32_t aPerm,
|
||||||
int32_t aBehaviorFlags)
|
int32_t aBehaviorFlags)
|
||||||
{
|
{
|
||||||
nsRefPtr<FileInputStream> stream = new FileInputStream(aOrigin);
|
nsRefPtr<FileInputStream> stream =
|
||||||
|
new FileInputStream(aPersistenceType, aGroup, aOrigin);
|
||||||
nsresult rv = stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
|
nsresult rv = stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
|
||||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||||
return stream.forget();
|
return stream.forget();
|
||||||
|
@ -102,11 +104,13 @@ FileInputStream::Create(const nsACString& aOrigin, nsIFile* aFile,
|
||||||
NS_IMPL_ISUPPORTS_INHERITED0(FileOutputStream, nsFileOutputStream)
|
NS_IMPL_ISUPPORTS_INHERITED0(FileOutputStream, nsFileOutputStream)
|
||||||
|
|
||||||
already_AddRefed<FileOutputStream>
|
already_AddRefed<FileOutputStream>
|
||||||
FileOutputStream::Create(const nsACString& aOrigin, nsIFile* aFile,
|
FileOutputStream::Create(PersistenceType aPersistenceType,
|
||||||
int32_t aIOFlags, int32_t aPerm,
|
const nsACString& aGroup, const nsACString& aOrigin,
|
||||||
|
nsIFile* aFile, int32_t aIOFlags, int32_t aPerm,
|
||||||
int32_t aBehaviorFlags)
|
int32_t aBehaviorFlags)
|
||||||
{
|
{
|
||||||
nsRefPtr<FileOutputStream> stream = new FileOutputStream(aOrigin);
|
nsRefPtr<FileOutputStream> stream =
|
||||||
|
new FileOutputStream(aPersistenceType, aGroup, aOrigin);
|
||||||
nsresult rv = stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
|
nsresult rv = stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
|
||||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||||
return stream.forget();
|
return stream.forget();
|
||||||
|
@ -115,10 +119,12 @@ FileOutputStream::Create(const nsACString& aOrigin, nsIFile* aFile,
|
||||||
NS_IMPL_ISUPPORTS_INHERITED0(FileStream, nsFileStream)
|
NS_IMPL_ISUPPORTS_INHERITED0(FileStream, nsFileStream)
|
||||||
|
|
||||||
already_AddRefed<FileStream>
|
already_AddRefed<FileStream>
|
||||||
FileStream::Create(const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags,
|
FileStream::Create(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags,
|
||||||
int32_t aPerm, int32_t aBehaviorFlags)
|
int32_t aPerm, int32_t aBehaviorFlags)
|
||||||
{
|
{
|
||||||
nsRefPtr<FileStream> stream = new FileStream(aOrigin);
|
nsRefPtr<FileStream> stream =
|
||||||
|
new FileStream(aPersistenceType, aGroup, aOrigin);
|
||||||
nsresult rv = stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
|
nsresult rv = stream->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
|
||||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||||
return stream.forget();
|
return stream.forget();
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "nsFileStreams.h"
|
#include "nsFileStreams.h"
|
||||||
|
|
||||||
|
#include "PersistenceType.h"
|
||||||
#include "QuotaObject.h"
|
#include "QuotaObject.h"
|
||||||
|
|
||||||
BEGIN_QUOTA_NAMESPACE
|
BEGIN_QUOTA_NAMESPACE
|
||||||
|
@ -27,14 +28,17 @@ public:
|
||||||
Close() MOZ_OVERRIDE;
|
Close() MOZ_OVERRIDE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FileQuotaStream(const nsACString& aOrigin)
|
FileQuotaStream(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||||
: mOrigin(aOrigin)
|
const nsACString& aOrigin)
|
||||||
|
: mPersistenceType(aPersistenceType), mGroup(aGroup), mOrigin(aOrigin)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// nsFileStreamBase override
|
// nsFileStreamBase override
|
||||||
virtual nsresult
|
virtual nsresult
|
||||||
DoOpen() MOZ_OVERRIDE;
|
DoOpen() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
PersistenceType mPersistenceType;
|
||||||
|
nsCString mGroup;
|
||||||
nsCString mOrigin;
|
nsCString mOrigin;
|
||||||
nsRefPtr<QuotaObject> mQuotaObject;
|
nsRefPtr<QuotaObject> mQuotaObject;
|
||||||
};
|
};
|
||||||
|
@ -48,8 +52,9 @@ public:
|
||||||
Write(const char* aBuf, uint32_t aCount, uint32_t* _retval) MOZ_OVERRIDE;
|
Write(const char* aBuf, uint32_t aCount, uint32_t* _retval) MOZ_OVERRIDE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FileQuotaStreamWithWrite(const nsACString& aOrigin)
|
FileQuotaStreamWithWrite(PersistenceType aPersistenceType,
|
||||||
: FileQuotaStream<FileStreamBase>(aOrigin)
|
const nsACString& aGroup, const nsACString& aOrigin)
|
||||||
|
: FileQuotaStream<FileStreamBase>(aPersistenceType, aGroup, aOrigin)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,12 +64,14 @@ public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
static already_AddRefed<FileInputStream>
|
static already_AddRefed<FileInputStream>
|
||||||
Create(const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
|
Create(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
|
||||||
int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
|
int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FileInputStream(const nsACString& aOrigin)
|
FileInputStream(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||||
: FileQuotaStream<nsFileInputStream>(aOrigin)
|
const nsACString& aOrigin)
|
||||||
|
: FileQuotaStream<nsFileInputStream>(aPersistenceType, aGroup, aOrigin)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual ~FileInputStream() {
|
virtual ~FileInputStream() {
|
||||||
|
@ -78,12 +85,15 @@ public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
static already_AddRefed<FileOutputStream>
|
static already_AddRefed<FileOutputStream>
|
||||||
Create(const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
|
Create(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
|
||||||
int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
|
int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FileOutputStream(const nsACString& aOrigin)
|
FileOutputStream(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||||
: FileQuotaStreamWithWrite<nsFileOutputStream>(aOrigin)
|
const nsACString& aOrigin)
|
||||||
|
: FileQuotaStreamWithWrite<nsFileOutputStream>(aPersistenceType, aGroup,
|
||||||
|
aOrigin)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual ~FileOutputStream() {
|
virtual ~FileOutputStream() {
|
||||||
|
@ -97,12 +107,14 @@ public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
static already_AddRefed<FileStream>
|
static already_AddRefed<FileStream>
|
||||||
Create(const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
|
Create(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin, nsIFile* aFile, int32_t aIOFlags = -1,
|
||||||
int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
|
int32_t aPerm = -1, int32_t aBehaviorFlags = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FileStream(const nsACString& aOrigin)
|
FileStream(PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||||
: FileQuotaStreamWithWrite<nsFileStream>(aOrigin)
|
const nsACString& aOrigin)
|
||||||
|
: FileQuotaStreamWithWrite<nsFileStream>(aPersistenceType, aGroup, aOrigin)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual ~FileStream() {
|
virtual ~FileStream() {
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_quota_origincollection_h__
|
||||||
|
#define mozilla_dom_quota_origincollection_h__
|
||||||
|
|
||||||
|
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||||
|
|
||||||
|
#include "nsHashKeys.h"
|
||||||
|
#include "nsTHashtable.h"
|
||||||
|
|
||||||
|
#include "Utilities.h"
|
||||||
|
|
||||||
|
BEGIN_QUOTA_NAMESPACE
|
||||||
|
|
||||||
|
class OriginCollection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
ContainsPattern(const nsACString& aPattern)
|
||||||
|
{
|
||||||
|
return mPatterns.Contains(aPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AddPattern(const nsACString& aPattern)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!mOrigins.Count());
|
||||||
|
MOZ_ASSERT(!ContainsPattern(aPattern));
|
||||||
|
mPatterns.AppendElement(aPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ContainsOrigin(const nsACString& aOrigin)
|
||||||
|
{
|
||||||
|
for (uint32_t index = 0; index < mPatterns.Length(); index++) {
|
||||||
|
if (PatternMatchesOrigin(mPatterns[index], aOrigin)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mOrigins.GetEntry(aOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AddOrigin(const nsACString& aOrigin)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!ContainsOrigin(aOrigin));
|
||||||
|
mOrigins.PutEntry(aOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsTArray<nsCString> mPatterns;
|
||||||
|
nsTHashtable<nsCStringHashKey> mOrigins;
|
||||||
|
};
|
||||||
|
|
||||||
|
END_QUOTA_NAMESPACE
|
||||||
|
|
||||||
|
#endif // mozilla_dom_quota_origincollection_h__
|
|
@ -26,6 +26,12 @@ public:
|
||||||
return OriginOrPatternString(aPattern, false);
|
return OriginOrPatternString(aPattern, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static OriginOrPatternString
|
||||||
|
FromNull()
|
||||||
|
{
|
||||||
|
return OriginOrPatternString();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IsOrigin() const
|
IsOrigin() const
|
||||||
{
|
{
|
||||||
|
@ -35,18 +41,31 @@ public:
|
||||||
bool
|
bool
|
||||||
IsPattern() const
|
IsPattern() const
|
||||||
{
|
{
|
||||||
return !mIsOrigin;
|
return mIsPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsNull() const
|
||||||
|
{
|
||||||
|
return mIsNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OriginOrPatternString(const nsACString& aOriginOrPattern, bool aIsOrigin)
|
OriginOrPatternString(const nsACString& aOriginOrPattern, bool aIsOrigin)
|
||||||
: nsCString(aOriginOrPattern), mIsOrigin(aIsOrigin)
|
: nsCString(aOriginOrPattern),
|
||||||
|
mIsOrigin(aIsOrigin), mIsPattern(!aIsOrigin), mIsNull(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
OriginOrPatternString()
|
||||||
|
: mIsOrigin(false), mIsPattern(false), mIsNull(true)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
bool
|
bool
|
||||||
operator==(const OriginOrPatternString& aOther) MOZ_DELETE;
|
operator==(const OriginOrPatternString& aOther) MOZ_DELETE;
|
||||||
|
|
||||||
bool mIsOrigin;
|
bool mIsOrigin;
|
||||||
|
bool mIsPattern;
|
||||||
|
bool mIsNull;
|
||||||
};
|
};
|
||||||
|
|
||||||
END_QUOTA_NAMESPACE
|
END_QUOTA_NAMESPACE
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_quota_persistencetype_h__
|
||||||
|
#define mozilla_dom_quota_persistencetype_h__
|
||||||
|
|
||||||
|
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/StorageTypeBinding.h"
|
||||||
|
|
||||||
|
BEGIN_QUOTA_NAMESPACE
|
||||||
|
|
||||||
|
enum PersistenceType
|
||||||
|
{
|
||||||
|
PERSISTENCE_TYPE_PERSISTENT = 0,
|
||||||
|
PERSISTENCE_TYPE_TEMPORARY,
|
||||||
|
|
||||||
|
// Only needed for IPC serialization helper, should never be used in code.
|
||||||
|
PERSISTENCE_TYPE_INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void
|
||||||
|
PersistenceTypeToText(PersistenceType aPersistenceType, nsACString& aText)
|
||||||
|
{
|
||||||
|
switch (aPersistenceType) {
|
||||||
|
case PERSISTENCE_TYPE_PERSISTENT:
|
||||||
|
aText.AssignLiteral("persistent");
|
||||||
|
return;
|
||||||
|
case PERSISTENCE_TYPE_TEMPORARY:
|
||||||
|
aText.AssignLiteral("temporary");
|
||||||
|
return;
|
||||||
|
|
||||||
|
case PERSISTENCE_TYPE_INVALID:
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("Bad persistence type value!");
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSUME_UNREACHABLE("Should never get here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PersistenceType
|
||||||
|
PersistenceTypeFromText(const nsACString& aText)
|
||||||
|
{
|
||||||
|
if (aText.EqualsLiteral("persistent")) {
|
||||||
|
return PERSISTENCE_TYPE_PERSISTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aText.EqualsLiteral("temporary")) {
|
||||||
|
return PERSISTENCE_TYPE_TEMPORARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSUME_UNREACHABLE("Should never get here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline mozilla::dom::StorageType
|
||||||
|
PersistenceTypeToStorage(PersistenceType aPersistenceType)
|
||||||
|
{
|
||||||
|
return mozilla::dom::StorageType(static_cast<int>(aPersistenceType));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PersistenceType
|
||||||
|
PersistenceTypeFromStorage(const Optional<mozilla::dom::StorageType>& aStorage,
|
||||||
|
PersistenceType aDefaultPersistenceType)
|
||||||
|
{
|
||||||
|
if (aStorage.WasPassed()) {
|
||||||
|
return PersistenceType(static_cast<int>(aStorage.Value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return aDefaultPersistenceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
END_QUOTA_NAMESPACE
|
||||||
|
|
||||||
|
#endif // mozilla_dom_quota_persistencetype_h__
|
|
@ -24,14 +24,14 @@
|
||||||
|
|
||||||
BEGIN_QUOTA_NAMESPACE
|
BEGIN_QUOTA_NAMESPACE
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void
|
void
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
#else
|
|
||||||
inline void
|
void
|
||||||
AssertIsOnIOThread()
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
{ }
|
|
||||||
#endif
|
bool
|
||||||
|
IsOnIOThread();
|
||||||
|
|
||||||
END_QUOTA_NAMESPACE
|
END_QUOTA_NAMESPACE
|
||||||
|
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -12,13 +12,16 @@
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
#include "nsIQuotaManager.h"
|
#include "nsIQuotaManager.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/Nullable.h"
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
|
|
||||||
#include "nsClassHashtable.h"
|
#include "nsClassHashtable.h"
|
||||||
#include "nsRefPtrHashtable.h"
|
#include "nsRefPtrHashtable.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
|
||||||
#include "ArrayCluster.h"
|
#include "ArrayCluster.h"
|
||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
|
#include "PersistenceType.h"
|
||||||
#include "StoragePrivilege.h"
|
#include "StoragePrivilege.h"
|
||||||
|
|
||||||
#define QUOTA_MANAGER_CONTRACTID "@mozilla.org/dom/quota/manager;1"
|
#define QUOTA_MANAGER_CONTRACTID "@mozilla.org/dom/quota/manager;1"
|
||||||
|
@ -36,19 +39,28 @@ BEGIN_QUOTA_NAMESPACE
|
||||||
class AcquireListener;
|
class AcquireListener;
|
||||||
class AsyncUsageRunnable;
|
class AsyncUsageRunnable;
|
||||||
class CheckQuotaHelper;
|
class CheckQuotaHelper;
|
||||||
|
class CollectOriginsHelper;
|
||||||
|
class FinalizeOriginEvictionRunnable;
|
||||||
|
class GroupInfo;
|
||||||
|
class GroupInfoPair;
|
||||||
class OriginClearRunnable;
|
class OriginClearRunnable;
|
||||||
class OriginInfo;
|
class OriginInfo;
|
||||||
class OriginOrPatternString;
|
class OriginOrPatternString;
|
||||||
class QuotaObject;
|
class QuotaObject;
|
||||||
|
class ResetOrClearRunnable;
|
||||||
struct SynchronizedOp;
|
struct SynchronizedOp;
|
||||||
|
|
||||||
class QuotaManager MOZ_FINAL : public nsIQuotaManager,
|
class QuotaManager MOZ_FINAL : public nsIQuotaManager,
|
||||||
public nsIObserver
|
public nsIObserver
|
||||||
{
|
{
|
||||||
friend class AsyncUsageRunnable;
|
friend class AsyncUsageRunnable;
|
||||||
|
friend class CollectOriginsHelper;
|
||||||
|
friend class FinalizeOriginEvictionRunnable;
|
||||||
|
friend class GroupInfo;
|
||||||
friend class OriginClearRunnable;
|
friend class OriginClearRunnable;
|
||||||
friend class OriginInfo;
|
friend class OriginInfo;
|
||||||
friend class QuotaObject;
|
friend class QuotaObject;
|
||||||
|
friend class ResetOrClearRunnable;
|
||||||
|
|
||||||
enum MozBrowserPatternFlag
|
enum MozBrowserPatternFlag
|
||||||
{
|
{
|
||||||
|
@ -81,23 +93,53 @@ public:
|
||||||
static bool IsShuttingDown();
|
static bool IsShuttingDown();
|
||||||
|
|
||||||
void
|
void
|
||||||
InitQuotaForOrigin(const nsACString& aOrigin,
|
InitQuotaForOrigin(PersistenceType aPersistenceType,
|
||||||
int64_t aLimitBytes,
|
const nsACString& aGroup,
|
||||||
int64_t aUsageBytes);
|
const nsACString& aOrigin,
|
||||||
|
uint64_t aLimitBytes,
|
||||||
|
uint64_t aUsageBytes,
|
||||||
|
int64_t aAccessTime);
|
||||||
|
|
||||||
void
|
void
|
||||||
DecreaseUsageForOrigin(const nsACString& aOrigin,
|
DecreaseUsageForOrigin(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin,
|
||||||
int64_t aSize);
|
int64_t aSize);
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoveQuotaForPattern(const nsACString& aPattern);
|
UpdateOriginAccessTime(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin);
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoveQuota();
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoveQuotaForPersistenceType(PersistenceType);
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoveQuotaForOrigin(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin)
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mQuotaMutex);
|
||||||
|
LockedRemoveQuotaForOrigin(aPersistenceType, aGroup, aOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoveQuotaForPattern(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aPattern);
|
||||||
|
|
||||||
already_AddRefed<QuotaObject>
|
already_AddRefed<QuotaObject>
|
||||||
GetQuotaObject(const nsACString& aOrigin,
|
GetQuotaObject(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin,
|
||||||
nsIFile* aFile);
|
nsIFile* aFile);
|
||||||
|
|
||||||
already_AddRefed<QuotaObject>
|
already_AddRefed<QuotaObject>
|
||||||
GetQuotaObject(const nsACString& aOrigin,
|
GetQuotaObject(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin,
|
||||||
const nsAString& aPath);
|
const nsAString& aPath);
|
||||||
|
|
||||||
// Set the Window that the current thread is doing operations for.
|
// Set the Window that the current thread is doing operations for.
|
||||||
|
@ -148,6 +190,7 @@ public:
|
||||||
// complete before dispatching the given runnable.
|
// complete before dispatching the given runnable.
|
||||||
nsresult
|
nsresult
|
||||||
WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern,
|
WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern,
|
||||||
|
Nullable<PersistenceType> aPersistenceType,
|
||||||
nsIAtom* aId,
|
nsIAtom* aId,
|
||||||
nsIRunnable* aRunnable);
|
nsIRunnable* aRunnable);
|
||||||
|
|
||||||
|
@ -178,25 +221,39 @@ public:
|
||||||
|
|
||||||
void
|
void
|
||||||
AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
||||||
|
Nullable<PersistenceType> aPersistenceType,
|
||||||
nsIAtom* aId);
|
nsIAtom* aId);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IsClearOriginPending(const nsACString& aPattern)
|
IsClearOriginPending(const nsACString& aPattern)
|
||||||
{
|
{
|
||||||
return !!FindSynchronizedOp(aPattern, nullptr);
|
return !!FindSynchronizedOp(aPattern, Nullable<PersistenceType>(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
GetDirectoryForOrigin(const nsACString& aASCIIOrigin,
|
GetDirectoryForOrigin(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aASCIIOrigin,
|
||||||
nsIFile** aDirectory) const;
|
nsIFile** aDirectory) const;
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
EnsureOriginIsInitialized(const nsACString& aOrigin,
|
EnsureOriginIsInitialized(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin,
|
||||||
bool aTrackQuota,
|
bool aTrackQuota,
|
||||||
nsIFile** aDirectory);
|
nsIFile** aDirectory);
|
||||||
|
|
||||||
void
|
void
|
||||||
OriginClearCompleted(const nsACString& aPattern);
|
OriginClearCompleted(PersistenceType aPersistenceType,
|
||||||
|
const OriginOrPatternString& aOriginOrPattern);
|
||||||
|
|
||||||
|
void
|
||||||
|
ResetOrClearCompleted();
|
||||||
|
|
||||||
|
void
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex()
|
||||||
|
{
|
||||||
|
mQuotaMutex.AssertCurrentThreadOwns();
|
||||||
|
}
|
||||||
|
|
||||||
nsIThread*
|
nsIThread*
|
||||||
IOThread()
|
IOThread()
|
||||||
|
@ -209,31 +266,53 @@ public:
|
||||||
GetClient(Client::Type aClientType);
|
GetClient(Client::Type aClientType);
|
||||||
|
|
||||||
const nsString&
|
const nsString&
|
||||||
GetBaseDirectory() const
|
GetStoragePath(PersistenceType aPersistenceType) const
|
||||||
{
|
{
|
||||||
return mStorageBasePath;
|
if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
|
||||||
|
return mPersistentStoragePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(aPersistenceType == PERSISTENCE_TYPE_TEMPORARY, "Huh?");
|
||||||
|
|
||||||
|
return mTemporaryStoragePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
GetGroupLimit() const
|
||||||
|
{
|
||||||
|
return mTemporaryStorageLimit / 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
GetStorageQuotaMB();
|
GetStorageQuotaMB();
|
||||||
|
|
||||||
static already_AddRefed<nsIAtom>
|
static already_AddRefed<nsIAtom>
|
||||||
GetStorageId(const nsACString& aOrigin,
|
GetStorageId(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aOrigin,
|
||||||
const nsAString& aName);
|
const nsAString& aName);
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
GetASCIIOriginFromURI(nsIURI* aURI,
|
GetInfoFromURI(nsIURI* aURI,
|
||||||
uint32_t aAppId,
|
uint32_t aAppId,
|
||||||
bool aInMozBrowser,
|
bool aInMozBrowser,
|
||||||
nsACString& aASCIIOrigin);
|
nsACString* aGroup,
|
||||||
|
nsACString* aASCIIOrigin,
|
||||||
|
StoragePrivilege* aPrivilege,
|
||||||
|
PersistenceType* aDefaultPersistenceType);
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
GetASCIIOriginFromPrincipal(nsIPrincipal* aPrincipal,
|
GetInfoFromPrincipal(nsIPrincipal* aPrincipal,
|
||||||
nsACString& aASCIIOrigin);
|
nsACString* aGroup,
|
||||||
|
nsACString* aASCIIOrigin,
|
||||||
|
StoragePrivilege* aPrivilege,
|
||||||
|
PersistenceType* aDefaultPersistenceType);
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow,
|
GetInfoFromWindow(nsPIDOMWindow* aWindow,
|
||||||
nsACString& aASCIIOrigin);
|
nsACString* aGroup,
|
||||||
|
nsACString* aASCIIOrigin,
|
||||||
|
StoragePrivilege* aPrivilege,
|
||||||
|
PersistenceType* aDefaultPersistenceType);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly,
|
GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly,
|
||||||
|
@ -272,6 +351,15 @@ private:
|
||||||
bool
|
bool
|
||||||
LockedQuotaIsLifted();
|
LockedQuotaIsLifted();
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
LockedCollectOriginsForEviction(uint64_t aMinSizeToBeFreed,
|
||||||
|
nsTArray<OriginInfo*>& aOriginInfos);
|
||||||
|
|
||||||
|
void
|
||||||
|
LockedRemoveQuotaForOrigin(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin);
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
AcquireExclusiveAccess(const nsACString& aOrigin,
|
AcquireExclusiveAccess(const nsACString& aOrigin,
|
||||||
nsIOfflineStorage* aStorage,
|
nsIOfflineStorage* aStorage,
|
||||||
|
@ -279,19 +367,50 @@ private:
|
||||||
WaitingOnStoragesCallback aCallback,
|
WaitingOnStoragesCallback aCallback,
|
||||||
void* aClosure);
|
void* aClosure);
|
||||||
|
|
||||||
|
void
|
||||||
|
AddSynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
||||||
|
Nullable<PersistenceType> aPersistenceType,
|
||||||
|
nsIAtom* aId);
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
RunSynchronizedOp(nsIOfflineStorage* aStorage,
|
RunSynchronizedOp(nsIOfflineStorage* aStorage,
|
||||||
SynchronizedOp* aOp);
|
SynchronizedOp* aOp);
|
||||||
|
|
||||||
SynchronizedOp*
|
SynchronizedOp*
|
||||||
FindSynchronizedOp(const nsACString& aPattern,
|
FindSynchronizedOp(const nsACString& aPattern,
|
||||||
|
Nullable<PersistenceType> aPersistenceType,
|
||||||
nsISupports* aId);
|
nsISupports* aId);
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
MaybeUpgradeIndexedDBDirectory();
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
InitializeOrigin(PersistenceType aPersistenceType,
|
||||||
|
const nsACString& aGroup,
|
||||||
|
const nsACString& aOrigin,
|
||||||
|
bool aTrackQuota,
|
||||||
|
int64_t aAccessTime,
|
||||||
|
nsIFile* aDirectory);
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
ClearStoragesForApp(uint32_t aAppId, bool aBrowserOnly);
|
ClearStoragesForApp(uint32_t aAppId, bool aBrowserOnly);
|
||||||
|
|
||||||
nsresult
|
void
|
||||||
MaybeUpgradeOriginDirectory(nsIFile* aDirectory);
|
CheckTemporaryStorageLimits();
|
||||||
|
|
||||||
|
// Collect inactive and the least recently used origins.
|
||||||
|
uint64_t
|
||||||
|
CollectOriginsForEviction(uint64_t aMinSizeToBeFreed,
|
||||||
|
nsTArray<OriginInfo*>& aOriginInfos);
|
||||||
|
|
||||||
|
void
|
||||||
|
DeleteTemporaryFilesForOrigin(const nsACString& aOrigin);
|
||||||
|
|
||||||
|
void
|
||||||
|
FinalizeOriginEviction(nsTArray<nsCString>& aOrigins);
|
||||||
|
|
||||||
|
void
|
||||||
|
SaveOriginAccessTime(const nsACString& aOrigin, int64_t aTimestamp);
|
||||||
|
|
||||||
void
|
void
|
||||||
ReleaseIOThreadObjects()
|
ReleaseIOThreadObjects()
|
||||||
|
@ -309,12 +428,47 @@ private:
|
||||||
const nsACString& aOrigin,
|
const nsACString& aOrigin,
|
||||||
nsAutoCString& _retval);
|
nsAutoCString& _retval);
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
RemoveQuotaForPersistenceTypeCallback(const nsACString& aKey,
|
||||||
|
nsAutoPtr<GroupInfoPair>& aValue,
|
||||||
|
void* aUserArg);
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
RemoveQuotaCallback(const nsACString& aKey,
|
||||||
|
nsAutoPtr<GroupInfoPair>& aValue,
|
||||||
|
void* aUserArg);
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
RemoveQuotaForPatternCallback(const nsACString& aKey,
|
||||||
|
nsAutoPtr<GroupInfoPair>& aValue,
|
||||||
|
void* aUserArg);
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
GetOriginsExceedingGroupLimit(const nsACString& aKey,
|
||||||
|
GroupInfoPair* aValue,
|
||||||
|
void* aUserArg);
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
GetAllTemporaryStorageOrigins(const nsACString& aKey,
|
||||||
|
GroupInfoPair* aValue,
|
||||||
|
void* aUserArg);
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
AddTemporaryStorageOrigins(const nsACString& aKey,
|
||||||
|
ArrayCluster<nsIOfflineStorage*>* aValue,
|
||||||
|
void* aUserArg);
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
GetInactiveTemporaryStorageOrigins(const nsACString& aKey,
|
||||||
|
GroupInfoPair* aValue,
|
||||||
|
void* aUserArg);
|
||||||
|
|
||||||
// TLS storage index for the current thread's window.
|
// TLS storage index for the current thread's window.
|
||||||
unsigned int mCurrentWindowIndex;
|
unsigned int mCurrentWindowIndex;
|
||||||
|
|
||||||
mozilla::Mutex mQuotaMutex;
|
mozilla::Mutex mQuotaMutex;
|
||||||
|
|
||||||
nsRefPtrHashtable<nsCStringHashKey, OriginInfo> mOriginInfos;
|
nsClassHashtable<nsCStringHashKey, GroupInfoPair> mGroupInfoPairs;
|
||||||
|
|
||||||
// A map of Windows to the corresponding quota helper.
|
// A map of Windows to the corresponding quota helper.
|
||||||
nsRefPtrHashtable<nsPtrHashKey<nsPIDOMWindow>,
|
nsRefPtrHashtable<nsPtrHashKey<nsPIDOMWindow>,
|
||||||
|
@ -339,7 +493,15 @@ private:
|
||||||
|
|
||||||
nsAutoTArray<nsRefPtr<Client>, Client::TYPE_MAX> mClients;
|
nsAutoTArray<nsRefPtr<Client>, Client::TYPE_MAX> mClients;
|
||||||
|
|
||||||
nsString mStorageBasePath;
|
nsString mIndexedDBPath;
|
||||||
|
nsString mPersistentStoragePath;
|
||||||
|
nsString mTemporaryStoragePath;
|
||||||
|
|
||||||
|
uint64_t mTemporaryStorageLimit;
|
||||||
|
uint64_t mTemporaryStorageUsage;
|
||||||
|
bool mTemporaryStorageInitialized;
|
||||||
|
|
||||||
|
bool mStorageAreaInitialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AutoEnterWindow
|
class AutoEnterWindow
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "QuotaObject.h"
|
#include "QuotaObject.h"
|
||||||
|
|
||||||
#include "QuotaManager.h"
|
#include "QuotaManager.h"
|
||||||
|
#include "Utilities.h"
|
||||||
|
|
||||||
USING_QUOTA_NAMESPACE
|
USING_QUOTA_NAMESPACE
|
||||||
|
|
||||||
|
@ -68,10 +69,24 @@ QuotaObject::UpdateSize(int64_t aSize)
|
||||||
|
|
||||||
MutexAutoLock lock(quotaManager->mQuotaMutex);
|
MutexAutoLock lock(quotaManager->mQuotaMutex);
|
||||||
|
|
||||||
if (mOriginInfo) {
|
if (!mOriginInfo) {
|
||||||
mOriginInfo->mUsage -= mSize;
|
return;
|
||||||
mSize = aSize;
|
}
|
||||||
mOriginInfo->mUsage += mSize;
|
|
||||||
|
GroupInfo* groupInfo = mOriginInfo->mGroupInfo;
|
||||||
|
|
||||||
|
if (groupInfo->IsForTemporaryStorage()) {
|
||||||
|
quotaManager->mTemporaryStorageUsage -= mSize;
|
||||||
|
}
|
||||||
|
groupInfo->mUsage -= mSize;
|
||||||
|
mOriginInfo->mUsage -= mSize;
|
||||||
|
|
||||||
|
mSize = aSize;
|
||||||
|
|
||||||
|
mOriginInfo->mUsage += mSize;
|
||||||
|
groupInfo->mUsage += mSize;
|
||||||
|
if (groupInfo->IsForTemporaryStorage()) {
|
||||||
|
quotaManager->mTemporaryStorageUsage += mSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,60 +104,194 @@ QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t newUsage = mOriginInfo->mUsage - mSize + end;
|
GroupInfo* groupInfo = mOriginInfo->mGroupInfo;
|
||||||
if (newUsage > mOriginInfo->mLimit) {
|
|
||||||
// This will block the thread, but it will also drop the mutex while
|
|
||||||
// waiting. The mutex will be reacquired again when the waiting is finished.
|
|
||||||
if (!quotaManager->LockedQuotaIsLifted()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Threads raced, the origin info removal has been done by some other
|
if (groupInfo->IsForPersistentStorage()) {
|
||||||
// thread.
|
uint64_t newUsage = mOriginInfo->mUsage - mSize + end;
|
||||||
if (!mOriginInfo) {
|
|
||||||
// The other thread could allocate more space.
|
if (newUsage > mOriginInfo->mLimit) {
|
||||||
if (end > mSize) {
|
// This will block the thread, but it will also drop the mutex while
|
||||||
mSize = end;
|
// waiting. The mutex will be reacquired again when the waiting is
|
||||||
|
// finished.
|
||||||
|
if (!quotaManager->LockedQuotaIsLifted()) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Threads raced, the origin info removal has been done by some other
|
||||||
|
// thread.
|
||||||
|
if (!mOriginInfo) {
|
||||||
|
// The other thread could allocate more space.
|
||||||
|
if (end > mSize) {
|
||||||
|
mSize = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCString group = mOriginInfo->mGroupInfo->mGroup;
|
||||||
|
nsCString origin = mOriginInfo->mOrigin;
|
||||||
|
|
||||||
|
mOriginInfo->LockedClearOriginInfos();
|
||||||
|
NS_ASSERTION(!mOriginInfo,
|
||||||
|
"Should have cleared in LockedClearOriginInfos!");
|
||||||
|
|
||||||
|
quotaManager->LockedRemoveQuotaForOrigin(PERSISTENCE_TYPE_PERSISTENT,
|
||||||
|
group, origin);
|
||||||
|
|
||||||
|
// Some other thread could increase the size without blocking (increasing
|
||||||
|
// the origin usage without hitting the limit), but no more than this one.
|
||||||
|
NS_ASSERTION(mSize < end, "This shouldn't happen!");
|
||||||
|
|
||||||
|
mSize = end;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCString origin = mOriginInfo->mOrigin;
|
mOriginInfo->mUsage = newUsage;
|
||||||
|
|
||||||
mOriginInfo->LockedClearOriginInfos();
|
groupInfo->mUsage = groupInfo->mUsage - mSize + end;
|
||||||
NS_ASSERTION(!mOriginInfo,
|
|
||||||
"Should have cleared in LockedClearOriginInfos!");
|
|
||||||
|
|
||||||
quotaManager->mOriginInfos.Remove(origin);
|
|
||||||
|
|
||||||
// Some other thread could increase the size without blocking (increasing
|
|
||||||
// the origin usage without hitting the limit), but no more than this one.
|
|
||||||
NS_ASSERTION(mSize < end, "This shouldn't happen!");
|
|
||||||
|
|
||||||
mSize = end;
|
mSize = end;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(groupInfo->mPersistenceType == PERSISTENCE_TYPE_TEMPORARY,
|
||||||
|
"Huh?");
|
||||||
|
|
||||||
|
uint64_t delta = end - mSize;
|
||||||
|
|
||||||
|
uint64_t newUsage = mOriginInfo->mUsage + delta;
|
||||||
|
|
||||||
|
// Temporary storage has no limit for origin usage (there's a group and the
|
||||||
|
// global limit though).
|
||||||
|
|
||||||
|
uint64_t newGroupUsage = groupInfo->mUsage + delta;
|
||||||
|
|
||||||
|
// Temporary storage has a hard limit for group usage (20 % of the global
|
||||||
|
// limit).
|
||||||
|
if (newGroupUsage > quotaManager->GetGroupLimit()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t newTemporaryStorageUsage = quotaManager->mTemporaryStorageUsage +
|
||||||
|
delta;
|
||||||
|
|
||||||
|
if (newTemporaryStorageUsage > quotaManager->mTemporaryStorageLimit) {
|
||||||
|
// This will block the thread without holding the lock while waitting.
|
||||||
|
|
||||||
|
nsAutoTArray<OriginInfo*, 10> originInfos;
|
||||||
|
uint64_t sizeToBeFreed =
|
||||||
|
quotaManager->LockedCollectOriginsForEviction(delta, originInfos);
|
||||||
|
|
||||||
|
if (!sizeToBeFreed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(sizeToBeFreed >= delta, "Huh?");
|
||||||
|
|
||||||
|
{
|
||||||
|
MutexAutoUnlock autoUnlock(quotaManager->mQuotaMutex);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < originInfos.Length(); i++) {
|
||||||
|
quotaManager->DeleteTemporaryFilesForOrigin(originInfos[i]->mOrigin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relocked.
|
||||||
|
|
||||||
|
NS_ASSERTION(mOriginInfo, "How come?!");
|
||||||
|
|
||||||
|
nsTArray<nsCString> origins;
|
||||||
|
for (uint32_t i = 0; i < originInfos.Length(); i++) {
|
||||||
|
OriginInfo* originInfo = originInfos[i];
|
||||||
|
|
||||||
|
NS_ASSERTION(originInfo != mOriginInfo, "Deleted itself!");
|
||||||
|
|
||||||
|
nsCString group = originInfo->mGroupInfo->mGroup;
|
||||||
|
nsCString origin = originInfo->mOrigin;
|
||||||
|
quotaManager->LockedRemoveQuotaForOrigin(PERSISTENCE_TYPE_TEMPORARY,
|
||||||
|
group, origin);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
originInfos[i] = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
origins.AppendElement(origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We unlocked and relocked several times so we need to recompute all the
|
||||||
|
// essential variables and recheck the group limit.
|
||||||
|
|
||||||
|
delta = end - mSize;
|
||||||
|
|
||||||
|
newUsage = mOriginInfo->mUsage + delta;
|
||||||
|
|
||||||
|
newGroupUsage = groupInfo->mUsage + delta;
|
||||||
|
|
||||||
|
if (newGroupUsage > quotaManager->GetGroupLimit()) {
|
||||||
|
// Unfortunately some other thread increased the group usage in the
|
||||||
|
// meantime and we are not below the group limit anymore.
|
||||||
|
|
||||||
|
// However, the origin eviction must be finalized in this case too.
|
||||||
|
MutexAutoUnlock autoUnlock(quotaManager->mQuotaMutex);
|
||||||
|
|
||||||
|
quotaManager->FinalizeOriginEviction(origins);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
newTemporaryStorageUsage = quotaManager->mTemporaryStorageUsage + delta;
|
||||||
|
|
||||||
|
NS_ASSERTION(newTemporaryStorageUsage <=
|
||||||
|
quotaManager->mTemporaryStorageLimit, "How come?!");
|
||||||
|
|
||||||
|
// Ok, we successfully freed enough space and the operation can continue
|
||||||
|
// without throwing the quota error.
|
||||||
|
|
||||||
|
mOriginInfo->mUsage = newUsage;
|
||||||
|
groupInfo->mUsage = newGroupUsage;
|
||||||
|
quotaManager->mTemporaryStorageUsage = newTemporaryStorageUsage;;
|
||||||
|
|
||||||
|
// Some other thread could increase the size in the meantime, but no more
|
||||||
|
// than this one.
|
||||||
|
NS_ASSERTION(mSize < end, "This shouldn't happen!");
|
||||||
|
mSize = end;
|
||||||
|
|
||||||
|
// Finally, release IO thread only objects and allow next synchronized
|
||||||
|
// ops for the evicted origins.
|
||||||
|
MutexAutoUnlock autoUnlock(quotaManager->mQuotaMutex);
|
||||||
|
|
||||||
|
quotaManager->FinalizeOriginEviction(origins);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
mOriginInfo->mUsage = newUsage;
|
mOriginInfo->mUsage = newUsage;
|
||||||
|
groupInfo->mUsage = newGroupUsage;
|
||||||
|
quotaManager->mTemporaryStorageUsage = newTemporaryStorageUsage;
|
||||||
|
|
||||||
mSize = end;
|
mSize = end;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void
|
void
|
||||||
OriginInfo::LockedClearOriginInfos()
|
OriginInfo::LockedDecreaseUsage(int64_t aSize)
|
||||||
{
|
{
|
||||||
QuotaManager* quotaManager = QuotaManager::Get();
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
|
||||||
|
|
||||||
quotaManager->mQuotaMutex.AssertCurrentThreadOwns();
|
mUsage -= aSize;
|
||||||
|
|
||||||
mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr);
|
mGroupInfo->mUsage -= aSize;
|
||||||
|
|
||||||
|
if (mGroupInfo->IsForTemporaryStorage()) {
|
||||||
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
|
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||||
|
|
||||||
|
quotaManager->mTemporaryStorageUsage -= aSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
PLDHashOperator
|
PLDHashOperator
|
||||||
|
@ -157,3 +306,118 @@ OriginInfo::ClearOriginInfoCallback(const nsAString& aKey,
|
||||||
|
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<OriginInfo>
|
||||||
|
GroupInfo::LockedGetOriginInfo(const nsACString& aOrigin)
|
||||||
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
|
for (uint32_t index = 0; index < mOriginInfos.Length(); index++) {
|
||||||
|
nsRefPtr<OriginInfo>& originInfo = mOriginInfos[index];
|
||||||
|
|
||||||
|
if (originInfo->mOrigin == aOrigin) {
|
||||||
|
nsRefPtr<OriginInfo> result = originInfo;
|
||||||
|
return result.forget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupInfo::LockedAddOriginInfo(OriginInfo* aOriginInfo)
|
||||||
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
|
NS_ASSERTION(!mOriginInfos.Contains(aOriginInfo),
|
||||||
|
"Replacing an existing entry!");
|
||||||
|
mOriginInfos.AppendElement(aOriginInfo);
|
||||||
|
|
||||||
|
mUsage += aOriginInfo->mUsage;
|
||||||
|
|
||||||
|
if (IsForTemporaryStorage()) {
|
||||||
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
|
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||||
|
|
||||||
|
quotaManager->mTemporaryStorageUsage += aOriginInfo->mUsage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupInfo::LockedRemoveOriginInfo(const nsACString& aOrigin)
|
||||||
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
|
for (uint32_t index = 0; index < mOriginInfos.Length(); index++) {
|
||||||
|
if (mOriginInfos[index]->mOrigin == aOrigin) {
|
||||||
|
mUsage -= mOriginInfos[index]->mUsage;
|
||||||
|
|
||||||
|
if (IsForTemporaryStorage()) {
|
||||||
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
|
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||||
|
|
||||||
|
quotaManager->mTemporaryStorageUsage -= mOriginInfos[index]->mUsage;
|
||||||
|
}
|
||||||
|
|
||||||
|
mOriginInfos.RemoveElementAt(index);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupInfo::LockedRemoveOriginInfos()
|
||||||
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
|
for (uint32_t index = mOriginInfos.Length(); index > 0; index--) {
|
||||||
|
mUsage -= mOriginInfos[index - 1]->mUsage;
|
||||||
|
|
||||||
|
if (IsForTemporaryStorage()) {
|
||||||
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
|
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||||
|
|
||||||
|
quotaManager->mTemporaryStorageUsage -= mOriginInfos[index - 1]->mUsage;
|
||||||
|
}
|
||||||
|
|
||||||
|
mOriginInfos.RemoveElementAt(index - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupInfo::LockedRemoveOriginInfosForPattern(const nsACString& aPattern)
|
||||||
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
|
for (uint32_t index = mOriginInfos.Length(); index > 0; index--) {
|
||||||
|
if (PatternMatchesOrigin(aPattern, mOriginInfos[index - 1]->mOrigin)) {
|
||||||
|
mUsage -= mOriginInfos[index - 1]->mUsage;
|
||||||
|
|
||||||
|
if (IsForTemporaryStorage()) {
|
||||||
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
|
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||||
|
|
||||||
|
quotaManager->mTemporaryStorageUsage -= mOriginInfos[index - 1]->mUsage;
|
||||||
|
}
|
||||||
|
|
||||||
|
mOriginInfos.RemoveElementAt(index - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<GroupInfo>&
|
||||||
|
GroupInfoPair::GetGroupInfoForPersistenceType(PersistenceType aPersistenceType)
|
||||||
|
{
|
||||||
|
switch (aPersistenceType) {
|
||||||
|
case PERSISTENCE_TYPE_PERSISTENT:
|
||||||
|
return mPersistentStorageGroupInfo;
|
||||||
|
case PERSISTENCE_TYPE_TEMPORARY:
|
||||||
|
return mTemporaryStorageGroupInfo;
|
||||||
|
|
||||||
|
case PERSISTENCE_TYPE_INVALID:
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("Bad persistence type value!");
|
||||||
|
return mPersistentStorageGroupInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,8 +11,12 @@
|
||||||
|
|
||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
|
|
||||||
|
#include "PersistenceType.h"
|
||||||
|
|
||||||
BEGIN_QUOTA_NAMESPACE
|
BEGIN_QUOTA_NAMESPACE
|
||||||
|
|
||||||
|
class GroupInfo;
|
||||||
|
class GroupInfoPair;
|
||||||
class OriginInfo;
|
class OriginInfo;
|
||||||
class QuotaManager;
|
class QuotaManager;
|
||||||
|
|
||||||
|
@ -37,10 +41,14 @@ public:
|
||||||
private:
|
private:
|
||||||
QuotaObject(OriginInfo* aOriginInfo, const nsAString& aPath, int64_t aSize)
|
QuotaObject(OriginInfo* aOriginInfo, const nsAString& aPath, int64_t aSize)
|
||||||
: mOriginInfo(aOriginInfo), mPath(aPath), mSize(aSize)
|
: mOriginInfo(aOriginInfo), mPath(aPath), mSize(aSize)
|
||||||
{ }
|
{
|
||||||
|
MOZ_COUNT_CTOR(QuotaObject);
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~QuotaObject()
|
~QuotaObject()
|
||||||
{ }
|
{
|
||||||
|
MOZ_COUNT_DTOR(QuotaObject);
|
||||||
|
}
|
||||||
|
|
||||||
mozilla::ThreadSafeAutoRefCnt mRefCnt;
|
mozilla::ThreadSafeAutoRefCnt mRefCnt;
|
||||||
|
|
||||||
|
@ -51,27 +59,51 @@ private:
|
||||||
|
|
||||||
class OriginInfo
|
class OriginInfo
|
||||||
{
|
{
|
||||||
|
friend class GroupInfo;
|
||||||
friend class QuotaManager;
|
friend class QuotaManager;
|
||||||
friend class QuotaObject;
|
friend class QuotaObject;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OriginInfo(const nsACString& aOrigin, int64_t aLimit, int64_t aUsage)
|
OriginInfo(GroupInfo* aGroupInfo, const nsACString& aOrigin, uint64_t aLimit,
|
||||||
: mOrigin(aOrigin), mLimit(aLimit), mUsage(aUsage)
|
uint64_t aUsage, int64_t aAccessTime)
|
||||||
|
: mGroupInfo(aGroupInfo), mOrigin(aOrigin), mLimit(aLimit), mUsage(aUsage),
|
||||||
|
mAccessTime(aAccessTime)
|
||||||
{
|
{
|
||||||
|
MOZ_COUNT_CTOR(OriginInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
~OriginInfo()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(OriginInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OriginInfo)
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OriginInfo)
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
AccessTime() const
|
||||||
|
{
|
||||||
|
return mAccessTime;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void
|
void
|
||||||
#ifdef DEBUG
|
LockedDecreaseUsage(int64_t aSize);
|
||||||
LockedClearOriginInfos();
|
|
||||||
#else
|
void
|
||||||
|
LockedUpdateAccessTime(int64_t aAccessTime)
|
||||||
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
|
mAccessTime = aAccessTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
LockedClearOriginInfos()
|
LockedClearOriginInfos()
|
||||||
{
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr);
|
mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static PLDHashOperator
|
static PLDHashOperator
|
||||||
ClearOriginInfoCallback(const nsAString& aKey,
|
ClearOriginInfoCallback(const nsAString& aKey,
|
||||||
|
@ -79,9 +111,153 @@ private:
|
||||||
|
|
||||||
nsDataHashtable<nsStringHashKey, QuotaObject*> mQuotaObjects;
|
nsDataHashtable<nsStringHashKey, QuotaObject*> mQuotaObjects;
|
||||||
|
|
||||||
|
GroupInfo* mGroupInfo;
|
||||||
nsCString mOrigin;
|
nsCString mOrigin;
|
||||||
int64_t mLimit;
|
uint64_t mLimit;
|
||||||
int64_t mUsage;
|
uint64_t mUsage;
|
||||||
|
int64_t mAccessTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OriginInfoLRUComparator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
Equals(const OriginInfo* a, const OriginInfo* b) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
a && b ? a->AccessTime() == b->AccessTime() : !a && !b ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
LessThan(const OriginInfo* a, const OriginInfo* b) const
|
||||||
|
{
|
||||||
|
return a && b ? a->AccessTime() < b->AccessTime() : b ? true : false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GroupInfo
|
||||||
|
{
|
||||||
|
friend class GroupInfoPair;
|
||||||
|
friend class OriginInfo;
|
||||||
|
friend class QuotaManager;
|
||||||
|
friend class QuotaObject;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GroupInfo(PersistenceType aPersistenceType, const nsACString& aGroup)
|
||||||
|
: mPersistenceType(aPersistenceType), mGroup(aGroup), mUsage(0)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(GroupInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
~GroupInfo()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(GroupInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GroupInfo)
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsForPersistentStorage() const
|
||||||
|
{
|
||||||
|
return mPersistenceType == PERSISTENCE_TYPE_PERSISTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsForTemporaryStorage() const
|
||||||
|
{
|
||||||
|
return mPersistenceType == PERSISTENCE_TYPE_TEMPORARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
already_AddRefed<OriginInfo>
|
||||||
|
LockedGetOriginInfo(const nsACString& aOrigin);
|
||||||
|
|
||||||
|
void
|
||||||
|
LockedAddOriginInfo(OriginInfo* aOriginInfo);
|
||||||
|
|
||||||
|
void
|
||||||
|
LockedRemoveOriginInfo(const nsACString& aOrigin);
|
||||||
|
|
||||||
|
void
|
||||||
|
LockedRemoveOriginInfos();
|
||||||
|
|
||||||
|
void
|
||||||
|
LockedRemoveOriginInfosForPattern(const nsACString& aPattern);
|
||||||
|
|
||||||
|
bool
|
||||||
|
LockedHasOriginInfos()
|
||||||
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
|
return !mOriginInfos.IsEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<nsRefPtr<OriginInfo> > mOriginInfos;
|
||||||
|
|
||||||
|
PersistenceType mPersistenceType;
|
||||||
|
nsCString mGroup;
|
||||||
|
uint64_t mUsage;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GroupInfoPair
|
||||||
|
{
|
||||||
|
friend class QuotaManager;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GroupInfoPair()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(GroupInfoPair);
|
||||||
|
}
|
||||||
|
|
||||||
|
~GroupInfoPair()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(GroupInfoPair);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
already_AddRefed<GroupInfo>
|
||||||
|
LockedGetGroupInfo(PersistenceType aPersistenceType)
|
||||||
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
|
nsRefPtr<GroupInfo> groupInfo =
|
||||||
|
GetGroupInfoForPersistenceType(aPersistenceType);
|
||||||
|
return groupInfo.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LockedSetGroupInfo(GroupInfo* aGroupInfo)
|
||||||
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
|
nsRefPtr<GroupInfo>& groupInfo =
|
||||||
|
GetGroupInfoForPersistenceType(aGroupInfo->mPersistenceType);
|
||||||
|
groupInfo = aGroupInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LockedClearGroupInfo(PersistenceType aPersistenceType)
|
||||||
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
|
nsRefPtr<GroupInfo>& groupInfo =
|
||||||
|
GetGroupInfoForPersistenceType(aPersistenceType);
|
||||||
|
groupInfo = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
LockedHasGroupInfos()
|
||||||
|
{
|
||||||
|
AssertCurrentThreadOwnsQuotaMutex();
|
||||||
|
|
||||||
|
return mPersistentStorageGroupInfo || mTemporaryStorageGroupInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<GroupInfo>&
|
||||||
|
GetGroupInfoForPersistenceType(PersistenceType aPersistenceType);
|
||||||
|
|
||||||
|
nsRefPtr<GroupInfo> mPersistentStorageGroupInfo;
|
||||||
|
nsRefPtr<GroupInfo> mTemporaryStorageGroupInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
END_QUOTA_NAMESPACE
|
END_QUOTA_NAMESPACE
|
||||||
|
|
|
@ -12,8 +12,13 @@
|
||||||
BEGIN_QUOTA_NAMESPACE
|
BEGIN_QUOTA_NAMESPACE
|
||||||
|
|
||||||
enum StoragePrivilege {
|
enum StoragePrivilege {
|
||||||
Content,
|
// Quota not tracked, persistence type is always "persistent".
|
||||||
Chrome
|
Chrome,
|
||||||
|
|
||||||
|
// Quota tracked, persistence type can be either "persistent" or "temporary".
|
||||||
|
// The permission "defaul-persistent-storage" is used to determine the
|
||||||
|
// default persistence type.
|
||||||
|
Content
|
||||||
};
|
};
|
||||||
|
|
||||||
END_QUOTA_NAMESPACE
|
END_QUOTA_NAMESPACE
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#ifndef mozilla_dom_quota_usagerunnable_h__
|
#ifndef mozilla_dom_quota_usageinfo_h__
|
||||||
#define mozilla_dom_quota_usagerunnable_h__
|
#define mozilla_dom_quota_usageinfo_h__
|
||||||
|
|
||||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||||
|
|
||||||
|
@ -14,14 +14,14 @@
|
||||||
|
|
||||||
BEGIN_QUOTA_NAMESPACE
|
BEGIN_QUOTA_NAMESPACE
|
||||||
|
|
||||||
class UsageRunnable
|
class UsageInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UsageRunnable()
|
UsageInfo()
|
||||||
: mCanceled(0), mDatabaseUsage(0), mFileUsage(0)
|
: mCanceled(0), mDatabaseUsage(0), mFileUsage(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual ~UsageRunnable()
|
virtual ~UsageInfo()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -79,4 +79,4 @@ private:
|
||||||
|
|
||||||
END_QUOTA_NAMESPACE
|
END_QUOTA_NAMESPACE
|
||||||
|
|
||||||
#endif // mozilla_dom_quota_usagerunnable_h__
|
#endif // mozilla_dom_quota_usageinfo_h__
|
|
@ -24,11 +24,12 @@ EXPORTS.mozilla.dom.quota += [
|
||||||
'Client.h',
|
'Client.h',
|
||||||
'FileStreams.h',
|
'FileStreams.h',
|
||||||
'OriginOrPatternString.h',
|
'OriginOrPatternString.h',
|
||||||
|
'PersistenceType.h',
|
||||||
'QuotaCommon.h',
|
'QuotaCommon.h',
|
||||||
'QuotaManager.h',
|
'QuotaManager.h',
|
||||||
'QuotaObject.h',
|
'QuotaObject.h',
|
||||||
'StoragePrivilege.h',
|
'StoragePrivilege.h',
|
||||||
'UsageRunnable.h',
|
'UsageInfo.h',
|
||||||
'Utilities.h',
|
'Utilities.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,13 @@
|
||||||
|
|
||||||
#include "nsIFileStorage.h"
|
#include "nsIFileStorage.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/quota/PersistenceType.h"
|
||||||
|
|
||||||
#define NS_OFFLINESTORAGE_IID \
|
#define NS_OFFLINESTORAGE_IID \
|
||||||
{0xe531b6e0, 0x55b8, 0x4f39, \
|
{0xec7e878d, 0xc8c1, 0x402e, \
|
||||||
{ 0x95, 0xbb, 0x97, 0x21, 0x4c, 0xb0, 0xf6, 0x1a } }
|
{ 0xa2, 0xc4, 0xf6, 0x82, 0x29, 0x4e, 0x3c, 0xb1 } }
|
||||||
|
|
||||||
|
class nsPIDOMWindow;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
@ -25,6 +29,7 @@ class nsIOfflineStorage : public nsIFileStorage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef mozilla::dom::quota::Client Client;
|
typedef mozilla::dom::quota::Client Client;
|
||||||
|
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||||
|
|
||||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_OFFLINESTORAGE_IID)
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_OFFLINESTORAGE_IID)
|
||||||
|
|
||||||
|
@ -34,6 +39,18 @@ public:
|
||||||
NS_IMETHOD_(bool)
|
NS_IMETHOD_(bool)
|
||||||
IsOwned(nsPIDOMWindow* aOwner) = 0;
|
IsOwned(nsPIDOMWindow* aOwner) = 0;
|
||||||
|
|
||||||
|
NS_IMETHOD_(PersistenceType)
|
||||||
|
Type()
|
||||||
|
{
|
||||||
|
return mPersistenceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD_(const nsACString&)
|
||||||
|
Group()
|
||||||
|
{
|
||||||
|
return mGroup;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHOD_(const nsACString&)
|
NS_IMETHOD_(const nsACString&)
|
||||||
Origin() = 0;
|
Origin() = 0;
|
||||||
|
|
||||||
|
@ -50,6 +67,17 @@ public:
|
||||||
// operations should be aborted and pending operations should be discarded.
|
// operations should be aborted and pending operations should be discarded.
|
||||||
NS_IMETHOD_(void)
|
NS_IMETHOD_(void)
|
||||||
Invalidate() = 0;
|
Invalidate() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nsIOfflineStorage()
|
||||||
|
: mPersistenceType(mozilla::dom::quota::PERSISTENCE_TYPE_INVALID)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual ~nsIOfflineStorage()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
PersistenceType mPersistenceType;
|
||||||
|
nsCString mGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIOfflineStorage, NS_OFFLINESTORAGE_IID)
|
NS_DEFINE_STATIC_IID_ACCESSOR(nsIOfflineStorage, NS_OFFLINESTORAGE_IID)
|
||||||
|
|
|
@ -10,7 +10,7 @@ interface nsIQuotaRequest;
|
||||||
interface nsIURI;
|
interface nsIURI;
|
||||||
interface nsIUsageCallback;
|
interface nsIUsageCallback;
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(8d74e6f8-81c3-4045-9bb7-70bdb7b11b25)]
|
[scriptable, builtinclass, uuid(f19a03ae-e97d-41e9-95dd-681b910c4093)]
|
||||||
interface nsIQuotaManager : nsISupports
|
interface nsIQuotaManager : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -29,6 +29,17 @@ interface nsIQuotaManager : nsISupports
|
||||||
[optional] in unsigned long aAppId,
|
[optional] in unsigned long aAppId,
|
||||||
[optional] in boolean aInMozBrowserOnly);
|
[optional] in boolean aInMozBrowserOnly);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all storages. The files may not be deleted immediately depending
|
||||||
|
* on prohibitive concurrent operations.
|
||||||
|
* Be careful, this removes *all* the data that has ever been stored!
|
||||||
|
*
|
||||||
|
* If the dom.quotaManager.testing preference is not true the call will be
|
||||||
|
* a no-op.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clear();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all storages stored for the given URI. The files may not be
|
* Removes all storages stored for the given URI. The files may not be
|
||||||
* deleted immediately depending on prohibitive concurrent operations.
|
* deleted immediately depending on prohibitive concurrent operations.
|
||||||
|
@ -41,4 +52,16 @@ interface nsIQuotaManager : nsISupports
|
||||||
clearStoragesForURI(in nsIURI aURI,
|
clearStoragesForURI(in nsIURI aURI,
|
||||||
[optional] in unsigned long aAppId,
|
[optional] in unsigned long aAppId,
|
||||||
[optional] in boolean aInMozBrowserOnly);
|
[optional] in boolean aInMozBrowserOnly);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets quota and storage management. This can be used to force
|
||||||
|
* reinitialization of the temp storage, for example when the pref for
|
||||||
|
* overriding the temp storage limit has changed.
|
||||||
|
* Be carefull, this invalidates all live storages!
|
||||||
|
*
|
||||||
|
* If the dom.quotaManager.testing preference is not true the call will be
|
||||||
|
* a no-op.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
reset();
|
||||||
};
|
};
|
||||||
|
|
|
@ -44,6 +44,9 @@ interface IDBDatabase : EventTarget {
|
||||||
};
|
};
|
||||||
|
|
||||||
partial interface IDBDatabase {
|
partial interface IDBDatabase {
|
||||||
|
[Pref="dom.indexedDB.experimental"]
|
||||||
|
readonly attribute StorageType storage;
|
||||||
|
|
||||||
[Throws]
|
[Throws]
|
||||||
IDBRequest mozCreateFileHandle (DOMString name, optional DOMString type);
|
IDBRequest mozCreateFileHandle (DOMString name, optional DOMString type);
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,12 @@
|
||||||
|
|
||||||
interface Principal;
|
interface Principal;
|
||||||
|
|
||||||
|
dictionary IDBOpenDBOptions
|
||||||
|
{
|
||||||
|
[EnforceRange] unsigned long long version;
|
||||||
|
StorageType storage;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface that defines the indexedDB property on a window. See
|
* Interface that defines the indexedDB property on a window. See
|
||||||
* http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBFactory
|
* http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBFactory
|
||||||
|
@ -21,11 +27,17 @@ interface IDBFactory {
|
||||||
[Throws]
|
[Throws]
|
||||||
IDBOpenDBRequest
|
IDBOpenDBRequest
|
||||||
open(DOMString name,
|
open(DOMString name,
|
||||||
[EnforceRange] optional unsigned long long version);
|
[EnforceRange] unsigned long long version);
|
||||||
|
|
||||||
[Throws]
|
[Throws]
|
||||||
IDBOpenDBRequest
|
IDBOpenDBRequest
|
||||||
deleteDatabase(DOMString name);
|
open(DOMString name,
|
||||||
|
optional IDBOpenDBOptions options);
|
||||||
|
|
||||||
|
[Throws]
|
||||||
|
IDBOpenDBRequest
|
||||||
|
deleteDatabase(DOMString name,
|
||||||
|
optional IDBOpenDBOptions options);
|
||||||
|
|
||||||
[Throws]
|
[Throws]
|
||||||
short
|
short
|
||||||
|
@ -36,10 +48,17 @@ interface IDBFactory {
|
||||||
IDBOpenDBRequest
|
IDBOpenDBRequest
|
||||||
openForPrincipal(Principal principal,
|
openForPrincipal(Principal principal,
|
||||||
DOMString name,
|
DOMString name,
|
||||||
[EnforceRange] optional unsigned long long version);
|
[EnforceRange] unsigned long long version);
|
||||||
|
|
||||||
|
[Throws, ChromeOnly]
|
||||||
|
IDBOpenDBRequest
|
||||||
|
openForPrincipal(Principal principal,
|
||||||
|
DOMString name,
|
||||||
|
optional IDBOpenDBOptions options);
|
||||||
|
|
||||||
[Throws, ChromeOnly]
|
[Throws, ChromeOnly]
|
||||||
IDBOpenDBRequest
|
IDBOpenDBRequest
|
||||||
deleteForPrincipal(Principal principal,
|
deleteForPrincipal(Principal principal,
|
||||||
DOMString name);
|
DOMString name,
|
||||||
|
optional IDBOpenDBOptions options);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum StorageType { "persistent", "temporary" };
|
|
@ -259,6 +259,7 @@ WEBIDL_FILES = [
|
||||||
'SimpleGestureEvent.webidl',
|
'SimpleGestureEvent.webidl',
|
||||||
'SourceBuffer.webidl',
|
'SourceBuffer.webidl',
|
||||||
'SourceBufferList.webidl',
|
'SourceBufferList.webidl',
|
||||||
|
'StorageType.webidl',
|
||||||
'StyleSheet.webidl',
|
'StyleSheet.webidl',
|
||||||
'SVGAElement.webidl',
|
'SVGAElement.webidl',
|
||||||
'SVGAltGlyphElement.webidl',
|
'SVGAltGlyphElement.webidl',
|
||||||
|
|
|
@ -78,10 +78,15 @@ pref("offline-apps.quota.warn", 51200);
|
||||||
// cache compression turned off for now - see bug #715198
|
// cache compression turned off for now - see bug #715198
|
||||||
pref("browser.cache.compression_level", 0);
|
pref("browser.cache.compression_level", 0);
|
||||||
|
|
||||||
|
// Whether or not testing features are enabled.
|
||||||
|
pref("dom.quotaManager.testing", false);
|
||||||
|
|
||||||
// Whether or not indexedDB is enabled.
|
// Whether or not indexedDB is enabled.
|
||||||
pref("dom.indexedDB.enabled", true);
|
pref("dom.indexedDB.enabled", true);
|
||||||
// Space to allow indexedDB databases before prompting (in MB).
|
// Space to allow indexedDB databases before prompting (in MB).
|
||||||
pref("dom.indexedDB.warningQuota", 50);
|
pref("dom.indexedDB.warningQuota", 50);
|
||||||
|
// Whether or not indexedDB experimental features are enabled.
|
||||||
|
pref("dom.indexedDB.experimental", false);
|
||||||
|
|
||||||
// Whether or not Web Workers are enabled.
|
// Whether or not Web Workers are enabled.
|
||||||
pref("dom.workers.enabled", true);
|
pref("dom.workers.enabled", true);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "mozilla/Util.h"
|
#include "mozilla/Util.h"
|
||||||
|
#include "mozilla/dom/quota/PersistenceType.h"
|
||||||
#include "mozilla/dom/quota/QuotaManager.h"
|
#include "mozilla/dom/quota/QuotaManager.h"
|
||||||
#include "mozilla/dom/quota/QuotaObject.h"
|
#include "mozilla/dom/quota/QuotaObject.h"
|
||||||
#include "mozilla/SQLiteInterposer.h"
|
#include "mozilla/SQLiteInterposer.h"
|
||||||
|
@ -349,15 +350,19 @@ xOpen(sqlite3_vfs* vfs, const char *zName, sqlite3_file* pFile,
|
||||||
}
|
}
|
||||||
p->histograms = h;
|
p->histograms = h;
|
||||||
|
|
||||||
|
const char* persistenceType;
|
||||||
|
const char* group;
|
||||||
const char* origin;
|
const char* origin;
|
||||||
if ((flags & SQLITE_OPEN_URI) &&
|
if ((flags & SQLITE_OPEN_URI) &&
|
||||||
|
(persistenceType = sqlite3_uri_parameter(zName, "persistenceType")) &&
|
||||||
|
(group = sqlite3_uri_parameter(zName, "group")) &&
|
||||||
(origin = sqlite3_uri_parameter(zName, "origin"))) {
|
(origin = sqlite3_uri_parameter(zName, "origin"))) {
|
||||||
QuotaManager* quotaManager = QuotaManager::Get();
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
MOZ_ASSERT(quotaManager);
|
MOZ_ASSERT(quotaManager);
|
||||||
|
|
||||||
p->quotaObject = quotaManager->GetQuotaObject(nsDependentCString(origin),
|
p->quotaObject = quotaManager->GetQuotaObject(PersistenceTypeFromText(
|
||||||
NS_ConvertUTF8toUTF16(zName));
|
nsDependentCString(persistenceType)), nsDependentCString(group),
|
||||||
|
nsDependentCString(origin), NS_ConvertUTF8toUTF16(zName));
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = orig_vfs->xOpen(orig_vfs, zName, p->pReal, flags, pOutFlags);
|
rc = orig_vfs->xOpen(orig_vfs, zName, p->pReal, flags, pOutFlags);
|
||||||
|
|
|
@ -1182,6 +1182,11 @@ SpecialPowersAPI.prototype = {
|
||||||
Cu.forceCC();
|
Cu.forceCC();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Due to various dependencies between JS objects and C++ objects, an ordinary
|
||||||
|
// forceGC doesn't necessarily clear all unused objects, thus the GC and CC
|
||||||
|
// needs to run several times and when no other JS is running.
|
||||||
|
// The current number of iterations has been determined according to massive
|
||||||
|
// cross platform testing.
|
||||||
exactGC: function(win, callback) {
|
exactGC: function(win, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче