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