1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/bind.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/location.h" 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/single_thread_task_runner.h" 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/thread_task_runner_handle.h" 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/gcm_driver/gcm_driver.h" 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/invalidation/gcm_invalidation_bridge.h" 11effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/profile_oauth2_token_service.h" 12e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_manager.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "google_apis/gaia/gaia_constants.h" 140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "google_apis/gaia/identity_provider.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace invalidation { 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// For 3rd party developers SenderId should come from application dashboard when 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// server side application is registered with Google. Android invalidations use 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// legacy format where gmail account can be specificed. Below value is copied 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// from Android. 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kInvalidationsSenderId[] = "ipc.invalidation@gmail.com"; 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// In Android world AppId is provided by operating system and should 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// match package name and hash of application. In desktop world these values 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// are arbitrary and not verified/enforced by registration service (yet). 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kInvalidationsAppId[] = "com.google.chrome.invalidations"; 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Cacheinvalidation specific gcm message keys. 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kContentKey[] = "content"; 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kEchoTokenKey[] = "echo-token"; 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Core should be very simple class that implements GCMNetwrokChannelDelegate 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// and passes all calls to GCMInvalidationBridge. All calls should be serialized 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// through GCMInvalidationBridge to avoid race conditions. 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class GCMInvalidationBridge::Core : public syncer::GCMNetworkChannelDelegate, 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public base::NonThreadSafe { 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public: 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Core(base::WeakPtr<GCMInvalidationBridge> bridge, 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner); 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual ~Core(); 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // syncer::GCMNetworkChannelDelegate implementation. 446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) virtual void Initialize(ConnectionStateCallback callback) OVERRIDE; 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void RequestToken(RequestTokenCallback callback) OVERRIDE; 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void InvalidateToken(const std::string& token) OVERRIDE; 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void Register(RegisterCallback callback) OVERRIDE; 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void SetMessageReceiver(MessageCallback callback) OVERRIDE; 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void RequestTokenFinished(RequestTokenCallback callback, 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const GoogleServiceAuthError& error, 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& token); 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void RegisterFinished(RegisterCallback callback, 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& registration_id, 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gcm::GCMClient::Result result); 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OnIncomingMessage(const std::string& message, 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& echo_token); 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) void OnConnectionStateChanged(bool online); 626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private: 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WeakPtr<GCMInvalidationBridge> bridge_; 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_; 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MessageCallback message_callback_; 686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ConnectionStateCallback connection_state_callback_; 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WeakPtrFactory<Core> weak_factory_; 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Core); 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)GCMInvalidationBridge::Core::Core( 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WeakPtr<GCMInvalidationBridge> bridge, 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : bridge_(bridge), 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ui_thread_task_runner_(ui_thread_task_runner), 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_factory_(this) { 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Core is created on UI thread but all calls happen on IO thread. 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DetachFromThread(); 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)GCMInvalidationBridge::Core::~Core() {} 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void GCMInvalidationBridge::Core::Initialize(ConnectionStateCallback callback) { 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) connection_state_callback_ = callback; 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Pass core WeapPtr and TaskRunner to GCMInvalidationBridge for it to be able 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // to post back. 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ui_thread_task_runner_->PostTask( 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::CoreInitializationDone, 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bridge_, 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_factory_.GetWeakPtr(), 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::ThreadTaskRunnerHandle::Get())); 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::Core::RequestToken(RequestTokenCallback callback) { 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ui_thread_task_runner_->PostTask( 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::RequestToken, bridge_, callback)); 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::Core::InvalidateToken(const std::string& token) { 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ui_thread_task_runner_->PostTask( 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::InvalidateToken, bridge_, token)); 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::Core::Register(RegisterCallback callback) { 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ui_thread_task_runner_->PostTask( 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::Register, bridge_, callback)); 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::Core::SetMessageReceiver(MessageCallback callback) { 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) message_callback_ = callback; 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ui_thread_task_runner_->PostTask( 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::SubscribeForIncomingMessages, 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bridge_)); 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::Core::RequestTokenFinished( 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RequestTokenCallback callback, 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const GoogleServiceAuthError& error, 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& token) { 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) callback.Run(error, token); 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::Core::RegisterFinished( 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RegisterCallback callback, 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& registration_id, 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gcm::GCMClient::Result result) { 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) callback.Run(registration_id, result); 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::Core::OnIncomingMessage( 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& message, 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& echo_token) { 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!message_callback_.is_null()); 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) message_callback_.Run(message, echo_token); 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void GCMInvalidationBridge::Core::OnConnectionStateChanged(bool online) { 1536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!connection_state_callback_.is_null()) { 1546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) connection_state_callback_.Run(online); 1556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 1576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 15823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)GCMInvalidationBridge::GCMInvalidationBridge( 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gcm::GCMDriver* gcm_driver, 1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch IdentityProvider* identity_provider) 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : OAuth2TokenService::Consumer("gcm_network_channel"), 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gcm_driver_(gcm_driver), 1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider_(identity_provider), 164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch subscribed_for_incoming_messages_(false), 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_factory_(this) {} 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)GCMInvalidationBridge::~GCMInvalidationBridge() { 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (subscribed_for_incoming_messages_) { 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gcm_driver_->RemoveAppHandler(kInvalidationsAppId); 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gcm_driver_->RemoveConnectionObserver(this); 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<syncer::GCMNetworkChannelDelegate> 175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)GCMInvalidationBridge::CreateDelegate() { 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<syncer::GCMNetworkChannelDelegate> core(new Core( 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get())); 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return core.Pass(); 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::CoreInitializationDone( 183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WeakPtr<Core> core, 184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> core_thread_task_runner) { 185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_ = core; 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_thread_task_runner_ = core_thread_task_runner; 188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::RequestToken( 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) syncer::GCMNetworkChannelDelegate::RequestTokenCallback callback) { 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (access_token_request_ != NULL) { 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Report previous request as cancelled. 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string access_token; 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_thread_task_runner_->PostTask( 198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished, 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_, 201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_token_callback_, 202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) error, 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) access_token)); 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_token_callback_ = callback; 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OAuth2TokenService::ScopeSet scopes; 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope); 2080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch access_token_request_ = identity_provider_->GetTokenService()->StartRequest( 2090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider_->GetActiveAccountId(), scopes, this); 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::OnGetTokenSuccess( 213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const OAuth2TokenService::Request* request, 214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& access_token, 215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::Time& expiration_time) { 216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(access_token_request_, request); 218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_thread_task_runner_->PostTask( 219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished, 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_, 222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_token_callback_, 223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GoogleServiceAuthError::AuthErrorNone(), 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) access_token)); 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_token_callback_.Reset(); 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) access_token_request_.reset(); 227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::OnGetTokenFailure( 230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const OAuth2TokenService::Request* request, 231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const GoogleServiceAuthError& error) { 232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(access_token_request_, request); 234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_thread_task_runner_->PostTask( 235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished, 237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_, 238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_token_callback_, 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) error, 240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string())); 241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_token_callback_.Reset(); 242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) access_token_request_.reset(); 243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::InvalidateToken(const std::string& token) { 246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OAuth2TokenService::ScopeSet scopes; 248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope); 2490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider_->GetTokenService()->InvalidateToken( 2500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider_->GetActiveAccountId(), scopes, token); 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::Register( 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) syncer::GCMNetworkChannelDelegate::RegisterCallback callback) { 255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // No-op if GCMClient is disabled. 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (gcm_driver_ == NULL) 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<std::string> sender_ids; 261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sender_ids.push_back(kInvalidationsSenderId); 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gcm_driver_->Register(kInvalidationsAppId, 2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sender_ids, 2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::Bind(&GCMInvalidationBridge::RegisterFinished, 2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu weak_factory_.GetWeakPtr(), 2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu callback)); 267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::RegisterFinished( 270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) syncer::GCMNetworkChannelDelegate::RegisterCallback callback, 271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& registration_id, 272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gcm::GCMClient::Result result) { 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(CalledOnValidThread()); 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_thread_task_runner_->PostTask( 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::Core::RegisterFinished, 277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_, 278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) callback, 279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) registration_id, 280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) result)); 281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::SubscribeForIncomingMessages() { 284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // No-op if GCMClient is disabled. 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (gcm_driver_ == NULL) 286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!subscribed_for_incoming_messages_); 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gcm_driver_->AddAppHandler(kInvalidationsAppId, this); 2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gcm_driver_->AddConnectionObserver(this); 2916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) core_thread_task_runner_->PostTask( 2926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) FROM_HERE, 2936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::Core::OnConnectionStateChanged, 2946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) core_, 2956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) gcm_driver_->IsConnected())); 2966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) subscribed_for_incoming_messages_ = true; 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 30023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void GCMInvalidationBridge::ShutdownHandler() { 30123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Nothing to do. 30223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 30323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::OnMessage( 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& app_id, 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gcm::GCMClient::IncomingMessage& message) { 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gcm::GCMClient::MessageData::const_iterator it; 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string content; 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string echo_token; 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) it = message.data.find(kContentKey); 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (it != message.data.end()) 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) content = it->second; 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) it = message.data.find(kEchoTokenKey); 314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (it != message.data.end()) 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) echo_token = it->second; 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_thread_task_runner_->PostTask( 318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::Core::OnIncomingMessage, 320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) core_, 321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) content, 322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) echo_token)); 323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::OnMessagesDeleted(const std::string& app_id) { 326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Cacheinvalidation doesn't use long lived non-collapsable messages with GCM. 327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Android implementation of cacheinvalidation doesn't handle MessagesDeleted 328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // callback so this should be no-op in desktop version as well. 329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GCMInvalidationBridge::OnSendError( 332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& app_id, 333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gcm::GCMClient::SendErrorDetails& send_error_details) { 334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // cacheinvalidation doesn't send messages over GCM. 335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOTREACHED(); 336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void GCMInvalidationBridge::OnSendAcknowledged( 3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& app_id, 3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& message_id) { 3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // cacheinvalidation doesn't send messages over GCM. 3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NOTREACHED(); 3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GCMInvalidationBridge::OnConnected(const net::IPEndPoint& ip_endpoint) { 3466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) core_thread_task_runner_->PostTask( 3476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) FROM_HERE, 3486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) base::Bind( 3496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) &GCMInvalidationBridge::Core::OnConnectionStateChanged, core_, true)); 350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GCMInvalidationBridge::OnDisconnected() { 3536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) core_thread_task_runner_->PostTask( 3546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) FROM_HERE, 3556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) base::Bind(&GCMInvalidationBridge::Core::OnConnectionStateChanged, 3566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) core_, 3576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) false)); 358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace invalidation 362