OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 UI_BASE_RESOURCE_RESOURCE_BUNDLE_H_ | |
6 #define UI_BASE_RESOURCE_RESOURCE_BUNDLE_H_ | |
7 | |
8 #include <map> | |
9 #include <string> | |
10 | |
11 #include "base/basictypes.h" | |
12 #include "base/containers/hash_tables.h" | |
13 #include "base/files/file_path.h" | |
14 #include "base/files/memory_mapped_file.h" | |
15 #include "base/gtest_prod_util.h" | |
16 #include "base/memory/scoped_ptr.h" | |
17 #include "base/memory/scoped_vector.h" | |
18 #include "base/strings/string16.h" | |
19 #include "base/strings/string_piece.h" | |
20 #include "build/build_config.h" | |
21 #include "ui/base/layout.h" | |
22 #include "ui/base/ui_base_export.h" | |
23 #include "ui/gfx/font_list.h" | |
24 #include "ui/gfx/image/image.h" | |
25 #include "ui/gfx/native_widget_types.h" | |
26 | |
27 class SkBitmap; | |
28 | |
29 namespace base { | |
30 class File; | |
31 class Lock; | |
32 class RefCountedStaticMemory; | |
33 } | |
34 | |
35 namespace ui { | |
36 | |
37 class DataPack; | |
38 class ResourceHandle; | |
39 | |
40 // ResourceBundle is a central facility to load images and other resources, | |
41 // such as theme graphics. Every resource is loaded only once. | |
42 class UI_BASE_EXPORT ResourceBundle { | |
43 public: | |
44 // An enumeration of the various font styles used throughout Chrome. | |
45 // The following holds true for the font sizes: | |
46 // Small <= SmallBold <= Base <= Bold <= Medium <= MediumBold <= Large. | |
47 enum FontStyle { | |
48 // NOTE: depending upon the locale, using one of the *BoldFont below | |
49 // may *not* actually result in a bold font. | |
50 SmallFont, | |
51 SmallBoldFont, | |
52 BaseFont, | |
53 BoldFont, | |
54 MediumFont, | |
55 MediumBoldFont, | |
56 LargeFont, | |
57 LargeBoldFont, | |
58 }; | |
59 | |
60 enum ImageRTL { | |
61 // Images are flipped in RTL locales. | |
62 RTL_ENABLED, | |
63 // Images are never flipped. | |
64 RTL_DISABLED, | |
65 }; | |
66 | |
67 enum LoadResources { | |
68 LOAD_COMMON_RESOURCES, | |
69 DO_NOT_LOAD_COMMON_RESOURCES | |
70 }; | |
71 | |
72 // Delegate class that allows interception of pack file loading and resource | |
73 // requests. The methods of this class may be called on multiple threads. | |
74 class Delegate { | |
75 public: | |
76 // Called before a resource pack file is loaded. Return the full path for | |
77 // the pack file to continue loading or an empty value to cancel loading. | |
78 // |pack_path| will contain the complete default path for the pack file if | |
79 // known or just the pack file name otherwise. | |
80 virtual base::FilePath GetPathForResourcePack( | |
81 const base::FilePath& pack_path, | |
82 ScaleFactor scale_factor) = 0; | |
83 | |
84 // Called before a locale pack file is loaded. Return the full path for | |
85 // the pack file to continue loading or an empty value to cancel loading. | |
86 // |pack_path| will contain the complete default path for the pack file if | |
87 // known or just the pack file name otherwise. | |
88 virtual base::FilePath GetPathForLocalePack( | |
89 const base::FilePath& pack_path, | |
90 const std::string& locale) = 0; | |
91 | |
92 // Return an image resource or an empty value to attempt retrieval of the | |
93 // default resource. | |
94 virtual gfx::Image GetImageNamed(int resource_id) = 0; | |
95 | |
96 // Return an image resource or an empty value to attempt retrieval of the | |
97 // default resource. | |
98 virtual gfx::Image GetNativeImageNamed(int resource_id, ImageRTL rtl) = 0; | |
99 | |
100 // Return a static memory resource or NULL to attempt retrieval of the | |
101 // default resource. | |
102 virtual base::RefCountedStaticMemory* LoadDataResourceBytes( | |
103 int resource_id, | |
104 ScaleFactor scale_factor) = 0; | |
105 | |
106 // Retrieve a raw data resource. Return true if a resource was provided or | |
107 // false to attempt retrieval of the default resource. | |
108 virtual bool GetRawDataResource(int resource_id, | |
109 ScaleFactor scale_factor, | |
110 base::StringPiece* value) = 0; | |
111 | |
112 // Retrieve a localized string. Return true if a string was provided or | |
113 // false to attempt retrieval of the default string. | |
114 virtual bool GetLocalizedString(int message_id, base::string16* value) = 0; | |
115 | |
116 // Returns a font or NULL to attempt retrieval of the default resource. | |
117 virtual scoped_ptr<gfx::Font> GetFont(FontStyle style) = 0; | |
118 | |
119 protected: | |
120 virtual ~Delegate() {} | |
121 }; | |
122 | |
123 // Initialize the ResourceBundle for this process. Does not take ownership of | |
124 // the |delegate| value. Returns the language selected. | |
125 // NOTE: Mac ignores this and always loads up resources for the language | |
126 // defined by the Cocoa UI (i.e., NSBundle does the language work). | |
127 // | |
128 // TODO(sergeyu): This method also loads common resources (i.e. chrome.pak). | |
129 // There is no way to specify which resource files are loaded, i.e. names of | |
130 // the files are hardcoded in ResourceBundle. Fix it to allow to specify which | |
131 // files are loaded (e.g. add a new method in Delegate). | |
132 // |load_resources| controls whether or not LoadCommonResources is called. | |
133 static std::string InitSharedInstanceWithLocale( | |
134 const std::string& pref_locale, | |
135 Delegate* delegate, | |
136 LoadResources load_resources); | |
137 | |
138 // Initialize the ResourceBundle using the given file region. If |region| is | |
139 // MemoryMappedFile::Region::kWholeFile, the entire |pak_file| is used. | |
140 // This allows the use of this function in a sandbox without local file | |
141 // access (as on Android). | |
142 static void InitSharedInstanceWithPakFileRegion( | |
143 base::File pak_file, | |
144 const base::MemoryMappedFile::Region& region); | |
145 | |
146 // Initialize the ResourceBundle using given data pack path for testing. | |
147 static void InitSharedInstanceWithPakPath(const base::FilePath& path); | |
148 | |
149 // Delete the ResourceBundle for this process if it exists. | |
150 static void CleanupSharedInstance(); | |
151 | |
152 // Returns true after the global resource loader instance has been created. | |
153 static bool HasSharedInstance(); | |
154 | |
155 // Return the global resource loader instance. | |
156 static ResourceBundle& GetSharedInstance(); | |
157 | |
158 // Check if the .pak for the given locale exists. | |
159 bool LocaleDataPakExists(const std::string& locale); | |
160 | |
161 // Registers additional data pack files with this ResourceBundle. When | |
162 // looking for a DataResource, we will search these files after searching the | |
163 // main module. |path| should be the complete path to the pack file if known | |
164 // or just the pack file name otherwise (the delegate may optionally override | |
165 // this value). |scale_factor| is the scale of images in this resource pak | |
166 // relative to the images in the 1x resource pak. This method is not thread | |
167 // safe! You should call it immediately after calling InitSharedInstance. | |
168 void AddDataPackFromPath(const base::FilePath& path, | |
169 ScaleFactor scale_factor); | |
170 | |
171 // Same as above but using an already open file. | |
172 void AddDataPackFromFile(base::File file, ScaleFactor scale_factor); | |
173 | |
174 // Same as above but using only a region (offset + size) of the file. | |
175 void AddDataPackFromFileRegion(base::File file, | |
176 const base::MemoryMappedFile::Region& region, | |
177 ScaleFactor scale_factor); | |
178 | |
179 // Same as AddDataPackFromPath but does not log an error if the pack fails to | |
180 // load. | |
181 void AddOptionalDataPackFromPath(const base::FilePath& path, | |
182 ScaleFactor scale_factor); | |
183 | |
184 // Changes the locale for an already-initialized ResourceBundle, returning the | |
185 // name of the newly-loaded locale. Future calls to get strings will return | |
186 // the strings for this new locale. This has no effect on existing or future | |
187 // image resources. |locale_resources_data_| is protected by a lock for the | |
188 // duration of the swap, as GetLocalizedString() may be concurrently invoked | |
189 // on another thread. | |
190 std::string ReloadLocaleResources(const std::string& pref_locale); | |
191 | |
192 // Gets image with the specified resource_id from the current module data. | |
193 // Returns a pointer to a shared instance of gfx::ImageSkia. This shared | |
194 // instance is owned by the resource bundle and should not be freed. | |
195 // TODO(pkotwicz): Make method return const gfx::ImageSkia* | |
196 // | |
197 // NOTE: GetNativeImageNamed is preferred for cross-platform gfx::Image use. | |
198 gfx::ImageSkia* GetImageSkiaNamed(int resource_id); | |
199 | |
200 // Gets an image resource from the current module data. This will load the | |
201 // image in Skia format by default. The ResourceBundle owns this. | |
202 gfx::Image& GetImageNamed(int resource_id); | |
203 | |
204 // Similar to GetImageNamed, but rather than loading the image in Skia format, | |
205 // it will load in the native platform type. This can avoid conversion from | |
206 // one image type to another. ResourceBundle owns the result. | |
207 // | |
208 // Note that if the same resource has already been loaded in GetImageNamed(), | |
209 // gfx::Image will perform a conversion, rather than using the native image | |
210 // loading code of ResourceBundle. | |
211 // | |
212 // If |rtl| is RTL_ENABLED then the image is flipped in RTL locales. | |
213 gfx::Image& GetNativeImageNamed(int resource_id, ImageRTL rtl); | |
214 | |
215 // Same as GetNativeImageNamed() except that RTL is not enabled. | |
216 gfx::Image& GetNativeImageNamed(int resource_id); | |
217 | |
218 // Loads the raw bytes of a scale independent data resource. | |
219 base::RefCountedStaticMemory* LoadDataResourceBytes(int resource_id) const; | |
220 | |
221 // Loads the raw bytes of a data resource nearest the scale factor | |
222 // |scale_factor| into |bytes|, without doing any processing or | |
223 // interpretation of the resource. Use ResourceHandle::SCALE_FACTOR_NONE | |
224 // for scale independent image resources (such as wallpaper). | |
225 // Returns NULL if we fail to read the resource. | |
226 base::RefCountedStaticMemory* LoadDataResourceBytesForScale( | |
227 int resource_id, | |
228 ScaleFactor scale_factor) const; | |
229 | |
230 // Return the contents of a scale independent resource in a | |
231 // StringPiece given the resource id | |
232 base::StringPiece GetRawDataResource(int resource_id) const; | |
233 | |
234 // Return the contents of a resource in a StringPiece given the resource id | |
235 // nearest the scale factor |scale_factor|. | |
236 // Use ResourceHandle::SCALE_FACTOR_NONE for scale independent image resources | |
237 // (such as wallpaper). | |
238 base::StringPiece GetRawDataResourceForScale(int resource_id, | |
239 ScaleFactor scale_factor) const; | |
240 | |
241 // Get a localized string given a message id. Returns an empty | |
242 // string if the message_id is not found. | |
243 base::string16 GetLocalizedString(int message_id); | |
244 | |
245 // Returns the font list for the specified style. | |
246 const gfx::FontList& GetFontList(FontStyle style); | |
247 | |
248 // Returns the font for the specified style. | |
249 const gfx::Font& GetFont(FontStyle style); | |
250 | |
251 // Resets and reloads the cached fonts. This is useful when the fonts of the | |
252 // system have changed, for example, when the locale has changed. | |
253 void ReloadFonts(); | |
254 | |
255 // Overrides the path to the pak file from which the locale resources will be | |
256 // loaded. Pass an empty path to undo. | |
257 void OverrideLocalePakForTest(const base::FilePath& pak_path); | |
258 | |
259 // Overrides a localized string resource with the given string. If no delegate | |
260 // is present, the |string| will be returned when getting the localized string | |
261 // |message_id|. If |ReloadLocaleResources| is called, all overrides are | |
262 // cleared. This is intended to be used in conjunction with field trials and | |
263 // the variations service to experiment with different UI strings. This method | |
264 // is not thread safe! | |
265 void OverrideLocaleStringResource(int message_id, | |
266 const base::string16& string); | |
267 | |
268 // Returns the full pathname of the locale file to load. May return an empty | |
269 // string if no locale data files are found and |test_file_exists| is true. | |
270 // Used on Android to load the local file in the browser process and pass it | |
271 // to the sandboxed renderer process. | |
272 base::FilePath GetLocaleFilePath(const std::string& app_locale, | |
273 bool test_file_exists); | |
274 | |
275 // Returns the maximum scale factor currently loaded. | |
276 // Returns SCALE_FACTOR_100P if no resource is loaded. | |
277 ScaleFactor GetMaxScaleFactor() const; | |
278 | |
279 protected: | |
280 // Returns true if |scale_factor| is supported by this platform. | |
281 static bool IsScaleFactorSupported(ScaleFactor scale_factor); | |
282 | |
283 private: | |
284 FRIEND_TEST_ALL_PREFIXES(ResourceBundleTest, DelegateGetPathForLocalePack); | |
285 FRIEND_TEST_ALL_PREFIXES(ResourceBundleTest, DelegateGetImageNamed); | |
286 FRIEND_TEST_ALL_PREFIXES(ResourceBundleTest, DelegateGetNativeImageNamed); | |
287 | |
288 friend class ResourceBundleImageTest; | |
289 friend class ResourceBundleTest; | |
290 | |
291 class ResourceBundleImageSource; | |
292 friend class ResourceBundleImageSource; | |
293 | |
294 typedef base::hash_map<int, base::string16> IdToStringMap; | |
295 | |
296 // Ctor/dtor are private, since we're a singleton. | |
297 explicit ResourceBundle(Delegate* delegate); | |
298 ~ResourceBundle(); | |
299 | |
300 // Shared initialization. | |
301 static void InitSharedInstance(Delegate* delegate); | |
302 | |
303 // Free skia_images_. | |
304 void FreeImages(); | |
305 | |
306 // Load the main resources. | |
307 void LoadCommonResources(); | |
308 | |
309 // Implementation for AddDataPackFromPath and AddOptionalDataPackFromPath, if | |
310 // the pack is not |optional| logs an error on failure to load. | |
311 void AddDataPackFromPathInternal(const base::FilePath& path, | |
312 ScaleFactor scale_factor, | |
313 bool optional); | |
314 | |
315 // Inserts |data_pack| to |data_pack_| and updates |max_scale_factor_| | |
316 // accordingly. | |
317 void AddDataPack(DataPack* data_pack); | |
318 | |
319 // Try to load the locale specific strings from an external data module. | |
320 // Returns the locale that is loaded. | |
321 std::string LoadLocaleResources(const std::string& pref_locale); | |
322 | |
323 // Load test resources in given paths. If either path is empty an empty | |
324 // resource pack is loaded. | |
325 void LoadTestResources(const base::FilePath& path, | |
326 const base::FilePath& locale_path); | |
327 | |
328 // Unload the locale specific strings and prepares to load new ones. See | |
329 // comments for ReloadLocaleResources(). | |
330 void UnloadLocaleResources(); | |
331 | |
332 // Initializes all the gfx::FontList members if they haven't yet been | |
333 // initialized. | |
334 void LoadFontsIfNecessary(); | |
335 | |
336 // Returns a FontList or NULL by calling Delegate::GetFont and converting | |
337 // scoped_ptr<gfx::Font> to scoped_ptr<gfx::FontList>. | |
338 scoped_ptr<gfx::FontList> GetFontListFromDelegate(FontStyle style); | |
339 | |
340 // Fills the |bitmap| given the data file to look in and the |resource_id|. | |
341 // Returns false if the resource does not exist. | |
342 // | |
343 // If the call succeeds, |fell_back_to_1x| indicates whether Chrome's custom | |
344 // csCl PNG chunk is present (added by GRIT if it falls back to a 100% image). | |
345 bool LoadBitmap(const ResourceHandle& data_handle, | |
346 int resource_id, | |
347 SkBitmap* bitmap, | |
348 bool* fell_back_to_1x) const; | |
349 | |
350 // Fills the |bitmap| given the |resource_id| and |scale_factor|. | |
351 // Returns false if the resource does not exist. This may fall back to | |
352 // the data pack with SCALE_FACTOR_NONE, and when this happens, | |
353 // |scale_factor| will be set to SCALE_FACTOR_100P. | |
354 bool LoadBitmap(int resource_id, | |
355 ScaleFactor* scale_factor, | |
356 SkBitmap* bitmap, | |
357 bool* fell_back_to_1x) const; | |
358 | |
359 // Returns true if missing scaled resources should be visually indicated when | |
360 // drawing the fallback (e.g., by tinting the image). | |
361 static bool ShouldHighlightMissingScaledResources(); | |
362 | |
363 // Returns true if the data in |buf| is a PNG that has the special marker | |
364 // added by GRIT that indicates that the image is actually 1x data. | |
365 static bool PNGContainsFallbackMarker(const unsigned char* buf, size_t size); | |
366 | |
367 // A wrapper for PNGCodec::Decode that returns information about custom | |
368 // chunks. For security reasons we can't alter PNGCodec to return this | |
369 // information. Our PNG files are preprocessed by GRIT, and any special chunks | |
370 // should occur immediately after the IHDR chunk. | |
371 static bool DecodePNG(const unsigned char* buf, | |
372 size_t size, | |
373 SkBitmap* bitmap, | |
374 bool* fell_back_to_1x); | |
375 | |
376 // Returns an empty image for when a resource cannot be loaded. This is a | |
377 // bright red bitmap. | |
378 gfx::Image& GetEmptyImage(); | |
379 | |
380 const base::FilePath& GetOverriddenPakPath(); | |
381 | |
382 // This pointer is guaranteed to outlive the ResourceBundle instance and may | |
383 // be NULL. | |
384 Delegate* delegate_; | |
385 | |
386 // Protects |images_| and font-related members. | |
387 scoped_ptr<base::Lock> images_and_fonts_lock_; | |
388 | |
389 // Protects |locale_resources_data_|. | |
390 scoped_ptr<base::Lock> locale_resources_data_lock_; | |
391 | |
392 // Handles for data sources. | |
393 scoped_ptr<ResourceHandle> locale_resources_data_; | |
394 ScopedVector<ResourceHandle> data_packs_; | |
395 | |
396 // The maximum scale factor currently loaded. | |
397 ScaleFactor max_scale_factor_; | |
398 | |
399 // Cached images. The ResourceBundle caches all retrieved images and keeps | |
400 // ownership of the pointers. | |
401 typedef std::map<int, gfx::Image> ImageMap; | |
402 ImageMap images_; | |
403 | |
404 gfx::Image empty_image_; | |
405 | |
406 // The various font lists used. Cached to avoid repeated GDI | |
407 // creation/destruction. | |
408 scoped_ptr<gfx::FontList> base_font_list_; | |
409 scoped_ptr<gfx::FontList> bold_font_list_; | |
410 scoped_ptr<gfx::FontList> small_font_list_; | |
411 scoped_ptr<gfx::FontList> small_bold_font_list_; | |
412 scoped_ptr<gfx::FontList> medium_font_list_; | |
413 scoped_ptr<gfx::FontList> medium_bold_font_list_; | |
414 scoped_ptr<gfx::FontList> large_font_list_; | |
415 scoped_ptr<gfx::FontList> large_bold_font_list_; | |
416 scoped_ptr<gfx::FontList> web_font_list_; | |
417 | |
418 base::FilePath overridden_pak_path_; | |
419 | |
420 IdToStringMap overridden_locale_strings_; | |
421 | |
422 DISALLOW_COPY_AND_ASSIGN(ResourceBundle); | |
423 }; | |
424 | |
425 } // namespace ui | |
426 | |
427 // TODO(beng): Someday, maybe, get rid of this. | |
428 using ui::ResourceBundle; | |
429 | |
430 #endif // UI_BASE_RESOURCE_RESOURCE_BUNDLE_H_ | |
OLD | NEW |