[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / invalidation / gcm_invalidation_bridge.cc
blob26c4c8df927cc40e57ac1d03c4f25e27de7ba98b
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 "base/bind.h"
6 #include "base/location.h"
7 #include "base/single_thread_task_runner.h"
8 #include "base/thread_task_runner_handle.h"
9 #include "chrome/browser/invalidation/gcm_invalidation_bridge.h"
10 #include "chrome/browser/services/gcm/gcm_driver.h"
11 #include "chrome/browser/signin/signin_manager_factory.h"
12 #include "components/signin/core/browser/profile_oauth2_token_service.h"
13 #include "components/signin/core/browser/signin_manager.h"
14 #include "google_apis/gaia/gaia_constants.h"
15 #include "google_apis/gaia/identity_provider.h"
17 namespace invalidation {
18 namespace {
19 // For 3rd party developers SenderId should come from application dashboard when
20 // server side application is registered with Google. Android invalidations use
21 // legacy format where gmail account can be specificed. Below value is copied
22 // from Android.
23 const char kInvalidationsSenderId[] = "ipc.invalidation@gmail.com";
24 // In Android world AppId is provided by operating system and should
25 // match package name and hash of application. In desktop world these values
26 // are arbitrary and not verified/enforced by registration service (yet).
27 const char kInvalidationsAppId[] = "com.google.chrome.invalidations";
29 // Cacheinvalidation specific gcm message keys.
30 const char kContentKey[] = "content";
31 const char kEchoTokenKey[] = "echo-token";
32 } // namespace
34 // Core should be very simple class that implements GCMNetwrokChannelDelegate
35 // and passes all calls to GCMInvalidationBridge. All calls should be serialized
36 // through GCMInvalidationBridge to avoid race conditions.
37 class GCMInvalidationBridge::Core : public syncer::GCMNetworkChannelDelegate,
38 public base::NonThreadSafe {
39 public:
40 Core(base::WeakPtr<GCMInvalidationBridge> bridge,
41 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner);
42 virtual ~Core();
44 // syncer::GCMNetworkChannelDelegate implementation.
45 virtual void Initialize() OVERRIDE;
46 virtual void RequestToken(RequestTokenCallback callback) OVERRIDE;
47 virtual void InvalidateToken(const std::string& token) OVERRIDE;
48 virtual void Register(RegisterCallback callback) OVERRIDE;
49 virtual void SetMessageReceiver(MessageCallback callback) OVERRIDE;
51 void RequestTokenFinished(RequestTokenCallback callback,
52 const GoogleServiceAuthError& error,
53 const std::string& token);
55 void RegisterFinished(RegisterCallback callback,
56 const std::string& registration_id,
57 gcm::GCMClient::Result result);
59 void OnIncomingMessage(const std::string& message,
60 const std::string& echo_token);
62 private:
63 base::WeakPtr<GCMInvalidationBridge> bridge_;
64 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_;
66 MessageCallback message_callback_;
68 base::WeakPtrFactory<Core> weak_factory_;
70 DISALLOW_COPY_AND_ASSIGN(Core);
73 GCMInvalidationBridge::Core::Core(
74 base::WeakPtr<GCMInvalidationBridge> bridge,
75 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
76 : bridge_(bridge),
77 ui_thread_task_runner_(ui_thread_task_runner),
78 weak_factory_(this) {
79 // Core is created on UI thread but all calls happen on IO thread.
80 DetachFromThread();
83 GCMInvalidationBridge::Core::~Core() {}
85 void GCMInvalidationBridge::Core::Initialize() {
86 DCHECK(CalledOnValidThread());
87 // Pass core WeapPtr and TaskRunner to GCMInvalidationBridge for it to be able
88 // to post back.
89 ui_thread_task_runner_->PostTask(
90 FROM_HERE,
91 base::Bind(&GCMInvalidationBridge::CoreInitializationDone,
92 bridge_,
93 weak_factory_.GetWeakPtr(),
94 base::ThreadTaskRunnerHandle::Get()));
97 void GCMInvalidationBridge::Core::RequestToken(RequestTokenCallback callback) {
98 DCHECK(CalledOnValidThread());
99 ui_thread_task_runner_->PostTask(
100 FROM_HERE,
101 base::Bind(&GCMInvalidationBridge::RequestToken, bridge_, callback));
104 void GCMInvalidationBridge::Core::InvalidateToken(const std::string& token) {
105 DCHECK(CalledOnValidThread());
106 ui_thread_task_runner_->PostTask(
107 FROM_HERE,
108 base::Bind(&GCMInvalidationBridge::InvalidateToken, bridge_, token));
111 void GCMInvalidationBridge::Core::Register(RegisterCallback callback) {
112 DCHECK(CalledOnValidThread());
113 ui_thread_task_runner_->PostTask(
114 FROM_HERE,
115 base::Bind(&GCMInvalidationBridge::Register, bridge_, callback));
118 void GCMInvalidationBridge::Core::SetMessageReceiver(MessageCallback callback) {
119 message_callback_ = callback;
120 ui_thread_task_runner_->PostTask(
121 FROM_HERE,
122 base::Bind(&GCMInvalidationBridge::SubscribeForIncomingMessages,
123 bridge_));
126 void GCMInvalidationBridge::Core::RequestTokenFinished(
127 RequestTokenCallback callback,
128 const GoogleServiceAuthError& error,
129 const std::string& token) {
130 DCHECK(CalledOnValidThread());
131 callback.Run(error, token);
134 void GCMInvalidationBridge::Core::RegisterFinished(
135 RegisterCallback callback,
136 const std::string& registration_id,
137 gcm::GCMClient::Result result) {
138 DCHECK(CalledOnValidThread());
139 callback.Run(registration_id, result);
142 void GCMInvalidationBridge::Core::OnIncomingMessage(
143 const std::string& message,
144 const std::string& echo_token) {
145 DCHECK(!message_callback_.is_null());
146 message_callback_.Run(message, echo_token);
149 GCMInvalidationBridge::GCMInvalidationBridge(
150 gcm::GCMDriver* gcm_driver,
151 IdentityProvider* identity_provider)
152 : OAuth2TokenService::Consumer("gcm_network_channel"),
153 gcm_driver_(gcm_driver),
154 identity_provider_(identity_provider),
155 subscribed_for_incoming_messages_(false),
156 weak_factory_(this) {}
158 GCMInvalidationBridge::~GCMInvalidationBridge() {
159 if (subscribed_for_incoming_messages_)
160 gcm_driver_->RemoveAppHandler(kInvalidationsAppId);
163 scoped_ptr<syncer::GCMNetworkChannelDelegate>
164 GCMInvalidationBridge::CreateDelegate() {
165 DCHECK(CalledOnValidThread());
166 scoped_ptr<syncer::GCMNetworkChannelDelegate> core(new Core(
167 weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get()));
168 return core.Pass();
171 void GCMInvalidationBridge::CoreInitializationDone(
172 base::WeakPtr<Core> core,
173 scoped_refptr<base::SingleThreadTaskRunner> core_thread_task_runner) {
174 DCHECK(CalledOnValidThread());
175 core_ = core;
176 core_thread_task_runner_ = core_thread_task_runner;
179 void GCMInvalidationBridge::RequestToken(
180 syncer::GCMNetworkChannelDelegate::RequestTokenCallback callback) {
181 DCHECK(CalledOnValidThread());
182 if (access_token_request_ != NULL) {
183 // Report previous request as cancelled.
184 GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
185 std::string access_token;
186 core_thread_task_runner_->PostTask(
187 FROM_HERE,
188 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished,
189 core_,
190 request_token_callback_,
191 error,
192 access_token));
194 request_token_callback_ = callback;
195 OAuth2TokenService::ScopeSet scopes;
196 scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
197 access_token_request_ = identity_provider_->GetTokenService()->StartRequest(
198 identity_provider_->GetActiveAccountId(), scopes, this);
201 void GCMInvalidationBridge::OnGetTokenSuccess(
202 const OAuth2TokenService::Request* request,
203 const std::string& access_token,
204 const base::Time& expiration_time) {
205 DCHECK(CalledOnValidThread());
206 DCHECK_EQ(access_token_request_, request);
207 core_thread_task_runner_->PostTask(
208 FROM_HERE,
209 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished,
210 core_,
211 request_token_callback_,
212 GoogleServiceAuthError::AuthErrorNone(),
213 access_token));
214 request_token_callback_.Reset();
215 access_token_request_.reset();
218 void GCMInvalidationBridge::OnGetTokenFailure(
219 const OAuth2TokenService::Request* request,
220 const GoogleServiceAuthError& error) {
221 DCHECK(CalledOnValidThread());
222 DCHECK_EQ(access_token_request_, request);
223 core_thread_task_runner_->PostTask(
224 FROM_HERE,
225 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished,
226 core_,
227 request_token_callback_,
228 error,
229 std::string()));
230 request_token_callback_.Reset();
231 access_token_request_.reset();
234 void GCMInvalidationBridge::InvalidateToken(const std::string& token) {
235 DCHECK(CalledOnValidThread());
236 OAuth2TokenService::ScopeSet scopes;
237 scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
238 identity_provider_->GetTokenService()->InvalidateToken(
239 identity_provider_->GetActiveAccountId(), scopes, token);
242 void GCMInvalidationBridge::Register(
243 syncer::GCMNetworkChannelDelegate::RegisterCallback callback) {
244 DCHECK(CalledOnValidThread());
245 // No-op if GCMClient is disabled.
246 if (gcm_driver_ == NULL)
247 return;
249 std::vector<std::string> sender_ids;
250 sender_ids.push_back(kInvalidationsSenderId);
251 gcm_driver_->Register(kInvalidationsAppId,
252 sender_ids,
253 base::Bind(&GCMInvalidationBridge::RegisterFinished,
254 weak_factory_.GetWeakPtr(),
255 callback));
258 void GCMInvalidationBridge::RegisterFinished(
259 syncer::GCMNetworkChannelDelegate::RegisterCallback callback,
260 const std::string& registration_id,
261 gcm::GCMClient::Result result) {
262 DCHECK(CalledOnValidThread());
263 core_thread_task_runner_->PostTask(
264 FROM_HERE,
265 base::Bind(&GCMInvalidationBridge::Core::RegisterFinished,
266 core_,
267 callback,
268 registration_id,
269 result));
272 void GCMInvalidationBridge::SubscribeForIncomingMessages() {
273 // No-op if GCMClient is disabled.
274 if (gcm_driver_ == NULL)
275 return;
277 DCHECK(!subscribed_for_incoming_messages_);
278 gcm_driver_->AddAppHandler(kInvalidationsAppId, this);
279 subscribed_for_incoming_messages_ = true;
282 void GCMInvalidationBridge::ShutdownHandler() {
283 // Nothing to do.
286 void GCMInvalidationBridge::OnMessage(
287 const std::string& app_id,
288 const gcm::GCMClient::IncomingMessage& message) {
289 gcm::GCMClient::MessageData::const_iterator it;
290 std::string content;
291 std::string echo_token;
292 it = message.data.find(kContentKey);
293 if (it != message.data.end())
294 content = it->second;
295 it = message.data.find(kEchoTokenKey);
296 if (it != message.data.end())
297 echo_token = it->second;
299 core_thread_task_runner_->PostTask(
300 FROM_HERE,
301 base::Bind(&GCMInvalidationBridge::Core::OnIncomingMessage,
302 core_,
303 content,
304 echo_token));
307 void GCMInvalidationBridge::OnMessagesDeleted(const std::string& app_id) {
308 // Cacheinvalidation doesn't use long lived non-collapsable messages with GCM.
309 // Android implementation of cacheinvalidation doesn't handle MessagesDeleted
310 // callback so this should be no-op in desktop version as well.
313 void GCMInvalidationBridge::OnSendError(
314 const std::string& app_id,
315 const gcm::GCMClient::SendErrorDetails& send_error_details) {
316 // cacheinvalidation doesn't send messages over GCM.
317 NOTREACHED();
320 } // namespace invalidation