diff options
author | noyau <noyau@chromium.org> | 2014-10-07 15:00:43 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-07 22:01:00 +0000 |
commit | 6bb374fc58bfeeb7966b6a548b1c7b41af9c8e47 (patch) | |
tree | 7b9d87b6c35ea4350be96c62016e5c2a77fd5d0b /components/enhanced_bookmarks/bookmark_server_cluster_service.cc | |
parent | da97e832e41826d3ce0e6bd5c495feb636345ece (diff) | |
download | chromium_src-6bb374fc58bfeeb7966b6a548b1c7b41af9c8e47.zip chromium_src-6bb374fc58bfeeb7966b6a548b1c7b41af9c8e47.tar.gz chromium_src-6bb374fc58bfeeb7966b6a548b1c7b41af9c8e47.tar.bz2 |
Bring up of the enhanced bookmarks cluster service.
This service retrieves the cluster of bookmarks from the bookmark
server.
BUG=None
Review URL: https://codereview.chromium.org/539173004
Cr-Commit-Position: refs/heads/master@{#298582}
Diffstat (limited to 'components/enhanced_bookmarks/bookmark_server_cluster_service.cc')
-rw-r--r-- | components/enhanced_bookmarks/bookmark_server_cluster_service.cc | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/components/enhanced_bookmarks/bookmark_server_cluster_service.cc b/components/enhanced_bookmarks/bookmark_server_cluster_service.cc new file mode 100644 index 0000000..9cdd243 --- /dev/null +++ b/components/enhanced_bookmarks/bookmark_server_cluster_service.cc @@ -0,0 +1,315 @@ +// Copyright 2014 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/enhanced_bookmarks/bookmark_server_cluster_service.h" + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/memory/scoped_ptr.h" +#include "base/prefs/pref_service.h" +#include "base/values.h" +#include "components/bookmarks/browser/bookmark_model.h" +#include "components/enhanced_bookmarks/enhanced_bookmark_model.h" +#include "components/enhanced_bookmarks/enhanced_bookmark_utils.h" +#include "components/enhanced_bookmarks/pref_names.h" +#include "components/enhanced_bookmarks/proto/cluster.pb.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "components/signin/core/browser/signin_manager.h" +#include "net/base/url_util.h" +#include "net/url_request/url_fetcher.h" +#include "net/url_request/url_request_context_getter.h" + +namespace { +const std::string kClusterUrl("https://www.google.com/stars/cluster"); +const int kPrefServiceVersion = 1; +const char* kPrefServiceVersionKey = "version"; +const char* kPrefServiceDataKey = "data"; +const char* kAuthIdKey = "auth_id"; +} // namespace + +namespace enhanced_bookmarks { + +BookmarkServerClusterService::BookmarkServerClusterService( + const std::string& application_language_code, + scoped_refptr<net::URLRequestContextGetter> request_context_getter, + ProfileOAuth2TokenService* token_service, + SigninManagerBase* signin_manager, + enhanced_bookmarks::EnhancedBookmarkModel* enhanced_bookmark_model, + PrefService* pref_service) + : BookmarkServerService(request_context_getter, + token_service, + signin_manager, + enhanced_bookmark_model), + application_language_code_(application_language_code), + pref_service_(pref_service) { + LoadModel(); + + if (model_->loaded()) + TriggerTokenRequest(false); + + GetSigninManager()->AddObserver(this); +} + +BookmarkServerClusterService::~BookmarkServerClusterService() { + GetSigninManager()->RemoveObserver(this); +} + +const std::vector<const BookmarkNode*> +BookmarkServerClusterService::BookmarksForClusterNamed( + const std::string& cluster_name) const { + std::vector<const BookmarkNode*> results; + + ClusterMap::const_iterator cluster_it = cluster_data_.find(cluster_name); + if (cluster_it == cluster_data_.end()) + return results; + + for (auto& star_id : cluster_it->second) { + const BookmarkNode* bookmark = BookmarkForRemoteId(star_id); + if (bookmark) + results.push_back(bookmark); + } + return results; +} + +const std::vector<std::string> +BookmarkServerClusterService::ClustersForBookmark( + const BookmarkNode* bookmark) const { + const std::string& star_id = RemoteIDForBookmark(bookmark); + + // TODO(noyau): if this turns out to be a perf bottleneck this may be improved + // by storing a reverse map from id to cluster. + std::vector<std::string> clusters; + for (auto& pair : cluster_data_) { + const std::vector<std::string>& stars_ids = pair.second; + if (std::find(stars_ids.begin(), stars_ids.end(), star_id) != + stars_ids.end()) + clusters.push_back(pair.first); + } + return clusters; +} + +const std::vector<std::string> BookmarkServerClusterService::GetClusters() + const { + std::vector<std::string> cluster_names; + + for (auto& pair : cluster_data_) + cluster_names.push_back(pair.first); + + return cluster_names; +} + +// static +void BookmarkServerClusterService::RegisterPrefs( + user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterDictionaryPref( + prefs::kBookmarkClusters, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); +} + +scoped_ptr<net::URLFetcher> BookmarkServerClusterService::CreateFetcher() { + // Add the necessary arguments to the URI. + GURL url(kClusterUrl); + url = net::AppendQueryParameter(url, "output", "proto"); + + // Append language. + if (!application_language_code_.empty()) + url = net::AppendQueryParameter(url, "hl", application_language_code_); + + url = net::AppendQueryParameter(url, "v", model_->GetVersionString()); + + // Build the URLFetcher to perform the request. + scoped_ptr<net::URLFetcher> url_fetcher( + net::URLFetcher::Create(url, net::URLFetcher::POST, this)); + + // Binary encode a basic request proto. + image_collections::ClusterRequest request_proto; + request_proto.set_cluster_all(true); + + std::string proto_output; + bool result = request_proto.SerializePartialToString(&proto_output); + DCHECK(result); + + url_fetcher->SetUploadData("application/octet-stream", proto_output); + return url_fetcher; +} + +bool BookmarkServerClusterService::ProcessResponse(const std::string& response, + bool* should_notify) { + DCHECK(*should_notify); + image_collections::ClusterResponse response_proto; + bool result = response_proto.ParseFromString(response); + if (!result) + return false; // Not formatted properly. + + ClusterMap new_cluster_data; + for (const auto& cluster : response_proto.clusters()) { + const std::string& title = cluster.title(); + if (title.empty()) + continue; + std::vector<std::string> stars_ids; + for (auto& doc : cluster.docs()) { + if (!doc.empty()) + stars_ids.push_back(doc); + } + if (stars_ids.size()) + new_cluster_data[title] = stars_ids; + } + + if (new_cluster_data.size() == cluster_data_.size() && + std::equal(new_cluster_data.begin(), + new_cluster_data.end(), + cluster_data_.begin())) { + *should_notify = false; + } else { + SwapModel(&new_cluster_data); + } + return true; +} + +void BookmarkServerClusterService::CleanAfterFailure() { + if (cluster_data_.empty()) + return; + + ClusterMap empty; + SwapModel(&empty); +} + +void BookmarkServerClusterService::EnhancedBookmarkModelLoaded() { + TriggerTokenRequest(false); +} + +void BookmarkServerClusterService::EnhancedBookmarkAdded( + const BookmarkNode* node) { + // Nothing to do. +} + +void BookmarkServerClusterService::EnhancedBookmarkRemoved( + const BookmarkNode* node) { + // It is possible to remove the entries from the map here, but as those are + // filtered in ClustersForBookmark() this is not strictly necessary. +} + +void BookmarkServerClusterService::EnhancedBookmarkAllUserNodesRemoved() { + if (!cluster_data_.empty()) { + ClusterMap empty; + SwapModel(&empty); + } +} + +void BookmarkServerClusterService::EnhancedBookmarkRemoteIdChanged( + const BookmarkNode* node, + const std::string& old_remote_id, + const std::string& remote_id) { + std::vector<std::string> clusters; + for (auto& pair : cluster_data_) { + std::vector<std::string>& stars_ids = pair.second; + std::replace(stars_ids.begin(), stars_ids.end(), old_remote_id, remote_id); + } +} + +void BookmarkServerClusterService::GoogleSignedOut( + const std::string& account_id, + const std::string& username) { + if (!cluster_data_.empty()) { + ClusterMap empty; + SwapModel(&empty); + } +} + +void BookmarkServerClusterService::SwapModel(ClusterMap* cluster_map) { + cluster_data_.swap(*cluster_map); + const std::string& auth_id = GetSigninManager()->GetAuthenticatedAccountId(); + scoped_ptr<base::DictionaryValue> dictionary( + Serialize(cluster_data_, auth_id)); + pref_service_->Set(prefs::kBookmarkClusters, *dictionary); +} + +void BookmarkServerClusterService::LoadModel() { + const base::DictionaryValue* dictionary = + pref_service_->GetDictionary(prefs::kBookmarkClusters); + const std::string& auth_id = GetSigninManager()->GetAuthenticatedAccountId(); + + ClusterMap loaded_data; + bool result = BookmarkServerClusterService::Deserialize( + *dictionary, auth_id, &loaded_data); + if (result) + cluster_data_.swap(loaded_data); +} + +// +// Serialization. +// +// static +scoped_ptr<base::DictionaryValue> BookmarkServerClusterService::Serialize( + const ClusterMap& cluster_map, + const std::string& auth_id) { + // Create a list of all clusters. For each cluster, make another list. The + // first element in the list is the key (cluster name). All subsequent + // elements are stars ids. + scoped_ptr<base::ListValue> all_clusters(new base::ListValue); + for (auto& pair : cluster_map) { + scoped_ptr<base::ListValue> cluster(new base::ListValue); + cluster->AppendString(pair.first); + cluster->AppendStrings(pair.second); + all_clusters->Append(cluster.release()); + } + + // The dictionary that will be serialized has two fields: a version field and + // a data field. + scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue); + data->SetInteger(kPrefServiceVersionKey, kPrefServiceVersion); + data->Set(kPrefServiceDataKey, all_clusters.release()); + data->SetString(kAuthIdKey, auth_id); + + return data.Pass(); +} + +// static +bool BookmarkServerClusterService::Deserialize( + const base::DictionaryValue& value, + const std::string& auth_id, + ClusterMap* out_map) { + ClusterMap output; + + // Check version. + int version; + if (!value.GetInteger(kPrefServiceVersionKey, &version)) + return false; + if (version != kPrefServiceVersion) + return false; + + // Check auth id. + std::string id; + if (!value.GetString(kAuthIdKey, &id)) + return false; + if (id != auth_id) + return false; + + const base::ListValue* all_clusters = NULL; + if (!value.GetList(kPrefServiceDataKey, &all_clusters)) + return false; + + for (size_t index = 0; index < all_clusters->GetSize(); ++index) { + const base::ListValue* cluster = NULL; + if (!all_clusters->GetList(index, &cluster)) + return false; + if (cluster->GetSize() < 1) + return false; + std::string key; + if (!cluster->GetString(0, &key)) + return false; + std::vector<std::string> stars_ids; + for (size_t index = 1; index < cluster->GetSize(); ++index) { + std::string stars_id; + if (!cluster->GetString(index, &stars_id)) + return false; + stars_ids.push_back(stars_id); + } + output.insert(std::make_pair(key, stars_ids)); + } + out_map->swap(output); + return true; +} + +} // namespace enhanced_bookmarks |