1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_dom_cache_QuotaClientImpl_h
8 #define mozilla_dom_cache_QuotaClientImpl_h
9 
10 #include "mozilla/dom/cache/QuotaClient.h"
11 #include "mozilla/dom/cache/FileUtils.h"
12 
13 namespace mozilla {
14 namespace dom {
15 namespace cache {
16 
17 class CacheQuotaClient final : public quota::Client {
18   static CacheQuotaClient* sInstance;
19 
20  public:
21   using OriginMetadata = quota::OriginMetadata;
22   using PersistenceType = quota::PersistenceType;
23   using UsageInfo = quota::UsageInfo;
24 
25   CacheQuotaClient();
26 
27   static CacheQuotaClient* Get();
28 
29   virtual Type GetType() override;
30 
31   virtual Result<UsageInfo, nsresult> InitOrigin(
32       PersistenceType aPersistenceType, const OriginMetadata& aOriginMetadata,
33       const AtomicBool& aCanceled) override;
34 
35   virtual nsresult InitOriginWithoutTracking(
36       PersistenceType aPersistenceType, const OriginMetadata& aOriginMetadata,
37       const AtomicBool& aCanceled) override;
38 
39   virtual Result<UsageInfo, nsresult> GetUsageForOrigin(
40       PersistenceType aPersistenceType, const OriginMetadata& aOriginMetadata,
41       const AtomicBool& aCanceled) override;
42 
43   virtual void OnOriginClearCompleted(PersistenceType aPersistenceType,
44                                       const nsACString& aOrigin) override;
45 
46   virtual void ReleaseIOThreadObjects() override;
47 
48   void AbortOperationsForLocks(
49       const DirectoryLockIdTable& aDirectoryLockIds) override;
50 
51   virtual void AbortOperationsForProcess(
52       ContentParentId aContentParentId) override;
53 
54   virtual void AbortAllOperations() override;
55 
56   virtual void StartIdleMaintenance() override;
57 
58   virtual void StopIdleMaintenance() override;
59 
60   nsresult UpgradeStorageFrom2_0To2_1(nsIFile* aDirectory) override;
61 
62   template <typename Callable>
MaybeUpdatePaddingFileInternal(nsIFile & aBaseDir,mozIStorageConnection & aConn,const int64_t aIncreaseSize,const int64_t aDecreaseSize,Callable && aCommitHook)63   nsresult MaybeUpdatePaddingFileInternal(nsIFile& aBaseDir,
64                                           mozIStorageConnection& aConn,
65                                           const int64_t aIncreaseSize,
66                                           const int64_t aDecreaseSize,
67                                           Callable&& aCommitHook) {
68     MOZ_ASSERT(!NS_IsMainThread());
69     MOZ_DIAGNOSTIC_ASSERT(aIncreaseSize >= 0);
70     MOZ_DIAGNOSTIC_ASSERT(aDecreaseSize >= 0);
71 
72     // Temporary should be removed at the end of each action. If not, it means
73     // the failure happened.
74     const bool temporaryPaddingFileExist =
75         DirectoryPaddingFileExists(aBaseDir, DirPaddingFile::TMP_FILE);
76 
77     if (aIncreaseSize == aDecreaseSize && !temporaryPaddingFileExist) {
78       // Early return here, since most cache actions won't modify padding size.
79       QM_TRY(aCommitHook());
80 
81       return NS_OK;
82     }
83 
84     // Don't delete the temporary padding file in case of an error to force the
85     // next action recalculate the padding size.
86     QM_TRY(UpdateDirectoryPaddingFile(aBaseDir, aConn, aIncreaseSize,
87                                       aDecreaseSize,
88                                       temporaryPaddingFileExist));
89 
90     // Don't delete the temporary padding file in case of an error to force the
91     // next action recalculate the padding size.
92     QM_TRY(aCommitHook());
93 
94     QM_WARNONLY_TRY(ToResult(DirectoryPaddingFinalizeWrite(aBaseDir)),
95                     ([&aBaseDir](const nsresult) {
96                       // Force restore file next time.
97                       QM_WARNONLY_TRY(DirectoryPaddingDeleteFile(
98                           aBaseDir, DirPaddingFile::FILE));
99 
100                       // Ensure that we are able to force the padding file to
101                       // be restored.
102                       MOZ_ASSERT(DirectoryPaddingFileExists(
103                           aBaseDir, DirPaddingFile::TMP_FILE));
104 
105                       // Since both the body file and header have been stored
106                       // in the file-system, just make the action be resolve
107                       // and let the padding file be restored in the next
108                       // action.
109                     }));
110 
111     return NS_OK;
112   }
113 
114   nsresult RestorePaddingFileInternal(nsIFile* aBaseDir,
115                                       mozIStorageConnection* aConn);
116 
117   nsresult WipePaddingFileInternal(const QuotaInfo& aQuotaInfo,
118                                    nsIFile* aBaseDir);
119 
120  private:
121   ~CacheQuotaClient();
122 
123   void InitiateShutdown() override;
124   bool IsShutdownCompleted() const override;
125   nsCString GetShutdownStatus() const override;
126   void ForceKillActors() override;
127   void FinalizeShutdown() override;
128 
129   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CacheQuotaClient, override)
130 };
131 
132 }  // namespace cache
133 }  // namespace dom
134 }  // namespace mozilla
135 
136 #endif  // mozilla_dom_cache_QuotaClientImpl_h
137