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

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: Pass scoped_refptr as const reference. 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 Reset();
170 void Load(const base::WeakPtr<GCMProfileService>& service); 157 void Load(const base::WeakPtr<GCMService>& service);
171 void Stop(); 158 void Stop();
172 void CheckOut(); 159 void CheckOut();
173 void Register(const std::string& app_id, 160 void Register(const std::string& app_id,
174 const std::vector<std::string>& sender_ids); 161 const std::vector<std::string>& sender_ids);
175 void Unregister(const std::string& app_id); 162 void Unregister(const std::string& app_id);
176 void Send(const std::string& app_id, 163 void Send(const std::string& app_id,
177 const std::string& receiver_id, 164 const std::string& receiver_id,
178 const GCMClient::OutgoingMessage& message); 165 const GCMClient::OutgoingMessage& message);
179 void RequestGCMStatistics(); 166 void RequestGCMStatistics();
180 167
181 // 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.
182 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); } 169 GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); }
183 170
184 private: 171 private:
185 friend class base::RefCountedThreadSafe<IOWorker>; 172 base::WeakPtr<GCMService> service_;
186 virtual ~IOWorker();
187
188 base::WeakPtr<GCMProfileService> service_;
189 173
190 scoped_ptr<GCMClient> gcm_client_; 174 scoped_ptr<GCMClient> gcm_client_;
175
176 DISALLOW_COPY_AND_ASSIGN(IOWorker);
191 }; 177 };
192 178
193 GCMProfileService::IOWorker::IOWorker() { 179 GCMService::IOWorker::IOWorker() {
194 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 180 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
195 } 181 }
196 182
197 GCMProfileService::IOWorker::~IOWorker() { 183 GCMService::IOWorker::~IOWorker() {
184 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
jianli 2014/04/10 20:39:56 I do not think IOWorker can be destructed on IO th
bartfab (slow) 2014/04/11 16:58:52 Since it does work on the IO thread, it must be de
198 } 185 }
199 186
200 void GCMProfileService::IOWorker::Initialize( 187 void GCMService::IOWorker::Initialize(
201 scoped_ptr<GCMClientFactory> gcm_client_factory, 188 scoped_ptr<GCMClientFactory> gcm_client_factory,
202 const base::FilePath& store_path, 189 const base::FilePath& store_path,
203 const std::vector<std::string>& account_ids, 190 const std::vector<std::string>& account_ids,
204 const scoped_refptr<net::URLRequestContextGetter>& 191 const scoped_refptr<net::URLRequestContextGetter>&
205 url_request_context_getter) { 192 url_request_context_getter) {
206 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 193 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
207 194
208 gcm_client_ = gcm_client_factory->BuildInstance().Pass(); 195 gcm_client_ = gcm_client_factory->BuildInstance().Pass();
209 196
210 checkin_proto::ChromeBuildProto chrome_build_proto; 197 checkin_proto::ChromeBuildProto chrome_build_proto;
211 chrome_build_proto.set_platform(GetPlatform()); 198 chrome_build_proto.set_platform(GetPlatform());
212 chrome_build_proto.set_chrome_version(GetVersion()); 199 chrome_build_proto.set_chrome_version(GetVersion());
213 chrome_build_proto.set_channel(GetChannel()); 200 chrome_build_proto.set_channel(GetChannel());
214 201
215 scoped_refptr<base::SequencedWorkerPool> worker_pool( 202 scoped_refptr<base::SequencedWorkerPool> worker_pool(
216 content::BrowserThread::GetBlockingPool()); 203 content::BrowserThread::GetBlockingPool());
217 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( 204 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner(
218 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( 205 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
219 worker_pool->GetSequenceToken(), 206 worker_pool->GetSequenceToken(),
220 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 207 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
221 208
222 gcm_client_->Initialize(chrome_build_proto, 209 gcm_client_->Initialize(chrome_build_proto,
223 store_path, 210 store_path,
224 account_ids, 211 account_ids,
225 blocking_task_runner, 212 blocking_task_runner,
226 url_request_context_getter, 213 url_request_context_getter,
227 this); 214 this);
228 } 215 }
229 216
230 void GCMProfileService::IOWorker::Reset() { 217 void GCMService::IOWorker::Reset() {
231 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 218 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
232 219
233 // GCMClient instance must be destroyed from the same thread where it was 220 // GCMClient instance must be destroyed from the same thread where it was
234 // created. 221 // created.
235 gcm_client_.reset(); 222 gcm_client_.reset();
236 } 223 }
237 224
238 void GCMProfileService::IOWorker::OnRegisterFinished( 225 void GCMService::IOWorker::OnRegisterFinished(
239 const std::string& app_id, 226 const std::string& app_id,
240 const std::string& registration_id, 227 const std::string& registration_id,
241 GCMClient::Result result) { 228 GCMClient::Result result) {
242 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 229 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
243 230
244 content::BrowserThread::PostTask( 231 content::BrowserThread::PostTask(content::BrowserThread::UI,
245 content::BrowserThread::UI, 232 FROM_HERE,
246 FROM_HERE, 233 base::Bind(&GCMService::RegisterFinished,
247 base::Bind(&GCMProfileService::RegisterFinished, 234 service_,
248 service_, 235 app_id,
249 app_id, 236 registration_id,
250 registration_id, 237 result));
251 result));
252 } 238 }
253 239
254 void GCMProfileService::IOWorker::OnUnregisterFinished( 240 void GCMService::IOWorker::OnUnregisterFinished(const std::string& app_id,
255 const std::string& app_id, 241 GCMClient::Result result) {
256 GCMClient::Result result) {
257 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 242 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
258 243
259 content::BrowserThread::PostTask( 244 content::BrowserThread::PostTask(
260 content::BrowserThread::UI, 245 content::BrowserThread::UI,
261 FROM_HERE, 246 FROM_HERE,
262 base::Bind( 247 base::Bind(&GCMService::UnregisterFinished, service_, app_id, result));
263 &GCMProfileService::UnregisterFinished, service_, app_id, result));
264 } 248 }
265 249
266 void GCMProfileService::IOWorker::OnSendFinished( 250 void GCMService::IOWorker::OnSendFinished(const std::string& app_id,
267 const std::string& app_id, 251 const std::string& message_id,
268 const std::string& message_id, 252 GCMClient::Result result) {
269 GCMClient::Result result) {
270 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 253 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
271 254
272 content::BrowserThread::PostTask( 255 content::BrowserThread::PostTask(content::BrowserThread::UI,
273 content::BrowserThread::UI, 256 FROM_HERE,
274 FROM_HERE, 257 base::Bind(&GCMService::SendFinished,
275 base::Bind(&GCMProfileService::SendFinished, 258 service_,
276 service_, 259 app_id,
277 app_id, 260 message_id,
278 message_id, 261 result));
279 result));
280 } 262 }
281 263
282 void GCMProfileService::IOWorker::OnMessageReceived( 264 void GCMService::IOWorker::OnMessageReceived(
283 const std::string& app_id, 265 const std::string& app_id,
284 const GCMClient::IncomingMessage& message) { 266 const GCMClient::IncomingMessage& message) {
285 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 267 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
286 268
287 content::BrowserThread::PostTask( 269 content::BrowserThread::PostTask(content::BrowserThread::UI,
288 content::BrowserThread::UI, 270 FROM_HERE,
289 FROM_HERE, 271 base::Bind(&GCMService::MessageReceived,
290 base::Bind(&GCMProfileService::MessageReceived, 272 service_,
291 service_, 273 app_id,
292 app_id, 274 message));
293 message));
294 } 275 }
295 276
296 void GCMProfileService::IOWorker::OnMessagesDeleted(const std::string& app_id) { 277 void GCMService::IOWorker::OnMessagesDeleted(const std::string& app_id) {
297 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 278 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
298 279
299 content::BrowserThread::PostTask( 280 content::BrowserThread::PostTask(content::BrowserThread::UI,
300 content::BrowserThread::UI, 281 FROM_HERE,
301 FROM_HERE, 282 base::Bind(&GCMService::MessagesDeleted,
302 base::Bind(&GCMProfileService::MessagesDeleted, 283 service_,
303 service_, 284 app_id));
304 app_id));
305 } 285 }
306 286
307 void GCMProfileService::IOWorker::OnMessageSendError( 287 void GCMService::IOWorker::OnMessageSendError(
308 const std::string& app_id, 288 const std::string& app_id,
309 const GCMClient::SendErrorDetails& send_error_details) { 289 const GCMClient::SendErrorDetails& send_error_details) {
310 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 290 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
311 291
312 content::BrowserThread::PostTask( 292 content::BrowserThread::PostTask(content::BrowserThread::UI,
313 content::BrowserThread::UI, 293 FROM_HERE,
314 FROM_HERE, 294 base::Bind(&GCMService::MessageSendError,
315 base::Bind(&GCMProfileService::MessageSendError, 295 service_,
316 service_, 296 app_id,
317 app_id, 297 send_error_details));
318 send_error_details));
319 } 298 }
320 299
321 void GCMProfileService::IOWorker::OnGCMReady() { 300 void GCMService::IOWorker::OnGCMReady() {
322 content::BrowserThread::PostTask( 301 content::BrowserThread::PostTask(content::BrowserThread::UI,
323 content::BrowserThread::UI, 302 FROM_HERE,
324 FROM_HERE, 303 base::Bind(&GCMService::GCMClientReady,
325 base::Bind(&GCMProfileService::GCMClientReady, 304 service_));
326 service_));
327 } 305 }
328 306
329 void GCMProfileService::IOWorker::Load( 307 void GCMService::IOWorker::Load(const base::WeakPtr<GCMService>& service) {
330 const base::WeakPtr<GCMProfileService>& service) {
331 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 308 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
332 309
333 service_ = service; 310 service_ = service;
334 gcm_client_->Load(); 311 gcm_client_->Load();
335 } 312 }
336 313
337 void GCMProfileService::IOWorker::Stop() { 314 void GCMService::IOWorker::Stop() {
338 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 315 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
339 316
340 gcm_client_->Stop(); 317 gcm_client_->Stop();
341 } 318 }
342 319
343 void GCMProfileService::IOWorker::CheckOut() { 320 void GCMService::IOWorker::CheckOut() {
344 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 321 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
345 322
346 gcm_client_->CheckOut(); 323 gcm_client_->CheckOut();
347 324
348 // Note that we still need to keep GCMClient instance alive since the profile 325 // Note that we still need to keep GCMClient instance alive since the
349 // might be signed in again. 326 // GCMService may check in again.
350 } 327 }
351 328
352 void GCMProfileService::IOWorker::Register( 329 void GCMService::IOWorker::Register(
353 const std::string& app_id, 330 const std::string& app_id,
354 const std::vector<std::string>& sender_ids) { 331 const std::vector<std::string>& sender_ids) {
355 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 332 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
356 333
357 gcm_client_->Register(app_id, sender_ids); 334 gcm_client_->Register(app_id, sender_ids);
358 } 335 }
359 336
360 void GCMProfileService::IOWorker::Unregister(const std::string& app_id) { 337 void GCMService::IOWorker::Unregister(const std::string& app_id) {
361 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 338 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
362 339
363 gcm_client_->Unregister(app_id); 340 gcm_client_->Unregister(app_id);
364 } 341 }
365 342
366 void GCMProfileService::IOWorker::Send( 343 void GCMService::IOWorker::Send(const std::string& app_id,
367 const std::string& app_id, 344 const std::string& receiver_id,
368 const std::string& receiver_id, 345 const GCMClient::OutgoingMessage& message) {
369 const GCMClient::OutgoingMessage& message) {
370 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 346 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
371 347
372 gcm_client_->Send(app_id, receiver_id, message); 348 gcm_client_->Send(app_id, receiver_id, message);
373 } 349 }
374 350
375 void GCMProfileService::IOWorker::RequestGCMStatistics() { 351 void GCMService::IOWorker::RequestGCMStatistics() {
376 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 352 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
377 gcm::GCMClient::GCMStatistics stats; 353 gcm::GCMClient::GCMStatistics stats;
378 354
379 if (gcm_client_.get()) { 355 if (gcm_client_.get()) {
380 stats.gcm_client_created = true; 356 stats.gcm_client_created = true;
381 stats = gcm_client_->GetStatistics(); 357 stats = gcm_client_->GetStatistics();
382 } 358 }
383 359
384 content::BrowserThread::PostTask( 360 content::BrowserThread::PostTask(
385 content::BrowserThread::UI, 361 content::BrowserThread::UI,
386 FROM_HERE, 362 FROM_HERE,
387 base::Bind(&GCMProfileService::RequestGCMStatisticsFinished, 363 base::Bind(&GCMService::RequestGCMStatisticsFinished, service_, stats));
388 service_,
389 stats));
390 } 364 }
391 365
392 std::string GCMProfileService::GetGCMEnabledStateString(GCMEnabledState state) { 366 GCMService::GCMService(
393 switch (state) { 367 scoped_ptr<invalidation::InvalidationAuthProvider> auth_provider,
394 case GCMProfileService::ALWAYS_ENABLED: 368 const scoped_refptr<net::URLRequestContextGetter>& request_context,
395 return "ALWAYS_ENABLED"; 369 const base::FilePath& store_path)
396 case GCMProfileService::ENABLED_FOR_APPS: 370 : auth_provider_(auth_provider.Pass()),
397 return "ENABLED_FOR_APPS"; 371 request_context_(request_context),
398 case GCMProfileService::ALWAYS_DISABLED: 372 store_path_(store_path),
399 return "ALWAYS_DISABLED"; 373 gcm_client_ready_(false),
400 default: 374 weak_ptr_factory_(this) {
401 NOTREACHED();
402 return std::string();
403 }
404 } 375 }
405 376
406 // static 377 GCMService::~GCMService() {
407 GCMProfileService::GCMEnabledState GCMProfileService::GetGCMEnabledState(
408 Profile* profile) {
409 const base::Value* gcm_enabled_value =
410 profile->GetPrefs()->GetUserPrefValue(prefs::kGCMChannelEnabled);
411 if (!gcm_enabled_value)
412 return ENABLED_FOR_APPS;
413
414 bool gcm_enabled = false;
415 if (!gcm_enabled_value->GetAsBoolean(&gcm_enabled))
416 return ENABLED_FOR_APPS;
417
418 return gcm_enabled ? ALWAYS_ENABLED : ALWAYS_DISABLED;
419 } 378 }
420 379
421 // static 380 void GCMService::Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory) {
422 void GCMProfileService::RegisterProfilePrefs(
423 user_prefs::PrefRegistrySyncable* registry) {
424 // GCM support is only enabled by default for Canary/Dev/Custom builds.
425 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
426 bool on_by_default = false;
427 if (channel == chrome::VersionInfo::CHANNEL_UNKNOWN ||
428 channel == chrome::VersionInfo::CHANNEL_CANARY ||
429 channel == chrome::VersionInfo::CHANNEL_DEV) {
430 on_by_default = true;
431 }
432 registry->RegisterBooleanPref(
433 prefs::kGCMChannelEnabled,
434 on_by_default,
435 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
436 }
437
438 GCMProfileService::GCMProfileService(Profile* profile)
439 : profile_(profile),
440 gcm_client_ready_(false),
441 weak_ptr_factory_(this) {
442 DCHECK(!profile->IsOffTheRecord());
443 }
444
445 GCMProfileService::~GCMProfileService() {
446 }
447
448 void GCMProfileService::Initialize(
449 scoped_ptr<GCMClientFactory> gcm_client_factory) {
450 registrar_.Add(this,
451 chrome::NOTIFICATION_PROFILE_DESTROYED,
452 content::Source<Profile>(profile_));
453
454 SigninManagerFactory::GetForProfile(profile_)->AddObserver(this);
455
456 // Get the list of available accounts. 381 // Get the list of available accounts.
457 std::vector<std::string> account_ids; 382 std::vector<std::string> account_ids;
458 #if !defined(OS_ANDROID) 383 #if !defined(OS_ANDROID)
459 account_ids = 384 account_ids = auth_provider_->GetTokenService()->GetAccounts();
460 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->GetAccounts();
461 #endif 385 #endif
462 386
463 // Create and initialize the GCMClient. Note that this does not initiate the 387 // Create and initialize the GCMClient. Note that this does not initiate the
464 // GCM check-in. 388 // GCM check-in.
465 io_worker_ = new IOWorker(); 389 DCHECK(!io_worker_);
466 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter = 390 io_worker_.reset(new IOWorker());
467 profile_->GetRequestContext();
468 content::BrowserThread::PostTask( 391 content::BrowserThread::PostTask(
469 content::BrowserThread::IO, 392 content::BrowserThread::IO,
470 FROM_HERE, 393 FROM_HERE,
471 base::Bind(&GCMProfileService::IOWorker::Initialize, 394 base::Bind(&GCMService::IOWorker::Initialize,
472 io_worker_, 395 base::Unretained(io_worker_.get()),
473 base::Passed(&gcm_client_factory), 396 base::Passed(&gcm_client_factory),
474 profile_->GetPath().Append(chrome::kGCMStoreDirname), 397 store_path_,
475 account_ids, 398 account_ids,
476 url_request_context_getter)); 399 request_context_));
477 400
478 // Load from the GCM store and initiate the GCM check-in if the rollout signal 401 // Load from the GCM store and initiate the GCM check-in if the rollout signal
479 // indicates yes. 402 // indicates yes.
480 if (GetGCMEnabledState(profile_) == ALWAYS_ENABLED) 403 if (IsAlwaysEnabled())
481 EnsureLoaded(); 404 EnsureLoaded();
405
406 auth_provider_->AddObserver(this);
482 } 407 }
483 408
484 void GCMProfileService::Start() { 409 void GCMService::Start() {
485 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 410 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
486 411
487 EnsureLoaded(); 412 EnsureLoaded();
488 } 413 }
489 414
490 void GCMProfileService::Stop() { 415 void GCMService::Stop() {
491 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 416 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
492 417
493 // No need to stop GCM service if not started yet. 418 // No need to stop GCM service if not started yet.
494 if (username_.empty()) 419 if (account_id_.empty())
495 return; 420 return;
496 421
497 RemoveCachedData(); 422 RemoveCachedData();
498 423
499 content::BrowserThread::PostTask( 424 content::BrowserThread::PostTask(
500 content::BrowserThread::IO, 425 content::BrowserThread::IO,
501 FROM_HERE, 426 FROM_HERE,
502 base::Bind(&GCMProfileService::IOWorker::Stop, io_worker_)); 427 base::Bind(&GCMService::IOWorker::Stop,
428 base::Unretained(io_worker_.get())));
jianli 2014/04/10 20:39:56 base::Unretained should almost never be used in no
bartfab (slow) 2014/04/11 16:58:52 Used correctly, base::Unretained is both useful an
jianli 2014/04/17 00:33:18 I understand this, but it still seems to be danger
bartfab (slow) 2014/04/17 14:20:00 The way to ensure safe and predictable operation i
503 } 429 }
504 430
505 void GCMProfileService::Shutdown() { 431 void GCMService::Shutdown() {
432 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
433 auth_provider_->RemoveObserver(this);
506 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin(); 434 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin();
507 iter != app_handlers_.end(); ++iter) { 435 iter != app_handlers_.end(); ++iter) {
508 iter->second->ShutdownHandler(); 436 iter->second->ShutdownHandler();
509 } 437 }
510 app_handlers_.clear(); 438 app_handlers_.clear();
511 439 content::BrowserThread::DeleteSoon(content::BrowserThread::IO,
512 SigninManagerFactory::GetForProfile(profile_)->RemoveObserver(this); 440 FROM_HERE,
441 io_worker_.release());
513 } 442 }
514 443
515 void GCMProfileService::AddAppHandler(const std::string& app_id, 444 void GCMService::AddAppHandler(const std::string& app_id,
516 GCMAppHandler* handler) { 445 GCMAppHandler* handler) {
446 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
517 DCHECK(!app_id.empty()); 447 DCHECK(!app_id.empty());
518 DCHECK(handler); 448 DCHECK(handler);
519 DCHECK(app_handlers_.find(app_id) == app_handlers_.end()); 449 DCHECK(app_handlers_.find(app_id) == app_handlers_.end());
520 450
521 app_handlers_[app_id] = handler; 451 app_handlers_[app_id] = handler;
522 } 452 }
523 453
524 void GCMProfileService::RemoveAppHandler(const std::string& app_id) { 454 void GCMService::RemoveAppHandler(const std::string& app_id) {
455 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
525 DCHECK(!app_id.empty()); 456 DCHECK(!app_id.empty());
526 457
527 app_handlers_.erase(app_id); 458 app_handlers_.erase(app_id);
528 } 459 }
529 460
530 void GCMProfileService::Register(const std::string& app_id, 461 void GCMService::Register(const std::string& app_id,
531 const std::vector<std::string>& sender_ids, 462 const std::vector<std::string>& sender_ids,
532 RegisterCallback callback) { 463 RegisterCallback callback) {
533 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 464 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
534 DCHECK(!app_id.empty() && !sender_ids.empty() && !callback.is_null()); 465 DCHECK(!app_id.empty());
466 DCHECK(!sender_ids.empty());
467 DCHECK(!callback.is_null());
535 468
536 GCMClient::Result result = EnsureAppReady(app_id); 469 GCMClient::Result result = EnsureAppReady(app_id);
537 if (result != GCMClient::SUCCESS) { 470 if (result != GCMClient::SUCCESS) {
538 callback.Run(std::string(), result); 471 callback.Run(std::string(), result);
539 return; 472 return;
540 } 473 }
541 474
542 // If previous un/register operation is still in progress, bail out. 475 // If previous un/register operation is still in progress, bail out.
543 if (IsAsyncOperationPending(app_id)) { 476 if (IsAsyncOperationPending(app_id)) {
544 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); 477 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
545 return; 478 return;
546 } 479 }
547 480
548 register_callbacks_[app_id] = callback; 481 register_callbacks_[app_id] = callback;
549 482
550 // Delay the register operation until GCMClient is ready. 483 // Delay the register operation until GCMClient is ready.
551 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 484 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
552 delayed_task_controller_->AddTask( 485 delayed_task_controller_->AddTask(base::Bind(&GCMService::DoRegister,
553 base::Bind(&GCMProfileService::DoRegister, 486 weak_ptr_factory_.GetWeakPtr(),
554 weak_ptr_factory_.GetWeakPtr(), 487 app_id,
555 app_id, 488 sender_ids));
556 sender_ids));
557 return; 489 return;
558 } 490 }
559 491
560 DoRegister(app_id, sender_ids); 492 DoRegister(app_id, sender_ids);
561 } 493 }
562 494
563 void GCMProfileService::DoRegister(const std::string& app_id, 495 void GCMService::DoRegister(const std::string& app_id,
564 const std::vector<std::string>& sender_ids) { 496 const std::vector<std::string>& sender_ids) {
497 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
565 std::map<std::string, RegisterCallback>::iterator callback_iter = 498 std::map<std::string, RegisterCallback>::iterator callback_iter =
566 register_callbacks_.find(app_id); 499 register_callbacks_.find(app_id);
567 if (callback_iter == register_callbacks_.end()) { 500 if (callback_iter == register_callbacks_.end()) {
568 // The callback could have been removed when the app is uninstalled. 501 // The callback could have been removed when the app is uninstalled.
569 return; 502 return;
570 } 503 }
571 504
572 // Normalize the sender IDs by making them sorted. 505 // Normalize the sender IDs by making them sorted.
573 std::vector<std::string> normalized_sender_ids = sender_ids; 506 std::vector<std::string> normalized_sender_ids = sender_ids;
574 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end()); 507 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
575 508
576 content::BrowserThread::PostTask( 509 content::BrowserThread::PostTask(
577 content::BrowserThread::IO, 510 content::BrowserThread::IO,
578 FROM_HERE, 511 FROM_HERE,
579 base::Bind(&GCMProfileService::IOWorker::Register, 512 base::Bind(&GCMService::IOWorker::Register,
580 io_worker_, 513 base::Unretained(io_worker_.get()),
581 app_id, 514 app_id,
582 normalized_sender_ids)); 515 normalized_sender_ids));
583 } 516 }
584 517
585 void GCMProfileService::Unregister(const std::string& app_id, 518 void GCMService::Unregister(const std::string& app_id,
586 UnregisterCallback callback) { 519 UnregisterCallback callback) {
587 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 520 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
588 DCHECK(!app_id.empty() && !callback.is_null()); 521 DCHECK(!app_id.empty());
522 DCHECK(!callback.is_null());
589 523
590 GCMClient::Result result = EnsureAppReady(app_id); 524 GCMClient::Result result = EnsureAppReady(app_id);
591 if (result != GCMClient::SUCCESS) { 525 if (result != GCMClient::SUCCESS) {
592 callback.Run(result); 526 callback.Run(result);
593 return; 527 return;
594 } 528 }
595 529
596 // If previous un/register operation is still in progress, bail out. 530 // If previous un/register operation is still in progress, bail out.
597 if (IsAsyncOperationPending(app_id)) { 531 if (IsAsyncOperationPending(app_id)) {
598 callback.Run(GCMClient::ASYNC_OPERATION_PENDING); 532 callback.Run(GCMClient::ASYNC_OPERATION_PENDING);
599 return; 533 return;
600 } 534 }
601 535
602 unregister_callbacks_[app_id] = callback; 536 unregister_callbacks_[app_id] = callback;
603 537
604 // Delay the unregister operation until GCMClient is ready. 538 // Delay the unregister operation until GCMClient is ready.
605 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 539 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
606 delayed_task_controller_->AddTask( 540 delayed_task_controller_->AddTask(base::Bind(&GCMService::DoUnregister,
607 base::Bind(&GCMProfileService::DoUnregister, 541 weak_ptr_factory_.GetWeakPtr(),
608 weak_ptr_factory_.GetWeakPtr(), 542 app_id));
609 app_id));
610 return; 543 return;
611 } 544 }
612 545
613 DoUnregister(app_id); 546 DoUnregister(app_id);
614 } 547 }
615 548
616 void GCMProfileService::DoUnregister(const std::string& app_id) { 549 void GCMService::DoUnregister(const std::string& app_id) {
617 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 550 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
618 551
619 // Ask the server to unregister it. There could be a small chance that the 552 // Ask the server to unregister it. There could be a small chance that the
620 // unregister request fails. If this occurs, it does not bring any harm since 553 // unregister request fails. If this occurs, it does not bring any harm since
621 // we simply reject the messages/events received from the server. 554 // we simply reject the messages/events received from the server.
622 content::BrowserThread::PostTask( 555 content::BrowserThread::PostTask(
623 content::BrowserThread::IO, 556 content::BrowserThread::IO,
624 FROM_HERE, 557 FROM_HERE,
625 base::Bind(&GCMProfileService::IOWorker::Unregister, 558 base::Bind(&GCMService::IOWorker::Unregister,
626 io_worker_, 559 base::Unretained(io_worker_.get()),
627 app_id)); 560 app_id));
628 } 561 }
629 562
630 void GCMProfileService::Send(const std::string& app_id, 563 void GCMService::Send(const std::string& app_id,
631 const std::string& receiver_id, 564 const std::string& receiver_id,
632 const GCMClient::OutgoingMessage& message, 565 const GCMClient::OutgoingMessage& message,
633 SendCallback callback) { 566 SendCallback callback) {
634 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 567 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
635 DCHECK(!app_id.empty() && !receiver_id.empty() && !callback.is_null()); 568 DCHECK(!app_id.empty());
569 DCHECK(!receiver_id.empty());
570 DCHECK(!callback.is_null());
636 571
637 GCMClient::Result result = EnsureAppReady(app_id); 572 GCMClient::Result result = EnsureAppReady(app_id);
638 if (result != GCMClient::SUCCESS) { 573 if (result != GCMClient::SUCCESS) {
639 callback.Run(std::string(), result); 574 callback.Run(std::string(), result);
640 return; 575 return;
641 } 576 }
642 577
643 // If the message with send ID is still in progress, bail out. 578 // If the message with send ID is still in progress, bail out.
644 std::pair<std::string, std::string> key(app_id, message.id); 579 std::pair<std::string, std::string> key(app_id, message.id);
645 if (send_callbacks_.find(key) != send_callbacks_.end()) { 580 if (send_callbacks_.find(key) != send_callbacks_.end()) {
646 callback.Run(message.id, GCMClient::INVALID_PARAMETER); 581 callback.Run(message.id, GCMClient::INVALID_PARAMETER);
647 return; 582 return;
648 } 583 }
649 584
650 send_callbacks_[key] = callback; 585 send_callbacks_[key] = callback;
651 586
652 // Delay the send operation until all GCMClient is ready. 587 // Delay the send operation until all GCMClient is ready.
653 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { 588 if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
654 delayed_task_controller_->AddTask( 589 delayed_task_controller_->AddTask(base::Bind(&GCMService::DoSend,
655 base::Bind(&GCMProfileService::DoSend, 590 weak_ptr_factory_.GetWeakPtr(),
656 weak_ptr_factory_.GetWeakPtr(), 591 app_id,
657 app_id, 592 receiver_id,
658 receiver_id, 593 message));
659 message));
660 return; 594 return;
661 } 595 }
662 596
663 DoSend(app_id, receiver_id, message); 597 DoSend(app_id, receiver_id, message);
664 } 598 }
665 599
666 void GCMProfileService::DoSend(const std::string& app_id, 600 void GCMService::DoSend(const std::string& app_id,
667 const std::string& receiver_id, 601 const std::string& receiver_id,
668 const GCMClient::OutgoingMessage& message) { 602 const GCMClient::OutgoingMessage& message) {
603 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
669 content::BrowserThread::PostTask( 604 content::BrowserThread::PostTask(
670 content::BrowserThread::IO, 605 content::BrowserThread::IO,
671 FROM_HERE, 606 FROM_HERE,
672 base::Bind(&GCMProfileService::IOWorker::Send, 607 base::Bind(&GCMService::IOWorker::Send,
673 io_worker_, 608 base::Unretained(io_worker_.get()),
674 app_id, 609 app_id,
675 receiver_id, 610 receiver_id,
676 message)); 611 message));
677 } 612 }
678 613
679 GCMClient* GCMProfileService::GetGCMClientForTesting() const { 614 GCMClient* GCMService::GetGCMClientForTesting() const {
615 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
680 return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL; 616 return io_worker_ ? io_worker_->gcm_client_for_testing() : NULL;
681 } 617 }
682 618
683 std::string GCMProfileService::SignedInUserName() const { 619 bool GCMService::IsStarted() const {
684 return username_; 620 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
621 return !account_id_.empty();
685 } 622 }
686 623
687 bool GCMProfileService::IsGCMClientReady() const { 624 bool GCMService::IsGCMClientReady() const {
625 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
688 return gcm_client_ready_; 626 return gcm_client_ready_;
689 } 627 }
690 628
691 void GCMProfileService::RequestGCMStatistics( 629 void GCMService::RequestGCMStatistics(RequestGCMStatisticsCallback callback) {
692 RequestGCMStatisticsCallback callback) {
693 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 630 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
694 DCHECK(!callback.is_null()); 631 DCHECK(!callback.is_null());
695 632
696 request_gcm_statistics_callback_ = callback; 633 request_gcm_statistics_callback_ = callback;
697 content::BrowserThread::PostTask( 634 content::BrowserThread::PostTask(
698 content::BrowserThread::IO, 635 content::BrowserThread::IO,
699 FROM_HERE, 636 FROM_HERE,
700 base::Bind(&GCMProfileService::IOWorker::RequestGCMStatistics, 637 base::Bind(&GCMService::IOWorker::RequestGCMStatistics,
701 io_worker_)); 638 base::Unretained(io_worker_.get())));
702 } 639 }
703 640
704 void GCMProfileService::Observe(int type, 641 void GCMService::OnInvalidationAuthLogin() {
705 const content::NotificationSource& source, 642 if (IsAlwaysEnabled())
706 const content::NotificationDetails& details) {
707 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
708
709 switch (type) {
710 case chrome::NOTIFICATION_PROFILE_DESTROYED:
711 ResetGCMClient();
712 break;
713 default:
714 NOTREACHED();
715 }
716 }
717
718 void GCMProfileService::GoogleSigninSucceeded(const std::string& username,
719 const std::string& password) {
720 if (GetGCMEnabledState(profile_) == ALWAYS_ENABLED)
721 EnsureLoaded(); 643 EnsureLoaded();
722 } 644 }
723 645
724 void GCMProfileService::GoogleSignedOut(const std::string& username) { 646 void GCMService::OnInvalidationAuthLogout() {
725 CheckOut(); 647 CheckOut();
726 } 648 }
727 649
728 void GCMProfileService::EnsureLoaded() { 650 void GCMService::ResetGCMClient() {
729 SigninManagerBase* manager = SigninManagerFactory::GetForProfile(profile_); 651 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
730 if (!manager) 652 content::BrowserThread::PostTask(
731 return; 653 content::BrowserThread::IO,
732 std::string username = manager->GetAuthenticatedUsername(); 654 FROM_HERE,
733 if (username.empty()) 655 base::Bind(&GCMService::IOWorker::Reset,
656 base::Unretained(io_worker_.get())));
657 }
658
659 void GCMService::EnsureLoaded() {
660 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
661 std::string account_id = auth_provider_->GetAccountId();
662 if (account_id.empty())
734 return; 663 return;
735 664
736 // CheckIn could be called more than once when: 665 // CheckIn could be called more than once when:
737 // 1) The password changes. 666 // 1) The password changes.
738 // 2) Register/send function calls it to ensure CheckIn is done. 667 // 2) Register/send function calls it to ensure CheckIn is done.
739 if (username_ == username) 668 if (account_id_ == account_id)
740 return; 669 return;
741 username_ = username; 670 account_id_ = account_id;
742 671
743 DCHECK(!delayed_task_controller_); 672 DCHECK(!delayed_task_controller_);
744 delayed_task_controller_.reset(new DelayedTaskController); 673 delayed_task_controller_.reset(new DelayedTaskController);
745 674
746 // This will load the data from the gcm store and trigger the check-in if 675 // This will load the data from the gcm store and trigger the check-in if
747 // the persisted check-in info is not found. 676 // the persisted check-in info is not found.
748 // Note that we need to pass weak pointer again since the existing weak 677 // Note that we need to pass weak pointer again since the existing weak
749 // pointer in IOWorker might have been invalidated when check-out occurs. 678 // pointer in IOWorker might have been invalidated when check-out occurs.
750 content::BrowserThread::PostTask( 679 content::BrowserThread::PostTask(
751 content::BrowserThread::IO, 680 content::BrowserThread::IO,
752 FROM_HERE, 681 FROM_HERE,
753 base::Bind(&GCMProfileService::IOWorker::Load, 682 base::Bind(&GCMService::IOWorker::Load,
754 io_worker_, 683 base::Unretained(io_worker_.get()),
755 weak_ptr_factory_.GetWeakPtr())); 684 weak_ptr_factory_.GetWeakPtr()));
756 } 685 }
757 686
758 void GCMProfileService::RemoveCachedData() { 687 void GCMService::RemoveCachedData() {
688 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
759 // Remove all the queued tasks since they no longer make sense after 689 // Remove all the queued tasks since they no longer make sense after
760 // GCM service is stopped. 690 // GCM service is stopped.
761 weak_ptr_factory_.InvalidateWeakPtrs(); 691 weak_ptr_factory_.InvalidateWeakPtrs();
762 692
763 username_.clear(); 693 account_id_.clear();
764 gcm_client_ready_ = false; 694 gcm_client_ready_ = false;
765 delayed_task_controller_.reset(); 695 delayed_task_controller_.reset();
766 register_callbacks_.clear(); 696 register_callbacks_.clear();
767 send_callbacks_.clear(); 697 send_callbacks_.clear();
768 } 698 }
769 699
770 void GCMProfileService::CheckOut() { 700 void GCMService::CheckOut() {
771 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 701 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
772 702
773 // We still proceed with the check-out logic even if the check-in is not 703 // We still proceed with the check-out logic even if the check-in is not
774 // initiated in the current session. This will make sure that all the 704 // initiated in the current session. This will make sure that all the
775 // persisted data written previously will get purged. 705 // persisted data written previously will get purged.
776 706
777 RemoveCachedData(); 707 RemoveCachedData();
778 708
779 content::BrowserThread::PostTask( 709 content::BrowserThread::PostTask(
780 content::BrowserThread::IO, 710 content::BrowserThread::IO,
781 FROM_HERE, 711 FROM_HERE,
782 base::Bind(&GCMProfileService::IOWorker::CheckOut, io_worker_)); 712 base::Bind(&GCMService::IOWorker::CheckOut,
713 base::Unretained(io_worker_.get())));
783 } 714 }
784 715
785 void GCMProfileService::ResetGCMClient() { 716 GCMClient::Result GCMService::EnsureAppReady(const std::string& app_id) {
786 content::BrowserThread::PostTask( 717 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
787 content::BrowserThread::IO,
788 FROM_HERE,
789 base::Bind(&GCMProfileService::IOWorker::Reset, io_worker_));
790 }
791
792 GCMClient::Result GCMProfileService::EnsureAppReady(const std::string& app_id) {
793 // Ensure that check-in has been done. 718 // Ensure that check-in has been done.
794 EnsureLoaded(); 719 EnsureLoaded();
795 720
796 // If the profile was not signed in, bail out. 721 // If the service was not started, bail out.
797 if (username_.empty()) 722 if (account_id_.empty())
798 return GCMClient::NOT_SIGNED_IN; 723 return GCMClient::NOT_SIGNED_IN;
799 724
800 return GCMClient::SUCCESS; 725 return GCMClient::SUCCESS;
801 } 726 }
802 727
803 bool GCMProfileService::IsAsyncOperationPending( 728 bool GCMService::IsAsyncOperationPending(const std::string& app_id) const {
804 const std::string& app_id) const { 729 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
805 return register_callbacks_.find(app_id) != register_callbacks_.end() || 730 return register_callbacks_.find(app_id) != register_callbacks_.end() ||
806 unregister_callbacks_.find(app_id) != unregister_callbacks_.end(); 731 unregister_callbacks_.find(app_id) != unregister_callbacks_.end();
807 } 732 }
808 733
809 void GCMProfileService::RegisterFinished(const std::string& app_id, 734 void GCMService::RegisterFinished(const std::string& app_id,
810 const std::string& registration_id, 735 const std::string& registration_id,
811 GCMClient::Result result) { 736 GCMClient::Result result) {
812 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 737 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
813 738
814 std::map<std::string, RegisterCallback>::iterator callback_iter = 739 std::map<std::string, RegisterCallback>::iterator callback_iter =
815 register_callbacks_.find(app_id); 740 register_callbacks_.find(app_id);
816 if (callback_iter == register_callbacks_.end()) { 741 if (callback_iter == register_callbacks_.end()) {
817 // The callback could have been removed when the app is uninstalled. 742 // The callback could have been removed when the app is uninstalled.
818 return; 743 return;
819 } 744 }
820 745
821 RegisterCallback callback = callback_iter->second; 746 RegisterCallback callback = callback_iter->second;
822 register_callbacks_.erase(callback_iter); 747 register_callbacks_.erase(callback_iter);
823 callback.Run(registration_id, result); 748 callback.Run(registration_id, result);
824 } 749 }
825 750
826 void GCMProfileService::UnregisterFinished(const std::string& app_id, 751 void GCMService::UnregisterFinished(const std::string& app_id,
827 GCMClient::Result result) { 752 GCMClient::Result result) {
828 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 753 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
829 754
830 std::map<std::string, UnregisterCallback>::iterator callback_iter = 755 std::map<std::string, UnregisterCallback>::iterator callback_iter =
831 unregister_callbacks_.find(app_id); 756 unregister_callbacks_.find(app_id);
832 if (callback_iter == unregister_callbacks_.end()) 757 if (callback_iter == unregister_callbacks_.end())
833 return; 758 return;
834 759
835 UnregisterCallback callback = callback_iter->second; 760 UnregisterCallback callback = callback_iter->second;
836 unregister_callbacks_.erase(callback_iter); 761 unregister_callbacks_.erase(callback_iter);
837 callback.Run(result); 762 callback.Run(result);
838 } 763 }
839 764
840 void GCMProfileService::SendFinished(const std::string& app_id, 765 void GCMService::SendFinished(const std::string& app_id,
841 const std::string& message_id, 766 const std::string& message_id,
842 GCMClient::Result result) { 767 GCMClient::Result result) {
843 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 768 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
844 769
845 std::map<std::pair<std::string, std::string>, SendCallback>::iterator 770 std::map<std::pair<std::string, std::string>, SendCallback>::iterator
846 callback_iter = send_callbacks_.find( 771 callback_iter = send_callbacks_.find(
847 std::pair<std::string, std::string>(app_id, message_id)); 772 std::pair<std::string, std::string>(app_id, message_id));
848 if (callback_iter == send_callbacks_.end()) { 773 if (callback_iter == send_callbacks_.end()) {
849 // The callback could have been removed when the app is uninstalled. 774 // The callback could have been removed when the app is uninstalled.
850 return; 775 return;
851 } 776 }
852 777
853 SendCallback callback = callback_iter->second; 778 SendCallback callback = callback_iter->second;
854 send_callbacks_.erase(callback_iter); 779 send_callbacks_.erase(callback_iter);
855 callback.Run(message_id, result); 780 callback.Run(message_id, result);
856 } 781 }
857 782
858 void GCMProfileService::MessageReceived(const std::string& app_id, 783 void GCMService::MessageReceived(const std::string& app_id,
859 GCMClient::IncomingMessage message) { 784 GCMClient::IncomingMessage message) {
860 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 785 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
861 786
862 // Drop the event if signed out. 787 // Drop the event if signed out.
863 if (username_.empty()) 788 if (account_id_.empty())
864 return; 789 return;
865 790
866 GetAppHandler(app_id)->OnMessage(app_id, message); 791 GetAppHandler(app_id)->OnMessage(app_id, message);
867 } 792 }
868 793
869 void GCMProfileService::MessagesDeleted(const std::string& app_id) { 794 void GCMService::MessagesDeleted(const std::string& app_id) {
870 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 795 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
871 796
872 // Drop the event if signed out. 797 // Drop the event if signed out.
873 if (username_.empty()) 798 if (account_id_.empty())
874 return; 799 return;
875 800
876 GetAppHandler(app_id)->OnMessagesDeleted(app_id); 801 GetAppHandler(app_id)->OnMessagesDeleted(app_id);
877 } 802 }
878 803
879 void GCMProfileService::MessageSendError( 804 void GCMService::MessageSendError(
880 const std::string& app_id, 805 const std::string& app_id,
881 const GCMClient::SendErrorDetails& send_error_details) { 806 const GCMClient::SendErrorDetails& send_error_details) {
882 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 807 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
883 808
884 // Drop the event if signed out. 809 // Drop the event if signed out.
885 if (username_.empty()) 810 if (account_id_.empty())
886 return; 811 return;
887 812
888 GetAppHandler(app_id)->OnSendError(app_id, send_error_details); 813 GetAppHandler(app_id)->OnSendError(app_id, send_error_details);
889 } 814 }
890 815
891 void GCMProfileService::GCMClientReady() { 816 void GCMService::GCMClientReady() {
892 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 817 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
893 818
894 if (gcm_client_ready_) 819 if (gcm_client_ready_)
895 return; 820 return;
896 gcm_client_ready_ = true; 821 gcm_client_ready_ = true;
897 822
898 delayed_task_controller_->SetReady(); 823 delayed_task_controller_->SetReady();
899 } 824 }
900 825
901 GCMAppHandler* GCMProfileService::GetAppHandler(const std::string& app_id) { 826 GCMAppHandler* GCMService::GetAppHandler(const std::string& app_id) {
827 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
828
902 std::map<std::string, GCMAppHandler*>::const_iterator iter = 829 std::map<std::string, GCMAppHandler*>::const_iterator iter =
903 app_handlers_.find(app_id); 830 app_handlers_.find(app_id);
904 return iter == app_handlers_.end() ? &default_app_handler_ : iter->second; 831 return iter == app_handlers_.end() ? &default_app_handler_ : iter->second;
905 } 832 }
906 833
907 void GCMProfileService::RequestGCMStatisticsFinished( 834 void GCMService::RequestGCMStatisticsFinished(
908 GCMClient::GCMStatistics stats) { 835 GCMClient::GCMStatistics stats) {
909 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 836 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
910 837
911 request_gcm_statistics_callback_.Run(stats); 838 request_gcm_statistics_callback_.Run(stats);
912 } 839 }
913 840
914 } // namespace gcm 841 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698