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

Side by Side Diff: components/enhanced_bookmarks/bookmark_server_cluster_service.cc

Issue 539173004: Bring up of the enhanced bookmarks cluster service. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@intermediary2
Patch Set: Rebase. Created 6 years, 3 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/enhanced_bookmarks/bookmark_server_cluster_service.h"
6
7 #include "base/json/json_reader.h"
8 #include "base/json/json_writer.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/values.h"
12 #include "components/bookmarks/browser/bookmark_model.h"
13 #include "components/enhanced_bookmarks/enhanced_bookmark_utils.h"
14 #include "components/enhanced_bookmarks/proto/cluster.pb.h"
15 #include "components/pref_registry/pref_registry_syncable.h"
16 #include "components/signin/core/browser/signin_manager.h"
17 #include "net/base/url_util.h"
18 #include "net/url_request/url_fetcher.h"
19 #include "net/url_request/url_request_context_getter.h"
20
21 namespace {
22 const std::string kClusterUrl(
23 "https://www.google.com/stars/cluster");
24 const char* kPrefServiceKey =
25 "pref_service_key_for_stored_bookmark_clusters";
battre 2014/09/12 16:49:02 Please use a different key. E.g. "stored_bookmark_
noyau (Ping after 24h) 2014/09/18 12:41:47 Done. And moved to pref_names.
26 const int kPrefServiceVersion = 1;
27 const char* kPrefServiceVersionKey = "version";
28 const char* kPrefServiceDataKey = "data";
29 const char* kAuthIdKey = "auth_id";
30 } // namespace
31
32 namespace enhanced_bookmarks {
33
34 BookmarkServerClusterService::BookmarkServerClusterService(
35 const std::string& application_language_code,
36 scoped_refptr<net::URLRequestContextGetter> request_context_getter,
37 ProfileOAuth2TokenService* token_service,
38 SigninManagerBase* signin_manager,
39 BookmarkModel* bookmark_model,
40 PrefService* pref_service)
41 : BookmarkServerService(request_context_getter,
42 token_service,
43 signin_manager,
44 bookmark_model),
45 application_language_code_(application_language_code),
46 pref_service_(pref_service) {
47 LoadModel();
48
49 if (bookmark_model_->loaded())
50 TriggerTokenRequest(false);
51
52 GetSigninManager()->AddObserver(this);
53 }
54
55 BookmarkServerClusterService::~BookmarkServerClusterService() {
56 GetSigninManager()->RemoveObserver(this);
57 }
58
59 const std::vector<const BookmarkNode*>
60 BookmarkServerClusterService::BookmarksForClusterNamed(
61 const std::string& cluster_name) const {
62 std::vector<const BookmarkNode*> results;
63
64 ClusterMap::const_iterator cluster_it = cluster_data_.find(cluster_name);
65 if (cluster_it == cluster_data_.end())
66 return results;
67
68 for (std::vector<std::string>::const_iterator it = cluster_it->second.begin();
69 it != cluster_it->second.end();
70 ++it) {
71 std::string stars_id = *it;
72 const BookmarkNode* bookmark = BookmarkForRemoteId(stars_id);
73 if (bookmark)
74 results.push_back(bookmark);
75 }
76 return results;
77 }
78
79 const std::vector<std::string>
80 BookmarkServerClusterService::ClustersForBookmark(
81 const BookmarkNode* bookmark) const {
82 std::string starid = RemoteIDForBookmark(bookmark);
83
84 // TODO(noyau): if this turns out to be a perf bottleneck this may be improved
85 // by storing a reverse map from id to cluster.
86 std::vector<std::string> clusters;
87 for (ClusterMap::const_iterator it = cluster_data_.begin();
88 it != cluster_data_.end();
89 ++it) {
90 const std::vector<std::string>& v = it->second;
91 if (std::find(v.begin(), v.end(), starid) != v.end())
92 clusters.push_back(it->first);
93 }
94 return clusters;
95 }
96
97 const std::vector<std::string> BookmarkServerClusterService::GetClusters()
98 const {
99 std::vector<std::string> cluster_names;
100
101 for (auto pair : cluster_data_)
Kibeom Kim (inactive) 2014/09/12 21:31:25 I'm not sure if this is changed, but people on chr
noyau (Ping after 24h) 2014/09/18 12:41:47 Yes you're right. Porting code from iOS I'm always
102 cluster_names.push_back(pair.first);
103
104 return cluster_names;
105 }
106
107 void BookmarkServerClusterService::RegisterPrefs(
108 user_prefs::PrefRegistrySyncable* registry) {
109 // Register a string, unsyncable preference.
110 registry->RegisterStringPref(
111 kPrefServiceKey,
battre 2014/09/12 16:49:01 Please follow the style of e.g. components/compone
noyau (Ping after 24h) 2014/09/18 12:41:48 Done.
112 std::string(),
113 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
114 }
115
116 net::URLFetcher* BookmarkServerClusterService::CreateFetcher() {
117 // Add the necessary arguments to the URI.
118 GURL url(kClusterUrl);
119 url = net::AppendQueryParameter(url, "output", "proto");
120
121 // Append language.
122 if (!application_language_code_.empty())
123 url = net::AppendQueryParameter(url, "hl", application_language_code_);
Mark 2014/09/18 18:08:51 You are also going to need to specify the version
noyau (Ping after 24h) 2014/10/01 16:04:42 Done. Added the version for the search service as
124
125 // Build the URLFetcher to perform the request.
126 net::URLFetcher* url_fetcher =
127 net::URLFetcher::Create(url, net::URLFetcher::POST, this);
128
129 // Binary encode a basic request proto.
130 image_collections::ClusterRequest request_proto;
131 request_proto.mutable_options()->set_min_cluster_size(1);
132 request_proto.set_cluster_all(true);
133
134 std::string proto_output;
135 bool result = request_proto.SerializePartialToString(&proto_output);
136 DCHECK(result);
137
138 url_fetcher->SetUploadData("application/octet-stream", proto_output);
139 return url_fetcher;
140 }
141
142 bool BookmarkServerClusterService::ProcessResponse(const std::string& response,
143 bool* should_notify) {
144 DCHECK(*should_notify);
145 image_collections::ClusterResponse response_proto;
146 bool result = response_proto.ParseFromString(response);
147 if (!result)
148 return false; // Not formatted properly.
149
150 std::map<std::string, std::vector<std::string> > new_cluster_data;
151 for (auto cluster : response_proto.clusters()) {
152 const std::string& title = cluster.title();
153 if (!title.length())
Kibeom Kim (inactive) 2014/09/12 21:31:24 .empty()? (also #157 and #160)
noyau (Ping after 24h) 2014/09/18 12:41:47 Done.
154 continue;
155 std::vector<std::string> starids;
156 for (std::string doc : cluster.docs()) {
157 if (doc.length())
158 starids.push_back(doc);
159 }
160 if (starids.size())
161 new_cluster_data[title] = starids;
162 }
163
164 if (new_cluster_data.size() == cluster_data_.size() &&
165 std::equal(new_cluster_data.begin(),
166 new_cluster_data.end(),
167 cluster_data_.begin())) {
Kibeom Kim (inactive) 2014/09/12 21:31:24 can we use std:map's operator == here? (I think th
noyau (Ping after 24h) 2014/09/18 12:41:47 Excellent question. According to the spec std::map
Kibeom Kim (inactive) 2014/09/29 21:15:55 I agree that we don't need to change already worki
noyau (Ping after 24h) 2014/10/01 16:04:42 Acknowledged.
168 *should_notify = false;
169 } else {
170 UpdateModel(&new_cluster_data);
171 }
172 return true;
173 }
174
175 void BookmarkServerClusterService::CleanAfterFailure() {
176 if (cluster_data_.empty())
177 return;
178
179 ClusterMap empty;
180 UpdateModel(&empty);
181 }
182
183 void BookmarkServerClusterService::BookmarkModelLoaded(BookmarkModel* model,
184 bool ids_reassigned) {
185 BookmarkServerService::BookmarkModelLoaded(model, ids_reassigned);
186 TriggerTokenRequest(false);
187 }
188
189 void BookmarkServerClusterService::BookmarkNodeAdded(BookmarkModel* model,
Kibeom Kim (inactive) 2014/09/12 21:31:25 Q: do we need BookmarkNodeAdded and BookmarkMetaIn
noyau (Ping after 24h) 2014/09/18 12:41:47 Done.
190 const BookmarkNode* parent,
191 int index) {
192 BookmarkServerService::BookmarkNodeAdded(model, parent, index);
193 }
194
195 void BookmarkServerClusterService::BookmarkMetaInfoChanged(
196 BookmarkModel* model,
197 const BookmarkNode* node) {
198 BookmarkServerService::BookmarkMetaInfoChanged(model, node);
199 }
200
201 void BookmarkServerClusterService::BookmarkAllUserNodesRemoved(
202 BookmarkModel* model,
203 const std::set<GURL>& removed_urls) {
204 if (!cluster_data_.empty()) {
205 ClusterMap empty;
206 UpdateModel(&empty);
207 }
208 BookmarkServerService::BookmarkAllUserNodesRemoved(model, removed_urls);
209 }
210
211 void BookmarkServerClusterService::GoogleSignedOut(
212 const std::string& account_id,
213 const std::string& username) {
214 if (!cluster_data_.empty()) {
215 ClusterMap empty;
216 UpdateModel(&empty);
217 }
218 }
219
220 void BookmarkServerClusterService::UpdateModel(ClusterMap* cluster_map) {
221 cluster_data_.swap(*cluster_map);
222 std::string serialized;
223 std::string auth_id = GetSigninManager()->GetAuthenticatedAccountId();
224 bool result = BookmarkServerClusterService::Serialize(
225 cluster_data_, &serialized, auth_id);
226 if (result)
227 pref_service_->SetString(kPrefServiceKey, serialized);
Kibeom Kim (inactive) 2014/09/12 21:31:25 Q: looks like this line won't be called on ::Googl
noyau (Ping after 24h) 2014/09/18 12:41:48 The key will be there, with the proper version num
228 }
229
230 void BookmarkServerClusterService::LoadModel() {
231 std::string serialized(pref_service_->GetString(kPrefServiceKey));
232 std::string auth_id = GetSigninManager()->GetAuthenticatedAccountId();
233
234 ClusterMap loaded_data;
235 bool result = BookmarkServerClusterService::Deserialize(
236 serialized, &loaded_data, auth_id);
237 if (result)
238 cluster_data_.swap(loaded_data);
239 }
240
241 //
242 // Serialization.
243 //
244 bool BookmarkServerClusterService::Serialize(const ClusterMap& cluster_map,
245 std::string* out_result,
246 const std::string& auth_id) {
247 // Create a list of all clusters. For each cluster, make another list. The
248 // first element in the list is the key (cluster name). All subsequent
249 // elements are stars ids.
250 // This non reference counted pointer is going to be consumed by |data|.
251 base::ListValue* all_clusters = new base::ListValue;
252 for (auto it : cluster_map) {
253 // This non reference counted pointer is going to be consumed by
254 // |all_clusters|.
255 base::ListValue* cluster = new base::ListValue;
256 cluster->AppendString(it.first);
257 cluster->AppendStrings(it.second);
258 all_clusters->Append(cluster);
259 }
260
261 // The dictionary that will be serialized has two fields: a version field and
262 // a data field.
263 base::DictionaryValue data;
264 data.SetInteger(kPrefServiceVersionKey, kPrefServiceVersion);
265 data.Set(kPrefServiceDataKey, all_clusters);
266 data.SetString(kAuthIdKey, auth_id);
267
268 std::string output;
269 bool result = base::JSONWriter::Write(&data, &output);
270 DCHECK(result);
271 out_result->swap(output);
272 return true;
273 }
274
275 bool BookmarkServerClusterService::Deserialize(const std::string& input,
276 ClusterMap* out_map,
277 const std::string& auth_id) {
278 if (input.empty())
279 return false;
280
281 base::JSONReader reader;
282 scoped_ptr<base::Value> value(reader.ReadToValue(input));
283 if (value == NULL)
284 return false;
285 if (!value->IsType(base::Value::TYPE_DICTIONARY))
286 return false;
287
288 base::DictionaryValue* dictionary_value;
289 bool result = value->GetAsDictionary(&dictionary_value);
290 if (!result)
291 return false;
292
293 // Check version.
294 int version;
295 result = dictionary_value->GetInteger(kPrefServiceVersionKey, &version);
296 if (!result)
297 return false;
298 if (version != kPrefServiceVersion)
299 return false;
300
301 // Check auth id.
302 std::string id;
303 result = dictionary_value->GetString(kAuthIdKey, &id);
304 if (!result)
305 return false;
306 if (id != auth_id)
307 return false;
308
309 base::ListValue* all_clusters;
310 result = dictionary_value->GetList(kPrefServiceDataKey, &all_clusters);
311 if (!result)
312 return false;
313
314 ClusterMap output;
315 for (size_t index = 0; index < all_clusters->GetSize(); ++index) {
316 base::ListValue* cluster;
317 result = all_clusters->GetList(index, &cluster);
318 if (!result)
319 return false;
320 if (cluster->GetSize() < 1)
321 return false;
322 std::string key;
323 result = cluster->GetString(0, &key);
324 if (!result)
325 return false;
326 std::vector<std::string> stars_ids;
327 for (size_t index = 1; index < cluster->GetSize(); ++index) {
328 std::string stars_id;
329 result = cluster->GetString(index, &stars_id);
330 if (!result)
331 return false;
332 stars_ids.push_back(stars_id);
333 }
334
335 output.insert(std::make_pair(key, stars_ids));
336 }
337 out_map->swap(output);
338 return true;
339 }
340 } // namespace enhanced_bookmarks
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698