Commit 932e3b11 authored by Kathleen Brade's avatar Kathleen Brade Committed by Georg Koppen
Browse files

Bug #6564: Isolate DOM storage to first party URI.

Also prevent DOM storage from ever writing to disk.
parent e6a755ba
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -112,6 +112,8 @@ let SessionStorageInternal = {
      // There is no need to pass documentURI, it's only used to fill documentURI property of
      // domstorage event, which in this case has no consumer. Prevention of events in case
      // of missing documentURI will be solved in a followup bug to bug 600307.
      // TODO: We should call createStorageForFirstParty() here.  See comment
      //       inside _readEntry() for details.
      let storage = storageManager.createStorage(window, principal, "", aDocShell.usePrivateBrowsing);

      for (let key of Object.keys(data)) {
@@ -140,6 +142,11 @@ let SessionStorageInternal = {

    try {
      let storageManager = aDocShell.QueryInterface(Ci.nsIDOMStorageManager);
      // TODO: We should call getStorageForFirstParty() here, but we need an
      //       nsIDocument to call thirdPartyUtil.getFirstPartyURI(), and
      //       unfortunately nsIDocument is not exposed to JavaScript.
      //       However, this code is not called in TBB because the
      //       browser.sessionstore.privacy_level pref. is set to 2.
      storage = storageManager.getStorage(window, aPrincipal);
    } catch (e) {
      // sessionStorage might throw if it's turned off, see bug 458954
+19 −3
Original line number Diff line number Diff line
@@ -171,6 +171,7 @@
#include "nsIContentSecurityPolicy.h"
#include "nsILoadInfo.h"
#include "nsSandboxFlags.h"
#include "mozIThirdPartyUtil.h"
#include "nsXULAppAPI.h"
#include "nsDOMNavigationTiming.h"
#include "nsISecurityUITelemetry.h"
@@ -3177,14 +3178,29 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,

  nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(GetAsSupports(this));

  nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
    do_GetService(THIRDPARTYUTIL_CONTRACTID);
  if (!thirdPartyUtil)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDocument> doc(do_GetInterface(GetAsSupports(this)));
  nsCOMPtr<nsIURI> firstPartyIsolationURI;
  nsresult rv = thirdPartyUtil->GetFirstPartyIsolationURI(nullptr, doc,
                                                          getter_AddRefs(firstPartyIsolationURI));
  NS_ENSURE_SUCCESS(rv, rv);
  
  if (aCreate) {
    return manager->CreateStorage(domWin, aPrincipal, aDocumentURI,
    return manager->CreateStorageForFirstParty(domWin, firstPartyIsolationURI,
                                               aPrincipal, aDocumentURI,
                                               mInPrivateBrowsing, aStorage);
  }

  return manager->GetStorage(domWin, aPrincipal, mInPrivateBrowsing, aStorage);
  return manager->GetStorageForFirstParty(domWin, firstPartyIsolationURI, aPrincipal,
                                          mInPrivateBrowsing, aStorage);
}

// Bacause it is not called from anywhere, nsDocShell::AddSessionStorage()
// does not need to be modified to isolate DOM Storage to the first party URI.
nsresult
nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal, nsIDOMStorage* aStorage)
{
+49 −8
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@
#include "MessageEvent.h"
#include "nsAboutProtocolUtils.h"
#include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE
#include "mozIThirdPartyUtil.h"

// Interfaces Needed
#include "nsIFrame.h"
@@ -2759,6 +2760,11 @@ nsGlobalWindow::PreloadLocalStorage()
  }

  nsresult rv;
  nsCOMPtr<nsIURI> firstPartyIsolationURI;
  rv = GetFirstPartyIsolationURI(getter_AddRefs(firstPartyIsolationURI));
  if (NS_FAILED(rv)) {
    return;
  }

  nsCOMPtr<nsIDOMStorageManager> storageManager =
    do_GetService("@mozilla.org/dom/localStorage-manager;1", &rv);
@@ -2766,7 +2772,7 @@ nsGlobalWindow::PreloadLocalStorage()
    return;
  }

  storageManager->PrecacheStorage(principal);
  storageManager->PrecacheStorageForFirstParty(firstPartyIsolationURI, principal);
}

void
@@ -7888,6 +7894,19 @@ nsGlobalWindow::CallerInnerWindow()
  return static_cast<nsGlobalWindow*>(win.get());
}

