OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "components/favicon/core/favicon_handler.h" | 5 #include "components/favicon/core/favicon_handler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
213 case FaviconDriverObserver::NON_TOUCH_16_DIP: | 213 case FaviconDriverObserver::NON_TOUCH_16_DIP: |
214 case FaviconDriverObserver::NON_TOUCH_LARGEST: | 214 case FaviconDriverObserver::NON_TOUCH_LARGEST: |
215 return favicon_base::FAVICON; | 215 return favicon_base::FAVICON; |
216 case FaviconDriverObserver::TOUCH_LARGEST: | 216 case FaviconDriverObserver::TOUCH_LARGEST: |
217 return favicon_base::TOUCH_ICON | favicon_base::TOUCH_PRECOMPOSED_ICON; | 217 return favicon_base::TOUCH_ICON | favicon_base::TOUCH_PRECOMPOSED_ICON; |
218 } | 218 } |
219 return 0; | 219 return 0; |
220 } | 220 } |
221 | 221 |
222 void FaviconHandler::FetchFavicon(const GURL& url) { | 222 void FaviconHandler::FetchFavicon(const GURL& url) { |
223 cancelable_task_tracker_.TryCancelAll(); | 223 cancelable_task_tracker_for_page_url_.TryCancelAll(); |
224 cancelable_task_tracker_for_candidates_.TryCancelAll(); | |
224 | 225 |
225 url_ = url; | 226 url_ = url; |
226 | 227 |
227 initial_history_result_expired_or_incomplete_ = false; | 228 initial_history_result_expired_or_incomplete_ = false; |
228 redownload_icons_ = false; | 229 redownload_icons_ = false; |
229 got_favicon_from_history_ = false; | 230 got_favicon_from_history_ = false; |
230 download_request_.Cancel(); | 231 manifest_download_request_.Cancel(); |
232 image_download_request_.Cancel(); | |
233 manifest_url_.reset(); | |
231 candidates_.clear(); | 234 candidates_.clear(); |
232 notification_icon_url_ = GURL(); | 235 notification_icon_url_ = GURL(); |
233 notification_icon_type_ = favicon_base::INVALID_ICON; | 236 notification_icon_type_ = favicon_base::INVALID_ICON; |
234 num_download_requests_ = 0; | 237 num_download_requests_ = 0; |
235 current_candidate_index_ = 0u; | 238 current_candidate_index_ = 0u; |
236 best_favicon_ = DownloadedFavicon(); | 239 best_favicon_ = DownloadedFavicon(); |
237 | 240 |
238 // Request the favicon from the history service. In parallel to this the | 241 // Request the favicon from the history service. In parallel to this the |
239 // renderer is going to notify us (well WebContents) when the favicon url is | 242 // renderer is going to notify us (well WebContents) when the favicon url is |
240 // available. | 243 // available. |
241 service_->GetFaviconForPageURL( | 244 service_->GetFaviconForPageURL( |
242 url_, icon_types_, preferred_icon_size(), | 245 url_, icon_types_, preferred_icon_size(), |
243 base::Bind(&FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, | 246 base::Bind(&FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, |
244 base::Unretained(this)), | 247 base::Unretained(this)), |
245 &cancelable_task_tracker_); | 248 &cancelable_task_tracker_for_page_url_); |
246 } | 249 } |
247 | 250 |
248 bool FaviconHandler::UpdateFaviconCandidate( | 251 bool FaviconHandler::UpdateFaviconCandidate( |
249 const DownloadedFavicon& downloaded_favicon) { | 252 const DownloadedFavicon& downloaded_favicon) { |
250 if (downloaded_favicon.candidate.score > best_favicon_.candidate.score) | 253 if (downloaded_favicon.candidate.score > best_favicon_.candidate.score) |
251 best_favicon_ = downloaded_favicon; | 254 best_favicon_ = downloaded_favicon; |
252 | 255 |
253 if (download_largest_icon_) { | 256 if (download_largest_icon_) { |
254 // The size of the downloaded icon may not match the declared size. It's | 257 // The size of the downloaded icon may not match the declared size. It's |
255 // important to stop downloading if: | 258 // important to stop downloading if: |
(...skipping 10 matching lines...) Expand all Loading... | |
266 candidates_[current_candidate_index_ + 1].score <= | 269 candidates_[current_candidate_index_ + 1].score <= |
267 best_favicon_.candidate.score; | 270 best_favicon_.candidate.score; |
268 } else { | 271 } else { |
269 return best_favicon_.candidate.score == 1; | 272 return best_favicon_.candidate.score == 1; |
270 } | 273 } |
271 } | 274 } |
272 | 275 |
273 void FaviconHandler::SetFavicon(const GURL& icon_url, | 276 void FaviconHandler::SetFavicon(const GURL& icon_url, |
274 const gfx::Image& image, | 277 const gfx::Image& image, |
275 favicon_base::IconType icon_type) { | 278 favicon_base::IconType icon_type) { |
279 LOG(INFO) << "MIKEL FaviconHandler::SetFavicon() type " << icon_type << " url " | |
280 << icon_url; | |
276 if (ShouldSaveFavicon()) | 281 if (ShouldSaveFavicon()) |
277 service_->SetFavicons(url_, icon_url, icon_type, image); | 282 service_->SetFavicons(url_, icon_url, icon_type, image); |
278 | 283 |
279 NotifyFaviconUpdated(icon_url, icon_type, image); | 284 NotifyFaviconUpdated(icon_url, icon_type, image); |
280 } | 285 } |
281 | 286 |
282 void FaviconHandler::NotifyFaviconUpdated( | 287 void FaviconHandler::NotifyFaviconUpdated( |
283 const std::vector<favicon_base::FaviconRawBitmapResult>& | 288 const std::vector<favicon_base::FaviconRawBitmapResult>& |
284 favicon_bitmap_results) { | 289 favicon_bitmap_results) { |
285 if (favicon_bitmap_results.empty()) | |
286 return; | |
287 | |
288 gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs( | 290 gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs( |
289 favicon_bitmap_results, | 291 favicon_bitmap_results, |
290 favicon_base::GetFaviconScales(), | 292 favicon_base::GetFaviconScales(), |
291 preferred_icon_size()); | 293 preferred_icon_size()); |
292 // The history service sends back results for a single icon URL and icon | 294 // The history service sends back results for a single icon URL and icon |
293 // type, so it does not matter which result we get |icon_url| and |icon_type| | 295 // type, so it does not matter which result we get |icon_url| and |icon_type| |
294 // from. | 296 // from. |
295 const GURL icon_url = favicon_bitmap_results[0].icon_url; | 297 const GURL icon_url = favicon_bitmap_results[0].icon_url; |
296 favicon_base::IconType icon_type = favicon_bitmap_results[0].icon_type; | 298 favicon_base::IconType icon_type = favicon_bitmap_results[0].icon_type; |
297 NotifyFaviconUpdated(icon_url, icon_type, resized_image); | 299 NotifyFaviconUpdated(icon_url, icon_type, resized_image); |
298 } | 300 } |
299 | 301 |
300 void FaviconHandler::NotifyFaviconUpdated(const GURL& icon_url, | 302 void FaviconHandler::NotifyFaviconUpdated(const GURL& icon_url, |
301 favicon_base::IconType icon_type, | 303 favicon_base::IconType icon_type, |
302 const gfx::Image& image) { | 304 const gfx::Image& image) { |
303 if (image.IsEmpty()) | 305 if (image.IsEmpty()) |
304 return; | 306 return; |
305 | 307 |
308 // If a manifest is being processed, it's URL overrides the icon URL. | |
309 const GURL& notification_icon_url = manifest_url_.value_or(icon_url); | |
310 | |
306 gfx::Image image_with_adjusted_colorspace = image; | 311 gfx::Image image_with_adjusted_colorspace = image; |
307 favicon_base::SetFaviconColorSpace(&image_with_adjusted_colorspace); | 312 favicon_base::SetFaviconColorSpace(&image_with_adjusted_colorspace); |
308 | 313 |
309 delegate_->OnFaviconUpdated(url_, handler_type_, icon_url, | 314 delegate_->OnFaviconUpdated(url_, handler_type_, notification_icon_url, |
310 icon_url != notification_icon_url_, | 315 notification_icon_url != notification_icon_url_, |
311 image_with_adjusted_colorspace); | 316 image_with_adjusted_colorspace); |
312 | 317 |
313 notification_icon_url_ = icon_url; | 318 notification_icon_url_ = notification_icon_url; |
314 notification_icon_type_ = icon_type; | 319 notification_icon_type_ = icon_type; |
315 } | 320 } |
316 | 321 |
317 void FaviconHandler::OnUpdateFaviconURL( | 322 void FaviconHandler::OnUpdateCandidates( |
318 const GURL& page_url, | 323 const GURL& page_url, |
319 const std::vector<FaviconURL>& candidates) { | 324 const std::vector<FaviconURL>& candidates, |
325 const base::Optional<GURL>& manifest_url) { | |
326 DCHECK_EQ(page_url, url_); | |
320 if (page_url != url_) | 327 if (page_url != url_) |
321 return; | 328 return; |
322 | 329 |
330 // |candidates| or |manifest_url| could have been modified via Javascript. | |
331 if (manifest_url_ && manifest_url_ == manifest_url) | |
332 return; | |
333 | |
334 manifest_url_ = manifest_url; | |
335 non_manifest_original_candidates_ = candidates; | |
336 | |
337 // Check if the manifest previously returned a 404 (or a 200 but contained no | |
338 // icons), and ignore the manifest URL if that's the case. | |
339 if (manifest_url_ && service_->WasUnableToDownloadFavicon(*manifest_url_)) { | |
340 DVLOG(1) << "Skip failed Manifest: " << *manifest_url_; | |
341 manifest_url_.reset(); | |
342 } | |
343 | |
344 if (manifest_url_) { | |
345 cancelable_task_tracker_for_candidates_.TryCancelAll(); | |
pkotwicz
2017/05/01 04:56:53
- Can this be moved outside of the if() statement.
mastiz
2017/05/04 10:57:53
I don't think this is desirable because OnGotFinal
pkotwicz
2017/05/04 17:28:25
Isn't this because |cancelable_task_tracker_for_ca
mastiz
2017/05/10 10:03:52
I'm not really sure why splitting would be any sim
pkotwicz
2017/05/12 06:13:28
I think that splitting the trackers would fix "Bug
mastiz
2017/05/15 14:06:59
I might have achieved this, PTAL.
I've traded sim
pkotwicz
2017/05/16 06:36:35
This change is reasonable. Its a neat solution to
| |
346 // See if there is a cached favicon for the manifest. | |
347 GetFaviconAndUpdateMappingsUnlessIncognito( | |
348 /*icon_url=*/*manifest_url_, favicon_base::FAVICON, | |
349 base::Bind(&FaviconHandler::OnFaviconDataForManifestFromFaviconService, | |
350 base::Unretained(this))); | |
351 } else { | |
352 // If no manifest available, proceed with the regular candidates only. | |
353 OnGotFinalIconURLCandidates(candidates); | |
354 } | |
355 } | |
356 | |
357 void FaviconHandler::OnFaviconDataForManifestFromFaviconService( | |
358 const std::vector<favicon_base::FaviconRawBitmapResult>& | |
359 favicon_bitmap_results) { | |
360 bool has_valid_result = HasValidResult(favicon_bitmap_results); | |
361 bool has_expired_or_incomplete_result = | |
362 !has_valid_result || HasExpiredOrIncompleteResult(preferred_icon_size(), | |
363 favicon_bitmap_results); | |
364 | |
365 if (has_valid_result) { | |
366 // There is a valid favicon. Notify any observers. It is useful to notify | |
367 // the observers even if the favicon is expired or incomplete (incorrect | |
368 // size) because temporarily showing the user an expired favicon or | |
369 // streched favicon is preferable to showing the user the default favicon. | |
370 NotifyFaviconUpdated(favicon_bitmap_results); | |
371 } | |
372 | |
373 if (has_expired_or_incomplete_result) { | |
374 manifest_download_request_.Reset(base::Bind( | |
375 &FaviconHandler::OnDidDownloadManifest, base::Unretained(this))); | |
376 delegate_->DownloadManifest(*manifest_url_, | |
377 manifest_download_request_.callback()); | |
378 } | |
379 } | |
380 | |
381 void FaviconHandler::OnDidDownloadManifest( | |
382 int status_code, | |
383 const std::vector<FaviconURL>& candidates) { | |
384 // Mark manifest download as finished. | |
385 manifest_download_request_.Cancel(); | |
386 | |
387 if (!candidates.empty()) { | |
388 OnGotFinalIconURLCandidates(candidates); | |
389 return; | |
390 } | |
391 | |
392 // If either the downloading of the manifest failed, OR the manifest contains | |
393 // no icons, proceed with the list of icons listed in the HTML. | |
394 DVLOG(1) << "Could not fetch Manifest icons from " << *manifest_url_ | |
395 << ", falling back to inlined ones, which are " | |
396 << non_manifest_original_candidates_.size(); | |
397 | |
398 if (status_code == 404 || status_code == 200) | |
399 service_->UnableToDownloadFavicon(*manifest_url_); | |
400 | |
401 manifest_url_.reset(); | |
402 OnGotFinalIconURLCandidates(non_manifest_original_candidates_); | |
403 } | |
404 | |
405 void FaviconHandler::OnGotFinalIconURLCandidates( | |
406 const std::vector<FaviconURL>& candidates) { | |
323 std::vector<FaviconCandidate> sorted_candidates; | 407 std::vector<FaviconCandidate> sorted_candidates; |
324 const std::vector<int> desired_pixel_sizes = | 408 const std::vector<int> desired_pixel_sizes = |
325 GetDesiredPixelSizes(handler_type_); | 409 GetDesiredPixelSizes(handler_type_); |
326 for (const FaviconURL& candidate : candidates) { | 410 for (const FaviconURL& candidate : candidates) { |
327 if (!candidate.icon_url.is_empty() && (candidate.icon_type & icon_types_)) { | 411 if (!candidate.icon_url.is_empty() && (candidate.icon_type & icon_types_)) { |
328 sorted_candidates.push_back( | 412 sorted_candidates.push_back( |
329 FaviconCandidate::FromFaviconURL(candidate, desired_pixel_sizes)); | 413 FaviconCandidate::FromFaviconURL(candidate, desired_pixel_sizes)); |
330 } | 414 } |
331 } | 415 } |
332 | 416 |
333 std::stable_sort(sorted_candidates.begin(), sorted_candidates.end(), | 417 std::stable_sort(sorted_candidates.begin(), sorted_candidates.end(), |
334 &FaviconCandidate::CompareScore); | 418 &FaviconCandidate::CompareScore); |
335 | 419 |
336 if (candidates_.size() == sorted_candidates.size() && | 420 if (candidates_.size() == sorted_candidates.size() && |
337 std::equal(sorted_candidates.begin(), sorted_candidates.end(), | 421 std::equal(sorted_candidates.begin(), sorted_candidates.end(), |
338 candidates_.begin())) { | 422 candidates_.begin())) { |
339 return; | 423 return; |
340 } | 424 } |
341 | 425 |
342 download_request_.Cancel(); | 426 cancelable_task_tracker_for_candidates_.TryCancelAll(); |
427 image_download_request_.Cancel(); | |
343 candidates_ = std::move(sorted_candidates); | 428 candidates_ = std::move(sorted_candidates); |
344 num_download_requests_ = 0; | 429 num_download_requests_ = 0; |
345 current_candidate_index_ = 0u; | 430 current_candidate_index_ = 0u; |
346 best_favicon_ = DownloadedFavicon(); | 431 best_favicon_ = DownloadedFavicon(); |
347 | 432 |
348 // TODO(davemoore) Should clear on empty url. Currently we ignore it. | 433 // TODO(davemoore) Should clear on empty url. Currently we ignore it. |
349 // This appears to be what FF does as well. | 434 // This appears to be what FF does as well. |
350 if (current_candidate() && got_favicon_from_history_) | 435 if (current_candidate() && got_favicon_from_history_) |
351 OnGotInitialHistoryDataAndIconURLCandidates(); | 436 OnGotInitialHistoryDataAndIconURLCandidates(); |
352 } | 437 } |
(...skipping 26 matching lines...) Expand all Loading... | |
379 } | 464 } |
380 | 465 |
381 void FaviconHandler::OnDidDownloadFavicon( | 466 void FaviconHandler::OnDidDownloadFavicon( |
382 favicon_base::IconType icon_type, | 467 favicon_base::IconType icon_type, |
383 int id, | 468 int id, |
384 int http_status_code, | 469 int http_status_code, |
385 const GURL& image_url, | 470 const GURL& image_url, |
386 const std::vector<SkBitmap>& bitmaps, | 471 const std::vector<SkBitmap>& bitmaps, |
387 const std::vector<gfx::Size>& original_bitmap_sizes) { | 472 const std::vector<gfx::Size>& original_bitmap_sizes) { |
388 // Mark download as finished. | 473 // Mark download as finished. |
389 download_request_.Cancel(); | 474 image_download_request_.Cancel(); |
390 | 475 |
391 if (bitmaps.empty() && http_status_code == 404) { | 476 if (bitmaps.empty() && http_status_code == 404) { |
392 DVLOG(1) << "Failed to Download Favicon:" << image_url; | 477 DVLOG(1) << "Failed to Download Favicon:" << image_url; |
393 RecordDownloadOutcome(DownloadOutcome::FAILED); | 478 RecordDownloadOutcome(DownloadOutcome::FAILED); |
394 service_->UnableToDownloadFavicon(image_url); | 479 service_->UnableToDownloadFavicon(image_url); |
395 } | 480 } |
396 | 481 |
397 bool request_next_icon = true; | 482 bool request_next_icon = true; |
398 if (!bitmaps.empty()) { | 483 if (!bitmaps.empty()) { |
399 RecordDownloadOutcome(DownloadOutcome::SUCCEEDED); | 484 RecordDownloadOutcome(DownloadOutcome::SUCCEEDED); |
(...skipping 29 matching lines...) Expand all Loading... | |
429 if (request_next_icon && current_candidate_index_ + 1 < candidates_.size()) { | 514 if (request_next_icon && current_candidate_index_ + 1 < candidates_.size()) { |
430 // Process the next candidate. | 515 // Process the next candidate. |
431 ++current_candidate_index_; | 516 ++current_candidate_index_; |
432 DownloadCurrentCandidateOrAskFaviconService(); | 517 DownloadCurrentCandidateOrAskFaviconService(); |
433 } else { | 518 } else { |
434 // OnDidDownloadFavicon() can only be called after requesting a download, so | 519 // OnDidDownloadFavicon() can only be called after requesting a download, so |
435 // |num_download_requests_| can never be 0. | 520 // |num_download_requests_| can never be 0. |
436 RecordDownloadAttemptsForHandlerType(handler_type_, num_download_requests_); | 521 RecordDownloadAttemptsForHandlerType(handler_type_, num_download_requests_); |
437 // We have either found the ideal candidate or run out of candidates. | 522 // We have either found the ideal candidate or run out of candidates. |
438 if (best_favicon_.candidate.icon_type != favicon_base::INVALID_ICON) { | 523 if (best_favicon_.candidate.icon_type != favicon_base::INVALID_ICON) { |
439 // No more icons to request, set the favicon from the candidate. | 524 // No more icons to request, set the favicon from the candidate. Note that |
440 SetFavicon(best_favicon_.candidate.icon_url, best_favicon_.image, | 525 // manifest URLs override icon URLs if available. |
441 best_favicon_.candidate.icon_type); | 526 SetFavicon(manifest_url_.value_or(best_favicon_.candidate.icon_url), |
527 best_favicon_.image, best_favicon_.candidate.icon_type); | |
442 } | 528 } |
443 // Clear download related state. | 529 // Clear download related state. |
444 current_candidate_index_ = candidates_.size(); | 530 current_candidate_index_ = candidates_.size(); |
445 num_download_requests_ = 0; | 531 num_download_requests_ = 0; |
446 best_favicon_ = DownloadedFavicon(); | 532 best_favicon_ = DownloadedFavicon(); |
447 } | 533 } |
448 } | 534 } |
449 | 535 |
450 const std::vector<GURL> FaviconHandler::GetIconURLs() const { | 536 const std::vector<GURL> FaviconHandler::GetIconURLs() const { |
451 std::vector<GURL> icon_urls; | 537 std::vector<GURL> icon_urls; |
452 for (const FaviconCandidate& candidate : candidates_) | 538 for (const FaviconCandidate& candidate : candidates_) |
453 icon_urls.push_back(candidate.icon_url); | 539 icon_urls.push_back(candidate.icon_url); |
454 return icon_urls; | 540 return icon_urls; |
455 } | 541 } |
456 | 542 |
457 bool FaviconHandler::HasPendingTasksForTest() { | 543 bool FaviconHandler::HasPendingTasksForTest() { |
458 return !download_request_.IsCancelled() || | 544 return !manifest_download_request_.IsCancelled() || |
459 cancelable_task_tracker_.HasTrackedTasks(); | 545 !image_download_request_.IsCancelled() || |
546 cancelable_task_tracker_for_page_url_.HasTrackedTasks() || | |
547 cancelable_task_tracker_for_candidates_.HasTrackedTasks(); | |
460 } | 548 } |
461 | 549 |
462 bool FaviconHandler::ShouldSaveFavicon() { | 550 bool FaviconHandler::ShouldSaveFavicon() { |
463 if (!delegate_->IsOffTheRecord()) | 551 if (!delegate_->IsOffTheRecord()) |
464 return true; | 552 return true; |
465 | 553 |
466 // Always save favicon if the page is bookmarked. | 554 // Always save favicon if the page is bookmarked. |
467 return delegate_->IsBookmarked(url_); | 555 return delegate_->IsBookmarked(url_); |
468 } | 556 } |
469 | 557 |
470 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( | 558 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( |
471 const std::vector<favicon_base::FaviconRawBitmapResult>& | 559 const std::vector<favicon_base::FaviconRawBitmapResult>& |
472 favicon_bitmap_results) { | 560 favicon_bitmap_results) { |
473 got_favicon_from_history_ = true; | 561 got_favicon_from_history_ = true; |
474 bool has_valid_result = HasValidResult(favicon_bitmap_results); | 562 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
475 initial_history_result_expired_or_incomplete_ = | 563 initial_history_result_expired_or_incomplete_ = |
476 !has_valid_result || | 564 !has_valid_result || |
477 HasExpiredOrIncompleteResult(preferred_icon_size(), | 565 HasExpiredOrIncompleteResult(preferred_icon_size(), |
478 favicon_bitmap_results); | 566 favicon_bitmap_results); |
479 redownload_icons_ = initial_history_result_expired_or_incomplete_ && | 567 redownload_icons_ = initial_history_result_expired_or_incomplete_ && |
480 !favicon_bitmap_results.empty(); | 568 !favicon_bitmap_results.empty(); |
481 | 569 |
482 if (has_valid_result && (!current_candidate() || | 570 if (has_valid_result) { |
483 DoUrlsAndIconsMatch(current_candidate()->icon_url, | 571 if (!current_candidate() || |
484 current_candidate()->icon_type, | 572 DoUrlsAndIconsMatch(current_candidate()->icon_url, |
485 favicon_bitmap_results))) { | 573 current_candidate()->icon_type, |
486 // The db knows the favicon (although it may be out of date) and the entry | 574 favicon_bitmap_results) || |
487 // doesn't have an icon. Set the favicon now, and if the favicon turns out | 575 (manifest_url_ && |
488 // to be expired (or the wrong url) we'll fetch later on. This way the | 576 DoUrlsAndIconsMatch(*manifest_url_, favicon_base::FAVICON, |
489 // user doesn't see a flash of the default favicon. | 577 favicon_bitmap_results))) { |
490 NotifyFaviconUpdated(favicon_bitmap_results); | 578 // The db knows the favicon (although it may be out of date) and the entry |
579 // doesn't have an icon. Set the favicon now, and if the favicon turns out | |
580 // to be expired (or the wrong url) we'll fetch later on. This way the | |
581 // user doesn't see a flash of the default favicon. | |
582 NotifyFaviconUpdated(favicon_bitmap_results); | |
583 } | |
491 } | 584 } |
492 | 585 |
493 if (current_candidate()) | 586 if (current_candidate()) |
494 OnGotInitialHistoryDataAndIconURLCandidates(); | 587 OnGotInitialHistoryDataAndIconURLCandidates(); |
495 } | 588 } |
496 | 589 |
497 void FaviconHandler::DownloadCurrentCandidateOrAskFaviconService() { | 590 void FaviconHandler::DownloadCurrentCandidateOrAskFaviconService() { |
498 GURL icon_url = current_candidate()->icon_url; | 591 const GURL icon_url = current_candidate()->icon_url; |
499 favicon_base::IconType icon_type = current_candidate()->icon_type; | 592 const favicon_base::IconType icon_type = current_candidate()->icon_type; |
500 | 593 // If the icons listed in a manifest are being processed, skip the cache |
501 if (redownload_icons_) { | 594 // lookup for |icon_url| since the manifest's URL is used for caching anyway, |
595 // and this lookup has happened earlier. | |
596 if (redownload_icons_ || manifest_url_) { | |
502 // We have the mapping, but the favicon is out of date. Download it now. | 597 // We have the mapping, but the favicon is out of date. Download it now. |
503 ScheduleDownload(icon_url, icon_type); | 598 ScheduleFaviconDownload(icon_url, icon_type); |
504 } else { | 599 } else { |
505 // We don't know the favicon, but we may have previously downloaded the | 600 GetFaviconAndUpdateMappingsUnlessIncognito( |
506 // favicon for another page that shares the same favicon. Ask for the | 601 icon_url, icon_type, |
507 // favicon given the favicon URL. | 602 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this))); |
508 if (delegate_->IsOffTheRecord()) { | |
509 service_->GetFavicon( | |
510 icon_url, icon_type, preferred_icon_size(), | |
511 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), | |
512 &cancelable_task_tracker_); | |
513 } else { | |
514 // Ask the history service for the icon. This does two things: | |
515 // 1. Attempts to fetch the favicon data from the database. | |
516 // 2. If the favicon exists in the database, this updates the database to | |
517 // include the mapping between the page url and the favicon url. | |
518 // This is asynchronous. The history service will call back when done. | |
519 // TODO(pkotwicz): pass in all of |image_urls_| to | |
520 // UpdateFaviconMappingsAndFetch(). | |
521 service_->UpdateFaviconMappingsAndFetch( | |
522 url_, {icon_url}, icon_type, preferred_icon_size(), | |
523 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), | |
524 &cancelable_task_tracker_); | |
525 } | |
526 } | 603 } |
527 } | 604 } |
528 | 605 |
606 void FaviconHandler::GetFaviconAndUpdateMappingsUnlessIncognito( | |
607 const GURL& icon_url, | |
608 favicon_base::IconType icon_type, | |
609 const favicon_base::FaviconResultsCallback& callback) { | |
610 // We don't know the favicon, but we may have previously downloaded the | |
611 // favicon for another page that shares the same favicon. Ask for the | |
612 // favicon given the favicon URL. | |
613 if (delegate_->IsOffTheRecord()) { | |
614 service_->GetFavicon(icon_url, icon_type, preferred_icon_size(), callback, | |
615 &cancelable_task_tracker_for_candidates_); | |
616 } else { | |
617 // Ask the history service for the icon. This does two things: | |
618 // 1. Attempts to fetch the favicon data from the database. | |
619 // 2. If the favicon exists in the database, this updates the database to | |
620 // include the mapping between the page url and the favicon url. | |
621 // This is asynchronous. The history service will call back when done. | |
622 // TODO(pkotwicz): pass in all of |image_urls_| to | |
623 // UpdateFaviconMappingsAndFetch(). | |
624 service_->UpdateFaviconMappingsAndFetch( | |
625 url_, {icon_url}, icon_type, preferred_icon_size(), callback, | |
626 &cancelable_task_tracker_for_candidates_); | |
627 } | |
628 } | |
629 | |
529 void FaviconHandler::OnFaviconData(const std::vector< | 630 void FaviconHandler::OnFaviconData(const std::vector< |
530 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { | 631 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { |
531 bool has_results = !favicon_bitmap_results.empty(); | 632 bool has_results = !favicon_bitmap_results.empty(); |
532 bool has_valid_result = HasValidResult(favicon_bitmap_results); | 633 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
533 bool has_expired_or_incomplete_result = | 634 bool has_expired_or_incomplete_result = |
534 !has_valid_result || HasExpiredOrIncompleteResult(preferred_icon_size(), | 635 !has_valid_result || HasExpiredOrIncompleteResult(preferred_icon_size(), |
535 favicon_bitmap_results); | 636 favicon_bitmap_results); |
536 | 637 |
537 if (has_valid_result) { | 638 if (has_valid_result) { |
538 // There is a valid favicon. Notify any observers. It is useful to notify | 639 // There is a valid favicon. Notify any observers. It is useful to notify |
539 // the observers even if the favicon is expired or incomplete (incorrect | 640 // the observers even if the favicon is expired or incomplete (incorrect |
540 // size) because temporarily showing the user an expired favicon or | 641 // size) because temporarily showing the user an expired favicon or |
541 // streched favicon is preferable to showing the user the default favicon. | 642 // streched favicon is preferable to showing the user the default favicon. |
542 NotifyFaviconUpdated(favicon_bitmap_results); | 643 NotifyFaviconUpdated(favicon_bitmap_results); |
543 } | 644 } |
544 | 645 |
545 if (!current_candidate() || | 646 if (!current_candidate() || |
546 (has_results && !DoUrlsAndIconsMatch(current_candidate()->icon_url, | 647 (has_results && !DoUrlsAndIconsMatch(current_candidate()->icon_url, |
547 current_candidate()->icon_type, | 648 current_candidate()->icon_type, |
548 favicon_bitmap_results))) { | 649 favicon_bitmap_results))) { |
549 // The icon URLs have been updated since the favicon data was requested. | 650 // The icon URLs have been updated since the favicon data was requested. |
550 return; | 651 // TODO(mastiz) / DONOTSUBMIT: Remove all this 'if' block. |
652 NOTREACHED(); | |
pkotwicz
2017/05/01 04:56:53
Can you move the removal of this if() statement an
mastiz
2017/05/04 10:57:53
Yes, will do, together with a few changes in tests
mastiz
2017/05/10 10:03:52
Done.
| |
551 } | 653 } |
552 | 654 |
553 if (has_expired_or_incomplete_result) { | 655 if (has_expired_or_incomplete_result) { |
554 ScheduleDownload(current_candidate()->icon_url, | 656 ScheduleFaviconDownload(current_candidate()->icon_url, |
555 current_candidate()->icon_type); | 657 current_candidate()->icon_type); |
556 } else if (num_download_requests_ > 0) { | 658 } else if (num_download_requests_ > 0) { |
557 RecordDownloadAttemptsForHandlerType(handler_type_, num_download_requests_); | 659 RecordDownloadAttemptsForHandlerType(handler_type_, num_download_requests_); |
558 } | 660 } |
559 } | 661 } |
560 | 662 |
561 void FaviconHandler::ScheduleDownload(const GURL& image_url, | 663 void FaviconHandler::ScheduleFaviconDownload(const GURL& image_url, |
562 favicon_base::IconType icon_type) { | 664 favicon_base::IconType icon_type) { |
563 DCHECK(image_url.is_valid()); | 665 DCHECK(image_url.is_valid()); |
564 // Note that CancelableCallback starts cancelled. | 666 // Note that CancelableCallback starts cancelled. |
565 DCHECK(download_request_.IsCancelled()) << "More than one ongoing download"; | 667 DCHECK(image_download_request_.IsCancelled()) |
668 << "More than one ongoing download"; | |
566 if (service_->WasUnableToDownloadFavicon(image_url)) { | 669 if (service_->WasUnableToDownloadFavicon(image_url)) { |
567 DVLOG(1) << "Skip Failed FavIcon: " << image_url; | 670 DVLOG(1) << "Skip Failed FavIcon: " << image_url; |
568 RecordDownloadOutcome(DownloadOutcome::SKIPPED); | 671 RecordDownloadOutcome(DownloadOutcome::SKIPPED); |
569 OnDidDownloadFavicon(icon_type, 0, 0, image_url, std::vector<SkBitmap>(), | 672 OnDidDownloadFavicon(icon_type, 0, 0, image_url, std::vector<SkBitmap>(), |
570 std::vector<gfx::Size>()); | 673 std::vector<gfx::Size>()); |
571 return; | 674 return; |
572 } | 675 } |
573 ++num_download_requests_; | 676 ++num_download_requests_; |
574 download_request_.Reset(base::Bind(&FaviconHandler::OnDidDownloadFavicon, | 677 image_download_request_.Reset( |
575 base::Unretained(this), icon_type)); | 678 base::Bind(&FaviconHandler::OnDidDownloadFavicon, base::Unretained(this), |
679 icon_type)); | |
576 // A max bitmap size is specified to avoid receiving huge bitmaps in | 680 // A max bitmap size is specified to avoid receiving huge bitmaps in |
577 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() | 681 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() |
578 // for more details about the max bitmap size. | 682 // for more details about the max bitmap size. |
579 const int download_id = | 683 const int download_id = |
580 delegate_->DownloadImage(image_url, GetMaximalIconSize(handler_type_), | 684 delegate_->DownloadImage(image_url, GetMaximalIconSize(handler_type_), |
581 download_request_.callback()); | 685 image_download_request_.callback()); |
582 DCHECK_NE(download_id, 0); | 686 DCHECK_NE(download_id, 0); |
583 } | 687 } |
584 | 688 |
585 } // namespace favicon | 689 } // namespace favicon |
OLD | NEW |