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.
5 #ifndef CHROME_BROWSER_THEMES_BROWSER_THEME_PACK_H_
6 #define CHROME_BROWSER_THEMES_BROWSER_THEME_PACK_H_
12 #include "base/basictypes.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/sequenced_task_runner_helpers.h"
15 #include "chrome/browser/themes/custom_theme_supplier.h"
16 #include "extensions/common/extension.h"
17 #include "third_party/skia/include/core/SkColor.h"
18 #include "ui/base/layout.h"
19 #include "ui/gfx/color_utils.h"
22 class DictionaryValue
;
24 class RefCountedMemory
;
27 namespace extensions
{
39 // An optimized representation of a theme, backed by a mmapped DataPack.
41 // The idea is to pre-process all images (tinting, compositing, etc) at theme
42 // install time, save all the PNG-ified data into an mmappable file so we don't
43 // suffer multiple file system access times, therefore solving two of the
44 // problems with the previous implementation.
46 // A note on const-ness. All public, non-static methods are const. We do this
47 // because once we've constructed a BrowserThemePack through the
48 // BuildFromExtension() interface, we WriteToDisk() on a thread other than the
49 // UI thread that consumes a BrowserThemePack. There is no locking; thread
50 // safety between the writing thread and the UI thread is ensured by having the
53 // BrowserThemePacks are always deleted on the file thread because in the
54 // common case, they are backed by mmapped data and the unmmapping operation
55 // will trip our IO on the UI thread detector.
56 class BrowserThemePack
: public CustomThemeSupplier
{
58 // Builds the theme pack from all data from |extension|. This is often done
59 // on a separate thread as it takes so long. This can fail and return NULL in
60 // the case where the theme has invalid data.
61 static scoped_refptr
<BrowserThemePack
> BuildFromExtension(
62 const extensions::Extension
* extension
);
64 // Builds the theme pack from a previously performed WriteToDisk(). This
65 // operation should be relatively fast, as it should be an mmap() and some
66 // pointer swizzling. Returns NULL on any error attempting to read |path|.
67 static scoped_refptr
<BrowserThemePack
> BuildFromDataPack(
68 const base::FilePath
& path
, const std::string
& expected_id
);
70 // Returns whether the specified identifier is one of the images we persist
72 static bool IsPersistentImageID(int id
);
74 // Builds a data pack on disk at |path| for future quick loading by
75 // BuildFromDataPack(). Often (but not always) called from the file thread;
76 // implementation should be threadsafe because neither thread will write to
77 // |image_memory_| and the worker thread will keep a reference to prevent
79 bool WriteToDisk(const base::FilePath
& path
) const;
81 // Overridden from CustomThemeSupplier:
82 bool GetTint(int id
, color_utils::HSL
* hsl
) const override
;
83 bool GetColor(int id
, SkColor
* color
) const override
;
84 bool GetDisplayProperty(int id
, int* result
) const override
;
85 gfx::Image
GetImageNamed(int id
) override
;
86 base::RefCountedMemory
* GetRawData(int id
, ui::ScaleFactor scale_factor
)
88 bool HasCustomImage(int id
) const override
;
91 friend class BrowserThemePackTest
;
94 typedef std::map
<int, gfx::Image
> ImageCache
;
96 // The raw PNG memory associated with a certain id.
97 typedef std::map
<int, scoped_refptr
<base::RefCountedMemory
> > RawImages
;
99 // The type passed to ui::DataPack::WritePack.
100 typedef std::map
<uint16
, base::StringPiece
> RawDataForWriting
;
102 // Maps scale factors (enum values) to file paths.
103 typedef std::map
<ui::ScaleFactor
, base::FilePath
> ScaleFactorToFileMap
;
105 // Maps image ids to maps of scale factors to file paths.
106 typedef std::map
<int, ScaleFactorToFileMap
> FilePathMap
;
108 // Default. Everything is empty.
111 ~BrowserThemePack() override
;
113 // Builds a header ready to write to disk.
114 void BuildHeader(const extensions::Extension
* extension
);
116 // Transforms the JSON tint values into their final versions in the |tints_|
118 void BuildTintsFromJSON(const base::DictionaryValue
* tints_value
);
120 // Transforms the JSON color values into their final versions in the
121 // |colors_| array and also fills in unspecified colors based on tint values.
122 void BuildColorsFromJSON(const base::DictionaryValue
* color_value
);
124 // Implementation details of BuildColorsFromJSON().
125 void ReadColorsFromJSON(const base::DictionaryValue
* colors_value
,
126 std::map
<int, SkColor
>* temp_colors
);
127 void GenerateMissingColors(std::map
<int, SkColor
>* temp_colors
);
129 // Transforms the JSON display properties into |display_properties_|.
130 void BuildDisplayPropertiesFromJSON(
131 const base::DictionaryValue
* display_value
);
133 // Parses the image names out of an extension.
134 void ParseImageNamesFromJSON(const base::DictionaryValue
* images_value
,
135 const base::FilePath
& images_path
,
136 FilePathMap
* file_paths
) const;
138 // Helper function to populate the FilePathMap.
139 void AddFileAtScaleToMap(const std::string
& image_name
,
140 ui::ScaleFactor scale_factor
,
141 const base::FilePath
& image_path
,
142 FilePathMap
* file_paths
) const;
144 // Creates the data for |source_images_| from |file_paths|.
145 void BuildSourceImagesArray(const FilePathMap
& file_paths
);
147 // Loads the unmodified images packed in the extension to SkBitmaps. Returns
148 // true if all images loaded.
149 bool LoadRawBitmapsTo(const FilePathMap
& file_paths
,
150 ImageCache
* image_cache
);
152 // Populate |images| cache with empty gfx::Images. Image reps are lazily
153 // generated when an image rep is requested via ImageSkia::GetRepresentation.
154 // Source and destination is |images|.
155 void CreateImages(ImageCache
* images
) const;
157 // Crops images down to a size such that most of the cropped image will be
158 // displayed in the UI. Cropping is useful because images from custom themes
159 // can be of any size. Source and destination is |images|.
160 void CropImages(ImageCache
* images
) const;
162 // Creates tinted and composited frame images. Source and destination is
164 void CreateFrameImages(ImageCache
* images
) const;
166 // Creates button images tinted with |button_tint| and places them in
168 void CreateTintedButtons(const color_utils::HSL
& button_tint
,
169 ImageCache
* processed_images
) const;
171 // Creates the semi-transparent tab background images, putting the results
172 // in |images|. Must be called after GenerateFrameImages().
173 void CreateTabBackgroundImages(ImageCache
* images
) const;
175 // Takes all the SkBitmaps in |images|, encodes them as PNGs and places
176 // them in |reencoded_images|.
177 void RepackImages(const ImageCache
& images
,
178 RawImages
* reencoded_images
) const;
180 // Takes all images in |source| and puts them in |destination|, freeing any
181 // image already in |destination| that |source| would overwrite.
182 void MergeImageCaches(const ImageCache
& source
,
183 ImageCache
* destination
) const;
185 // Copies images from |source| to |destination| such that the lifetimes of
186 // the images in |destination| are not affected by the lifetimes of the
187 // images in |source|.
188 void CopyImagesTo(const ImageCache
& source
, ImageCache
* destination
) const;
190 // Changes the RefCountedMemory based |images| into StringPiece data in |out|.
191 void AddRawImagesTo(const RawImages
& images
, RawDataForWriting
* out
) const;
193 // Retrieves the tint OR the default tint. Unlike the public interface, we
194 // always need to return a reasonable tint here, instead of partially
195 // querying if the tint exists.
196 color_utils::HSL
GetTintInternal(int id
) const;
198 // Returns a unique id to use to store the raw bitmap for |prs_id| at
199 // |scale_factor| in memory.
200 int GetRawIDByPersistentID(int prs_id
, ui::ScaleFactor scale_factor
) const;
202 // Returns true if the |key| specifies a valid scale (e.g. "100") and
203 // the corresponding scale factor is currently in use. If true, returns
204 // the scale factor in |scale_factor|.
205 bool GetScaleFactorFromManifestKey(const std::string
& key
,
206 ui::ScaleFactor
* scale_factor
) const;
208 // Generates raw images for any missing scale from an available scale.
209 void GenerateRawImageForAllSupportedScales(int prs_id
);
211 // Data pack, if we have one.
212 scoped_ptr
<ui::DataPack
> data_pack_
;
214 // All structs written to disk need to be packed; no alignment tricks here,
217 // Header that is written to disk.
218 struct BrowserThemePackHeader
{
219 // Numeric version to make sure we're compatible in the future.
222 // 1 if little_endian. 0 if big_endian. On mismatch, abort load.
225 // theme_id without NULL terminator.
229 // The remaining structs represent individual entries in an array. For the
230 // following three structs, BrowserThemePack will either allocate an array or
231 // will point directly to mmapped data.
244 struct DisplayPropertyPair
{
247 } *display_properties_
;
249 // A list of included source images. A pointer to a -1 terminated array of
250 // our persistent IDs.
254 // The scale factors represented by the images in the theme pack.
255 std::vector
<ui::ScaleFactor
> scale_factors_
;
257 // References to raw PNG data. This map isn't touched when |data_pack_| is
258 // non-NULL; |image_memory_| is only filled during BuildFromExtension(). Any
259 // image data that needs to be written to the DataPack during WriteToDisk()
260 // needs to be in |image_memory_|.
261 RawImages image_memory_
;
263 // Loaded images. These are loaded from |image_memory_|, from |data_pack_|,
264 // and by BuildFromExtension(). These images should only be accessed on the UI
266 ImageCache images_on_ui_thread_
;
268 // Cache of images created in BuildFromExtension(). Once the theme pack is
269 // created, this cache should only be accessed on the file thread. There
270 // should be no IDs in |image_memory_| that are in |images_on_file_thread_|
272 ImageCache images_on_file_thread_
;
274 DISALLOW_COPY_AND_ASSIGN(BrowserThemePack
);
277 #endif // CHROME_BROWSER_THEMES_BROWSER_THEME_PACK_H_