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.
5 #ifndef CHROME_BROWSER_FONT_FAMILY_CACHE_H_
6 #define CHROME_BROWSER_FONT_FAMILY_CACHE_H_
8 #include <unordered_map>
10 #include "base/gtest_prod_util.h"
11 #include "base/macros.h"
12 #include "base/strings/string16.h"
13 #include "base/supports_user_data.h"
14 #include "chrome/browser/font_pref_change_notifier.h"
15 #include "content/public/common/web_preferences.h"
20 FORWARD_DECLARE_TEST(FontFamilyCacheTest, Caching);
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 maps are compile time constants.
26 // This class caches the strings necessary to update
27 // "content::ScriptFontFamilyMap". This is necessary since Chrome attempts to
28 // update content::ScriptFontFamilyMap 20000 times at startup. See
29 // https://crbug.com/308095.
30 class FontFamilyCache : public base::SupportsUserData::Data {
32 explicit FontFamilyCache(Profile* profile);
33 ~FontFamilyCache() override;
35 // Gets or creates the relevant FontFamilyCache, and then fills |map|.
36 static void FillFontFamilyMap(Profile* profile,
38 content::ScriptFontFamilyMap* map);
40 // Fills |map| with font family preferences.
41 void FillFontFamilyMap(const char* map_name,
42 content::ScriptFontFamilyMap* map);
45 // Exposed and virtual for testing.
46 // Fetches the font without checking the cache.
47 virtual base::string16 FetchFont(const char* script, const char* map_name);
50 FRIEND_TEST_ALL_PREFIXES(::FontFamilyCacheTest, Caching);
52 // Map from script to font.
53 // Key comparison uses pointer equality.
54 using ScriptFontMap = std::unordered_map<const char*, base::string16>;
56 // Map from font family to ScriptFontMap.
57 // Key comparison uses pointer equality.
58 using FontFamilyMap = std::unordered_map<const char*, ScriptFontMap>;
60 // Checks the cache for the font. If not present, fetches the font and stores
61 // the result in the cache.
62 // This method needs to be very fast, because it's called ~20,000 times on a
63 // fresh launch with an empty profile. It's important to avoid unnecessary
64 // object construction, hence the heavy use of const char* and the minimal use
66 // |script| and |map_name| must be compile time constants. Two behaviors rely
67 // on this: key comparison uses pointer equality, and keys must outlive the
69 base::string16 FetchAndCacheFont(const char* script, const char* map_name);
71 // Called when font family preferences changed.
72 // Invalidates the cached entry, and removes the relevant observer.
73 // Note: It is safe to remove the observer from the pref change callback.
74 void OnPrefsChanged(const std::string& pref_name);
76 // Cache of font family preferences.
77 FontFamilyMap font_family_map_;
80 // Note: The lifetime of this object is tied to the lifetime of the
81 // PrefService, so there is no worry about an invalid pointer.
82 const PrefService* prefs_;
84 // Reacts to profile font changes. |font_change_registrar_| will be
85 // automatically unregistered when the FontPrefChangeNotifier is destroyed as
86 // part of Profile destruction, thus ensuring safe unregistration even though
87 // |this| is destroyed after the Profile destructor completes as part of
88 // Profile's super class destructor ~base::SupportsUserData.
89 FontPrefChangeNotifier::Registrar font_change_registrar_;
91 DISALLOW_COPY_AND_ASSIGN(FontFamilyCache);
94 #endif // CHROME_BROWSER_FONT_FAMILY_CACHE_H_