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

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: More feedback 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/pref_names.h"
15 #include "components/enhanced_bookmarks/proto/cluster.pb.h"
16 #include "components/pref_registry/pref_registry_syncable.h"
17 #include "components/signin/core/browser/signin_manager.h"
18 #include "net/base/url_util.h"
19 #include "net/url_request/url_fetcher.h"
20 #include "net/url_request/url_request_context_getter.h"
21
22 namespace {
23 const std::string kClusterUrl("https://www.google.com/stars/cluster");
24 const int kPrefServiceVersion = 1;
25 const char* kPrefServiceVersionKey = "version";
26 const char* kPrefServiceDataKey = "data";
27 const char* kAuthIdKey = "auth_id";
28 } // namespace
29
30 namespace enhanced_bookmarks {
31
32 BookmarkServerClusterService::BookmarkServerClusterService(
33 const std::string& application_language_code,
34 scoped_refptr<net::URLRequestContextGetter> request_context_getter,
35 ProfileOAuth2TokenService* token_service,
36 SigninManagerBase* signin_manager,
37 BookmarkModel* bookmark_model,
38 PrefService* pref_service)
39 : BookmarkServerService(request_context_getter,
40 token_service,
41 signin_manager,
42 bookmark_model),
43 application_language_code_(application_language_code),
44 pref_service_(pref_service) {
45 LoadModel();
46
47 if (bookmark_model_->loaded())
48 TriggerTokenRequest(false);
49
50 GetSigninManager()->AddObserver(this);
51 }
52
53 BookmarkServerClusterService::~BookmarkServerClusterService() {
54 GetSigninManager()->RemoveObserver(this);
55 }
56
57 const std::vector<const BookmarkNode*>
58 BookmarkServerClusterService::BookmarksForClusterNamed(
59 const std::string& cluster_name) const {
60 std::vector<const BookmarkNode*> results;
61
62 ClusterMap::const_iterator cluster_it = cluster_data_.find(cluster_name);
63 if (cluster_it == cluster_data_.end())
64 return results;
65
66 for (std::vector<std::string>::const_iterator it = cluster_it->second.begin();
67 it != cluster_it->second.end();
68 ++it) {
69 std::string stars_id = *it;
Yaron 2014/09/23 17:08:30 star_id
battre 2014/09/26 14:33:04 const std::string& star_id = *it; ?
noyau (Ping after 24h) 2014/10/01 16:04:42 Done.
noyau (Ping after 24h) 2014/10/01 16:04:43 On 2014/09/26 14:33:04, battre wrote: > const std:
70 const BookmarkNode* bookmark = BookmarkForRemoteId(stars_id);
71 if (bookmark)
72 results.push_back(bookmark);
73 }
74 return results;
75 }
76
77 const std::vector<std::string>
78 BookmarkServerClusterService::ClustersForBookmark(
79 const BookmarkNode* bookmark) const {
80 std::string starid = RemoteIDForBookmark(bookmark);
Yaron 2014/09/23 17:08:30 star_id
noyau (Ping after 24h) 2014/10/01 16:04:43 Done.
81
82 // TODO(noyau): if this turns out to be a perf bottleneck this may be improved
83 // by storing a reverse map from id to cluster.
84 std::vector<std::string> clusters;
85 for (ClusterMap::const_iterator it = cluster_data_.begin();
86 it != cluster_data_.end();
87 ++it) {
88 const std::vector<std::string>& v = it->second;
89 if (std::find(v.begin(), v.end(), starid) != v.end())
90 clusters.push_back(it->first);
91 }
92 return clusters;
93 }
94
95 const std::vector<std::string> BookmarkServerClusterService::GetClusters()
96 const {
97 std::vector<std::string> cluster_names;
98
99 for (ClusterMap::const_iterator it = cluster_data_.begin();
100 it != cluster_data_.end();
101 ++it) {
102 cluster_names.push_back(it->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 prefs::kBookmarkClusters,
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_);
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 ClusterMap new_cluster_data;
151 for (int i = 0; i < response_proto.clusters_size(); ++i) {
152 const image_collections::ClusterResponse_Cluster cluster =
153 response_proto.clusters(i);
154 const std::string& title = cluster.title();
155 if (title.empty())
156 continue;
157 std::vector<std::string> starids;
158 for (int j = 0; j < cluster.docs_size(); ++j) {
159 const std::string doc = cluster.docs(j);
160 if (!doc.empty())
161 starids.push_back(doc);
162 }
163 if (starids.size())
164 new_cluster_data[title] = starids;
165 }
166 if (new_cluster_data.size() == cluster_data_.size() &&
167 std::equal(new_cluster_data.begin(),
168 new_cluster_data.end(),
169 cluster_data_.begin())) {
170 *should_notify = false;
171 } else {
172 UpdateModel(&new_cluster_data);
173 }
174 return true;
175 }
176
177 void BookmarkServerClusterService::CleanAfterFailure() {
178 if (cluster_data_.empty())
179 return;
180
181 ClusterMap empty;
182 UpdateModel(&empty);
183 }
184
185 void BookmarkServerClusterService::BookmarkModelLoaded(BookmarkModel* model,
186 bool ids_reassigned) {
187 BookmarkServerService::BookmarkModelLoaded(model, ids_reassigned);
188 TriggerTokenRequest(false);
189 }
190
191 void BookmarkServerClusterService::BookmarkAllUserNodesRemoved(
192 BookmarkModel* model,
193 const std::set<GURL>& removed_urls) {
194 if (!cluster_data_.empty()) {
195 ClusterMap empty;
196 UpdateModel(&empty);
197 }
198 BookmarkServerService::BookmarkAllUserNodesRemoved(model, removed_urls);
199 }
200
201 void BookmarkServerClusterService::GoogleSignedOut(
202 const std::string& account_id,
203 const std::string& username) {
204 if (!cluster_data_.empty()) {
205 ClusterMap empty;
206 UpdateModel(&empty);
207 }
208 }
209
210 void BookmarkServerClusterService::UpdateModel(ClusterMap* cluster_map) {
211 cluster_data_.swap(*cluster_map);
212 std::string serialized;
213 std::string auth_id = GetSigninManager()->GetAuthenticatedAccountId();
214 BookmarkServerClusterService::Serialize(cluster_data_, &serialized, auth_id);
battre 2014/09/26 14:33:05 Nit: Do you need the BookmarkServerClusterService:
noyau (Ping after 24h) 2014/10/01 16:04:42 Done.
215 pref_service_->SetString(prefs::kBookmarkClusters, serialized);
battre 2014/09/26 14:33:04 Why do you store this as a string instead of a dic
noyau (Ping after 24h) 2014/10/01 16:04:42 I didn't do this code originally, so I must admit
216 }
217
218 void BookmarkServerClusterService::LoadModel() {
219 std::string serialized(pref_service_->GetString(prefs::kBookmarkClusters));
220 std::string auth_id = GetSigninManager()->GetAuthenticatedAccountId();
221
222 ClusterMap loaded_data;
223 BookmarkServerClusterService::Deserialize(serialized, &loaded_data, auth_id);
224 cluster_data_.swap(loaded_data);
225 }
226
227 //
228 // Serialization.
229 //
230 void BookmarkServerClusterService::Serialize(const ClusterMap& cluster_map,
231 std::string* out_result,
232 const std::string& auth_id) {
233 // Create a list of all clusters. For each cluster, make another list. The
234 // first element in the list is the key (cluster name). All subsequent
235 // elements are stars ids.
236 // This non reference counted pointer is going to be consumed by |data|.
237 base::ListValue* all_clusters = new base::ListValue;
battre 2014/09/26 14:33:05 scoped_ptr?
noyau (Ping after 24h) 2014/10/01 16:04:43 Used scoped_ptr and release() to make the ownershi
238 for (ClusterMap::const_iterator it = cluster_map.begin();
239 it != cluster_map.end();
240 ++it) {
241 // This non reference counted pointer is going to be consumed by
242 // |all_clusters|.
243 base::ListValue* cluster = new base::ListValue;
battre 2014/09/26 14:33:05 scoped_ptr?
noyau (Ping after 24h) 2014/10/01 16:04:43 Same, removed the comment and used scoped_ptr and
244 cluster->AppendString(it->first);
245 cluster->AppendStrings(it->second);
246 all_clusters->Append(cluster);
247 }
248
249 // The dictionary that will be serialized has two fields: a version field and
250 // a data field.
251 base::DictionaryValue data;
252 data.SetInteger(kPrefServiceVersionKey, kPrefServiceVersion);
253 data.Set(kPrefServiceDataKey, all_clusters);
254 data.SetString(kAuthIdKey, auth_id);
battre 2014/09/26 14:33:05 Why don't you just return data?
noyau (Ping after 24h) 2014/10/01 16:04:43 base::DictionaryValue is not copiable (DISALLOW_CO
255
256 std::string output;
257 bool result = base::JSONWriter::Write(&data, &output);
258 DCHECK(result);
259 out_result->swap(output);
260 }
261
262 bool BookmarkServerClusterService::Deserialize(const std::string& input,
263 ClusterMap* out_map,
264 const std::string& auth_id) {
265 if (input.empty())
266 return false;
267
268 base::JSONReader reader;
Mark 2014/09/18 18:10:43 Any reason why you would serialize this down to JS
Yaron 2014/09/23 17:08:30 +1
battre 2014/09/26 14:33:04 I think this is used only for the pref service. Th
noyau (Ping after 24h) 2014/10/01 16:04:42 The is no precedent in storing binary data in pref
269 scoped_ptr<base::Value> value(reader.ReadToValue(input));
270 if (value == NULL)
271 return false;
272 if (!value->IsType(base::Value::TYPE_DICTIONARY))
273 return false;
274
275 base::DictionaryValue* dictionary_value;
276 bool result = value->GetAsDictionary(&dictionary_value);
277 if (!result)
battre 2014/09/26 14:33:05 nit: I would inline all of these if (!value->GetAs
noyau (Ping after 24h) 2014/10/01 16:04:43 Done.
278 return false;
279
280 // Check version.
281 int version;
282 result = dictionary_value->GetInteger(kPrefServiceVersionKey, &version);
283 if (!result)
284 return false;
285 if (version != kPrefServiceVersion)
286 return false;
287
288 // Check auth id.
289 std::string id;
290 result = dictionary_value->GetString(kAuthIdKey, &id);
291 if (!result)
292 return false;
293 if (id != auth_id)
294 return false;
295
296 base::ListValue* all_clusters;
297 result = dictionary_value->GetList(kPrefServiceDataKey, &all_clusters);
298 if (!result)
299 return false;
300
301 ClusterMap output;
302 for (size_t index = 0; index < all_clusters->GetSize(); ++index) {
303 base::ListValue* cluster;
battre 2014/09/26 14:33:05 base::ListValue* cluster = NULL;
noyau (Ping after 24h) 2014/10/01 16:04:42 Done.
304 result = all_clusters->GetList(index, &cluster);
305 if (!result)
306 return false;
307 if (cluster->GetSize() < 1)
308 return false;
309 std::string key;
310 result = cluster->GetString(0, &key);
311 if (!result)
312 return false;
313 std::vector<std::string> stars_ids;
314 for (size_t index = 1; index < cluster->GetSize(); ++index) {
315 std::string stars_id;
316 result = cluster->GetString(index, &stars_id);
317 if (!result)
318 return false;
319 stars_ids.push_back(stars_id);
320 }
321
322 output.insert(std::make_pair(key, stars_ids));
323 }
324 out_map->swap(output);
325 return true;
326 }
327 } // namespace enhanced_bookmarks
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698