startupcache/StartupCacheUtils.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "nsCOMPtr.h"
     6 #include "nsIInputStream.h"
     7 #include "nsIStringStream.h"
     8 #include "nsNetUtil.h"
     9 #include "nsIJARURI.h"
    10 #include "nsIResProtocolHandler.h"
    11 #include "nsIChromeRegistry.h"
    12 #include "nsAutoPtr.h"
    13 #include "StartupCacheUtils.h"
    14 #include "mozilla/scache/StartupCache.h"
    15 #include "mozilla/Omnijar.h"
    17 namespace mozilla {
    18 namespace scache {
    20 NS_EXPORT nsresult
    21 NewObjectInputStreamFromBuffer(char* buffer, uint32_t len, 
    22                                nsIObjectInputStream** stream)
    23 {
    24   nsCOMPtr<nsIStringInputStream> stringStream
    25     = do_CreateInstance("@mozilla.org/io/string-input-stream;1");
    26   nsCOMPtr<nsIObjectInputStream> objectInput 
    27     = do_CreateInstance("@mozilla.org/binaryinputstream;1");
    29   stringStream->AdoptData(buffer, len);
    30   objectInput->SetInputStream(stringStream);
    32   objectInput.forget(stream);
    33   return NS_OK;
    34 }
    36 NS_EXPORT nsresult
    37 NewObjectOutputWrappedStorageStream(nsIObjectOutputStream **wrapperStream,
    38                                     nsIStorageStream** stream,
    39                                     bool wantDebugStream)
    40 {
    41   nsCOMPtr<nsIStorageStream> storageStream;
    43   nsresult rv = NS_NewStorageStream(256, UINT32_MAX, getter_AddRefs(storageStream));
    44   NS_ENSURE_SUCCESS(rv, rv);
    46   nsCOMPtr<nsIObjectOutputStream> objectOutput
    47     = do_CreateInstance("@mozilla.org/binaryoutputstream;1");
    48   nsCOMPtr<nsIOutputStream> outputStream
    49     = do_QueryInterface(storageStream);
    51   objectOutput->SetOutputStream(outputStream);
    53 #ifdef DEBUG
    54   if (wantDebugStream) {
    55     // Wrap in debug stream to detect unsupported writes of 
    56     // multiply-referenced non-singleton objects
    57     StartupCache* sc = StartupCache::GetSingleton();
    58     NS_ENSURE_TRUE(sc, NS_ERROR_UNEXPECTED);
    59     nsCOMPtr<nsIObjectOutputStream> debugStream;
    60     sc->GetDebugObjectOutputStream(objectOutput, getter_AddRefs(debugStream));
    61     debugStream.forget(wrapperStream);
    62   } else {
    63     objectOutput.forget(wrapperStream);
    64   }
    65 #else
    66   objectOutput.forget(wrapperStream);
    67 #endif
    69   storageStream.forget(stream);
    70   return NS_OK;
    71 }
    73 NS_EXPORT nsresult
    74 NewBufferFromStorageStream(nsIStorageStream *storageStream, 
    75                            char** buffer, uint32_t* len) 
    76 {
    77   nsresult rv;
    78   nsCOMPtr<nsIInputStream> inputStream;
    79   rv = storageStream->NewInputStream(0, getter_AddRefs(inputStream));
    80   NS_ENSURE_SUCCESS(rv, rv);
    82   uint64_t avail64;
    83   rv = inputStream->Available(&avail64);
    84   NS_ENSURE_SUCCESS(rv, rv);
    85   NS_ENSURE_TRUE(avail64 <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
    87   uint32_t avail = (uint32_t)avail64;
    88   nsAutoArrayPtr<char> temp (new char[avail]);
    89   uint32_t read;
    90   rv = inputStream->Read(temp, avail, &read);
    91   if (NS_SUCCEEDED(rv) && avail != read)
    92     rv = NS_ERROR_UNEXPECTED;
    94   if (NS_FAILED(rv)) {
    95     return rv;
    96   }
    98   *len = avail;
    99   *buffer = temp.forget();
   100   return NS_OK;
   101 }
   103 static const char baseName[2][5] = { "gre/", "app/" };
   105 static inline bool
   106 canonicalizeBase(nsAutoCString &spec,
   107                  nsACString &out)
   108 {
   109     nsAutoCString greBase, appBase;
   110     nsresult rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::GRE, greBase);
   111     if (NS_FAILED(rv) || !greBase.Length())
   112         return false;
   114     rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::APP, appBase);
   115     if (NS_FAILED(rv))
   116         return false;
   118     bool underGre = !greBase.Compare(spec.get(), false, greBase.Length());
   119     bool underApp = appBase.Length() &&
   120                     !appBase.Compare(spec.get(), false, appBase.Length());
   122     if (!underGre && !underApp)
   123         return false;
   125     /**
   126      * At this point, if both underGre and underApp are true, it can be one
   127      * of the two following cases:
   128      * - the GRE directory points to a subdirectory of the APP directory,
   129      *   meaning spec points under GRE.
   130      * - the APP directory points to a subdirectory of the GRE directory,
   131      *   meaning spec points under APP.
   132      * Checking the GRE and APP path length is enough to know in which case
   133      * we are.
   134      */
   135     if (underGre && underApp && greBase.Length() < appBase.Length())
   136         underGre = false;
   138     out.Append("/resource/");
   139     out.Append(baseName[underGre ? mozilla::Omnijar::GRE : mozilla::Omnijar::APP]);
   140     out.Append(Substring(spec, underGre ? greBase.Length() : appBase.Length()));
   141     return true;
   142 }
   144 /**
   145  * PathifyURI transforms uris into useful zip paths
   146  * to make it easier to manipulate startup cache entries
   147  * using standard zip tools.
   148  * Transformations applied:
   149  *  * resource:// URIs are resolved to their corresponding file/jar URI to
   150  *    canonicalize resources URIs other than gre and app.
   151  *  * Paths under GRE or APP directory have their base path replaced with
   152  *    resource/gre or resource/app to avoid depending on install location.
   153  *  * jar:file:///path/to/file.jar!/sub/path urls are replaced with
   154  *    /path/to/file.jar/sub/path
   155  *
   156  *  The result is appended to the string passed in. Adding a prefix before
   157  *  calling is recommended to avoid colliding with other cache users.
   158  *
   159  * For example, in the js loader (string is prefixed with jsloader by caller):
   160  *  resource://gre/modules/XPCOMUtils.jsm or
   161  *  file://$GRE_DIR/modules/XPCOMUtils.jsm or
   162  *  jar:file://$GRE_DIR/omni.jar!/modules/XPCOMUtils.jsm becomes
   163  *     jsloader/resource/gre/modules/XPCOMUtils.jsm
   164  *  file://$PROFILE_DIR/extensions/{uuid}/components/component.js becomes
   165  *     jsloader/$PROFILE_DIR/extensions/%7Buuid%7D/components/component.js
   166  *  jar:file://$PROFILE_DIR/extensions/some.xpi!/components/component.js becomes
   167  *     jsloader/$PROFILE_DIR/extensions/some.xpi/components/component.js
   168  */
   169 NS_EXPORT nsresult
   170 PathifyURI(nsIURI *in, nsACString &out)
   171 {
   172     bool equals;
   173     nsresult rv;
   174     nsCOMPtr<nsIURI> uri = in;
   175     nsAutoCString spec;
   177     // Resolve resource:// URIs. At the end of this if/else block, we
   178     // have both spec and uri variables identifying the same URI.
   179     if (NS_SUCCEEDED(in->SchemeIs("resource", &equals)) && equals) {
   180         nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
   181         NS_ENSURE_SUCCESS(rv, rv);
   183         nsCOMPtr<nsIProtocolHandler> ph;
   184         rv = ioService->GetProtocolHandler("resource", getter_AddRefs(ph));
   185         NS_ENSURE_SUCCESS(rv, rv);
   187         nsCOMPtr<nsIResProtocolHandler> irph(do_QueryInterface(ph, &rv));
   188         NS_ENSURE_SUCCESS(rv, rv);
   190         rv = irph->ResolveURI(in, spec);
   191         NS_ENSURE_SUCCESS(rv, rv);
   193         rv = ioService->NewURI(spec, nullptr, nullptr, getter_AddRefs(uri));
   194         NS_ENSURE_SUCCESS(rv, rv);
   195     } else {
   196         if (NS_SUCCEEDED(in->SchemeIs("chrome", &equals)) && equals) {
   197             nsCOMPtr<nsIChromeRegistry> chromeReg =
   198                 mozilla::services::GetChromeRegistryService();
   199             if (!chromeReg)
   200                 return NS_ERROR_UNEXPECTED;
   202             rv = chromeReg->ConvertChromeURL(in, getter_AddRefs(uri));
   203             NS_ENSURE_SUCCESS(rv, rv);
   204         }
   206         rv = uri->GetSpec(spec);
   207         NS_ENSURE_SUCCESS(rv, rv);
   208     }
   210     if (!canonicalizeBase(spec, out)) {
   211         if (NS_SUCCEEDED(uri->SchemeIs("file", &equals)) && equals) {
   212             nsCOMPtr<nsIFileURL> baseFileURL;
   213             baseFileURL = do_QueryInterface(uri, &rv);
   214             NS_ENSURE_SUCCESS(rv, rv);
   216             nsAutoCString path;
   217             rv = baseFileURL->GetPath(path);
   218             NS_ENSURE_SUCCESS(rv, rv);
   220             out.Append(path);
   221         } else if (NS_SUCCEEDED(uri->SchemeIs("jar", &equals)) && equals) {
   222             nsCOMPtr<nsIJARURI> jarURI = do_QueryInterface(uri, &rv);
   223             NS_ENSURE_SUCCESS(rv, rv);
   225             nsCOMPtr<nsIURI> jarFileURI;
   226             rv = jarURI->GetJARFile(getter_AddRefs(jarFileURI));
   227             NS_ENSURE_SUCCESS(rv, rv);
   229             rv = PathifyURI(jarFileURI, out);
   230             NS_ENSURE_SUCCESS(rv, rv);
   232             nsAutoCString path;
   233             rv = jarURI->GetJAREntry(path);
   234             NS_ENSURE_SUCCESS(rv, rv);
   235             out.Append("/");
   236             out.Append(path);
   237         } else { // Very unlikely
   238             nsAutoCString spec;
   239             rv = uri->GetSpec(spec);
   240             NS_ENSURE_SUCCESS(rv, rv);
   242             out.Append("/");
   243             out.Append(spec);
   244         }
   245     }
   246     return NS_OK;
   247 }
   249 }
   250 }

mercurial