Bug 1322316 - Split SessionStorage and LocalStorage implementation - part 2 - Rename Storage.{cpp,h} to LocalStorage.{cpp,h}, r=asuth
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 17 May 2017 07:01:13 +0200
changeset 358631 d959241eaf7d41b9d391e2dfb027d9321a719b63
parent 358630 9957d3e640736942b95c21dad5cfea3192cc1e96
child 358632 1d7d7228924b539e2e771c7d0a64e0db6e94aac6
push id90362
push useramarchesini@mozilla.com
push dateWed, 17 May 2017 05:03:33 +0000
treeherdermozilla-inbound@2f47ba116b42 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1322316
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1322316 - Split SessionStorage and LocalStorage implementation - part 2 - Rename Storage.{cpp,h} to LocalStorage.{cpp,h}, r=asuth
dom/storage/LocalStorage.cpp
dom/storage/LocalStorage.h
dom/storage/Storage.cpp
dom/storage/Storage.h
dom/storage/StorageManager.h
dom/storage/moz.build
copy from dom/storage/Storage.cpp
copy to dom/storage/LocalStorage.cpp
--- a/dom/storage/Storage.cpp
+++ b/dom/storage/LocalStorage.cpp
@@ -1,15 +1,15 @@
 /* -*- 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 "Storage.h"
+#include "LocalStorage.h"
 #include "StorageCache.h"
 #include "StorageManager.h"
 
 #include "nsIObserverService.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "nsICookiePermission.h"
@@ -28,49 +28,16 @@
 #include "nsServiceManagerUtils.h"
 
 namespace mozilla {
 
 using namespace ipc;
 
 namespace dom {
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Storage, mWindow, mPrincipal)
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(Storage)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(Storage)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Storage)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStorage)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMStorage)
-NS_INTERFACE_MAP_END
-
-Storage::Storage(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal)
-  : mWindow(aWindow)
-  , mPrincipal(aPrincipal)
-{
-  MOZ_ASSERT(aPrincipal);
-}
-
-Storage::~Storage()
-{}
-
-bool
-Storage::CanAccess(nsIPrincipal* aPrincipal)
-{
-  return !aPrincipal || aPrincipal->Subsumes(mPrincipal);
-}
-
-/* virtual */ JSObject*
-Storage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return StorageBinding::Wrap(aCx, this, aGivenProto);
-}
-
 NS_IMPL_CYCLE_COLLECTION_INHERITED(LocalStorage, Storage, mManager);
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LocalStorage)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_INHERITING(Storage)
 
 NS_IMPL_ADDREF_INHERITED(LocalStorage, Storage)
 NS_IMPL_RELEASE_INHERITED(LocalStorage, Storage)
copy from dom/storage/Storage.h
copy to dom/storage/LocalStorage.h
--- a/dom/storage/Storage.h
+++ b/dom/storage/LocalStorage.h
@@ -1,124 +1,27 @@
 /* -*- 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/. */
 
-#ifndef mozilla_dom_Storage_h
-#define mozilla_dom_Storage_h
+#ifndef mozilla_dom_LocalStorage_h
+#define mozilla_dom_LocalStorage_h
 
-#include "mozilla/Attributes.h"
-#include "mozilla/ErrorResult.h"
-#include "mozilla/Maybe.h"
-#include "nsIDOMStorage.h"
-#include "nsCycleCollectionParticipant.h"
+#include "Storage.h"
 #include "nsWeakReference.h"
