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

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: Removing empty DEPS file, fixing a nit. 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 "ios_pref_service_key_for_stored_bookmark_clusters";
Yaron 2014/09/05 05:18:01 nit: not ios specific. changing means clients will
noyau (Ping after 24h) 2014/09/10 08:53:57 Done.
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_)
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,
112 std::string(),
113 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
114 }
115
116 net::URLFetcher* BookmarkServerClusterService::CreateFetcherWithToken(
117 const std::string& access_token) {
118 // Add the necessary arguments to the URI.
119 GURL url(kClusterUrl);
120 url = net::AppendQueryParameter(url, "output", "proto");
121
122 // Append language.
123 if (!application_language_code_.empty())
124 url = net::AppendQueryParameter(url, "hl", application_language_code_);
125
126 // Build the URLFetcher to perform the request.
127 net::URLFetcher* url_fetcher =
128 net::URLFetcher::Create(url, net::URLFetcher::POST, this);
129
130 // Binary encode a basic request proto.
131 image_collections::ClusterRequest request_proto;
132 request_proto.mutable_options()->set_min_cluster_size(1);
133 request_proto.set_cluster_all(true);
134
135 std::string proto_output;
136 bool result = request_proto.SerializePartialToString(&proto_output);
137 DCHECK(result);
138
139 url_fetcher->SetUploadData("application/octet-stream", proto_output);
140 return url_fetcher;
141 }
142
143 bool BookmarkServerClusterService::ProcessResponse(const std::string& response,
144 bool* should_notify) {
145 DCHECK(*should_notify);
146 image_collections::ClusterResponse response_proto;
147 bool result = response_proto.ParseFromString(response);
148 if (!result)
149 return false; // Not formatted properly.
150
151 std::map<std::string, std::vector<std::string> > new_cluster_data;
152 for (auto cluster : response_proto.clusters()) {
153 const std::string& title = cluster.title();
154 if (!title.length())
155 continue;
156 std::vector<std::string> starids;
157 for (std::string doc : cluster.docs()) {
158 if (doc.length())
159 starids.push_back(doc);
160 }
161 if (starids.size())
162 new_cluster_data[title] = starids;
163 }
164
165 if (new_cluster_data.size() == cluster_data_.size() &&
166 std::equal(new_cluster_data.begin(),
167 new_cluster_data.end(),
168 cluster_data_.begin())) {
169 *should_notify = false;
170 } else {
171 UpdateModel(&new_cluster_data);
172 }
173 return true;
174 }
175
176 void BookmarkServerClusterService::CleanAfterFailure() {
177 if (cluster_data_.empty())
178 return;
179
180 ClusterMap empty;
181 UpdateModel(&empty);
182 }
183
184 void BookmarkServerClusterService::BookmarkModelLoaded(BookmarkModel* model,
185 bool ids_reassigned) {
186 BookmarkServerService::BookmarkModelLoaded(model, ids_reassigned);
187 TriggerTokenRequest(false);
188 }
189
190 void BookmarkServerClusterService::BookmarkNodeAdded(BookmarkModel* model,
Yaron 2014/09/05 05:18:00 these overrides seem unnecessary unless you take m
191 const BookmarkNode* parent,
192 int index) {
193 BookmarkServerService::BookmarkNodeAdded(model, parent, index);
194 }
195
196 void BookmarkServerClusterService::BookmarkMetaInfoChanged(
197 BookmarkModel* model,
198 const BookmarkNode* node) {
199 BookmarkServerService::BookmarkMetaInfoChanged(model, node);
200 }
201
202 void BookmarkServerClusterService::BookmarkAllUserNodesRemoved(
203 BookmarkModel* model,
204 const std::set<GURL>& removed_urls) {
205 if (!cluster_data_.empty()) {
206 ClusterMap empty;
207 UpdateModel(&empty);
208 }
209 BookmarkServerService::BookmarkAllUserNodesRemoved(model, removed_urls);
210 }
211
212 void BookmarkServerClusterService::GoogleSignedOut(
213 const std::string& account_id,
214 const std::string& username) {
215 if (!cluster_data_.empty()) {
216 ClusterMap empty;
217 UpdateModel(&empty);
218 }
219 }
220
221 void BookmarkServerClusterService::UpdateModel(ClusterMap* cluster_map) {
222 cluster_data_.swap(*cluster_map);
223 std::string serialized;
224 std::string auth_id = GetSigninManager()->GetAuthenticatedAccountId();
225 bool result = BookmarkServerClusterService::Serialize(
226 cluster_data_, &serialized, auth_id);
227 if (result)
228 pref_service_->SetString(kPrefServiceKey, serialized);
229 }
230
231 void BookmarkServerClusterService::LoadModel() {
232 std::string serialized(pref_service_->GetString(kPrefServiceKey));
233 std::string auth_id = GetSigninManager()->GetAuthenticatedAccountId();
234
235 ClusterMap loaded_data;
236 bool result = BookmarkServerClusterService::Deserialize(
237 serialized, &loaded_data, auth_id);
238 if (result)
239 cluster_data_.swap(loaded_data);
Yaron 2014/09/05 05:18:01 if we failed to deserialize, issue a request to ge
noyau (Ping after 24h) 2014/09/10 08:53:57 I didn't on purpose, to avoid looping over and ove
240 }
241
242 //
243 // Serialization.
244 //
245 bool BookmarkServerClusterService::Serialize(const ClusterMap& cluster_map,
246 std::string* out_result,
247 const std::string& auth_id) {
248 // Create a list of all clusters. For each cluster, make another list. The
249 // first element in the list is the key (cluster name). All subsequent
250 // elements are stars ids.
251 // This non reference counted pointer is going to be consumed by |data|.
252 base::ListValue* all_clusters = new base::ListValue;
253 for (auto it : cluster_map) {
254 // This non reference counted pointer is going to be consumed by
255 // |all_clusters|.
256 base::ListValue* cluster = new base::ListValue;
257 cluster->AppendString(it.first);
258 cluster->AppendStrings(it.second);
259 all_clusters->Append(cluster);
260 }
261
262 // The dictionary that will be serialized has two fields: a version field and
263 // a data field.
264 base::DictionaryValue data;
265 data.SetInteger(kPrefServiceVersionKey, kPrefServiceVersion);
266 data.Set(kPrefServiceDataKey, all_clusters);
267 data.SetString(kAuthIdKey, auth_id);
268
269 std::string output;
270 bool result = base::JSONWriter::Write(&data, &output);
271 DCHECK(result);
272 out_result->swap(output);
273 return true;
274 }
275
276 bool BookmarkServerClusterService::Deserialize(const std::string& input,
277 ClusterMap* out_map,
278 const std::string& auth_id) {
279 if (input.empty())
280 return false;
281
282 base::JSONReader reader;
283 scoped_ptr<base::Value> value(reader.ReadToValue(input));
284 if (value == NULL)
285 return false;
286 if (!value->IsType(base::Value::TYPE_DICTIONARY))
287 return false;
288
289 base::DictionaryValue* dictionary_value;
290 bool result = value->GetAsDictionary(&dictionary_value);
291 if (!result)
292 return false;
293
294 // Check version.
295 int version;
296 result = dictionary_value->GetInteger(kPrefServiceVersionKey, &version);
297 if (!result)
298 return false;
299 if (version != kPrefServiceVersion)
300 return false;
301
302 // Check auth id.
303 std::string id;
304 result = dictionary_value->GetString(kAuthIdKey, &id);
305 if (!result)
306 return false;
307 if (id != auth_id)
308 return false;
309
310 base::ListValue* all_clusters;
311 result = dictionary_value->GetList(kPrefServiceDataKey, &all_clusters);
312 if (!result)
313 return false;
314
315 ClusterMap output;
316 for (size_t index = 0; index < all_clusters->GetSize(); ++index) {
317 base::ListValue* cluster;
318 result = all_clusters->GetList(index, &cluster);
319 if (!result)
320 return false;
321 if (cluster->GetSize() < 1)
322 return false;
323 std::string key;
324 result = cluster->GetString(0, &key);
325 if (!result)
326 return false;
327 std::vector<std::string> stars_ids;
328 for (size_t index = 1; index < cluster->GetSize(); ++index) {
329 std::string stars_id;
330 result = cluster->GetString(index, &stars_id);
331 if (!result)
332 return false;
333 stars_ids.push_back(stars_id);
334 }
335
336 output.insert(std::make_pair(key, stars_ids));
337 }
338 out_map->swap(output);
339 return true;
340 }
341 } // namespace enhanced_bookmarks
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698