nsresult
nsGlobalWindow::GetFirstPartyIsolationURI(nsIURI** aFirstPartyIsolationURI)
{
  nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
                               do_GetService(THIRDPARTYUTIL_CONTRACTID);
  if (!thirdPartyUtil)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDoc);
  return thirdPartyUtil->GetFirstPartyIsolationURI(NULL, doc, aFirstPartyIsolationURI);
}


/**
 * Class used to represent events generated by calls to Window.postMessage,
 * which asynchronously creates and dispatches events.
@@ -10552,7 +10571,16 @@ nsGlobalWindow::GetSessionStorage(ErrorResult& aError)
    nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);

    nsCOMPtr<nsIDOMStorage> storage;
    aError = storageManager->CreateStorage(this, principal, documentURI,

    nsCOMPtr<nsIURI> firstPartyIsolationURI;
    rv = GetFirstPartyIsolationURI(getter_AddRefs(firstPartyIsolationURI));
    if (NS_FAILED(rv)) {
      aError.Throw(rv);
      return nullptr;
    }

    aError = storageManager->CreateStorageForFirstParty(this, firstPartyIsolationURI,
                                                        principal, documentURI,
                                                        loadContext && loadContext->UsePrivateBrowsing(),
                                                        getter_AddRefs(storage));
    if (aError.Failed()) {
@@ -10633,11 +10661,18 @@ nsGlobalWindow::GetLocalStorage(ErrorResult& aError)
      mDoc->GetDocumentURI(documentURI);
    }

    nsCOMPtr<nsIURI> firstPartyIsolationURI;
    rv = GetFirstPartyIsolationURI(getter_AddRefs(firstPartyIsolationURI));
    if (NS_FAILED(rv)) {
      aError.Throw(rv);
      return nullptr;
    }

    nsIDocShell* docShell = GetDocShell();
    nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);

    nsCOMPtr<nsIDOMStorage> storage;
    aError = storageManager->CreateStorage(this, principal, documentURI,
    aError = storageManager->CreateStorageForFirstParty(this, firstPartyIsolationURI, principal, documentURI,
                                                        loadContext && loadContext->UsePrivateBrowsing(),
                                                        getter_AddRefs(storage));
    if (aError.Failed()) {
@@ -11470,7 +11505,13 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,

      nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(GetDocShell());
      if (storageManager) {
        rv = storageManager->CheckStorage(principal, istorage, &check);
        nsresult rv;
        nsCOMPtr<nsIURI> firstPartyIsolationURI;
        rv = GetFirstPartyIsolationURI(getter_AddRefs(firstPartyIsolationURI));
        NS_ENSURE_SUCCESS(rv, rv);

        rv = storageManager->CheckStorageForFirstParty(firstPartyIsolationURI,
                                          principal, changingStorage, &check);
        if (NS_FAILED(rv)) {
          return rv;
        }
+1 −0
Original line number Diff line number Diff line
@@ -971,6 +971,7 @@ public:
                                mozilla::ErrorResult& aError);
  void CancelAnimationFrame(int32_t aHandle, mozilla::ErrorResult& aError);
  nsPerformance* GetPerformance();
  nsresult GetFirstPartyIsolationURI(nsIURI** aFirstPartyIsolationURI);
#ifdef MOZ_WEBSPEECH
  mozilla::dom::SpeechSynthesis*
    GetSpeechSynthesis(mozilla::ErrorResult& aError);
+29 −3
Original line number Diff line number Diff line
@@ -8,20 +8,28 @@
interface nsIDOMStorage;
interface nsIPrincipal;
interface nsIDOMWindow;
interface nsIURI;

/**
 * General purpose interface that has two implementations, for localStorage
 * resp. sessionStorage with "@mozilla.org/dom/localStorage-manager;1" resp.
 * "@mozilla.org/dom/sessionStorage-manager;1" contract IDs.
 */
