• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "chrome/browser/ui/webui/ntp/favicon_webui_handler.h"
6 
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/strings/string_split.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/values.h"
13 #include "chrome/browser/extensions/extension_icon_manager.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/favicon/favicon_service.h"
16 #include "chrome/browser/favicon/favicon_service_factory.h"
17 #include "chrome/browser/history/top_sites.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/url_constants.h"
20 #include "content/public/browser/web_ui.h"
21 #include "grit/ui_resources.h"
22 #include "third_party/skia/include/core/SkBitmap.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/gfx/codec/png_codec.h"
25 #include "ui/gfx/color_analysis.h"
26 #include "ui/gfx/favicon_size.h"
27 
28 namespace {
29 
SkColorToCss(SkColor color)30 base::StringValue* SkColorToCss(SkColor color) {
31   return new base::StringValue(base::StringPrintf("rgb(%d, %d, %d)",
32                                             SkColorGetR(color),
33                                             SkColorGetG(color),
34                                             SkColorGetB(color)));
35 }
36 
GetDominantColorCssString(scoped_refptr<base::RefCountedMemory> png)37 base::StringValue* GetDominantColorCssString(
38     scoped_refptr<base::RefCountedMemory> png) {
39   color_utils::GridSampler sampler;
40   SkColor color = color_utils::CalculateKMeanColorOfPNG(png);
41   return SkColorToCss(color);
42 }
43 
44 }  // namespace
45 
46 // Thin inheritance-dependent trampoline to forward notification of app
47 // icon loads to the FaviconWebUIHandler. Base class does caching of icons.
48 class ExtensionIconColorManager : public ExtensionIconManager {
49  public:
ExtensionIconColorManager(FaviconWebUIHandler * handler)50   explicit ExtensionIconColorManager(FaviconWebUIHandler* handler)
51       : ExtensionIconManager(),
52         handler_(handler) {}
~ExtensionIconColorManager()53   virtual ~ExtensionIconColorManager() {}
54 
OnImageLoaded(const std::string & extension_id,const gfx::Image & image)55   virtual void OnImageLoaded(const std::string& extension_id,
56                              const gfx::Image& image) OVERRIDE {
57     ExtensionIconManager::OnImageLoaded(extension_id, image);
58     handler_->NotifyAppIconReady(extension_id);
59   }
60 
61  private:
62   FaviconWebUIHandler* handler_;
63 };
64 
FaviconWebUIHandler()65 FaviconWebUIHandler::FaviconWebUIHandler()
66     : id_(0),
67       app_icon_color_manager_(new ExtensionIconColorManager(this)) {
68 }
69 
~FaviconWebUIHandler()70 FaviconWebUIHandler::~FaviconWebUIHandler() {
71 }
72 
RegisterMessages()73 void FaviconWebUIHandler::RegisterMessages() {
74   web_ui()->RegisterMessageCallback("getFaviconDominantColor",
75       base::Bind(&FaviconWebUIHandler::HandleGetFaviconDominantColor,
76                  base::Unretained(this)));
77   web_ui()->RegisterMessageCallback("getAppIconDominantColor",
78       base::Bind(&FaviconWebUIHandler::HandleGetAppIconDominantColor,
79                  base::Unretained(this)));
80 }
81 
HandleGetFaviconDominantColor(const base::ListValue * args)82 void FaviconWebUIHandler::HandleGetFaviconDominantColor(
83     const base::ListValue* args) {
84   std::string path;
85   CHECK(args->GetString(0, &path));
86   std::string prefix = "chrome://favicon/size/";
87   DCHECK(StartsWithASCII(path, prefix, false)) << "path is " << path;
88   size_t slash = path.find("/", prefix.length());
89   path = path.substr(slash + 1);
90 
91   std::string dom_id;
92   CHECK(args->GetString(1, &dom_id));
93 
94   FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(
95       Profile::FromWebUI(web_ui()), Profile::EXPLICIT_ACCESS);
96   if (!favicon_service || path.empty())
97     return;
98 
99   GURL url(path);
100   // Intercept requests for prepopulated pages.
101   for (size_t i = 0; i < arraysize(history::kPrepopulatedPages); i++) {
102     if (url.spec() ==
103         l10n_util::GetStringUTF8(history::kPrepopulatedPages[i].url_id)) {
104       base::StringValue dom_id_value(dom_id);
105       scoped_ptr<base::StringValue> color(
106           SkColorToCss(history::kPrepopulatedPages[i].color));
107       web_ui()->CallJavascriptFunction("ntp.setFaviconDominantColor",
108                                        dom_id_value, *color);
109       return;
110     }
111   }
112 
113   dom_id_map_[id_] = dom_id;
114   favicon_service->GetRawFaviconForPageURL(
115       FaviconService::FaviconForPageURLParams(
116           url, favicon_base::FAVICON, gfx::kFaviconSize),
117       1.0f,
118       base::Bind(&FaviconWebUIHandler::OnFaviconDataAvailable,
119                  base::Unretained(this),
120                  id_++),
121       &cancelable_task_tracker_);
122 }
123 
OnFaviconDataAvailable(int id,const favicon_base::FaviconRawBitmapResult & bitmap_result)124 void FaviconWebUIHandler::OnFaviconDataAvailable(
125     int id,
126     const favicon_base::FaviconRawBitmapResult& bitmap_result) {
127   scoped_ptr<base::StringValue> color_value;
128 
129   if (bitmap_result.is_valid())
130     color_value.reset(GetDominantColorCssString(bitmap_result.bitmap_data));
131   else
132     color_value.reset(new base::StringValue("#919191"));
133 
134   base::StringValue dom_id(dom_id_map_[id]);
135   web_ui()->CallJavascriptFunction("ntp.setFaviconDominantColor",
136                                    dom_id, *color_value);
137   dom_id_map_.erase(id);
138 }
139 
HandleGetAppIconDominantColor(const base::ListValue * args)140 void FaviconWebUIHandler::HandleGetAppIconDominantColor(
141     const base::ListValue* args) {
142   std::string extension_id;
143   CHECK(args->GetString(0, &extension_id));
144 
145   ExtensionService* extension_service =
146       Profile::FromWebUI(web_ui())->GetExtensionService();
147   const extensions::Extension* extension = extension_service->GetExtensionById(
148       extension_id, false);
149   if (!extension)
150     return;
151   app_icon_color_manager_->LoadIcon(extension_service->profile(), extension);
152 }
153 
NotifyAppIconReady(const std::string & extension_id)154 void FaviconWebUIHandler::NotifyAppIconReady(const std::string& extension_id) {
155   const SkBitmap& bitmap = app_icon_color_manager_->GetIcon(extension_id);
156   // TODO(estade): would be nice to avoid a round trip through png encoding.
157   std::vector<unsigned char> bits;
158   if (!gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &bits))
159     return;
160   scoped_refptr<base::RefCountedStaticMemory> bits_mem(
161       new base::RefCountedStaticMemory(&bits.front(), bits.size()));
162   scoped_ptr<base::StringValue> color_value(
163       GetDominantColorCssString(bits_mem));
164   base::StringValue id(extension_id);
165   web_ui()->CallJavascriptFunction(
166       "ntp.setFaviconDominantColor", id, *color_value);
167 }
168