OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/sync/glue/favicon_cache.h" | 5 #include "chrome/browser/sync/glue/favicon_cache.h" |
6 | 6 |
7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "chrome/browser/chrome_notification_types.h" | 9 #include "chrome/browser/chrome_notification_types.h" |
10 #include "chrome/browser/favicon/favicon_service.h" | 10 #include "chrome/browser/favicon/favicon_service.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 // See crbug.com/122890. | 29 // See crbug.com/122890. |
30 struct SyncedFaviconInfo { | 30 struct SyncedFaviconInfo { |
31 explicit SyncedFaviconInfo(const GURL& favicon_url) | 31 explicit SyncedFaviconInfo(const GURL& favicon_url) |
32 : favicon_url(favicon_url), | 32 : favicon_url(favicon_url), |
33 is_bookmarked(false), | 33 is_bookmarked(false), |
34 received_local_update(false) {} | 34 received_local_update(false) {} |
35 | 35 |
36 // The actual favicon data. | 36 // The actual favicon data. |
37 // TODO(zea): don't keep around the actual data for locally sourced | 37 // TODO(zea): don't keep around the actual data for locally sourced |
38 // favicons (UI can access those directly). | 38 // favicons (UI can access those directly). |
39 favicon_base::FaviconBitmapResult bitmap_data[NUM_SIZES]; | 39 favicon_base::FaviconRawBitmapResult bitmap_data[NUM_SIZES]; |
40 // The URL this favicon was loaded from. | 40 // The URL this favicon was loaded from. |
41 const GURL favicon_url; | 41 const GURL favicon_url; |
42 // Is the favicon for a bookmarked page? | 42 // Is the favicon for a bookmarked page? |
43 bool is_bookmarked; | 43 bool is_bookmarked; |
44 // The last time a tab needed this favicon. | 44 // The last time a tab needed this favicon. |
45 // Note: Do not modify this directly! It should only be modified via | 45 // Note: Do not modify this directly! It should only be modified via |
46 // UpdateFaviconVisitTime(..). | 46 // UpdateFaviconVisitTime(..). |
47 base::Time last_visit_time; | 47 base::Time last_visit_time; |
48 // Whether we've received a local update for this favicon since starting up. | 48 // Whether we've received a local update for this favicon since starting up. |
49 bool received_local_update; | 49 bool received_local_update; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 } | 112 } |
113 | 113 |
114 // Extract the favicon url from either of the favicon types. | 114 // Extract the favicon url from either of the favicon types. |
115 GURL GetFaviconURLFromSpecifics(const sync_pb::EntitySpecifics& specifics) { | 115 GURL GetFaviconURLFromSpecifics(const sync_pb::EntitySpecifics& specifics) { |
116 if (specifics.has_favicon_tracking()) | 116 if (specifics.has_favicon_tracking()) |
117 return GURL(specifics.favicon_tracking().favicon_url()); | 117 return GURL(specifics.favicon_tracking().favicon_url()); |
118 else | 118 else |
119 return GURL(specifics.favicon_image().favicon_url()); | 119 return GURL(specifics.favicon_image().favicon_url()); |
120 } | 120 } |
121 | 121 |
122 // Convert protobuf image data into a FaviconBitmapResult. | 122 // Convert protobuf image data into a FaviconRawBitmapResult. |
123 favicon_base::FaviconBitmapResult GetImageDataFromSpecifics( | 123 favicon_base::FaviconRawBitmapResult GetImageDataFromSpecifics( |
124 const sync_pb::FaviconData& favicon_data) { | 124 const sync_pb::FaviconData& favicon_data) { |
125 base::RefCountedString* temp_string = | 125 base::RefCountedString* temp_string = |
126 new base::RefCountedString(); | 126 new base::RefCountedString(); |
127 temp_string->data() = favicon_data.favicon(); | 127 temp_string->data() = favicon_data.favicon(); |
128 favicon_base::FaviconBitmapResult bitmap_result; | 128 favicon_base::FaviconRawBitmapResult bitmap_result; |
129 bitmap_result.bitmap_data = temp_string; | 129 bitmap_result.bitmap_data = temp_string; |
130 bitmap_result.pixel_size.set_height(favicon_data.height()); | 130 bitmap_result.pixel_size.set_height(favicon_data.height()); |
131 bitmap_result.pixel_size.set_width(favicon_data.width()); | 131 bitmap_result.pixel_size.set_width(favicon_data.width()); |
132 return bitmap_result; | 132 return bitmap_result; |
133 } | 133 } |
134 | 134 |
135 // Convert a FaviconBitmapResult into protobuf image data. | 135 // Convert a FaviconRawBitmapResult into protobuf image data. |
136 void FillSpecificsWithImageData( | 136 void FillSpecificsWithImageData( |
137 const favicon_base::FaviconBitmapResult& bitmap_result, | 137 const favicon_base::FaviconRawBitmapResult& bitmap_result, |
138 sync_pb::FaviconData* favicon_data) { | 138 sync_pb::FaviconData* favicon_data) { |
139 if (!bitmap_result.bitmap_data.get()) | 139 if (!bitmap_result.bitmap_data.get()) |
140 return; | 140 return; |
141 favicon_data->set_height(bitmap_result.pixel_size.height()); | 141 favicon_data->set_height(bitmap_result.pixel_size.height()); |
142 favicon_data->set_width(bitmap_result.pixel_size.width()); | 142 favicon_data->set_width(bitmap_result.pixel_size.width()); |
143 favicon_data->set_favicon(bitmap_result.bitmap_data->front(), | 143 favicon_data->set_favicon(bitmap_result.bitmap_data->front(), |
144 bitmap_result.bitmap_data->size()); | 144 bitmap_result.bitmap_data->size()); |
145 } | 145 } |
146 | 146 |
147 // Build a FaviconImageSpecifics from a SyncedFaviconInfo. | 147 // Build a FaviconImageSpecifics from a SyncedFaviconInfo. |
(...skipping 15 matching lines...) Expand all Loading... |
163 const SyncedFaviconInfo* favicon_info, | 163 const SyncedFaviconInfo* favicon_info, |
164 sync_pb::FaviconTrackingSpecifics* tracking_specifics) { | 164 sync_pb::FaviconTrackingSpecifics* tracking_specifics) { |
165 tracking_specifics->set_favicon_url(favicon_info->favicon_url.spec()); | 165 tracking_specifics->set_favicon_url(favicon_info->favicon_url.spec()); |
166 tracking_specifics->set_last_visit_time_ms( | 166 tracking_specifics->set_last_visit_time_ms( |
167 syncer::TimeToProtoTime(favicon_info->last_visit_time)); | 167 syncer::TimeToProtoTime(favicon_info->last_visit_time)); |
168 tracking_specifics->set_is_bookmarked(favicon_info->is_bookmarked); | 168 tracking_specifics->set_is_bookmarked(favicon_info->is_bookmarked); |
169 } | 169 } |
170 | 170 |
171 // Updates |favicon_info| with the image data in |bitmap_result|. | 171 // Updates |favicon_info| with the image data in |bitmap_result|. |
172 bool UpdateFaviconFromBitmapResult( | 172 bool UpdateFaviconFromBitmapResult( |
173 const favicon_base::FaviconBitmapResult& bitmap_result, | 173 const favicon_base::FaviconRawBitmapResult& bitmap_result, |
174 SyncedFaviconInfo* favicon_info) { | 174 SyncedFaviconInfo* favicon_info) { |
175 DCHECK_EQ(favicon_info->favicon_url, bitmap_result.icon_url); | 175 DCHECK_EQ(favicon_info->favicon_url, bitmap_result.icon_url); |
176 if (!bitmap_result.is_valid()) { | 176 if (!bitmap_result.is_valid()) { |
177 DVLOG(1) << "Received invalid favicon at " << bitmap_result.icon_url.spec(); | 177 DVLOG(1) << "Received invalid favicon at " << bitmap_result.icon_url.spec(); |
178 return false; | 178 return false; |
179 } | 179 } |
180 | 180 |
181 IconSize icon_size = GetIconSizeBinFromBitmapResult( | 181 IconSize icon_size = GetIconSizeBinFromBitmapResult( |
182 bitmap_result.pixel_size); | 182 bitmap_result.pixel_size); |
183 if (icon_size == SIZE_INVALID) { | 183 if (icon_size == SIZE_INVALID) { |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 page_task_map_[page_url] = 0; // For testing only. | 434 page_task_map_[page_url] = 0; // For testing only. |
435 return; | 435 return; |
436 } | 436 } |
437 FaviconService* favicon_service = | 437 FaviconService* favicon_service = |
438 FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); | 438 FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); |
439 if (!favicon_service) | 439 if (!favicon_service) |
440 return; | 440 return; |
441 // TODO(zea): This appears to only fetch one favicon (best match based on | 441 // TODO(zea): This appears to only fetch one favicon (best match based on |
442 // desired_size_in_dip). Figure out a way to fetch all favicons we support. | 442 // desired_size_in_dip). Figure out a way to fetch all favicons we support. |
443 // See crbug.com/181068. | 443 // See crbug.com/181068. |
444 base::CancelableTaskTracker::TaskId id = favicon_service->GetFaviconForURL( | 444 base::CancelableTaskTracker::TaskId id = |
445 FaviconService::FaviconForURLParams( | 445 favicon_service->GetFaviconForPageURL( |
446 page_url, SupportedFaviconTypes(), kMaxFaviconResolution), | 446 FaviconService::FaviconForPageURLParams( |
447 base::Bind(&FaviconCache::OnFaviconDataAvailable, | 447 page_url, SupportedFaviconTypes(), kMaxFaviconResolution), |
448 weak_ptr_factory_.GetWeakPtr(), | 448 base::Bind(&FaviconCache::OnFaviconDataAvailable, |
449 page_url), | 449 weak_ptr_factory_.GetWeakPtr(), |
450 &cancelable_task_tracker_); | 450 page_url), |
| 451 &cancelable_task_tracker_); |
451 page_task_map_[page_url] = id; | 452 page_task_map_[page_url] = id; |
452 } | 453 } |
453 | 454 |
454 void FaviconCache::OnFaviconVisited(const GURL& page_url, | 455 void FaviconCache::OnFaviconVisited(const GURL& page_url, |
455 const GURL& favicon_url) { | 456 const GURL& favicon_url) { |
456 DCHECK(page_url.is_valid()); | 457 DCHECK(page_url.is_valid()); |
457 if (!favicon_url.is_valid() || | 458 if (!favicon_url.is_valid() || |
458 synced_favicons_.find(favicon_url) == synced_favicons_.end()) { | 459 synced_favicons_.find(favicon_url) == synced_favicons_.end()) { |
459 // TODO(zea): consider triggering a favicon load if we have some but not | 460 // TODO(zea): consider triggering a favicon load if we have some but not |
460 // all desired resolutions? | 461 // all desired resolutions? |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 // TODO(zea): incorporate bookmarked status here once we care about it. | 611 // TODO(zea): incorporate bookmarked status here once we care about it. |
611 if (lhs->last_visit_time < rhs->last_visit_time) | 612 if (lhs->last_visit_time < rhs->last_visit_time) |
612 return true; | 613 return true; |
613 else if (lhs->last_visit_time == rhs->last_visit_time) | 614 else if (lhs->last_visit_time == rhs->last_visit_time) |
614 return lhs->favicon_url.spec() < rhs->favicon_url.spec(); | 615 return lhs->favicon_url.spec() < rhs->favicon_url.spec(); |
615 return false; | 616 return false; |
616 } | 617 } |
617 | 618 |
618 void FaviconCache::OnFaviconDataAvailable( | 619 void FaviconCache::OnFaviconDataAvailable( |
619 const GURL& page_url, | 620 const GURL& page_url, |
620 const std::vector<favicon_base::FaviconBitmapResult>& bitmap_results) { | 621 const std::vector<favicon_base::FaviconRawBitmapResult>& bitmap_results) { |
621 PageTaskMap::iterator page_iter = page_task_map_.find(page_url); | 622 PageTaskMap::iterator page_iter = page_task_map_.find(page_url); |
622 if (page_iter == page_task_map_.end()) | 623 if (page_iter == page_task_map_.end()) |
623 return; | 624 return; |
624 page_task_map_.erase(page_iter); | 625 page_task_map_.erase(page_iter); |
625 | 626 |
626 if (bitmap_results.size() == 0) { | 627 if (bitmap_results.size() == 0) { |
627 // Either the favicon isn't loaded yet or there is no valid favicon. | 628 // Either the favicon isn't loaded yet or there is no valid favicon. |
628 // We already cleared the task id, so just return. | 629 // We already cleared the task id, so just return. |
629 DVLOG(1) << "Favicon load failed for page " << page_url.spec(); | 630 DVLOG(1) << "Favicon load failed for page " << page_url.spec(); |
630 return; | 631 return; |
631 } | 632 } |
632 | 633 |
633 base::Time now = base::Time::Now(); | 634 base::Time now = base::Time::Now(); |
634 std::map<GURL, LocalFaviconUpdateInfo> favicon_updates; | 635 std::map<GURL, LocalFaviconUpdateInfo> favicon_updates; |
635 for (size_t i = 0; i < bitmap_results.size(); ++i) { | 636 for (size_t i = 0; i < bitmap_results.size(); ++i) { |
636 const favicon_base::FaviconBitmapResult& bitmap_result = bitmap_results[i]; | 637 const favicon_base::FaviconRawBitmapResult& bitmap_result = |
| 638 bitmap_results[i]; |
637 GURL favicon_url = bitmap_result.icon_url; | 639 GURL favicon_url = bitmap_result.icon_url; |
638 if (!favicon_url.is_valid() || favicon_url.SchemeIs("data")) | 640 if (!favicon_url.is_valid() || favicon_url.SchemeIs("data")) |
639 continue; // Can happen if the page is still loading. | 641 continue; // Can happen if the page is still loading. |
640 | 642 |
641 SyncedFaviconInfo* favicon_info = GetFaviconInfo(favicon_url); | 643 SyncedFaviconInfo* favicon_info = GetFaviconInfo(favicon_url); |
642 if (!favicon_info) | 644 if (!favicon_info) |
643 return; // We reached the in-memory limit. | 645 return; // We reached the in-memory limit. |
644 | 646 |
645 favicon_updates[favicon_url].new_image |= | 647 favicon_updates[favicon_url].new_image |= |
646 !FaviconInfoHasImages(*favicon_info); | 648 !FaviconInfoHasImages(*favicon_info); |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 !FaviconInfoHasTracking(*favicon_iter->second))) { | 1034 !FaviconInfoHasTracking(*favicon_iter->second))) { |
1033 DropSyncedFavicon(favicon_iter); | 1035 DropSyncedFavicon(favicon_iter); |
1034 return; | 1036 return; |
1035 } | 1037 } |
1036 | 1038 |
1037 if (type == syncer::FAVICON_IMAGES) { | 1039 if (type == syncer::FAVICON_IMAGES) { |
1038 DVLOG(1) << "Dropping favicon image " | 1040 DVLOG(1) << "Dropping favicon image " |
1039 << favicon_iter->second.get()->favicon_url; | 1041 << favicon_iter->second.get()->favicon_url; |
1040 for (int i = 0; i < NUM_SIZES; ++i) { | 1042 for (int i = 0; i < NUM_SIZES; ++i) { |
1041 favicon_iter->second->bitmap_data[i] = | 1043 favicon_iter->second->bitmap_data[i] = |
1042 favicon_base::FaviconBitmapResult(); | 1044 favicon_base::FaviconRawBitmapResult(); |
1043 } | 1045 } |
1044 DCHECK(!FaviconInfoHasImages(*favicon_iter->second)); | 1046 DCHECK(!FaviconInfoHasImages(*favicon_iter->second)); |
1045 } else { | 1047 } else { |
1046 DCHECK_EQ(type, syncer::FAVICON_TRACKING); | 1048 DCHECK_EQ(type, syncer::FAVICON_TRACKING); |
1047 DVLOG(1) << "Dropping favicon tracking " | 1049 DVLOG(1) << "Dropping favicon tracking " |
1048 << favicon_iter->second.get()->favicon_url; | 1050 << favicon_iter->second.get()->favicon_url; |
1049 recent_favicons_.erase(favicon_iter->second); | 1051 recent_favicons_.erase(favicon_iter->second); |
1050 favicon_iter->second->last_visit_time = base::Time(); | 1052 favicon_iter->second->last_visit_time = base::Time(); |
1051 favicon_iter->second->is_bookmarked = false; | 1053 favicon_iter->second->is_bookmarked = false; |
1052 recent_favicons_.insert(favicon_iter->second); | 1054 recent_favicons_.insert(favicon_iter->second); |
1053 DCHECK(!FaviconInfoHasTracking(*favicon_iter->second)); | 1055 DCHECK(!FaviconInfoHasTracking(*favicon_iter->second)); |
1054 } | 1056 } |
1055 } | 1057 } |
1056 | 1058 |
1057 size_t FaviconCache::NumFaviconsForTest() const { | 1059 size_t FaviconCache::NumFaviconsForTest() const { |
1058 return synced_favicons_.size(); | 1060 return synced_favicons_.size(); |
1059 } | 1061 } |
1060 | 1062 |
1061 size_t FaviconCache::NumTasksForTest() const { | 1063 size_t FaviconCache::NumTasksForTest() const { |
1062 return page_task_map_.size(); | 1064 return page_task_map_.size(); |
1063 } | 1065 } |
1064 | 1066 |
1065 } // namespace browser_sync | 1067 } // namespace browser_sync |
OLD | NEW |