OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/bind.h" | |
6 #include "base/location.h" | |
7 #include "base/single_thread_task_runner.h" | |
8 #include "base/thread_task_runner_handle.h" | |
9 #include "chrome/browser/invalidation/gcm_invalidation_bridge.h" | |
10 #include "chrome/browser/services/gcm/gcm_profile_service.h" | |
11 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" | |
12 #include "chrome/browser/signin/profile_oauth2_token_service.h" | |
13 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" | |
14 #include "google_apis/gaia/gaia_constants.h" | |
15 | |
16 namespace invalidation { | |
17 namespace { | |
18 // For 3rd party developers SenderId should come from application dashboard when | |
19 // server side application is registered with Google. Android invalidations use | |
20 // legacy format where gmail account can be specificed. Below value is copied | |
21 // from Android. | |
22 const char kInvalidationsSenderId[] = "ipc.invalidation@gmail.com"; | |
23 // In Android world AppId and Cert are provided by operating system and should | |
24 // match package name and hash of application. In desktop world these values | |
25 // are arbitrary and not verified/enforced by registration service (yet). | |
26 const char kInvalidationsAppId[] = "com.google.chrome.invalidations"; | |
27 const char kInvalidationsCert[] = "ABC"; | |
28 | |
29 } // namespace | |
30 | |
31 // Core should be very simple class that implements GCMNetwrokChannelDelegate | |
32 // and passes all calls to GCMInvalidationBridge. All calls should be serialized | |
33 // through GCMInvalidationBridge to avoid race conditions. | |
34 class GCMInvalidationBridge::Core : public syncer::GCMNetworkChannelDelegate, | |
35 public base::NonThreadSafe { | |
36 public: | |
37 Core(base::WeakPtr<GCMInvalidationBridge> bridge, | |
38 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner); | |
39 virtual ~Core(); | |
40 | |
41 // syncer::GCMNetworkChannelDelegate implementation. | |
42 virtual void Initialize() OVERRIDE; | |
43 virtual void RequestToken(RequestTokenCallback callback) OVERRIDE; | |
44 virtual void InvalidateToken(const std::string& token) OVERRIDE; | |
45 virtual void Register(RegisterCallback callback) OVERRIDE; | |
46 | |
47 void RequestTokenFinished(RequestTokenCallback callback, | |
48 const GoogleServiceAuthError& error, | |
49 const std::string& token); | |
50 | |
51 void RegisterFinished(RegisterCallback callback, | |
52 const std::string& registration_id, | |
53 gcm::GCMClient::Result result); | |
54 | |
55 private: | |
56 base::WeakPtr<GCMInvalidationBridge> bridge_; | |
57 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_; | |
58 | |
59 base::WeakPtrFactory<Core> weak_factory_; | |
60 | |
61 DISALLOW_COPY_AND_ASSIGN(Core); | |
62 }; | |
63 | |
64 GCMInvalidationBridge::Core::Core( | |
65 base::WeakPtr<GCMInvalidationBridge> bridge, | |
66 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) | |
67 : bridge_(bridge), | |
68 ui_thread_task_runner_(ui_thread_task_runner), | |
69 weak_factory_(this) { | |
70 // Core is created on UI thread but all calls happen on IO thread. | |
71 DetachFromThread(); | |
rlarocque
2014/03/04 19:43:06
Neat. I didn't know about this trick. I'll have
| |
72 } | |
73 | |
74 GCMInvalidationBridge::Core::~Core() {} | |
75 | |
76 void GCMInvalidationBridge::Core::Initialize() { | |
77 DCHECK(CalledOnValidThread()); | |
78 // Pass core WeapPtr and TaskRunner to GCMInvalidationBridge for it to be able | |
79 // to post back. | |
80 ui_thread_task_runner_->PostTask( | |
rlarocque
2014/03/04 19:43:06
Is this necessary?
I think it would be safe to ge
pavely
2014/03/04 20:14:42
This was deliberate. I need to pass TaskRunner of
rlarocque
2014/03/04 21:30:19
OK, that works. Just making sure that there was a
| |
81 FROM_HERE, | |
82 base::Bind(&GCMInvalidationBridge::CoreInitializationDone, | |
83 bridge_, | |
84 weak_factory_.GetWeakPtr(), | |
85 base::ThreadTaskRunnerHandle::Get())); | |
86 } | |
87 | |
88 void GCMInvalidationBridge::Core::RequestToken(RequestTokenCallback callback) { | |
89 DCHECK(CalledOnValidThread()); | |
90 ui_thread_task_runner_->PostTask( | |
91 FROM_HERE, | |
92 base::Bind(&GCMInvalidationBridge::RequestToken, bridge_, callback)); | |
93 } | |
94 | |
95 void GCMInvalidationBridge::Core::InvalidateToken(const std::string& token) { | |
96 DCHECK(CalledOnValidThread()); | |
97 ui_thread_task_runner_->PostTask( | |
98 FROM_HERE, | |
99 base::Bind(&GCMInvalidationBridge::InvalidateToken, bridge_, token)); | |
100 } | |
101 | |
102 void GCMInvalidationBridge::Core::Register(RegisterCallback callback) { | |
103 DCHECK(CalledOnValidThread()); | |
104 ui_thread_task_runner_->PostTask( | |
105 FROM_HERE, | |
106 base::Bind(&GCMInvalidationBridge::Register, bridge_, callback)); | |
107 } | |
108 | |
109 void GCMInvalidationBridge::Core::RequestTokenFinished( | |
110 RequestTokenCallback callback, | |
111 const GoogleServiceAuthError& error, | |
112 const std::string& token) { | |
113 DCHECK(CalledOnValidThread()); | |
114 callback.Run(error, token); | |
115 } | |
116 | |
117 void GCMInvalidationBridge::Core::RegisterFinished( | |
118 RegisterCallback callback, | |
119 const std::string& registration_id, | |
120 gcm::GCMClient::Result result) { | |
121 DCHECK(CalledOnValidThread()); | |
122 callback.Run(registration_id, result); | |
123 } | |
124 | |
125 GCMInvalidationBridge::GCMInvalidationBridge(Profile* profile) | |
126 : OAuth2TokenService::Consumer("gcm_network_channel"), | |
127 profile_(profile), | |
128 weak_factory_(this) {} | |
129 | |
130 GCMInvalidationBridge::~GCMInvalidationBridge() {} | |
131 | |
132 scoped_ptr<syncer::GCMNetworkChannelDelegate> | |
133 GCMInvalidationBridge::CreateDelegate() { | |
134 DCHECK(CalledOnValidThread()); | |
135 scoped_ptr<syncer::GCMNetworkChannelDelegate> core(new Core( | |
136 weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get())); | |
137 return core.Pass(); | |
138 } | |
139 | |
140 void GCMInvalidationBridge::CoreInitializationDone( | |
141 base::WeakPtr<Core> core, | |
142 scoped_refptr<base::SingleThreadTaskRunner> core_thread_task_runner) { | |
143 DCHECK(CalledOnValidThread()); | |
144 core_ = core; | |
145 core_thread_task_runner_ = core_thread_task_runner; | |
146 } | |
147 | |
148 void GCMInvalidationBridge::RequestToken( | |
149 syncer::GCMNetworkChannelDelegate::RequestTokenCallback callback) { | |
150 DCHECK(CalledOnValidThread()); | |
151 if (access_token_request_ != NULL) { | |
152 // Report previous request as cancelled. | |
153 GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); | |
154 std::string access_token; | |
155 core_thread_task_runner_->PostTask( | |
156 FROM_HERE, | |
157 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished, | |
158 core_, | |
159 request_token_callback_, | |
160 error, | |
161 access_token)); | |
162 } | |
163 ProfileOAuth2TokenService* token_service = | |
164 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); | |
165 request_token_callback_ = callback; | |
166 std::string account_id = token_service->GetPrimaryAccountId(); | |
167 OAuth2TokenService::ScopeSet scopes; | |
168 scopes.insert(GaiaConstants::kGoogleTalkOAuth2Scope); | |
169 access_token_request_ = token_service->StartRequest(account_id, scopes, this); | |
170 } | |
171 | |
172 void GCMInvalidationBridge::OnGetTokenSuccess( | |
173 const OAuth2TokenService::Request* request, | |
174 const std::string& access_token, | |
175 const base::Time& expiration_time) { | |
176 DCHECK(CalledOnValidThread()); | |
177 DCHECK_EQ(access_token_request_, request); | |
178 core_thread_task_runner_->PostTask( | |
179 FROM_HERE, | |
180 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished, | |
181 core_, | |
182 request_token_callback_, | |
183 GoogleServiceAuthError::AuthErrorNone(), | |
184 access_token)); | |
185 request_token_callback_.Reset(); | |
186 access_token_request_.reset(); | |
187 } | |
188 | |
189 void GCMInvalidationBridge::OnGetTokenFailure( | |
190 const OAuth2TokenService::Request* request, | |
191 const GoogleServiceAuthError& error) { | |
192 DCHECK(CalledOnValidThread()); | |
193 DCHECK_EQ(access_token_request_, request); | |
194 core_thread_task_runner_->PostTask( | |
195 FROM_HERE, | |
196 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished, | |
197 core_, | |
198 request_token_callback_, | |
199 error, | |
200 std::string())); | |
201 request_token_callback_.Reset(); | |
202 access_token_request_.reset(); | |
203 } | |
204 | |
205 void GCMInvalidationBridge::InvalidateToken(const std::string& token) { | |
206 ProfileOAuth2TokenService* token_service = | |
207 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); | |
208 DCHECK(CalledOnValidThread()); | |
209 std::string account_id = token_service->GetPrimaryAccountId(); | |
210 OAuth2TokenService::ScopeSet scopes; | |
211 scopes.insert(GaiaConstants::kGoogleTalkOAuth2Scope); | |
212 token_service->InvalidateToken(account_id, scopes, token); | |
213 } | |
214 | |
215 void GCMInvalidationBridge::Register( | |
216 syncer::GCMNetworkChannelDelegate::RegisterCallback callback) { | |
217 DCHECK(CalledOnValidThread()); | |
218 // No-op if GCMClient is disabled. | |
219 gcm::GCMProfileService* gcm_profile_service = | |
220 gcm::GCMProfileServiceFactory::GetForProfile(profile_); | |
221 if (gcm_profile_service == NULL) | |
222 return; | |
223 | |
224 std::vector<std::string> sender_ids; | |
225 sender_ids.push_back(kInvalidationsSenderId); | |
226 gcm_profile_service->Register( | |
227 kInvalidationsAppId, | |
228 sender_ids, | |
229 kInvalidationsCert, | |
230 base::Bind(&GCMInvalidationBridge::RegisterFinished, | |
231 weak_factory_.GetWeakPtr(), | |
232 callback)); | |
233 } | |
234 | |
235 void GCMInvalidationBridge::RegisterFinished( | |
236 syncer::GCMNetworkChannelDelegate::RegisterCallback callback, | |
237 const std::string& registration_id, | |
238 gcm::GCMClient::Result result) { | |
239 DCHECK(CalledOnValidThread()); | |
240 core_thread_task_runner_->PostTask( | |
241 FROM_HERE, | |
242 base::Bind(&GCMInvalidationBridge::Core::RegisterFinished, | |
243 core_, | |
244 callback, | |
245 registration_id, | |
246 result)); | |
247 } | |
248 | |
249 } // namespace invalidation | |
OLD | NEW |