| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/favicon_helper.h" | 5 #include "chrome/browser/favicon_helper.h" |
| 6 | 6 |
| 7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/memory/ref_counted_memory.h" | 12 #include "base/memory/ref_counted_memory.h" |
| 13 #include "chrome/browser/bookmarks/bookmark_model.h" | 13 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 14 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
| 15 #include "chrome/common/render_messages.h" | 15 #include "chrome/common/icon_messages.h" |
| 16 #include "content/browser/renderer_host/render_view_host.h" | 16 #include "content/browser/renderer_host/render_view_host.h" |
| 17 #include "content/browser/tab_contents/navigation_controller.h" | 17 #include "content/browser/tab_contents/navigation_controller.h" |
| 18 #include "content/browser/tab_contents/navigation_entry.h" | 18 #include "content/browser/tab_contents/navigation_entry.h" |
| 19 #include "content/browser/tab_contents/tab_contents_delegate.h" | 19 #include "content/browser/tab_contents/tab_contents_delegate.h" |
| 20 #include "content/browser/tab_contents/tab_contents.h" | 20 #include "content/browser/tab_contents/tab_contents.h" |
| 21 #include "skia/ext/image_operations.h" | 21 #include "skia/ext/image_operations.h" |
| 22 #include "ui/gfx/codec/png_codec.h" | 22 #include "ui/gfx/codec/png_codec.h" |
| 23 | 23 |
| 24 namespace { |
| 25 |
| 26 // Returns history::IconType the given icon_type corresponds to. |
| 27 history::IconType ToHistoryIconType(FaviconURL::IconType icon_type) { |
| 28 switch (icon_type) { |
| 29 case FaviconURL::FAVICON: |
| 30 return history::FAVICON; |
| 31 case FaviconURL::TOUCH_ICON: |
| 32 return history::TOUCH_ICON; |
| 33 case FaviconURL::TOUCH_PRECOMPOSED_ICON: |
| 34 return history::TOUCH_PRECOMPOSED_ICON; |
| 35 case FaviconURL::INVALID_ICON: |
| 36 return history::INVALID_ICON; |
| 37 } |
| 38 NOTREACHED(); |
| 39 // Shouldn't reach here, just make compiler happy. |
| 40 return history::INVALID_ICON; |
| 41 } |
| 42 |
| 43 bool DoUrlAndIconMatch(const FaviconURL& favicon_url, |
| 44 const GURL& url, |
| 45 history::IconType icon_type) { |
| 46 return favicon_url.icon_url == url && |
| 47 favicon_url.icon_type == static_cast<FaviconURL::IconType>(icon_type); |
| 48 } |
| 49 |
| 50 } // namespace |
| 51 |
| 24 FaviconHelper::DownloadRequest::DownloadRequest() | 52 FaviconHelper::DownloadRequest::DownloadRequest() |
| 25 : callback(NULL), | 53 : callback(NULL), |
| 26 icon_type(history::INVALID_ICON) { | 54 icon_type(history::INVALID_ICON) { |
| 27 } | 55 } |
| 28 | 56 |
| 29 FaviconHelper::DownloadRequest::DownloadRequest(const GURL& url, | 57 FaviconHelper::DownloadRequest::DownloadRequest(const GURL& url, |
| 30 const GURL& image_url, | 58 const GURL& image_url, |
| 31 ImageDownloadCallback* callback, | 59 ImageDownloadCallback* callback, |
| 32 history::IconType icon_type) | 60 history::IconType icon_type) |
| 33 : url(url), | 61 : url(url), |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 // TODO(davemoore) Should clear on empty url. Currently we ignore it. | 180 // TODO(davemoore) Should clear on empty url. Currently we ignore it. |
| 153 // This appears to be what FF does as well. | 181 // This appears to be what FF does as well. |
| 154 // No URL was added. | 182 // No URL was added. |
| 155 if (!got_favicon_url_update) | 183 if (!got_favicon_url_update) |
| 156 return; | 184 return; |
| 157 | 185 |
| 158 if (!GetFaviconService()) | 186 if (!GetFaviconService()) |
| 159 return; | 187 return; |
| 160 | 188 |
| 161 // For FAVICON. | 189 // For FAVICON. |
| 162 if (current_candidate()->icon_type == ::FAVICON) { | 190 if (current_candidate()->icon_type == FaviconURL::FAVICON) { |
| 163 if (!favicon_expired_ && entry->favicon().is_valid() && | 191 if (!favicon_expired_ && entry->favicon().is_valid() && |
| 164 do_url_and_icon_match(*current_candidate(), entry->favicon().url(), | 192 DoUrlAndIconMatch(*current_candidate(), entry->favicon().url(), |
| 165 history::FAVICON)) | 193 history::FAVICON)) |
| 166 return; | 194 return; |
| 167 | 195 |
| 168 entry->favicon().set_url(current_candidate()->icon_url); | 196 entry->favicon().set_url(current_candidate()->icon_url); |
| 169 } else if (!favicon_expired_ && got_favicon_from_history_ && | 197 } else if (!favicon_expired_ && got_favicon_from_history_ && |
| 170 history_icon_.is_valid() && | 198 history_icon_.is_valid() && |
| 171 do_url_and_icon_match(*current_candidate(), | 199 DoUrlAndIconMatch( |
| 200 *current_candidate(), |
| 172 history_icon_.icon_url, history_icon_.icon_type)) { | 201 history_icon_.icon_url, history_icon_.icon_type)) { |
| 173 return; | 202 return; |
| 174 } | 203 } |
| 175 | 204 |
| 176 if (got_favicon_from_history_) | 205 if (got_favicon_from_history_) |
| 177 DownloadFaviconOrAskHistory(entry->url(), current_candidate()->icon_url, | 206 DownloadFaviconOrAskHistory(entry->url(), current_candidate()->icon_url, |
| 178 ToHistoryIconType(current_candidate()->icon_type)); | 207 ToHistoryIconType(current_candidate()->icon_type)); |
| 179 } | 208 } |
| 180 | 209 |
| 181 NavigationEntry* FaviconHelper::GetEntry() { | 210 NavigationEntry* FaviconHelper::GetEntry() { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 | 260 |
| 232 bool FaviconHelper::ShouldSaveFavicon(const GURL& url) { | 261 bool FaviconHelper::ShouldSaveFavicon(const GURL& url) { |
| 233 if (!tab_contents()->profile()->IsOffTheRecord()) | 262 if (!tab_contents()->profile()->IsOffTheRecord()) |
| 234 return true; | 263 return true; |
| 235 | 264 |
| 236 // Otherwise store the favicon if the page is bookmarked. | 265 // Otherwise store the favicon if the page is bookmarked. |
| 237 BookmarkModel* bookmark_model = tab_contents()->profile()->GetBookmarkModel(); | 266 BookmarkModel* bookmark_model = tab_contents()->profile()->GetBookmarkModel(); |
| 238 return bookmark_model && bookmark_model->IsBookmarked(url); | 267 return bookmark_model && bookmark_model->IsBookmarked(url); |
| 239 } | 268 } |
| 240 | 269 |
| 241 history::IconType FaviconHelper::ToHistoryIconType(IconType icon_type) { | |
| 242 switch (icon_type) { | |
| 243 case ::FAVICON: | |
| 244 return history::FAVICON; | |
| 245 case ::TOUCH_ICON: | |
| 246 return history::TOUCH_ICON; | |
| 247 case ::TOUCH_PRECOMPOSED_ICON: | |
| 248 return history::TOUCH_PRECOMPOSED_ICON; | |
| 249 case ::INVALID_ICON: | |
| 250 return history::INVALID_ICON; | |
| 251 } | |
| 252 NOTREACHED(); | |
| 253 // Shouldn't reach here, just make compiler happy. | |
| 254 return history::INVALID_ICON; | |
| 255 } | |
| 256 | |
| 257 bool FaviconHelper::OnMessageReceived(const IPC::Message& message) { | 270 bool FaviconHelper::OnMessageReceived(const IPC::Message& message) { |
| 258 bool message_handled = true; | 271 bool message_handled = true; |
| 259 IPC_BEGIN_MESSAGE_MAP(FaviconHelper, message) | 272 IPC_BEGIN_MESSAGE_MAP(FaviconHelper, message) |
| 260 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDownloadFavicon, OnDidDownloadFavicon) | 273 IPC_MESSAGE_HANDLER(IconHostMsg_DidDownloadFavicon, OnDidDownloadFavicon) |
| 261 IPC_MESSAGE_UNHANDLED(message_handled = false) | 274 IPC_MESSAGE_UNHANDLED(message_handled = false) |
| 262 IPC_END_MESSAGE_MAP() | 275 IPC_END_MESSAGE_MAP() |
| 263 return message_handled; | 276 return message_handled; |
| 264 } | 277 } |
| 265 | 278 |
| 266 void FaviconHelper::OnDidDownloadFavicon(int id, | 279 void FaviconHelper::OnDidDownloadFavicon(int id, |
| 267 const GURL& image_url, | 280 const GURL& image_url, |
| 268 bool errored, | 281 bool errored, |
| 269 const SkBitmap& image) { | 282 const SkBitmap& image) { |
| 270 DownloadRequests::iterator i = download_requests_.find(id); | 283 DownloadRequests::iterator i = download_requests_.find(id); |
| 271 if (i == download_requests_.end()) { | 284 if (i == download_requests_.end()) { |
| 272 // Currently TabContents notifies us of ANY downloads so that it is | 285 // Currently TabContents notifies us of ANY downloads so that it is |
| 273 // possible to get here. | 286 // possible to get here. |
| 274 return; | 287 return; |
| 275 } | 288 } |
| 276 | 289 |
| 277 if (i->second.callback) { | 290 if (i->second.callback) { |
| 278 i->second.callback->Run(id, errored, image); | 291 i->second.callback->Run(id, errored, image); |
| 279 } else if (current_candidate() && | 292 } else if (current_candidate() && |
| 280 do_url_and_icon_match(*current_candidate(), image_url, | 293 DoUrlAndIconMatch(*current_candidate(), image_url, |
| 281 i->second.icon_type)) { | 294 i->second.icon_type)) { |
| 282 // The downloaded icon is still valid when there is no FaviconURL update | 295 // The downloaded icon is still valid when there is no FaviconURL update |
| 283 // during the downloading. | 296 // during the downloading. |
| 284 if (!errored) { | 297 if (!errored) { |
| 285 SetFavicon(i->second.url, image_url, image, i->second.icon_type); | 298 SetFavicon(i->second.url, image_url, image, i->second.icon_type); |
| 286 } else if (GetEntry() && ++current_url_index_ < urls_.size()) { | 299 } else if (GetEntry() && ++current_url_index_ < urls_.size()) { |
| 287 // Copies all candidate except first one and notifies the FaviconHelper, | 300 // Copies all candidate except first one and notifies the FaviconHelper, |
| 288 // so the next candidate can be processed. | 301 // so the next candidate can be processed. |
| 289 std::vector<FaviconURL> new_candidates(++urls_.begin(), urls_.end()); | 302 std::vector<FaviconURL> new_candidates(++urls_.begin(), urls_.end()); |
| 290 OnUpdateFaviconURL(0, new_candidates); | 303 OnUpdateFaviconURL(0, new_candidates); |
| 291 } | 304 } |
| 292 } | 305 } |
| 293 download_requests_.erase(i); | 306 download_requests_.erase(i); |
| 294 } | 307 } |
| 295 | 308 |
| 296 void FaviconHelper::OnFaviconDataForInitialURL( | 309 void FaviconHelper::OnFaviconDataForInitialURL( |
| 297 FaviconService::Handle handle, | 310 FaviconService::Handle handle, |
| 298 history::FaviconData favicon) { | 311 history::FaviconData favicon) { |
| 299 NavigationEntry* entry = GetEntry(); | 312 NavigationEntry* entry = GetEntry(); |
| 300 if (!entry) | 313 if (!entry) |
| 301 return; | 314 return; |
| 302 | 315 |
| 303 got_favicon_from_history_ = true; | 316 got_favicon_from_history_ = true; |
| 304 history_icon_ = favicon; | 317 history_icon_ = favicon; |
| 305 | 318 |
| 306 favicon_expired_ = (favicon.known_icon && favicon.expired); | 319 favicon_expired_ = (favicon.known_icon && favicon.expired); |
| 307 | 320 |
| 308 if (favicon.known_icon && favicon.icon_type == history::FAVICON && | 321 if (favicon.known_icon && favicon.icon_type == history::FAVICON && |
| 309 !entry->favicon().is_valid() && | 322 !entry->favicon().is_valid() && |
| 310 (!current_candidate() || do_url_and_icon_match(*current_candidate(), | 323 (!current_candidate() || |
| 311 favicon.icon_url, favicon.icon_type))) { | 324 DoUrlAndIconMatch( |
| 325 *current_candidate(), favicon.icon_url, favicon.icon_type))) { |
| 312 // The db knows the favicon (although it may be out of date) and the entry | 326 // The db knows the favicon (although it may be out of date) and the entry |
| 313 // doesn't have an icon. Set the favicon now, and if the favicon turns out | 327 // doesn't have an icon. Set the favicon now, and if the favicon turns out |
| 314 // to be expired (or the wrong url) we'll fetch later on. This way the | 328 // to be expired (or the wrong url) we'll fetch later on. This way the |
| 315 // user doesn't see a flash of the default favicon. | 329 // user doesn't see a flash of the default favicon. |
| 316 entry->favicon().set_url(favicon.icon_url); | 330 entry->favicon().set_url(favicon.icon_url); |
| 317 if (favicon.is_valid()) | 331 if (favicon.is_valid()) |
| 318 UpdateFavicon(entry, favicon.image_data); | 332 UpdateFavicon(entry, favicon.image_data); |
| 319 entry->favicon().set_is_valid(true); | 333 entry->favicon().set_is_valid(true); |
| 320 } | 334 } |
| 321 | 335 |
| 322 if (favicon.known_icon && !favicon.expired) { | 336 if (favicon.known_icon && !favicon.expired) { |
| 323 if (current_candidate() && !do_url_and_icon_match(*current_candidate(), | 337 if (current_candidate() && |
| 324 favicon.icon_url, favicon.icon_type)) { | 338 !DoUrlAndIconMatch( |
| 339 *current_candidate(), favicon.icon_url, favicon.icon_type)) { |
| 325 // Mapping in the database is wrong. DownloadFavIconOrAskHistory will | 340 // Mapping in the database is wrong. DownloadFavIconOrAskHistory will |
| 326 // update the mapping for this url and download the favicon if we don't | 341 // update the mapping for this url and download the favicon if we don't |
| 327 // already have it. | 342 // already have it. |
| 328 DownloadFaviconOrAskHistory(entry->url(), current_candidate()->icon_url, | 343 DownloadFaviconOrAskHistory(entry->url(), current_candidate()->icon_url, |
| 329 static_cast<history::IconType>(current_candidate()->icon_type)); | 344 static_cast<history::IconType>(current_candidate()->icon_type)); |
| 330 } | 345 } |
| 331 } else if (current_candidate()) { | 346 } else if (current_candidate()) { |
| 332 // We know the official url for the favicon, by either don't have the | 347 // We know the official url for the favicon, by either don't have the |
| 333 // favicon or its expired. Continue on to DownloadFaviconOrAskHistory to | 348 // favicon or its expired. Continue on to DownloadFaviconOrAskHistory to |
| 334 // either download or check history again. | 349 // either download or check history again. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 UpdateFavicon(entry, favicon.image_data); | 399 UpdateFavicon(entry, favicon.image_data); |
| 385 } | 400 } |
| 386 if (!favicon.known_icon || favicon.expired) { | 401 if (!favicon.known_icon || favicon.expired) { |
| 387 // We don't know the favicon, or it is out of date. Request the current | 402 // We don't know the favicon, or it is out of date. Request the current |
| 388 // one. | 403 // one. |
| 389 ScheduleDownload(entry->url(), entry->favicon().url(), | 404 ScheduleDownload(entry->url(), entry->favicon().url(), |
| 390 preferred_icon_size(), | 405 preferred_icon_size(), |
| 391 history::FAVICON, NULL); | 406 history::FAVICON, NULL); |
| 392 } | 407 } |
| 393 } else if (current_candidate() && (!favicon.known_icon || favicon.expired || | 408 } else if (current_candidate() && (!favicon.known_icon || favicon.expired || |
| 394 !(do_url_and_icon_match(*current_candidate(), favicon.icon_url, | 409 !(DoUrlAndIconMatch( |
| 395 favicon.icon_type)))) { | 410 *current_candidate(), favicon.icon_url, favicon.icon_type)))) { |
| 396 // We don't know the favicon, it is out of date or its type is not same as | 411 // We don't know the favicon, it is out of date or its type is not same as |
| 397 // one got from page. Request the current one. | 412 // one got from page. Request the current one. |
| 398 ScheduleDownload(entry->url(), current_candidate()->icon_url, | 413 ScheduleDownload(entry->url(), current_candidate()->icon_url, |
| 399 preferred_icon_size(), | 414 preferred_icon_size(), |
| 400 ToHistoryIconType(current_candidate()->icon_type), NULL); | 415 ToHistoryIconType(current_candidate()->icon_type), NULL); |
| 401 } | 416 } |
| 402 history_icon_ = favicon; | 417 history_icon_ = favicon; |
| 403 } | 418 } |
| 404 | 419 |
| 405 int FaviconHelper::ScheduleDownload(const GURL& url, | 420 int FaviconHelper::ScheduleDownload(const GURL& url, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 422 int width = image.width(); | 437 int width = image.width(); |
| 423 int height = image.height(); | 438 int height = image.height(); |
| 424 if (width > 0 && height > 0) { | 439 if (width > 0 && height > 0) { |
| 425 calc_favicon_target_size(&width, &height); | 440 calc_favicon_target_size(&width, &height); |
| 426 return skia::ImageOperations::Resize( | 441 return skia::ImageOperations::Resize( |
| 427 image, skia::ImageOperations::RESIZE_LANCZOS3, | 442 image, skia::ImageOperations::RESIZE_LANCZOS3, |
| 428 width, height); | 443 width, height); |
| 429 } | 444 } |
| 430 return image; | 445 return image; |
| 431 } | 446 } |
| OLD | NEW |