Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(360)

Side by Side Diff: components/bookmarks/browser/bookmark_model.cc

Issue 1133463005: Update all bookmarks which use an icon URL when a favicon's bitmap is updated (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@startup_do_not_unexpire
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/bookmarks/browser/bookmark_model.h" 5 #include "components/bookmarks/browser/bookmark_model.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 24 matching lines...) Expand all
35 // Helper to get a mutable bookmark node. 35 // Helper to get a mutable bookmark node.
36 BookmarkNode* AsMutable(const BookmarkNode* node) { 36 BookmarkNode* AsMutable(const BookmarkNode* node) {
37 return const_cast<BookmarkNode*>(node); 37 return const_cast<BookmarkNode*>(node);
38 } 38 }
39 39
40 // Helper to get a mutable permanent bookmark node. 40 // Helper to get a mutable permanent bookmark node.
41 BookmarkPermanentNode* AsMutable(const BookmarkPermanentNode* node) { 41 BookmarkPermanentNode* AsMutable(const BookmarkPermanentNode* node) {
42 return const_cast<BookmarkPermanentNode*>(node); 42 return const_cast<BookmarkPermanentNode*>(node);
43 } 43 }
44 44
45 // Removes |node| from |set|. This method is useful when the multiset has a
46 // custom comparator.
47 template<class T> void RemoveFromMultiset(
48 std::multiset<BookmarkNode*, T>* set,
49 BookmarkNode* node) {
50 std::multiset<BookmarkNode*>::iterator it = set->find(node);
51 if (it == set->end())
52 return;
53
54 while (*it != node)
55 ++it;
56 set->erase(it);
57 }
58
45 // Comparator used when sorting permanent nodes. Nodes that are initially 59 // Comparator used when sorting permanent nodes. Nodes that are initially
46 // visible are sorted before nodes that are initially hidden. 60 // visible are sorted before nodes that are initially hidden.
47 class VisibilityComparator 61 class VisibilityComparator
48 : public std::binary_function<const BookmarkPermanentNode*, 62 : public std::binary_function<const BookmarkPermanentNode*,
49 const BookmarkPermanentNode*, 63 const BookmarkPermanentNode*,
50 bool> { 64 bool> {
51 public: 65 public:
52 explicit VisibilityComparator(BookmarkClient* client) : client_(client) {} 66 explicit VisibilityComparator(BookmarkClient* client) : client_(client) {}
53 67
54 // Returns true if |n1| preceeds |n2|. 68 // Returns true if |n1| preceeds |n2|.
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 BookmarkNodeChanged(this, node)); 353 BookmarkNodeChanged(this, node));
340 } 354 }
341 355
342 void BookmarkModel::SetURL(const BookmarkNode* node, const GURL& url) { 356 void BookmarkModel::SetURL(const BookmarkNode* node, const GURL& url) {
343 DCHECK(node && !node->is_folder()); 357 DCHECK(node && !node->is_folder());
344 358
345 if (node->url() == url) 359 if (node->url() == url)
346 return; 360 return;
347 361
348 BookmarkNode* mutable_node = AsMutable(node); 362 BookmarkNode* mutable_node = AsMutable(node);
349 mutable_node->InvalidateFavicon(); 363 InvalidateFavicon(mutable_node);
350 CancelPendingFaviconLoadRequests(mutable_node);
351 364
352 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, 365 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
353 OnWillChangeBookmarkNode(this, node)); 366 OnWillChangeBookmarkNode(this, node));
354 367
355 { 368 {
356 base::AutoLock url_lock(url_lock_); 369 base::AutoLock url_lock(url_lock_);
357 RemoveNodeFromInternalMaps(mutable_node); 370 RemoveNodeFromInternalMaps(mutable_node);
358 mutable_node->set_url(url); 371 mutable_node->set_url(url);
359 AddNodeToInternalMaps(mutable_node); 372 AddNodeToInternalMaps(mutable_node);
360 } 373 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 DCHECK(client_->CanSyncNode(node)); 441 DCHECK(client_->CanSyncNode(node));
429 442
430 if (sync_transaction_version == node->sync_transaction_version()) 443 if (sync_transaction_version == node->sync_transaction_version())
431 return; 444 return;
432 445
433 AsMutable(node)->set_sync_transaction_version(sync_transaction_version); 446 AsMutable(node)->set_sync_transaction_version(sync_transaction_version);
434 if (store_.get()) 447 if (store_.get())
435 store_->ScheduleSave(); 448 store_->ScheduleSave();
436 } 449 }
437 450
438 void BookmarkModel::OnFaviconChanged(const std::set<GURL>& urls) { 451 void BookmarkModel::OnFaviconsChanged(const std::vector<GURL>& page_urls,
452 const std::vector<GURL>& icon_urls) {
439 // Ignore events if |Load| has not been called yet. 453 // Ignore events if |Load| has not been called yet.
440 if (!store_) 454 if (!store_)
441 return; 455 return;
442 456
443 // Prevent the observers from getting confused for multiple favicon loads. 457 std::set<const BookmarkNode*> to_update;
444 for (std::set<GURL>::const_iterator i = urls.begin(); i != urls.end(); ++i) { 458 for (const GURL& page_url : page_urls) {
445 std::vector<const BookmarkNode*> nodes; 459 std::vector<const BookmarkNode*> nodes;
446 GetNodesByURL(*i, &nodes); 460 GetNodesByURL(page_url, &nodes);
447 for (size_t i = 0; i < nodes.size(); ++i) { 461 for (const BookmarkNode* node : nodes)
448 // Got an updated favicon, for a URL, do a new request. 462 to_update.insert(node);
449 BookmarkNode* node = AsMutable(nodes[i]); 463 }
450 node->InvalidateFavicon(); 464
451 CancelPendingFaviconLoadRequests(node); 465 for (const GURL& icon_url : icon_urls) {
452 FOR_EACH_OBSERVER(BookmarkModelObserver, 466 std::vector<const BookmarkNode*> nodes;
453 observers_, 467 GetNodesByIconURL(icon_url, &nodes);
454 BookmarkNodeFaviconChanged(this, node)); 468 for (const BookmarkNode* node : nodes)
455 } 469 to_update.insert(node);
470 }
471
472 for (const BookmarkNode* node : to_update) {
473 // Rerequest the favicon.
474 BookmarkNode* mutable_node = AsMutable(node);
475 InvalidateFavicon(mutable_node);
476 FOR_EACH_OBSERVER(BookmarkModelObserver,
477 observers_,
478 BookmarkNodeFaviconChanged(this, node));
456 } 479 }
457 } 480 }
458 481
459 void BookmarkModel::SetDateAdded(const BookmarkNode* node, Time date_added) { 482 void BookmarkModel::SetDateAdded(const BookmarkNode* node, Time date_added) {
460 DCHECK(node && !is_permanent_node(node)); 483 DCHECK(node && !is_permanent_node(node));
461 484
462 if (node->date_added() == date_added) 485 if (node->date_added() == date_added)
463 return; 486 return;
464 487
465 AsMutable(node)->set_date_added(date_added); 488 AsMutable(node)->set_date_added(date_added);
(...skipping 11 matching lines...) Expand all
477 std::vector<const BookmarkNode*>* nodes) { 500 std::vector<const BookmarkNode*>* nodes) {
478 base::AutoLock url_lock(url_lock_); 501 base::AutoLock url_lock(url_lock_);
479 BookmarkNode tmp_node(url); 502 BookmarkNode tmp_node(url);
480 NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.find(&tmp_node); 503 NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.find(&tmp_node);
481 while (i != nodes_ordered_by_url_set_.end() && (*i)->url() == url) { 504 while (i != nodes_ordered_by_url_set_.end() && (*i)->url() == url) {
482 nodes->push_back(*i); 505 nodes->push_back(*i);
483 ++i; 506 ++i;
484 } 507 }
485 } 508 }
486 509
510 void BookmarkModel::GetNodesByIconURL(const GURL& icon_url,
511 std::vector<const BookmarkNode*>* nodes) {
512 BookmarkNode tmp_node = BookmarkNode(GURL());
513 tmp_node.set_icon_url(icon_url);
514 NodesOrderedByURLSet::iterator i =
515 nodes_ordered_by_favicon_url_set_.find(&tmp_node);
516 while (i != nodes_ordered_by_favicon_url_set_.end() &&
517 (*i)->icon_url() == icon_url) {
518 nodes->push_back(*i);
519 ++i;
520 }
521 }
522
487 const BookmarkNode* BookmarkModel::GetMostRecentlyAddedUserNodeForURL( 523 const BookmarkNode* BookmarkModel::GetMostRecentlyAddedUserNodeForURL(
488 const GURL& url) { 524 const GURL& url) {
489 std::vector<const BookmarkNode*> nodes; 525 std::vector<const BookmarkNode*> nodes;
490 GetNodesByURL(url, &nodes); 526 GetNodesByURL(url, &nodes);
491 std::sort(nodes.begin(), nodes.end(), &MoreRecentlyAdded); 527 std::sort(nodes.begin(), nodes.end(), &MoreRecentlyAdded);
492 528
493 // Look for the first node that the user can edit. 529 // Look for the first node that the user can edit.
494 for (size_t i = 0; i < nodes.size(); ++i) { 530 for (size_t i = 0; i < nodes.size(); ++i) {
495 if (client_->CanBeEditedByUser(nodes[i])) 531 if (client_->CanBeEditedByUser(nodes[i]))
496 return nodes[i]; 532 return nodes[i];
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 store_->ScheduleSave(); 879 store_->ScheduleSave();
844 880
845 FOR_EACH_OBSERVER( 881 FOR_EACH_OBSERVER(
846 BookmarkModelObserver, 882 BookmarkModelObserver,
847 observers_, 883 observers_,
848 BookmarkNodeRemoved(this, parent, index, node.get(), removed_urls)); 884 BookmarkNodeRemoved(this, parent, index, node.get(), removed_urls));
849 } 885 }
850 886
851 void BookmarkModel::RemoveNodeFromInternalMaps(BookmarkNode* node) { 887 void BookmarkModel::RemoveNodeFromInternalMaps(BookmarkNode* node) {
852 index_->Remove(node); 888 index_->Remove(node);
889 if (!node->icon_url().is_empty())
890 RemoveFromMultiset(&nodes_ordered_by_favicon_url_set_, node);
853 // NOTE: this is called in such a way that url_lock_ is already held. As 891 // NOTE: this is called in such a way that url_lock_ is already held. As
854 // such, this doesn't explicitly grab the lock. 892 // such, this doesn't explicitly grab the lock.
855 url_lock_.AssertAcquired(); 893 url_lock_.AssertAcquired();
856 NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.find(node); 894 RemoveFromMultiset(&nodes_ordered_by_url_set_, node);
857 DCHECK(i != nodes_ordered_by_url_set_.end());
858 // i points to the first node with the URL, advance until we find the
859 // node we're removing.
860 while (*i != node)
861 ++i;
862 nodes_ordered_by_url_set_.erase(i);
863 } 895 }
864 896
865 void BookmarkModel::RemoveNodeAndGetRemovedUrls(BookmarkNode* node, 897 void BookmarkModel::RemoveNodeAndGetRemovedUrls(BookmarkNode* node,
866 std::set<GURL>* removed_urls) { 898 std::set<GURL>* removed_urls) {
867 // NOTE: this method should be always called with |url_lock_| held. 899 // NOTE: this method should be always called with |url_lock_| held.
868 // This method does not explicitly acquires a lock. 900 // This method does not explicitly acquires a lock.
869 url_lock_.AssertAcquired(); 901 url_lock_.AssertAcquired();
870 DCHECK(removed_urls); 902 DCHECK(removed_urls);
871 BookmarkNode* parent = node->parent(); 903 BookmarkNode* parent = node->parent();
872 DCHECK(parent); 904 DCHECK(parent);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 } 936 }
905 937
906 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, 938 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
907 BookmarkNodeAdded(this, parent, index)); 939 BookmarkNodeAdded(this, parent, index));
908 940
909 return node; 941 return node;
910 } 942 }
911 943
912 void BookmarkModel::AddNodeToInternalMaps(BookmarkNode* node) { 944 void BookmarkModel::AddNodeToInternalMaps(BookmarkNode* node) {
913 index_->Add(node); 945 index_->Add(node);
946 if (!node->icon_url().is_empty())
947 nodes_ordered_by_favicon_url_set_.insert(node);
914 url_lock_.AssertAcquired(); 948 url_lock_.AssertAcquired();
915 nodes_ordered_by_url_set_.insert(node); 949 nodes_ordered_by_url_set_.insert(node);
916 } 950 }
917 951
918 bool BookmarkModel::IsValidIndex(const BookmarkNode* parent, 952 bool BookmarkModel::IsValidIndex(const BookmarkNode* parent,
919 int index, 953 int index,
920 bool allow_end) { 954 bool allow_end) {
921 return (parent && parent->is_folder() && 955 return (parent && parent->is_folder() &&
922 (index >= 0 && (index < parent->child_count() || 956 (index >= 0 && (index < parent->child_count() ||
923 (allow_end && index == parent->child_count())))); 957 (allow_end && index == parent->child_count()))));
(...skipping 30 matching lines...) Expand all
954 } 988 }
955 989
956 void BookmarkModel::OnFaviconDataAvailable( 990 void BookmarkModel::OnFaviconDataAvailable(
957 BookmarkNode* node, 991 BookmarkNode* node,
958 favicon_base::IconType icon_type, 992 favicon_base::IconType icon_type,
959 const favicon_base::FaviconImageResult& image_result) { 993 const favicon_base::FaviconImageResult& image_result) {
960 DCHECK(node); 994 DCHECK(node);
961 node->set_favicon_load_task_id(base::CancelableTaskTracker::kBadTaskId); 995 node->set_favicon_load_task_id(base::CancelableTaskTracker::kBadTaskId);
962 node->set_favicon_state(BookmarkNode::LOADED_FAVICON); 996 node->set_favicon_state(BookmarkNode::LOADED_FAVICON);
963 if (!image_result.image.IsEmpty()) { 997 if (!image_result.image.IsEmpty()) {
998 SetFaviconURL(node, image_result.icon_url);
964 node->set_favicon_type(icon_type); 999 node->set_favicon_type(icon_type);
965 node->set_favicon(image_result.image); 1000 node->set_favicon(image_result.image);
966 node->set_icon_url(image_result.icon_url); 1001
967 FaviconLoaded(node); 1002 FaviconLoaded(node);
968 } else if (icon_type == favicon_base::TOUCH_ICON) { 1003 } else if (icon_type == favicon_base::TOUCH_ICON) {
969 // Couldn't load the touch icon, fallback to the regular favicon. 1004 // Couldn't load the touch icon, fallback to the regular favicon.
970 DCHECK(client_->PreferTouchIcon()); 1005 DCHECK(client_->PreferTouchIcon());
971 LoadFavicon(node, favicon_base::FAVICON); 1006 LoadFavicon(node, favicon_base::FAVICON);
972 } 1007 }
973 } 1008 }
974 1009
975 void BookmarkModel::LoadFavicon(BookmarkNode* node, 1010 void BookmarkModel::LoadFavicon(BookmarkNode* node,
976 favicon_base::IconType icon_type) { 1011 favicon_base::IconType icon_type) {
(...skipping 14 matching lines...) Expand all
991 &cancelable_task_tracker_); 1026 &cancelable_task_tracker_);
992 if (taskId != base::CancelableTaskTracker::kBadTaskId) 1027 if (taskId != base::CancelableTaskTracker::kBadTaskId)
993 node->set_favicon_load_task_id(taskId); 1028 node->set_favicon_load_task_id(taskId);
994 } 1029 }
995 1030
996 void BookmarkModel::FaviconLoaded(const BookmarkNode* node) { 1031 void BookmarkModel::FaviconLoaded(const BookmarkNode* node) {
997 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, 1032 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
998 BookmarkNodeFaviconChanged(this, node)); 1033 BookmarkNodeFaviconChanged(this, node));
999 } 1034 }
1000 1035
1036 void BookmarkModel::SetFaviconURL(BookmarkNode* node, const GURL& icon_url) {
1037 if (!node->icon_url().is_empty())
1038 RemoveFromMultiset(&nodes_ordered_by_favicon_url_set_, node);
1039 node->set_icon_url(icon_url);
1040 if (!node->icon_url().is_empty())
1041 nodes_ordered_by_favicon_url_set_.insert(node);
1042 }
1043
1044 void BookmarkModel::InvalidateFavicon(BookmarkNode* node) {
1045 SetFaviconURL(node, GURL());
1046 node->set_favicon(gfx::Image());
1047 node->set_favicon_type(favicon_base::INVALID_ICON);
1048 node->set_favicon_state(BookmarkNode::INVALID_FAVICON);
1049 CancelPendingFaviconLoadRequests(node);
1050 }
1051
1001 void BookmarkModel::CancelPendingFaviconLoadRequests(BookmarkNode* node) { 1052 void BookmarkModel::CancelPendingFaviconLoadRequests(BookmarkNode* node) {
1002 if (node->favicon_load_task_id() != base::CancelableTaskTracker::kBadTaskId) { 1053 if (node->favicon_load_task_id() != base::CancelableTaskTracker::kBadTaskId) {
1003 cancelable_task_tracker_.TryCancel(node->favicon_load_task_id()); 1054 cancelable_task_tracker_.TryCancel(node->favicon_load_task_id());
1004 node->set_favicon_load_task_id(base::CancelableTaskTracker::kBadTaskId); 1055 node->set_favicon_load_task_id(base::CancelableTaskTracker::kBadTaskId);
1005 } 1056 }
1006 } 1057 }
1007 1058
1008 void BookmarkModel::PopulateNodesByURL(BookmarkNode* node) { 1059 void BookmarkModel::PopulateNodesByURL(BookmarkNode* node) {
1009 // NOTE: this is called with url_lock_ already held. As such, this doesn't 1060 // NOTE: this is called with url_lock_ already held. As such, this doesn't
1010 // explicitly grab the lock. 1061 // explicitly grab the lock.
(...skipping 18 matching lines...) Expand all
1029 return scoped_ptr<BookmarkLoadDetails>(new BookmarkLoadDetails( 1080 return scoped_ptr<BookmarkLoadDetails>(new BookmarkLoadDetails(
1030 bb_node, 1081 bb_node,
1031 other_node, 1082 other_node,
1032 mobile_node, 1083 mobile_node,
1033 client_->GetLoadExtraNodesCallback(), 1084 client_->GetLoadExtraNodesCallback(),
1034 new BookmarkIndex(client_, accept_languages), 1085 new BookmarkIndex(client_, accept_languages),
1035 next_node_id_)); 1086 next_node_id_));
1036 } 1087 }
1037 1088
1038 } // namespace bookmarks 1089 } // namespace bookmarks
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698