Chromium Code Reviews| Index: components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc |
| diff --git a/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc b/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..deefb530f2e9fd720fd12f76dd90657dcaab2e29 |
| --- /dev/null |
| +++ b/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc |
| @@ -0,0 +1,166 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "components/ntp_snippets/bookmarks/bookmark_suggestions_provider.h" |
| + |
| +#include <utility> |
| +#include <vector> |
| + |
| +#include "base/strings/utf_string_conversions.h" |
| +#include "components/bookmarks/browser/bookmark_model.h" |
| +#include "components/ntp_snippets/bookmarks/bookmark_last_visit_date_helper.h" |
| +#include "components/ntp_snippets/content_suggestion.h" |
| + |
| +namespace { |
| +const int kMaxBookmarks = 10; |
| +const int kMaxBookmarkAgeInDays = 42; |
| + |
| +base::Time GetThresholdTime() { |
| + return base::Time::Now() - base::TimeDelta::FromDays(kMaxBookmarkAgeInDays); |
| +} |
| + |
| +} // namespace |
| + |
| +namespace ntp_snippets { |
| + |
| +BookmarkSuggestionsProvider::BookmarkSuggestionsProvider( |
| + bookmarks::BookmarkModel* bookmark_model) |
| + : ContentSuggestionsProvider({ContentSuggestionsCategory::BOOKMARKS}), |
| + category_status_(ContentSuggestionsCategoryStatus::AVAILABLE_LOADING), |
| + observer_(nullptr), |
| + bookmark_model_(bookmark_model), |
| + fetch_requested_(false), |
| + end_of_list_last_visit_date_(GetThresholdTime()) { |
| + bookmark_model_->AddObserver(this); |
| +} |
| + |
| +BookmarkSuggestionsProvider::~BookmarkSuggestionsProvider() {} |
| + |
| +// Inherited from KeyedService. |
| +void BookmarkSuggestionsProvider::Shutdown() { |
| + bookmark_model_->RemoveObserver(this); |
| + category_status_ = ContentSuggestionsCategoryStatus::NOT_PROVIDED; |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// Private methods |
| + |
| +void BookmarkSuggestionsProvider::SetObserver( |
| + ContentSuggestionsProvider::Observer* observer) { |
| + observer_ = observer; |
| + if (observer) |
| + FetchBookmarks(); |
| +} |
| + |
| +ContentSuggestionsCategoryStatus BookmarkSuggestionsProvider::GetCategoryStatus( |
| + ContentSuggestionsCategory category) { |
| + return category_status_; |
| +} |
| + |
| +void BookmarkSuggestionsProvider::DismissSuggestion( |
| + const std::string& suggestion_id) { |
| + // TODO(jkrcal): Implement blacklisting bookmarks until they are next visited. |
| + // Then also implement ClearDismissedSuggestionsForDebugging. |
| +} |
| + |
| +void BookmarkSuggestionsProvider::FetchSuggestionImage( |
| + const std::string& suggestion_id, |
| + const ImageFetchedCallback& callback) { |
| + // TODO(jkrcal): Make sure no image is displayed in the UI. |
|
Marc Treib
2016/07/29 10:08:34
Might be nice to call the callback with a "null" i
jkrcal
2016/07/29 13:57:17
Done.
|
| +} |
| + |
| +void BookmarkSuggestionsProvider::ClearCachedSuggestionsForDebugging() { |
| + // Ignored. |
| +} |
| + |
| +void BookmarkSuggestionsProvider::ClearDismissedSuggestionsForDebugging() { |
| + // TODO(jkrcal): Implement when discarded suggestions are supported. |
| +} |
| + |
| +void BookmarkSuggestionsProvider::BookmarkModelLoaded( |
| + bookmarks::BookmarkModel* model, |
| + bool ids_reassigned) { |
| + DCHECK_EQ(bookmark_model_, model); |
| + if (fetch_requested_) { |
| + fetch_requested_ = false; |
| + FetchBookmarksWhenLoaded(); |
| + } |
| +} |
| + |
| +void BookmarkSuggestionsProvider::OnWillChangeBookmarkMetaInfo( |
| + BookmarkModel* model, |
| + const BookmarkNode* node) { |
| + // Store the last visit date of the node that is about to change. |
| + node_to_change_last_visit_date_ = |
| + BookmarkLastVisitDateHelper::GetLastVisitDate(node); |
| +} |
| + |
| +void BookmarkSuggestionsProvider::BookmarkMetaInfoChanged( |
| + BookmarkModel* model, |
| + const BookmarkNode* node) { |
| + base::Time time = BookmarkLastVisitDateHelper::GetLastVisitDate(node); |
| + if (time == node_to_change_last_visit_date_ || |
| + time < end_of_list_last_visit_date_) |
| + return; |
| + |
| + // Last visit date of a node has changed (and is relevant for the list), we |
| + // should update the suggestions. |
| + FetchBookmarks(); |
| +} |
| + |
| +void BookmarkSuggestionsProvider::FetchBookmarksWhenLoaded() { |
| + NotifyStatusChanged(ContentSuggestionsCategoryStatus::AVAILABLE); |
| + if (!observer_) |
| + return; |
| + |
| + std::vector<const BookmarkNode*> bookmarks; |
| + BookmarkLastVisitDateHelper::GetRecentlyVisitedBookmarks( |
| + bookmark_model_, &bookmarks, kMaxBookmarks, |
| + GetThresholdTime()); |
| + |
| + std::vector<ContentSuggestion> suggestions; |
| + for (const BookmarkNode* bookmark : bookmarks) { |
| + ContentSuggestion suggestion( |
| + MakeUniqueID(ContentSuggestionsCategory::BOOKMARKS, |
| + bookmark->url().spec()), |
| + bookmark->url()); |
| + |
| + // TODO(jkrcal): keep it in UTF16 when ContentSuggestion title adapts to it. |
| + suggestion.set_title(base::UTF16ToUTF8(bookmark->GetTitle())); |
| + suggestion.set_snippet_text(std::string()); |
| + suggestion.set_publish_date( |
| + BookmarkLastVisitDateHelper::GetLastVisitDate(bookmark)); |
| + suggestion.set_publisher_name(bookmark->url().host()); |
| + suggestions.emplace_back(std::move(suggestion)); |
| + } |
| + |
| + if (suggestions.empty()) |
| + end_of_list_last_visit_date_ = GetThresholdTime(); |
| + else |
| + end_of_list_last_visit_date_ = suggestions.back().publish_date(); |
| + |
| + observer_->OnNewSuggestions(ContentSuggestionsCategory::BOOKMARKS, |
| + std::move(suggestions)); |
| +} |
| + |
| +void BookmarkSuggestionsProvider::FetchBookmarks() { |
| + if (bookmark_model_->loaded()) |
| + FetchBookmarksWhenLoaded(); |
| + else |
| + fetch_requested_ = true; |
| +} |
| + |
| +void BookmarkSuggestionsProvider::NotifyStatusChanged( |
| + ContentSuggestionsCategoryStatus new_status) { |
| + if (category_status_ == new_status) |
| + return; |
| + category_status_ = new_status; |
| + |
| + if (!observer_) |
| + return; |
| + observer_->OnCategoryStatusChanged(ContentSuggestionsCategory::BOOKMARKS, |
| + new_status); |
| +} |
| + |
| +} // namespace ntp_snippets |