| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |