xpcom/glue/nsCategoryCache.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* vim:set st=2 sts=2 ts=2 et cin: */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsIObserverService.h"
     7 #include "mozilla/Services.h"
     8 #include "nsISupportsPrimitives.h"
     9 #include "nsIStringEnumerator.h"
    11 #include "nsXPCOMCID.h"
    13 #include "nsCategoryCache.h"
    15 nsCategoryObserver::nsCategoryObserver(const char* aCategory)
    16   : mCategory(aCategory)
    17   , mObserversRemoved(false)
    18 {
    19   // First, enumerate the currently existing entries
    20   nsCOMPtr<nsICategoryManager> catMan =
    21     do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
    22   if (!catMan)
    23     return;
    25   nsCOMPtr<nsISimpleEnumerator> enumerator;
    26   nsresult rv = catMan->EnumerateCategory(aCategory,
    27                                           getter_AddRefs(enumerator));
    28   if (NS_FAILED(rv))
    29     return;
    31   nsCOMPtr<nsIUTF8StringEnumerator> strings = do_QueryInterface(enumerator);
    32   MOZ_ASSERT(strings);
    34   bool more;
    35   while (NS_SUCCEEDED(strings->HasMore(&more)) && more) {
    36     nsAutoCString entryName;
    37     strings->GetNext(entryName);
    39     nsCString entryValue;
    40     rv = catMan->GetCategoryEntry(aCategory,
    41 				  entryName.get(),
    42 				  getter_Copies(entryValue));
    43     if (NS_SUCCEEDED(rv)) {
    44       nsCOMPtr<nsISupports> service = do_GetService(entryValue.get());
    45       if (service) {
    46 	mHash.Put(entryName, service);
    47       }
    48     }
    49   }
    51   // Now, listen for changes
    52   nsCOMPtr<nsIObserverService> serv =
    53     mozilla::services::GetObserverService();
    54   if (serv) {
    55     serv->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
    56     serv->AddObserver(this, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID, false);
    57     serv->AddObserver(this, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID, false);
    58     serv->AddObserver(this, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID, false);
    59   }
    60 }
    62 nsCategoryObserver::~nsCategoryObserver() {
    63 }
    65 NS_IMPL_ISUPPORTS(nsCategoryObserver, nsIObserver)
    67 void
    68 nsCategoryObserver::ListenerDied() {
    69   RemoveObservers();
    70 }
    72 void
    73 nsCategoryObserver::RemoveObservers() {
    74   if (mObserversRemoved)
    75     return;
    77   mObserversRemoved = true;
    78   nsCOMPtr<nsIObserverService> obsSvc =
    79     mozilla::services::GetObserverService();
    80   if (obsSvc) {
    81     obsSvc->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
    82     obsSvc->RemoveObserver(this, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID);
    83     obsSvc->RemoveObserver(this, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID);
    84     obsSvc->RemoveObserver(this, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID);
    85   }
    86 }
    88 NS_IMETHODIMP
    89 nsCategoryObserver::Observe(nsISupports* aSubject, const char* aTopic,
    90                             const char16_t* aData) {
    91   if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
    92     mHash.Clear();
    93     RemoveObservers();
    95     return NS_OK;
    96   }
    98   if (!aData ||
    99       !nsDependentString(aData).Equals(NS_ConvertASCIItoUTF16(mCategory)))
   100     return NS_OK;
   102   nsAutoCString str;
   103   nsCOMPtr<nsISupportsCString> strWrapper(do_QueryInterface(aSubject));
   104   if (strWrapper)
   105     strWrapper->GetData(str);
   107   if (strcmp(aTopic, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID) == 0) {
   108     // We may get an add notification even when we already have an entry. This
   109     // is due to the notification happening asynchronously, so if the entry gets
   110     // added and an nsCategoryObserver gets instantiated before events get
   111     // processed, we'd get the notification for an existing entry.
   112     // Do nothing in that case.
   113     if (mHash.GetWeak(str))
   114       return NS_OK;
   116     nsCOMPtr<nsICategoryManager> catMan =
   117       do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
   118     if (!catMan)
   119       return NS_OK;
   121     nsCString entryValue;
   122     catMan->GetCategoryEntry(mCategory.get(),
   123                              str.get(),
   124                              getter_Copies(entryValue));
   126     nsCOMPtr<nsISupports> service = do_GetService(entryValue.get());
   128     if (service) {
   129       mHash.Put(str, service);
   130     }
   131   } else if (strcmp(aTopic, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID) == 0) {
   132     mHash.Remove(str);
   133   } else if (strcmp(aTopic, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID) == 0) {
   134     mHash.Clear();
   135   }
   136   return NS_OK;
   137 }

mercurial