-#include "nsWrapperCache.h"
-#include "nsISupports.h"
-
-class nsIPrincipal;
-class nsPIDOMWindowInner;
 
 namespace mozilla {
 namespace dom {
 
 class StorageManagerBase;
 class StorageCache;
 class StorageEvent;
 
-class Storage : public nsIDOMStorage
-              , public nsWrapperCache
-{
-public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Storage,
-                                                         nsIDOMStorage)
-
-  Storage(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal);
-
-  virtual int64_t GetOriginQuotaUsage() const = 0;
-
-  virtual bool CanAccess(nsIPrincipal* aPrincipal);
-
-  // WebIDL
-  JSObject* WrapObject(JSContext* aCx,
-                       JS::Handle<JSObject*> aGivenProto) override;
-
-  nsPIDOMWindowInner* GetParentObject() const
-  {
-    return mWindow;
-  }
-
-  virtual uint32_t
-  GetLength(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) = 0;
-
-  virtual void
-  Key(uint32_t aIndex, nsAString& aResult,
-      nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) = 0;
-
-  virtual void
-  GetItem(const nsAString& aKey, nsAString& aResult,
-          nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) = 0;
-
-  virtual void
-  GetSupportedNames(nsTArray<nsString>& aKeys) = 0;
-
-  void NamedGetter(const nsAString& aKey, bool& aFound, nsAString& aResult,
-                   nsIPrincipal& aSubjectPrincipal,
-                   ErrorResult& aRv)
-  {
-    GetItem(aKey, aResult, aSubjectPrincipal, aRv);
-    aFound = !aResult.IsVoid();
-  }
-
-  virtual void
-  SetItem(const nsAString& aKey, const nsAString& aValue,
-          nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) = 0;
-
-  void NamedSetter(const nsAString& aKey, const nsAString& aValue,
-                   nsIPrincipal& aSubjectPrincipal,
-                   ErrorResult& aRv)
-  {
-    SetItem(aKey, aValue, aSubjectPrincipal, aRv);
-  }
-
-  virtual void
-  RemoveItem(const nsAString& aKey, nsIPrincipal& aSubjectPrincipal,
-             ErrorResult& aRv) = 0;
-
-  void NamedDeleter(const nsAString& aKey, bool& aFound,
-                    nsIPrincipal& aSubjectPrincipal,
-                    ErrorResult& aRv)
-  {
-    RemoveItem(aKey, aSubjectPrincipal, aRv);
-
-    aFound = !aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION);
-  }
-
-  virtual void
-  Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) = 0;
-
-  virtual bool IsSessionOnly() const = 0;
-
-protected:
-  virtual ~Storage();
-
-  nsIPrincipal*
-  Principal() const
-  {
-    return mPrincipal;
-  }
-
-private:
-  nsCOMPtr<nsPIDOMWindowInner> mWindow;
-  nsCOMPtr<nsIPrincipal> mPrincipal;
-};
-
 class LocalStorage final : public Storage
                          , public nsSupportsWeakReference
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(LocalStorage, Storage)
 
   enum StorageType {
@@ -242,9 +145,9 @@ private:
   void BroadcastChangeNotification(const nsSubstring& aKey,
                                    const nsSubstring& aOldValue,
                                    const nsSubstring& aNewValue);
 };
 
 } // namespace dom
 } // namespace mozilla
 
