DirectoryMetadata.cpp (4150B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "DirectoryMetadata.h" 8 9 #include "mozilla/Result.h" 10 #include "mozilla/TypedEnumBits.h" 11 #include "mozilla/dom/quota/Assertions.h" 12 #include "mozilla/dom/quota/CommonMetadata.h" 13 #include "mozilla/dom/quota/QuotaCommon.h" 14 #include "mozilla/dom/quota/ResultExtensions.h" 15 #include "mozilla/dom/quota/StreamUtils.h" 16 #include "nsIBinaryInputStream.h" 17 #include "nsIBinaryOutputStream.h" 18 19 namespace mozilla::dom::quota { 20 21 // clang-format off 22 23 enum class DirectoryMetadataFlags : uint32_t { 24 None = 0, 25 Initialized = 1 << 0, 26 Accessed = 1 << 1, 27 }; 28 29 // clang-format on 30 31 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DirectoryMetadataFlags) 32 33 Result<OriginStateMetadata, nsresult> ReadDirectoryMetadataHeader( 34 nsIBinaryInputStream& aStream) { 35 AssertIsOnIOThread(); 36 37 OriginStateMetadata originStateMetadata; 38 39 QM_TRY_UNWRAP(originStateMetadata.mLastAccessTime, 40 MOZ_TO_RESULT_INVOKE_MEMBER(aStream, Read64)); 41 42 QM_TRY_UNWRAP(originStateMetadata.mPersisted, 43 MOZ_TO_RESULT_INVOKE_MEMBER(aStream, ReadBoolean)); 44 45 QM_TRY_INSPECT(const uint32_t& rawFlags, 46 MOZ_TO_RESULT_INVOKE_MEMBER(aStream, Read32)); 47 48 auto flags = static_cast<DirectoryMetadataFlags>(rawFlags); 49 50 // If DirectoryMetadataFlags::Initialized is not set, the flags field 51 // contains no valid data. Since mAccessed indicates whether a full scan must 52 // be done during initialization, we conservatively set it to true when the 53 // access state is unknown. 54 originStateMetadata.mAccessed = 55 rawFlags == 0 || (flags & DirectoryMetadataFlags::Accessed) != 56 DirectoryMetadataFlags::None; 57 58 QM_TRY_UNWRAP(originStateMetadata.mLastMaintenanceDate, 59 MOZ_TO_RESULT_INVOKE_MEMBER(aStream, Read32)); 60 61 return originStateMetadata; 62 } 63 64 nsresult WriteDirectoryMetadataHeader( 65 nsIBinaryOutputStream& aStream, 66 const OriginStateMetadata& aOriginStateMetadata) { 67 AssertIsOnIOThread(); 68 69 QM_TRY(MOZ_TO_RESULT(aStream.Write64(aOriginStateMetadata.mLastAccessTime))); 70 71 QM_TRY(MOZ_TO_RESULT(aStream.WriteBoolean(aOriginStateMetadata.mPersisted))); 72 73 // Always set DirectoryMetadataFlags::Initialized when writing new metadata, 74 // to mark the flags field as valid. This distinguishes real flags from older 75 // files where the field was reserved and always written as zero. 76 auto flags = 77 DirectoryMetadataFlags::Initialized | 78 (aOriginStateMetadata.mAccessed ? DirectoryMetadataFlags::Accessed 79 : DirectoryMetadataFlags::None); 80 81 auto rawFlags = static_cast<uint32_t>(flags); 82 83 QM_TRY(MOZ_TO_RESULT(aStream.Write32(rawFlags))); 84 85 QM_TRY(MOZ_TO_RESULT( 86 aStream.Write32(aOriginStateMetadata.mLastMaintenanceDate))); 87 88 return NS_OK; 89 } 90 91 Result<OriginStateMetadata, nsresult> LoadDirectoryMetadataHeader( 92 nsIFile& aDirectory) { 93 AssertIsOnIOThread(); 94 95 QM_TRY_INSPECT( 96 const auto& stream, 97 GetBinaryInputStream(aDirectory, nsLiteralString(METADATA_V2_FILE_NAME))); 98 99 QM_TRY_INSPECT(const OriginStateMetadata& originStateMetadata, 100 ReadDirectoryMetadataHeader(*stream)); 101 102 QM_TRY(MOZ_TO_RESULT(stream->Close())); 103 104 return originStateMetadata; 105 } 106 107 nsresult SaveDirectoryMetadataHeader( 108 nsIFile& aDirectory, const OriginStateMetadata& aOriginStateMetadata) { 109 AssertIsOnIOThread(); 110 111 QM_TRY_INSPECT( 112 const auto& file, 113 CloneFileAndAppend(aDirectory, nsLiteralString(METADATA_V2_FILE_NAME))); 114 115 QM_TRY_INSPECT(const auto& stream, 116 GetBinaryOutputStream(*file, FileFlag::Update)); 117 MOZ_ASSERT(stream); 118 119 QM_TRY(MOZ_TO_RESULT( 120 WriteDirectoryMetadataHeader(*stream, aOriginStateMetadata))); 121 122 QM_TRY(MOZ_TO_RESULT(stream->Flush())); 123 124 QM_TRY(MOZ_TO_RESULT(stream->Close())); 125 126 return NS_OK; 127 } 128 129 } // namespace mozilla::dom::quota