[scriptable, uuid(a15f7ebd-4f35-4e73-a2d8-255d27fd14ee)]
[scriptable, uuid(96dd7614-fcc8-4745-9a1d-52f44dea8818)]
interface nsIDOMStorageManager : nsISupports
{
  /**
   * This starts async preloading of a storage cache for scope
   * defined by the principal.
   *
   * @param aFirstPartyIsolationURI
   *    First party URI to bind storage to.
   * @param aPrincipal
   *    Principal to bind storage to.
   */
  void precacheStorage(in nsIPrincipal aPrincipal);
  void precacheStorageForFirstParty(in nsIURI aFirstPartyIsolationURI,
                                    in nsIPrincipal aPrincipal);

  /**
   * Returns instance of DOM storage object for given principal.
@@ -30,8 +38,10 @@ interface nsIDOMStorageManager : nsISupports
   *
   * @param aWindow
   *    The parent window.
   * @param aFirstPartyIsolationURI
   *    First party URI to bind storage to.
   * @param aPrincipal
   *    Principal to bound storage to.
   *    Principal to bind storage to.
   * @param aDocumentURI
   *    URL of the demanding document, used for DOM storage event only.
   * @param aPrivate
@@ -41,6 +51,11 @@ interface nsIDOMStorageManager : nsISupports
                              in nsIPrincipal aPrincipal,
                              in DOMString aDocumentURI,
                              [optional] in bool aPrivate);
  nsIDOMStorage createStorageForFirstParty(in nsIDOMWindow aWindow,
                                           in nsIURI aFirstPartyIsolationURI,
                                           in nsIPrincipal aPrincipal,
                                           in DOMString aDocumentURI,
                                           [optional] in bool aPrivate);
  /**
   * Returns instance of DOM storage object for given principal.
   * If there is no storage managed for the scope, then null is returned and
@@ -49,14 +64,20 @@ interface nsIDOMStorageManager : nsISupports
   *
   * @param aWindow
   *    The parent window.
   * @param aFirstPartyIsolationURI
   *    First party URI to bind storage to.
   * @param aPrincipal
   *    Principal to bound storage to.
   *    Principal to bind storage to.
   * @param aPrivate
   *    Whether the demanding document is running in Private Browsing mode or not.
   */
  nsIDOMStorage getStorage(in nsIDOMWindow aWindow,
                           in nsIPrincipal aPrincipal,
                           [optional] in bool aPrivate);
  nsIDOMStorage getStorageForFirstParty(in nsIDOMWindow aWindow,
                                        in nsIURI aFirstPartyIsolationURI,
                                        in nsIPrincipal aPrincipal,
                                        [optional] in bool aPrivate);

  /**
   * Clones given storage into this storage manager.
@@ -73,6 +94,8 @@ interface nsIDOMStorageManager : nsISupports
   * Returns true if the storage belongs to the given principal and is managed
   * (i.e. has been created and is cached) by this storage manager.
   *
   * @param aFirstPartyIsolationURI
   *    First party URI to check the storage against.
   * @param aPrincipal
   *    Principal to check the storage against.
   * @param aStorage
@@ -85,6 +108,9 @@ interface nsIDOMStorageManager : nsISupports
   */
  bool checkStorage(in nsIPrincipal aPrincipal,
                    in nsIDOMStorage aStorage);
  bool checkStorageForFirstParty(in nsIURI aFirstPartyIsolationURI,
                                 in nsIPrincipal aPrincipal,
                                 in nsIDOMStorage aStorage);

  /**
   * @deprecated
Loading