| Index: chrome/browser/invalidation/gcm_invalidation_bridge.cc
|
| diff --git a/chrome/browser/invalidation/gcm_invalidation_bridge.cc b/chrome/browser/invalidation/gcm_invalidation_bridge.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..36747124110c4139c14b9a150594e0c319e05c13
|
| --- /dev/null
|
| +++ b/chrome/browser/invalidation/gcm_invalidation_bridge.cc
|
| @@ -0,0 +1,253 @@
|
| +// 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 "base/bind.h"
|
| +#include "base/location.h"
|
| +#include "base/single_thread_task_runner.h"
|
| +#include "base/thread_task_runner_handle.h"
|
| +#include "chrome/browser/invalidation/gcm_invalidation_bridge.h"
|
| +#include "chrome/browser/services/gcm/gcm_profile_service.h"
|
| +#include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
|
| +#include "chrome/browser/signin/profile_oauth2_token_service.h"
|
| +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
|
| +#include "chrome/browser/signin/signin_manager.h"
|
| +#include "chrome/browser/signin/signin_manager_factory.h"
|
| +#include "google_apis/gaia/gaia_constants.h"
|
| +
|
| +namespace invalidation {
|
| +namespace {
|
| +// For 3rd party developers SenderId should come from application dashboard when
|
| +// server side application is registered with Google. Android invalidations use
|
| +// legacy format where gmail account can be specificed. Below value is copied
|
| +// from Android.
|
| +const char kInvalidationsSenderId[] = "ipc.invalidation@gmail.com";
|
| +// In Android world AppId is provided by operating system and should
|
| +// match package name and hash of application. In desktop world these values
|
| +// are arbitrary and not verified/enforced by registration service (yet).
|
| +const char kInvalidationsAppId[] = "com.google.chrome.invalidations";
|
| +
|
| +} // namespace
|
| +
|
| +// Core should be very simple class that implements GCMNetwrokChannelDelegate
|
| +// and passes all calls to GCMInvalidationBridge. All calls should be serialized
|
| +// through GCMInvalidationBridge to avoid race conditions.
|
| +class GCMInvalidationBridge::Core : public syncer::GCMNetworkChannelDelegate,
|
| + public base::NonThreadSafe {
|
| + public:
|
| + Core(base::WeakPtr<GCMInvalidationBridge> bridge,
|
| + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner);
|
| + virtual ~Core();
|
| +
|
| + // syncer::GCMNetworkChannelDelegate implementation.
|
| + virtual void Initialize() OVERRIDE;
|
| + virtual void RequestToken(RequestTokenCallback callback) OVERRIDE;
|
| + virtual void InvalidateToken(const std::string& token) OVERRIDE;
|
| + virtual void Register(RegisterCallback callback) OVERRIDE;
|
| +
|
| + void RequestTokenFinished(RequestTokenCallback callback,
|
| + const GoogleServiceAuthError& error,
|
| + const std::string& token);
|
| +
|
| + void RegisterFinished(RegisterCallback callback,
|
| + const std::string& registration_id,
|
| + gcm::GCMClient::Result result);
|
| +
|
| + private:
|
| + base::WeakPtr<GCMInvalidationBridge> bridge_;
|
| + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_;
|
| +
|
| + base::WeakPtrFactory<Core> weak_factory_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Core);
|
| +};
|
| +
|
| +GCMInvalidationBridge::Core::Core(
|
| + base::WeakPtr<GCMInvalidationBridge> bridge,
|
| + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
|
| + : bridge_(bridge),
|
| + ui_thread_task_runner_(ui_thread_task_runner),
|
| + weak_factory_(this) {
|
| + // Core is created on UI thread but all calls happen on IO thread.
|
| + DetachFromThread();
|
| +}
|
| +
|
| +GCMInvalidationBridge::Core::~Core() {}
|
| +
|
| +void GCMInvalidationBridge::Core::Initialize() {
|
| + DCHECK(CalledOnValidThread());
|
| + // Pass core WeapPtr and TaskRunner to GCMInvalidationBridge for it to be able
|
| + // to post back.
|
| + ui_thread_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GCMInvalidationBridge::CoreInitializationDone,
|
| + bridge_,
|
| + weak_factory_.GetWeakPtr(),
|
| + base::ThreadTaskRunnerHandle::Get()));
|
| +}
|
| +
|
| +void GCMInvalidationBridge::Core::RequestToken(RequestTokenCallback callback) {
|
| + DCHECK(CalledOnValidThread());
|
| + ui_thread_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GCMInvalidationBridge::RequestToken, bridge_, callback));
|
| +}
|
| +
|
| +void GCMInvalidationBridge::Core::InvalidateToken(const std::string& token) {
|
| + DCHECK(CalledOnValidThread());
|
| + ui_thread_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GCMInvalidationBridge::InvalidateToken, bridge_, token));
|
| +}
|
| +
|
| +void GCMInvalidationBridge::Core::Register(RegisterCallback callback) {
|
| + DCHECK(CalledOnValidThread());
|
| + ui_thread_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GCMInvalidationBridge::Register, bridge_, callback));
|
| +}
|
| +
|
| +void GCMInvalidationBridge::Core::RequestTokenFinished(
|
| + RequestTokenCallback callback,
|
| + const GoogleServiceAuthError& error,
|
| + const std::string& token) {
|
| + DCHECK(CalledOnValidThread());
|
| + callback.Run(error, token);
|
| +}
|
| +
|
| +void GCMInvalidationBridge::Core::RegisterFinished(
|
| + RegisterCallback callback,
|
| + const std::string& registration_id,
|
| + gcm::GCMClient::Result result) {
|
| + DCHECK(CalledOnValidThread());
|
| + callback.Run(registration_id, result);
|
| +}
|
| +
|
| +GCMInvalidationBridge::GCMInvalidationBridge(Profile* profile)
|
| + : OAuth2TokenService::Consumer("gcm_network_channel"),
|
| + profile_(profile),
|
| + weak_factory_(this) {}
|
| +
|
| +GCMInvalidationBridge::~GCMInvalidationBridge() {}
|
| +
|
| +scoped_ptr<syncer::GCMNetworkChannelDelegate>
|
| +GCMInvalidationBridge::CreateDelegate() {
|
| + DCHECK(CalledOnValidThread());
|
| + scoped_ptr<syncer::GCMNetworkChannelDelegate> core(new Core(
|
| + weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get()));
|
| + return core.Pass();
|
| +}
|
| +
|
| +void GCMInvalidationBridge::CoreInitializationDone(
|
| + base::WeakPtr<Core> core,
|
| + scoped_refptr<base::SingleThreadTaskRunner> core_thread_task_runner) {
|
| + DCHECK(CalledOnValidThread());
|
| + core_ = core;
|
| + core_thread_task_runner_ = core_thread_task_runner;
|
| +}
|
| +
|
| +void GCMInvalidationBridge::RequestToken(
|
| + syncer::GCMNetworkChannelDelegate::RequestTokenCallback callback) {
|
| + DCHECK(CalledOnValidThread());
|
| + if (access_token_request_ != NULL) {
|
| + // Report previous request as cancelled.
|
| + GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
|
| + std::string access_token;
|
| + core_thread_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished,
|
| + core_,
|
| + request_token_callback_,
|
| + error,
|
| + access_token));
|
| + }
|
| + ProfileOAuth2TokenService* token_service =
|
| + ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
|
| + request_token_callback_ = callback;
|
| + SigninManagerBase* signin_manager =
|
| + SigninManagerFactory::GetForProfile(profile_);
|
| + std::string account_id = signin_manager->GetAuthenticatedAccountId();
|
| + OAuth2TokenService::ScopeSet scopes;
|
| + scopes.insert(GaiaConstants::kGoogleTalkOAuth2Scope);
|
| + access_token_request_ = token_service->StartRequest(account_id, scopes, this);
|
| +}
|
| +
|
| +void GCMInvalidationBridge::OnGetTokenSuccess(
|
| + const OAuth2TokenService::Request* request,
|
| + const std::string& access_token,
|
| + const base::Time& expiration_time) {
|
| + DCHECK(CalledOnValidThread());
|
| + DCHECK_EQ(access_token_request_, request);
|
| + core_thread_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished,
|
| + core_,
|
| + request_token_callback_,
|
| + GoogleServiceAuthError::AuthErrorNone(),
|
| + access_token));
|
| + request_token_callback_.Reset();
|
| + access_token_request_.reset();
|
| +}
|
| +
|
| +void GCMInvalidationBridge::OnGetTokenFailure(
|
| + const OAuth2TokenService::Request* request,
|
| + const GoogleServiceAuthError& error) {
|
| + DCHECK(CalledOnValidThread());
|
| + DCHECK_EQ(access_token_request_, request);
|
| + core_thread_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished,
|
| + core_,
|
| + request_token_callback_,
|
| + error,
|
| + std::string()));
|
| + request_token_callback_.Reset();
|
| + access_token_request_.reset();
|
| +}
|
| +
|
| +void GCMInvalidationBridge::InvalidateToken(const std::string& token) {
|
| + ProfileOAuth2TokenService* token_service =
|
| + ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
|
| + DCHECK(CalledOnValidThread());
|
| + SigninManagerBase* signin_manager =
|
| + SigninManagerFactory::GetForProfile(profile_);
|
| + std::string account_id = signin_manager->GetAuthenticatedAccountId();
|
| + OAuth2TokenService::ScopeSet scopes;
|
| + scopes.insert(GaiaConstants::kGoogleTalkOAuth2Scope);
|
| + token_service->InvalidateToken(account_id, scopes, token);
|
| +}
|
| +
|
| +void GCMInvalidationBridge::Register(
|
| + syncer::GCMNetworkChannelDelegate::RegisterCallback callback) {
|
| + DCHECK(CalledOnValidThread());
|
| + // No-op if GCMClient is disabled.
|
| + gcm::GCMProfileService* gcm_profile_service =
|
| + gcm::GCMProfileServiceFactory::GetForProfile(profile_);
|
| + if (gcm_profile_service == NULL)
|
| + return;
|
| +
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back(kInvalidationsSenderId);
|
| + gcm_profile_service->Register(
|
| + kInvalidationsAppId,
|
| + sender_ids,
|
| + base::Bind(&GCMInvalidationBridge::RegisterFinished,
|
| + weak_factory_.GetWeakPtr(),
|
| + callback));
|
| +}
|
| +
|
| +void GCMInvalidationBridge::RegisterFinished(
|
| + syncer::GCMNetworkChannelDelegate::RegisterCallback callback,
|
| + const std::string& registration_id,
|
| + gcm::GCMClient::Result result) {
|
| + DCHECK(CalledOnValidThread());
|
| + core_thread_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GCMInvalidationBridge::Core::RegisterFinished,
|
| + core_,
|
| + callback,
|
| + registration_id,
|
| + result));
|
| +}
|
| +
|
| +} // namespace invalidation
|
|
|