-#endif // mozilla_dom_Storage_h
+#endif // mozilla_dom_LocalStorage_h
--- a/dom/storage/Storage.cpp
+++ b/dom/storage/Storage.cpp
@@ -1,41 +1,21 @@
 /* -*- 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 "Storage.h"
-#include "StorageCache.h"
-#include "StorageManager.h"
 
-#include "nsIObserverService.h"
-#include "nsIScriptSecurityManager.h"
-#include "nsIPermissionManager.h"
+#include "mozilla/dom/StorageBinding.h"
 #include "nsIPrincipal.h"
-#include "nsICookiePermission.h"
-
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/ContentParent.h"
-#include "mozilla/dom/PermissionMessageUtils.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"
+#include "nsPIDOMWindow.h"
 
 namespace mozilla {
-
-using namespace ipc;
-
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Storage, mWindow, mPrincipal)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Storage)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Storage)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Storage)
@@ -61,341 +41,10 @@ Storage::CanAccess(nsIPrincipal* aPrinci
 }
 
 /* virtual */ JSObject*
 Storage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return StorageBinding::Wrap(aCx, this, aGivenProto);
 }
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED(LocalStorage, Storage, mManager);
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LocalStorage)
-  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-NS_INTERFACE_MAP_END_INHERITING(Storage)
-
-NS_IMPL_ADDREF_INHERITED(LocalStorage, Storage)
-NS_IMPL_RELEASE_INHERITED(LocalStorage, Storage)
-
-LocalStorage::LocalStorage(nsPIDOMWindowInner* aWindow,
-                           StorageManagerBase* aManager,
-                           StorageCache* aCache,
-                           const nsAString& aDocumentURI,
-                           nsIPrincipal* aPrincipal,
-                           bool aIsPrivate)
-  : Storage(aWindow, aPrincipal)
-  , mManager(aManager)
-  , mCache(aCache)
-  , mDocumentURI(aDocumentURI)
-  , mIsPrivate(aIsPrivate)
-  , mIsSessionOnly(false)
-{
-  mCache->Preload();
-}
-
-LocalStorage::~LocalStorage()
-{
-}
-
-int64_t
-LocalStorage::GetOriginQuotaUsage() const
-{
-  return mCache->GetOriginQuotaUsage(this);
-}
-
-uint32_t
-LocalStorage::GetLength(nsIPrincipal& aSubjectPrincipal,
-                        ErrorResult& aRv)
-{
-  if (!CanUseStorage(aSubjectPrincipal)) {
-    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-    return 0;
-  }
-
-  uint32_t length;
-  aRv = mCache->GetLength(this, &length);
-  return length;
-}
-
-void
-LocalStorage::Key(uint32_t aIndex, nsAString& aResult,
-                  nsIPrincipal& aSubjectPrincipal,
-                  ErrorResult& aRv)
-{
-  if (!CanUseStorage(aSubjectPrincipal)) {
-    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-    return;
-  }
-
-  aRv = mCache->GetKey(this, aIndex, aResult);
-}
-
-void
-LocalStorage::GetItem(const nsAString& aKey, nsAString& aResult,
-                      nsIPrincipal& aSubjectPrincipal,
-                      ErrorResult& aRv)
-{
-  if (!CanUseStorage(aSubjectPrincipal)) {
-    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-    return;
-  }
-
-  aRv = mCache->GetItem(this, aKey, aResult);
-}
-
-void
-LocalStorage::SetItem(const nsAString& aKey, const nsAString& aData,
-                      nsIPrincipal& aSubjectPrincipal,
-                      ErrorResult& aRv)
-{
-  if (!CanUseStorage(aSubjectPrincipal)) {
-    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-    return;
-  }
-
-  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
-LocalStorage::RemoveItem(const nsAString& aKey, nsIPrincipal& aSubjectPrincipal,
-                         ErrorResult& aRv)
-{
-  if (!CanUseStorage(aSubjectPrincipal)) {
-    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
-LocalStorage::Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv)
-{
-  if (!CanUseStorage(aSubjectPrincipal)) {
-    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 Runnable
-{
-public:
-  StorageNotifierRunnable(nsISupports* aSubject, const char16_t* aType,
-                          bool aPrivateBrowsing)
-    : Runnable("StorageNotifierRunnable")
-    , mSubject(aSubject)
-    , mType(aType)
-    , mPrivateBrowsing(aPrivateBrowsing)
-  { }
-
-  NS_DECL_NSIRUNNABLE
-
-private:
-  nsCOMPtr<nsISupports> mSubject;
-  const char16_t* mType;
-  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",
-                                     mType);
-  }
-  return NS_OK;
-}
-
-} // namespace
-
-void
-LocalStorage::BroadcastChangeNotification(const nsSubstring& aKey,
-                                          const nsSubstring& aOldValue,
-                                          const nsSubstring& aNewValue)
-{
-  if (!XRE_IsParentProcess() && GetType() == eLocalStorage && Principal()) {
-    // If we are in a child process, we want to send a message to the parent in
-    // order to broadcast the StorageEvent correctly to any child process.
-    dom::ContentChild* cc = dom::ContentChild::GetSingleton();
-    Unused << NS_WARN_IF(!cc->SendBroadcastLocalStorageChange(
-      mDocumentURI, nsString(aKey), nsString(aOldValue), nsString(aNewValue),
-      IPC::Principal(Principal()), mIsPrivate));
-  }
-
-  DispatchStorageEvent(GetType(), mDocumentURI, aKey, aOldValue, aNewValue,
-                       Principal(), mIsPrivate, this, false);
-}
-
-/* static */ void
-LocalStorage::DispatchStorageEvent(StorageType aStorageType,
-                                   const nsAString& aDocumentURI,
-                                   const nsAString& aKey,
-                                   const nsAString& aOldValue,
-                                   const nsAString& aNewValue,
-                                   nsIPrincipal* aPrincipal,
-                                   bool aIsPrivate,
-                                   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,
-                                aStorageType == eLocalStorage
-                                  ? u"localStorage"
-                                  : u"sessionStorage",
-                                aIsPrivate);
-
-  if (aImmediateDispatch) {
-    Unused << r->Run();
-  } else {
-    NS_DispatchToMainThread(r);
-  }
-
-  // If we are in the parent process and we have the principal, we want to
-  // broadcast this event to every other process.
-  if (aStorageType == eLocalStorage && XRE_IsParentProcess() && aPrincipal) {
-    for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
-      Unused << cp->SendDispatchLocalStorageChange(
-        nsString(aDocumentURI), nsString(aKey), nsString(aOldValue),
-        nsString(aNewValue), IPC::Principal(aPrincipal), aIsPrivate);
-    }
-  }
-}
-
-void
-LocalStorage::ApplyEvent(StorageEvent* aStorageEvent)
-{
-  MOZ_ASSERT(aStorageEvent);
-
-  nsAutoString key;
-  nsAutoString old;
-  nsAutoString value;
-
-  aStorageEvent->GetKey(key);
-  aStorageEvent->GetNewValue(value);
-
-  // No key means clearing the full storage.
-  if (key.IsVoid()) {
-    MOZ_ASSERT(value.IsVoid());
-    mCache->Clear(this, StorageCache::E10sPropagated);
-    return;
-  }
-
-  // No new value means removing the key.
-  if (value.IsVoid()) {
-    mCache->RemoveItem(this, key, old, StorageCache::E10sPropagated);
-    return;
-  }
-
-  // Otherwise, we set the new value.
-  mCache->SetItem(this, key, value, old, StorageCache::E10sPropagated);
-}
-
-static const char kPermissionType[] = "cookie";
-static const char kStorageEnabled[] = "dom.storage.enabled";
-
-bool
-LocalStorage::CanUseStorage(nsIPrincipal& aSubjectPrincipal)
-{
-  // 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::StorageAllowedForPrincipal(Principal());
-
-  if (access == nsContentUtils::StorageAccess::eDeny) {
-    return false;
-  }
-
-  mIsSessionOnly = access <= nsContentUtils::StorageAccess::eSessionScoped;
-  return CanAccess(&aSubjectPrincipal);
-}
-
-LocalStorage::StorageType
-LocalStorage::GetType() const
-{
-  return mManager->Type();
-}
-
-// Defined in StorageManager.cpp
-extern bool
-PrincipalsEqual(nsIPrincipal* aObjectPrincipal,
-                nsIPrincipal* aSubjectPrincipal);
-
-bool
-LocalStorage::PrincipalEquals(nsIPrincipal* aPrincipal)
-{
-  return PrincipalsEqual(mPrincipal, aPrincipal);
-}
-
-void
-LocalStorage::GetSupportedNames(nsTArray<nsString>& aKeys)
-{
-  if (!CanUseStorage(*nsContentUtils::SubjectPrincipal())) {
-    // return just an empty array
-    aKeys.Clear();
-    return;
-  }
-
-  mCache->GetKeys(this, aKeys);
-}
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/storage/Storage.h
+++ b/dom/storage/Storage.h
@@ -17,20 +17,16 @@
 #include "nsISupports.h"
 
 class nsIPrincipal;
 class nsPIDOMWindowInner;
 
 namespace mozilla {
 namespace dom {
 
-class StorageManagerBase;
-class StorageCache;
-class StorageEvent;
-
 class Storage : public nsIDOMStorage
               , public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Storage,
                                                          nsIDOMStorage)
 
@@ -109,142 +105,12 @@ protected:
     return mPrincipal;
   }
 
 private:
   nsCOMPtr<nsPIDOMWindowInner> mWindow;
   nsCOMPtr<nsIPrincipal> mPrincipal;
 };
 
