Bug 1322316 - Split SessionStorage and LocalStorage implementation - part 5 - Shared broadcasting of changes, r=asuth

This commit is contained in:
Andrea Marchesini 2017-05-17 07:01:14 +02:00
Родитель 9ace5e5eb5
Коммит 24bdb3ece3
15 изменённых файлов: 170 добавлений и 199 удалений

Просмотреть файл

@ -35,7 +35,7 @@
#include "mozilla/dom/MemoryReportRequest.h"
#include "mozilla/dom/ProcessGlobal.h"
#include "mozilla/dom/PushNotifier.h"
#include "mozilla/dom/Storage.h"
#include "mozilla/dom/LocalStorage.h"
#include "mozilla/dom/StorageIPC.h"
#include "mozilla/dom/TabGroup.h"
#include "mozilla/dom/workers/ServiceWorkerManager.h"
@ -3185,9 +3185,8 @@ ContentChild::RecvDispatchLocalStorageChange(const nsString& aDocumentURI,
const IPC::Principal& aPrincipal,
const bool& aIsPrivate)
{
Storage::DispatchStorageEvent(Storage::LocalStorage,
aDocumentURI, aKey, aOldValue, aNewValue,
aPrincipal, aIsPrivate, nullptr, true);
LocalStorage::DispatchStorageEvent(aDocumentURI, aKey, aOldValue, aNewValue,
aPrincipal, aIsPrivate, nullptr, true);
return IPC_OK();
}

Просмотреть файл

