Index: chrome/browser/bookmarks/bookmark_model.cc |
diff --git a/chrome/browser/bookmarks/bookmark_model.cc b/chrome/browser/bookmarks/bookmark_model.cc |
index cdd91f5a973a1d0d8e0ba2b28e3f0da935a5f4b3..1e6a2042a28dfa1cf9e9324610b7bde19479ea38 100644 |
--- a/chrome/browser/bookmarks/bookmark_model.cc |
+++ b/chrome/browser/bookmarks/bookmark_model.cc |
@@ -9,7 +9,9 @@ |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
+#include "base/files/file_path.h" |
#include "base/i18n/string_compare.h" |
+#include "base/prefs/pref_service.h" |
#include "base/sequenced_task_runner.h" |
#include "chrome/browser/bookmarks/bookmark_expanded_state_tracker.h" |
#include "chrome/browser/bookmarks/bookmark_index.h" |
@@ -22,11 +24,13 @@ |
#include "chrome/browser/favicon/favicon_service_factory.h" |
#include "chrome/browser/history/history_service.h" |
#include "chrome/browser/history/history_service_factory.h" |
+#include "chrome/browser/history/url_database.h" |
#include "chrome/browser/profiles/profile.h" |
#include "components/bookmarks/core/browser/bookmark_title_match.h" |
#include "components/favicon_base/favicon_types.h" |
#include "content/public/browser/notification_details.h" |
#include "content/public/browser/notification_source.h" |
+#include "content/public/browser/user_metrics.h" |
#include "grit/generated_resources.h" |
#include "ui/base/l10n/l10n_util.h" |
#include "ui/gfx/favicon_size.h" |
@@ -70,8 +74,8 @@ class SortComparator : public std::binary_function<const BookmarkNode*, |
// BookmarkModel -------------------------------------------------------------- |
-BookmarkModel::BookmarkModel(Profile* profile) |
- : profile_(profile), |
+BookmarkModel::BookmarkModel(BookmarkClient* client) |
+ : client_(client), |
loaded_(false), |
root_(GURL()), |
bookmark_bar_node_(NULL), |
@@ -81,8 +85,8 @@ BookmarkModel::BookmarkModel(Profile* profile) |
observers_(ObserverList<BookmarkModelObserver>::NOTIFY_EXISTING_ONLY), |
loaded_signal_(true, false), |
extensive_changes_(0) { |
- if (!profile_) { |
- // Profile is null during testing. |
+ if (!client_) { |
+ // client is null during testing. |
DoneLoading(CreateLoadDetails()); |
} |
} |
@@ -108,7 +112,10 @@ void BookmarkModel::Shutdown() { |
} |
void BookmarkModel::Load( |
- const scoped_refptr<base::SequencedTaskRunner>& task_runner) { |
+ PrefService* pref_service, |
+ const base::FilePath& profile_path, |
+ const scoped_refptr<base::SequencedTaskRunner>& io_task_runner, |
+ const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner) { |
if (store_.get()) { |
// If the store is non-null, it means Load was already invoked. Load should |
// only be invoked once. |
@@ -117,16 +124,13 @@ void BookmarkModel::Load( |
} |
expanded_state_tracker_.reset( |
- new BookmarkExpandedStateTracker(this, profile_->GetPrefs())); |
+ new BookmarkExpandedStateTracker(this, pref_service)); |
- // Listen for changes to favicons so that we can update the favicon of the |
- // node appropriately. |
- registrar_.Add(this, chrome::NOTIFICATION_FAVICON_CHANGED, |
- content::Source<Profile>(profile_)); |
+ client_->OnLoad(); |
// Load the bookmarks. BookmarkStorage notifies us when done. |
- store_ = new BookmarkStorage(profile_, this, task_runner.get()); |
- store_->LoadBookmarks(CreateLoadDetails()); |
+ store_ = new BookmarkStorage(this, profile_path, io_task_runner.get()); |
+ store_->LoadBookmarks(CreateLoadDetails(), ui_task_runner); |
} |
const BookmarkNode* BookmarkModel::GetParentForNewNodes() { |
@@ -204,7 +208,7 @@ void BookmarkModel::RemoveAll() { |
if (store_.get()) |
store_->ScheduleSave(); |
- NotifyHistoryAboutRemovedBookmarks(removed_urls); |
+ client_->NotifyHistoryAboutRemovedBookmarks(removed_urls); |
FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
BookmarkAllNodesRemoved(this)); |
@@ -413,6 +417,23 @@ void BookmarkModel::SetNodeSyncTransactionVersion( |
store_->ScheduleSave(); |
} |
+void BookmarkModel::OnFaviconChanged(const std::set<GURL>& urls) { |
+ // Prevent the observers from getting confused for multiple favicon loads. |
+ for (std::set<GURL>::const_iterator i = urls.begin(); i != urls.end(); ++i) { |
+ std::vector<const BookmarkNode*> nodes; |
+ GetNodesByURL(*i, &nodes); |
+ for (size_t i = 0; i < nodes.size(); ++i) { |
+ // Got an updated favicon, for a URL, do a new request. |
+ BookmarkNode* node = AsMutable(nodes[i]); |
+ node->InvalidateFavicon(); |
+ CancelPendingFaviconLoadRequests(node); |
+ FOR_EACH_OBSERVER(BookmarkModelObserver, |
+ observers_, |
+ BookmarkNodeFaviconChanged(this, node)); |
+ } |
+ } |
+} |
+ |
void BookmarkModel::SetDateAdded(const BookmarkNode* node, |
base::Time date_added) { |
if (!node) { |
@@ -625,7 +646,7 @@ void BookmarkModel::GetBookmarksWithTitlesMatching( |
} |
void BookmarkModel::ClearStore() { |
- registrar_.RemoveAll(); |
+ client_->OnClearStore(); |
store_ = NULL; |
} |
@@ -741,7 +762,7 @@ void BookmarkModel::RemoveAndDeleteNode(BookmarkNode* delete_me) { |
if (store_.get()) |
store_->ScheduleSave(); |
- NotifyHistoryAboutRemovedBookmarks(removed_urls); |
+ client_->NotifyHistoryAboutRemovedBookmarks(removed_urls); |
FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
BookmarkNodeRemoved(this, parent, index, node.get())); |
@@ -785,22 +806,6 @@ void BookmarkModel::RemoveNodeAndGetRemovedUrls(BookmarkNode* node, |
} |
} |
-void BookmarkModel::NotifyHistoryAboutRemovedBookmarks( |
- const std::set<GURL>& removed_bookmark_urls) const { |
- if (removed_bookmark_urls.empty()) { |
- // No point in sending out notification if the starred state didn't change. |
- return; |
- } |
- |
- if (profile_) { |
- HistoryService* history = |
- HistoryServiceFactory::GetForProfile(profile_, |
- Profile::EXPLICIT_ACCESS); |
- if (history) |
- history->URLsNoLongerBookmarked(removed_bookmark_urls); |
- } |
-} |
- |
BookmarkNode* BookmarkModel::AddNode(BookmarkNode* parent, |
int index, |
BookmarkNode* node) { |
@@ -887,19 +892,15 @@ void BookmarkModel::LoadFavicon(BookmarkNode* node) { |
return; |
DCHECK(node->url().is_valid()); |
- FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( |
- profile_, Profile::EXPLICIT_ACCESS); |
- if (!favicon_service) |
- return; |
- base::CancelableTaskTracker::TaskId taskId = |
- favicon_service->GetFaviconImageForURL( |
- FaviconService::FaviconForURLParams( |
- node->url(), favicon_base::FAVICON, gfx::kFaviconSize), |
- base::Bind(&BookmarkModel::OnFaviconDataAvailable, |
- base::Unretained(this), |
- node), |
- &cancelable_task_tracker_); |
- node->set_favicon_load_task_id(taskId); |
+ base::CancelableTaskTracker::TaskId taskId = client_->GetFaviconImageForURL( |
+ node->url(), |
+ favicon_base::FAVICON, |
+ gfx::kFaviconSize, |
+ base::Bind( |
+ &BookmarkModel::OnFaviconDataAvailable, base::Unretained(this), node), |
+ &cancelable_task_tracker_); |
+ if (taskId != base::CancelableTaskTracker::kBadTaskId) |
+ node->set_favicon_load_task_id(taskId); |
} |
void BookmarkModel::FaviconLoaded(const BookmarkNode* node) { |
@@ -914,35 +915,6 @@ void BookmarkModel::CancelPendingFaviconLoadRequests(BookmarkNode* node) { |
} |
} |
-void BookmarkModel::Observe(int type, |
- const content::NotificationSource& source, |
- const content::NotificationDetails& details) { |
- switch (type) { |
- case chrome::NOTIFICATION_FAVICON_CHANGED: { |
- // Prevent the observers from getting confused for multiple favicon loads. |
- content::Details<FaviconChangedDetails> favicon_details(details); |
- for (std::set<GURL>::const_iterator i = favicon_details->urls.begin(); |
- i != favicon_details->urls.end(); ++i) { |
- std::vector<const BookmarkNode*> nodes; |
- GetNodesByURL(*i, &nodes); |
- for (size_t i = 0; i < nodes.size(); ++i) { |
- // Got an updated favicon, for a URL, do a new request. |
- BookmarkNode* node = AsMutable(nodes[i]); |
- node->InvalidateFavicon(); |
- CancelPendingFaviconLoadRequests(node); |
- FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
- BookmarkNodeFaviconChanged(this, node)); |
- } |
- } |
- break; |
- } |
- |
- default: |
- NOTREACHED(); |
- break; |
- } |
-} |
- |
void BookmarkModel::PopulateNodesByURL(BookmarkNode* node) { |
// NOTE: this is called with url_lock_ already held. As such, this doesn't |
// explicitly grab the lock. |
@@ -963,7 +935,109 @@ BookmarkLoadDetails* BookmarkModel::CreateLoadDetails() { |
CreatePermanentNode(BookmarkNode::OTHER_NODE); |
BookmarkPermanentNode* mobile_node = |
CreatePermanentNode(BookmarkNode::MOBILE); |
- return new BookmarkLoadDetails(bb_node, other_node, mobile_node, |
- new BookmarkIndex(profile_), |
+ return new BookmarkLoadDetails(bb_node, |
+ other_node, |
+ mobile_node, |
+ new BookmarkIndex(client_), |
next_node_id_); |
} |
+ |
+ChromeBookmarkClient::ChromeBookmarkClient(Profile* profile) |
+ : profile_(profile), model_(new BookmarkModel(this)) { |
+} |
+ |
+ChromeBookmarkClient::~ChromeBookmarkClient() { |
+} |
+ |
+void ChromeBookmarkClient::Shutdown() { |
+ model_->Shutdown(); |
+} |
+ |
+void ChromeBookmarkClient::Observe( |
+ int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ switch (type) { |
+ case chrome::NOTIFICATION_FAVICON_CHANGED: { |
+ content::Details<FaviconChangedDetails> favicon_details(details); |
+ model_->OnFaviconChanged(favicon_details->urls); |
+ break; |
+ } |
+ |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+} |
+ |
+void ChromeBookmarkClient::OnLoad() { |
+ // Listen for changes to favicons so that we can update the favicon of the |
+ // node appropriately. |
+ registrar_.Add(this, |
+ chrome::NOTIFICATION_FAVICON_CHANGED, |
+ content::Source<Profile>(profile_)); |
+} |
+ |
+void ChromeBookmarkClient::OnClearStore() { |
+ registrar_.RemoveAll(); |
+} |
+ |
+void ChromeBookmarkClient::NotifyHistoryAboutRemovedBookmarks( |
+ const std::set<GURL>& removed_bookmark_urls) const { |
+ if (removed_bookmark_urls.empty()) { |
+ // No point in sending out notification if the starred state didn't change. |
+ return; |
+ } |
+ |
+ HistoryService* history_service = |
+ HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); |
+ if (history_service) |
+ history_service->URLsNoLongerBookmarked(removed_bookmark_urls); |
+} |
+ |
+base::CancelableTaskTracker::TaskId ChromeBookmarkClient::GetFaviconImageForURL( |
+ const GURL& page_url, |
+ int icon_types, |
+ int desired_size_in_dip, |
+ const FaviconImageCallback& callback, |
+ base::CancelableTaskTracker* tracker) { |
+ FaviconService* favicon_service = |
+ FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); |
+ if (!favicon_service) |
+ return base::CancelableTaskTracker::kBadTaskId; |
+ return favicon_service->GetFaviconImageForURL( |
+ FaviconService::FaviconForURLParams( |
+ page_url, icon_types, desired_size_in_dip), |
+ callback, |
+ tracker); |
+} |
+ |
+bool ChromeBookmarkClient::SupportsTypedCountForNodes() { |
+ return true; |
+} |
+ |
+void ChromeBookmarkClient::GetTypedCountForNodes( |
+ const NodeSet& nodes, |
+ NodeTypedCountPairs* node_typed_count_pairs) { |
+ HistoryService* history_service = |
+ HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); |
+ history::URLDatabase* url_db = |
+ history_service ? history_service->InMemoryDatabase() : NULL; |
+ for (NodeSet::const_iterator i = nodes.begin(); i != nodes.end(); ++i) { |
+ int typed_count = 0; |
+ |
+ // If |url_db| is the InMemoryDatabase, it might not cache all URLRows, but |
+ // it guarantees to contain those with |typed_count| > 0. Thus, if we cannot |
+ // fetch the URLRow, it is safe to assume that its |typed_count| is 0. |
+ history::URLRow url; |
+ if (url_db && url_db->GetRowForURL((*i)->url(), &url)) |
+ typed_count = url.typed_count(); |
+ |
+ NodeTypedCountPair pair(*i, typed_count); |
+ node_typed_count_pairs->push_back(pair); |
+ } |
+} |
+ |
+void ChromeBookmarkClient::RecordAction(const base::UserMetricsAction& action) { |
+ content::RecordAction(action); |
+} |