-class LocalStorage final : public Storage
-                         , public nsSupportsWeakReference
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(LocalStorage, Storage)
-
-  enum StorageType {
-    eLocalStorage = 1,
-    eSessionStorage = 2
-  };
-
-  StorageType GetType() const;
-
-  StorageManagerBase* GetManager() const
-  {
-    return mManager;
-  }
-
-  StorageCache const* GetCache() const
-  {
-    return mCache;
-  }
-
-  bool PrincipalEquals(nsIPrincipal* aPrincipal);
-
-  LocalStorage(nsPIDOMWindowInner* aWindow,
-               StorageManagerBase* aManager,
-               StorageCache* aCache,
-               const nsAString& aDocumentURI,
-               nsIPrincipal* aPrincipal,
-               bool aIsPrivate);
-
-  // WebIDL
-
-  int64_t GetOriginQuotaUsage() const override;
-
-  uint32_t GetLength(nsIPrincipal& aSubjectPrincipal,
-                     ErrorResult& aRv) override;
-
-  void Key(uint32_t aIndex, nsAString& aResult,
-           nsIPrincipal& aSubjectPrincipal,
-           ErrorResult& aRv) override;
-
-  void GetItem(const nsAString& aKey, nsAString& aResult,
-               nsIPrincipal& aSubjectPrincipal,
-               ErrorResult& aRv) override;
-
-  void GetSupportedNames(nsTArray<nsString>& aKeys) override;
-
-  void SetItem(const nsAString& aKey, const nsAString& aValue,
-               nsIPrincipal& aSubjectPrincipal,
-               ErrorResult& aRv) override;
-
-  void RemoveItem(const nsAString& aKey,
-                  nsIPrincipal& aSubjectPrincipal,
-                  ErrorResult& aRv) override;
-
-  void Clear(nsIPrincipal& aSubjectPrincipal,
-             ErrorResult& aRv) override;
-
-  bool IsPrivate() const { return mIsPrivate; }
-  bool IsSessionOnly() const override { return mIsSessionOnly; }
-
-  bool IsForkOf(const LocalStorage* aOther) const
-  {
-    MOZ_ASSERT(aOther);
-    return mCache == aOther->mCache;
-  }
-
-  // aStorage can be null if this method is called by ContentChild.
-  //
-  // aImmediateDispatch is for use by (main-thread) IPC code so that PContent
-  // ordering can be maintained.  Without this, the event would be enqueued and
-  // run in a future turn of the event loop, potentially allowing other PContent
-  // Recv* methods to trigger script that wants to assume our localstorage
-  // changes have already been applied.  This is the case for message manager
-  // messages which are used by ContentTask testing logic and webextensions.
-  static void
-  DispatchStorageEvent(StorageType aStorageType,
-                       const nsAString& aDocumentURI,
-                       const nsAString& aKey,
-                       const nsAString& aOldValue,
-                       const nsAString& aNewValue,
-                       nsIPrincipal* aPrincipal,
-                       bool aIsPrivate,
-                       Storage* aStorage,
-                       bool aImmediateDispatch);
-
-  void
-  ApplyEvent(StorageEvent* aStorageEvent);
-
-protected:
-  // The method checks whether the caller can use a storage.
-  // CanUseStorage is called before any DOM initiated operation
-  // on a storage is about to happen and ensures that the storage's
-  // session-only flag is properly set according the current settings.
-  // It is an optimization since the privileges check and session only
-  // state determination are complex and share the code (comes hand in
-  // hand together).
-  bool CanUseStorage(nsIPrincipal& aSubjectPrincipal);
-
-private:
-  ~LocalStorage();
-
-  friend class StorageManagerBase;
-  friend class StorageCache;
-
-  nsCOMPtr<nsPIDOMWindowInner> mWindow;
-  RefPtr<StorageManagerBase> mManager;
-  RefPtr<StorageCache> mCache;
-  nsString mDocumentURI;
-
-  // Principal this Storage (i.e. localStorage or sessionStorage) has
-  // been created for
-  nsCOMPtr<nsIPrincipal> mPrincipal;
-
-  // Whether this storage is running in private-browsing window.
-  bool mIsPrivate : 1;
-
-  // Whether storage is set to persist data only per session, may change
-  // dynamically and is set by CanUseStorage function that is called
-  // before any operation on the storage.
-  bool mIsSessionOnly : 1;
-
-  void BroadcastChangeNotification(const nsSubstring& aKey,
-                                   const nsSubstring& aOldValue,
-                                   const nsSubstring& aNewValue);
-};
-
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_Storage_h
--- a/dom/storage/StorageManager.h
+++ b/dom/storage/StorageManager.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_StorageManager_h
 #define mozilla_dom_StorageManager_h
 
 #include "nsIDOMStorageManager.h"
 #include "StorageObserver.h"
 
+#include "LocalStorage.h"
 #include "StorageCache.h"
 #include "mozilla/dom/Storage.h"
 
 #include "nsTHashtable.h"
 #include "nsDataHashtable.h"
 #include "nsClassHashtable.h"
 #include "nsHashKeys.h"
 
--- a/dom/storage/moz.build
+++ b/dom/storage/moz.build
@@ -3,22 +3,22 @@
 # 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/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM")
 
 EXPORTS.mozilla.dom += [
-    'SessionStorage.h',
     'Storage.h',
     'StorageIPC.h',
 ]
 
 UNIFIED_SOURCES += [
+    'LocalStorage.cpp',
     'SessionStorage.cpp',
     'Storage.cpp',
     'StorageCache.cpp',
     'StorageDBThread.cpp',
     'StorageDBUpdater.cpp',
     'StorageIPC.cpp',
     'StorageManager.cpp',
     'StorageObserver.cpp',