@ -7,6 +7,7 @@
#include "LocalStorage.h"
#include "LocalStorageManager.h"
#include "StorageCache.h"
#include "StorageUtils.h"
#include "nsIObserverService.h"
#include "nsIScriptSecurityManager.h"
@ -174,41 +175,6 @@ LocalStorage::Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv)
}
}
namespace {
class StorageNotifierRunnable : public Runnable
{
public:
StorageNotifierRunnable(nsISupports* aSubject, bool aPrivateBrowsing)
: Runnable("StorageNotifierRunnable")
, mSubject(aSubject)
, mPrivateBrowsing(aPrivateBrowsing)
{ }
NS_DECL_NSIRUNNABLE
private:
nsCOMPtr<nsISupports> mSubject;
const bool mPrivateBrowsing;
};
NS_IMETHODIMP
StorageNotifierRunnable::Run()
{
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
observerService->NotifyObservers(mSubject,
mPrivateBrowsing
? "dom-private-storage2-changed"
: "dom-storage2-changed",
u"localStorage");
}
return NS_OK;
}
} // namespace
void
LocalStorage::BroadcastChangeNotification(const nsSubstring& aKey,
const nsSubstring& aOldValue,
@ -237,30 +203,8 @@ LocalStorage::DispatchStorageEvent(const nsAString& aDocumentURI,
Storage* aStorage,
bool aImmediateDispatch)
{
StorageEventInit dict;
dict.mBubbles = false;
dict.mCancelable = false;
dict.mKey = aKey;
dict.mNewValue = aNewValue;
dict.mOldValue = aOldValue;
dict.mStorageArea = aStorage;
dict.mUrl = aDocumentURI;
// Note, this DOM event should never reach JS. It is cloned later in
// nsGlobalWindow.
RefPtr<StorageEvent> event =
StorageEvent::Constructor(nullptr, NS_LITERAL_STRING("storage"), dict);
event->SetPrincipal(aPrincipal);
RefPtr<StorageNotifierRunnable> r =
new StorageNotifierRunnable(event, aIsPrivate);
if (aImmediateDispatch) {
Unused << r->Run();
} else {
NS_DispatchToMainThread(r);
}
NotifyChange(aStorage, aPrincipal, aKey, aOldValue, aNewValue,
u"localStorage", aDocumentURI, aIsPrivate, aImmediateDispatch);
// If we are in the parent process and we have the principal, we want to
// broadcast this event to every other process.
@ -327,15 +271,10 @@ LocalStorage::CanUseStorage(nsIPrincipal& aSubjectPrincipal)
return CanAccess(&aSubjectPrincipal);
}
// Defined in StorageManager.cpp
extern bool
PrincipalsEqual(nsIPrincipal* aObjectPrincipal,
nsIPrincipal* aSubjectPrincipal);
bool
LocalStorage::PrincipalEquals(nsIPrincipal* aPrincipal)
{
return PrincipalsEqual(mPrincipal, aPrincipal);
return StorageUtils::PrincipalsEqual(mPrincipal, aPrincipal);
}
void

Просмотреть файл

@ -7,6 +7,7 @@
#include "LocalStorageManager.h"
#include "LocalStorage.h"
#include "StorageDBThread.h"
#include "StorageUtils.h"
#include "nsIScriptSecurityManager.h"
#include "nsIEffectiveTLDService.h"
@ -29,6 +30,8 @@
namespace mozilla {
namespace dom {
using namespace StorageUtils;
namespace {
int32_t gQuotaLimit = DEFAULT_QUOTA_LIMIT;
@ -52,51 +55,6 @@ LocalStorageManager::GetQuota()
return gQuotaLimit * 1024; // pref is in kBs
}
void
ReverseString(const nsCSubstring& aSource, nsCSubstring& aResult)
{
nsACString::const_iterator sourceBegin, sourceEnd;
aSource.BeginReading(sourceBegin);
aSource.EndReading(sourceEnd);
aResult.SetLength(aSource.Length());
nsACString::iterator destEnd;
aResult.EndWriting(destEnd);
while (sourceBegin != sourceEnd) {
*(--destEnd) = *sourceBegin;
++sourceBegin;
}
}
nsresult
CreateReversedDomain(const nsACString& aAsciiDomain,
nsACString& aKey)
{
if (aAsciiDomain.IsEmpty()) {
return NS_ERROR_NOT_AVAILABLE;
}
ReverseString(aAsciiDomain, aKey);
aKey.Append('.');
return NS_OK;
}
bool
PrincipalsEqual(nsIPrincipal* aObjectPrincipal, nsIPrincipal* aSubjectPrincipal)
{
if (!aSubjectPrincipal) {
return true;
}
if (!aObjectPrincipal) {
return false;
}
return aSubjectPrincipal->Equals(aObjectPrincipal);
}
NS_IMPL_ISUPPORTS(LocalStorageManager,
nsIDOMStorageManager)
@ -134,59 +92,6 @@ LocalStorageManager::~LocalStorageManager()
namespace {
nsresult
AppendOriginNoSuffix(nsIPrincipal* aPrincipal, nsACString& aKey)
{
nsresult rv;
nsCOMPtr<nsIURI> uri;
rv = aPrincipal->GetURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
if (!uri) {
return NS_ERROR_UNEXPECTED;
}
nsAutoCString domainOrigin;
rv = uri->GetAsciiHost(domainOrigin);
NS_ENSURE_SUCCESS(rv, rv);
if (domainOrigin.IsEmpty()) {
// For the file:/// protocol use the exact directory as domain.
bool isScheme = false;
if (NS_SUCCEEDED(uri->SchemeIs("file", &isScheme)) && isScheme) {
nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = url->GetDirectory(domainOrigin);
NS_ENSURE_SUCCESS(rv, rv);
}
}
// Append reversed domain
nsAutoCString reverseDomain;
rv = CreateReversedDomain(domainOrigin, reverseDomain);
if (NS_FAILED(rv)) {
return rv;
}
aKey.Append(reverseDomain);
// Append scheme
nsAutoCString scheme;
rv = uri->GetScheme(scheme);
NS_ENSURE_SUCCESS(rv, rv);
aKey.Append(':');
aKey.Append(scheme);
// Append port if any
int32_t port = NS_GetRealPort(uri);
if (port != -1) {
aKey.Append(nsPrintfCString(":%d", port));
}
return NS_OK;
}
nsresult
CreateQuotaDBKey(nsIPrincipal* aPrincipal,
nsACString& aKey)
@ -309,15 +214,12 @@ LocalStorageManager::GetStorageInternal(CreateMode aCreateMode,
bool aPrivate,
nsIDOMStorage** aRetval)
{
nsresult rv;
nsAutoCString originAttrSuffix;
aPrincipal->OriginAttributesRef().CreateSuffix(originAttrSuffix);
nsAutoCString originKey;
rv = AppendOriginNoSuffix(aPrincipal, originKey);
if (NS_FAILED(rv)) {
return NS_ERROR_NOT_AVAILABLE;
nsresult rv = GenerateOriginKey(aPrincipal, originAttrSuffix, originKey);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
RefPtr<StorageCache> cache = GetCache(originAttrSuffix, originKey);
@ -415,11 +317,9 @@ LocalStorageManager::CheckStorage(nsIPrincipal* aPrincipal,
}
nsAutoCString suffix;
aPrincipal->OriginAttributesRef().CreateSuffix(suffix);
nsAutoCString origin;
rv = AppendOriginNoSuffix(aPrincipal, origin);
if (NS_FAILED(rv)) {
rv = GenerateOriginKey(aPrincipal, suffix, origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

Просмотреть файл

@ -32,19 +32,23 @@ class LocalStorageManager final : public nsIDOMStorageManager
NS_DECL_NSIDOMSTORAGEMANAGER
public:
LocalStorageManager();
// Reads the preference for DOM storage quota
static uint32_t GetQuota();
// Gets (but not ensures) cache for the given scope
StorageCache* GetCache(const nsACString& aOriginSuffix,
const nsACString& aOriginNoSuffix);
// Returns object keeping usage cache for the scope.
already_AddRefed<StorageUsage> GetOriginUsage(const nsACString& aOriginNoSuffix);
already_AddRefed<StorageUsage>
GetOriginUsage(const nsACString& aOriginNoSuffix);
static nsCString CreateOrigin(const nsACString& aOriginSuffix,
const nsACString& aOriginNoSuffix);
private:
LocalStorageManager();
~LocalStorageManager();
// StorageObserverSink, handler to various chrome clearing notification

Просмотреть файл

@ -196,7 +196,8 @@ SessionStorage::BroadcastChangeNotification(const nsAString& aKey,
const nsAString& aOldValue,
const nsAString& aNewValue)
{
// TODO
NotifyChange(this, Principal(), aKey, aOldValue, aNewValue, u"sessionStorage",
mDocumentURI, mIsPrivate, false);
}
// ----------------------------------------------------------------------------

Просмотреть файл

@ -180,11 +180,9 @@ SessionStorageManager::CheckStorage(nsIPrincipal* aPrincipal,
return NS_OK;
}
/* TODO
if (!storage->PrincipalEquals(aPrincipal)) {
if (!StorageUtils::PrincipalsEqual(storage->Principal(), aPrincipal)) {
return NS_OK;
}
*/
*aRetval = true;
return NS_OK;

Просмотреть файл

@ -46,5 +46,75 @@ Storage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
return StorageBinding::Wrap(aCx, this, aGivenProto);
}
namespace {
class StorageNotifierRunnable : public Runnable
{
public:
StorageNotifierRunnable(nsISupports* aSubject, const char16_t *aStorageType,
bool aPrivateBrowsing)
: Runnable("StorageNotifierRunnable")
, mSubject(aSubject)
, mStorageType(aStorageType)
, mPrivateBrowsing(aPrivateBrowsing)
{}
NS_IMETHOD
Run() override
{
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
observerService->NotifyObservers(mSubject,
mPrivateBrowsing
? "dom-private-storage2-changed"
: "dom-storage2-changed",
mStorageType);
}
return NS_OK;
}
private:
nsCOMPtr<nsISupports> mSubject;
const char16_t* mStorageType;
const bool mPrivateBrowsing;
};
} // namespace
/* static */ void
Storage::NotifyChange(Storage* aStorage, nsIPrincipal* aPrincipal,
const nsAString& aKey,
const nsAString& aOldValue, const nsAString& aNewValue,
const char16_t* aStorageType,
const nsAString& aDocumentURI, bool aIsPrivate,
bool aImmediateDispatch)
{
StorageEventInit dict;
dict.mBubbles = false;
dict.mCancelable = false;
dict.mKey = aKey;
dict.mNewValue = aNewValue;
dict.mOldValue = aOldValue;
dict.mStorageArea = aStorage;
dict.mUrl = aDocumentURI;
// Note, this DOM event should never reach JS. It is cloned later in
// nsGlobalWindow.
RefPtr<StorageEvent> event =
StorageEvent::Constructor(nullptr, NS_LITERAL_STRING("storage"), dict);
event->SetPrincipal(aPrincipal);
RefPtr<StorageNotifierRunnable> r =
new StorageNotifierRunnable(event, aStorageType, aIsPrivate);
if (aImmediateDispatch) {
Unused << r->Run();
} else {
NS_DispatchToMainThread(r, NS_DISPATCH_NORMAL);
}
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -109,6 +109,13 @@ public:
virtual bool IsSessionOnly() const = 0;
static void
NotifyChange(Storage* aStorage, nsIPrincipal* aPrincipal,
const nsAString& aKey, const nsAString& aOldValue,
const nsAString& aNewValue, const char16_t* aStorageType,
const nsAString& aDocumentURI, bool aIsPrivate,
bool aImmediateDispatch);
protected:
virtual ~Storage();

Просмотреть файл

@ -9,6 +9,7 @@
#include "Storage.h"
#include "StorageDBThread.h"
#include "StorageIPC.h"
#include "StorageUtils.h"
#include "LocalStorageManager.h"
#include "nsAutoPtr.h"
@ -546,15 +547,10 @@ StorageCache::GetOriginQuotaUsage(const LocalStorage* aStorage) const
return mData[GetDataSetIndex(aStorage)].mOriginQuotaUsage;
}
// Defined in StorageManager.cpp
extern bool
PrincipalsEqual(nsIPrincipal* aObjectPrincipal,
nsIPrincipal* aSubjectPrincipal);
bool
StorageCache::CheckPrincipal(nsIPrincipal* aPrincipal) const
{
return PrincipalsEqual(mPrincipal, aPrincipal);
return StorageUtils::PrincipalsEqual(mPrincipal, aPrincipal);
}
void

Просмотреть файл

@ -7,6 +7,7 @@
#include "StorageDBThread.h"
#include "StorageDBUpdater.h"
#include "StorageCache.h"
#include "StorageUtils.h"
#include "LocalStorageManager.h"
#include "nsIEffectiveTLDService.h"
@ -43,6 +44,8 @@
namespace mozilla {
namespace dom {
using namespace StorageUtils;
namespace { // anon
// This is only a compatibility code for schema version 0. Returns the 'scope'
@ -446,10 +449,6 @@ StorageDBThread::ThreadObserver::AfterProcessNextEvent(nsIThreadInternal* aThrea
return NS_OK;
}
extern void
ReverseString(const nsCSubstring& aSource, nsCSubstring& aResult);
nsresult
StorageDBThread::OpenDatabaseConnection()
{

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "LocalStorageManager.h"
#include "StorageUtils.h"
#include "mozIStorageBindingParamsArray.h"
#include "mozIStorageBindingParams.h"
@ -21,8 +22,7 @@
namespace mozilla {
namespace dom {
extern void
ReverseString(const nsCSubstring& aSource, nsCSubstring& aResult);
using namespace StorageUtils;
namespace {

Просмотреть файл

@ -8,6 +8,7 @@
#include "StorageDBThread.h"
#include "StorageCache.h"
#include "StorageUtils.h"
#include "mozilla/BasePrincipal.h"
#include "nsIObserverService.h"
@ -29,6 +30,8 @@
namespace mozilla {
namespace dom {
using namespace StorageUtils;
static const char kStartupTopic[] = "sessionstore-windows-restored";
static const uint32_t kStartupDelay = 0;
@ -40,9 +43,6 @@ NS_IMPL_ISUPPORTS(StorageObserver,
StorageObserver* StorageObserver::sSelf = nullptr;
extern nsresult
CreateReversedDomain(const nsACString& aAsciiDomain, nsACString& aKey);
// static
nsresult
StorageObserver::Init()

Просмотреть файл

@ -66,6 +66,52 @@ GenerateOriginKey(nsIPrincipal* aPrincipal, nsACString& aOriginAttrSuffix,
return NS_OK;
}
bool
PrincipalsEqual(nsIPrincipal* aObjectPrincipal,
nsIPrincipal* aSubjectPrincipal)
{
if (!aSubjectPrincipal) {
return true;
}
if (!aObjectPrincipal) {
return false;
}
return aSubjectPrincipal->Equals(aObjectPrincipal);
}
void
ReverseString(const nsCSubstring& aSource, nsCSubstring& aResult)
{
nsACString::const_iterator sourceBegin, sourceEnd;
aSource.BeginReading(sourceBegin);
aSource.EndReading(sourceEnd);
aResult.SetLength(aSource.Length());
nsACString::iterator destEnd;
aResult.EndWriting(destEnd);
while (sourceBegin != sourceEnd) {
*(--destEnd) = *sourceBegin;
++sourceBegin;
}
}
nsresult
CreateReversedDomain(const nsACString& aAsciiDomain,
nsACString& aKey)
{
if (aAsciiDomain.IsEmpty()) {
return NS_ERROR_NOT_AVAILABLE;
}
ReverseString(aAsciiDomain, aKey);
aKey.Append('.');
return NS_OK;
}
} // StorageUtils namespace
} // dom namespace
} // mozilla namespace

Просмотреть файл

@ -17,6 +17,17 @@ nsresult
GenerateOriginKey(nsIPrincipal* aPrincipal, nsACString& aOriginAttrSuffix,
nsACString& aOriginKey);
bool
PrincipalsEqual(nsIPrincipal* aObjectPrincipal,
nsIPrincipal* aSubjectPrincipal);
void
ReverseString(const nsCSubstring& aSource, nsCSubstring& aResult);
nsresult
CreateReversedDomain(const nsACString& aAsciiDomain,
nsACString& aKey);
} // StorageUtils namespace
} // dom namespace
} // mozilla namespace

Просмотреть файл

@ -8,6 +8,7 @@ with Files("**"):
BUG_COMPONENT = ("Core", "DOM")
EXPORTS.mozilla.dom += [
'LocalStorage.h',
'LocalStorageManager.h',
'SessionStorageManager.h',
'Storage.h',