Chromium Code Reviews| Index: chrome/browser/extensions/api/copresence/copresence_api.cc |
| diff --git a/chrome/browser/extensions/api/copresence/copresence_api.cc b/chrome/browser/extensions/api/copresence/copresence_api.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ec9ed078864b8c28c702c5df284f3e9ad33bc793 |
| --- /dev/null |
| +++ b/chrome/browser/extensions/api/copresence/copresence_api.cc |
| @@ -0,0 +1,182 @@ |
| +// 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 "chrome/browser/extensions/api/copresence/copresence_api.h" |
| + |
| +#include "base/lazy_instance.h" |
| +#include "base/memory/linked_ptr.h" |
| +#include "chrome/browser/copresence/chrome_whispernet_client.h" |
| +#include "chrome/common/chrome_version_info.h" |
| +#include "chrome/common/extensions/api/copresence.h" |
| +#include "components/copresence/proto/data.pb.h" |
| +#include "components/copresence/proto/enums.pb.h" |
| +#include "components/copresence/proto/rpcs.pb.h" |
| +#include "components/copresence/public/copresence_client.h" |
| +#include "components/copresence/public/whispernet_client.h" |
| +#include "content/public/browser/browser_context.h" |
| +#include "extensions/browser/event_router.h" |
| + |
| +namespace extensions { |
| + |
| +namespace { |
| + |
| +base::LazyInstance<BrowserContextKeyedAPIFactory<CopresenceService> > |
| + g_factory = LAZY_INSTANCE_INITIALIZER; |
| + |
| +const char kInvalidOperationsMessage[] = |
| + "Invalid operation in operations array."; |
| +const char kShuttingDownMessage[] = "Shutting down."; |
| + |
| +CopresenceService* GetCopresenceService( |
| + content::BrowserContext* browser_context) { |
| + return CopresenceService::GetFactoryInstance()->Get(browser_context); |
| +} |
| + |
| +copresence::CopresenceClient* GetCopresenceClient( |
| + content::BrowserContext* browser_context) { |
|
not at google - send to devlin
2014/08/07 22:23:38
make both of these instance methods, then you don'
rkc
2014/08/07 22:32:36
Actually, removing them completely doesn't really
|
| + CopresenceService* service_ptr = GetCopresenceService(browser_context); |
| + return service_ptr ? service_ptr->client() : NULL; |
| +} |
| + |
| +} // namespace |
| + |
| +// CopresenceService implementation: |
| + |
| +CopresenceService::CopresenceService(content::BrowserContext* context) |
| + : is_shutting_down_(false), browser_context_(context) { |
| +} |
| + |
| +CopresenceService::~CopresenceService() { |
| +} |
| + |
| +copresence::CopresenceClient* CopresenceService::client() { |
|
not at google - send to devlin
2014/08/07 22:23:38
what is the difference between this method and Get
rkc
2014/08/07 22:32:36
Removed all the GetCopresenceXXX() functions.
Done
|
| + if (!client_ && !is_shutting_down_) |
| + client_.reset(new copresence::CopresenceClient(this)); |
| + return client_.get(); |
|
not at google - send to devlin
2014/08/07 22:23:38
this returns the current client if it's shutting d
rkc
2014/08/07 22:32:36
Yes, and the current client is set to NULL if we'r
|
| +} |
| + |
| +copresence::WhispernetClient* CopresenceService::whispernet_client() { |
| + if (!whispernet_client_ && !is_shutting_down_) |
| + whispernet_client_.reset(new ChromeWhispernetClient(browser_context_)); |
| + return whispernet_client_.get(); |
| +} |
| + |
| +void CopresenceService::Shutdown() { |
| + is_shutting_down_ = true; |
| + client_.reset(); |
| + whispernet_client_.reset(); |
| +} |
| + |
| +// static |
| +BrowserContextKeyedAPIFactory<CopresenceService>* |
| +CopresenceService::GetFactoryInstance() { |
| + return g_factory.Pointer(); |
| +} |
| + |
| +void CopresenceService::HandleMessages( |
| + const std::string& /* app_id */, |
| + const std::string& subscription_id, |
| + const std::vector<copresence::Message>& messages) { |
| + // TODO(ckehoe): Once the server starts sending back the app ids associated |
| + // with subscriptions, use that instead of the apps_by_subs registry. |
| + std::string app_id = apps_by_subscription_id_[subscription_id]; |
| + |
| + if (app_id.empty()) { |
| + LOG(ERROR) << "Skipping message from unrecognized subscription " |
| + << subscription_id; |
| + return; |
| + } |
| + |
| + int message_count = messages.size(); |
| + std::vector<linked_ptr<api::copresence::Message> > api_messages( |
| + message_count); |
| + |
| + for (int m = 0; m < message_count; ++m) { |
| + api_messages[m].reset(new api::copresence::Message); |
| + api_messages[m]->type = messages[m].type().type(); |
| + api_messages[m]->payload = messages[m].payload(); |
| + DVLOG(2) << "Dispatching message of type " << api_messages[m]->type << ":\n" |
| + << api_messages[m]->payload; |
| + } |
| + |
| + // Send the messages to the client app. |
| + scoped_ptr<Event> event( |
| + new Event(api::copresence::OnMessagesReceived::kEventName, |
| + api::copresence::OnMessagesReceived::Create(subscription_id, |
| + api_messages), |
| + browser_context_)); |
| + EventRouter::Get(browser_context_) |
| + ->DispatchEventToExtension(app_id, event.Pass()); |
| + DVLOG(2) << "Passed " << api_messages.size() << " messages to app \"" |
| + << app_id << "\" for subscription \"" << subscription_id << "\""; |
| +} |
| + |
| +net::URLRequestContextGetter* CopresenceService::GetRequestContext() const { |
| + return browser_context_->GetRequestContext(); |
| +} |
| + |
| +const std::string CopresenceService::GetPlatformVersionString() const { |
| + return chrome::VersionInfo().CreateVersionString(); |
| +} |
| + |
| +copresence::WhispernetClient* CopresenceService::GetWhispernetClient() { |
| + return whispernet_client(); |
| +} |
| + |
| +template <> |
| +void |
| +BrowserContextKeyedAPIFactory<CopresenceService>::DeclareFactoryDependencies() { |
| + DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); |
| +} |
| + |
| +// CopresenceExecuteFunction implementation: |
| +ExtensionFunction::ResponseAction CopresenceExecuteFunction::Run() { |
| + scoped_ptr<api::copresence::Execute::Params> params( |
| + api::copresence::Execute::Params::Create(*args_)); |
| + EXTENSION_FUNCTION_VALIDATE(params.get()); |
| + |
| + // This can only happen if we're shutting down. In all other cases, if we |
| + // don't have a client, we'll create one. |
| + if (!GetCopresenceService(browser_context())->client()) |
| + return RespondNow(Error(kShuttingDownMessage)); |
| + |
| + SubscriptionToAppMap& apps_by_subscription_id = |
| + GetCopresenceService(browser_context())->apps_by_subscription_id(); |
| + |
| + // Each execute will correspond to one ReportRequest protocol buffer. |
| + copresence::ReportRequest request; |
| + if (!PrepareReportRequestProto(params->operations, |
| + extension_id(), |
| + &apps_by_subscription_id, |
| + &request)) { |
| + return RespondNow(Error(kInvalidOperationsMessage)); |
| + } |
| + |
| + GetCopresenceClient(browser_context())->ExecuteReportRequest( |
| + request, |
| + extension_id(), |
| + base::Bind(&CopresenceExecuteFunction::SendResult, this)); |
| + return RespondLater(); |
| +} |
| + |
| +void CopresenceExecuteFunction::SendResult( |
| + copresence::CopresenceStatus status) { |
| + api::copresence::ExecuteStatus api_status = |
| + (status == copresence::SUCCESS) ? api::copresence::EXECUTE_STATUS_SUCCESS |
| + : api::copresence::EXECUTE_STATUS_FAILED; |
| + Respond(ArgumentList(api::copresence::Execute::Results::Create(api_status))); |
| +} |
| + |
| +// CopresenceSetApiKeyFunction implementation: |
| +ExtensionFunction::ResponseAction CopresenceSetApiKeyFunction::Run() { |
| + scoped_ptr<api::copresence::SetApiKey::Params> params( |
| + api::copresence::SetApiKey::Params::Create(*args_)); |
| + EXTENSION_FUNCTION_VALIDATE(params.get()); |
| + |
| + // TODO(rkc): Use the API key set by this function for this app. |
| + // http://crbug.com/400617. |
| + return RespondNow(NoArguments()); |
| +} |
| + |
| +} // namespace extensions |