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 CHROME_BROWSER_UI_WEBUI_EXTENSIONS_EXTENSION_ICON_SOURCE_H_
6#define CHROME_BROWSER_UI_WEBUI_EXTENSIONS_EXTENSION_ICON_SOURCE_H_
7
8#include <map>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/memory/weak_ptr.h"
13#include "base/task/cancelable_task_tracker.h"
14#include "chrome/browser/favicon/favicon_service.h"
15#include "content/public/browser/url_data_source.h"
16#include "extensions/common/extension_icon_set.h"
17#include "extensions/common/extension_resource.h"
18#include "third_party/skia/include/core/SkBitmap.h"
19
20class ExtensionIconSet;
21class Profile;
22
23namespace extensions {
24class Extension;
25
26// ExtensionIconSource serves extension icons through network level chrome:
27// requests. Icons can be retrieved for any installed extension or app.
28//
29// The format for requesting an icon is as follows:
30//   chrome://extension-icon/<extension_id>/<icon_size>/<match_type>?[options]
31//
32//   Parameters (<> required, [] optional):
33//    <extension_id>  = the id of the extension
34//    <icon_size>     = the size of the icon, as the integer value of the
35//                      corresponding Extension:Icons enum.
36//    <match_type>    = the fallback matching policy, as the integer value of
37//                      the corresponding ExtensionIconSet::MatchType enum.
38//    [options]       = Optional transformations to apply. Supported options:
39//                        grayscale=true to desaturate the image.
40//
41// Examples:
42//   chrome-extension://gbmgkahjioeacddebbnengilkgbkhodg/32/1?grayscale=true
43//     (ICON_SMALL, MATCH_BIGGER, grayscale)
44//   chrome-extension://gbmgkahjioeacddebbnengilkgbkhodg/128/0
45//     (ICON_LARGE, MATCH_EXACTLY)
46//
47// We attempt to load icons from the following sources in order:
48//  1) The icons as listed in the extension / app manifests.
49//  2) If a 16px icon was requested, the favicon for extension's launch URL.
50//  3) The default extension / application icon if there are still no matches.
51//
52class ExtensionIconSource : public content::URLDataSource,
53                            public base::SupportsWeakPtr<ExtensionIconSource> {
54 public:
55  explicit ExtensionIconSource(Profile* profile);
56
57  // Gets the URL of the |extension| icon in the given |icon_size|, falling back
58  // based on the |match| type. If |grayscale|, the URL will be for the
59  // desaturated version of the icon. |exists|, if non-NULL, will be set to true
60  // if the icon exists; false if it will lead to a default or not-present
61  // image.
62  static GURL GetIconURL(const Extension* extension,
63                         int icon_size,
64                         ExtensionIconSet::MatchType match,
65                         bool grayscale,
66                         bool* exists);
67
68  // A public utility function for accessing the bitmap of the image specified
69  // by |resource_id|.
70  static SkBitmap* LoadImageByResourceId(int resource_id);
71
72  // content::URLDataSource implementation.
73  virtual std::string GetSource() const OVERRIDE;
74  virtual std::string GetMimeType(const std::string&) const OVERRIDE;
75  virtual void StartDataRequest(
76      const std::string& path,
77      int render_process_id,
78      int render_frame_id,
79      const content::URLDataSource::GotDataCallback& callback) OVERRIDE;
80
81 private:
82  // Encapsulates the request parameters for |request_id|.
83  struct ExtensionIconRequest;
84
85  virtual ~ExtensionIconSource();
86
87  // Returns the bitmap for the default app image.
88  const SkBitmap* GetDefaultAppImage();
89
90  // Returns the bitmap for the default extension.
91  const SkBitmap* GetDefaultExtensionImage();
92
93  // Performs any remaining transformations (like desaturating the |image|),
94  // then returns the |image| to the client and clears up any temporary data
95  // associated with the |request_id|.
96  void FinalizeImage(const SkBitmap* image, int request_id);
97
98  // Loads the default image for |request_id| and returns to the client.
99  void LoadDefaultImage(int request_id);
100
101  // Loads the extension's |icon| for the given |request_id| and returns the
102  // image to the client.
103  void LoadExtensionImage(const ExtensionResource& icon,
104                          int request_id);
105
106  // Loads the favicon image for the app associated with the |request_id|. If
107  // the image does not exist, we fall back to the default image.
108  void LoadFaviconImage(int request_id);
109
110  // FaviconService callback
111  void OnFaviconDataAvailable(
112      int request_id,
113      const favicon_base::FaviconRawBitmapResult& bitmap_result);
114
115  // ImageLoader callback
116  void OnImageLoaded(int request_id, const gfx::Image& image);
117
118  // Called when the extension doesn't have an icon. We fall back to multiple
119  // sources, using the following order:
120  //  1) The icons as listed in the extension / app manifests.
121  //  2) If a 16px icon and the extension has a launch URL, see if Chrome
122  //     has a corresponding favicon.
123  //  3) If still no matches, load the default extension / application icon.
124  void LoadIconFailed(int request_id);
125
126  // Parses and savse an ExtensionIconRequest for the URL |path| for the
127  // specified |request_id|.
128  bool ParseData(const std::string& path,
129                 int request_id,
130                 const content::URLDataSource::GotDataCallback& callback);
131
132  // Stores the parameters associated with the |request_id|, making them
133  // as an ExtensionIconRequest via GetData.
134  void SetData(int request_id,
135               const content::URLDataSource::GotDataCallback& callback,
136               const Extension* extension,
137               bool grayscale,
138               int size,
139               ExtensionIconSet::MatchType match);
140
141  // Returns the ExtensionIconRequest for the given |request_id|.
142  ExtensionIconRequest* GetData(int request_id);
143
144  // Removes temporary data associated with |request_id|.
145  void ClearData(int request_id);
146
147  Profile* profile_;
148
149  // Maps tracker ids to request ids.
150  std::map<int, int> tracker_map_;
151
152  // Maps request_ids to ExtensionIconRequests.
153  std::map<int, ExtensionIconRequest*> request_map_;
154
155  scoped_ptr<SkBitmap> default_app_data_;
156
157  scoped_ptr<SkBitmap> default_extension_data_;
158
159  base::CancelableTaskTracker cancelable_task_tracker_;
160
161  DISALLOW_COPY_AND_ASSIGN(ExtensionIconSource);
162};
163
164}  // namespace extensions
165
166#endif  // CHROME_BROWSER_UI_WEBUI_EXTENSIONS_EXTENSION_ICON_SOURCE_H_
167