netwerk/cache2/OldWrappers.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 // Stuff to link the old imp to the new api - will go away!
     3 #include "CacheLog.h"
     4 #include "OldWrappers.h"
     5 #include "CacheStorage.h"
     6 #include "CacheStorageService.h"
     7 #include "LoadContextInfo.h"
     9 #include "nsIURI.h"
    10 #include "nsICacheService.h"
    11 #include "nsICacheSession.h"
    12 #include "nsIApplicationCache.h"
    13 #include "nsIApplicationCacheService.h"
    14 #include "nsIStreamTransportService.h"
    15 #include "nsIFile.h"
    16 #include "nsICacheEntryDoomCallback.h"
    17 #include "nsICacheListener.h"
    18 #include "nsICacheStorageVisitor.h"
    20 #include "nsServiceManagerUtils.h"
    21 #include "nsNetCID.h"
    22 #include "nsProxyRelease.h"
    23 #include "mozilla/Telemetry.h"
    25 static NS_DEFINE_CID(kStreamTransportServiceCID,
    26                      NS_STREAMTRANSPORTSERVICE_CID);
    28 static uint32_t const CHECK_MULTITHREADED = nsICacheStorage::CHECK_MULTITHREADED;
    30 namespace mozilla {
    31 namespace net {
    33 namespace { // anon
    35 // Fires the doom callback back on the main thread
    36 // after the cache I/O thread is looped.
    38 class DoomCallbackSynchronizer : public nsRunnable
    39 {
    40 public:
    41   DoomCallbackSynchronizer(nsICacheEntryDoomCallback* cb) : mCB(cb)
    42   {
    43     MOZ_COUNT_CTOR(DoomCallbackSynchronizer);
    44   }
    45   nsresult Dispatch();
    47 private:
    48   virtual ~DoomCallbackSynchronizer()
    49   {
    50     MOZ_COUNT_DTOR(DoomCallbackSynchronizer);
    51   }
    53   NS_DECL_NSIRUNNABLE
    54   nsCOMPtr<nsICacheEntryDoomCallback> mCB;
    55 };
    57 nsresult DoomCallbackSynchronizer::Dispatch()
    58 {
    59   nsresult rv;
    61   nsCOMPtr<nsICacheService> serv =
    62       do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
    63   NS_ENSURE_SUCCESS(rv, rv);
    65   nsCOMPtr<nsIEventTarget> eventTarget;
    66   rv = serv->GetCacheIOTarget(getter_AddRefs(eventTarget));
    67   NS_ENSURE_SUCCESS(rv, rv);
    69   rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
    70   NS_ENSURE_SUCCESS(rv, rv);
    72   return NS_OK;
    73 }
    75 NS_IMETHODIMP DoomCallbackSynchronizer::Run()
    76 {
    77   if (!NS_IsMainThread()) {
    78     NS_DispatchToMainThread(this);
    79   }
    80   else {
    81     if (mCB)
    82       mCB->OnCacheEntryDoomed(NS_OK);
    83   }
    84   return NS_OK;
    85 }
    87 // Receives doom callback from the old API and forwards to the new API
    89 class DoomCallbackWrapper : public nsICacheListener
    90 {
    91   NS_DECL_THREADSAFE_ISUPPORTS
    92   NS_DECL_NSICACHELISTENER
    94   DoomCallbackWrapper(nsICacheEntryDoomCallback* cb) : mCB(cb)
    95   {
    96     MOZ_COUNT_CTOR(DoomCallbackWrapper);
    97   }
    99 private:
   100   virtual ~DoomCallbackWrapper()
   101   {
   102     MOZ_COUNT_DTOR(DoomCallbackWrapper);
   103   }
   105   nsCOMPtr<nsICacheEntryDoomCallback> mCB;
   106 };
   108 NS_IMPL_ISUPPORTS(DoomCallbackWrapper, nsICacheListener);
   110 NS_IMETHODIMP DoomCallbackWrapper::OnCacheEntryAvailable(nsICacheEntryDescriptor *descriptor,
   111                                                          nsCacheAccessMode accessGranted,
   112                                                          nsresult status)
   113 {
   114   return NS_OK;
   115 }
   117 NS_IMETHODIMP DoomCallbackWrapper::OnCacheEntryDoomed(nsresult status)
   118 {
   119   if (!mCB)
   120     return NS_ERROR_NULL_POINTER;
   122   mCB->OnCacheEntryDoomed(status);
   123   mCB = nullptr;
   124   return NS_OK;
   125 }
   127 // Receives visit callbacks from the old API and forwards it to the new API
   129 class VisitCallbackWrapper : public nsICacheVisitor
   130 {
   131   NS_DECL_THREADSAFE_ISUPPORTS
   132   NS_DECL_NSICACHEVISITOR
   134   VisitCallbackWrapper(char* const deviceID,
   135                        nsICacheStorageVisitor* cb,
   136                        bool visitEntries)
   137   : mCB(cb)
   138   , mVisitEntries(visitEntries)
   139   , mDeviceID(deviceID)
   140   {
   141     MOZ_COUNT_CTOR(VisitCallbackWrapper);
   142   }
   144 private:
   145   virtual ~VisitCallbackWrapper();
   146   nsCOMPtr<nsICacheStorageVisitor> mCB;
   147   bool mVisitEntries;
   148   char* const mDeviceID;
   149 };
   151 NS_IMPL_ISUPPORTS(VisitCallbackWrapper, nsICacheVisitor)
   153 VisitCallbackWrapper::~VisitCallbackWrapper()
   154 {
   155   if (mVisitEntries)
   156     mCB->OnCacheEntryVisitCompleted();
   158   MOZ_COUNT_DTOR(VisitCallbackWrapper);
   159 }
   161 NS_IMETHODIMP VisitCallbackWrapper::VisitDevice(const char * deviceID,
   162                                                 nsICacheDeviceInfo *deviceInfo,
   163                                                 bool *_retval)
   164 {
   165   if (!mCB)
   166     return NS_ERROR_NULL_POINTER;
   168   *_retval = false;
   169   if (strcmp(deviceID, mDeviceID)) {
   170     // Not the device we want to visit
   171     return NS_OK;
   172   }
   174   nsresult rv;
   176   uint32_t entryCount;
   177   rv = deviceInfo->GetEntryCount(&entryCount);
   178   NS_ENSURE_SUCCESS(rv, rv);
   180   uint32_t totalSize;
   181   rv = deviceInfo->GetTotalSize(&totalSize);
   182   NS_ENSURE_SUCCESS(rv, rv);
   184   mCB->OnCacheStorageInfo(entryCount, totalSize);
   185   *_retval = mVisitEntries;
   187   return NS_OK;
   188 }
   190 NS_IMETHODIMP VisitCallbackWrapper::VisitEntry(const char * deviceID,
   191                                                nsICacheEntryInfo *entryInfo,
   192                                                bool *_retval)
   193 {
   194   MOZ_ASSERT(!strcmp(deviceID, mDeviceID));
   196   nsRefPtr<_OldCacheEntryWrapper> wrapper = new _OldCacheEntryWrapper(entryInfo);
   197   nsresult rv = mCB->OnCacheEntryInfo(wrapper);
   198   *_retval = NS_SUCCEEDED(rv);
   200   return NS_OK;
   201 }
   203 } // anon
   206 // _OldGetDiskConsumption
   208 //static
   209 nsresult _OldGetDiskConsumption::Get(nsICacheStorageConsumptionObserver* aCallback)
   210 {
   211   nsresult rv;
   213   nsCOMPtr<nsICacheService> serv =
   214       do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
   215   NS_ENSURE_SUCCESS(rv, rv);
   217   nsRefPtr<_OldGetDiskConsumption> cb = new _OldGetDiskConsumption(aCallback);
   219   // _OldGetDiskConsumption stores the found size value, but until dispatched
   220   // to the main thread it doesn't call on the consupmtion observer. See bellow.
   221   rv = serv->VisitEntries(cb);
   222   NS_ENSURE_SUCCESS(rv, rv);
   224   // We are called from CacheStorageService::AsyncGetDiskConsumption whose IDL
   225   // documentation claims the callback is always delievered asynchronously
   226   // back to the main thread.  Despite we know the result synchronosusly when
   227   // querying the old cache, we need to stand the word and dispatch the result
   228   // to the main thread asynchronously.  Hence the dispatch here.
   229   return NS_DispatchToMainThread(cb);
   230 }
   232 NS_IMPL_ISUPPORTS_INHERITED(_OldGetDiskConsumption,
   233                             nsRunnable,
   234                             nsICacheVisitor)
   236 _OldGetDiskConsumption::_OldGetDiskConsumption(
   237   nsICacheStorageConsumptionObserver* aCallback)
   238   : mCallback(aCallback)
   239   , mSize(0)
   240 {
   241 }
   243 NS_IMETHODIMP
   244 _OldGetDiskConsumption::Run()
   245 {
   246   mCallback->OnNetworkCacheDiskConsumption(mSize);
   247   return NS_OK;
   248 }
   250 NS_IMETHODIMP
   251 _OldGetDiskConsumption::VisitDevice(const char * deviceID,
   252                                     nsICacheDeviceInfo *deviceInfo,
   253                                     bool *_retval)
   254 {
   255   if (!strcmp(deviceID, "disk")) {
   256     uint32_t size;
   257     nsresult rv = deviceInfo->GetTotalSize(&size);
   258     if (NS_SUCCEEDED(rv))
   259       mSize = (int64_t)size;
   260   }
   262   *_retval = false;
   263   return NS_OK;
   264 }
   266 NS_IMETHODIMP
   267 _OldGetDiskConsumption::VisitEntry(const char * deviceID,
   268                                    nsICacheEntryInfo *entryInfo,
   269                                    bool *_retval)
   270 {
   271   MOZ_CRASH("Unexpected");
   272   return NS_OK;
   273 }
   276 // _OldCacheEntryWrapper
   278 _OldCacheEntryWrapper::_OldCacheEntryWrapper(nsICacheEntryDescriptor* desc)
   279 : mOldDesc(desc), mOldInfo(desc)
   280 {
   281   MOZ_COUNT_CTOR(_OldCacheEntryWrapper);
   282   LOG(("Creating _OldCacheEntryWrapper %p for descriptor %p", this, desc));
   283 }
   285 _OldCacheEntryWrapper::_OldCacheEntryWrapper(nsICacheEntryInfo* info)
   286 : mOldDesc(nullptr), mOldInfo(info)
   287 {
   288   MOZ_COUNT_CTOR(_OldCacheEntryWrapper);
   289   LOG(("Creating _OldCacheEntryWrapper %p for info %p", this, info));
   290 }
   292 _OldCacheEntryWrapper::~_OldCacheEntryWrapper()
   293 {
   294   MOZ_COUNT_DTOR(_OldCacheEntryWrapper);
   295   LOG(("Destroying _OldCacheEntryWrapper %p for descriptor %p", this, mOldInfo.get()));
   296 }
   298 NS_IMPL_ISUPPORTS(_OldCacheEntryWrapper, nsICacheEntry)
   300 NS_IMETHODIMP _OldCacheEntryWrapper::AsyncDoom(nsICacheEntryDoomCallback* listener)
   301 {
   302   nsRefPtr<DoomCallbackWrapper> cb = listener
   303     ? new DoomCallbackWrapper(listener)
   304     : nullptr;
   305   return AsyncDoom(cb);
   306 }
   308 NS_IMETHODIMP _OldCacheEntryWrapper::GetDataSize(int64_t *aSize)
   309 {
   310   uint32_t size;
   311   nsresult rv = GetDataSize(&size);
   312   if (NS_FAILED(rv))
   313     return rv;
   315   *aSize = size;
   316   return NS_OK;
   317 }
   319 NS_IMETHODIMP _OldCacheEntryWrapper::GetPersistent(bool *aPersistToDisk)
   320 {
   321   if (!mOldDesc) {
   322     return NS_ERROR_NULL_POINTER;
   323   }
   325   nsresult rv;
   327   nsCacheStoragePolicy policy;
   328   rv = mOldDesc->GetStoragePolicy(&policy);
   329   NS_ENSURE_SUCCESS(rv, rv);
   331   *aPersistToDisk = policy != nsICache::STORE_IN_MEMORY;
   333   return NS_OK;
   334 }
   336 NS_IMETHODIMP _OldCacheEntryWrapper::Recreate(bool aMemoryOnly,
   337                                               nsICacheEntry** aResult)
   338 {
   339   NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NOT_AVAILABLE);
   341   nsCacheAccessMode mode;
   342   nsresult rv = mOldDesc->GetAccessGranted(&mode);
   343   NS_ENSURE_SUCCESS(rv, rv);
   345   if (!(mode & nsICache::ACCESS_WRITE))
   346     return NS_ERROR_NOT_AVAILABLE;
   348   LOG(("_OldCacheEntryWrapper::Recreate [this=%p]", this));
   350   if (aMemoryOnly)
   351     mOldDesc->SetStoragePolicy(nsICache::STORE_IN_MEMORY);
   353   nsCOMPtr<nsICacheEntry> self(this);
   354   self.forget(aResult);
   355   return NS_OK;
   356 }
   358 NS_IMETHODIMP _OldCacheEntryWrapper::OpenInputStream(int64_t offset,
   359                                                      nsIInputStream * *_retval)
   360 {
   361   if (offset > PR_UINT32_MAX)
   362     return NS_ERROR_INVALID_ARG;
   364   return OpenInputStream(uint32_t(offset), _retval);
   365 }
   366 NS_IMETHODIMP _OldCacheEntryWrapper::OpenOutputStream(int64_t offset,
   367                                                       nsIOutputStream * *_retval)
   368 {
   369   if (offset > PR_UINT32_MAX)
   370     return NS_ERROR_INVALID_ARG;
   372   return OpenOutputStream(uint32_t(offset), _retval);
   373 }
   375 NS_IMETHODIMP _OldCacheEntryWrapper::MaybeMarkValid()
   376 {
   377   LOG(("_OldCacheEntryWrapper::MaybeMarkValid [this=%p]", this));
   379   NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NULL_POINTER);
   381   nsCacheAccessMode mode;
   382   nsresult rv = mOldDesc->GetAccessGranted(&mode);
   383   NS_ENSURE_SUCCESS(rv, rv);
   385   if (mode & nsICache::ACCESS_WRITE) {
   386     LOG(("Marking cache entry valid [entry=%p, descr=%p]", this, mOldDesc));
   387     return mOldDesc->MarkValid();
   388   }
   390   LOG(("Not marking read-only cache entry valid [entry=%p, descr=%p]", this, mOldDesc));
   391   return NS_OK;
   392 }
   394 NS_IMETHODIMP _OldCacheEntryWrapper::HasWriteAccess(bool aWriteAllowed_unused, bool *aWriteAccess)
   395 {
   396   NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NULL_POINTER);
   397   NS_ENSURE_ARG(aWriteAccess);
   399   nsCacheAccessMode mode;
   400   nsresult rv = mOldDesc->GetAccessGranted(&mode);
   401   NS_ENSURE_SUCCESS(rv, rv);
   403   *aWriteAccess = !!(mode & nsICache::ACCESS_WRITE);
   405   LOG(("_OldCacheEntryWrapper::HasWriteAccess [this=%p, write-access=%d]", this, *aWriteAccess));
   407   return NS_OK;
   408 }
   411 namespace { // anon
   413 nsresult
   414 GetCacheSessionNameForStoragePolicy(
   415         nsCSubstring const &scheme,
   416         nsCacheStoragePolicy storagePolicy,
   417         bool isPrivate,
   418         uint32_t appId,
   419         bool inBrowser,
   420         nsACString& sessionName)
   421 {
   422   MOZ_ASSERT(!isPrivate || storagePolicy == nsICache::STORE_IN_MEMORY);
   424   // HTTP
   425   if (scheme.Equals(NS_LITERAL_CSTRING("http")) ||
   426       scheme.Equals(NS_LITERAL_CSTRING("https"))) {
   427     switch (storagePolicy) {
   428     case nsICache::STORE_IN_MEMORY:
   429       if (isPrivate)
   430         sessionName.Assign(NS_LITERAL_CSTRING("HTTP-memory-only-PB"));
   431       else
   432         sessionName.Assign(NS_LITERAL_CSTRING("HTTP-memory-only"));
   433       break;
   434     case nsICache::STORE_OFFLINE:
   435       // XXX This is actually never used, only added to prevent
   436       // any compatibility damage.
   437       sessionName.Assign(NS_LITERAL_CSTRING("HTTP-offline"));
   438       break;
   439     default:
   440       sessionName.Assign(NS_LITERAL_CSTRING("HTTP"));
   441       break;
   442     }
   443   }
   444   // WYCIWYG
   445   else if (scheme.Equals(NS_LITERAL_CSTRING("wyciwyg"))) {
   446     if (isPrivate)
   447       sessionName.Assign(NS_LITERAL_CSTRING("wyciwyg-private"));
   448     else
   449       sessionName.Assign(NS_LITERAL_CSTRING("wyciwyg"));
   450   }
   451   // FTP
   452   else if (scheme.Equals(NS_LITERAL_CSTRING("ftp"))) {
   453     if (isPrivate)
   454       sessionName.Assign(NS_LITERAL_CSTRING("FTP-private"));
   455     else
   456       sessionName.Assign(NS_LITERAL_CSTRING("FTP"));
   457   }
   458   // all remaining URL scheme
   459   else {
   460     // Since with the new API a consumer cannot specify its own session name
   461     // and partitioning of the cache is handled stricly only by the cache
   462     // back-end internally, we will use a separate session name to pretend
   463     // functionality of the new API wrapping the Darin's cache for all other
   464     // URL schemes.
   465     // Deliberately omitting |anonymous| since other session types don't
   466     // recognize it too.
   467     sessionName.Assign(NS_LITERAL_CSTRING("other"));
   468     if (isPrivate)
   469       sessionName.Append(NS_LITERAL_CSTRING("-private"));
   470   }
   472   if (appId != nsILoadContextInfo::NO_APP_ID || inBrowser) {
   473     sessionName.Append('~');
   474     sessionName.AppendInt(appId);
   475     sessionName.Append('~');
   476     sessionName.AppendInt(inBrowser);
   477   }
   479   return NS_OK;
   480 }
   482 nsresult
   483 GetCacheSession(nsCSubstring const &aScheme,
   484                 bool aWriteToDisk,
   485                 nsILoadContextInfo* aLoadInfo,
   486                 nsIApplicationCache* aAppCache,
   487                 nsICacheSession** _result)
   488 {
   489   nsresult rv;
   491   nsCacheStoragePolicy storagePolicy;
   492   if (aAppCache)
   493     storagePolicy = nsICache::STORE_OFFLINE;
   494   else if (!aWriteToDisk || aLoadInfo->IsPrivate())
   495     storagePolicy = nsICache::STORE_IN_MEMORY;
   496   else
   497     storagePolicy = nsICache::STORE_ANYWHERE;
   499   nsAutoCString clientId;
   500   if (aAppCache) {
   501     aAppCache->GetClientID(clientId);
   502   }
   503   else {
   504     rv = GetCacheSessionNameForStoragePolicy(
   505       aScheme,
   506       storagePolicy,
   507       aLoadInfo->IsPrivate(),
   508       aLoadInfo->AppId(),
   509       aLoadInfo->IsInBrowserElement(),
   510       clientId);
   511     NS_ENSURE_SUCCESS(rv, rv);
   512   }
   514   LOG(("  GetCacheSession for client=%s, policy=%d", clientId.get(), storagePolicy));
   516   nsCOMPtr<nsICacheService> serv =
   517       do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
   518   NS_ENSURE_SUCCESS(rv, rv);
   520   nsCOMPtr<nsICacheSession> session;
   521   rv = serv->CreateSession(clientId.get(),
   522                            storagePolicy,
   523                            nsICache::STREAM_BASED,
   524                            getter_AddRefs(session));
   525   NS_ENSURE_SUCCESS(rv, rv);
   527   rv = session->SetIsPrivate(aLoadInfo->IsPrivate());
   528   NS_ENSURE_SUCCESS(rv, rv);
   530   rv = session->SetDoomEntriesIfExpired(false);
   531   NS_ENSURE_SUCCESS(rv, rv);
   533   if (aAppCache) {
   534     nsCOMPtr<nsIFile> profileDirectory;
   535     aAppCache->GetProfileDirectory(getter_AddRefs(profileDirectory));
   536     if (profileDirectory)
   537       rv = session->SetProfileDirectory(profileDirectory);
   538     NS_ENSURE_SUCCESS(rv, rv);
   539   }
   541   session.forget(_result);
   542   return NS_OK;
   543 }
   545 } // anon
   548 NS_IMPL_ISUPPORTS_INHERITED(_OldCacheLoad, nsRunnable, nsICacheListener)
   550 _OldCacheLoad::_OldCacheLoad(nsCSubstring const& aScheme,
   551                              nsCSubstring const& aCacheKey,
   552                              nsICacheEntryOpenCallback* aCallback,
   553                              nsIApplicationCache* aAppCache,
   554                              nsILoadContextInfo* aLoadInfo,
   555                              bool aWriteToDisk,
   556                              uint32_t aFlags)
   557   : mScheme(aScheme)
   558   , mCacheKey(aCacheKey)
   559   , mCallback(aCallback)
   560   , mLoadInfo(GetLoadContextInfo(aLoadInfo))
   561   , mFlags(aFlags)
   562   , mWriteToDisk(aWriteToDisk)
   563   , mNew(true)
   564   , mOpening(true)
   565   , mSync(false)
   566   , mStatus(NS_ERROR_UNEXPECTED)
   567   , mRunCount(0)
   568   , mAppCache(aAppCache)
   569 {
   570   MOZ_COUNT_CTOR(_OldCacheLoad);
   571 }
   573 _OldCacheLoad::~_OldCacheLoad()
   574 {
   575   ProxyReleaseMainThread(mAppCache);
   576   MOZ_COUNT_DTOR(_OldCacheLoad);
   577 }
   579 nsresult _OldCacheLoad::Start()
   580 {
   581   LOG(("_OldCacheLoad::Start [this=%p, key=%s]", this, mCacheKey.get()));
   583   mLoadStart = mozilla::TimeStamp::Now();
   585   nsresult rv;
   587   // Consumers that can invoke this code as first and off the main thread
   588   // are responsible for initiating these two services on the main thread.
   589   // Currently this is only nsWyciwygChannel.
   591   // XXX: Start the cache service; otherwise DispatchToCacheIOThread will
   592   // fail.
   593   nsCOMPtr<nsICacheService> service =
   594     do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
   596   // Ensure the stream transport service gets initialized on the main thread
   597   if (NS_SUCCEEDED(rv) && NS_IsMainThread()) {
   598     nsCOMPtr<nsIStreamTransportService> sts =
   599       do_GetService(kStreamTransportServiceCID, &rv);
   600   }
   602   if (NS_SUCCEEDED(rv)) {
   603     rv = service->GetCacheIOTarget(getter_AddRefs(mCacheThread));
   604   }
   606   if (NS_SUCCEEDED(rv)) {
   607     bool onCacheTarget;
   608     rv = mCacheThread->IsOnCurrentThread(&onCacheTarget);
   609     if (NS_SUCCEEDED(rv) && onCacheTarget) {
   610       mSync = true;
   611     }
   612   }
   614   if (NS_SUCCEEDED(rv)) {
   615     if (mSync) {
   616       rv = Run();
   617     }
   618     else {
   619       rv = mCacheThread->Dispatch(this, NS_DISPATCH_NORMAL);
   620     }
   621   }
   623   return rv;
   624 }
   626 NS_IMETHODIMP
   627 _OldCacheLoad::Run()
   628 {
   629   LOG(("_OldCacheLoad::Run [this=%p, key=%s, cb=%p]", this, mCacheKey.get(), mCallback.get()));
   631   nsresult rv;
   633   if (mOpening) {
   634     mOpening = false;
   635     nsCOMPtr<nsICacheSession> session;
   636     rv = GetCacheSession(mScheme, mWriteToDisk, mLoadInfo, mAppCache,
   637                          getter_AddRefs(session));
   638     if (NS_SUCCEEDED(rv)) {
   639       // AsyncOpenCacheEntry isn't really async when its called on the
   640       // cache service thread.
   642       nsCacheAccessMode cacheAccess;
   643       if (mFlags & nsICacheStorage::OPEN_TRUNCATE)
   644         cacheAccess = nsICache::ACCESS_WRITE;
   645       else if ((mFlags & nsICacheStorage::OPEN_READONLY) || mAppCache)
   646         cacheAccess = nsICache::ACCESS_READ;
   647       else
   648         cacheAccess = nsICache::ACCESS_READ_WRITE;
   650       LOG(("  session->AsyncOpenCacheEntry with access=%d", cacheAccess));
   652       bool bypassBusy = mFlags & nsICacheStorage::OPEN_BYPASS_IF_BUSY;
   654       if (mSync && cacheAccess == nsICache::ACCESS_WRITE) {
   655         nsCOMPtr<nsICacheEntryDescriptor> entry;
   656         rv = session->OpenCacheEntry(mCacheKey, cacheAccess, bypassBusy,
   657           getter_AddRefs(entry));
   659         nsCacheAccessMode grantedAccess = 0;
   660         if (NS_SUCCEEDED(rv)) {
   661           entry->GetAccessGranted(&grantedAccess);
   662         }
   664         return OnCacheEntryAvailable(entry, grantedAccess, rv);
   665       }
   667       rv = session->AsyncOpenCacheEntry(mCacheKey, cacheAccess, this, bypassBusy);
   668       if (NS_SUCCEEDED(rv))
   669         return NS_OK;
   670     }
   672     // Opening failed, propagate the error to the consumer
   673     LOG(("  Opening cache entry failed with rv=0x%08x", rv));
   674     mStatus = rv;
   675     mNew = false;
   676     NS_DispatchToMainThread(this);
   677   } else {
   678     if (!mCallback) {
   679       LOG(("  duplicate call, bypassed"));
   680       return NS_OK;
   681     }
   683     if (NS_SUCCEEDED(mStatus)) {
   684       if (mFlags & nsICacheStorage::OPEN_TRUNCATE) {
   685         mozilla::Telemetry::AccumulateTimeDelta(
   686           mozilla::Telemetry::NETWORK_CACHE_V1_TRUNCATE_TIME_MS,
   687           mLoadStart);
   688       }
   689       else if (mNew) {
   690         mozilla::Telemetry::AccumulateTimeDelta(
   691           mozilla::Telemetry::NETWORK_CACHE_V1_MISS_TIME_MS,
   692           mLoadStart);
   693       }
   694       else {
   695         mozilla::Telemetry::AccumulateTimeDelta(
   696           mozilla::Telemetry::NETWORK_CACHE_V1_HIT_TIME_MS,
   697           mLoadStart);
   698       }
   699     }
   701     if (!(mFlags & CHECK_MULTITHREADED))
   702       Check();
   704     // break cycles
   705     nsCOMPtr<nsICacheEntryOpenCallback> cb = mCallback.forget();
   706     mCacheThread = nullptr;
   707     nsCOMPtr<nsICacheEntry> entry = mCacheEntry.forget();
   709     rv = cb->OnCacheEntryAvailable(entry, mNew, mAppCache, mStatus);
   711     if (NS_FAILED(rv) && entry) {
   712       LOG(("  cb->OnCacheEntryAvailable failed with rv=0x%08x", rv));
   713       if (mNew)
   714         entry->AsyncDoom(nullptr);
   715       else
   716         entry->Close();
   717     }
   718   }
   720   return rv;
   721 }
   723 NS_IMETHODIMP
   724 _OldCacheLoad::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry,
   725                                      nsCacheAccessMode access,
   726                                      nsresult status)
   727 {
   728   LOG(("_OldCacheLoad::OnCacheEntryAvailable [this=%p, ent=%p, cb=%p, appcache=%p, access=%x]",
   729     this, entry, mCallback.get(), mAppCache.get(), access));
   731   // XXX Bug 759805: Sometimes we will call this method directly from
   732   // HttpCacheQuery::Run when AsyncOpenCacheEntry fails, but
   733   // AsyncOpenCacheEntry will also call this method. As a workaround, we just
   734   // ensure we only execute this code once.
   735   NS_ENSURE_TRUE(mRunCount == 0, NS_ERROR_UNEXPECTED);
   736   ++mRunCount;
   738   mCacheEntry = entry ? new _OldCacheEntryWrapper(entry) : nullptr;
   739   mStatus = status;
   740   mNew = access == nsICache::ACCESS_WRITE;
   742   if (mFlags & CHECK_MULTITHREADED)
   743     Check();
   745   if (mSync)
   746     return Run();
   748   return NS_DispatchToMainThread(this);
   749 }
   751 void
   752 _OldCacheLoad::Check()
   753 {
   754   if (!mCacheEntry)
   755     return;
   757   if (mNew)
   758     return;
   760   uint32_t result;
   761   nsresult rv = mCallback->OnCacheEntryCheck(mCacheEntry, mAppCache, &result);
   762   LOG(("  OnCacheEntryCheck result ent=%p, cb=%p, appcache=%p, rv=0x%08x, result=%d",
   763     mCacheEntry.get(), mCallback.get(), mAppCache.get(), rv, result));
   765   if (NS_FAILED(rv)) {
   766     NS_WARNING("cache check failed");
   767   }
   769   if (NS_FAILED(rv) || result == nsICacheEntryOpenCallback::ENTRY_NOT_WANTED) {
   770     mCacheEntry->Close();
   771     mCacheEntry = nullptr;
   772     mStatus = NS_ERROR_CACHE_KEY_NOT_FOUND;
   773   }
   774 }
   776 NS_IMETHODIMP
   777 _OldCacheLoad::OnCacheEntryDoomed(nsresult)
   778 {
   779   return NS_ERROR_NOT_IMPLEMENTED;
   780 }
   782 // nsICacheStorage old cache wrapper
   784 NS_IMPL_ISUPPORTS(_OldStorage, nsICacheStorage)
   786 _OldStorage::_OldStorage(nsILoadContextInfo* aInfo,
   787                          bool aAllowDisk,
   788                          bool aLookupAppCache,
   789                          bool aOfflineStorage,
   790                          nsIApplicationCache* aAppCache)
   791 : mLoadInfo(GetLoadContextInfo(aInfo))
   792 , mAppCache(aAppCache)
   793 , mWriteToDisk(aAllowDisk)
   794 , mLookupAppCache(aLookupAppCache)
   795 , mOfflineStorage(aOfflineStorage)
   796 {
   797   MOZ_COUNT_CTOR(_OldStorage);
   798 }
   800 _OldStorage::~_OldStorage()
   801 {
   802   MOZ_COUNT_DTOR(_OldStorage);
   803 }
   805 NS_IMETHODIMP _OldStorage::AsyncOpenURI(nsIURI *aURI,
   806                                         const nsACString & aIdExtension,
   807                                         uint32_t aFlags,
   808                                         nsICacheEntryOpenCallback *aCallback)
   809 {
   810   NS_ENSURE_ARG(aURI);
   811   NS_ENSURE_ARG(aCallback);
   813 #ifdef MOZ_LOGGING
   814   nsAutoCString uriSpec;
   815   aURI->GetAsciiSpec(uriSpec);
   816   LOG(("_OldStorage::AsyncOpenURI [this=%p, uri=%s, ide=%s, flags=%x]",
   817     this, uriSpec.get(), aIdExtension.BeginReading(), aFlags));
   818 #endif
   820   nsresult rv;
   822   nsAutoCString cacheKey, scheme;
   823   rv = AssembleCacheKey(aURI, aIdExtension, cacheKey, scheme);
   824   NS_ENSURE_SUCCESS(rv, rv);
   826   if (!mAppCache && (mLookupAppCache || mOfflineStorage)) {
   827     rv = ChooseApplicationCache(cacheKey, getter_AddRefs(mAppCache));
   828     NS_ENSURE_SUCCESS(rv, rv);
   830     if (mAppCache) {
   831       // From a chosen appcache open only as readonly
   832       aFlags &= ~nsICacheStorage::OPEN_TRUNCATE;
   833     }
   834   }
   836   nsRefPtr<_OldCacheLoad> cacheLoad =
   837     new _OldCacheLoad(scheme, cacheKey, aCallback, mAppCache,
   838                       mLoadInfo, mWriteToDisk, aFlags);
   840   rv = cacheLoad->Start();
   841   NS_ENSURE_SUCCESS(rv, rv);
   843   return NS_OK;
   844 }
   846 NS_IMETHODIMP _OldStorage::AsyncDoomURI(nsIURI *aURI, const nsACString & aIdExtension,
   847                                         nsICacheEntryDoomCallback* aCallback)
   848 {
   849   LOG(("_OldStorage::AsyncDoomURI"));
   851   nsresult rv;
   853   nsAutoCString cacheKey, scheme;
   854   rv = AssembleCacheKey(aURI, aIdExtension, cacheKey, scheme);
   855   NS_ENSURE_SUCCESS(rv, rv);
   857   nsCOMPtr<nsICacheSession> session;
   858   rv = GetCacheSession(scheme, mWriteToDisk, mLoadInfo, mAppCache,
   859                        getter_AddRefs(session));
   860   NS_ENSURE_SUCCESS(rv, rv);
   862   nsRefPtr<DoomCallbackWrapper> cb = aCallback
   863     ? new DoomCallbackWrapper(aCallback)
   864     : nullptr;
   865   rv = session->DoomEntry(cacheKey, cb);
   866   NS_ENSURE_SUCCESS(rv, rv);
   868   return NS_OK;
   869 }
   871 NS_IMETHODIMP _OldStorage::AsyncEvictStorage(nsICacheEntryDoomCallback* aCallback)
   872 {
   873   LOG(("_OldStorage::AsyncEvictStorage"));
   875   nsresult rv;
   877   if (!mAppCache && mOfflineStorage) {
   878     // Special casing for pure offline storage
   879     if (mLoadInfo->AppId() == nsILoadContextInfo::NO_APP_ID &&
   880         !mLoadInfo->IsInBrowserElement()) {
   882       // Clear everything.
   883       nsCOMPtr<nsICacheService> serv =
   884           do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
   885       NS_ENSURE_SUCCESS(rv, rv);
   887       rv = serv->EvictEntries(nsICache::STORE_OFFLINE);
   888       NS_ENSURE_SUCCESS(rv, rv);
   889     }
   890     else {
   891       // Clear app or inbrowser staff.
   892       nsCOMPtr<nsIApplicationCacheService> appCacheService =
   893         do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
   894       NS_ENSURE_SUCCESS(rv, rv);
   896       rv = appCacheService->DiscardByAppId(mLoadInfo->AppId(),
   897                                            mLoadInfo->IsInBrowserElement());
   898       NS_ENSURE_SUCCESS(rv, rv);
   899     }
   900   }
   901   else {
   902     if (mAppCache) {
   903       nsCOMPtr<nsICacheSession> session;
   904       rv = GetCacheSession(EmptyCString(),
   905                            mWriteToDisk, mLoadInfo, mAppCache,
   906                            getter_AddRefs(session));
   907       NS_ENSURE_SUCCESS(rv, rv);
   909       rv = session->EvictEntries();
   910       NS_ENSURE_SUCCESS(rv, rv);
   911     }
   912     else {
   913       // Oh, I'll be so happy when session names are gone...
   914       nsCOMPtr<nsICacheSession> session;
   915       rv = GetCacheSession(NS_LITERAL_CSTRING("http"),
   916                            mWriteToDisk, mLoadInfo, mAppCache,
   917                            getter_AddRefs(session));
   918       NS_ENSURE_SUCCESS(rv, rv);
   920       rv = session->EvictEntries();
   921       NS_ENSURE_SUCCESS(rv, rv);
   923       rv = GetCacheSession(NS_LITERAL_CSTRING("wyciwyg"),
   924                            mWriteToDisk, mLoadInfo, mAppCache,
   925                            getter_AddRefs(session));
   926       NS_ENSURE_SUCCESS(rv, rv);
   928       rv = session->EvictEntries();
   929       NS_ENSURE_SUCCESS(rv, rv);
   931       // This clears any data from scheme other then http, wyciwyg or ftp
   932       rv = GetCacheSession(EmptyCString(),
   933                            mWriteToDisk, mLoadInfo, mAppCache,
   934                            getter_AddRefs(session));
   935       NS_ENSURE_SUCCESS(rv, rv);
   937       rv = session->EvictEntries();
   938       NS_ENSURE_SUCCESS(rv, rv);
   939     }
   940   }
   942   if (aCallback) {
   943     nsRefPtr<DoomCallbackSynchronizer> sync =
   944       new DoomCallbackSynchronizer(aCallback);
   945     rv = sync->Dispatch();
   946     NS_ENSURE_SUCCESS(rv, rv);
   947   }
   949   return NS_OK;
   950 }
   952 NS_IMETHODIMP _OldStorage::AsyncVisitStorage(nsICacheStorageVisitor* aVisitor,
   953                                              bool aVisitEntries)
   954 {
   955   LOG(("_OldStorage::AsyncVisitStorage"));
   957   NS_ENSURE_ARG(aVisitor);
   959   if (mLoadInfo->IsAnonymous()) {
   960     // There is no concept of 'anonymous' storage in the old cache
   961     // since anon cache entries are stored in 'non-anon' storage
   962     // with a special prefix.
   963     // Just fake we have 0 items with 0 consumption.  This at least
   964     // prevents displaying double size in the advanced section of
   965     // the Options dialog.
   966     aVisitor->OnCacheStorageInfo(0, 0);
   967     if (aVisitEntries)
   968       aVisitor->OnCacheEntryVisitCompleted();
   969     return NS_OK;
   970   }
   972   nsresult rv;
   974   nsCOMPtr<nsICacheService> serv =
   975       do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
   976   NS_ENSURE_SUCCESS(rv, rv);
   978   char* deviceID;
   979   if (mAppCache || mOfflineStorage) {
   980     deviceID = const_cast<char*>("offline");
   981   } else if (!mWriteToDisk || mLoadInfo->IsPrivate()) {
   982     deviceID = const_cast<char*>("memory");
   983   } else {
   984     deviceID = const_cast<char*>("disk");
   985   }
   987   nsRefPtr<VisitCallbackWrapper> cb = new VisitCallbackWrapper(
   988     deviceID, aVisitor, aVisitEntries);
   989   rv = serv->VisitEntries(cb);
   990   NS_ENSURE_SUCCESS(rv, rv);
   992   return NS_OK;
   993 }
   995 // Internal
   997 nsresult _OldStorage::AssembleCacheKey(nsIURI *aURI,
   998                                        nsACString const & aIdExtension,
   999                                        nsACString & aCacheKey,
  1000                                        nsACString & aScheme)
  1002   // Copied from nsHttpChannel::AssembleCacheKey
  1004   aCacheKey.Truncate();
  1006   nsresult rv;
  1008   rv = aURI->GetScheme(aScheme);
  1009   NS_ENSURE_SUCCESS(rv, rv);
  1011   nsAutoCString uriSpec;
  1012   if (aScheme.Equals(NS_LITERAL_CSTRING("http")) ||
  1013       aScheme.Equals(NS_LITERAL_CSTRING("https"))) {
  1014     if (mLoadInfo->IsAnonymous()) {
  1015       aCacheKey.AssignLiteral("anon&");
  1018     if (!aIdExtension.IsEmpty()) {
  1019       aCacheKey.AppendPrintf("id=%s&", aIdExtension.BeginReading());
  1022     nsCOMPtr<nsIURI> noRefURI;
  1023     rv = aURI->CloneIgnoringRef(getter_AddRefs(noRefURI));
  1024     NS_ENSURE_SUCCESS(rv, rv);
  1026     rv = noRefURI->GetAsciiSpec(uriSpec);
  1027     NS_ENSURE_SUCCESS(rv, rv);
  1029     if (!aCacheKey.IsEmpty()) {
  1030       aCacheKey.AppendLiteral("uri=");
  1033   else if (aScheme.Equals(NS_LITERAL_CSTRING("wyciwyg"))) {
  1034     rv = aURI->GetSpec(uriSpec);
  1035     NS_ENSURE_SUCCESS(rv, rv);
  1037   else {
  1038     rv = aURI->GetAsciiSpec(uriSpec);
  1039     NS_ENSURE_SUCCESS(rv, rv);
  1042   aCacheKey.Append(uriSpec);
  1044   return NS_OK;
  1047 nsresult _OldStorage::ChooseApplicationCache(nsCSubstring const &cacheKey,
  1048                                              nsIApplicationCache** aCache)
  1050   nsresult rv;
  1052   nsCOMPtr<nsIApplicationCacheService> appCacheService =
  1053     do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
  1054   NS_ENSURE_SUCCESS(rv, rv);
  1056   rv = appCacheService->ChooseApplicationCache(cacheKey, mLoadInfo, aCache);
  1057   NS_ENSURE_SUCCESS(rv, rv);
  1059   return NS_OK;
  1062 } // net
  1063 } // mozilla

mercurial