| 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 "chrome/browser/bookmarks/bookmark_model.h" | 5 #include "chrome/browser/bookmarks/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" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/i18n/string_compare.h" | 12 #include "base/i18n/string_compare.h" |
| 13 #include "base/prefs/pref_service.h" | 13 #include "base/logging.h" |
| 14 #include "base/sequenced_task_runner.h" | 14 #include "base/strings/string_util.h" |
| 15 #include "chrome/browser/bookmarks/bookmark_expanded_state_tracker.h" | 15 #include "chrome/browser/bookmarks/bookmark_expanded_state_tracker.h" |
| 16 #include "chrome/browser/bookmarks/bookmark_index.h" | 16 #include "chrome/browser/bookmarks/bookmark_index.h" |
| 17 #include "chrome/browser/bookmarks/bookmark_model_observer.h" | 17 #include "chrome/browser/bookmarks/bookmark_model_observer.h" |
| 18 #include "chrome/browser/bookmarks/bookmark_node_data.h" |
| 18 #include "chrome/browser/bookmarks/bookmark_storage.h" | 19 #include "chrome/browser/bookmarks/bookmark_storage.h" |
| 19 #include "chrome/browser/bookmarks/bookmark_utils.h" | 20 #include "chrome/browser/bookmarks/bookmark_utils.h" |
| 20 #include "chrome/browser/chrome_notification_types.h" | |
| 21 #include "chrome/browser/favicon/favicon_changed_details.h" | |
| 22 #include "chrome/browser/favicon/favicon_service.h" | |
| 23 #include "chrome/browser/favicon/favicon_service_factory.h" | |
| 24 #include "chrome/browser/history/history_service.h" | |
| 25 #include "chrome/browser/history/history_service_factory.h" | |
| 26 #include "chrome/browser/profiles/profile.h" | |
| 27 #include "chrome/common/pref_names.h" | |
| 28 #include "components/bookmarks/core/browser/bookmark_match.h" | 21 #include "components/bookmarks/core/browser/bookmark_match.h" |
| 29 #include "components/favicon_base/favicon_types.h" | 22 #include "components/favicon_base/favicon_types.h" |
| 30 #include "content/public/browser/notification_details.h" | |
| 31 #include "content/public/browser/notification_source.h" | |
| 32 #include "grit/component_strings.h" | 23 #include "grit/component_strings.h" |
| 33 #include "ui/base/l10n/l10n_util.h" | 24 #include "ui/base/l10n/l10n_util.h" |
| 34 #include "ui/gfx/favicon_size.h" | 25 #include "ui/gfx/favicon_size.h" |
| 35 #include "ui/gfx/image/image_util.h" | |
| 36 | 26 |
| 37 using base::Time; | 27 using base::Time; |
| 38 | 28 |
| 39 namespace { | 29 namespace { |
| 40 | 30 |
| 41 // Helper to get a mutable bookmark node. | 31 // Helper to get a mutable bookmark node. |
| 42 BookmarkNode* AsMutable(const BookmarkNode* node) { | 32 BookmarkNode* AsMutable(const BookmarkNode* node) { |
| 43 return const_cast<BookmarkNode*>(node); | 33 return const_cast<BookmarkNode*>(node); |
| 44 } | 34 } |
| 45 | 35 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 65 } | 55 } |
| 66 | 56 |
| 67 private: | 57 private: |
| 68 icu::Collator* collator_; | 58 icu::Collator* collator_; |
| 69 }; | 59 }; |
| 70 | 60 |
| 71 } // namespace | 61 } // namespace |
| 72 | 62 |
| 73 // BookmarkModel -------------------------------------------------------------- | 63 // BookmarkModel -------------------------------------------------------------- |
| 74 | 64 |
| 75 BookmarkModel::BookmarkModel(Profile* profile, | 65 BookmarkModel::BookmarkModel(BookmarkClient* client, bool index_urls) |
| 76 bool index_urls) | 66 : client_(client), |
| 77 : profile_(profile), | |
| 78 loaded_(false), | 67 loaded_(false), |
| 79 root_(GURL()), | 68 root_(GURL()), |
| 80 bookmark_bar_node_(NULL), | 69 bookmark_bar_node_(NULL), |
| 81 other_node_(NULL), | 70 other_node_(NULL), |
| 82 mobile_node_(NULL), | 71 mobile_node_(NULL), |
| 83 next_node_id_(1), | 72 next_node_id_(1), |
| 84 observers_(ObserverList<BookmarkModelObserver>::NOTIFY_EXISTING_ONLY), | 73 observers_(ObserverList<BookmarkModelObserver>::NOTIFY_EXISTING_ONLY), |
| 85 index_urls_(index_urls), | 74 index_urls_(index_urls), |
| 86 loaded_signal_(true, false), | 75 loaded_signal_(true, false), |
| 87 extensive_changes_(0) { | 76 extensive_changes_(0) { |
| 88 if (!profile_) { | 77 DCHECK(client_); |
| 89 // Profile is null during testing. | |
| 90 DoneLoading(CreateLoadDetails()); | |
| 91 } | |
| 92 } | 78 } |
| 93 | 79 |
| 94 BookmarkModel::~BookmarkModel() { | 80 BookmarkModel::~BookmarkModel() { |
| 95 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, | 81 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
| 96 BookmarkModelBeingDeleted(this)); | 82 BookmarkModelBeingDeleted(this)); |
| 97 | 83 |
| 98 if (store_.get()) { | 84 if (store_.get()) { |
| 99 // The store maintains a reference back to us. We need to tell it we're gone | 85 // The store maintains a reference back to us. We need to tell it we're gone |
| 100 // so that it doesn't try and invoke a method back on us again. | 86 // so that it doesn't try and invoke a method back on us again. |
| 101 store_->BookmarkModelDeleted(); | 87 store_->BookmarkModelDeleted(); |
| 102 } | 88 } |
| 103 } | 89 } |
| 104 | 90 |
| 105 void BookmarkModel::Shutdown() { | 91 void BookmarkModel::Shutdown() { |
| 106 if (loaded_) | 92 if (loaded_) |
| 107 return; | 93 return; |
| 108 | 94 |
| 109 // See comment in HistoryService::ShutdownOnUIThread where this is invoked for | 95 // See comment in HistoryService::ShutdownOnUIThread where this is invoked for |
| 110 // details. It is also called when the BookmarkModel is deleted. | 96 // details. It is also called when the BookmarkModel is deleted. |
| 111 loaded_signal_.Signal(); | 97 loaded_signal_.Signal(); |
| 112 } | 98 } |
| 113 | 99 |
| 114 void BookmarkModel::Load( | 100 void BookmarkModel::Load( |
| 115 const scoped_refptr<base::SequencedTaskRunner>& task_runner) { | 101 PrefService* pref_service, |
| 102 const std::string& accept_languages, |
| 103 const base::FilePath& profile_path, |
| 104 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner, |
| 105 const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner) { |
| 116 if (store_.get()) { | 106 if (store_.get()) { |
| 117 // If the store is non-null, it means Load was already invoked. Load should | 107 // If the store is non-null, it means Load was already invoked. Load should |
| 118 // only be invoked once. | 108 // only be invoked once. |
| 119 NOTREACHED(); | 109 NOTREACHED(); |
| 120 return; | 110 return; |
| 121 } | 111 } |
| 122 | 112 |
| 123 expanded_state_tracker_.reset( | 113 expanded_state_tracker_.reset( |
| 124 new BookmarkExpandedStateTracker(this, profile_->GetPrefs())); | 114 new BookmarkExpandedStateTracker(this, pref_service)); |
| 125 | |
| 126 // Listen for changes to favicons so that we can update the favicon of the | |
| 127 // node appropriately. | |
| 128 registrar_.Add(this, chrome::NOTIFICATION_FAVICON_CHANGED, | |
| 129 content::Source<Profile>(profile_)); | |
| 130 | 115 |
| 131 // Load the bookmarks. BookmarkStorage notifies us when done. | 116 // Load the bookmarks. BookmarkStorage notifies us when done. |
| 132 store_ = new BookmarkStorage(profile_, this, task_runner.get()); | 117 store_ = new BookmarkStorage(this, profile_path, io_task_runner.get()); |
| 133 store_->LoadBookmarks(CreateLoadDetails()); | 118 store_->LoadBookmarks(CreateLoadDetails(accept_languages), ui_task_runner); |
| 134 } | 119 } |
| 135 | 120 |
| 136 const BookmarkNode* BookmarkModel::GetParentForNewNodes() { | 121 const BookmarkNode* BookmarkModel::GetParentForNewNodes() { |
| 137 std::vector<const BookmarkNode*> nodes = | 122 std::vector<const BookmarkNode*> nodes = |
| 138 bookmark_utils::GetMostRecentlyModifiedFolders(this, 1); | 123 bookmark_utils::GetMostRecentlyModifiedFolders(this, 1); |
| 139 DCHECK(!nodes.empty()); // This list is always padded with default folders. | 124 DCHECK(!nodes.empty()); // This list is always padded with default folders. |
| 140 return nodes[0]; | 125 return nodes[0]; |
| 141 } | 126 } |
| 142 | 127 |
| 143 void BookmarkModel::AddObserver(BookmarkModelObserver* observer) { | 128 void BookmarkModel::AddObserver(BookmarkModelObserver* observer) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 BookmarkNode* child_node = permanent_node->GetChild(j); | 186 BookmarkNode* child_node = permanent_node->GetChild(j); |
| 202 removed_nodes.push_back(child_node); | 187 removed_nodes.push_back(child_node); |
| 203 RemoveNodeAndGetRemovedUrls(child_node, &removed_urls); | 188 RemoveNodeAndGetRemovedUrls(child_node, &removed_urls); |
| 204 } | 189 } |
| 205 } | 190 } |
| 206 } | 191 } |
| 207 EndExtensiveChanges(); | 192 EndExtensiveChanges(); |
| 208 if (store_.get()) | 193 if (store_.get()) |
| 209 store_->ScheduleSave(); | 194 store_->ScheduleSave(); |
| 210 | 195 |
| 211 NotifyHistoryAboutRemovedBookmarks(removed_urls); | 196 // TODO(sdefresne): remove this method from the BookmarkClient (by having |
| 197 // the client register itself as a BookmarkModelObserver if it is interested |
| 198 // in the events), http://crbug.com/364433 |
| 199 client_->NotifyHistoryAboutRemovedBookmarks(removed_urls); |
| 212 | 200 |
| 213 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, | 201 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
| 214 BookmarkAllNodesRemoved(this)); | 202 BookmarkAllNodesRemoved(this)); |
| 215 } | 203 } |
| 216 | 204 |
| 217 void BookmarkModel::Move(const BookmarkNode* node, | 205 void BookmarkModel::Move(const BookmarkNode* node, |
| 218 const BookmarkNode* new_parent, | 206 const BookmarkNode* new_parent, |
| 219 int index) { | 207 int index) { |
| 220 if (!loaded_ || !node || !IsValidIndex(new_parent, index, true) || | 208 if (!loaded_ || !node || !IsValidIndex(new_parent, index, true) || |
| 221 is_root_node(new_parent) || is_permanent_node(node)) { | 209 is_root_node(new_parent) || is_permanent_node(node)) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 const gfx::Image& BookmarkModel::GetFavicon(const BookmarkNode* node) { | 270 const gfx::Image& BookmarkModel::GetFavicon(const BookmarkNode* node) { |
| 283 DCHECK(node); | 271 DCHECK(node); |
| 284 if (node->favicon_state() == BookmarkNode::INVALID_FAVICON) { | 272 if (node->favicon_state() == BookmarkNode::INVALID_FAVICON) { |
| 285 BookmarkNode* mutable_node = AsMutable(node); | 273 BookmarkNode* mutable_node = AsMutable(node); |
| 286 mutable_node->set_favicon_state(BookmarkNode::LOADING_FAVICON); | 274 mutable_node->set_favicon_state(BookmarkNode::LOADING_FAVICON); |
| 287 LoadFavicon(mutable_node); | 275 LoadFavicon(mutable_node); |
| 288 } | 276 } |
| 289 return node->favicon(); | 277 return node->favicon(); |
| 290 } | 278 } |
| 291 | 279 |
| 292 void BookmarkModel::SetTitle(const BookmarkNode* node, const base::string16& tit
le) { | 280 void BookmarkModel::SetTitle(const BookmarkNode* node, |
| 281 const base::string16& title) { |
| 293 if (!node) { | 282 if (!node) { |
| 294 NOTREACHED(); | 283 NOTREACHED(); |
| 295 return; | 284 return; |
| 296 } | 285 } |
| 297 if (node->GetTitle() == title) | 286 if (node->GetTitle() == title) |
| 298 return; | 287 return; |
| 299 | 288 |
| 300 if (is_permanent_node(node)) { | 289 if (is_permanent_node(node)) { |
| 301 NOTREACHED(); | 290 NOTREACHED(); |
| 302 return; | 291 return; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 const BookmarkNode* node, | 399 const BookmarkNode* node, |
| 411 int64 sync_transaction_version) { | 400 int64 sync_transaction_version) { |
| 412 if (sync_transaction_version == node->sync_transaction_version()) | 401 if (sync_transaction_version == node->sync_transaction_version()) |
| 413 return; | 402 return; |
| 414 | 403 |
| 415 AsMutable(node)->set_sync_transaction_version(sync_transaction_version); | 404 AsMutable(node)->set_sync_transaction_version(sync_transaction_version); |
| 416 if (store_.get()) | 405 if (store_.get()) |
| 417 store_->ScheduleSave(); | 406 store_->ScheduleSave(); |
| 418 } | 407 } |
| 419 | 408 |
| 409 void BookmarkModel::OnFaviconChanged(const std::set<GURL>& urls) { |
| 410 // Ignore events if |Load| has not been called yet. |
| 411 if (!store_) |
| 412 return; |
| 413 |
| 414 // Prevent the observers from getting confused for multiple favicon loads. |
| 415 for (std::set<GURL>::const_iterator i = urls.begin(); i != urls.end(); ++i) { |
| 416 std::vector<const BookmarkNode*> nodes; |
| 417 GetNodesByURL(*i, &nodes); |
| 418 for (size_t i = 0; i < nodes.size(); ++i) { |
| 419 // Got an updated favicon, for a URL, do a new request. |
| 420 BookmarkNode* node = AsMutable(nodes[i]); |
| 421 node->InvalidateFavicon(); |
| 422 CancelPendingFaviconLoadRequests(node); |
| 423 FOR_EACH_OBSERVER(BookmarkModelObserver, |
| 424 observers_, |
| 425 BookmarkNodeFaviconChanged(this, node)); |
| 426 } |
| 427 } |
| 428 } |
| 429 |
| 420 void BookmarkModel::SetDateAdded(const BookmarkNode* node, | 430 void BookmarkModel::SetDateAdded(const BookmarkNode* node, |
| 421 base::Time date_added) { | 431 base::Time date_added) { |
| 422 if (!node) { | 432 if (!node) { |
| 423 NOTREACHED(); | 433 NOTREACHED(); |
| 424 return; | 434 return; |
| 425 } | 435 } |
| 426 | 436 |
| 427 if (node->date_added() == date_added) | 437 if (node->date_added() == date_added) |
| 428 return; | 438 return; |
| 429 | 439 |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 const base::string16& text, | 643 const base::string16& text, |
| 634 size_t max_count, | 644 size_t max_count, |
| 635 std::vector<BookmarkMatch>* matches) { | 645 std::vector<BookmarkMatch>* matches) { |
| 636 if (!loaded_) | 646 if (!loaded_) |
| 637 return; | 647 return; |
| 638 | 648 |
| 639 index_->GetBookmarksMatching(text, max_count, matches); | 649 index_->GetBookmarksMatching(text, max_count, matches); |
| 640 } | 650 } |
| 641 | 651 |
| 642 void BookmarkModel::ClearStore() { | 652 void BookmarkModel::ClearStore() { |
| 643 registrar_.RemoveAll(); | |
| 644 store_ = NULL; | 653 store_ = NULL; |
| 645 } | 654 } |
| 646 | 655 |
| 647 void BookmarkModel::SetPermanentNodeVisible(BookmarkNode::Type type, | 656 void BookmarkModel::SetPermanentNodeVisible(BookmarkNode::Type type, |
| 648 bool value) { | 657 bool value) { |
| 649 DCHECK(loaded_); | 658 DCHECK(loaded_); |
| 650 switch (type) { | 659 switch (type) { |
| 651 case BookmarkNode::BOOKMARK_BAR: | 660 case BookmarkNode::BOOKMARK_BAR: |
| 652 bookmark_bar_node_->set_visible(value); | 661 bookmark_bar_node_->set_visible(value); |
| 653 break; | 662 break; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 682 index_->Remove(node); | 691 index_->Remove(node); |
| 683 } | 692 } |
| 684 | 693 |
| 685 CancelPendingFaviconLoadRequests(node); | 694 CancelPendingFaviconLoadRequests(node); |
| 686 | 695 |
| 687 // Recurse through children. | 696 // Recurse through children. |
| 688 for (int i = node->child_count() - 1; i >= 0; --i) | 697 for (int i = node->child_count() - 1; i >= 0; --i) |
| 689 RemoveNode(node->GetChild(i), removed_urls); | 698 RemoveNode(node->GetChild(i), removed_urls); |
| 690 } | 699 } |
| 691 | 700 |
| 692 void BookmarkModel::DoneLoading(BookmarkLoadDetails* details_delete_me) { | 701 void BookmarkModel::DoneLoading(scoped_ptr<BookmarkLoadDetails> details) { |
| 693 DCHECK(details_delete_me); | 702 DCHECK(details); |
| 694 scoped_ptr<BookmarkLoadDetails> details(details_delete_me); | |
| 695 if (loaded_) { | 703 if (loaded_) { |
| 696 // We should only ever be loaded once. | 704 // We should only ever be loaded once. |
| 697 NOTREACHED(); | 705 NOTREACHED(); |
| 698 return; | 706 return; |
| 699 } | 707 } |
| 700 | 708 |
| 701 next_node_id_ = details->max_id(); | 709 next_node_id_ = details->max_id(); |
| 702 if (details->computed_checksum() != details->stored_checksum() || | 710 if (details->computed_checksum() != details->stored_checksum() || |
| 703 details->ids_reassigned()) { | 711 details->ids_reassigned()) { |
| 704 // If bookmarks file changed externally, the IDs may have changed | 712 // If bookmarks file changed externally, the IDs may have changed |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 | 757 |
| 750 std::set<GURL> removed_urls; | 758 std::set<GURL> removed_urls; |
| 751 { | 759 { |
| 752 base::AutoLock url_lock(url_lock_); | 760 base::AutoLock url_lock(url_lock_); |
| 753 RemoveNodeAndGetRemovedUrls(node.get(), &removed_urls); | 761 RemoveNodeAndGetRemovedUrls(node.get(), &removed_urls); |
| 754 } | 762 } |
| 755 | 763 |
| 756 if (store_.get()) | 764 if (store_.get()) |
| 757 store_->ScheduleSave(); | 765 store_->ScheduleSave(); |
| 758 | 766 |
| 759 NotifyHistoryAboutRemovedBookmarks(removed_urls); | 767 // TODO(sdefresne): remove this method from the BookmarkClient (by having |
| 768 // the client register itself as a BookmarkModelObserver if it is interested |
| 769 // in the events), http://crbug.com/364433 |
| 770 client_->NotifyHistoryAboutRemovedBookmarks(removed_urls); |
| 760 | 771 |
| 761 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, | 772 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
| 762 BookmarkNodeRemoved(this, parent, index, node.get())); | 773 BookmarkNodeRemoved(this, parent, index, node.get())); |
| 763 } | 774 } |
| 764 | 775 |
| 765 void BookmarkModel::RemoveNodeFromURLSet(BookmarkNode* node) { | 776 void BookmarkModel::RemoveNodeFromURLSet(BookmarkNode* node) { |
| 766 // NOTE: this is called in such a way that url_lock_ is already held. As | 777 // NOTE: this is called in such a way that url_lock_ is already held. As |
| 767 // such, this doesn't explicitly grab the lock. | 778 // such, this doesn't explicitly grab the lock. |
| 768 NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.find(node); | 779 NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.find(node); |
| 769 DCHECK(i != nodes_ordered_by_url_set_.end()); | 780 DCHECK(i != nodes_ordered_by_url_set_.end()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 793 // invalidated, so using i++ here within the "erase" call is | 804 // invalidated, so using i++ here within the "erase" call is |
| 794 // important as it advances the iterator before passing the | 805 // important as it advances the iterator before passing the |
| 795 // old value through to erase. | 806 // old value through to erase. |
| 796 removed_urls->erase(i++); | 807 removed_urls->erase(i++); |
| 797 } else { | 808 } else { |
| 798 ++i; | 809 ++i; |
| 799 } | 810 } |
| 800 } | 811 } |
| 801 } | 812 } |
| 802 | 813 |
| 803 void BookmarkModel::NotifyHistoryAboutRemovedBookmarks( | |
| 804 const std::set<GURL>& removed_bookmark_urls) const { | |
| 805 if (removed_bookmark_urls.empty()) { | |
| 806 // No point in sending out notification if the starred state didn't change. | |
| 807 return; | |
| 808 } | |
| 809 | |
| 810 if (profile_) { | |
| 811 HistoryService* history = | |
| 812 HistoryServiceFactory::GetForProfile(profile_, | |
| 813 Profile::EXPLICIT_ACCESS); | |
| 814 if (history) | |
| 815 history->URLsNoLongerBookmarked(removed_bookmark_urls); | |
| 816 } | |
| 817 } | |
| 818 | |
| 819 BookmarkNode* BookmarkModel::AddNode(BookmarkNode* parent, | 814 BookmarkNode* BookmarkModel::AddNode(BookmarkNode* parent, |
| 820 int index, | 815 int index, |
| 821 BookmarkNode* node) { | 816 BookmarkNode* node) { |
| 822 parent->Add(node, index); | 817 parent->Add(node, index); |
| 823 | 818 |
| 824 if (store_.get()) | 819 if (store_.get()) |
| 825 store_->ScheduleSave(); | 820 store_->ScheduleSave(); |
| 826 | 821 |
| 827 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, | 822 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
| 828 BookmarkNodeAdded(this, parent, index)); | 823 BookmarkNodeAdded(this, parent, index)); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 node->set_icon_url(image_result.icon_url); | 877 node->set_icon_url(image_result.icon_url); |
| 883 FaviconLoaded(node); | 878 FaviconLoaded(node); |
| 884 } | 879 } |
| 885 } | 880 } |
| 886 | 881 |
| 887 void BookmarkModel::LoadFavicon(BookmarkNode* node) { | 882 void BookmarkModel::LoadFavicon(BookmarkNode* node) { |
| 888 if (node->is_folder()) | 883 if (node->is_folder()) |
| 889 return; | 884 return; |
| 890 | 885 |
| 891 DCHECK(node->url().is_valid()); | 886 DCHECK(node->url().is_valid()); |
| 892 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( | 887 base::CancelableTaskTracker::TaskId taskId = client_->GetFaviconImageForURL( |
| 893 profile_, Profile::EXPLICIT_ACCESS); | 888 node->url(), |
| 894 if (!favicon_service) | 889 favicon_base::FAVICON, |
| 895 return; | 890 gfx::kFaviconSize, |
| 896 base::CancelableTaskTracker::TaskId taskId = | 891 base::Bind( |
| 897 favicon_service->GetFaviconImageForURL( | 892 &BookmarkModel::OnFaviconDataAvailable, base::Unretained(this), node), |
| 898 FaviconService::FaviconForURLParams( | 893 &cancelable_task_tracker_); |
| 899 node->url(), favicon_base::FAVICON, gfx::kFaviconSize), | 894 if (taskId != base::CancelableTaskTracker::kBadTaskId) |
| 900 base::Bind(&BookmarkModel::OnFaviconDataAvailable, | 895 node->set_favicon_load_task_id(taskId); |
| 901 base::Unretained(this), | |
| 902 node), | |
| 903 &cancelable_task_tracker_); | |
| 904 node->set_favicon_load_task_id(taskId); | |
| 905 } | 896 } |
| 906 | 897 |
| 907 void BookmarkModel::FaviconLoaded(const BookmarkNode* node) { | 898 void BookmarkModel::FaviconLoaded(const BookmarkNode* node) { |
| 908 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, | 899 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
| 909 BookmarkNodeFaviconChanged(this, node)); | 900 BookmarkNodeFaviconChanged(this, node)); |
| 910 } | 901 } |
| 911 | 902 |
| 912 void BookmarkModel::CancelPendingFaviconLoadRequests(BookmarkNode* node) { | 903 void BookmarkModel::CancelPendingFaviconLoadRequests(BookmarkNode* node) { |
| 913 if (node->favicon_load_task_id() != base::CancelableTaskTracker::kBadTaskId) { | 904 if (node->favicon_load_task_id() != base::CancelableTaskTracker::kBadTaskId) { |
| 914 cancelable_task_tracker_.TryCancel(node->favicon_load_task_id()); | 905 cancelable_task_tracker_.TryCancel(node->favicon_load_task_id()); |
| 915 node->set_favicon_load_task_id(base::CancelableTaskTracker::kBadTaskId); | 906 node->set_favicon_load_task_id(base::CancelableTaskTracker::kBadTaskId); |
| 916 } | 907 } |
| 917 } | 908 } |
| 918 | 909 |
| 919 void BookmarkModel::Observe(int type, | |
| 920 const content::NotificationSource& source, | |
| 921 const content::NotificationDetails& details) { | |
| 922 switch (type) { | |
| 923 case chrome::NOTIFICATION_FAVICON_CHANGED: { | |
| 924 // Prevent the observers from getting confused for multiple favicon loads. | |
| 925 content::Details<FaviconChangedDetails> favicon_details(details); | |
| 926 for (std::set<GURL>::const_iterator i = favicon_details->urls.begin(); | |
| 927 i != favicon_details->urls.end(); ++i) { | |
| 928 std::vector<const BookmarkNode*> nodes; | |
| 929 GetNodesByURL(*i, &nodes); | |
| 930 for (size_t i = 0; i < nodes.size(); ++i) { | |
| 931 // Got an updated favicon, for a URL, do a new request. | |
| 932 BookmarkNode* node = AsMutable(nodes[i]); | |
| 933 node->InvalidateFavicon(); | |
| 934 CancelPendingFaviconLoadRequests(node); | |
| 935 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, | |
| 936 BookmarkNodeFaviconChanged(this, node)); | |
| 937 } | |
| 938 } | |
| 939 break; | |
| 940 } | |
| 941 | |
| 942 default: | |
| 943 NOTREACHED(); | |
| 944 break; | |
| 945 } | |
| 946 } | |
| 947 | |
| 948 void BookmarkModel::PopulateNodesByURL(BookmarkNode* node) { | 910 void BookmarkModel::PopulateNodesByURL(BookmarkNode* node) { |
| 949 // NOTE: this is called with url_lock_ already held. As such, this doesn't | 911 // NOTE: this is called with url_lock_ already held. As such, this doesn't |
| 950 // explicitly grab the lock. | 912 // explicitly grab the lock. |
| 951 if (node->is_url()) | 913 if (node->is_url()) |
| 952 nodes_ordered_by_url_set_.insert(node); | 914 nodes_ordered_by_url_set_.insert(node); |
| 953 for (int i = 0; i < node->child_count(); ++i) | 915 for (int i = 0; i < node->child_count(); ++i) |
| 954 PopulateNodesByURL(node->GetChild(i)); | 916 PopulateNodesByURL(node->GetChild(i)); |
| 955 } | 917 } |
| 956 | 918 |
| 957 int64 BookmarkModel::generate_next_node_id() { | 919 int64 BookmarkModel::generate_next_node_id() { |
| 958 return next_node_id_++; | 920 return next_node_id_++; |
| 959 } | 921 } |
| 960 | 922 |
| 961 BookmarkLoadDetails* BookmarkModel::CreateLoadDetails() { | 923 scoped_ptr<BookmarkLoadDetails> BookmarkModel::CreateLoadDetails( |
| 924 const std::string& accept_languages) { |
| 962 BookmarkPermanentNode* bb_node = | 925 BookmarkPermanentNode* bb_node = |
| 963 CreatePermanentNode(BookmarkNode::BOOKMARK_BAR); | 926 CreatePermanentNode(BookmarkNode::BOOKMARK_BAR); |
| 964 BookmarkPermanentNode* other_node = | 927 BookmarkPermanentNode* other_node = |
| 965 CreatePermanentNode(BookmarkNode::OTHER_NODE); | 928 CreatePermanentNode(BookmarkNode::OTHER_NODE); |
| 966 BookmarkPermanentNode* mobile_node = | 929 BookmarkPermanentNode* mobile_node = |
| 967 CreatePermanentNode(BookmarkNode::MOBILE); | 930 CreatePermanentNode(BookmarkNode::MOBILE); |
| 968 return new BookmarkLoadDetails( | 931 return scoped_ptr<BookmarkLoadDetails>(new BookmarkLoadDetails( |
| 969 bb_node, other_node, mobile_node, | 932 bb_node, |
| 970 new BookmarkIndex( | 933 other_node, |
| 971 profile_, | 934 mobile_node, |
| 972 index_urls_, | 935 new BookmarkIndex(client_, index_urls_, accept_languages), |
| 973 profile_ ? | 936 next_node_id_)); |
| 974 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages) : | |
| 975 std::string()), | |
| 976 next_node_id_); | |
| 977 } | 937 } |
| OLD | NEW |