gecko/dom/storage/DOMStorage.cpp
Nathan Froyd e4e2da55c9 Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat
The bulk of this commit was generated with a script, executed at the top
level of a typical source code checkout.  The only non-machine-generated
part was modifying MFBT's moz.build to reflect the new naming.

CLOSED TREE makes big refactorings like this a piece of cake.

 # The main substitution.
find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \
    xargs perl -p -i -e '
 s/nsRefPtr\.h/RefPtr\.h/g; # handle includes
 s/nsRefPtr ?</RefPtr</g;   # handle declarations and variables
'

 # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h.
perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h

 # Handle nsRefPtr.h itself, a couple places that define constructors
 # from nsRefPtr, and code generators specially.  We do this here, rather
 # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename
 # things like nsRefPtrHashtable.
perl -p -i -e 's/nsRefPtr/RefPtr/g' \
     mfbt/nsRefPtr.h \
     xpcom/glue/nsCOMPtr.h \
     xpcom/base/OwningNonNull.h \
     ipc/ipdl/ipdl/lower.py \
     ipc/ipdl/ipdl/builtin.py \
     dom/bindings/Codegen.py \
     python/lldbutils/lldbutils/utils.py

 # In our indiscriminate substitution above, we renamed
 # nsRefPtrGetterAddRefs, the class behind getter_AddRefs.  Fix that up.
find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \
    xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g'

if [ -d .git ]; then
    git mv mfbt/nsRefPtr.h mfbt/RefPtr.h
else
    hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h
fi
2015-10-18 01:24:48 -04:00

312 lines
7.6 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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/. */
#include "DOMStorage.h"
#include "DOMStorageCache.h"
#include "DOMStorageManager.h"
#include "nsIObserverService.h"
#include "nsIScriptSecurityManager.h"
#include "nsIPermissionManager.h"
#include "nsIPrincipal.h"
#include "nsICookiePermission.h"
#include "nsPIDOMWindow.h"
#include "mozilla/dom/StorageBinding.h"
#include "mozilla/dom/StorageEvent.h"
#include "mozilla/dom/StorageEventBinding.h"
#include "mozilla/Services.h"
#include "mozilla/Preferences.h"
#include "mozilla/EnumSet.h"
#include "nsThreadUtils.h"
#include "nsContentUtils.h"
#include "nsServiceManagerUtils.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DOMStorage, mManager, mPrincipal, mWindow)
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMStorage)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMStorage)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMStorage)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStorage)
NS_INTERFACE_MAP_ENTRY(nsIDOMStorage)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END
DOMStorage::DOMStorage(nsIDOMWindow* aWindow,
DOMStorageManager* aManager,
DOMStorageCache* aCache,
const nsAString& aDocumentURI,
nsIPrincipal* aPrincipal,
bool aIsPrivate)
: mWindow(aWindow)
, mManager(aManager)
, mCache(aCache)
, mDocumentURI(aDocumentURI)
, mPrincipal(aPrincipal)
, mIsPrivate(aIsPrivate)
, mIsSessionOnly(false)
{
mCache->Preload();
}
DOMStorage::~DOMStorage()
{
mCache->KeepAlive();
}
/* virtual */ JSObject*
DOMStorage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return StorageBinding::Wrap(aCx, this, aGivenProto);
}
uint32_t
DOMStorage::GetLength(ErrorResult& aRv)
{
if (!CanUseStorage(nullptr, this)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return 0;
}
uint32_t length;
aRv = mCache->GetLength(this, &length);
return length;
}
void
DOMStorage::Key(uint32_t aIndex, nsAString& aResult, ErrorResult& aRv)
{
if (!CanUseStorage(nullptr, this)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
aRv = mCache->GetKey(this, aIndex, aResult);
}
void
DOMStorage::GetItem(const nsAString& aKey, nsAString& aResult, ErrorResult& aRv)
{
if (!CanUseStorage(nullptr, this)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
aRv = mCache->GetItem(this, aKey, aResult);
}
void
DOMStorage::SetItem(const nsAString& aKey, const nsAString& aData,
ErrorResult& aRv)
{
if (!CanUseStorage(nullptr, this)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
Telemetry::Accumulate(GetType() == LocalStorage
? Telemetry::LOCALDOMSTORAGE_KEY_SIZE_BYTES
: Telemetry::SESSIONDOMSTORAGE_KEY_SIZE_BYTES, aKey.Length());
Telemetry::Accumulate(GetType() == LocalStorage
? Telemetry::LOCALDOMSTORAGE_VALUE_SIZE_BYTES
: Telemetry::SESSIONDOMSTORAGE_VALUE_SIZE_BYTES, aData.Length());
nsString data;
bool ok = data.Assign(aData, fallible);
if (!ok) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
nsString old;
aRv = mCache->SetItem(this, aKey, data, old);
if (aRv.Failed()) {
return;
}
if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
BroadcastChangeNotification(aKey, old, aData);
}
}
void
DOMStorage::RemoveItem(const nsAString& aKey, ErrorResult& aRv)
{
if (!CanUseStorage(nullptr, this)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
nsAutoString old;
aRv = mCache->RemoveItem(this, aKey, old);
if (aRv.Failed()) {
return;
}
if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
BroadcastChangeNotification(aKey, old, NullString());
}
}
void
DOMStorage::Clear(ErrorResult& aRv)
{
if (!CanUseStorage(nullptr, this)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
aRv = mCache->Clear(this);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
BroadcastChangeNotification(NullString(), NullString(), NullString());
}
}
namespace {
class StorageNotifierRunnable : public nsRunnable
{
public:
StorageNotifierRunnable(nsISupports* aSubject, const char16_t* aType)
: mSubject(aSubject), mType(aType)
{ }
NS_DECL_NSIRUNNABLE
private:
nsCOMPtr<nsISupports> mSubject;
const char16_t* mType;
};
NS_IMETHODIMP
StorageNotifierRunnable::Run()
{
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
observerService->NotifyObservers(mSubject, "dom-storage2-changed", mType);
}
return NS_OK;
}
} // namespace
void
DOMStorage::BroadcastChangeNotification(const nsSubstring& aKey,
const nsSubstring& aOldValue,
const nsSubstring& aNewValue)
{
StorageEventInit dict;
dict.mBubbles = false;
dict.mCancelable = false;
dict.mKey = aKey;
dict.mNewValue = aNewValue;
dict.mOldValue = aOldValue;
dict.mStorageArea = this;
dict.mUrl = mDocumentURI;
// 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);
RefPtr<StorageNotifierRunnable> r =
new StorageNotifierRunnable(event,
GetType() == LocalStorage
? MOZ_UTF16("localStorage")
: MOZ_UTF16("sessionStorage"));
NS_DispatchToMainThread(r);
}
static const char kPermissionType[] = "cookie";
static const char kStorageEnabled[] = "dom.storage.enabled";
// static, public
bool
DOMStorage::CanUseStorage(nsPIDOMWindow* aWindow, DOMStorage* aStorage)
{
// This method is responsible for correct setting of mIsSessionOnly.
// It doesn't work with mIsPrivate flag at all, since it is checked
// regardless mIsSessionOnly flag in DOMStorageCache code.
if (!mozilla::Preferences::GetBool(kStorageEnabled)) {
return false;
}
nsContentUtils::StorageAccess access = nsContentUtils::StorageAccess::eDeny;
if (aWindow) {
access = nsContentUtils::StorageAllowedForWindow(aWindow);
} else if (aStorage) {
access = nsContentUtils::StorageAllowedForPrincipal(aStorage->mPrincipal);
}
if (access == nsContentUtils::StorageAccess::eDeny) {
return false;
}
if (aStorage) {
aStorage->mIsSessionOnly = access <= nsContentUtils::StorageAccess::eSessionScoped;
nsCOMPtr<nsIPrincipal> subjectPrincipal =
nsContentUtils::SubjectPrincipal();
return aStorage->CanAccess(subjectPrincipal);
}
return true;
}
DOMStorage::StorageType
DOMStorage::GetType() const
{
return mManager->Type();
}
nsIPrincipal*
DOMStorage::GetPrincipal()
{
return mPrincipal;
}
// Defined in DOMStorageManager.cpp
extern bool
PrincipalsEqual(nsIPrincipal* aObjectPrincipal, nsIPrincipal* aSubjectPrincipal);
bool
DOMStorage::PrincipalEquals(nsIPrincipal* aPrincipal)
{
return PrincipalsEqual(mPrincipal, aPrincipal);
}
bool
DOMStorage::CanAccess(nsIPrincipal* aPrincipal)
{
return !aPrincipal || aPrincipal->Subsumes(mPrincipal);
}
void
DOMStorage::GetSupportedNames(unsigned, nsTArray<nsString>& aKeys)
{
if (!CanUseStorage(nullptr, this)) {
// return just an empty array
aKeys.Clear();
return;
}
mCache->GetKeys(this, aKeys);
}
} // namespace dom
} // namespace mozilla