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

Side by Side Diff: components/ntp_snippets/offline_pages/offline_page_suggestions_provider.cc

Issue 2236303002: Make OfflinePage ContentSuggestions dismissable (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: base::Value --> std::unique_ptr<base::Value> Created 4 years, 4 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/ntp_snippets/offline_pages/offline_page_suggestions_provide r.h" 5 #include "components/ntp_snippets/offline_pages/offline_page_suggestions_provide r.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
11 #include "base/threading/thread_task_runner_handle.h" 11 #include "base/threading/thread_task_runner_handle.h"
12 #include "base/values.h"
13 #include "components/ntp_snippets/pref_names.h"
14 #include "components/prefs/pref_registry_simple.h"
15 #include "components/prefs/pref_service.h"
12 #include "ui/gfx/image/image.h" 16 #include "ui/gfx/image/image.h"
13 17
14 using offline_pages::MultipleOfflinePageItemResult; 18 using offline_pages::MultipleOfflinePageItemResult;
15 using offline_pages::OfflinePageModel; 19 using offline_pages::OfflinePageModel;
16 using offline_pages::OfflinePageItem; 20 using offline_pages::OfflinePageItem;
17 21
18 namespace ntp_snippets { 22 namespace ntp_snippets {
19 23
20 namespace { 24 namespace {
21 25
22 const int kMaxSuggestionsCount = 5; 26 const int kMaxSuggestionsCount = 5;
23 27
24 } // namespace 28 } // namespace
25 29
26 OfflinePageSuggestionsProvider::OfflinePageSuggestionsProvider( 30 OfflinePageSuggestionsProvider::OfflinePageSuggestionsProvider(
27 ContentSuggestionsProvider::Observer* observer, 31 ContentSuggestionsProvider::Observer* observer,
28 CategoryFactory* category_factory, 32 CategoryFactory* category_factory,
29 OfflinePageModel* offline_page_model) 33 OfflinePageModel* offline_page_model,
34 PrefService* pref_service)
30 : ContentSuggestionsProvider(observer, category_factory), 35 : ContentSuggestionsProvider(observer, category_factory),
31 category_status_(CategoryStatus::AVAILABLE_LOADING), 36 category_status_(CategoryStatus::AVAILABLE_LOADING),
32 offline_page_model_(offline_page_model), 37 offline_page_model_(offline_page_model),
33 provided_category_( 38 provided_category_(
34 category_factory->FromKnownCategory(KnownCategories::OFFLINE_PAGES)) { 39 category_factory->FromKnownCategory(KnownCategories::OFFLINE_PAGES)),
40 pref_service_(pref_service) {
35 offline_page_model_->AddObserver(this); 41 offline_page_model_->AddObserver(this);
42 ReadDismissedIDsFromPrefs();
36 FetchOfflinePages(); 43 FetchOfflinePages();
37 } 44 }
38 45
39 OfflinePageSuggestionsProvider::~OfflinePageSuggestionsProvider() { 46 OfflinePageSuggestionsProvider::~OfflinePageSuggestionsProvider() {
40 offline_page_model_->RemoveObserver(this); 47 offline_page_model_->RemoveObserver(this);
41 } 48 }
42 49
50 // static
51 void OfflinePageSuggestionsProvider::RegisterProfilePrefs(
52 PrefRegistrySimple* registry) {
53 registry->RegisterListPref(prefs::kDismissedOfflinePageSuggestions);
54 }
55
43 //////////////////////////////////////////////////////////////////////////////// 56 ////////////////////////////////////////////////////////////////////////////////
44 // Private methods 57 // Private methods
45 58
46 std::vector<Category> OfflinePageSuggestionsProvider::GetProvidedCategories() { 59 std::vector<Category> OfflinePageSuggestionsProvider::GetProvidedCategories() {
47 return std::vector<Category>({provided_category_}); 60 return std::vector<Category>({provided_category_});
48 } 61 }
49 62
50 CategoryStatus OfflinePageSuggestionsProvider::GetCategoryStatus( 63 CategoryStatus OfflinePageSuggestionsProvider::GetCategoryStatus(
51 Category category) { 64 Category category) {
52 DCHECK_EQ(category, provided_category_); 65 DCHECK_EQ(category, provided_category_);
53 return category_status_; 66 return category_status_;
54 } 67 }
55 68
56 CategoryInfo OfflinePageSuggestionsProvider::GetCategoryInfo( 69 CategoryInfo OfflinePageSuggestionsProvider::GetCategoryInfo(
57 Category category) { 70 Category category) {
58 // TODO(pke): Use the proper string once it's agreed on. 71 // TODO(pke): Use the proper string once it's agreed on.
59 return CategoryInfo(base::ASCIIToUTF16("Offline pages"), 72 return CategoryInfo(base::ASCIIToUTF16("Offline pages"),
60 ContentSuggestionsCardLayout::MINIMAL_CARD); 73 ContentSuggestionsCardLayout::MINIMAL_CARD);
61 } 74 }
62 75
63 void OfflinePageSuggestionsProvider::DismissSuggestion( 76 void OfflinePageSuggestionsProvider::DismissSuggestion(
64 const std::string& suggestion_id) { 77 const std::string& suggestion_id) {
65 // TODO(pke): Implement some "dont show on NTP anymore" behaviour, 78 std::string offline_page_id = GetWithinCategoryIDFromUniqueID(suggestion_id);
66 // then also implement ClearDismissedSuggestionsForDebugging. 79 dismissed_ids_.insert(offline_page_id);
80 StoreDismissedIDsToPrefs();
67 } 81 }
68 82
69 void OfflinePageSuggestionsProvider::FetchSuggestionImage( 83 void OfflinePageSuggestionsProvider::FetchSuggestionImage(
70 const std::string& suggestion_id, 84 const std::string& suggestion_id,
71 const ImageFetchedCallback& callback) { 85 const ImageFetchedCallback& callback) {
72 // TODO(pke): Fetch proper thumbnail from OfflinePageModel once it's available 86 // TODO(pke): Fetch proper thumbnail from OfflinePageModel once it's available
73 // there. 87 // there.
74 base::ThreadTaskRunnerHandle::Get()->PostTask( 88 base::ThreadTaskRunnerHandle::Get()->PostTask(
75 FROM_HERE, base::Bind(callback, suggestion_id, gfx::Image())); 89 FROM_HERE, base::Bind(callback, suggestion_id, gfx::Image()));
76 } 90 }
77 91
78 void OfflinePageSuggestionsProvider::ClearCachedSuggestionsForDebugging( 92 void OfflinePageSuggestionsProvider::ClearCachedSuggestionsForDebugging(
79 Category category) { 93 Category category) {
80 DCHECK_EQ(category, provided_category_); 94 DCHECK_EQ(category, provided_category_);
81 // Ignored. 95 // Ignored.
82 } 96 }
83 97
84 std::vector<ContentSuggestion> 98 std::vector<ContentSuggestion>
85 OfflinePageSuggestionsProvider::GetDismissedSuggestionsForDebugging( 99 OfflinePageSuggestionsProvider::GetDismissedSuggestionsForDebugging(
86 Category category) { 100 Category category) {
101 // TODO(pke): Make GetDismissedSuggestionsForDebugging asynchronous so this
102 // can return proper values.
87 DCHECK_EQ(category, provided_category_); 103 DCHECK_EQ(category, provided_category_);
88 // TODO(pke): Implement when dismissed suggestions are supported. 104 std::vector<ContentSuggestion> suggestions;
89 return std::vector<ContentSuggestion>(); 105 for (const std::string& dismissed_id : dismissed_ids_) {
106 ContentSuggestion suggestion(
107 MakeUniqueID(provided_category_, dismissed_id),
108 GURL("http://dismissed-offline-page-" + dismissed_id));
109 suggestion.set_title(base::UTF8ToUTF16("Title not available"));
110 suggestions.push_back(std::move(suggestion));
111 }
112 return suggestions;
90 } 113 }
91 114
92 void OfflinePageSuggestionsProvider::ClearDismissedSuggestionsForDebugging( 115 void OfflinePageSuggestionsProvider::ClearDismissedSuggestionsForDebugging(
93 Category category) { 116 Category category) {
94 DCHECK_EQ(category, provided_category_); 117 DCHECK_EQ(category, provided_category_);
95 // TODO(pke): Implement when dismissed suggestions are supported. 118 dismissed_ids_.clear();
119 StoreDismissedIDsToPrefs();
120 FetchOfflinePages();
96 } 121 }
97 122
98 void OfflinePageSuggestionsProvider::OfflinePageModelLoaded( 123 void OfflinePageSuggestionsProvider::OfflinePageModelLoaded(
99 OfflinePageModel* model) { 124 OfflinePageModel* model) {
100 DCHECK_EQ(offline_page_model_, model); 125 DCHECK_EQ(offline_page_model_, model);
101 } 126 }
102 127
103 void OfflinePageSuggestionsProvider::OfflinePageModelChanged( 128 void OfflinePageSuggestionsProvider::OfflinePageModelChanged(
104 OfflinePageModel* model) { 129 OfflinePageModel* model) {
105 DCHECK_EQ(offline_page_model_, model); 130 DCHECK_EQ(offline_page_model_, model);
(...skipping 11 matching lines...) Expand all
117 base::Bind(&OfflinePageSuggestionsProvider::OnOfflinePagesLoaded, 142 base::Bind(&OfflinePageSuggestionsProvider::OnOfflinePagesLoaded,
118 base::Unretained(this))); 143 base::Unretained(this)));
119 } 144 }
120 145
121 void OfflinePageSuggestionsProvider::OnOfflinePagesLoaded( 146 void OfflinePageSuggestionsProvider::OnOfflinePagesLoaded(
122 const MultipleOfflinePageItemResult& result) { 147 const MultipleOfflinePageItemResult& result) {
123 NotifyStatusChanged(CategoryStatus::AVAILABLE); 148 NotifyStatusChanged(CategoryStatus::AVAILABLE);
124 149
125 std::vector<ContentSuggestion> suggestions; 150 std::vector<ContentSuggestion> suggestions;
126 for (const OfflinePageItem& item : result) { 151 for (const OfflinePageItem& item : result) {
127 // TODO(pke): Make sure the URL is actually opened as an offline URL. 152 if (dismissed_ids_.count(base::IntToString(item.offline_id)))
128 // Currently, the browser opens the offline URL and then immediately 153 continue;
129 // redirects to the online URL if the device is online. 154 suggestions.push_back(ConvertOfflinePage(item));
130 ContentSuggestion suggestion(
131 MakeUniqueID(provided_category_, base::IntToString(item.offline_id)),
132 item.GetOfflineURL());
133
134 // TODO(pke): Sort my most recently visited and only keep the top one of
135 // multiple entries for the same URL.
136 // TODO(pke): Get more reasonable data from the OfflinePageModel here.
137 suggestion.set_title(base::UTF8ToUTF16(item.url.spec()));
138 suggestion.set_snippet_text(base::string16());
139 suggestion.set_publish_date(item.creation_time);
140 suggestion.set_publisher_name(base::UTF8ToUTF16(item.url.host()));
141 suggestions.emplace_back(std::move(suggestion));
142 if (suggestions.size() == kMaxSuggestionsCount) 155 if (suggestions.size() == kMaxSuggestionsCount)
143 break; 156 break;
144 } 157 }
145 158
146 observer()->OnNewSuggestions(this, provided_category_, 159 observer()->OnNewSuggestions(this, provided_category_,
147 std::move(suggestions)); 160 std::move(suggestions));
148 } 161 }
149 162
150 void OfflinePageSuggestionsProvider::NotifyStatusChanged( 163 void OfflinePageSuggestionsProvider::NotifyStatusChanged(
151 CategoryStatus new_status) { 164 CategoryStatus new_status) {
152 if (category_status_ == new_status) 165 if (category_status_ == new_status)
153 return; 166 return;
154 category_status_ = new_status; 167 category_status_ = new_status;
155 168
156 observer()->OnCategoryStatusChanged(this, provided_category_, new_status); 169 observer()->OnCategoryStatusChanged(this, provided_category_, new_status);
157 } 170 }
158 171
172 ContentSuggestion OfflinePageSuggestionsProvider::ConvertOfflinePage(
173 const OfflinePageItem& offline_page) const {
174 // TODO(pke): Make sure the URL is actually opened as an offline URL.
175 // Currently, the browser opens the offline URL and then immediately
176 // redirects to the online URL if the device is online.
177 ContentSuggestion suggestion(
178 MakeUniqueID(provided_category_,
179 base::IntToString(offline_page.offline_id)),
180 offline_page.GetOfflineURL());
181
182 // TODO(pke): Sort by most recently visited and only keep the top one of
183 // multiple entries for the same URL.
184 // TODO(pke): Get more reasonable data from the OfflinePageModel here.
185 suggestion.set_title(base::UTF8ToUTF16(offline_page.url.spec()));
186 suggestion.set_snippet_text(base::string16());
187 suggestion.set_publish_date(offline_page.creation_time);
188 suggestion.set_publisher_name(base::UTF8ToUTF16(offline_page.url.host()));
189 return suggestion;
190 }
191
192 void OfflinePageSuggestionsProvider::ReadDismissedIDsFromPrefs() {
193 dismissed_ids_.clear();
194 const base::ListValue* list =
195 pref_service_->GetList(prefs::kDismissedOfflinePageSuggestions);
196 for (const std::unique_ptr<base::Value>& value : *list) {
197 std::string dismissed_id;
198 bool success = value->GetAsString(&dismissed_id);
199 DCHECK(success) << "Failed to parse dismissed offline page ID from prefs";
200 dismissed_ids_.insert(std::move(dismissed_id));
201 }
202 }
203
204 void OfflinePageSuggestionsProvider::StoreDismissedIDsToPrefs() {
205 base::ListValue list;
206 for (const std::string& dismissed_id : dismissed_ids_)
207 list.AppendString(dismissed_id);
208 pref_service_->Set(prefs::kDismissedOfflinePageSuggestions, list);
209 }
210
159 } // namespace ntp_snippets 211 } // namespace ntp_snippets
OLDNEW
« no previous file with comments | « components/ntp_snippets/offline_pages/offline_page_suggestions_provider.h ('k') | components/ntp_snippets/pref_names.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698