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