зеркало из https://github.com/mozilla/gecko-dev.git
Bug 786295 - 'Delete IndexedDB related to an app when uninstalled'. r=bz+khuey+sicking.
This commit is contained in:
Родитель
993f960b0d
Коммит
5e8d8d57f2
|
@ -21,7 +21,7 @@ interface nsIContentSecurityPolicy;
|
|||
[ptr] native JSPrincipals(JSPrincipals);
|
||||
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
|
||||
|
||||
[scriptable, uuid(96a92f0c-adcb-44ac-a034-37627647ec97)]
|
||||
[scriptable, uuid(3a283dc9-f733-4618-a36f-e2b68c280ab7)]
|
||||
interface nsIPrincipal : nsISerializable
|
||||
{
|
||||
/**
|
||||
|
@ -195,6 +195,12 @@ interface nsIPrincipal : nsISerializable
|
|||
* appId everywhere where we construct principals.
|
||||
*/
|
||||
readonly attribute boolean unknownAppId;
|
||||
|
||||
/**
|
||||
* Returns true iff this principal is a null principal (corresponding to an
|
||||
* unknown, hence assumed minimally privileged, security context).
|
||||
*/
|
||||
readonly attribute boolean isNullPrincipal;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -217,4 +223,4 @@ interface nsIExpandedPrincipal : nsISupports
|
|||
* should not be changed and should only be used ephemerally.
|
||||
*/
|
||||
[noscript] readonly attribute PrincipalArray whiteList;
|
||||
};
|
||||
};
|
|
@ -71,6 +71,7 @@ public:
|
|||
NS_IMETHOD GetAppId(uint32_t* aAppStatus);
|
||||
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
|
||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId);
|
||||
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal);
|
||||
#ifdef DEBUG
|
||||
virtual void dumpImpl();
|
||||
#endif
|
||||
|
@ -152,6 +153,7 @@ public:
|
|||
NS_IMETHOD GetAppId(uint32_t* aAppStatus);
|
||||
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
|
||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId);
|
||||
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal);
|
||||
#ifdef DEBUG
|
||||
virtual void dumpImpl();
|
||||
#endif
|
||||
|
|
|
@ -291,6 +291,13 @@ nsNullPrincipal::GetUnknownAppId(bool* aUnknownAppId)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
|
||||
{
|
||||
*aIsNullPrincipal = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* nsISerializable implementation
|
||||
*/
|
||||
|
|
|
@ -541,6 +541,13 @@ nsPrincipal::GetUnknownAppId(bool* aUnknownAppId)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
|
||||
{
|
||||
*aIsNullPrincipal = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrincipal::Read(nsIObjectInputStream* aStream)
|
||||
{
|
||||
|
@ -852,6 +859,13 @@ nsExpandedPrincipal::GetUnknownAppId(bool* aUnknownAppId)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
|
||||
{
|
||||
*aIsNullPrincipal = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
|
||||
{
|
||||
|
|
|
@ -2992,11 +2992,13 @@ GetExtendedOrigin(nsIURI* aURI, uint32_t aAppId, bool aInMozBrowser,
|
|||
return;
|
||||
}
|
||||
|
||||
// aExtendedOrigin = appId + "+" + origin + "+" + { 't', 'f' }
|
||||
// aExtendedOrigin = appId + "+" + { 't', 'f' } "+" + origin;
|
||||
aExtendedOrigin.Truncate();
|
||||
aExtendedOrigin.AppendInt(aAppId);
|
||||
aExtendedOrigin.Append(NS_LITERAL_CSTRING("+") + origin + NS_LITERAL_CSTRING("+"));
|
||||
aExtendedOrigin.Append('+');
|
||||
aExtendedOrigin.Append(aInMozBrowser ? 't' : 'f');
|
||||
aExtendedOrigin.Append('+');
|
||||
aExtendedOrigin.Append(origin);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -198,6 +198,13 @@ nsSystemPrincipal::GetUnknownAppId(bool* aUnknownAppId)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
|
||||
{
|
||||
*aIsNullPrincipal = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// Methods implementing nsISerializable //
|
||||
//////////////////////////////////////////
|
||||
|
|
|
@ -1725,6 +1725,10 @@ let DOMApplicationRegistry = {
|
|||
switch (message.name) {
|
||||
case "Webapps:ClearBrowserData":
|
||||
this._clearPrivateData(appId, true);
|
||||
// XXXbent This is a hack until bug 802366 is fixed. Currently all data
|
||||
// loaded in mozbrowser frames within an app believe that their
|
||||
// appId is 0.
|
||||
this._clearPrivateData(0, true);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -181,31 +181,6 @@ DatabaseInfo::Remove(nsIAtom* aId)
|
|||
}
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
EnumerateDatabasesRemoveOrigin(nsISupports* aId,
|
||||
DatabaseInfo*& aDatabaseInfo,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
const nsACString* origin = static_cast<const nsACString*>(aUserArg);
|
||||
return aDatabaseInfo->origin.Equals(*origin) ?
|
||||
PL_DHASH_REMOVE :
|
||||
PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
DatabaseInfo::RemoveAllForOrigin(const nsACString& aOrigin)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (gDatabaseHash) {
|
||||
gDatabaseHash->Enumerate(EnumerateDatabasesRemoveOrigin,
|
||||
const_cast<nsACString*>(&aOrigin));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DatabaseInfo::GetObjectStoreNames(nsTArray<nsString>& aNames)
|
||||
{
|
||||
|
|
|
@ -62,8 +62,6 @@ struct DatabaseInfo : public DatabaseInfoGuts
|
|||
|
||||
static void Remove(nsIAtom* aId);
|
||||
|
||||
static void RemoveAllForOrigin(const nsACString& aOrigin);
|
||||
|
||||
bool GetObjectStoreNames(nsTArray<nsString>& aNames);
|
||||
bool ContainsStoreName(const nsAString& aName);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMLists.h"
|
||||
|
@ -33,6 +34,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
|
||||
#include "ipc/IndexedDBChild.h"
|
||||
#include "ipc/IndexedDBParent.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using mozilla::dom::ContentParent;
|
||||
|
@ -269,12 +271,14 @@ IDBDatabase::Invalidate()
|
|||
if (owner) {
|
||||
IndexedDatabaseManager::CancelPromptsForWindow(owner);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
IDBDatabase::IsInvalidated()
|
||||
{
|
||||
return mInvalidated;
|
||||
DatabaseInfo::Remove(mDatabaseId);
|
||||
|
||||
// And let the child process know as well.
|
||||
if (mActorParent) {
|
||||
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
||||
mozilla::unused << mActorParent->SendInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -299,8 +303,9 @@ IDBDatabase::DisconnectFromActor()
|
|||
}
|
||||
|
||||
bool
|
||||
IDBDatabase::IsDisconnectedFromActor()
|
||||
IDBDatabase::IsDisconnectedFromActor() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return mDisconnected;
|
||||
}
|
||||
|
||||
|
@ -330,7 +335,7 @@ IDBDatabase::CloseInternal(bool aIsDead)
|
|||
}
|
||||
|
||||
// And let the parent process know as well.
|
||||
if (mActorChild) {
|
||||
if (mActorChild && !IsInvalidated()) {
|
||||
NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
|
||||
mActorChild->SendClose(aIsDead);
|
||||
}
|
||||
|
@ -338,7 +343,7 @@ IDBDatabase::CloseInternal(bool aIsDead)
|
|||
}
|
||||
|
||||
bool
|
||||
IDBDatabase::IsClosed()
|
||||
IDBDatabase::IsClosed() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return mClosed;
|
||||
|
|
|
@ -74,12 +74,12 @@ public:
|
|||
return mDatabaseInfo;
|
||||
}
|
||||
|
||||
const nsString& Name()
|
||||
const nsString& Name() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
const nsString& FilePath()
|
||||
const nsString& FilePath() const
|
||||
{
|
||||
return mFilePath;
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public:
|
|||
return doc.forget();
|
||||
}
|
||||
|
||||
nsCString& Origin()
|
||||
const nsCString& Origin() const
|
||||
{
|
||||
return mASCIIOrigin;
|
||||
}
|
||||
|
@ -103,20 +103,24 @@ public:
|
|||
void Invalidate();
|
||||
|
||||
// Whether or not the database has been invalidated. If it has then no further
|
||||
// transactions for this database will be allowed to run.
|
||||
bool IsInvalidated();
|
||||
// transactions for this database will be allowed to run. This function may be
|
||||
// called on any thread.
|
||||
bool IsInvalidated() const
|
||||
{
|
||||
return mInvalidated;
|
||||
}
|
||||
|
||||
void DisconnectFromActor();
|
||||
|
||||
// Whether or not the database has been disconnected from its actor. If true
|
||||
// it is not safe to send any IPC messages to the actor representing this db
|
||||
// or any of its subactors.
|
||||
bool IsDisconnectedFromActor();
|
||||
bool IsDisconnectedFromActor() const;
|
||||
|
||||
void CloseInternal(bool aIsDead);
|
||||
|
||||
// Whether or not the database has had Close called on it.
|
||||
bool IsClosed();
|
||||
bool IsClosed() const;
|
||||
|
||||
void EnterSetVersionTransaction();
|
||||
void ExitSetVersionTransaction();
|
||||
|
|
|
@ -541,8 +541,9 @@ IDBFactory::OpenCommon(const nsAString& aName,
|
|||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
|
||||
rv =
|
||||
mgr->WaitForOpenAllowed(mASCIIOrigin, openHelper->Id(), permissionHelper);
|
||||
rv =
|
||||
mgr->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(mASCIIOrigin),
|
||||
openHelper->Id(), permissionHelper);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
}
|
||||
else if (aDeleting) {
|
||||
|
|
|
@ -175,6 +175,44 @@ struct SerializedStructuredCloneWriteInfo
|
|||
uint64_t offsetToKeyProp;
|
||||
};
|
||||
|
||||
class OriginOrPatternString : public nsCString
|
||||
{
|
||||
public:
|
||||
static OriginOrPatternString
|
||||
FromOrigin(const nsACString& aOrigin)
|
||||
{
|
||||
return OriginOrPatternString(aOrigin, true);
|
||||
}
|
||||
|
||||
static OriginOrPatternString
|
||||
FromPattern(const nsACString& aPattern)
|
||||
{
|
||||
return OriginOrPatternString(aPattern, false);
|
||||
}
|
||||
|
||||
bool
|
||||
IsOrigin() const
|
||||
{
|
||||
return mIsOrigin;
|
||||
}
|
||||
|
||||
bool
|
||||
IsPattern() const
|
||||
{
|
||||
return !mIsOrigin;
|
||||
}
|
||||
|
||||
private:
|
||||
OriginOrPatternString(const nsACString& aOriginOrPattern, bool aIsOrigin)
|
||||
: nsCString(aOriginOrPattern), mIsOrigin(aIsOrigin)
|
||||
{ }
|
||||
|
||||
bool
|
||||
operator==(const OriginOrPatternString& aOther) MOZ_DELETE;
|
||||
|
||||
bool mIsOrigin;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_indexeddb_indexeddatabase_h__
|
||||
|
|
|
@ -5,14 +5,15 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "DatabaseInfo.h"
|
||||
|
||||
#include "mozIApplicationClearPrivateDataParams.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIFileStorage.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
|
@ -27,8 +28,10 @@
|
|||
#include "mozilla/storage.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsXPCOMPrivate.h"
|
||||
|
@ -133,34 +136,247 @@ EnumerateToTArray(const nsACString& aKey,
|
|||
NS_ASSERTION(aValue, "Null pointer!");
|
||||
NS_ASSERTION(aUserArg, "Null pointer!");
|
||||
|
||||
nsTArray<T>* array =
|
||||
static_cast<nsTArray<T>*>(aUserArg);
|
||||
|
||||
if (!array->AppendElements(*aValue)) {
|
||||
NS_WARNING("Out of memory!");
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
static_cast<nsTArray<T>*>(aUserArg)->AppendElements(*aValue);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
bool
|
||||
PatternMatchesOrigin(const nsACString& aPatternString, const nsACString& aOrigin)
|
||||
{
|
||||
// Aren't we smart!
|
||||
return StringBeginsWith(aOrigin, aPatternString);
|
||||
}
|
||||
|
||||
enum MozBrowserPatternFlag
|
||||
{
|
||||
MozBrowser = 0,
|
||||
NotMozBrowser,
|
||||
IgnoreMozBrowser
|
||||
};
|
||||
|
||||
// Use one of the friendly overloads below.
|
||||
void
|
||||
GetOriginPatternString(uint32_t aAppId, MozBrowserPatternFlag aBrowserFlag,
|
||||
const nsACString& aOrigin, nsAutoCString& _retval)
|
||||
{
|
||||
NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
"Bad appId!");
|
||||
NS_ASSERTION(aOrigin.IsEmpty() || aBrowserFlag != IgnoreMozBrowser,
|
||||
"Bad args!");
|
||||
|
||||
if (aOrigin.IsEmpty()) {
|
||||
_retval.Truncate();
|
||||
|
||||
_retval.AppendInt(aAppId);
|
||||
_retval.Append('+');
|
||||
|
||||
if (aBrowserFlag != IgnoreMozBrowser) {
|
||||
if (aBrowserFlag == MozBrowser) {
|
||||
_retval.Append('t');
|
||||
}
|
||||
else {
|
||||
_retval.Append('f');
|
||||
}
|
||||
_retval.Append('+');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (aAppId != nsIScriptSecurityManager::NO_APP_ID ||
|
||||
aBrowserFlag == MozBrowser) {
|
||||
nsAutoCString pattern;
|
||||
GetOriginPatternString(aAppId, aBrowserFlag, EmptyCString(), pattern);
|
||||
NS_ASSERTION(PatternMatchesOrigin(pattern, aOrigin),
|
||||
"Origin doesn't match parameters!");
|
||||
}
|
||||
#endif
|
||||
|
||||
_retval = aOrigin;
|
||||
}
|
||||
|
||||
void
|
||||
GetOriginPatternString(uint32_t aAppId, nsAutoCString& _retval)
|
||||
{
|
||||
return GetOriginPatternString(aAppId, IgnoreMozBrowser, EmptyCString(),
|
||||
_retval);
|
||||
}
|
||||
|
||||
void
|
||||
GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly,
|
||||
nsAutoCString& _retval)
|
||||
{
|
||||
return GetOriginPatternString(aAppId,
|
||||
aBrowserOnly ? MozBrowser : NotMozBrowser,
|
||||
EmptyCString(), _retval);
|
||||
}
|
||||
|
||||
void
|
||||
GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly,
|
||||
const nsACString& aOrigin, nsAutoCString& _retval)
|
||||
{
|
||||
return GetOriginPatternString(aAppId,
|
||||
aBrowserOnly ? MozBrowser : NotMozBrowser,
|
||||
aOrigin, _retval);
|
||||
}
|
||||
|
||||
void
|
||||
GetOriginPatternStringMaybeIgnoreBrowser(uint32_t aAppId, bool aBrowserOnly,
|
||||
nsAutoCString& _retval)
|
||||
{
|
||||
return GetOriginPatternString(aAppId,
|
||||
aBrowserOnly ? MozBrowser : IgnoreMozBrowser,
|
||||
EmptyCString(), _retval);
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
class PatternMatchArray : public nsAutoTArray<ValueType, 20>
|
||||
{
|
||||
typedef PatternMatchArray<ValueType> SelfType;
|
||||
|
||||
struct Closure
|
||||
{
|
||||
Closure(SelfType& aSelf, const nsACString& aPattern)
|
||||
: mSelf(aSelf), mPattern(aPattern)
|
||||
{ }
|
||||
|
||||
SelfType& mSelf;
|
||||
const nsACString& mPattern;
|
||||
};
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
void
|
||||
Find(const T& aHashtable,
|
||||
const nsACString& aPattern)
|
||||
{
|
||||
SelfType::Clear();
|
||||
|
||||
Closure closure(*this, aPattern);
|
||||
aHashtable.EnumerateRead(SelfType::Enumerate, &closure);
|
||||
}
|
||||
|
||||
private:
|
||||
static PLDHashOperator
|
||||
Enumerate(const nsACString& aKey,
|
||||
nsTArray<ValueType>* aValue,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
|
||||
NS_ASSERTION(aValue, "Null pointer!");
|
||||
NS_ASSERTION(aUserArg, "Null pointer!");
|
||||
|
||||
Closure* closure = static_cast<Closure*>(aUserArg);
|
||||
|
||||
if (PatternMatchesOrigin(closure->mPattern, aKey)) {
|
||||
closure->mSelf.AppendElements(*aValue);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
|
||||
typedef PatternMatchArray<IDBDatabase*> DatabasePatternMatchArray;
|
||||
|
||||
PLDHashOperator
|
||||
InvalidateAllFileManagers(const nsACString& aKey,
|
||||
nsTArray<nsRefPtr<FileManager> >* aValue,
|
||||
void* aUserArg)
|
||||
InvalidateAndRemoveFileManagers(
|
||||
const nsACString& aKey,
|
||||
nsAutoPtr<nsTArray<nsRefPtr<FileManager> > >& aValue,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
|
||||
NS_ASSERTION(aValue, "Null pointer!");
|
||||
|
||||
for (uint32_t i = 0; i < aValue->Length(); i++) {
|
||||
nsRefPtr<FileManager> fileManager = aValue->ElementAt(i);
|
||||
fileManager->Invalidate();
|
||||
const nsACString* pattern =
|
||||
static_cast<const nsACString*>(aUserArg);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
SanitizeOriginString(nsCString& aOrigin)
|
||||
{
|
||||
// We want profiles to be platform-independent so we always need to replace
|
||||
// the same characters on every platform. Windows has the most extensive set
|
||||
// of illegal characters so we use its FILE_ILLEGAL_CHARACTERS and
|
||||
// FILE_PATH_SEPARATOR.
|
||||
static const char kReplaceChars[] = CONTROL_CHARACTERS "/:*?\"<>|\\";
|
||||
|
||||
#ifdef XP_WIN
|
||||
NS_ASSERTION(!strcmp(kReplaceChars,
|
||||
FILE_ILLEGAL_CHARACTERS FILE_PATH_SEPARATOR),
|
||||
"Illegal file characters have changed!");
|
||||
#endif
|
||||
|
||||
aOrigin.ReplaceChar(kReplaceChars, '+');
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetASCIIOriginFromURI(nsIURI* aURI,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowser,
|
||||
nsACString& aOrigin)
|
||||
{
|
||||
NS_ASSERTION(aURI, "Null uri!");
|
||||
|
||||
nsCString origin;
|
||||
mozilla::GetExtendedOrigin(aURI, aAppId, aInMozBrowser, origin);
|
||||
|
||||
if (origin.IsEmpty()) {
|
||||
NS_WARNING("GetExtendedOrigin returned empty string!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
aOrigin.Assign(origin);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetASCIIOriginFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
nsACString& aOrigin)
|
||||
{
|
||||
NS_ASSERTION(aPrincipal, "Don't hand me a null principal!");
|
||||
|
||||
static const char kChromeOrigin[] = "chrome";
|
||||
|
||||
nsCString origin;
|
||||
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
|
||||
origin.AssignLiteral(kChromeOrigin);
|
||||
}
|
||||
else {
|
||||
bool isNullPrincipal;
|
||||
nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPrincipal);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (isNullPrincipal) {
|
||||
NS_WARNING("IndexedDB not supported from this principal!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
rv = aPrincipal->GetExtendedOrigin(origin);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (origin.EqualsLiteral(kChromeOrigin)) {
|
||||
NS_WARNING("Non-chrome principal can't use chrome origin!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
aOrigin.Assign(origin);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
IndexedDatabaseManager::IndexedDatabaseManager()
|
||||
|
@ -297,10 +513,10 @@ IndexedDatabaseManager::GetDirectoryForOrigin(const nsACString& aASCIIOrigin,
|
|||
rv = directory->InitWithPath(GetBaseDirectory());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ConvertASCIItoUTF16 originSanitized(aASCIIOrigin);
|
||||
originSanitized.ReplaceChar(":/", '+');
|
||||
nsAutoCString originSanitized(aASCIIOrigin);
|
||||
SanitizeOriginString(originSanitized);
|
||||
|
||||
rv = directory->Append(originSanitized);
|
||||
rv = directory->Append(NS_ConvertASCIItoUTF16(originSanitized));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
directory.forget(aDirectory);
|
||||
|
@ -406,6 +622,37 @@ IndexedDatabaseManager::FireWindowOnError(nsPIDOMWindow* aOwner,
|
|||
return consoleService->LogMessage(scriptError);
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
IndexedDatabaseManager::OriginMatchesApp(const nsACString& aOrigin,
|
||||
uint32_t aAppId)
|
||||
{
|
||||
NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
|
||||
NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
"Bad appId!");
|
||||
|
||||
nsAutoCString pattern;
|
||||
GetOriginPatternString(aAppId, pattern);
|
||||
|
||||
return PatternMatchesOrigin(pattern, aOrigin);
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
IndexedDatabaseManager::OriginMatchesApp(const nsACString& aOrigin,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowser)
|
||||
{
|
||||
NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
|
||||
NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
"Bad appId!");
|
||||
|
||||
nsAutoCString pattern;
|
||||
GetOriginPatternString(aAppId, aInMozBrowser, pattern);
|
||||
|
||||
return PatternMatchesOrigin(pattern, aOrigin);
|
||||
}
|
||||
|
||||
bool
|
||||
IndexedDatabaseManager::RegisterDatabase(IDBDatabase* aDatabase)
|
||||
{
|
||||
|
@ -466,15 +713,16 @@ IndexedDatabaseManager::OnUsageCheckComplete(AsyncUsageRunnable* aRunnable)
|
|||
}
|
||||
|
||||
nsresult
|
||||
IndexedDatabaseManager::WaitForOpenAllowed(const nsACString& aOrigin,
|
||||
nsIAtom* aId,
|
||||
nsIRunnable* aRunnable)
|
||||
IndexedDatabaseManager::WaitForOpenAllowed(
|
||||
const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId,
|
||||
nsIRunnable* aRunnable)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
|
||||
NS_ASSERTION(!aOriginOrPattern.IsEmpty(), "Empty pattern!");
|
||||
NS_ASSERTION(aRunnable, "Null pointer!");
|
||||
|
||||
nsAutoPtr<SynchronizedOp> op(new SynchronizedOp(aOrigin, aId));
|
||||
nsAutoPtr<SynchronizedOp> op(new SynchronizedOp(aOriginOrPattern, aId));
|
||||
|
||||
// See if this runnable needs to wait.
|
||||
bool delayed = false;
|
||||
|
@ -501,16 +749,18 @@ IndexedDatabaseManager::WaitForOpenAllowed(const nsACString& aOrigin,
|
|||
}
|
||||
|
||||
void
|
||||
IndexedDatabaseManager::AllowNextSynchronizedOp(const nsACString& aOrigin,
|
||||
nsIAtom* aId)
|
||||
IndexedDatabaseManager::AllowNextSynchronizedOp(
|
||||
const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
|
||||
NS_ASSERTION(!aOriginOrPattern.IsEmpty(), "Empty origin/pattern!");
|
||||
|
||||
uint32_t count = mSynchronizedOps.Length();
|
||||
for (uint32_t index = 0; index < count; index++) {
|
||||
nsAutoPtr<SynchronizedOp>& op = mSynchronizedOps[index];
|
||||
if (op->mOrigin.Equals(aOrigin)) {
|
||||
if (op->mOriginOrPattern.IsOrigin() == aOriginOrPattern.IsOrigin() &&
|
||||
op->mOriginOrPattern == aOriginOrPattern) {
|
||||
if (op->mId == aId) {
|
||||
NS_ASSERTION(op->mDatabases.IsEmpty(), "How did this happen?");
|
||||
|
||||
|
@ -531,7 +781,7 @@ IndexedDatabaseManager::AllowNextSynchronizedOp(const nsACString& aOrigin,
|
|||
|
||||
nsresult
|
||||
IndexedDatabaseManager::AcquireExclusiveAccess(
|
||||
const nsACString& aOrigin,
|
||||
const nsACString& aPattern,
|
||||
IDBDatabase* aDatabase,
|
||||
AsyncConnectionHelper* aHelper,
|
||||
nsIRunnable* aRunnable,
|
||||
|
@ -544,26 +794,26 @@ IndexedDatabaseManager::AcquireExclusiveAccess(
|
|||
|
||||
// Find the right SynchronizedOp.
|
||||
SynchronizedOp* op =
|
||||
FindSynchronizedOp(aOrigin, aDatabase ? aDatabase->Id() : nullptr);
|
||||
FindSynchronizedOp(aPattern, aDatabase ? aDatabase->Id() : nullptr);
|
||||
|
||||
NS_ASSERTION(op, "We didn't find a SynchronizedOp?");
|
||||
NS_ASSERTION(!op->mHelper, "SynchronizedOp already has a helper?!?");
|
||||
NS_ASSERTION(!op->mRunnable, "SynchronizedOp already has a runnable?!?");
|
||||
|
||||
nsTArray<IDBDatabase*>* array;
|
||||
mLiveDatabases.Get(aOrigin, &array);
|
||||
DatabasePatternMatchArray matches;
|
||||
matches.Find(mLiveDatabases, aPattern);
|
||||
|
||||
// We need to wait for the databases to go away.
|
||||
// Hold on to all database objects that represent the same database file
|
||||
// (except the one that is requesting this version change).
|
||||
nsTArray<nsRefPtr<IDBDatabase> > liveDatabases;
|
||||
|
||||
if (array) {
|
||||
if (!matches.IsEmpty()) {
|
||||
if (aDatabase) {
|
||||
// Grab all databases that are not yet closed but whose database id match
|
||||
// the one we're looking for.
|
||||
for (uint32_t index = 0; index < array->Length(); index++) {
|
||||
IDBDatabase*& database = array->ElementAt(index);
|
||||
for (uint32_t index = 0; index < matches.Length(); index++) {
|
||||
IDBDatabase*& database = matches[index];
|
||||
if (!database->IsClosed() &&
|
||||
database != aDatabase &&
|
||||
database->Id() == aDatabase->Id()) {
|
||||
|
@ -574,7 +824,7 @@ IndexedDatabaseManager::AcquireExclusiveAccess(
|
|||
else {
|
||||
// We want *all* databases, even those that are closed, if we're going to
|
||||
// clear the origin.
|
||||
liveDatabases.AppendElements(*array);
|
||||
liveDatabases.AppendElements(matches);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -986,18 +1236,8 @@ IndexedDatabaseManager::GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow,
|
|||
nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
|
||||
NS_ENSURE_TRUE(principal, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (nsContentUtils::IsSystemPrincipal(principal)) {
|
||||
aASCIIOrigin.AssignLiteral("chrome");
|
||||
}
|
||||
else {
|
||||
nsresult rv = principal->GetExtendedOrigin(aASCIIOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (aASCIIOrigin.EqualsLiteral("null")) {
|
||||
NS_WARNING("IndexedDB databases not allowed for this principal!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
nsresult rv = GetASCIIOriginFromPrincipal(principal, aASCIIOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1053,17 +1293,12 @@ IndexedDatabaseManager::AddFileManager(const nsACString& aOrigin,
|
|||
}
|
||||
|
||||
void
|
||||
IndexedDatabaseManager::InvalidateFileManagersForOrigin(
|
||||
const nsACString& aOrigin)
|
||||
IndexedDatabaseManager::InvalidateFileManagersForPattern(
|
||||
const nsACString& aPattern)
|
||||
{
|
||||
nsTArray<nsRefPtr<FileManager> >* array;
|
||||
if (mFileManagers.Get(aOrigin, &array)) {
|
||||
for (uint32_t i = 0; i < array->Length(); i++) {
|
||||
nsRefPtr<FileManager> fileManager = array->ElementAt(i);
|
||||
fileManager->Invalidate();
|
||||
}
|
||||
mFileManagers.Remove(aOrigin);
|
||||
}
|
||||
NS_ASSERTION(!aPattern.IsEmpty(), "Empty pattern!");
|
||||
mFileManagers.Enumerate(InvalidateAndRemoveFileManagers,
|
||||
const_cast<nsACString*>(&aPattern));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1173,39 +1408,103 @@ IndexedDatabaseManager::RunSynchronizedOp(IDBDatabase* aDatabase,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
IndexedDatabaseManager::SynchronizedOp*
|
||||
IndexedDatabaseManager::FindSynchronizedOp(const nsACString& aPattern,
|
||||
nsIAtom* aId)
|
||||
{
|
||||
for (uint32_t index = 0; index < mSynchronizedOps.Length(); index++) {
|
||||
const nsAutoPtr<SynchronizedOp>& currentOp = mSynchronizedOps[index];
|
||||
if (PatternMatchesOrigin(aPattern, currentOp->mOriginOrPattern) &&
|
||||
(!currentOp->mId || currentOp->mId == aId)) {
|
||||
return currentOp;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
IndexedDatabaseManager::ClearDatabasesForApp(uint32_t aAppId, bool aBrowserOnly)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
"Bad appId!");
|
||||
|
||||
// This only works from the main process.
|
||||
NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsAutoCString pattern;
|
||||
GetOriginPatternStringMaybeIgnoreBrowser(aAppId, aBrowserOnly, pattern);
|
||||
|
||||
// If there is a pending or running clear operation for this app, return
|
||||
// immediately.
|
||||
if (IsClearOriginPending(pattern)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
OriginOrPatternString oops = OriginOrPatternString::FromPattern(pattern);
|
||||
|
||||
// Queue up the origin clear runnable.
|
||||
nsRefPtr<OriginClearRunnable> runnable = new OriginClearRunnable(oops);
|
||||
|
||||
nsresult rv = WaitForOpenAllowed(oops, nullptr, runnable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable->AdvanceState();
|
||||
|
||||
// Give the runnable some help by invalidating any databases in the way.
|
||||
DatabasePatternMatchArray matches;
|
||||
matches.Find(mLiveDatabases, pattern);
|
||||
|
||||
for (uint32_t index = 0; index < matches.Length(); index++) {
|
||||
// We need to grab references here to prevent the database from dying while
|
||||
// we invalidate it.
|
||||
nsRefPtr<IDBDatabase> database = matches[index];
|
||||
database->Invalidate();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(IndexedDatabaseManager, nsIIndexedDatabaseManager,
|
||||
nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
IndexedDatabaseManager::GetUsageForURI(
|
||||
nsIURI* aURI,
|
||||
nsIIndexedDatabaseUsageCallback* aCallback)
|
||||
nsIIndexedDatabaseUsageCallback* aCallback,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowserOnly,
|
||||
uint8_t aOptionalArgCount)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
// This only works from the main process.
|
||||
NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
if (!aOptionalArgCount) {
|
||||
aAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
// Figure out which origin we're dealing with.
|
||||
nsCString origin;
|
||||
nsresult rv = nsContentUtils::GetASCIIOrigin(aURI, origin);
|
||||
nsresult rv = GetASCIIOriginFromURI(aURI, aAppId, aInMozBrowserOnly, origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
OriginOrPatternString oops = OriginOrPatternString::FromOrigin(origin);
|
||||
|
||||
nsRefPtr<AsyncUsageRunnable> runnable =
|
||||
new AsyncUsageRunnable(aURI, origin, aCallback);
|
||||
new AsyncUsageRunnable(aAppId, aInMozBrowserOnly, oops, aURI, aCallback);
|
||||
|
||||
nsRefPtr<AsyncUsageRunnable>* newRunnable =
|
||||
mUsageRunnables.AppendElement(runnable);
|
||||
NS_ENSURE_TRUE(newRunnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Non-standard URIs can't create databases anyway so fire the callback
|
||||
// immediately.
|
||||
if (origin.EqualsLiteral("null")) {
|
||||
return runnable->TakeShortcut();
|
||||
}
|
||||
|
||||
// Otherwise put the computation runnable in the queue.
|
||||
rv = WaitForOpenAllowed(origin, nullptr, runnable);
|
||||
rv = WaitForOpenAllowed(oops, nullptr, runnable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable->AdvanceState();
|
||||
|
@ -1216,77 +1515,95 @@ IndexedDatabaseManager::GetUsageForURI(
|
|||
NS_IMETHODIMP
|
||||
IndexedDatabaseManager::CancelGetUsageForURI(
|
||||
nsIURI* aURI,
|
||||
nsIIndexedDatabaseUsageCallback* aCallback)
|
||||
nsIIndexedDatabaseUsageCallback* aCallback,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowserOnly,
|
||||
uint8_t aOptionalArgCount)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
// This only works from the main process.
|
||||
NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
if (!aOptionalArgCount) {
|
||||
aAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
// See if one of our pending callbacks matches both the URI and the callback
|
||||
// given. Cancel an remove it if so.
|
||||
for (uint32_t index = 0; index < mUsageRunnables.Length(); index++) {
|
||||
nsRefPtr<AsyncUsageRunnable>& runnable = mUsageRunnables[index];
|
||||
|
||||
bool equals;
|
||||
nsresult rv = runnable->mURI->Equals(aURI, &equals);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (runnable->mAppId == aAppId &&
|
||||
runnable->mInMozBrowserOnly == aInMozBrowserOnly) {
|
||||
bool equals;
|
||||
nsresult rv = runnable->mURI->Equals(aURI, &equals);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (equals && SameCOMIdentity(aCallback, runnable->mCallback)) {
|
||||
runnable->Cancel();
|
||||
break;
|
||||
if (equals && SameCOMIdentity(aCallback, runnable->mCallback)) {
|
||||
runnable->Cancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IndexedDatabaseManager::ClearDatabasesForURI(nsIURI* aURI)
|
||||
IndexedDatabaseManager::ClearDatabasesForURI(nsIURI* aURI,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowserOnly,
|
||||
uint8_t aOptionalArgCount)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
|
||||
// This only works from the main process.
|
||||
NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
if (!aOptionalArgCount) {
|
||||
aAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
// Figure out which origin we're dealing with.
|
||||
nsCString origin;
|
||||
nsresult rv = nsContentUtils::GetASCIIOrigin(aURI, origin);
|
||||
nsresult rv = GetASCIIOriginFromURI(aURI, aAppId, aInMozBrowserOnly, origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Non-standard URIs can't create databases anyway, so return immediately.
|
||||
if (origin.EqualsLiteral("null")) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsAutoCString pattern;
|
||||
GetOriginPatternString(aAppId, aInMozBrowserOnly, origin, pattern);
|
||||
|
||||
// If there is a pending or running clear operation for this origin, return
|
||||
// immediately.
|
||||
if (IsClearOriginPending(origin)) {
|
||||
if (IsClearOriginPending(pattern)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Queue up the origin clear runnable.
|
||||
nsRefPtr<OriginClearRunnable> runnable = new OriginClearRunnable(origin);
|
||||
OriginOrPatternString oops = OriginOrPatternString::FromPattern(pattern);
|
||||
|
||||
rv = WaitForOpenAllowed(origin, nullptr, runnable);
|
||||
// Queue up the origin clear runnable.
|
||||
nsRefPtr<OriginClearRunnable> runnable = new OriginClearRunnable(oops);
|
||||
|
||||
rv = WaitForOpenAllowed(oops, nullptr, runnable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable->AdvanceState();
|
||||
|
||||
// Give the runnable some help by invalidating any databases in the way. We
|
||||
// need to grab references to any live databases here to prevent them from
|
||||
// dying while we invalidate them.
|
||||
nsTArray<nsRefPtr<IDBDatabase> > liveDatabases;
|
||||
// Give the runnable some help by invalidating any databases in the way.
|
||||
DatabasePatternMatchArray matches;
|
||||
matches.Find(mLiveDatabases, pattern);
|
||||
|
||||
nsTArray<IDBDatabase*>* array;
|
||||
if (mLiveDatabases.Get(origin, &array)) {
|
||||
liveDatabases.AppendElements(*array);
|
||||
for (uint32_t index = 0; index < matches.Length(); index++) {
|
||||
// We need to grab references to any live databases here to prevent them
|
||||
// from dying while we invalidate them.
|
||||
nsRefPtr<IDBDatabase> database = matches[index];
|
||||
database->Invalidate();
|
||||
}
|
||||
|
||||
for (uint32_t index = 0; index < liveDatabases.Length(); index++) {
|
||||
liveDatabases[index]->Invalidate();
|
||||
}
|
||||
|
||||
DatabaseInfo::RemoveAllForOrigin(origin);
|
||||
|
||||
// After everything has been invalidated the helper should be dispatched to
|
||||
// the end of the event queue.
|
||||
return NS_OK;
|
||||
|
@ -1361,7 +1678,7 @@ IndexedDatabaseManager::Observe(nsISupports* aSubject,
|
|||
}
|
||||
}
|
||||
|
||||
mFileManagers.EnumerateRead(InvalidateAllFileManagers, nullptr);
|
||||
mFileManagers.Enumerate(InvalidateAndRemoveFileManagers, nullptr);
|
||||
|
||||
if (PR_ATOMIC_SET(&gClosed, 1)) {
|
||||
NS_ERROR("Close more than once?!");
|
||||
|
@ -1392,6 +1709,25 @@ IndexedDatabaseManager::Observe(nsISupports* aSubject,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, TOPIC_WEB_APP_CLEAR_DATA)) {
|
||||
nsCOMPtr<mozIApplicationClearPrivateDataParams> params =
|
||||
do_QueryInterface(aSubject);
|
||||
NS_ENSURE_TRUE(params, NS_ERROR_UNEXPECTED);
|
||||
|
||||
uint32_t appId;
|
||||
nsresult rv = params->GetAppId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool browserOnly;
|
||||
rv = params->GetBrowserOnly(&browserOnly);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = ClearDatabasesForApp(appId, browserOnly);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_NOTREACHED("Unknown topic!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
@ -1408,16 +1744,75 @@ OriginClearRunnable::InvalidateOpenedDatabases(
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
OriginClearRunnable* self = static_cast<OriginClearRunnable*>(aClosure);
|
||||
|
||||
nsTArray<nsRefPtr<IDBDatabase> > databases;
|
||||
databases.SwapElements(aDatabases);
|
||||
|
||||
for (uint32_t index = 0; index < databases.Length(); index++) {
|
||||
databases[index]->Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseInfo::RemoveAllForOrigin(self->mOrigin);
|
||||
void
|
||||
IndexedDatabaseManager::
|
||||
OriginClearRunnable::DeleteFiles(IndexedDatabaseManager* aManager)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aManager, "Don't pass me null!");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIFile> directory =
|
||||
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
rv = directory->InitWithPath(aManager->GetBaseDirectory());
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||
rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
if (!entries) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString originSanitized(mOriginOrPattern);
|
||||
SanitizeOriginString(originSanitized);
|
||||
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
|
||||
nsCOMPtr<nsISupports> entry;
|
||||
rv = entries->GetNext(getter_AddRefs(entry));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
|
||||
NS_ASSERTION(file, "Don't know what this is!");
|
||||
|
||||
bool isDirectory;
|
||||
rv = file->IsDirectory(&isDirectory);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
if (!isDirectory) {
|
||||
NS_WARNING("Something in the IndexedDB directory that doesn't belong!");
|
||||
continue;
|
||||
}
|
||||
|
||||
nsString leafName;
|
||||
rv = file->GetLeafName(leafName);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
// Skip databases for other apps.
|
||||
if (!PatternMatchesOrigin(originSanitized,
|
||||
NS_ConvertUTF16toUTF8(leafName))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NS_FAILED(file->Remove(true))) {
|
||||
// This should never fail if we've closed all database connections
|
||||
// correctly...
|
||||
NS_ERROR("Failed to remove directory!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1439,9 +1834,9 @@ IndexedDatabaseManager::OriginClearRunnable::Run()
|
|||
|
||||
// Now we have to wait until the thread pool is done with all of the
|
||||
// databases we care about.
|
||||
nsresult rv =
|
||||
mgr->AcquireExclusiveAccess(mOrigin, this, InvalidateOpenedDatabases,
|
||||
this);
|
||||
nsresult rv = mgr->AcquireExclusiveAccess(mOriginOrPattern, this,
|
||||
InvalidateOpenedDatabases,
|
||||
nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1452,24 +1847,7 @@ IndexedDatabaseManager::OriginClearRunnable::Run()
|
|||
|
||||
AdvanceState();
|
||||
|
||||
// Remove the directory that contains all our databases.
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
nsresult rv =
|
||||
mgr->GetDirectoryForOrigin(mOrigin, getter_AddRefs(directory));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to get directory to remove!");
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
bool exists;
|
||||
rv = directory->Exists(&exists);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
|
||||
"Failed to check that the directory exists!");
|
||||
|
||||
if (NS_SUCCEEDED(rv) && exists && NS_FAILED(directory->Remove(true))) {
|
||||
// This should never fail if we've closed all database connections
|
||||
// correctly...
|
||||
NS_ERROR("Failed to remove directory!");
|
||||
}
|
||||
}
|
||||
DeleteFiles(mgr);
|
||||
|
||||
// Now dispatch back to the main thread.
|
||||
if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
|
||||
|
@ -1483,10 +1861,10 @@ IndexedDatabaseManager::OriginClearRunnable::Run()
|
|||
case Complete: {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
mgr->InvalidateFileManagersForOrigin(mOrigin);
|
||||
mgr->InvalidateFileManagersForPattern(mOriginOrPattern);
|
||||
|
||||
// Tell the IndexedDatabaseManager that we're done.
|
||||
mgr->AllowNextSynchronizedOp(mOrigin, nullptr);
|
||||
mgr->AllowNextSynchronizedOp(mOriginOrPattern, nullptr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1501,19 +1879,24 @@ IndexedDatabaseManager::OriginClearRunnable::Run()
|
|||
}
|
||||
|
||||
IndexedDatabaseManager::AsyncUsageRunnable::AsyncUsageRunnable(
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowserOnly,
|
||||
const OriginOrPatternString& aOrigin,
|
||||
nsIURI* aURI,
|
||||
const nsACString& aOrigin,
|
||||
nsIIndexedDatabaseUsageCallback* aCallback)
|
||||
: mURI(aURI),
|
||||
mOrigin(aOrigin),
|
||||
mCallback(aCallback),
|
||||
mUsage(0),
|
||||
mFileUsage(0),
|
||||
mAppId(aAppId),
|
||||
mCanceled(0),
|
||||
mCallbackState(Pending)
|
||||
mOrigin(aOrigin),
|
||||
mCallbackState(Pending),
|
||||
mInMozBrowserOnly(aInMozBrowserOnly)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aURI, "Null pointer!");
|
||||
NS_ASSERTION(aOrigin.IsOrigin(), "Expect origin only here!");
|
||||
NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
|
||||
NS_ASSERTION(aCallback, "Null pointer!");
|
||||
}
|
||||
|
@ -1612,7 +1995,8 @@ IndexedDatabaseManager::AsyncUsageRunnable::RunInternal()
|
|||
if (!mCanceled) {
|
||||
uint64_t usage = mUsage;
|
||||
IncrementUsage(&usage, mFileUsage);
|
||||
mCallback->OnUsageResult(mURI, usage, mFileUsage);
|
||||
mCallback->OnUsageResult(mURI, usage, mFileUsage, mAppId,
|
||||
mInMozBrowserOnly);
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
|
@ -1779,9 +2163,9 @@ IndexedDatabaseManager::WaitForLockedFilesToFinishRunnable::Run()
|
|||
}
|
||||
|
||||
IndexedDatabaseManager::
|
||||
SynchronizedOp::SynchronizedOp(const nsACString& aOrigin,
|
||||
SynchronizedOp::SynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId)
|
||||
: mOrigin(aOrigin), mId(aId)
|
||||
: mOriginOrPattern(aOriginOrPattern), mId(aId)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
MOZ_COUNT_CTOR(IndexedDatabaseManager::SynchronizedOp);
|
||||
|
@ -1794,24 +2178,42 @@ IndexedDatabaseManager::SynchronizedOp::~SynchronizedOp()
|
|||
}
|
||||
|
||||
bool
|
||||
IndexedDatabaseManager::SynchronizedOp::MustWaitFor(const SynchronizedOp& aRhs)
|
||||
const
|
||||
IndexedDatabaseManager::
|
||||
SynchronizedOp::MustWaitFor(const SynchronizedOp& aExistingOp)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
bool match;
|
||||
|
||||
if (aExistingOp.mOriginOrPattern.IsOrigin()) {
|
||||
if (mOriginOrPattern.IsOrigin()) {
|
||||
match = aExistingOp.mOriginOrPattern.Equals(mOriginOrPattern);
|
||||
}
|
||||
else {
|
||||
match = PatternMatchesOrigin(mOriginOrPattern, aExistingOp.mOriginOrPattern);
|
||||
}
|
||||
}
|
||||
else if (mOriginOrPattern.IsOrigin()) {
|
||||
match = PatternMatchesOrigin(aExistingOp.mOriginOrPattern, mOriginOrPattern);
|
||||
}
|
||||
else {
|
||||
match = PatternMatchesOrigin(mOriginOrPattern, aExistingOp.mOriginOrPattern) ||
|
||||
PatternMatchesOrigin(aExistingOp.mOriginOrPattern, mOriginOrPattern);
|
||||
}
|
||||
|
||||
// If the origins don't match, the second can proceed.
|
||||
if (!aRhs.mOrigin.Equals(mOrigin)) {
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the origins and the ids match, the second must wait.
|
||||
if (aRhs.mId == mId) {
|
||||
if (aExistingOp.mId == mId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Waiting is required if either one corresponds to an origin clearing
|
||||
// (a null Id).
|
||||
if (!aRhs.mId || !mId) {
|
||||
if (!aExistingOp.mId || !mId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,11 +57,11 @@ public:
|
|||
|
||||
// Waits for databases to be cleared and for version change transactions to
|
||||
// complete before dispatching the given runnable.
|
||||
nsresult WaitForOpenAllowed(const nsACString& aOrigin,
|
||||
nsresult WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId,
|
||||
nsIRunnable* aRunnable);
|
||||
|
||||
void AllowNextSynchronizedOp(const nsACString& aOrigin,
|
||||
void AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId);
|
||||
|
||||
nsIThread* IOThread()
|
||||
|
@ -169,7 +169,7 @@ public:
|
|||
const nsAString& aDatabaseName,
|
||||
FileManager* aFileManager);
|
||||
|
||||
void InvalidateFileManagersForOrigin(const nsACString& aOrigin);
|
||||
void InvalidateFileManagersForPattern(const nsACString& aPattern);
|
||||
|
||||
void InvalidateFileManager(const nsACString& aOrigin,
|
||||
const nsAString& aDatabaseName);
|
||||
|
@ -200,7 +200,18 @@ public:
|
|||
const nsAString& aName);
|
||||
|
||||
static nsresult
|
||||
FireWindowOnError(nsPIDOMWindow* aOwner, nsEventChainPostVisitor& aVisitor);
|
||||
FireWindowOnError(nsPIDOMWindow* aOwner,
|
||||
nsEventChainPostVisitor& aVisitor);
|
||||
|
||||
static bool
|
||||
OriginMatchesApp(const nsACString& aOrigin,
|
||||
uint32_t aAppId);
|
||||
|
||||
static bool
|
||||
OriginMatchesApp(const nsACString& aOrigin,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowser);
|
||||
|
||||
private:
|
||||
IndexedDatabaseManager();
|
||||
~IndexedDatabaseManager();
|
||||
|
@ -225,6 +236,8 @@ private:
|
|||
// Called when a database has been closed.
|
||||
void OnDatabaseClosed(IDBDatabase* aDatabase);
|
||||
|
||||
nsresult ClearDatabasesForApp(uint32_t aAppId, bool aBrowserOnly);
|
||||
|
||||
// Responsible for clearing the database files for a particular origin on the
|
||||
// IO thread. Created when nsIIDBIndexedDatabaseManager::ClearDatabasesForURI
|
||||
// is called. Runs three times, first on the main thread, next on the IO
|
||||
|
@ -253,8 +266,8 @@ private:
|
|||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
OriginClearRunnable(const nsACString& aOrigin)
|
||||
: mOrigin(aOrigin),
|
||||
OriginClearRunnable(const OriginOrPatternString& aOriginOrPattern)
|
||||
: mOriginOrPattern(aOriginOrPattern),
|
||||
mCallbackState(Pending)
|
||||
{ }
|
||||
|
||||
|
@ -279,8 +292,10 @@ private:
|
|||
nsTArray<nsRefPtr<IDBDatabase> >& aDatabases,
|
||||
void* aClosure);
|
||||
|
||||
void DeleteFiles(IndexedDatabaseManager* aManager);
|
||||
|
||||
private:
|
||||
nsCString mOrigin;
|
||||
OriginOrPatternString mOriginOrPattern;
|
||||
CallbackState mCallbackState;
|
||||
};
|
||||
|
||||
|
@ -311,12 +326,15 @@ private:
|
|||
// Running on the main thread after skipping the work
|
||||
Shortcut
|
||||
};
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
AsyncUsageRunnable(nsIURI* aURI,
|
||||
const nsACString& aOrigin,
|
||||
AsyncUsageRunnable(uint32_t aAppId,
|
||||
bool aInMozBrowserOnly,
|
||||
const OriginOrPatternString& aOrigin,
|
||||
nsIURI* aURI,
|
||||
nsIIndexedDatabaseUsageCallback* aCallback);
|
||||
|
||||
// Sets the canceled flag so that the callback is never called.
|
||||
|
@ -349,13 +367,14 @@ private:
|
|||
uint64_t* aUsage);
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCString mOrigin;
|
||||
|
||||
nsCOMPtr<nsIIndexedDatabaseUsageCallback> mCallback;
|
||||
uint64_t mUsage;
|
||||
uint64_t mFileUsage;
|
||||
uint32_t mAppId;
|
||||
int32_t mCanceled;
|
||||
OriginOrPatternString mOrigin;
|
||||
CallbackState mCallbackState;
|
||||
bool mInMozBrowserOnly;
|
||||
};
|
||||
|
||||
// Called when AsyncUsageRunnable has finished its Run() method.
|
||||
|
@ -366,16 +385,17 @@ private:
|
|||
// clearing dbs for an origin, etc).
|
||||
struct SynchronizedOp
|
||||
{
|
||||
SynchronizedOp(const nsACString& aOrigin, nsIAtom* aId);
|
||||
SynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId);
|
||||
~SynchronizedOp();
|
||||
|
||||
// Test whether the second SynchronizedOp needs to get behind this one.
|
||||
bool MustWaitFor(const SynchronizedOp& aRhs) const;
|
||||
// Test whether this SynchronizedOp needs to wait for the given op.
|
||||
bool MustWaitFor(const SynchronizedOp& aOp);
|
||||
|
||||
void DelayRunnable(nsIRunnable* aRunnable);
|
||||
void DispatchDelayedRunnables();
|
||||
|
||||
const nsCString mOrigin;
|
||||
const OriginOrPatternString mOriginOrPattern;
|
||||
nsCOMPtr<nsIAtom> mId;
|
||||
nsRefPtr<AsyncConnectionHelper> mHelper;
|
||||
nsCOMPtr<nsIRunnable> mRunnable;
|
||||
|
@ -442,22 +462,12 @@ private:
|
|||
static nsresult RunSynchronizedOp(IDBDatabase* aDatabase,
|
||||
SynchronizedOp* aOp);
|
||||
|
||||
SynchronizedOp* FindSynchronizedOp(const nsACString& aOrigin,
|
||||
nsIAtom* aId)
|
||||
{
|
||||
for (uint32_t index = 0; index < mSynchronizedOps.Length(); index++) {
|
||||
const nsAutoPtr<SynchronizedOp>& currentOp = mSynchronizedOps[index];
|
||||
if (currentOp->mOrigin == aOrigin &&
|
||||
(!currentOp->mId || currentOp->mId == aId)) {
|
||||
return currentOp;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
SynchronizedOp* FindSynchronizedOp(const nsACString& aPattern,
|
||||
nsIAtom* aId);
|
||||
|
||||
bool IsClearOriginPending(const nsACString& aOrigin)
|
||||
bool IsClearOriginPending(const nsACString& aPattern)
|
||||
{
|
||||
return !!FindSynchronizedOp(aOrigin, nullptr);
|
||||
return !!FindSynchronizedOp(aPattern, nullptr);
|
||||
}
|
||||
|
||||
// Maintains a list of live databases per origin.
|
||||
|
|
|
@ -66,12 +66,13 @@ EXPORTS_mozilla/dom/indexedDB = \
|
|||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(topsrcdir)/db/sqlite3/src \
|
||||
-I$(topsrcdir)/xpcom/build \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
-I$(topsrcdir)/dom/src/storage \
|
||||
-I$(topsrcdir)/caps/include \
|
||||
-I$(topsrcdir)/content/base/src \
|
||||
-I$(topsrcdir)/content/events/src \
|
||||
-I$(topsrcdir)/db/sqlite3/src \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
-I$(topsrcdir)/dom/src/storage \
|
||||
-I$(topsrcdir)/xpcom/build \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
||||
|
|
|
@ -2018,7 +2018,9 @@ OpenDatabaseHelper::Run()
|
|||
IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(manager, "This should never be null!");
|
||||
|
||||
manager->AllowNextSynchronizedOp(mASCIIOrigin, mDatabaseId);
|
||||
manager->AllowNextSynchronizedOp(
|
||||
OriginOrPatternString::FromOrigin(mASCIIOrigin),
|
||||
mDatabaseId);
|
||||
|
||||
ReleaseMainThreadObjects();
|
||||
|
||||
|
|
|
@ -434,6 +434,15 @@ IndexedDBDatabaseChild::RecvVersionChange(const uint64_t& aOldVersion,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IndexedDBDatabaseChild::RecvInvalidate()
|
||||
{
|
||||
if (mDatabase) {
|
||||
mDatabase->Invalidate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IndexedDBDatabaseChild::RecvPIndexedDBTransactionConstructor(
|
||||
PIndexedDBTransactionChild* aActor,
|
||||
|
@ -584,9 +593,30 @@ IndexedDBTransactionChild::ActorDestroy(ActorDestroyReason aWhy)
|
|||
}
|
||||
|
||||
bool
|
||||
IndexedDBTransactionChild::RecvComplete(const nsresult& aRv)
|
||||
IndexedDBTransactionChild::RecvComplete(const CompleteParams& aParams)
|
||||
{
|
||||
FireCompleteEvent(aRv);
|
||||
MOZ_ASSERT(mTransaction);
|
||||
MOZ_ASSERT(mStrongTransaction);
|
||||
|
||||
nsresult resultCode;
|
||||
|
||||
switch (aParams.type()) {
|
||||
case CompleteParams::TCompleteResult:
|
||||
resultCode = NS_OK;
|
||||
break;
|
||||
case CompleteParams::TAbortResult:
|
||||
resultCode = aParams.get_AbortResult().errorCode();
|
||||
if (NS_SUCCEEDED(resultCode)) {
|
||||
resultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_NOT_REACHED("Unknown union type!");
|
||||
return false;
|
||||
}
|
||||
|
||||
FireCompleteEvent(resultCode);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,9 @@ protected:
|
|||
RecvVersionChange(const uint64_t& aOldVersion, const uint64_t& aNewVersion)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvInvalidate() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvPIndexedDBTransactionConstructor(PIndexedDBTransactionChild* aActor,
|
||||
const TransactionParams& aParams)
|
||||
|
@ -163,7 +166,7 @@ protected:
|
|||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvComplete(const nsresult& aRv) MOZ_OVERRIDE;
|
||||
RecvComplete(const CompleteParams& aParams) MOZ_OVERRIDE;
|
||||
|
||||
virtual PIndexedDBObjectStoreChild*
|
||||
AllocPIndexedDBObjectStore(const ObjectStoreConstructorParams& aParams)
|
||||
|
|
|
@ -355,7 +355,11 @@ IndexedDBDatabaseParent::HandleRequestEvent(nsIDOMEvent* aEvent,
|
|||
}
|
||||
|
||||
MOZ_ASSERT(!mDatabase || mDatabase == databaseConcrete);
|
||||
mDatabase = databaseConcrete;
|
||||
|
||||
if (!mDatabase) {
|
||||
databaseConcrete->SetActor(this);
|
||||
mDatabase = databaseConcrete;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -390,6 +394,7 @@ IndexedDBDatabaseParent::HandleRequestEvent(nsIDOMEvent* aEvent,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
databaseConcrete->SetActor(this);
|
||||
mDatabase = databaseConcrete;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -555,10 +560,10 @@ IndexedDBTransactionParent::HandleEvent(nsIDOMEvent* aEvent)
|
|||
nsresult rv = aEvent->GetType(type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsresult transactionResult;
|
||||
CompleteParams params;
|
||||
|
||||
if (type.EqualsLiteral(COMPLETE_EVT_STR)) {
|
||||
transactionResult = NS_OK;
|
||||
params = CompleteResult();
|
||||
}
|
||||
else if (type.EqualsLiteral(ABORT_EVT_STR)) {
|
||||
#ifdef DEBUG
|
||||
|
@ -573,15 +578,14 @@ IndexedDBTransactionParent::HandleEvent(nsIDOMEvent* aEvent)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
MOZ_ASSERT(NS_FAILED(mTransaction->GetAbortCode()));
|
||||
transactionResult = mTransaction->GetAbortCode();
|
||||
params = AbortResult(mTransaction->GetAbortCode());
|
||||
}
|
||||
else {
|
||||
NS_WARNING("Unknown message type!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!SendComplete(transactionResult)) {
|
||||
if (!SendComplete(params)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ child:
|
|||
|
||||
VersionChange(uint64_t oldVersion, uint64_t newVersion);
|
||||
|
||||
Invalidate();
|
||||
|
||||
both:
|
||||
PIndexedDBTransaction(TransactionParams params);
|
||||
};
|
||||
|
|
|
@ -31,6 +31,20 @@ union ObjectStoreConstructorParams
|
|||
GetObjectStoreParams;
|
||||
};
|
||||
|
||||
struct CompleteResult
|
||||
{ };
|
||||
|
||||
struct AbortResult
|
||||
{
|
||||
nsresult errorCode;
|
||||
};
|
||||
|
||||
union CompleteParams
|
||||
{
|
||||
CompleteResult;
|
||||
AbortResult;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
protocol PIndexedDBTransaction
|
||||
|
@ -51,7 +65,7 @@ parent:
|
|||
DeleteObjectStore(nsString name);
|
||||
|
||||
child:
|
||||
Complete(nsresult rv);
|
||||
Complete(CompleteParams params);
|
||||
};
|
||||
|
||||
} // namespace indexedDB
|
||||
|
|
|
@ -8,18 +8,17 @@
|
|||
|
||||
interface nsIURI;
|
||||
|
||||
[scriptable, function, uuid(ef1795ec-7050-4658-b80f-0e48cbe1d64b)]
|
||||
[scriptable, function, uuid(38f15cc7-2df0-4a90-8b7f-1606b2243522)]
|
||||
interface nsIIndexedDatabaseUsageCallback : nsISupports
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void onUsageResult(in nsIURI aURI,
|
||||
in unsigned long long aUsage,
|
||||
in unsigned long long aFileUsage);
|
||||
in unsigned long long aFileUsage,
|
||||
in unsigned long aAppId,
|
||||
in boolean aInMozBrowserOnly);
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(02256aa7-70d8-473f-bf3b-8cb35d28fd75)]
|
||||
[scriptable, builtinclass, uuid(e5168115-baff-4559-887e-7c0405cc9e63)]
|
||||
interface nsIIndexedDatabaseManager : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -31,8 +30,11 @@ interface nsIIndexedDatabaseManager : nsISupports
|
|||
* @param aCallback
|
||||
* The callback that will be called when the usage is available.
|
||||
*/
|
||||
[optional_argc]
|
||||
void getUsageForURI(in nsIURI aURI,
|
||||
in nsIIndexedDatabaseUsageCallback aCallback);
|
||||
in nsIIndexedDatabaseUsageCallback aCallback,
|
||||
[optional] in unsigned long aAppId,
|
||||
[optional] in boolean aInMozBrowserOnly);
|
||||
|
||||
/**
|
||||
* Cancels an asynchronous usage check initiated by a previous call to
|
||||
|
@ -43,9 +45,11 @@ interface nsIIndexedDatabaseManager : nsISupports
|
|||
* @param aCallback
|
||||
* The callback that will be called when the usage is available.
|
||||
*/
|
||||
[optional_argc]
|
||||
void cancelGetUsageForURI(in nsIURI aURI,
|
||||
in nsIIndexedDatabaseUsageCallback aCallback);
|
||||
|
||||
in nsIIndexedDatabaseUsageCallback aCallback,
|
||||
[optional] in unsigned long aAppId,
|
||||
[optional] in boolean aInMozBrowserOnly);
|
||||
|
||||
/**
|
||||
* Removes all databases stored for the given URI. The files may not be
|
||||
|
@ -54,7 +58,10 @@ interface nsIIndexedDatabaseManager : nsISupports
|
|||
* @param aURI
|
||||
* The URI whose databases are to be cleared.
|
||||
*/
|
||||
void clearDatabasesForURI(in nsIURI aURI);
|
||||
[optional_argc]
|
||||
void clearDatabasesForURI(in nsIURI aURI,
|
||||
[optional] in unsigned long aAppId,
|
||||
[optional] in boolean aInMozBrowserOnly);
|
||||
|
||||
/**
|
||||
* Defines indexedDB and IDBKeyrange with its static functions on
|
||||
|
|
|
@ -21,6 +21,8 @@ MOCHITEST_FILES = \
|
|||
event_propagation_iframe.html \
|
||||
exceptions_in_events_iframe.html \
|
||||
file.js \
|
||||
file_app_isolation.html \
|
||||
file_app_isolation.js \
|
||||
helpers.js \
|
||||
leaving_page_iframe.html \
|
||||
test_add_put.html \
|
||||
|
@ -100,12 +102,13 @@ MOCHITEST_FILES = \
|
|||
test_setVersion_events.html \
|
||||
test_setVersion_exclusion.html \
|
||||
test_unique_index_update.html \
|
||||
test_webapp_clearBrowserData.html \
|
||||
third_party_iframe1.html \
|
||||
third_party_iframe2.html \
|
||||
test_app_isolation_inproc.html \
|
||||
test_app_isolation_oop.html \
|
||||
file_app_isolation.html \
|
||||
file_app_isolation.js \
|
||||
webapp_clearBrowserData_appFrame.html \
|
||||
webapp_clearBrowserData_browserFrame.html \
|
||||
$(NULL)
|
||||
|
||||
# test_writer_starvation.html disabled for infinite loops, bug 595368
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Clear Browser Data 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">
|
||||
"use strict";
|
||||
|
||||
const appDomain = "example.org";
|
||||
const manifestURL =
|
||||
location.protocol + "//" + appDomain + "/manifest.webapp";
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const objectStoreName = "foo";
|
||||
const testKey = 1;
|
||||
const testValue = objectStoreName;
|
||||
|
||||
let request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
db.onversionchange = function(event) {
|
||||
event.target.close();
|
||||
}
|
||||
|
||||
let objectStore = db.createObjectStore(objectStoreName);
|
||||
objectStore.add(testValue, testKey);
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
let srcURL =
|
||||
location.protocol + "//" + appDomain +
|
||||
location.pathname.replace("test_webapp_clearBrowserData.html",
|
||||
"webapp_clearBrowserData_appFrame.html");
|
||||
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("mozbrowser", "");
|
||||
iframe.setAttribute("mozapp", manifestURL);
|
||||
iframe.setAttribute("src", srcURL);
|
||||
iframe.setAttribute("remote", "true");
|
||||
iframe.addEventListener("mozbrowsershowmodalprompt", function(event) {
|
||||
let message = JSON.parse(event.detail.message);
|
||||
switch (message.type) {
|
||||
case "info":
|
||||
case "ok":
|
||||
window[message.type].apply(window, message.args);
|
||||
break;
|
||||
case "done":
|
||||
continueToNextStepSync();
|
||||
break;
|
||||
default:
|
||||
throw "unknown message";
|
||||
}
|
||||
});
|
||||
|
||||
info("loading app frame");
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
yield;
|
||||
|
||||
request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = unexpectedSuccessHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
objectStore =
|
||||
db.transaction(objectStoreName).objectStore(objectStoreName);
|
||||
objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(testValue == event.target.result, "data still exists");
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
||||
|
||||
function start()
|
||||
{
|
||||
if (!SpecialPowers.isMainProcess()) {
|
||||
todo(false, "Test disabled in child processes, for now");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
SpecialPowers.addPermission("browser", true, document);
|
||||
SpecialPowers.addPermission("browser", true, { manifestURL: manifestURL,
|
||||
isInBrowserElement: false });
|
||||
SpecialPowers.addPermission("embed-apps", true, document);
|
||||
|
||||
let Webapps = {};
|
||||
SpecialPowers.wrap(Components)
|
||||
.utils.import("resource://gre/modules/Webapps.jsm", Webapps);
|
||||
let appRegistry = SpecialPowers.wrap(Webapps.DOMApplicationRegistry);
|
||||
|
||||
let originalAllAppsLaunchable = appRegistry.allAppsLaunchable;
|
||||
appRegistry.allAppsLaunchable = true;
|
||||
|
||||
window.addEventListener("unload", function cleanup(event) {
|
||||
if (event.target == document) {
|
||||
window.removeEventListener("unload", cleanup, false);
|
||||
|
||||
SpecialPowers.removePermission("browser", location.href);
|
||||
SpecialPowers.removePermission("browser",
|
||||
location.protocol + "//" + appDomain);
|
||||
SpecialPowers.removePermission("embed-apps", location.href);
|
||||
appRegistry.allAppsLaunchable = originalAllAppsLaunchable;
|
||||
}
|
||||
}, false);
|
||||
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [["dom.mozBrowserFramesEnabled", true]]
|
||||
}, runTest);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="start();"></body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,126 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Clear Browser Data Test</title>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
function ok(cond, message)
|
||||
{
|
||||
alert(JSON.stringify({ type: "ok",
|
||||
args: [!!cond, "appFrame: " + message] }));
|
||||
}
|
||||
|
||||
function info(message)
|
||||
{
|
||||
alert(JSON.stringify({ type: "info",
|
||||
args: ["appFrame: " + message] }));
|
||||
}
|
||||
|
||||
function finish()
|
||||
{
|
||||
alert(JSON.stringify({ type: "done" }));
|
||||
}
|
||||
|
||||
window.onerror = ok.bind(window, false);
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const objectStoreName = "foo";
|
||||
const testKey = 1;
|
||||
const testValue = objectStoreName;
|
||||
|
||||
let request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
db.onversionchange = function(event) {
|
||||
event.target.close();
|
||||
}
|
||||
|
||||
let objectStore = db.createObjectStore(objectStoreName);
|
||||
objectStore.add(testValue, testKey);
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(db === event.target.result, "created database");
|
||||
|
||||
objectStore =
|
||||
db.transaction(objectStoreName).objectStore(objectStoreName);
|
||||
objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(testValue == event.target.result, "data exists");
|
||||
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("mozbrowser", "");
|
||||
iframe.setAttribute("src", "webapp_clearBrowserData_browserFrame.html");
|
||||
iframe.addEventListener("mozbrowsershowmodalprompt", function(event) {
|
||||
let message = JSON.parse(event.detail.message);
|
||||
switch (message.type) {
|
||||
case "block":
|
||||
info("blocking browserFrame");
|
||||
event.preventDefault();
|
||||
|
||||
let request = navigator.mozApps.getSelf();
|
||||
request.onsuccess = function() {
|
||||
let app = request.result;
|
||||
ok(app, "got app");
|
||||
|
||||
info("clearing browser data");
|
||||
app.clearBrowserData();
|
||||
|
||||
info("unblocking browserFrame");
|
||||
event.detail.unblock();
|
||||
}
|
||||
break;
|
||||
case "done":
|
||||
continueToNextStepSync();
|
||||
break;
|
||||
default:
|
||||
alert(event.detail.message);
|
||||
}
|
||||
});
|
||||
|
||||
info("loading browser frame");
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
yield;
|
||||
|
||||
request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = unexpectedSuccessHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
objectStore =
|
||||
db.transaction(objectStoreName).objectStore(objectStoreName);
|
||||
objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(testValue == event.target.result, "data still exists");
|
||||
|
||||
finish();
|
||||
yield;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="testGenerator.next();"></body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,103 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Clear Browser Data Test</title>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
function ok(cond, message)
|
||||
{
|
||||
alert(JSON.stringify({ type: "ok",
|
||||
args: [!!cond, "browserFrame: " + message] }));
|
||||
}
|
||||
|
||||
function info(message)
|
||||
{
|
||||
alert(JSON.stringify({ type: "info",
|
||||
args: ["browserFrame: " + message] }));
|
||||
}
|
||||
|
||||
function block()
|
||||
{
|
||||
info("about to block");
|
||||
|
||||
// This will block until the parent has cleared our database.
|
||||
alert(JSON.stringify({ type: "block" }));
|
||||
|
||||
info("unblocked");
|
||||
}
|
||||
|
||||
function finish()
|
||||
{
|
||||
alert(JSON.stringify({ type: "done" }));
|
||||
}
|
||||
|
||||
window.onerror = ok.bind(window, false);
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const objectStoreName = "foo";
|
||||
const testKey = 1;
|
||||
const testValue = objectStoreName;
|
||||
|
||||
let request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield;
|
||||
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
db.onversionchange = function(event) {
|
||||
event.target.close();
|
||||
}
|
||||
|
||||
let objectStore = db.createObjectStore(objectStoreName);
|
||||
objectStore.add(testValue, testKey);
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(db === event.target.result, "created database");
|
||||
|
||||
objectStore =
|
||||
db.transaction(objectStoreName).objectStore(objectStoreName);
|
||||
objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
ok(testValue == event.target.result, "data exists");
|
||||
|
||||
block();
|
||||
|
||||
request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
event = yield;
|
||||
|
||||
ok(event.type == "upgradeneeded", "db doesn't exist");
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
db = event.target.result;
|
||||
info(db.objectStoreNames.length);
|
||||
ok(!db.objectStoreNames.length, "no object stores");
|
||||
|
||||
finish();
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="testGenerator.next();"></body>
|
||||
|
||||
</html>
|
|
@ -13,3 +13,7 @@ interface mozIApplicationClearPrivateDataParams : nsISupports
|
|||
readonly attribute unsigned long appId;
|
||||
readonly attribute boolean browserOnly;
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define TOPIC_WEB_APP_CLEAR_DATA "webapps-clear-data"
|
||||
%}
|
||||
|
|
|
@ -884,6 +884,23 @@ TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
|
|||
NS_RUNTIMEABORT("Not supported yet!");
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// XXXbent Need to make sure we have a whitelist for chrome databases!
|
||||
|
||||
// Verify the appID in the origin first.
|
||||
if (mApp && !aASCIIOrigin.EqualsLiteral("chrome")) {
|
||||
uint32_t appId;
|
||||
rv = mApp->GetLocalId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (!IndexedDatabaseManager::OriginMatchesApp(aASCIIOrigin, appId)) {
|
||||
NS_WARNING("App attempted to open databases that it does not have "
|
||||
"permission to access!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(GetOwnerElement());
|
||||
NS_ENSURE_TRUE(node, false);
|
||||
|
||||
|
@ -897,9 +914,8 @@ TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
|
|||
NS_ASSERTION(contentParent, "Null manager?!");
|
||||
|
||||
nsRefPtr<IDBFactory> factory;
|
||||
nsresult rv =
|
||||
IDBFactory::Create(window, aASCIIOrigin, contentParent,
|
||||
getter_AddRefs(factory));
|
||||
rv = IDBFactory::Create(window, aASCIIOrigin, contentParent,
|
||||
getter_AddRefs(factory));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (!factory) {
|
||||
|
|
|
@ -331,7 +331,7 @@ nsDOMStorageManager::Observe(nsISupports *aSubject,
|
|||
rv = params->GetBrowserOnly(&browserOnly);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MOZ_ASSERT(appId != nsIScriptSecurityManager::NO_APP_ID);
|
||||
MOZ_ASSERT(appId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||
|
||||
return DOMStorageImpl::gStorageDB->RemoveAllForApp(appId, browserOnly);
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#include "nsDOMStorage.h"
|
||||
#include "nsJSON.h"
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
||||
#include "mozIApplicationClearPrivateDataParams.h"
|
||||
#include "mozilla/dom/DOMRequest.h"
|
||||
#include "mozilla/OSFileConstants.h"
|
||||
#include "mozilla/dom/Activity.h"
|
||||
|
@ -1296,6 +1297,7 @@ static const mozilla::Module::CategoryEntry kLayoutCategories[] = {
|
|||
{ "net-channel-event-sinks", "CSPService", CSPSERVICE_CONTRACTID },
|
||||
{ JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY, "PrivilegeManager", NS_SECURITYNAMESET_CONTRACTID },
|
||||
{ "app-startup", "Script Security Manager", "service," NS_SCRIPTSECURITYMANAGER_CONTRACTID },
|
||||
{ TOPIC_WEB_APP_CLEAR_DATA, "IndexedDatabaseManager", "service," INDEXEDDB_MANAGER_CONTRACTID },
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
{ "app-startup", "Volume Service", "service," NS_VOLUMESERVICE_CONTRACTID },
|
||||
#endif
|
||||
|
|
|
@ -1336,8 +1336,6 @@ NS_GetAppInfo(nsIChannel *aChannel, uint32_t *aAppID, bool *aIsInBrowserElement)
|
|||
return true;
|
||||
}
|
||||
|
||||
#define TOPIC_WEB_APP_CLEAR_DATA "webapps-clear-data"
|
||||
|
||||
/**
|
||||
* Gets appId and browserOnly parameters from the TOPIC_WEB_APP_CLEAR_DATA
|
||||
* nsIObserverService notification. Used when clearing user data or
|
||||
|
@ -1359,10 +1357,9 @@ NS_GetAppInfoFromClearDataNotification(nsISupports *aSubject,
|
|||
uint32_t appId;
|
||||
rv = clearParams->GetAppId(&appId);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
MOZ_ASSERT(appId != NECKO_NO_APP_ID);
|
||||
MOZ_ASSERT(appId != NECKO_UNKNOWN_APP_ID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (appId == NECKO_NO_APP_ID || appId == NECKO_UNKNOWN_APP_ID) {
|
||||
if (appId == NECKO_UNKNOWN_APP_ID) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -3816,8 +3816,7 @@ nsCookieService::GetCookiesForApp(uint32_t aAppId, bool aOnlyBrowserElement,
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(aAppId != NECKO_NO_APP_ID && aAppId != NECKO_UNKNOWN_APP_ID,
|
||||
NS_ERROR_INVALID_ARG);
|
||||
NS_ENSURE_TRUE(aAppId != NECKO_UNKNOWN_APP_ID, NS_ERROR_INVALID_ARG);
|
||||
|
||||
GetCookiesForAppStruct data(aAppId, aOnlyBrowserElement);
|
||||
mDBState->hostTable.EnumerateEntries(GetCookiesForApp, &data);
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
"dom/indexedDB/test/test_event_propagation.html": "TIMED_OUT, bug 780855",
|
||||
"dom/indexedDB/test/test_app_isolation_inproc.html": "TIMED_OUT",
|
||||
"dom/indexedDB/test/test_app_isolation_oop.html": "TIMED_OUT",
|
||||
"dom/indexedDB/test/test_webapp_clearBrowserData.html": "No test app installed",
|
||||
"dom/network/tests/test_network_basics.html": "",
|
||||
"dom/permission/tests/test_permission_basics.html": "",
|
||||
"dom/sms/tests/test_sms_basics.html": "",
|
||||
|
|
|
@ -1194,6 +1194,19 @@ SpecialPowersAPI.prototype = {
|
|||
.getService(Ci.nsIIOService)
|
||||
.newURI(arg, null, null)
|
||||
.spec;
|
||||
} else if (arg.manifestURL) {
|
||||
// It's a thing representing an app.
|
||||
let tmp = {};
|
||||
Components.utils.import("resource://gre/modules/Webapps.jsm", tmp);
|
||||
|
||||
let app = tmp.DOMApplicationRegistry.getAppByManifestURL(arg.manifestURL);
|
||||
if (!app) {
|
||||
throw "No app for this manifest!";
|
||||
}
|
||||
|
||||
appId = app.localId;
|
||||
url = app.origin;
|
||||
isInBrowserElement = arg.isInBrowserElement || false;
|
||||
} else if (arg.nodePrincipal) {
|
||||
// It's a document.
|
||||
url = arg.nodePrincipal.URI.spec;
|
||||
|
|
Загрузка…
Ссылка в новой задаче