Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Side by Side Diff: chrome/browser/services/gcm/gcm_service.cc

Issue 225403021: Extract Profile-independent GCMService from GCMProfileService (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments addressed. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/services/gcm/gcm_profile_service.h" 5 #include "chrome/browser/services/gcm/gcm_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <utility>
9 #include <vector>
10 9
11 #include "base/base64.h" 10 #include "base/bind.h"
12 #include "base/files/file_path.h" 11 #include "base/bind_helpers.h"
12 #include "base/location.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/path_service.h" 14 #include "base/sequenced_task_runner.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/threading/sequenced_worker_pool.h" 15 #include "base/threading/sequenced_worker_pool.h"
18 #include "chrome/browser/chrome_notification_types.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/services/gcm/gcm_app_handler.h" 16 #include "chrome/browser/services/gcm/gcm_app_handler.h"
21 #include "chrome/browser/services/gcm/gcm_client_factory.h" 17 #include "chrome/browser/services/gcm/gcm_client_factory.h"
22 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
23 #include "chrome/browser/signin/signin_manager_factory.h"
24 #include "chrome/common/chrome_constants.h"
25 #include "chrome/common/chrome_paths.h"
26 #include "chrome/common/chrome_version_info.h" 18 #include "chrome/common/chrome_version_info.h"
27 #include "chrome/common/pref_names.h"
28 #include "components/signin/core/browser/profile_oauth2_token_service.h"
29 #include "components/signin/core/browser/signin_manager.h"
30 #include "components/user_prefs/pref_registry_syncable.h"
31 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
32 #include "content/public/browser/notification_details.h" 20 #include "google_apis/gaia/oauth2_token_service.h"
33 #include "content/public/browser/notification_source.h"
34 #include "google_apis/gcm/protocol/android_checkin.pb.h" 21 #include "google_apis/gcm/protocol/android_checkin.pb.h"
35 #include "net/url_request/url_request_context_getter.h" 22 #include "net/url_request/url_request_context_getter.h"
36 23
37 namespace gcm { 24 namespace gcm {
38 25
39 namespace { 26 namespace {
40 27
41 checkin_proto::ChromeBuildProto_Platform GetPlatform() { 28 checkin_proto::ChromeBuildProto_Platform GetPlatform() {
42 #if defined(OS_WIN) 29 #if defined(OS_WIN)
43 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN; 30 return checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 return checkin_proto::ChromeBuildProto_Channel_CHANNEL_STABLE; 62 return checkin_proto::ChromeBuildProto_Channel_CHANNEL_STABLE;
76 default: 63 default:
77 NOTREACHED(); 64 NOTREACHED();
78 return checkin_proto::ChromeBuildProto_Channel_CHANNEL_UNKNOWN; 65 return checkin_proto::ChromeBuildProto_Channel_CHANNEL_UNKNOWN;
79 }; 66 };
80 } 67 }
81 68
82 } // namespace 69 } // namespace
83 70
84 // Helper class to save tasks to run until we're ready to execute them. 71 // Helper class to save tasks to run until we're ready to execute them.
85 class GCMProfileService::DelayedTaskController { 72 class GCMService::DelayedTaskController {
86 public: 73 public:
87 DelayedTaskController(); 74 DelayedTaskController();
88 ~DelayedTaskController(); 75 ~DelayedTaskController();
89 76
90 // Adds a task that will be invoked once we're ready. 77 // Adds a task that will be invoked once we're ready.
91 void AddTask(base::Closure task); 78 void AddTask(const base::Closure& task);
92 79
93 // Sets ready status. It is ready only when check-in is completed and 80 // Sets ready status. It is ready only when check-in is completed and
94 // the GCMClient is fully initialized. 81 // the GCMClient is fully initialized.
95 void SetReady(); 82 void SetReady();
96 83
97 // Returns true if it is ready to perform tasks. 84 // Returns true if it is ready to perform tasks.
98 bool CanRunTaskWithoutDelay() const; 85 bool CanRunTaskWithoutDelay() const;
99 86
100 private: 87 private:
101 void RunTasks(); 88 void RunTasks();
102 89
103 // Flag that indicates that GCM is ready. 90 // Flag that indicates that GCM is ready.
104 bool ready_; 91 bool ready_;
105 92
106 std::vector<base::Closure> delayed_tasks_; 93 std::vector<base::Closure> delayed_tasks_;
94
95 DISALLOW_COPY_AND_ASSIGN(DelayedTaskController);
107 }; 96 };
108 97
109 GCMProfileService::DelayedTaskController::DelayedTaskController() 98 GCMService::DelayedTaskController::DelayedTaskController() : ready_(false) {
110 : ready_(false) {
111 } 99 }
112 100
113 GCMProfileService::DelayedTaskController::~DelayedTaskController() { 101 GCMService::DelayedTaskController::~DelayedTaskController() {
114 } 102 }
115 103
116 void GCMProfileService::DelayedTaskController::AddTask(base::Closure task) { 104 void GCMService::DelayedTaskController::AddTask(const base::Closure& task) {
117 delayed_tasks_.push_back(task); 105 delayed_tasks_.push_back(task);
118 } 106 }
119 107
120 void GCMProfileService::DelayedTaskController::SetReady() { 108 void GCMService::DelayedTaskController::SetReady() {
121 ready_ = true; 109 ready_ = true;
122 RunTasks(); 110 RunTasks();
123 } 111 }
124 112
125 bool GCMProfileService::DelayedTaskController::CanRunTaskWithoutDelay() const { 113 bool GCMService::DelayedTaskController::CanRunTaskWithoutDelay() const {
126 return ready_; 114 return ready_;
127 } 115 }
128 116
129 void GCMProfileService::DelayedTaskController::RunTasks() { 117 void GCMService::DelayedTaskController::RunTasks() {
130 DCHECK(ready_); 118 DCHECK(ready_);
131 119
132 for (size_t i = 0; i < delayed_tasks_.size(); ++i) 120 for (size_t i = 0; i < delayed_tasks_.size(); ++i)
133 delayed_tasks_[i].Run(); 121 delayed_tasks_[i].Run();
134 delayed_tasks_.clear(); 122 delayed_tasks_.clear();
135 } 123 }
136 124
137 class GCMProfileService::IOWorker 125 class GCMService::IOWorker : public GCMClient::Delegate {
138 : public GCMClient::Delegate,
139 public base::RefCountedThreadSafe<GCMProfileService::IOWorker>{
140 public: 126 public:
141 // Called on UI thread. 127 // Called on UI thread.
142 IOWorker(); 128 IOWorker();
129 virtual ~IOWorker();
143 130
144 // Overridden from GCMClient::Delegate: 131 // Overridden from GCMClient::Delegate:
145 // Called on IO thread. 132 // Called on IO thread.
146 virtual void OnRegisterFinished(const std::string& app_id, 133 virtual void OnRegisterFinished(const std::string& app_id,
147 const std::string& registration_id, 134 const std::string& registration_id,
148 GCMClient::Result result) OVERRIDE; 135 GCMClient::Result result) OVERRIDE;
149 virtual void OnUnregisterFinished(const std::string& app_id, 136 virtual void OnUnregisterFinished(const std::string& app_id,
150 GCMClient::Result result) OVERRIDE; 137 GCMClient::Result result) OVERRIDE;
151 virtual void OnSendFinished(const std::string& app_id, 138 virtual void OnSendFinished(const std::string& app_id,
152 const std::string& message_id, 139 const std::string& message_id,
153 GCMClient::Result result) OVERRIDE; 140 GCMClient::Result result) OVERRIDE;
154 virtual void OnMessageReceived( 141 virtual void OnMessageReceived(
155 const std::string& app_id, 142 const std::string& app_id,
156 const GCMClient::IncomingMessage& message) OVERRIDE; 143 const GCMClient::IncomingMessage& message) OVERRIDE;
157 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE; 144 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
158 virtual void OnMessageSendError( 145 virtual void OnMessageSendError(
159 const std::string& app_id, 146 const std::string& app_id,
160 const GCMClient::SendErrorDetails& send_error_details) OVERRIDE; 147 const GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
161 virtual void OnGCMReady() OVERRIDE; 148 virtual void OnGCMReady() OVERRIDE;
162 149
163 // Called on IO thread. 150 // Called on IO thread.
164 void Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory, 151 void Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory,
165 const base::FilePath& store_path, 152 const base::FilePath& store_path,
166 const std::vector<std::string>& account_ids, 153 const std::vector<std::string>& account_ids,
167 const scoped_refptr<net::URLRequestContextGetter>& 154 const scoped_refptr<net::URLRequestContextGetter>&
168 url_request_context_getter); 155 url_request_context_getter);
169 void Reset(); 156 void Load(const base::WeakPtr<GCMService>& service);
170 void Load(const base::WeakPtr<GCMProfileService>& service);
171 void Stop(); 157 void Stop();
172 void CheckOut(); 158 void CheckOut();
173 void Register(const std::string& app_id, 159 void Register(const std::string& app_id,
174 const std::vector<std::string>& sender_ids); 160 const std::vector<std::string>& sender_ids);
175 void Unregister(const std::string& app_id); 161 void Unregister(const std::string& app_id);
176 void Send(const std::string& app_id, 162 void Send(const std::string& app_id,
177 const std::string& receiver_id, 163 const std::string& receiver_id,
178 const GCMClient::OutgoingMessage& message); 164 const GCMClient::OutgoingMessage& message);
179 void GetGCMStatistics(bool clear_logs); 165 void GetGCMStatistics(bool clear_logs);
180 void SetGCMRecording(bool recording); 166 void SetGCMRecording(bool recording);
181 167
182 // For testing purpose. Can be called from UI thread. Use with care. 168 // For testing purpose. Can be called from UI thread. Use with care.
183 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); } 169 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); }
184 170
185 private: 171 private:
186 friend class base::RefCountedThreadSafe<IOWorker>; 172 base::WeakPtr<GCMService> service_;
187 virtual ~IOWorker();
188
189 base::WeakPtr<GCMProfileService> service_;
190 173
191 scoped_ptr<GCMClient> gcm_client_; 174 scoped_ptr<GCMClient> gcm_client_;
175
176 DISALLOW_COPY_AND_ASSIGN(IOWorker);
192 }; 177 };
193 178
194 GCMProfileService::IOWorker::IOWorker() { 179 GCMService::IOWorker::IOWorker() {
195 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 180 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
196 } 181 }
197 182
198 GCMProfileService::IOWorker::~IOWorker() { 183 GCMService::IOWorker::~IOWorker() {
184 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
199 } 185 }
200 186
201 void GCMProfileService::IOWorker::Initialize( 187 void GCMService::IOWorker::Initialize(
202 scoped_ptr<GCMClientFactory> gcm_client_factory, 188 scoped_ptr<GCMClientFactory> gcm_client_factory,
203 const base::FilePath& store_path, 189 const base::FilePath& store_path,
204 const std::vector<std::string>& account_ids, 190 const std::vector<std::string>& account_ids,
205 const scoped_refptr<net::URLRequestContextGetter>& 191 const scoped_refptr<net::URLRequestContextGetter>&
206 url_request_context_getter) { 192 url_request_context_getter) {
207 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 193 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
208 194
209 gcm_client_ = gcm_client_factory->BuildInstance().Pass(); 195 gcm_client_ = gcm_client_factory->BuildInstance().Pass();
210 196
211 checkin_proto::ChromeBuildProto chrome_build_proto; 197 checkin_proto::ChromeBuildProto chrome_build_proto;
212 chrome_build_proto.set_platform(GetPlatform()); 198 chrome_build_proto.set_platform(GetPlatform());
213 chrome_build_proto.set_chrome_version(GetVersion()); 199 chrome_build_proto.set_chrome_version(GetVersion());
214 chrome_build_proto.set_channel(GetChannel()); 200 chrome_build_proto.set_channel(GetChannel());
215 201
216 scoped_refptr<base::SequencedWorkerPool> worker_pool( 202 scoped_refptr<base::SequencedWorkerPool> worker_pool(
217 content::BrowserThread::GetBlockingPool()); 203 content::BrowserThread::GetBlockingPool());
218 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( 204 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner(
219 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( 205 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
220 worker_pool->GetSequenceToken(), 206 worker_pool->GetSequenceToken(),
221 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 207 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
222 208
223 gcm_client_->Initialize(chrome_build_proto, 209 gcm_client_->Initialize(chrome_build_proto,
224 store_path, 210 store_path,
225 account_ids, 211 account_ids,
226 blocking_task_runner, 212 blocking_task_runner,
227 url_request_context_getter, 213 url_request_context_getter,
228 this); 214 this);
229 } 215 }
230 216
231 void GCMProfileService::IOWorker::Reset() { 217 void GCMService::IOWorker::OnRegisterFinished(
232 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
233
234 // GCMClient instance must be destroyed from the same thread where it was
235 // created.
236 gcm_client_.reset();
237 }
238
239 void GCMProfileService::IOWorker::OnRegisterFinished(
240 const std::string& app_id, 218 const std::string& app_id,
241 const std::string& registration_id, 219 const std::string& registration_id,
242 GCMClient::Result result) { 220 GCMClient::Result result) {
243 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 221 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
244 222
245 content::BrowserThread::PostTask( 223 content::BrowserThread::PostTask(content::BrowserThread::UI,
246 content::BrowserThread::UI, 224 FROM_HERE,
247 FROM_HERE, 225 base::Bind(&GCMService::RegisterFinished,
248 base::Bind(&GCMProfileService::RegisterFinished, 226 service_,
249 service_, 227 app_id,
250 app_id, 228 registration_id,
251 registration_id, 229 result));
252 result));
253 } 230 }
254 231
255 void GCMProfileService::IOWorker::OnUnregisterFinished( 232 void GCMService::IOWorker::OnUnregisterFinished(const std::string& app_id,
256 const std::string& app_id, 233 GCMClient::Result result) {
257 GCMClient::Result result) {
258 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 234 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
259 235
260 content::BrowserThread::PostTask( 236 content::BrowserThread::PostTask(
261 content::BrowserThread::UI, 237 content::BrowserThread::UI,
262 FROM_HERE, 238 FROM_HERE,
263 base::Bind( 239 base::Bind(&GCMService::UnregisterFinished, service_, app_id, result));
264 &GCMProfileService::UnregisterFinished, service_, app_id, result));
265 } 240 }
266 241
267 void GCMProfileService::IOWorker::OnSendFinished( 242 void GCMService::IOWorker::OnSendFinished(const std::string& app_id,
268 const std::string& app_id, 243 const std::string& message_id,
269 const std::string& message_id, 244 GCMClient::Result result) {
270 GCMClient::Result result) {
271 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 245 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
272 246
273 content::BrowserThread::PostTask( 247 content::BrowserThread::PostTask(content::BrowserThread::UI,
274 content::BrowserThread::UI, 248 FROM_HERE,
275 FROM_HERE, 249 base::Bind(&GCMService::SendFinished,
276 base::Bind(&GCMProfileService::SendFinished, 250 service_,
277 service_, 251 app_id,
278 app_id, 252 message_id,
279 message_id, 253 result));
280 result));
281 } 254 }
282 255
283 void GCMProfileService::IOWorker::OnMessageReceived( 256 void GCMService::IOWorker::OnMessageReceived(
284 const std::string& app_id, 257 const std::string& app_id,
285 const GCMClient::IncomingMessage& message) { 258 const GCMClient::IncomingMessage& message) {
286 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 259 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
287 260
288 content::BrowserThread::PostTask( 261 content::BrowserThread::PostTask(content::BrowserThread::UI,
289 content::BrowserThread::UI, 262 FROM_HERE,
290 FROM_HERE, 263 base::Bind(&GCMService::MessageReceived,
291 base::Bind(&GCMProfileService::MessageReceived, 264 service_,
292 service_, 265 app_id,
293 app_id, 266 message));
294 message));
295 } 267 }
296 268
297 void GCMProfileService::IOWorker::OnMessagesDeleted(const std::string& app_id) { 269 void GCMService::IOWorker::OnMessagesDeleted(const std::string& app_id) {
298 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 270 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
299 271
300 content::BrowserThread::PostTask( 272 content::BrowserThread::PostTask(content::BrowserThread::UI,
301 content::BrowserThread::UI, 273 FROM_HERE,
302 FROM_HERE, 274 base::Bind(&GCMService::MessagesDeleted,
303 base::Bind(&GCMProfileService::MessagesDeleted, 275 service_,
304 service_, 276 app_id));
305 app_id));
306 } 277 }
307 278
308 void GCMProfileService::IOWorker::OnMessageSendError( 279 void GCMService::IOWorker::OnMessageSendError(
309 const std::string& app_id, 280 const std::string& app_id,
310 const GCMClient::SendErrorDetails& send_error_details) { 281 const GCMClient::SendErrorDetails& send_error_details) {
311 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 282 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
312 283
313 content::BrowserThread::PostTask( 284 content::BrowserThread::PostTask(content::BrowserThread::UI,
314 content::BrowserThread::UI, 285 FROM_HERE,
315 FROM_HERE, 286 base::Bind(&GCMService::MessageSendError,
316 base::Bind(&GCMProfileService::MessageSendError, 287 service_,
317 service_, 288 app_id,
318 app_id, 289 send_error_details));
319 send_error_details));
320 } 290 }
321 291
322 void GCMProfileService::IOWorker::OnGCMReady() { 292 void GCMService::IOWorker::OnGCMReady() {
323 content::BrowserThread::PostTask( 293 content::BrowserThread::PostTask(content::BrowserThread::UI,
324 content::BrowserThread::UI, 294 FROM_HERE,
325 FROM_HERE, 295 base::Bind(&GCMService::GCMClientReady,
326 base::Bind(&GCMProfileService::GCMClientReady, 296 service_));
327 service_));
328 } 297 }
329 298
330 void GCMProfileService::IOWorker::Load( 299 void GCMService::IOWorker::Load(const base::WeakPtr<GCMService>& service) {
331 const base::WeakPtr<GCMProfileService>& service) {
332 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 300 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
333 301
334 service_ = service; 302 service_ = service;
335 gcm_client_->Load(); 303 gcm_client_->Load();
336 } 304 }
337 305
338 void GCMProfileService::IOWorker::Stop() { 306 void GCMService::IOWorker::Stop() {
339 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 307 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
340 308
341 gcm_client_->Stop(); 309 gcm_client_->Stop();
342 } 310 }
343 311
344 void GCMProfileService::IOWorker::CheckOut() { 312 void GCMService::IOWorker::CheckOut() {
345 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 313 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
346 314
347 gcm_client_->CheckOut(); 315 gcm_client_->CheckOut();
348 316
349 // Note that we still need to keep GCMClient instance alive since the profile 317 // Note that we still need to keep GCMClient instance alive since the
350 // might be signed in again. 318 // GCMService may check in again.
351 } 319 }
352 320
353 void GCMProfileService::IOWorker::Register( 321 void GCMService::IOWorker::Register(
354 const std::string& app_id, 322 const std::string& app_id,
355 const std::vector<std::string>& sender_ids) { 323 const std::vector<std::string>& sender_ids) {
356 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 324 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
357 325
358 gcm_client_->Register(app_id, sender_ids); 326 gcm_client_->Register(app_id, sender_ids);
359 } 327 }
360 328
361 void GCMProfileService::IOWorker::Unregister(const std::string& app_id) { 329 void GCMService::IOWorker::Unregister(const std::string& app_id) {
362 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 330 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
363 331
364 gcm_client_->Unregister(app_id); 332 gcm_client_->Unregister(app_id);
365 } 333 }
366 334
367 void GCMProfileService::IOWorker::Send( 335 void GCMService::IOWorker::Send(const std::string& app_id,
368 const std::string& app_id, 336 const std::string& receiver_id,
369 const std::string& receiver_id, 337 const GCMClient::OutgoingMessage& message) {
370 const GCMClient::OutgoingMessage& message) {
371 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 338 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
372 339
373 gcm_client_->Send(app_id, receiver_id, message); 340 gcm_client_->Send(app_id, receiver_id, message);
374 } 341 }
375 342
376 void GCMProfileService::IOWorker::GetGCMStatistics(bool clear_logs) { 343 void GCMService::IOWorker::GetGCMStatistics(bool clear_logs) {
377 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 344 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
378 gcm::GCMClient::GCMStatistics stats; 345 gcm::GCMClient::GCMStatistics stats;
379 346
380 if (gcm_client_.get()) { 347 if (gcm_client_.get()) {
381 if (clear_logs) 348 if (clear_logs)
382 gcm_client_->ClearActivityLogs(); 349 gcm_client_->ClearActivityLogs();
383 stats = gcm_client_->GetStatistics(); 350 stats = gcm_client_->GetStatistics();
384 } 351 }
385 352
386 content::BrowserThread::PostTask( 353 content::BrowserThread::PostTask(
387 content::BrowserThread::UI, 354 content::BrowserThread::UI,
388 FROM_HERE, 355 FROM_HERE,
389 base::Bind(&GCMProfileService::GetGCMStatisticsFinished, 356 base::Bind(&GCMService::GetGCMStatisticsFinished, service_, stats));
390 service_,
391 stats));
392 } 357 }
393 358
394 void GCMProfileService::IOWorker::SetGCMRecording(bool recording) { 359 void GCMService::IOWorker::SetGCMRecording(bool recording) {
395 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 360 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
396 gcm::GCMClient::GCMStatistics stats; 361 gcm::GCMClient::GCMStatistics stats;
397 362
398 if (gcm_client_.get()) { 363 if (gcm_client_.get()) {
399 gcm_client_->SetRecording(recording); 364 gcm_client_->SetRecording(recording);
400 stats = gcm_client_->GetStatistics(); 365 stats = gcm_client_->GetStatistics();
401 stats.gcm_client_created = true; 366 stats.gcm_client_created = true;
402 } 367 }
403 368
404 content::BrowserThread::PostTask( 369 content::BrowserThread::PostTask(
405 content::BrowserThread::UI, 370 content::BrowserThread::UI,
406 FROM_HERE, 371 FROM_HERE,
407 base::Bind(&GCMProfileService::GetGCMStatisticsFinished, 372 base::Bind(&GCMService::GetGCMStatisticsFinished, service_, stats));
408 service_,
409 stats));
410 } 373 }
411 374
412 std::string GCMProfileService::GetGCMEnabledStateString(GCMEnabledState state) { 375 GCMService::GCMService(scoped_ptr<IdentityProvider> identity_provider)
413 switch (state) { 376 : identity_provider_(identity_provider.Pass()),
414 case GCMProfileService::ALWAYS_ENABLED: 377 gcm_client_ready_(false),
415 return "ALWAYS_ENABLED"; 378 weak_ptr_factory_(this) {
416 case GCMProfileService::ENABLED_FOR_APPS:
417 return "ENABLED_FOR_APPS";
418 case GCMProfileService::ALWAYS_DISABLED:
419 return "ALWAYS_DISABLED";
420 default:
421 NOTREACHED();
422 return std::string();
423 }
424 } 379 }
425 380
426 // static 381 GCMService::~GCMService() {
427 GCMProfileService::GCMEnabledState GCMProfileService::GetGCMEnabledState(
428 Profile* profile) {
429 const base::Value* gcm_enabled_value =
430 profile->GetPrefs()->GetUserPrefValue(prefs::kGCMChannelEnabled);
431 if (!gcm_enabled_value)
432 return ENABLED_FOR_APPS;
433
434 bool gcm_enabled = false;
435 if (!gcm_enabled_value->GetAsBoolean(&gcm_enabled))
436 return ENABLED_FOR_APPS;
437
438 return gcm_enabled ? ALWAYS_ENABLED : ALWAYS_DISABLED;
439 } 382 }
440 383
441 // static 384 void GCMService::Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory) {
442 void GCMProfileService::RegisterProfilePrefs(
443 user_prefs::PrefRegistrySyncable* registry) {
444 // GCM support is only enabled by default for Canary/Dev/Custom builds.
445 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
446 bool on_by_default = false;
447 if (channel == chrome::VersionInfo::CHANNEL_UNKNOWN ||
448 channel == chrome::VersionInfo::CHANNEL_CANARY ||
449 channel == chrome::VersionInfo::CHANNEL_DEV) {
450 on_by_default = true;
451 }
452 registry->RegisterBooleanPref(
453 prefs::kGCMChannelEnabled,
454 on_by_default,
455 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
456 }
457
458 GCMProfileService::GCMProfileService(Profile* profile)
459 : profile_(profile),
460 gcm_client_ready_(false),
461 weak_ptr_factory_(this) {
462 DCHECK(!profile->IsOffTheRecord());
463 }
464
465 GCMProfileService::~GCMProfileService() {
466 }
467
468 void GCMProfileService::Initialize(
469 scoped_ptr<GCMClientFactory> gcm_client_factory) {
470 registrar_.Add(this,
471 chrome::NOTIFICATION_PROFILE_DESTROYED,
472 content::Source<Profile>(profile_));
473
474 SigninManagerFactory::GetForProfile(profile_)->AddObserver(this);
475
476 // Get the list of available accounts. 385 // Get the list of available accounts.
477 std::vector<std::string> account_ids; 386 std::vector<std::string> account_ids;
478 #if !defined(OS_ANDROID) 387 #if !defined(OS_ANDROID)
479 account_ids = 388 account_ids = identity_provider_->GetTokenService()->GetAccounts();
480 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->GetAccounts();
481 #endif 389 #endif
482 390
483 // Create and initialize the GCMClient. Note that this does not initiate the 391 // Create and initialize the GCMClient. Note that this does not initiate the
484 // GCM check-in. 392 // GCM check-in.
485 io_worker_ = new IOWorker(); 393 DCHECK(!io_worker_);
486 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter = 394 io_worker_.reset(new IOWorker());
487 profile_->GetRequestContext();
488 content::BrowserThread::PostTask( 395 content::BrowserThread::PostTask(
489 content::BrowserThread::IO, 396 content::BrowserThread::IO,
490 FROM_HERE, 397 FROM_HERE,
491 base::Bind(&GCMProfileService::IOWorker::Initialize, 398 base::Bind(&GCMService::IOWorker::Initialize,
492 io_worker_, 399 base::Unretained(io_worker_.get()),
493 base::Passed(&gcm_client_factory), 400 base::Passed(&gcm_client_factory),
494 profile_->GetPath().Append(chrome::kGCMStoreDirname), 401 GetStorePath(),
495 account_ids, 402 account_ids,
496 url_request_context_getter)); 403 GetURLRequestContextGetter()));
497 404
498 // Load from the GCM store and initiate the GCM check-in if the rollout signal 405 // Load from the GCM store and initiate the GCM check-in if the rollout signal
499 // indicates yes. 406 // indicates yes.
500 if (GetGCMEnabledState(profile_) == ALWAYS_ENABLED) 407 if (ShouldStartAutomatically())
501 EnsureLoaded(); 408 EnsureLoaded();
409
410 identity_provider_->AddObserver(this);
502 } 411 }
503 412
504 void GCMProfileService::Start() { 413 void GCMService::Start() {
505 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 414 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
506 415
507 EnsureLoaded(); 416 EnsureLoaded();
508 } 417 }
509 418
510 void GCMProfileService::Stop() { 419 void GCMService::Stop() {
511 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 420 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
512 421
513 // No need to stop GCM service if not started yet. 422 // No need to stop GCM service if not started yet.
514 if (username_.empty()) 423 if (account_id_.empty())
515 return; 424 return;
516 425
517 RemoveCachedData(); 426 RemoveCachedData();
518 427
519 content::BrowserThread::PostTask( 428 content::BrowserThread::PostTask(
520 content::BrowserThread::IO, 429 content::BrowserThread::IO,
521 FROM_HERE, 430 FROM_HERE,
522 base::Bind(&GCMProfileService::IOWorker::Stop, io_worker_)); 431 base::Bind(&GCMService::IOWorker::Stop,
432 base::Unretained(io_worker_.get())));
523 } 433 }
524 434
525 void GCMProfileService::Shutdown() { 435 void GCMService::ShutdownService() {
436 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
437 identity_provider_->RemoveObserver(this);
526 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin(); 438 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin();
527 iter != app_handlers_.end(); ++iter) { 439 iter != app_handlers_.end(); ++iter) {
528 iter->second->ShutdownHandler(); 440 iter->second->ShutdownHandler();
529 } 441 }
530 app_handlers_.clear(); 442 app_handlers_.clear();
531 443 content::BrowserThread::DeleteSoon(content::BrowserThread::IO,
532 SigninManagerFactory::GetForProfile(profile_)->RemoveObserver(this); 444 FROM_HERE,
445 io_worker_.release());
533 } 446 }
534 447
535 void GCMProfileService::AddAppHandler(const std::string& app_id, 448 void GCMService::AddAppHandler(const std::string& app_id,
536 GCMAppHandler* handler) { 449 GCMAppHandler* handler) {
450 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
537 DCHECK(!app_id.empty()); 451 DCHECK(!app_id.empty());
538 DCHECK(handler); 452 DCHECK(handler);
539 DCHECK(app_handlers_.find(app_id) == app_handlers_.end()); 453 DCHECK(app_handlers_.find(app_id) == app_handlers_.end());
540 454
541 app_handlers_[app_id] = handler; 455 app_handlers_[app_id] = handler;
542 } 456 }
543 457
544 void GCMProfileService::RemoveAppHandler(const std::string& app_id) { 458 void GCMService::RemoveAppHandler(const std::string& app_id) {
459 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
545 DCHECK(!app_id.empty()); 460 DCHECK(!app_id.empty());
546 461
547 app_handlers_.erase(app_id); 462 app_handlers_.erase(app_id);
548 } 463 }
549 464
550 void GCMProfileService::Register(const std::string& app_id, 465 void GCMService::Register(const std::string& app_id,
551 const std::vector<std::string>& sender_ids, 466 const std::vector<std::string>& sender_ids,
552 RegisterCallback callback) { 467 RegisterCallback callback) {
553 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 468 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
554 DCHECK(!app_id.empty() && !sender_ids.empty() && !callback.is_null()); 469 DCHECK(!app_id.empty());
470 DCHECK(!sender_ids.empty());
471 DCHECK(!callback.is_null());
555 472
556 GCMClient::Result result = EnsureAppReady(app_id); 473 GCMClient::Result result = EnsureAppReady(app_id);
557 if (result != GCMClient::SUCCESS) { 474 if (result != GCMClient::SUCCESS) {
558 callback.Run(std::string(), result); 475 callback.Run(std::string(), result);
559 return; 476 return;
560 } 477 }
561 478
562 // If previous un/register operation is still in progress, bail out. 479 // If previous un/register operation is still in progress, bail out.
563 if (IsAsyncOperationPending(app_id)) { 480 if (IsAsyncOperationPending(app_id)) {
564 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); 481 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
565 return; 482 return;
566 } 483 }
567 484
568 register_callbacks_[app_id] = callback; 485 register_callbacks_[app_id] = callback;
569 486
570 // Delay the register operation until GCMClient is ready. 487 // Delay the register operation until GCMClient is ready.
571 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 488 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
572 delayed_task_controller_->AddTask( 489 delayed_task_controller_->AddTask(base::Bind(&GCMService::DoRegister,
573 base::Bind(&GCMProfileService::DoRegister, 490 weak_ptr_factory_.GetWeakPtr(),
574 weak_ptr_factory_.GetWeakPtr(), 491 app_id,
575 app_id, 492 sender_ids));
576 sender_ids));
577 return; 493 return;
578 } 494 }
579 495
580 DoRegister(app_id, sender_ids); 496 DoRegister(app_id, sender_ids);
581 } 497 }
582 498
583 void GCMProfileService::DoRegister(const std::string& app_id, 499 void GCMService::DoRegister(const std::string& app_id,
584 const std::vector<std::string>& sender_ids) { 500 const std::vector<std::string>& sender_ids) {
501 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
585 std::map<std::string, RegisterCallback>::iterator callback_iter = 502 std::map<std::string, RegisterCallback>::iterator callback_iter =
586 register_callbacks_.find(app_id); 503 register_callbacks_.find(app_id);
587 if (callback_iter == register_callbacks_.end()) { 504 if (callback_iter == register_callbacks_.end()) {
588 // The callback could have been removed when the app is uninstalled. 505 // The callback could have been removed when the app is uninstalled.
589 return; 506 return;
590 } 507 }
591 508
592 // Normalize the sender IDs by making them sorted. 509 // Normalize the sender IDs by making them sorted.
593 std::vector<std::string> normalized_sender_ids = sender_ids; 510 std::vector<std::string> normalized_sender_ids = sender_ids;
594 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end()); 511 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
595 512
596 content::BrowserThread::PostTask( 513 content::BrowserThread::PostTask(
597 content::BrowserThread::IO, 514 content::BrowserThread::IO,
598 FROM_HERE, 515 FROM_HERE,
599 base::Bind(&GCMProfileService::IOWorker::Register, 516 base::Bind(&GCMService::IOWorker::Register,
600 io_worker_, 517 base::Unretained(io_worker_.get()),
601 app_id, 518 app_id,
602 normalized_sender_ids)); 519 normalized_sender_ids));
603 } 520 }
604 521
605 void GCMProfileService::Unregister(const std::string& app_id, 522 void GCMService::Unregister(const std::string& app_id,
606 UnregisterCallback callback) { 523 UnregisterCallback callback) {
607 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 524 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
608 DCHECK(!app_id.empty() && !callback.is_null()); 525 DCHECK(!app_id.empty());
526 DCHECK(!callback.is_null());
609 527
610 GCMClient::Result result = EnsureAppReady(app_id); 528 GCMClient::Result result = EnsureAppReady(app_id);
611 if (result != GCMClient::SUCCESS) { 529 if (result != GCMClient::SUCCESS) {
612 callback.Run(result); 530 callback.Run(result);
613 return; 531 return;
614 } 532 }
615 533
616 // If previous un/register operation is still in progress, bail out. 534 // If previous un/register operation is still in progress, bail out.
617 if (IsAsyncOperationPending(app_id)) { 535 if (IsAsyncOperationPending(app_id)) {
618 callback.Run(GCMClient::ASYNC_OPERATION_PENDING); 536 callback.Run(GCMClient::ASYNC_OPERATION_PENDING);
619 return; 537 return;
620 } 538 }
621 539
622 unregister_callbacks_[app_id] = callback; 540 unregister_callbacks_[app_id] = callback;
623 541
624 // Delay the unregister operation until GCMClient is ready. 542 // Delay the unregister operation until GCMClient is ready.
625 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 543 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
626 delayed_task_controller_->AddTask( 544 delayed_task_controller_->AddTask(base::Bind(&GCMService::DoUnregister,
627 base::Bind(&GCMProfileService::DoUnregister, 545 weak_ptr_factory_.GetWeakPtr(),
628 weak_ptr_factory_.GetWeakPtr(), 546 app_id));
629 app_id));
630 return; 547 return;
631 } 548 }
632 549
633 DoUnregister(app_id); 550 DoUnregister(app_id);
634 } 551 }
635 552
636 void GCMProfileService::DoUnregister(const std::string& app_id) { 553 void GCMService::DoUnregister(const std::string& app_id) {
637 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 554 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
638 555
639 // Ask the server to unregister it. There could be a small chance that the 556 // Ask the server to unregister it. There could be a small chance that the
640 // unregister request fails. If this occurs, it does not bring any harm since 557 // unregister request fails. If this occurs, it does not bring any harm since
641 // we simply reject the messages/events received from the server. 558 // we simply reject the messages/events received from the server.
642 content::BrowserThread::PostTask( 559 content::BrowserThread::PostTask(
643 content::BrowserThread::IO, 560 content::BrowserThread::IO,
644 FROM_HERE, 561 FROM_HERE,
645 base::Bind(&GCMProfileService::IOWorker::Unregister, 562 base::Bind(&GCMService::IOWorker::Unregister,
646 io_worker_, 563 base::Unretained(io_worker_.get()),
647 app_id)); 564 app_id));
648 } 565 }
649 566
650 void GCMProfileService::Send(const std::string& app_id, 567 void GCMService::Send(const std::string& app_id,
651 const std::string& receiver_id, 568 const std::string& receiver_id,
652 const GCMClient::OutgoingMessage& message, 569 const GCMClient::OutgoingMessage& message,
653 SendCallback callback) { 570 SendCallback callback) {
654 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 571 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
655 DCHECK(!app_id.empty() && !receiver_id.empty() && !callback.is_null()); 572 DCHECK(!app_id.empty());
573 DCHECK(!receiver_id.empty());
574 DCHECK(!callback.is_null());
656 575
657 GCMClient::Result result = EnsureAppReady(app_id); 576 GCMClient::Result result = EnsureAppReady(app_id);
658 if (result != GCMClient::SUCCESS) { 577 if (result != GCMClient::SUCCESS) {
659 callback.Run(std::string(), result); 578 callback.Run(std::string(), result);
660 return; 579 return;
661 } 580 }
662 581
663 // If the message with send ID is still in progress, bail out. 582 // If the message with send ID is still in progress, bail out.
664 std::pair<std::string, std::string> key(app_id, message.id); 583 std::pair<std::string, std::string> key(app_id, message.id);
665 if (send_callbacks_.find(key) != send_callbacks_.end()) { 584 if (send_callbacks_.find(key) != send_callbacks_.end()) {
666 callback.Run(message.id, GCMClient::INVALID_PARAMETER); 585 callback.Run(message.id, GCMClient::INVALID_PARAMETER);
667 return; 586 return;
668 } 587 }
669 588
670 send_callbacks_[key] = callback; 589 send_callbacks_[key] = callback;
671 590
672 // Delay the send operation until all GCMClient is ready. 591 // Delay the send operation until all GCMClient is ready.
673 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 592 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
674 delayed_task_controller_->AddTask( 593 delayed_task_controller_->AddTask(base::Bind(&GCMService::DoSend,
675 base::Bind(&GCMProfileService::DoSend, 594 weak_ptr_factory_.GetWeakPtr(),
676 weak_ptr_factory_.GetWeakPtr(), 595 app_id,
677 app_id, 596 receiver_id,
678 receiver_id, 597 message));
679 message));
680 return; 598 return;
681 } 599 }
682 600
683 DoSend(app_id, receiver_id, message); 601 DoSend(app_id, receiver_id, message);
684 } 602 }
685 603
686 void GCMProfileService::DoSend(const std::string& app_id, 604 void GCMService::DoSend(const std::string& app_id,
687 const std::string& receiver_id, 605 const std::string& receiver_id,
688 const GCMClient::OutgoingMessage& message) { 606 const GCMClient::OutgoingMessage& message) {
607 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
689 content::BrowserThread::PostTask( 608 content::BrowserThread::PostTask(
690 content::BrowserThread::IO, 609 content::BrowserThread::IO,
691 FROM_HERE, 610 FROM_HERE,
692 base::Bind(&GCMProfileService::IOWorker::Send, 611 base::Bind(&GCMService::IOWorker::Send,
693 io_worker_, 612 base::Unretained(io_worker_.get()),
694 app_id, 613 app_id,
695 receiver_id, 614 receiver_id,
696 message)); 615 message));
697 } 616 }
698 617
699 GCMClient* GCMProfileService::GetGCMClientForTesting() const { 618 GCMClient* GCMService::GetGCMClientForTesting() const {
619 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
700 return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL; 620 return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL;
701 } 621 }
702 622
703 std::string GCMProfileService::SignedInUserName() const { 623 bool GCMService::IsStarted() const {
704 return username_; 624 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
625 return !account_id_.empty();
705 } 626 }
706 627
707 bool GCMProfileService::IsGCMClientReady() const { 628 bool GCMService::IsGCMClientReady() const {
629 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
708 return gcm_client_ready_; 630 return gcm_client_ready_;
709 } 631 }
710 632
711 void GCMProfileService::GetGCMStatistics( 633 void GCMService::GetGCMStatistics(GetGCMStatisticsCallback callback,
712 GetGCMStatisticsCallback callback, bool clear_logs) { 634 bool clear_logs) {
713 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 635 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
714 DCHECK(!callback.is_null()); 636 DCHECK(!callback.is_null());
715 637
716 request_gcm_statistics_callback_ = callback; 638 request_gcm_statistics_callback_ = callback;
717 content::BrowserThread::PostTask( 639 content::BrowserThread::PostTask(
718 content::BrowserThread::IO, 640 content::BrowserThread::IO,
719 FROM_HERE, 641 FROM_HERE,
720 base::Bind(&GCMProfileService::IOWorker::GetGCMStatistics, 642 base::Bind(&GCMService::IOWorker::GetGCMStatistics,
721 io_worker_, 643 base::Unretained(io_worker_.get()),
722 clear_logs)); 644 clear_logs));
723 } 645 }
724 646
725 void GCMProfileService::SetGCMRecording( 647 void GCMService::SetGCMRecording(GetGCMStatisticsCallback callback,
726 GetGCMStatisticsCallback callback, bool recording) { 648 bool recording) {
727 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 649 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
728 650
729 request_gcm_statistics_callback_ = callback; 651 request_gcm_statistics_callback_ = callback;
730 content::BrowserThread::PostTask( 652 content::BrowserThread::PostTask(
731 content::BrowserThread::IO, 653 content::BrowserThread::IO,
732 FROM_HERE, 654 FROM_HERE,
733 base::Bind(&GCMProfileService::IOWorker::SetGCMRecording, 655 base::Bind(&GCMService::IOWorker::SetGCMRecording,
734 io_worker_, 656 base::Unretained(io_worker_.get()),
735 recording)); 657 recording));
736 } 658 }
737 659
738 void GCMProfileService::Observe(int type, 660 void GCMService::OnActiveAccountLogin() {
739 const content::NotificationSource& source, 661 if (ShouldStartAutomatically())
740 const content::NotificationDetails& details) {
741 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
742
743 switch (type) {
744 case chrome::NOTIFICATION_PROFILE_DESTROYED:
745 ResetGCMClient();
746 break;
747 default:
748 NOTREACHED();
749 }
750 }
751
752 void GCMProfileService::GoogleSigninSucceeded(const std::string& username,
753 const std::string& password) {
754 if (GetGCMEnabledState(profile_) == ALWAYS_ENABLED)
755 EnsureLoaded(); 662 EnsureLoaded();
756 } 663 }
757 664
758 void GCMProfileService::GoogleSignedOut(const std::string& username) { 665 void GCMService::OnActiveAccountLogout() {
759 CheckOut(); 666 CheckOut();
760 } 667 }
761 668
762 void GCMProfileService::EnsureLoaded() { 669 void GCMService::EnsureLoaded() {
763 SigninManagerBase* manager = SigninManagerFactory::GetForProfile(profile_); 670 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
764 if (!manager) 671 const std::string account_id = identity_provider_->GetActiveAccountId();
765 return; 672 if (account_id.empty())
766 std::string username = manager->GetAuthenticatedUsername();
767 if (username.empty())
768 return; 673 return;
769 674
770 // CheckIn could be called more than once when: 675 // CheckIn could be called more than once when:
771 // 1) The password changes. 676 // 1) The password changes.
772 // 2) Register/send function calls it to ensure CheckIn is done. 677 // 2) Register/send function calls it to ensure CheckIn is done.
773 if (username_ == username) 678 if (account_id_ == account_id)
774 return; 679 return;
775 username_ = username; 680 account_id_ = account_id;
776 681
777 DCHECK(!delayed_task_controller_); 682 DCHECK(!delayed_task_controller_);
778 delayed_task_controller_.reset(new DelayedTaskController); 683 delayed_task_controller_.reset(new DelayedTaskController);
779 684
780 // This will load the data from the gcm store and trigger the check-in if 685 // This will load the data from the gcm store and trigger the check-in if
781 // the persisted check-in info is not found. 686 // the persisted check-in info is not found.
782 // Note that we need to pass weak pointer again since the existing weak 687 // Note that we need to pass weak pointer again since the existing weak
783 // pointer in IOWorker might have been invalidated when check-out occurs. 688 // pointer in IOWorker might have been invalidated when check-out occurs.
784 content::BrowserThread::PostTask( 689 content::BrowserThread::PostTask(
785 content::BrowserThread::IO, 690 content::BrowserThread::IO,
786 FROM_HERE, 691 FROM_HERE,
787 base::Bind(&GCMProfileService::IOWorker::Load, 692 base::Bind(&GCMService::IOWorker::Load,
788 io_worker_, 693 base::Unretained(io_worker_.get()),
789 weak_ptr_factory_.GetWeakPtr())); 694 weak_ptr_factory_.GetWeakPtr()));
790 } 695 }
791 696
792 void GCMProfileService::RemoveCachedData() { 697 void GCMService::RemoveCachedData() {
698 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
793 // Remove all the queued tasks since they no longer make sense after 699 // Remove all the queued tasks since they no longer make sense after
794 // GCM service is stopped. 700 // GCM service is stopped.
795 weak_ptr_factory_.InvalidateWeakPtrs(); 701 weak_ptr_factory_.InvalidateWeakPtrs();
796 702
797 username_.clear(); 703 account_id_.clear();
798 gcm_client_ready_ = false; 704 gcm_client_ready_ = false;
799 delayed_task_controller_.reset(); 705 delayed_task_controller_.reset();
800 register_callbacks_.clear(); 706 register_callbacks_.clear();
801 send_callbacks_.clear(); 707 send_callbacks_.clear();
802 } 708 }
803 709
804 void GCMProfileService::CheckOut() { 710 void GCMService::CheckOut() {
805 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 711 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
806 712
807 // We still proceed with the check-out logic even if the check-in is not 713 // We still proceed with the check-out logic even if the check-in is not
808 // initiated in the current session. This will make sure that all the 714 // initiated in the current session. This will make sure that all the
809 // persisted data written previously will get purged. 715 // persisted data written previously will get purged.
810 716
811 RemoveCachedData(); 717 RemoveCachedData();
812 718
813 content::BrowserThread::PostTask( 719 content::BrowserThread::PostTask(
814 content::BrowserThread::IO, 720 content::BrowserThread::IO,
815 FROM_HERE, 721 FROM_HERE,
816 base::Bind(&GCMProfileService::IOWorker::CheckOut, io_worker_)); 722 base::Bind(&GCMService::IOWorker::CheckOut,
723 base::Unretained(io_worker_.get())));
817 } 724 }
818 725
819 void GCMProfileService::ResetGCMClient() { 726 GCMClient::Result GCMService::EnsureAppReady(const std::string& app_id) {
820 content::BrowserThread::PostTask( 727 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
821 content::BrowserThread::IO,
822 FROM_HERE,
823 base::Bind(&GCMProfileService::IOWorker::Reset, io_worker_));
824 }
825
826 GCMClient::Result GCMProfileService::EnsureAppReady(const std::string& app_id) {
827 // Ensure that check-in has been done. 728 // Ensure that check-in has been done.
828 EnsureLoaded(); 729 EnsureLoaded();
829 730
830 // If the profile was not signed in, bail out. 731 // If the service was not started, bail out.
831 if (username_.empty()) 732 if (account_id_.empty())
832 return GCMClient::NOT_SIGNED_IN; 733 return GCMClient::NOT_SIGNED_IN;
833 734
834 return GCMClient::SUCCESS; 735 return GCMClient::SUCCESS;
835 } 736 }
836 737
837 bool GCMProfileService::IsAsyncOperationPending( 738 bool GCMService::IsAsyncOperationPending(const std::string& app_id) const {
838 const std::string& app_id) const { 739 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
839 return register_callbacks_.find(app_id) != register_callbacks_.end() || 740 return register_callbacks_.find(app_id) != register_callbacks_.end() ||
840 unregister_callbacks_.find(app_id) != unregister_callbacks_.end(); 741 unregister_callbacks_.find(app_id) != unregister_callbacks_.end();
841 } 742 }
842 743
843 void GCMProfileService::RegisterFinished(const std::string& app_id, 744 void GCMService::RegisterFinished(const std::string& app_id,
844 const std::string& registration_id, 745 const std::string& registration_id,
845 GCMClient::Result result) { 746 GCMClient::Result result) {
846 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 747 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
847 748
848 std::map<std::string, RegisterCallback>::iterator callback_iter = 749 std::map<std::string, RegisterCallback>::iterator callback_iter =
849 register_callbacks_.find(app_id); 750 register_callbacks_.find(app_id);
850 if (callback_iter == register_callbacks_.end()) { 751 if (callback_iter == register_callbacks_.end()) {
851 // The callback could have been removed when the app is uninstalled. 752 // The callback could have been removed when the app is uninstalled.
852 return; 753 return;
853 } 754 }
854 755
855 RegisterCallback callback = callback_iter->second; 756 RegisterCallback callback = callback_iter->second;
856 register_callbacks_.erase(callback_iter); 757 register_callbacks_.erase(callback_iter);
857 callback.Run(registration_id, result); 758 callback.Run(registration_id, result);
858 } 759 }
859 760
860 void GCMProfileService::UnregisterFinished(const std::string& app_id, 761 void GCMService::UnregisterFinished(const std::string& app_id,
861 GCMClient::Result result) { 762 GCMClient::Result result) {
862 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 763 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
863 764
864 std::map<std::string, UnregisterCallback>::iterator callback_iter = 765 std::map<std::string, UnregisterCallback>::iterator callback_iter =
865 unregister_callbacks_.find(app_id); 766 unregister_callbacks_.find(app_id);
866 if (callback_iter == unregister_callbacks_.end()) 767 if (callback_iter == unregister_callbacks_.end())
867 return; 768 return;
868 769
869 UnregisterCallback callback = callback_iter->second; 770 UnregisterCallback callback = callback_iter->second;
870 unregister_callbacks_.erase(callback_iter); 771 unregister_callbacks_.erase(callback_iter);
871 callback.Run(result); 772 callback.Run(result);
872 } 773 }
873 774
874 void GCMProfileService::SendFinished(const std::string& app_id, 775 void GCMService::SendFinished(const std::string& app_id,
875 const std::string& message_id, 776 const std::string& message_id,
876 GCMClient::Result result) { 777 GCMClient::Result result) {
877 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 778 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
878 779
879 std::map<std::pair<std::string, std::string>, SendCallback>::iterator 780 std::map<std::pair<std::string, std::string>, SendCallback>::iterator
880 callback_iter = send_callbacks_.find( 781 callback_iter = send_callbacks_.find(
881 std::pair<std::string, std::string>(app_id, message_id)); 782 std::pair<std::string, std::string>(app_id, message_id));
882 if (callback_iter == send_callbacks_.end()) { 783 if (callback_iter == send_callbacks_.end()) {
883 // The callback could have been removed when the app is uninstalled. 784 // The callback could have been removed when the app is uninstalled.
884 return; 785 return;
885 } 786 }
886 787
887 SendCallback callback = callback_iter->second; 788 SendCallback callback = callback_iter->second;
888 send_callbacks_.erase(callback_iter); 789 send_callbacks_.erase(callback_iter);
889 callback.Run(message_id, result); 790 callback.Run(message_id, result);
890 } 791 }
891 792
892 void GCMProfileService::MessageReceived(const std::string& app_id, 793 void GCMService::MessageReceived(const std::string& app_id,
893 GCMClient::IncomingMessage message) { 794 GCMClient::IncomingMessage message) {
894 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 795 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
895 796
896 // Drop the event if signed out. 797 // Drop the event if signed out.
897 if (username_.empty()) 798 if (account_id_.empty())
898 return; 799 return;
899 800
900 GetAppHandler(app_id)->OnMessage(app_id, message); 801 GetAppHandler(app_id)->OnMessage(app_id, message);
901 } 802 }
902 803
903 void GCMProfileService::MessagesDeleted(const std::string& app_id) { 804 void GCMService::MessagesDeleted(const std::string& app_id) {
904 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 805 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
905 806
906 // Drop the event if signed out. 807 // Drop the event if signed out.
907 if (username_.empty()) 808 if (account_id_.empty())
908 return; 809 return;
909 810
910 GetAppHandler(app_id)->OnMessagesDeleted(app_id); 811 GetAppHandler(app_id)->OnMessagesDeleted(app_id);
911 } 812 }
912 813
913 void GCMProfileService::MessageSendError( 814 void GCMService::MessageSendError(
914 const std::string& app_id, 815 const std::string& app_id,
915 const GCMClient::SendErrorDetails& send_error_details) { 816 const GCMClient::SendErrorDetails& send_error_details) {
916 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 817 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
917 818
918 // Drop the event if signed out. 819 // Drop the event if signed out.
919 if (username_.empty()) 820 if (account_id_.empty())
920 return; 821 return;
921 822
922 GetAppHandler(app_id)->OnSendError(app_id, send_error_details); 823 GetAppHandler(app_id)->OnSendError(app_id, send_error_details);
923 } 824 }
924 825
925 void GCMProfileService::GCMClientReady() { 826 void GCMService::GCMClientReady() {
926 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 827 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
927 828
928 if (gcm_client_ready_) 829 if (gcm_client_ready_)
929 return; 830 return;
930 gcm_client_ready_ = true; 831 gcm_client_ready_ = true;
931 832
932 delayed_task_controller_->SetReady(); 833 delayed_task_controller_->SetReady();
933 } 834 }
934 835
935 GCMAppHandler* GCMProfileService::GetAppHandler(const std::string& app_id) { 836 GCMAppHandler* GCMService::GetAppHandler(const std::string& app_id) {
837 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
838
936 std::map<std::string, GCMAppHandler*>::const_iterator iter = 839 std::map<std::string, GCMAppHandler*>::const_iterator iter =
937 app_handlers_.find(app_id); 840 app_handlers_.find(app_id);
938 return iter == app_handlers_.end() ? &default_app_handler_ : iter->second; 841 return iter == app_handlers_.end() ? &default_app_handler_ : iter->second;
939 } 842 }
940 843
941 void GCMProfileService::GetGCMStatisticsFinished( 844 void GCMService::GetGCMStatisticsFinished(
942 GCMClient::GCMStatistics stats) { 845 GCMClient::GCMStatistics stats) {
943 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 846 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
944 request_gcm_statistics_callback_.Run(stats); 847 request_gcm_statistics_callback_.Run(stats);
945 } 848 }
946 849
947 } // namespace gcm 850 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698