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 #include "chrome/browser/ui/views/ash/launcher/launcher_favicon_loader.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "chrome/browser/favicon/favicon_util.h" | |
9 #include "chrome/browser/ui/views/ash/launcher/browser_launcher_item_controller.
h" | |
10 #include "chrome/common/favicon_url.h" | |
11 #include "chrome/common/icon_messages.h" | |
12 #include "content/public/browser/render_view_host.h" | |
13 #include "content/public/browser/web_contents.h" | |
14 #include "content/public/browser/web_contents_delegate.h" | |
15 #include "googleurl/src/gurl.h" | |
16 #include "third_party/skia/include/core/SkBitmap.h" | |
17 | |
18 namespace internal { | |
19 | |
20 const int kMaxBitmapSize = 256; | |
21 | |
22 //////////////////////////////////////////////////////////////////////////////// | |
23 // FaviconBitmapHandler fetchs all bitmaps with the 'icon' (or 'shortcut icon') | |
24 // link tag, storing the one that best matches ash::kLauncherPreferredSize. | |
25 // These icon bitmaps are not resized and are not cached beyond the lifetime | |
26 // of the class. Bitmaps larger than kMaxBitmapSize are ignored. | |
27 | |
28 class FaviconBitmapHandler { | |
29 public: | |
30 FaviconBitmapHandler(content::WebContents* web_contents, | |
31 LauncherFaviconLoader::Delegate* delegate) | |
32 : web_contents_(web_contents), | |
33 delegate_(delegate) { | |
34 } | |
35 | |
36 ~FaviconBitmapHandler() {} | |
37 | |
38 const SkBitmap& bitmap() const { return bitmap_; } | |
39 | |
40 void OnUpdateFaviconURL(int32 page_id, | |
41 const std::vector<FaviconURL>& candidates); | |
42 | |
43 void OnDidDownloadFavicon(int id, | |
44 const GURL& image_url, | |
45 bool errored, | |
46 int requested_size, | |
47 const std::vector<SkBitmap>& bitmaps); | |
48 | |
49 private: | |
50 void DownloadFavicon(const GURL& image_url); | |
51 void AddFavicon(const GURL& image_url, const SkBitmap& new_bitmap); | |
52 | |
53 content::WebContents* web_contents_; | |
54 LauncherFaviconLoader::Delegate* delegate_; | |
55 | |
56 typedef std::set<GURL> UrlSet; | |
57 // Map of pending download urls. | |
58 UrlSet pending_requests_; | |
59 // Map of processed urls. | |
60 UrlSet processed_requests_; | |
61 // Current bitmap and source url. | |
62 SkBitmap bitmap_; | |
63 GURL bitmap_url_; | |
64 | |
65 DISALLOW_COPY_AND_ASSIGN(FaviconBitmapHandler); | |
66 }; | |
67 | |
68 void FaviconBitmapHandler::OnUpdateFaviconURL( | |
69 int32 page_id, | |
70 const std::vector<FaviconURL>& candidates) { | |
71 // This function receives a complete list of faviocn urls for the page. | |
72 // It may get called multiple times with the same list, and will also get | |
73 // called any time an item is added or removed. As such, we track processed | |
74 // and pending urls, but only until they are removed from the list. | |
75 UrlSet new_pending, new_processed; | |
76 // Create a map of valid favicon urls. | |
77 std::set<GURL> urls; | |
78 for (std::vector<FaviconURL>::const_iterator iter = candidates.begin(); | |
79 iter != candidates.end(); ++iter) { | |
80 if (iter->icon_type != FaviconURL::FAVICON) | |
81 continue; | |
82 const GURL& url = iter->icon_url; | |
83 if (url.is_valid()) | |
84 urls.insert(url); | |
85 // Preserve matching pending requests amd processed requests. | |
86 if (pending_requests_.find(url) != pending_requests_.end()) | |
87 new_pending.insert(url); | |
88 if (processed_requests_.find(url) != processed_requests_.end()) | |
89 new_processed.insert(url); | |
90 } | |
91 pending_requests_ = new_pending; | |
92 processed_requests_ = new_processed; | |
93 // Reset bitmap_ if no longer valid (i.e. not in the list of urls). | |
94 if (urls.find(bitmap_url_) == urls.end()) { | |
95 bitmap_url_ = GURL(); | |
96 bitmap_.reset(); | |
97 } | |
98 // Request any new urls. | |
99 for (std::set<GURL>::iterator iter = urls.begin(); | |
100 iter != urls.end(); ++iter) { | |
101 if (processed_requests_.find(*iter) != processed_requests_.end()) | |
102 continue; // Skip already processed downloads. | |
103 if (pending_requests_.find(*iter) != pending_requests_.end()) | |
104 continue; // Skip already pending downloads. | |
105 DownloadFavicon(*iter); | |
106 } | |
107 } | |
108 | |
109 void FaviconBitmapHandler::DownloadFavicon(const GURL& image_url) { | |
110 int image_size = 0; // Request the full sized image. | |
111 pending_requests_.insert(image_url); | |
112 content::RenderViewHost* host = web_contents_->GetRenderViewHost(); | |
113 FaviconUtil::DownloadFavicon(host, image_url, image_size); | |
114 } | |
115 | |
116 | |
117 void FaviconBitmapHandler::OnDidDownloadFavicon( | |
118 int id, | |
119 const GURL& image_url, | |
120 bool errored, | |
121 int requested_size, | |
122 const std::vector<SkBitmap>& bitmaps) { | |
123 UrlSet::iterator iter = pending_requests_.find(image_url); | |
124 if (iter == pending_requests_.end()) { | |
125 // Updates are received for all downloads; ignore unrequested urls. | |
126 return; | |
127 } | |
128 pending_requests_.erase(iter); | |
129 | |
130 // Favicon bitmaps are ordered by decreasing width. | |
131 if (!errored && !bitmaps.empty()) | |
132 AddFavicon(image_url, bitmaps[0]); | |
133 } | |
134 | |
135 void FaviconBitmapHandler::AddFavicon(const GURL& image_url, | |
136 const SkBitmap& new_bitmap) { | |
137 processed_requests_.insert(image_url); | |
138 if (new_bitmap.height() > kMaxBitmapSize || | |
139 new_bitmap.width() > kMaxBitmapSize) | |
140 return; | |
141 if (new_bitmap.height() < ash::kLauncherPreferredSize) | |
142 return; | |
143 if (!bitmap_.isNull()) { | |
144 // We want the smallest icon that is large enough. | |
145 if (new_bitmap.height() > bitmap_.height()) | |
146 return; | |
147 } | |
148 bitmap_url_ = image_url; | |
149 bitmap_ = new_bitmap; | |
150 delegate_->FaviconUpdated(); | |
151 } | |
152 | |
153 } // namespace internal | |
154 | |
155 //////////////////////////////////////////////////////////////////////////////// | |
156 | |
157 LauncherFaviconLoader::LauncherFaviconLoader(Delegate* delegate, | |
158 content::WebContents* web_contents) | |
159 : content::WebContentsObserver(web_contents) { | |
160 favicon_handler_.reset( | |
161 new internal::FaviconBitmapHandler(web_contents, delegate)); | |
162 } | |
163 | |
164 LauncherFaviconLoader::~LauncherFaviconLoader() { | |
165 } | |
166 | |
167 bool LauncherFaviconLoader::OnMessageReceived(const IPC::Message& message) { | |
168 bool message_handled = false; // Allow other handlers to receive these. | |
169 IPC_BEGIN_MESSAGE_MAP(LauncherFaviconLoader, message) | |
170 IPC_MESSAGE_HANDLER(IconHostMsg_DidDownloadFavicon, OnDidDownloadFavicon) | |
171 IPC_MESSAGE_HANDLER(IconHostMsg_UpdateFaviconURL, OnUpdateFaviconURL) | |
172 IPC_MESSAGE_UNHANDLED(message_handled = false) | |
173 IPC_END_MESSAGE_MAP() | |
174 return message_handled; | |
175 } | |
176 | |
177 SkBitmap LauncherFaviconLoader::GetFavicon() const { | |
178 return favicon_handler_->bitmap(); | |
179 } | |
180 | |
181 void LauncherFaviconLoader::OnUpdateFaviconURL( | |
182 int32 page_id, | |
183 const std::vector<FaviconURL>& candidates) { | |
184 favicon_handler_->OnUpdateFaviconURL(page_id, candidates); | |
185 } | |
186 | |
187 void LauncherFaviconLoader::OnDidDownloadFavicon( | |
188 int id, | |
189 const GURL& image_url, | |
190 bool errored, | |
191 int requested_size, | |
192 const std::vector<SkBitmap>& bitmaps) { | |
193 favicon_handler_->OnDidDownloadFavicon( | |
194 id, image_url, errored, requested_size, bitmaps); | |
195 } | |
OLD | NEW |