LCOV - code coverage report
Current view: top level - startupcache - StartupCacheUtils.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 59 112 52.7 %
Date: 2017-07-14 16:53:18 Functions: 5 7 71.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13