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 CHROME_BROWSER_FONT_FAMILY_CACHE_H_ 6 #define CHROME_BROWSER_FONT_FAMILY_CACHE_H_ 7 8 #include "base/containers/hash_tables.h" 9 #include "base/gtest_prod_util.h" 10 #include "base/prefs/pref_change_registrar.h" 11 #include "base/strings/string16.h" 12 #include "base/supports_user_data.h" 13 #include "content/public/browser/notification_observer.h" 14 #include "content/public/browser/notification_registrar.h" 15 #include "content/public/common/web_preferences.h" 16 17 class PrefService; 18 class Profile; 19 20 FORWARD_DECLARE_TEST(FontFamilyCacheTest, Caching); 21 22 // Caches font family preferences associated with a PrefService. This class 23 // relies on the assumption that each concatenation of map_name + '.' + script 24 // is a unique string. It also relies on the assumption that the (const char*) 25 // keys used in both inner and outer hash_maps are compile time constants. 26 class FontFamilyCache : public base::SupportsUserData::Data, 27 public content::NotificationObserver { 28 public: 29 explicit FontFamilyCache(Profile* profile); 30 virtual ~FontFamilyCache(); 31 32 // Gets or creates the relevant FontFamilyCache, and then fills |map|. 33 static void FillFontFamilyMap(Profile* profile, 34 const char* map_name, 35 content::ScriptFontFamilyMap* map); 36 37 // Fills |map| with font family preferences. 38 void FillFontFamilyMap(const char* map_name, 39 content::ScriptFontFamilyMap* map); 40 41 protected: 42 // Exposed and virtual for testing. 43 // Fetches the font without checking the cache. 44 virtual base::string16 FetchFont(const char* script, const char* map_name); 45 46 private: 47 FRIEND_TEST_ALL_PREFIXES(::FontFamilyCacheTest, Caching); 48 49 // Map from script to font. 50 // Key comparison uses pointer equality. 51 typedef base::hash_map<const char*, base::string16> ScriptFontMap; 52 53 // Map from font family to ScriptFontMap. 54 // Key comparison uses pointer equality. 55 typedef base::hash_map<const char*, ScriptFontMap> FontFamilyMap; 56 57 // Checks the cache for the font. If not present, fetches the font and stores 58 // the result in the cache. 59 // This method needs to be very fast, because it's called ~20,000 times on a 60 // fresh launch with an empty profile. It's important to avoid unnecessary 61 // object construction, hence the heavy use of const char* and the minimal use 62 // of std::string. 63 // |script| and |map_name| must be compile time constants. Two behaviors rely 64 // on this: key comparison uses pointer equality, and keys must outlive the 65 // hash_maps. 66 base::string16 FetchAndCacheFont(const char* script, const char* map_name); 67 68 // Called when font family preferences changed. 69 // Invalidates the cached entry, and removes the relevant observer. 70 // Note: It is safe to remove the observer from the pref change callback. 71 void OnPrefsChanged(const std::string& pref_name); 72 73 // content::NotificationObserver override. 74 // Called when the profile is being destructed. 75 virtual void Observe(int type, 76 const content::NotificationSource& source, 77 const content::NotificationDetails& details) OVERRIDE; 78 79 // Cache of font family preferences. 80 FontFamilyMap font_family_map_; 81 82 // Weak reference. 83 // Note: The lifetime of this object is tied to the lifetime of the 84 // PrefService, so there is no worry about an invalid pointer. 85 const PrefService* prefs_; 86 87 // Reacts to profile changes. 88 PrefChangeRegistrar profile_pref_registrar_; 89 90 // Listens for profile destruction. 91 content::NotificationRegistrar notification_registrar_; 92 93 DISALLOW_COPY_AND_ASSIGN(FontFamilyCache); 94 }; 95 96 #endif // CHROME_BROWSER_FONT_FAMILY_CACHE_H_ 97