app_list: Re-enable people search.
[chromium-blink-merge.git] / chrome / browser / extensions / api / copresence / copresence_api.cc
blobfc4b525197a04e27ef8a0cca39b33d5c64c1aab6
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.
5 #include "chrome/browser/extensions/api/copresence/copresence_api.h"
7 #include "base/lazy_instance.h"
8 #include "base/memory/linked_ptr.h"
9 #include "base/prefs/pref_service.h"
10 #include "chrome/browser/copresence/chrome_whispernet_client.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/services/gcm/gcm_profile_service.h"
13 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
14 #include "chrome/common/chrome_version_info.h"
15 #include "chrome/common/extensions/api/copresence.h"
16 #include "chrome/common/extensions/manifest_handlers/copresence_manifest.h"
17 #include "chrome/common/pref_names.h"
18 #include "components/copresence/copresence_manager_impl.h"
19 #include "components/copresence/proto/data.pb.h"
20 #include "components/copresence/proto/enums.pb.h"
21 #include "components/copresence/proto/rpcs.pb.h"
22 #include "components/copresence/public/whispernet_client.h"
23 #include "components/pref_registry/pref_registry_syncable.h"
24 #include "content/public/browser/browser_context.h"
25 #include "extensions/browser/event_router.h"
26 #include "extensions/browser/extension_registry.h"
27 #include "extensions/common/extension.h"
28 #include "extensions/common/manifest_constants.h"
30 using user_prefs::PrefRegistrySyncable;
32 namespace extensions {
34 namespace {
36 base::LazyInstance<BrowserContextKeyedAPIFactory<CopresenceService>>
37 g_factory = LAZY_INSTANCE_INITIALIZER;
39 const char kInvalidOperationsMessage[] =
40 "Invalid operation in operations array.";
41 const char kShuttingDownMessage[] = "Shutting down.";
43 const std::string GetPrefName(bool authenticated) {
44 return authenticated ? prefs::kCopresenceAuthenticatedDeviceId
45 : prefs::kCopresenceAnonymousDeviceId;
48 } // namespace
51 // Public functions.
53 CopresenceService::CopresenceService(content::BrowserContext* context)
54 : is_shutting_down_(false), browser_context_(context) {}
56 CopresenceService::~CopresenceService() {}
58 void CopresenceService::Shutdown() {
59 is_shutting_down_ = true;
60 manager_.reset();
61 whispernet_client_.reset();
64 copresence::CopresenceManager* CopresenceService::manager() {
65 if (!manager_ && !is_shutting_down_)
66 manager_.reset(new copresence::CopresenceManagerImpl(this));
67 return manager_.get();
70 copresence::WhispernetClient* CopresenceService::whispernet_client() {
71 if (!whispernet_client_ && !is_shutting_down_)
72 whispernet_client_.reset(new ChromeWhispernetClient(browser_context_));
73 return whispernet_client_.get();
76 const std::string CopresenceService::auth_token(const std::string& app_id)
77 const {
78 // This won't be const if we use map[]
79 const auto& key = auth_tokens_by_app_.find(app_id);
80 return key == auth_tokens_by_app_.end() ? std::string() : key->second;
83 void CopresenceService::set_api_key(const std::string& app_id,
84 const std::string& api_key) {
85 DCHECK(!app_id.empty());
86 api_keys_by_app_[app_id] = api_key;
89 void CopresenceService::set_auth_token(const std::string& app_id,
90 const std::string& token) {
91 DCHECK(!app_id.empty());
92 auth_tokens_by_app_[app_id] = token;
95 void CopresenceService::set_manager_for_testing(
96 scoped_ptr<copresence::CopresenceManager> manager) {
97 manager_ = manager.Pass();
100 void CopresenceService::ResetState() {
101 DVLOG(2) << "Deleting copresence state";
102 GetPrefService()->ClearPref(prefs::kCopresenceAuthenticatedDeviceId);
103 GetPrefService()->ClearPref(prefs::kCopresenceAnonymousDeviceId);
104 manager_ = nullptr;
107 // static
108 void CopresenceService::RegisterProfilePrefs(PrefRegistrySyncable* registry) {
109 registry->RegisterStringPref(
110 prefs::kCopresenceAuthenticatedDeviceId,
111 std::string(),
112 PrefRegistrySyncable::UNSYNCABLE_PREF);
113 registry->RegisterStringPref(
114 prefs::kCopresenceAnonymousDeviceId,
115 std::string(),
116 PrefRegistrySyncable::UNSYNCABLE_PREF);
119 // static
120 BrowserContextKeyedAPIFactory<CopresenceService>*
121 CopresenceService::GetFactoryInstance() {
122 return g_factory.Pointer();
126 // Private functions.
128 void CopresenceService::HandleMessages(
129 const std::string& /* app_id */,
130 const std::string& subscription_id,
131 const std::vector<copresence::Message>& messages) {
132 // TODO(ckehoe): Once the server starts sending back the app ids associated
133 // with subscriptions, use that instead of the apps_by_subs registry.
134 std::string app_id = apps_by_subscription_id_[subscription_id];
136 if (app_id.empty()) {
137 LOG(ERROR) << "Skipping message from unrecognized subscription "
138 << subscription_id;
139 return;
142 int message_count = messages.size();
143 std::vector<linked_ptr<api::copresence::Message>> api_messages(
144 message_count);
146 for (int m = 0; m < message_count; ++m) {
147 api_messages[m].reset(new api::copresence::Message);
148 api_messages[m]->type = messages[m].type().type();
149 api_messages[m]->payload = messages[m].payload();
150 DVLOG(2) << "Dispatching message of type " << api_messages[m]->type << ":\n"
151 << api_messages[m]->payload;
154 // Send the messages to the client app.
155 scoped_ptr<Event> event(
156 new Event(api::copresence::OnMessagesReceived::kEventName,
157 api::copresence::OnMessagesReceived::Create(subscription_id,
158 api_messages),
159 browser_context_));
160 EventRouter::Get(browser_context_)
161 ->DispatchEventToExtension(app_id, event.Pass());
162 DVLOG(2) << "Passed " << api_messages.size() << " messages to app \""
163 << app_id << "\" for subscription \"" << subscription_id << "\"";
166 void CopresenceService::HandleStatusUpdate(
167 copresence::CopresenceStatus status) {
168 scoped_ptr<Event> event(
169 new Event(api::copresence::OnStatusUpdated::kEventName,
170 api::copresence::OnStatusUpdated::Create(
171 api::copresence::STATUS_AUDIOFAILED),
172 browser_context_));
173 EventRouter::Get(browser_context_)->BroadcastEvent(event.Pass());
174 DVLOG(2) << "Sent Audio Failed status update.";
177 net::URLRequestContextGetter* CopresenceService::GetRequestContext() const {
178 return browser_context_->GetRequestContext();
181 const std::string CopresenceService::GetPlatformVersionString() const {
182 return chrome::VersionInfo().CreateVersionString();
185 const std::string
186 CopresenceService::GetAPIKey(const std::string& app_id) const {
187 // This won't be const if we use map[]
188 const auto& key = api_keys_by_app_.find(app_id);
189 return key == api_keys_by_app_.end() ? std::string() : key->second;
192 const std::string
193 CopresenceService::GetProjectId(const std::string& app_id) const {
194 const Extension* extension = ExtensionRegistry::Get(browser_context_)
195 ->GetExtensionById(app_id, ExtensionRegistry::ENABLED);
196 DCHECK(extension) << "Invalid extension ID";
197 CopresenceManifestData* manifest_data = static_cast<CopresenceManifestData*>(
198 extension->GetManifestData(manifest_keys::kCopresence));
199 return manifest_data ? manifest_data->project_id : std::string();
202 copresence::WhispernetClient* CopresenceService::GetWhispernetClient() {
203 return whispernet_client();
206 gcm::GCMDriver* CopresenceService::GetGCMDriver() {
207 gcm::GCMProfileService* gcm_service =
208 gcm::GCMProfileServiceFactory::GetForProfile(browser_context_);
209 return gcm_service ? gcm_service->driver() : nullptr;
212 const std::string CopresenceService::GetDeviceId(bool authenticated) {
213 std::string id = GetPrefService()->GetString(GetPrefName(authenticated));
214 DVLOG(3) << "Retrieved device ID \"" << id << "\", "
215 << "authenticated = " << authenticated;
216 return id;
219 void CopresenceService::SaveDeviceId(bool authenticated,
220 const std::string& device_id) {
221 DVLOG(3) << "Storing device ID \"" << device_id << "\", "
222 << "authenticated = " << authenticated;
223 if (device_id.empty())
224 GetPrefService()->ClearPref(GetPrefName(authenticated));
225 else
226 GetPrefService()->SetString(GetPrefName(authenticated), device_id);
229 PrefService* CopresenceService::GetPrefService() {
230 return Profile::FromBrowserContext(browser_context_)->GetPrefs();
233 template <>
234 void
235 BrowserContextKeyedAPIFactory<CopresenceService>::DeclareFactoryDependencies() {
236 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
239 // CopresenceExecuteFunction implementation.
240 ExtensionFunction::ResponseAction CopresenceExecuteFunction::Run() {
241 scoped_ptr<api::copresence::Execute::Params> params(
242 api::copresence::Execute::Params::Create(*args_));
243 EXTENSION_FUNCTION_VALIDATE(params.get());
245 CopresenceService* service =
246 CopresenceService::GetFactoryInstance()->Get(browser_context());
248 // This can only happen if we're shutting down. In all other cases, if we
249 // don't have a manager, we'll create one.
250 if (!service->manager())
251 return RespondNow(Error(kShuttingDownMessage));
253 // Each execute will correspond to one ReportRequest protocol buffer.
254 copresence::ReportRequest request;
255 if (!PrepareReportRequestProto(params->operations,
256 extension_id(),
257 &service->apps_by_subscription_id(),
258 &request)) {
259 return RespondNow(Error(kInvalidOperationsMessage));
262 service->manager()->ExecuteReportRequest(
263 request,
264 extension_id(),
265 service->auth_token(extension_id()),
266 base::Bind(&CopresenceExecuteFunction::SendResult, this));
267 return RespondLater();
270 void CopresenceExecuteFunction::SendResult(
271 copresence::CopresenceStatus status) {
272 api::copresence::ExecuteStatus api_status =
273 (status == copresence::SUCCESS) ? api::copresence::EXECUTE_STATUS_SUCCESS
274 : api::copresence::EXECUTE_STATUS_FAILED;
275 Respond(ArgumentList(api::copresence::Execute::Results::Create(api_status)));
278 // CopresenceSetApiKeyFunction implementation.
279 ExtensionFunction::ResponseAction CopresenceSetApiKeyFunction::Run() {
280 scoped_ptr<api::copresence::SetApiKey::Params> params(
281 api::copresence::SetApiKey::Params::Create(*args_));
282 EXTENSION_FUNCTION_VALIDATE(params.get());
284 // The api key may be set to empty, to clear it.
285 CopresenceService::GetFactoryInstance()->Get(browser_context())
286 ->set_api_key(extension_id(), params->api_key);
287 return RespondNow(NoArguments());
290 // CopresenceSetAuthTokenFunction implementation
291 ExtensionFunction::ResponseAction CopresenceSetAuthTokenFunction::Run() {
292 scoped_ptr<api::copresence::SetAuthToken::Params> params(
293 api::copresence::SetAuthToken::Params::Create(*args_));
294 EXTENSION_FUNCTION_VALIDATE(params.get());
296 // The token may be set to empty, to clear it.
297 CopresenceService::GetFactoryInstance()->Get(browser_context())
298 ->set_auth_token(extension_id(), params->token);
299 return RespondNow(NoArguments());
302 } // namespace extensions