1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_CACHE_H_ 6 #define COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_CACHE_H_ 7 8 #include <string> 9 10 #include "base/callback.h" 11 #include "base/files/file_path.h" 12 #include "base/gtest_prod_util.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted_memory.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/threading/thread_checker.h" 17 #include "components/search_provider_logos/logo_common.h" 18 19 namespace search_provider_logos { 20 21 // A file-based cache for the search provider's logo. This allows clients to 22 // store and retrieve a logo (of type EncodedLogo) and its associated metadata 23 // (of type LogoMetadata). Metadata can be updated independently from the logo 24 // to handle cases where, e.g. the expiration date changes, but the logo stays 25 // the same. If corruption is detected in the metadata or logo, the cache will 26 // be cleared. 27 // 28 // Note: this class must only be used on a single thread. All methods are 29 // are blocking, so this should not be used on the UI thread. 30 // 31 // The logo and its metadata are stored in files, so they persist even when 32 // Chrome is closed. Once loaded from disk, the metadata is kept in memory to 33 // enable quick retrieval. The logo is not kept around in memory because of its 34 // size. 35 class LogoCache { 36 public: 37 // Constructs a logo cache that stores data in |cache_directory|. 38 // |cache_directory| will be created if it does not already exist. 39 explicit LogoCache(const base::FilePath& cache_directory); 40 virtual ~LogoCache(); 41 42 // Updates the metadata for the cached logo. 43 virtual void UpdateCachedLogoMetadata(const LogoMetadata& metadata); 44 45 // Returns metadata for the cached logo, or NULL if logo is cached. 46 virtual const LogoMetadata* GetCachedLogoMetadata(); 47 48 // Sets the cached logo and metadata. |logo| may be NULL, in which case the 49 // cached logo and metadata will be cleared. 50 virtual void SetCachedLogo(const EncodedLogo* logo); 51 52 // Returns the cached logo, or NULL if no logo is cached or the cached logo is 53 // corrupt. 54 virtual scoped_ptr<EncodedLogo> GetCachedLogo(); 55 56 private: 57 FRIEND_TEST_ALL_PREFIXES(LogoCacheSerializationTest, SerializeMetadata); 58 FRIEND_TEST_ALL_PREFIXES(LogoCacheSerializationTest, 59 DeserializeCorruptMetadata); 60 FRIEND_TEST_ALL_PREFIXES(LogoCacheTest, StoreAndRetrieveMetadata); 61 FRIEND_TEST_ALL_PREFIXES(LogoCacheTest, RetrieveCorruptMetadata); 62 FRIEND_TEST_ALL_PREFIXES(LogoCacheTest, RetrieveCorruptLogo); 63 64 // Converts string |str| to a LogoMetadata object and returns it. Returns NULL 65 // if |str| cannot be converted. 66 static scoped_ptr<LogoMetadata> LogoMetadataFromString( 67 const std::string& str, int* logo_num_bytes); 68 69 // Converts |metadata| to a string and stores it in |str|. 70 static void LogoMetadataToString(const LogoMetadata& metadata, 71 int logo_num_bytes, 72 std::string* str); 73 74 // Returns the path where the cached logo will be saved. 75 base::FilePath GetLogoPath(); 76 77 // Returns the path where the metadata for the cached logo will be saved. 78 base::FilePath GetMetadataPath(); 79 80 // Updates the in-memory metadata. 81 void UpdateMetadata(scoped_ptr<LogoMetadata> metadata); 82 83 // If the cached logo's metadata isn't available in memory (i.e. 84 // |metadata_is_valid_| is false), reads it from disk and stores it in 85 // |metadata_|. If no logo is cached, |metadata_| will be updated to NULL. 86 void ReadMetadataIfNeeded(); 87 88 // Writes the metadata for the cached logo to disk. 89 void WriteMetadata(); 90 91 // Writes |metadata_| to the cached metadata file and |encoded_image| to the 92 // cached logo file. 93 void WriteLogo(scoped_refptr<base::RefCountedMemory> encoded_image); 94 95 // Deletes all the cache files. 96 void DeleteLogoAndMetadata(); 97 98 // Tries to create the cache directory if it does not already exist. Returns 99 // whether the cache directory exists. 100 bool EnsureCacheDirectoryExists(); 101 102 // The directory in which the cached logo and metadata will be saved. 103 base::FilePath cache_directory_; 104 105 // The metadata describing the cached logo, or NULL if no logo is cached. This 106 // value is meaningful iff |metadata_is_valid_| is true; otherwise, the 107 // metadata must be read from file and |metadata_| will be NULL. 108 // Note: Once read from file, metadata will be stored in memory indefinitely. 109 scoped_ptr<LogoMetadata> metadata_; 110 bool metadata_is_valid_; 111 112 // The number of bytes in the logo file, as recorded in the metadata file. 113 // Valid iff |metadata_is_valid_|. This is used to verify that the logo file 114 // is complete and corresponds to the current metadata file. 115 int logo_num_bytes_; 116 117 // Ensure LogoCache is only used on a single thread. 118 base::ThreadChecker thread_checker_; 119 120 DISALLOW_COPY_AND_ASSIGN(LogoCache); 121 }; 122 123 } // namespace search_provider_logos 124 125 #endif // COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_CACHE_H_ 126