Commit e72c7d09 authored by Kathleen Brade's avatar Kathleen Brade Committed by Mike Perry
Browse files

Isolate DOM storage to first party URI.

Also prevent DOM storage from ever writing to disk.
parent d12f3386
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -90,6 +90,8 @@ let DomStorage = {
      // 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(principal, "", aDocShell.usePrivateBrowsing);

      for (let [key, value] in Iterator(data)) {
@@ -116,6 +118,11 @@ let DomStorage = {

    try {
      let storageManager = aDocShell.QueryInterface(Components.interfaces.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(aPrincipal);
    } catch (e) {
      // sessionStorage might throw if it's turned off, see bug 458954
+18 −2
Original line number Diff line number Diff line
@@ -193,6 +193,7 @@
#include "nsIChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsSandboxFlags.h"
#include "mozIThirdPartyUtil.h"

#include "nsXULAppAPI.h"

@@ -2691,14 +2692,29 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
        return NS_ERROR_UNEXPECTED;
    }

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

    nsCOMPtr<nsIDocument> doc(do_GetInterface(GetAsSupports(this)));
    nsCOMPtr<nsIURI> firstPartyURI;
    nsresult rv = thirdPartyUtil->GetFirstPartyURI(nullptr, doc,
                                           getter_AddRefs(firstPartyURI));
    NS_ENSURE_SUCCESS(rv, rv);

    if (aCreate) {
        return manager->CreateStorage(aPrincipal, aDocumentURI,
        return manager->CreateStorageForFirstParty(firstPartyURI,
                                      aPrincipal, aDocumentURI,
                                      mInPrivateBrowsing, aStorage);
    }

    return manager->GetStorage(aPrincipal, mInPrivateBrowsing, aStorage);
    return manager->GetStorageForFirstParty(firstPartyURI, 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)
+36 −4
Original line number Diff line number Diff line
@@ -2604,6 +2604,11 @@ nsGlobalWindow::PreloadLocalStorage()
  }

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

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

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

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

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

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


/**
 * Class used to represent events generated by calls to Window.postMessage,
 * which asynchronously creates and dispatches events.
@@ -8966,7 +8984,11 @@ nsGlobalWindow::GetSessionStorage(nsIDOMStorage ** aSessionStorage)

    nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);

    rv = storageManager->CreateStorage(principal,
    nsCOMPtr<nsIURI> firstPartyURI;
    rv = GetFirstPartyURI(getter_AddRefs(firstPartyURI));
    NS_ENSURE_SUCCESS(rv, rv);

    rv = storageManager->CreateStorageForFirstParty(firstPartyURI, principal,
                                       documentURI,
                                       loadContext && loadContext->UsePrivateBrowsing(),
                                       getter_AddRefs(mSessionStorage));
@@ -9034,10 +9056,14 @@ nsGlobalWindow::GetLocalStorage(nsIDOMStorage ** aLocalStorage)
      mDoc->GetDocumentURI(documentURI);
    }

    nsCOMPtr<nsIURI> firstPartyURI;
    rv = GetFirstPartyURI(getter_AddRefs(firstPartyURI));
    NS_ENSURE_SUCCESS(rv, rv);

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

    rv = storageManager->CreateStorage(principal,
    rv = storageManager->CreateStorageForFirstParty(firstPartyURI, principal,
                                       documentURI,
                                       loadContext && loadContext->UsePrivateBrowsing(),
                                       getter_AddRefs(mLocalStorage));
@@ -9654,7 +9680,13 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,

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

        rv = storageManager->CheckStorageForFirstParty(firstPartyURI,
                                          principal, changingStorage, &check);
        NS_ENSURE_SUCCESS(rv, rv);
      }

+2 −0
Original line number Diff line number Diff line
@@ -1092,6 +1092,8 @@ protected:
  nsresult RequestAnimationFrame(const nsIDocument::FrameRequestCallbackHolder& aCallback,
                                 int32_t* aHandle);

  nsresult GetFirstPartyURI(nsIURI** aFirstPartyURI);

  // When adding new member variables, be careful not to create cycles
  // through JavaScript.  If there is any chance that a member variable
  // could own objects that are implemented in JavaScript, then those
+23 −1
Original line number Diff line number Diff line
@@ -7,26 +7,36 @@

interface nsIDOMStorage;
interface nsIPrincipal;
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(8096f9ea-fa61-4960-b5d7-fb30ac42c8d8)]
[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 aFirstPartyURI
   *    First party URI to bound storage to.
   * @param aPrincipal
   *    Principal to bound storage to.
   */
  void precacheStorage(in nsIPrincipal aPrincipal);
  void precacheStorageForFirstParty(in nsIURI aFirstPartyURI,
                                    in nsIPrincipal aPrincipal);

  /**
   * Returns instance of DOM storage object for given principal.
   * A new object is always returned and it is ensured there is
   * a storage for the scope created.
   *
   * @param aFirstPartyURI
   *    First party URI to bound storage to.
   * @param aPrincipal
   *    Principal to bound storage to.
   * @param aDocumentURI
@@ -37,6 +47,10 @@ interface nsIDOMStorageManager : nsISupports
  nsIDOMStorage createStorage(in nsIPrincipal aPrincipal,
                              in DOMString aDocumentURI,
                              [optional] in bool aPrivate);
  nsIDOMStorage createStorageForFirstParty(in nsIURI aFirstPartyURI,
                                           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
@@ -50,6 +64,9 @@ interface nsIDOMStorageManager : nsISupports
   */
  nsIDOMStorage getStorage(in nsIPrincipal aPrincipal,
                           [optional] in bool aPrivate);
  nsIDOMStorage getStorageForFirstParty(in nsIURI aFirstPartyURI,
                                        in nsIPrincipal aPrincipal,
                                        [optional] in bool aPrivate);

  /**
   * Clones given storage into this storage manager.
@@ -66,6 +83,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 aFirstPartyURI
   *    First party URI to check the storage against.
   * @param aPrincipal
   *    Principal to check the storage against.
   * @param aStorage
@@ -78,6 +97,9 @@ interface nsIDOMStorageManager : nsISupports
   */
  bool checkStorage(in nsIPrincipal aPrincipal,
                    in nsIDOMStorage aStorage);
  bool checkStorageForFirstParty(in nsIURI aFirstPartyURI,
                                 in nsIPrincipal aPrincipal,
                                 in nsIDOMStorage aStorage);

  /**
   * @deprecated
Loading