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