dom/quota/QuotaManager.h

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.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef mozilla_dom_quota_quotamanager_h__
michael@0 8 #define mozilla_dom_quota_quotamanager_h__
michael@0 9
michael@0 10 #include "QuotaCommon.h"
michael@0 11
michael@0 12 #include "nsIObserver.h"
michael@0 13 #include "nsIQuotaManager.h"
michael@0 14
michael@0 15 #include "mozilla/dom/Nullable.h"
michael@0 16 #include "mozilla/Mutex.h"
michael@0 17
michael@0 18 #include "nsClassHashtable.h"
michael@0 19 #include "nsRefPtrHashtable.h"
michael@0 20
michael@0 21 #include "ArrayCluster.h"
michael@0 22 #include "Client.h"
michael@0 23 #include "PersistenceType.h"
michael@0 24 #include "StoragePrivilege.h"
michael@0 25
michael@0 26 #define QUOTA_MANAGER_CONTRACTID "@mozilla.org/dom/quota/manager;1"
michael@0 27
michael@0 28 class nsIOfflineStorage;
michael@0 29 class nsIPrincipal;
michael@0 30 class nsIThread;
michael@0 31 class nsITimer;
michael@0 32 class nsIURI;
michael@0 33 class nsPIDOMWindow;
michael@0 34 class nsIRunnable;
michael@0 35
michael@0 36 BEGIN_QUOTA_NAMESPACE
michael@0 37
michael@0 38 class AcquireListener;
michael@0 39 class AsyncUsageRunnable;
michael@0 40 class CheckQuotaHelper;
michael@0 41 class CollectOriginsHelper;
michael@0 42 class FinalizeOriginEvictionRunnable;
michael@0 43 class GroupInfo;
michael@0 44 class GroupInfoPair;
michael@0 45 class OriginClearRunnable;
michael@0 46 class OriginInfo;
michael@0 47 class OriginOrPatternString;
michael@0 48 class QuotaObject;
michael@0 49 class ResetOrClearRunnable;
michael@0 50 struct SynchronizedOp;
michael@0 51
michael@0 52 class QuotaManager MOZ_FINAL : public nsIQuotaManager,
michael@0 53 public nsIObserver
michael@0 54 {
michael@0 55 friend class AsyncUsageRunnable;
michael@0 56 friend class CollectOriginsHelper;
michael@0 57 friend class FinalizeOriginEvictionRunnable;
michael@0 58 friend class GroupInfo;
michael@0 59 friend class OriginClearRunnable;
michael@0 60 friend class OriginInfo;
michael@0 61 friend class QuotaObject;
michael@0 62 friend class ResetOrClearRunnable;
michael@0 63
michael@0 64 enum MozBrowserPatternFlag
michael@0 65 {
michael@0 66 MozBrowser = 0,
michael@0 67 NotMozBrowser,
michael@0 68 IgnoreMozBrowser
michael@0 69 };
michael@0 70
michael@0 71 typedef void
michael@0 72 (*WaitingOnStoragesCallback)(nsTArray<nsCOMPtr<nsIOfflineStorage> >&, void*);
michael@0 73
michael@0 74 public:
michael@0 75 NS_DECL_ISUPPORTS
michael@0 76 NS_DECL_NSIQUOTAMANAGER
michael@0 77 NS_DECL_NSIOBSERVER
michael@0 78
michael@0 79 // Returns a non-owning reference.
michael@0 80 static QuotaManager*
michael@0 81 GetOrCreate();
michael@0 82
michael@0 83 // Returns a non-owning reference.
michael@0 84 static QuotaManager*
michael@0 85 Get();
michael@0 86
michael@0 87 // Returns an owning reference! No one should call this but the factory.
michael@0 88 static QuotaManager*
michael@0 89 FactoryCreate();
michael@0 90
michael@0 91 // Returns true if we've begun the shutdown process.
michael@0 92 static bool IsShuttingDown();
michael@0 93
michael@0 94 void
michael@0 95 InitQuotaForOrigin(PersistenceType aPersistenceType,
michael@0 96 const nsACString& aGroup,
michael@0 97 const nsACString& aOrigin,
michael@0 98 uint64_t aLimitBytes,
michael@0 99 uint64_t aUsageBytes,
michael@0 100 int64_t aAccessTime);
michael@0 101
michael@0 102 void
michael@0 103 DecreaseUsageForOrigin(PersistenceType aPersistenceType,
michael@0 104 const nsACString& aGroup,
michael@0 105 const nsACString& aOrigin,
michael@0 106 int64_t aSize);
michael@0 107
michael@0 108 void
michael@0 109 UpdateOriginAccessTime(PersistenceType aPersistenceType,
michael@0 110 const nsACString& aGroup,
michael@0 111 const nsACString& aOrigin);
michael@0 112
michael@0 113 void
michael@0 114 RemoveQuota();
michael@0 115
michael@0 116 void
michael@0 117 RemoveQuotaForPersistenceType(PersistenceType);
michael@0 118
michael@0 119 void
michael@0 120 RemoveQuotaForOrigin(PersistenceType aPersistenceType,
michael@0 121 const nsACString& aGroup,
michael@0 122 const nsACString& aOrigin)
michael@0 123 {
michael@0 124 MutexAutoLock lock(mQuotaMutex);
michael@0 125 LockedRemoveQuotaForOrigin(aPersistenceType, aGroup, aOrigin);
michael@0 126 }
michael@0 127
michael@0 128 void
michael@0 129 RemoveQuotaForPattern(PersistenceType aPersistenceType,
michael@0 130 const nsACString& aPattern);
michael@0 131
michael@0 132 already_AddRefed<QuotaObject>
michael@0 133 GetQuotaObject(PersistenceType aPersistenceType,
michael@0 134 const nsACString& aGroup,
michael@0 135 const nsACString& aOrigin,
michael@0 136 nsIFile* aFile);
michael@0 137
michael@0 138 already_AddRefed<QuotaObject>
michael@0 139 GetQuotaObject(PersistenceType aPersistenceType,
michael@0 140 const nsACString& aGroup,
michael@0 141 const nsACString& aOrigin,
michael@0 142 const nsAString& aPath);
michael@0 143
michael@0 144 // Set the Window that the current thread is doing operations for.
michael@0 145 // The caller is responsible for ensuring that aWindow is held alive.
michael@0 146 static void
michael@0 147 SetCurrentWindow(nsPIDOMWindow* aWindow)
michael@0 148 {
michael@0 149 QuotaManager* quotaManager = Get();
michael@0 150 NS_ASSERTION(quotaManager, "Must have a manager here!");
michael@0 151
michael@0 152 quotaManager->SetCurrentWindowInternal(aWindow);
michael@0 153 }
michael@0 154
michael@0 155 static void
michael@0 156 CancelPromptsForWindow(nsPIDOMWindow* aWindow)
michael@0 157 {
michael@0 158 NS_ASSERTION(aWindow, "Passed null window!");
michael@0 159
michael@0 160 QuotaManager* quotaManager = Get();
michael@0 161 NS_ASSERTION(quotaManager, "Must have a manager here!");
michael@0 162
michael@0 163 quotaManager->CancelPromptsForWindowInternal(aWindow);
michael@0 164 }
michael@0 165
michael@0 166 // Called when a storage is created.
michael@0 167 bool
michael@0 168 RegisterStorage(nsIOfflineStorage* aStorage);
michael@0 169
michael@0 170 // Called when a storage is being unlinked or destroyed.
michael@0 171 void
michael@0 172 UnregisterStorage(nsIOfflineStorage* aStorage);
michael@0 173
michael@0 174 // Called when a storage has been closed.
michael@0 175 void
michael@0 176 OnStorageClosed(nsIOfflineStorage* aStorage);
michael@0 177
michael@0 178 // Called when a window is being purged from the bfcache or the user leaves
michael@0 179 // a page which isn't going into the bfcache. Forces any live storage
michael@0 180 // objects to close themselves and aborts any running transactions.
michael@0 181 void
michael@0 182 AbortCloseStoragesForWindow(nsPIDOMWindow* aWindow);
michael@0 183
michael@0 184 // Used to check if there are running transactions in a given window.
michael@0 185 bool
michael@0 186 HasOpenTransactions(nsPIDOMWindow* aWindow);
michael@0 187
michael@0 188 // Waits for storages to be cleared and for version change transactions to
michael@0 189 // complete before dispatching the given runnable.
michael@0 190 nsresult
michael@0 191 WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern,
michael@0 192 Nullable<PersistenceType> aPersistenceType,
michael@0 193 const nsACString& aId, nsIRunnable* aRunnable);
michael@0 194
michael@0 195 // Acquire exclusive access to the storage given (waits for all others to
michael@0 196 // close). If storages need to close first, the callback will be invoked
michael@0 197 // with an array of said storages.
michael@0 198 nsresult
michael@0 199 AcquireExclusiveAccess(nsIOfflineStorage* aStorage,
michael@0 200 const nsACString& aOrigin,
michael@0 201 Nullable<PersistenceType> aPersistenceType,
michael@0 202 AcquireListener* aListener,
michael@0 203 WaitingOnStoragesCallback aCallback,
michael@0 204 void* aClosure)
michael@0 205 {
michael@0 206 NS_ASSERTION(aStorage, "Need a storage here!");
michael@0 207 return AcquireExclusiveAccess(aOrigin, aPersistenceType, aStorage,
michael@0 208 aListener, aCallback, aClosure);
michael@0 209 }
michael@0 210
michael@0 211 nsresult
michael@0 212 AcquireExclusiveAccess(const nsACString& aOrigin,
michael@0 213 Nullable<PersistenceType> aPersistenceType,
michael@0 214 AcquireListener* aListener,
michael@0 215 WaitingOnStoragesCallback aCallback,
michael@0 216 void* aClosure)
michael@0 217 {
michael@0 218 return AcquireExclusiveAccess(aOrigin, aPersistenceType, nullptr,
michael@0 219 aListener, aCallback, aClosure);
michael@0 220 }
michael@0 221
michael@0 222 void
michael@0 223 AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
michael@0 224 Nullable<PersistenceType> aPersistenceType,
michael@0 225 const nsACString& aId);
michael@0 226
michael@0 227 bool
michael@0 228 IsClearOriginPending(const nsACString& aPattern,
michael@0 229 Nullable<PersistenceType> aPersistenceType)
michael@0 230 {
michael@0 231 return !!FindSynchronizedOp(aPattern, aPersistenceType, EmptyCString());
michael@0 232 }
michael@0 233
michael@0 234 nsresult
michael@0 235 GetDirectoryForOrigin(PersistenceType aPersistenceType,
michael@0 236 const nsACString& aASCIIOrigin,
michael@0 237 nsIFile** aDirectory) const;
michael@0 238
michael@0 239 nsresult
michael@0 240 EnsureOriginIsInitialized(PersistenceType aPersistenceType,
michael@0 241 const nsACString& aGroup,
michael@0 242 const nsACString& aOrigin,
michael@0 243 bool aTrackQuota,
michael@0 244 nsIFile** aDirectory);
michael@0 245
michael@0 246 void
michael@0 247 OriginClearCompleted(PersistenceType aPersistenceType,
michael@0 248 const OriginOrPatternString& aOriginOrPattern);
michael@0 249
michael@0 250 void
michael@0 251 ResetOrClearCompleted();
michael@0 252
michael@0 253 void
michael@0 254 AssertCurrentThreadOwnsQuotaMutex()
michael@0 255 {
michael@0 256 mQuotaMutex.AssertCurrentThreadOwns();
michael@0 257 }
michael@0 258
michael@0 259 nsIThread*
michael@0 260 IOThread()
michael@0 261 {
michael@0 262 NS_ASSERTION(mIOThread, "This should never be null!");
michael@0 263 return mIOThread;
michael@0 264 }
michael@0 265
michael@0 266 already_AddRefed<Client>
michael@0 267 GetClient(Client::Type aClientType);
michael@0 268
michael@0 269 const nsString&
michael@0 270 GetStoragePath(PersistenceType aPersistenceType) const
michael@0 271 {
michael@0 272 if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
michael@0 273 return mPersistentStoragePath;
michael@0 274 }
michael@0 275
michael@0 276 NS_ASSERTION(aPersistenceType == PERSISTENCE_TYPE_TEMPORARY, "Huh?");
michael@0 277
michael@0 278 return mTemporaryStoragePath;
michael@0 279 }
michael@0 280
michael@0 281 uint64_t
michael@0 282 GetGroupLimit() const;
michael@0 283
michael@0 284 static uint32_t
michael@0 285 GetStorageQuotaMB();
michael@0 286
michael@0 287 static void
michael@0 288 GetStorageId(PersistenceType aPersistenceType,
michael@0 289 const nsACString& aOrigin,
michael@0 290 Client::Type aClientType,
michael@0 291 const nsAString& aName,
michael@0 292 nsACString& aDatabaseId);
michael@0 293
michael@0 294 static nsresult
michael@0 295 GetInfoFromURI(nsIURI* aURI,
michael@0 296 uint32_t aAppId,
michael@0 297 bool aInMozBrowser,
michael@0 298 nsACString* aGroup,
michael@0 299 nsACString* aASCIIOrigin,
michael@0 300 StoragePrivilege* aPrivilege,
michael@0 301 PersistenceType* aDefaultPersistenceType);
michael@0 302
michael@0 303 static nsresult
michael@0 304 GetInfoFromPrincipal(nsIPrincipal* aPrincipal,
michael@0 305 nsACString* aGroup,
michael@0 306 nsACString* aASCIIOrigin,
michael@0 307 StoragePrivilege* aPrivilege,
michael@0 308 PersistenceType* aDefaultPersistenceType);
michael@0 309
michael@0 310 static nsresult
michael@0 311 GetInfoFromWindow(nsPIDOMWindow* aWindow,
michael@0 312 nsACString* aGroup,
michael@0 313 nsACString* aASCIIOrigin,
michael@0 314 StoragePrivilege* aPrivilege,
michael@0 315 PersistenceType* aDefaultPersistenceType);
michael@0 316
michael@0 317 static void
michael@0 318 GetInfoForChrome(nsACString* aGroup,
michael@0 319 nsACString* aASCIIOrigin,
michael@0 320 StoragePrivilege* aPrivilege,
michael@0 321 PersistenceType* aDefaultPersistenceType);
michael@0 322
michael@0 323 static void
michael@0 324 GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly,
michael@0 325 const nsACString& aOrigin, nsAutoCString& _retval)
michael@0 326 {
michael@0 327 return GetOriginPatternString(aAppId,
michael@0 328 aBrowserOnly ? MozBrowser : NotMozBrowser,
michael@0 329 aOrigin, _retval);
michael@0 330 }
michael@0 331
michael@0 332 static void
michael@0 333 GetOriginPatternStringMaybeIgnoreBrowser(uint32_t aAppId, bool aBrowserOnly,
michael@0 334 nsAutoCString& _retval)
michael@0 335 {
michael@0 336 return GetOriginPatternString(aAppId,
michael@0 337 aBrowserOnly ? MozBrowser : IgnoreMozBrowser,
michael@0 338 EmptyCString(), _retval);
michael@0 339 }
michael@0 340
michael@0 341 private:
michael@0 342 QuotaManager();
michael@0 343
michael@0 344 virtual ~QuotaManager();
michael@0 345
michael@0 346 nsresult
michael@0 347 Init();
michael@0 348
michael@0 349 void
michael@0 350 SetCurrentWindowInternal(nsPIDOMWindow* aWindow);
michael@0 351
michael@0 352 void
michael@0 353 CancelPromptsForWindowInternal(nsPIDOMWindow* aWindow);
michael@0 354
michael@0 355 // Determine if the quota is lifted for the Window the current thread is
michael@0 356 // using.
michael@0 357 bool
michael@0 358 LockedQuotaIsLifted();
michael@0 359
michael@0 360 uint64_t
michael@0 361 LockedCollectOriginsForEviction(uint64_t aMinSizeToBeFreed,
michael@0 362 nsTArray<OriginInfo*>& aOriginInfos);
michael@0 363
michael@0 364 void
michael@0 365 LockedRemoveQuotaForOrigin(PersistenceType aPersistenceType,
michael@0 366 const nsACString& aGroup,
michael@0 367 const nsACString& aOrigin);
michael@0 368
michael@0 369 nsresult
michael@0 370 AcquireExclusiveAccess(const nsACString& aOrigin,
michael@0 371 Nullable<PersistenceType> aPersistenceType,
michael@0 372 nsIOfflineStorage* aStorage,
michael@0 373 AcquireListener* aListener,
michael@0 374 WaitingOnStoragesCallback aCallback,
michael@0 375 void* aClosure);
michael@0 376
michael@0 377 void
michael@0 378 AddSynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
michael@0 379 Nullable<PersistenceType> aPersistenceType);
michael@0 380
michael@0 381 nsresult
michael@0 382 RunSynchronizedOp(nsIOfflineStorage* aStorage,
michael@0 383 SynchronizedOp* aOp);
michael@0 384
michael@0 385 SynchronizedOp*
michael@0 386 FindSynchronizedOp(const nsACString& aPattern,
michael@0 387 Nullable<PersistenceType> aPersistenceType,
michael@0 388 const nsACString& aId);
michael@0 389
michael@0 390 nsresult
michael@0 391 MaybeUpgradeIndexedDBDirectory();
michael@0 392
michael@0 393 nsresult
michael@0 394 InitializeOrigin(PersistenceType aPersistenceType,
michael@0 395 const nsACString& aGroup,
michael@0 396 const nsACString& aOrigin,
michael@0 397 bool aTrackQuota,
michael@0 398 int64_t aAccessTime,
michael@0 399 nsIFile* aDirectory);
michael@0 400
michael@0 401 nsresult
michael@0 402 ClearStoragesForApp(uint32_t aAppId, bool aBrowserOnly);
michael@0 403
michael@0 404 void
michael@0 405 CheckTemporaryStorageLimits();
michael@0 406
michael@0 407 // Collect inactive and the least recently used origins.
michael@0 408 uint64_t
michael@0 409 CollectOriginsForEviction(uint64_t aMinSizeToBeFreed,
michael@0 410 nsTArray<OriginInfo*>& aOriginInfos);
michael@0 411
michael@0 412 void
michael@0 413 DeleteTemporaryFilesForOrigin(const nsACString& aOrigin);
michael@0 414
michael@0 415 void
michael@0 416 FinalizeOriginEviction(nsTArray<nsCString>& aOrigins);
michael@0 417
michael@0 418 void
michael@0 419 SaveOriginAccessTime(const nsACString& aOrigin, int64_t aTimestamp);
michael@0 420
michael@0 421 void
michael@0 422 ReleaseIOThreadObjects()
michael@0 423 {
michael@0 424 AssertIsOnIOThread();
michael@0 425
michael@0 426 for (uint32_t index = 0; index < Client::TYPE_MAX; index++) {
michael@0 427 mClients[index]->ReleaseIOThreadObjects();
michael@0 428 }
michael@0 429 }
michael@0 430
michael@0 431 static void
michael@0 432 GetOriginPatternString(uint32_t aAppId,
michael@0 433 MozBrowserPatternFlag aBrowserFlag,
michael@0 434 const nsACString& aOrigin,
michael@0 435 nsAutoCString& _retval);
michael@0 436
michael@0 437 static PLDHashOperator
michael@0 438 RemoveQuotaForPersistenceTypeCallback(const nsACString& aKey,
michael@0 439 nsAutoPtr<GroupInfoPair>& aValue,
michael@0 440 void* aUserArg);
michael@0 441
michael@0 442 static PLDHashOperator
michael@0 443 RemoveQuotaCallback(const nsACString& aKey,
michael@0 444 nsAutoPtr<GroupInfoPair>& aValue,
michael@0 445 void* aUserArg);
michael@0 446
michael@0 447 static PLDHashOperator
michael@0 448 RemoveQuotaForPatternCallback(const nsACString& aKey,
michael@0 449 nsAutoPtr<GroupInfoPair>& aValue,
michael@0 450 void* aUserArg);
michael@0 451
michael@0 452 static PLDHashOperator
michael@0 453 GetOriginsExceedingGroupLimit(const nsACString& aKey,
michael@0 454 GroupInfoPair* aValue,
michael@0 455 void* aUserArg);
michael@0 456
michael@0 457 static PLDHashOperator
michael@0 458 GetAllTemporaryStorageOrigins(const nsACString& aKey,
michael@0 459 GroupInfoPair* aValue,
michael@0 460 void* aUserArg);
michael@0 461
michael@0 462 static PLDHashOperator
michael@0 463 AddTemporaryStorageOrigins(const nsACString& aKey,
michael@0 464 ArrayCluster<nsIOfflineStorage*>* aValue,
michael@0 465 void* aUserArg);
michael@0 466
michael@0 467 static PLDHashOperator
michael@0 468 GetInactiveTemporaryStorageOrigins(const nsACString& aKey,
michael@0 469 GroupInfoPair* aValue,
michael@0 470 void* aUserArg);
michael@0 471
michael@0 472 // TLS storage index for the current thread's window.
michael@0 473 unsigned int mCurrentWindowIndex;
michael@0 474
michael@0 475 mozilla::Mutex mQuotaMutex;
michael@0 476
michael@0 477 nsClassHashtable<nsCStringHashKey, GroupInfoPair> mGroupInfoPairs;
michael@0 478
michael@0 479 // A map of Windows to the corresponding quota helper.
michael@0 480 nsRefPtrHashtable<nsPtrHashKey<nsPIDOMWindow>,
michael@0 481 CheckQuotaHelper> mCheckQuotaHelpers;
michael@0 482
michael@0 483 // Maintains a list of live storages per origin.
michael@0 484 nsClassHashtable<nsCStringHashKey,
michael@0 485 ArrayCluster<nsIOfflineStorage*> > mLiveStorages;
michael@0 486
michael@0 487 // Maintains a list of synchronized operatons that are in progress or queued.
michael@0 488 nsAutoTArray<nsAutoPtr<SynchronizedOp>, 5> mSynchronizedOps;
michael@0 489
michael@0 490 // Thread on which IO is performed.
michael@0 491 nsCOMPtr<nsIThread> mIOThread;
michael@0 492
michael@0 493 // A timer that gets activated at shutdown to ensure we close all storages.
michael@0 494 nsCOMPtr<nsITimer> mShutdownTimer;
michael@0 495
michael@0 496 // A list of all successfully initialized origins. This list isn't protected
michael@0 497 // by any mutex but it is only ever touched on the IO thread.
michael@0 498 nsTArray<nsCString> mInitializedOrigins;
michael@0 499
michael@0 500 nsAutoTArray<nsRefPtr<Client>, Client::TYPE_MAX> mClients;
michael@0 501
michael@0 502 nsString mIndexedDBPath;
michael@0 503 nsString mPersistentStoragePath;
michael@0 504 nsString mTemporaryStoragePath;
michael@0 505
michael@0 506 uint64_t mTemporaryStorageLimit;
michael@0 507 uint64_t mTemporaryStorageUsage;
michael@0 508 bool mTemporaryStorageInitialized;
michael@0 509
michael@0 510 bool mStorageAreaInitialized;
michael@0 511 };
michael@0 512
michael@0 513 class AutoEnterWindow
michael@0 514 {
michael@0 515 public:
michael@0 516 AutoEnterWindow(nsPIDOMWindow* aWindow)
michael@0 517 {
michael@0 518 QuotaManager::SetCurrentWindow(aWindow);
michael@0 519 }
michael@0 520
michael@0 521 ~AutoEnterWindow()
michael@0 522 {
michael@0 523 QuotaManager::SetCurrentWindow(nullptr);
michael@0 524 }
michael@0 525 };
michael@0 526
michael@0 527 END_QUOTA_NAMESPACE
michael@0 528
michael@0 529 #endif /* mozilla_dom_quota_quotamanager_h__ */

mercurial