CacheEntry.h (22200B)
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 #ifndef CacheEntry__h__ 6 #define CacheEntry__h__ 7 8 #include "mozilla/LinkedList.h" 9 #include "nsICacheEntry.h" 10 #include "CacheFile.h" 11 12 #include "nsIRunnable.h" 13 #include "nsIOutputStream.h" 14 #include "nsICacheEntryOpenCallback.h" 15 #include "nsICacheEntryDoomCallback.h" 16 #include "nsITransportSecurityInfo.h" 17 18 #include "nsCOMPtr.h" 19 #include "nsRefPtrHashtable.h" 20 #include "nsHashKeys.h" 21 #include "nsString.h" 22 #include "nsCOMArray.h" 23 #include "nsThreadUtils.h" 24 #include "mozilla/Mutex.h" 25 #include "mozilla/TimeStamp.h" 26 #include "Dictionary.h" 27 28 static inline uint32_t PRTimeToSeconds(PRTime t_usec) { 29 return uint32_t(t_usec / PR_USEC_PER_SEC); 30 } 31 32 #define NowInSeconds() PRTimeToSeconds(PR_Now()) 33 34 class nsIOutputStream; 35 class nsIURI; 36 class nsIThread; 37 38 namespace mozilla { 39 namespace net { 40 41 class CacheStorageService; 42 class CacheStorage; 43 class CacheOutputCloseListener; 44 class CacheEntryHandle; 45 46 class CacheEntry final : public nsIRunnable, 47 public CacheFileListener, 48 // Used by CacheStorageService::MemoryPool 49 public LinkedListElement<RefPtr<CacheEntry>> { 50 public: 51 NS_DECL_THREADSAFE_ISUPPORTS 52 NS_DECL_NSIRUNNABLE 53 54 static uint64_t GetNextId(); 55 56 CacheEntry(const nsACString& aStorageID, const nsACString& aURI, 57 const nsACString& aEnhanceID, bool aUseDisk, bool aSkipSizeCheck, 58 bool aPin); 59 60 void AsyncOpen(nsICacheEntryOpenCallback* aCallback, uint32_t aFlags); 61 62 CacheEntryHandle* NewHandle(); 63 // For a new and recreated entry w/o a callback, we need to wrap it 64 // with a handle to detect writing consumer is gone. 65 CacheEntryHandle* NewWriteHandle(); 66 67 // Forwarded to from CacheEntryHandle : nsICacheEntry 68 nsresult GetKey(nsACString& aKey); 69 nsresult GetCacheEntryId(uint64_t* aCacheEntryId); 70 nsresult GetPersistent(bool* aPersistToDisk); 71 nsresult GetFetchCount(uint32_t* aFetchCount); 72 nsresult GetLastFetched(uint32_t* aLastFetched); 73 nsresult GetLastModified(uint32_t* aLastModified); 74 nsresult GetExpirationTime(uint32_t* aExpirationTime); 75 nsresult SetExpirationTime(uint32_t expirationTime); 76 nsresult GetOnStartTime(uint64_t* aTime); 77 nsresult GetOnStopTime(uint64_t* aTime); 78 nsresult GetReadyOrRevalidating(bool* aReady); 79 nsresult SetNetworkTimes(uint64_t onStartTime, uint64_t onStopTime); 80 nsresult SetContentType(uint8_t aContentType); 81 nsresult ForceValidFor(uint32_t aSecondsToTheFuture); 82 nsresult GetIsForcedValid(bool* aIsForcedValid); 83 nsresult MarkForcedValidUse(); 84 nsresult OpenInputStream(int64_t offset, nsIInputStream** _retval); 85 nsresult OpenOutputStream(int64_t offset, int64_t predictedSize, 86 nsIOutputStream** _retval); 87 nsresult GetSecurityInfo(nsITransportSecurityInfo** aSecurityInfo); 88 nsresult SetSecurityInfo(nsITransportSecurityInfo* aSecurityInfo); 89 nsresult GetStorageDataSize(uint32_t* aStorageDataSize); 90 nsresult AsyncDoom(nsICacheEntryDoomCallback* aCallback); 91 nsresult GetMetaDataElement(const char* key, char** aRetval); 92 nsresult SetMetaDataElement(const char* key, const char* value); 93 nsresult GetIsEmpty(bool* aEmpty); 94 nsresult VisitMetaData(nsICacheEntryMetaDataVisitor* visitor); 95 nsresult MetaDataReady(void); 96 nsresult SetValid(void); 97 nsresult GetDiskStorageSizeInKB(uint32_t* aDiskStorageSizeInKB); 98 nsresult Recreate(bool aMemoryOnly, nsICacheEntry** _retval); 99 nsresult GetDataSize(int64_t* aDataSize); 100 nsresult GetAltDataSize(int64_t* aDataSize); 101 nsresult GetAltDataType(nsACString& aAltDataType); 102 nsresult OpenAlternativeOutputStream(const nsACString& type, 103 int64_t predictedSize, 104 nsIAsyncOutputStream** _retval); 105 nsresult OpenAlternativeInputStream(const nsACString& type, 106 nsIInputStream** _retval); 107 nsresult GetLoadContextInfo(nsILoadContextInfo** aInfo); 108 109 nsresult SetDictionary(DictionaryCacheEntry* aDict); 110 111 public: 112 uint32_t GetMetadataMemoryConsumption(); 113 nsCString const& GetStorageID() const { return mStorageID; } 114 nsCString const& GetEnhanceID() const { return mEnhanceID; } 115 nsCString const& GetURI() const { return mURI; } 116 // Accessible at any time 117 bool IsUsingDisk() const { return mUseDisk; } 118 bool IsReferenced() const MOZ_NO_THREAD_SAFETY_ANALYSIS; 119 bool IsFileDoomed(); 120 bool IsDoomed() const { return mIsDoomed; } 121 bool IsPinned() const { return mPinned; } 122 123 // Mark entry to allow bypassing writer lock for new listeners 124 void SetBypassWriterLock(bool aBypass); 125 bool ShouldBypassWriterLock() const MOZ_REQUIRES(mLock) { 126 return mBypassWriterLock; 127 } 128 129 // Methods for entry management (eviction from memory), 130 // called only on the management thread. 131 132 // TODO make these inline 133 double GetFrecency() const; 134 uint32_t GetExpirationTime() const; 135 uint32_t UseCount() const { return mUseCount; } 136 137 bool IsRegistered() const; 138 bool CanRegister() const; 139 void SetRegistered(bool aRegistered); 140 141 TimeStamp const& LoadStart() const { return mLoadStart; } 142 143 enum EPurge { 144 PURGE_DATA_ONLY_DISK_BACKED, 145 PURGE_WHOLE_ONLY_DISK_BACKED, 146 PURGE_WHOLE, 147 }; 148 149 bool DeferOrBypassRemovalOnPinStatus(bool aPinned); 150 bool Purge(uint32_t aWhat); 151 void PurgeAndDoom(); 152 void DoomAlreadyRemoved(); 153 154 nsresult HashingKeyWithStorage(nsACString& aResult) const; 155 nsresult HashingKey(nsACString& aResult) const; 156 157 static nsresult HashingKey(const nsACString& aStorageID, 158 const nsACString& aEnhanceID, nsIURI* aURI, 159 nsACString& aResult); 160 161 static nsresult HashingKey(const nsACString& aStorageID, 162 const nsACString& aEnhanceID, 163 const nsACString& aURISpec, nsACString& aResult); 164 165 // Accessed only on the service management thread 166 double mFrecency{0}; 167 ::mozilla::Atomic<uint32_t, ::mozilla::Relaxed> mSortingExpirationTime{ 168 uint32_t(-1)}; 169 170 // Memory reporting 171 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf); 172 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); 173 174 private: 175 virtual ~CacheEntry(); 176 177 // CacheFileListener 178 NS_IMETHOD OnFileReady(nsresult aResult, bool aIsNew) override; 179 NS_IMETHOD OnFileDoomed(nsresult aResult) override; 180 181 // Keep the service alive during life-time of an entry 182 RefPtr<CacheStorageService> mService; 183 184 // We must monitor when a cache entry whose consumer is responsible 185 // for writing it the first time gets released. We must then invoke 186 // waiting callbacks to not break the chain. 187 class Callback { 188 public: 189 Callback(CacheEntry* aEntry, nsICacheEntryOpenCallback* aCallback, 190 bool aReadOnly, bool aCheckOnAnyThread, bool aSecret); 191 // Special constructor for Callback objects added to the chain 192 // just to ensure proper defer dooming (recreation) of this entry. 193 Callback(CacheEntry* aEntry, bool aDoomWhenFoundInPinStatus); 194 Callback(Callback const& aThat); 195 ~Callback(); 196 197 // Called when this callback record changes it's owning entry, 198 // mainly during recreation. 199 void ExchangeEntry(CacheEntry* aEntry) MOZ_REQUIRES(aEntry->mLock); 200 201 // Returns true when an entry is about to be "defer" doomed and this is 202 // a "defer" callback. The caller must hold a lock (this entry is in the 203 // caller's mCallback array) 204 bool DeferDoom(bool* aDoom) const; 205 206 // We are raising reference count here to take into account the pending 207 // callback (that virtually holds a ref to this entry before it gets 208 // it's pointer). 209 RefPtr<CacheEntry> mEntry; 210 nsCOMPtr<nsICacheEntryOpenCallback> mCallback; 211 nsCOMPtr<nsIEventTarget> mTarget; 212 bool mReadOnly : 1; 213 bool mRevalidating : 1; 214 bool mCheckOnAnyThread : 1; 215 bool mRecheckAfterWrite : 1; 216 bool mNotWanted : 1; 217 bool mSecret : 1; 218 219 // These are set only for the defer-doomer Callback instance inserted 220 // to the callback chain. When any of these is set and also any of 221 // the corressponding flags on the entry is set, this callback will 222 // indicate (via DeferDoom()) the entry have to be recreated/doomed. 223 bool mDoomWhenFoundPinned : 1; 224 bool mDoomWhenFoundNonPinned : 1; 225 226 nsresult OnCheckThread(bool* aOnCheckThread) const; 227 nsresult OnAvailThread(bool* aOnAvailThread) const; 228 }; 229 230 // Since OnCacheEntryAvailable must be invoked on the main thread 231 // we need a runnable for it... 232 class AvailableCallbackRunnable : public Runnable { 233 public: 234 AvailableCallbackRunnable(CacheEntry* aEntry, Callback const& aCallback) 235 : Runnable("CacheEntry::AvailableCallbackRunnable"), 236 mEntry(aEntry), 237 mCallback(aCallback) {} 238 239 private: 240 NS_IMETHOD Run() override { 241 mEntry->InvokeAvailableCallback(mCallback); 242 return NS_OK; 243 } 244 245 RefPtr<CacheEntry> mEntry; 246 Callback mCallback; 247 }; 248 249 // Since OnCacheEntryDoomed must be invoked on the main thread 250 // we need a runnable for it... 251 class DoomCallbackRunnable : public Runnable { 252 public: 253 DoomCallbackRunnable(CacheEntry* aEntry, nsresult aRv) 254 : Runnable("net::CacheEntry::DoomCallbackRunnable"), 255 mEntry(aEntry), 256 mRv(aRv) {} 257 258 private: 259 NS_IMETHOD Run() override { 260 nsCOMPtr<nsICacheEntryDoomCallback> callback; 261 { 262 mozilla::MutexAutoLock lock(mEntry->mLock); 263 mEntry->mDoomCallback.swap(callback); 264 } 265 266 if (callback) callback->OnCacheEntryDoomed(mRv); 267 return NS_OK; 268 } 269 270 RefPtr<CacheEntry> mEntry; 271 nsresult mRv; 272 }; 273 274 // Starts the load or just invokes the callback, bypasses (when required) 275 // if busy. Returns true on job done, false on bypass. 276 bool Open(Callback& aCallback, bool aTruncate, bool aPriority, 277 bool aBypassIfBusy); 278 // Loads from disk asynchronously 279 bool Load(bool aTruncate, bool aPriority); 280 281 void RememberCallback(Callback& aCallback) MOZ_REQUIRES(mLock); 282 void InvokeCallbacksLock(); 283 void InvokeCallbacks(); 284 bool InvokeCallbacks(bool aReadOnly); 285 bool InvokeCallback(Callback& aCallback); 286 void InvokeAvailableCallback(Callback const& aCallback); 287 void OnFetched(Callback const& aCallback); 288 289 nsresult OpenOutputStreamInternal(int64_t offset, nsIOutputStream** _retval); 290 nsresult OpenInputStreamInternal(int64_t offset, const char* aAltDataType, 291 nsIInputStream** _retval); 292 293 void OnHandleClosed(CacheEntryHandle const* aHandle); 294 295 private: 296 friend class CacheEntryHandle; 297 // Increment/decrements the number of handles keeping this entry. 298 void AddHandleRef() MOZ_REQUIRES(mLock) { ++mHandlesCount; } 299 void ReleaseHandleRef() MOZ_REQUIRES(mLock) { --mHandlesCount; } 300 // Current number of handles keeping this entry. 301 uint32_t HandlesCount() const MOZ_REQUIRES(mLock) { return mHandlesCount; } 302 303 private: 304 friend class CacheOutputCloseListener; 305 void OnOutputClosed(); 306 307 private: 308 // Schedules a background operation on the management thread. 309 // When executed on the management thread directly, the operation(s) 310 // is (are) executed immediately. 311 void BackgroundOp(uint32_t aOperation, bool aForceAsync = false); 312 void StoreFrecency(double aFrecency); 313 314 // Called only from DoomAlreadyRemoved() 315 void DoomFile() MOZ_REQUIRES(mLock); 316 // When this entry is doomed the first time, this method removes 317 // any force-valid timing info for this entry. 318 void RemoveForcedValidity(); 319 320 already_AddRefed<CacheEntryHandle> ReopenTruncated( 321 bool aMemoryOnly, nsICacheEntryOpenCallback* aCallback); 322 void TransferCallbacks(CacheEntry& aFromEntry); 323 324 mozilla::Mutex mLock{"CacheEntry"}; 325 326 // Reflects the number of existing handles for this entry 327 ::mozilla::ThreadSafeAutoRefCnt mHandlesCount MOZ_GUARDED_BY(mLock); 328 329 nsTArray<Callback> mCallbacks MOZ_GUARDED_BY(mLock); 330 nsCOMPtr<nsICacheEntryDoomCallback> mDoomCallback; 331 332 // Set in CacheEntry::Load(), only - shouldn't need to be under lock 333 // XXX FIX? is this correct? 334 RefPtr<CacheFile> mFile; 335 336 // Using ReleaseAcquire since we only control access to mFile with this. 337 // When mFileStatus is read and found success it is ensured there is mFile and 338 // that it is after a successful call to Init(). 339 Atomic<nsresult, ReleaseAcquire> mFileStatus{NS_ERROR_NOT_INITIALIZED}; 340 // Set in constructor 341 nsCString const mURI; 342 nsCString const mEnhanceID; 343 nsCString const mStorageID; 344 345 // mUseDisk, mSkipSizeCheck, mIsDoomed are plain "bool", not "bool:1", 346 // so as to avoid bitfield races with the byte containing 347 // mSecurityInfoLoaded et al. See bug 1278524. 348 // 349 // Whether it's allowed to persist the data to disk 350 bool const mUseDisk; 351 // Whether it should skip max size check. 352 bool const mSkipSizeCheck; 353 // Set when entry is doomed with AsyncDoom() or DoomAlreadyRemoved(). 354 Atomic<bool, Relaxed> mIsDoomed{false}; 355 // The indication of pinning this entry was open with 356 Atomic<bool, Relaxed> mPinned; 357 358 // Following flags are all synchronized with the cache entry lock. 359 360 // Whether security info has already been looked up in metadata. 361 bool mSecurityInfoLoaded : 1 MOZ_GUARDED_BY(mLock); 362 // Prevents any callback invocation 363 bool mPreventCallbacks : 1 MOZ_GUARDED_BY(mLock); 364 // true: after load and an existing file, or after output stream has been 365 // opened. 366 // note - when opening an input stream, and this flag is false, output 367 // stream is open along ; this makes input streams on new entries 368 // behave correctly when EOF is reached (WOULD_BLOCK is returned). 369 // false: after load and a new file, or dropped to back to false when a 370 // writer fails to open an output stream. 371 bool mHasData : 1 MOZ_GUARDED_BY(mLock); 372 // Whether the pinning state of the entry is known (equals to the actual state 373 // of the cache file) 374 bool mPinningKnown : 1 MOZ_GUARDED_BY(mLock); 375 // Whether to bypass writer lock for new listeners (when writer is suspended) 376 bool mBypassWriterLock : 1 MOZ_GUARDED_BY(mLock); 377 378 static char const* StateString(uint32_t aState); 379 380 enum EState { // transiting to: 381 NOTLOADED = 0, // -> LOADING | EMPTY 382 LOADING = 1, // -> EMPTY | READY 383 EMPTY = 2, // -> WRITING 384 WRITING = 3, // -> EMPTY | READY 385 READY = 4, // -> REVALIDATING 386 REVALIDATING = 5 // -> READY 387 }; 388 389 // State of this entry. 390 EState mState MOZ_GUARDED_BY(mLock){NOTLOADED}; 391 392 enum ERegistration { 393 NEVERREGISTERED = 0, // The entry has never been registered 394 REGISTERED = 1, // The entry is stored in the memory pool index 395 DEREGISTERED = 2 // The entry has been removed from the pool 396 }; 397 398 // Accessed only on the management thread. Records the state of registration 399 // this entry in the memory pool intermediate cache. 400 ERegistration mRegistration{NEVERREGISTERED}; 401 402 // If a new (empty) entry is requested to open an input stream before 403 // output stream has been opened, we must open output stream internally 404 // on CacheFile and hold until writer releases the entry or opens the output 405 // stream for read (then we trade him mOutputStream). 406 nsCOMPtr<nsIOutputStream> mOutputStream MOZ_GUARDED_BY(mLock); 407 408 // Weak reference to the current writter. There can be more then one 409 // writer at a time and OnHandleClosed() must be processed only for the 410 // current one. 411 CacheEntryHandle* mWriter MOZ_GUARDED_BY(mLock){nullptr}; 412 413 // Background thread scheduled operation. Set (under the lock) one 414 // of this flags to tell the background thread what to do. 415 class Ops { 416 public: 417 static uint32_t const REGISTER = 1 << 0; 418 static uint32_t const FRECENCYUPDATE = 1 << 1; 419 static uint32_t const CALLBACKS = 1 << 2; 420 static uint32_t const UNREGISTER = 1 << 3; 421 422 Ops() = default; 423 uint32_t Grab() { 424 uint32_t flags = mFlags; 425 mFlags = 0; 426 return flags; 427 } 428 bool Set(uint32_t aFlags) { 429 if (mFlags & aFlags) return false; 430 mFlags |= aFlags; 431 return true; 432 } 433 434 private: 435 uint32_t mFlags{0}; 436 } mBackgroundOperations; 437 438 nsCOMPtr<nsITransportSecurityInfo> mSecurityInfo; 439 mozilla::TimeStamp mLoadStart; 440 uint32_t mUseCount{0}; 441 442 RefPtr<DictionaryCacheEntry> mDict; 443 444 const uint64_t mCacheEntryId; 445 }; 446 447 class CacheEntryHandle final : public nsICacheEntry { 448 public: 449 explicit CacheEntryHandle(CacheEntry* aEntry); 450 CacheEntry* Entry() const { return mEntry; } 451 452 NS_DECL_THREADSAFE_ISUPPORTS 453 454 // Default implementation is simply safely forwarded. 455 NS_IMETHOD GetKey(nsACString& aKey) override { return mEntry->GetKey(aKey); } 456 NS_IMETHOD GetCacheEntryId(uint64_t* aCacheEntryId) override { 457 return mEntry->GetCacheEntryId(aCacheEntryId); 458 } 459 NS_IMETHOD GetPersistent(bool* aPersistent) override { 460 return mEntry->GetPersistent(aPersistent); 461 } 462 NS_IMETHOD GetFetchCount(uint32_t* aFetchCount) override { 463 return mEntry->GetFetchCount(aFetchCount); 464 } 465 NS_IMETHOD GetLastFetched(uint32_t* aLastFetched) override { 466 return mEntry->GetLastFetched(aLastFetched); 467 } 468 NS_IMETHOD GetLastModified(uint32_t* aLastModified) override { 469 return mEntry->GetLastModified(aLastModified); 470 } 471 NS_IMETHOD GetExpirationTime(uint32_t* aExpirationTime) override { 472 return mEntry->GetExpirationTime(aExpirationTime); 473 } 474 NS_IMETHOD SetExpirationTime(uint32_t expirationTime) override { 475 return mEntry->SetExpirationTime(expirationTime); 476 } 477 NS_IMETHOD GetOnStartTime(uint64_t* aOnStartTime) override { 478 return mEntry->GetOnStartTime(aOnStartTime); 479 } 480 NS_IMETHOD GetOnStopTime(uint64_t* aOnStopTime) override { 481 return mEntry->GetOnStopTime(aOnStopTime); 482 } 483 NS_IMETHOD GetReadyOrRevalidating(bool* aReady) override { 484 return mEntry->GetReadyOrRevalidating(aReady); 485 } 486 NS_IMETHOD SetNetworkTimes(uint64_t onStartTime, 487 uint64_t onStopTime) override { 488 return mEntry->SetNetworkTimes(onStartTime, onStopTime); 489 } 490 NS_IMETHOD SetContentType(uint8_t contentType) override { 491 return mEntry->SetContentType(contentType); 492 } 493 NS_IMETHOD ForceValidFor(uint32_t aSecondsToTheFuture) override { 494 return mEntry->ForceValidFor(aSecondsToTheFuture); 495 } 496 NS_IMETHOD GetIsForcedValid(bool* aIsForcedValid) override { 497 return mEntry->GetIsForcedValid(aIsForcedValid); 498 } 499 NS_IMETHOD MarkForcedValidUse() override { 500 return mEntry->MarkForcedValidUse(); 501 } 502 NS_IMETHOD OpenInputStream(int64_t offset, 503 nsIInputStream** _retval) override { 504 return mEntry->OpenInputStream(offset, _retval); 505 } 506 NS_IMETHOD OpenOutputStream(int64_t offset, int64_t predictedSize, 507 nsIOutputStream** _retval) override { 508 return mEntry->OpenOutputStream(offset, predictedSize, _retval); 509 } 510 NS_IMETHOD GetSecurityInfo( 511 nsITransportSecurityInfo** aSecurityInfo) override { 512 return mEntry->GetSecurityInfo(aSecurityInfo); 513 } 514 NS_IMETHOD SetSecurityInfo(nsITransportSecurityInfo* aSecurityInfo) override { 515 return mEntry->SetSecurityInfo(aSecurityInfo); 516 } 517 NS_IMETHOD GetStorageDataSize(uint32_t* aStorageDataSize) override { 518 return mEntry->GetStorageDataSize(aStorageDataSize); 519 } 520 NS_IMETHOD AsyncDoom(nsICacheEntryDoomCallback* listener) override { 521 return mEntry->AsyncDoom(listener); 522 } 523 NS_IMETHOD GetMetaDataElement(const char* key, char** _retval) override { 524 return mEntry->GetMetaDataElement(key, _retval); 525 } 526 NS_IMETHOD SetMetaDataElement(const char* key, const char* value) override { 527 return mEntry->SetMetaDataElement(key, value); 528 } 529 NS_IMETHOD GetIsEmpty(bool* empty) override { 530 return mEntry->GetIsEmpty(empty); 531 } 532 NS_IMETHOD VisitMetaData(nsICacheEntryMetaDataVisitor* visitor) override { 533 return mEntry->VisitMetaData(visitor); 534 } 535 NS_IMETHOD MetaDataReady(void) override { return mEntry->MetaDataReady(); } 536 NS_IMETHOD SetValid(void) override { return mEntry->SetValid(); } 537 NS_IMETHOD GetDiskStorageSizeInKB(uint32_t* aDiskStorageSizeInKB) override { 538 return mEntry->GetDiskStorageSizeInKB(aDiskStorageSizeInKB); 539 } 540 NS_IMETHOD Recreate(bool aMemoryOnly, nsICacheEntry** _retval) override { 541 return mEntry->Recreate(aMemoryOnly, _retval); 542 } 543 NS_IMETHOD GetDataSize(int64_t* aDataSize) override { 544 return mEntry->GetDataSize(aDataSize); 545 } 546 NS_IMETHOD GetAltDataSize(int64_t* aAltDataSize) override { 547 return mEntry->GetAltDataSize(aAltDataSize); 548 } 549 NS_IMETHOD GetAltDataType(nsACString& aType) override { 550 return mEntry->GetAltDataType(aType); 551 } 552 NS_IMETHOD OpenAlternativeOutputStream( 553 const nsACString& type, int64_t predictedSize, 554 nsIAsyncOutputStream** _retval) override { 555 return mEntry->OpenAlternativeOutputStream(type, predictedSize, _retval); 556 } 557 NS_IMETHOD OpenAlternativeInputStream(const nsACString& type, 558 nsIInputStream** _retval) override { 559 return mEntry->OpenAlternativeInputStream(type, _retval); 560 } 561 NS_IMETHOD GetLoadContextInfo( 562 nsILoadContextInfo** aLoadContextInfo) override { 563 return mEntry->GetLoadContextInfo(aLoadContextInfo); 564 } 565 NS_IMETHOD SetDictionary(DictionaryCacheEntry* aDict) override { 566 return mEntry->SetDictionary(aDict); 567 } 568 NS_IMETHOD SetBypassWriterLock(bool aBypass) override { 569 mEntry->SetBypassWriterLock(aBypass); 570 return NS_OK; 571 } 572 573 // Specific implementation: 574 NS_IMETHOD Dismiss() override; 575 576 private: 577 virtual ~CacheEntryHandle(); 578 RefPtr<CacheEntry> mEntry; 579 580 // This is |false| until Dismiss() was called and prevents OnHandleClosed 581 // being called more than once. 582 Atomic<bool, ReleaseAcquire> mClosed{false}; 583 }; 584 585 class CacheOutputCloseListener final : public Runnable { 586 public: 587 void OnOutputClosed(); 588 589 private: 590 friend class CacheEntry; 591 592 virtual ~CacheOutputCloseListener() = default; 593 594 NS_DECL_NSIRUNNABLE 595 explicit CacheOutputCloseListener(CacheEntry* aEntry); 596 597 private: 598 RefPtr<CacheEntry> mEntry; 599 }; 600 601 } // namespace net 602 } // namespace mozilla 603 604 #endif