[safe-browsing] Database full hash matches like prefix match.
[chromium-blink-merge.git] / chrome / browser / invalidation / gcm_invalidation_bridge.cc
blob88d09719bbc2d22714263cbd472d72c70ad64467
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.
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_service.h"
11 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
12 #include "chrome/browser/signin/signin_manager_factory.h"
13 #include "components/signin/core/browser/profile_oauth2_token_service.h"
14 #include "components/signin/core/browser/signin_manager.h"
15 #include "google_apis/gaia/gaia_constants.h"
16 #include "google_apis/gaia/identity_provider.h"
18 namespace invalidation {
19 namespace {
20 // For 3rd party developers SenderId should come from application dashboard when
21 // server side application is registered with Google. Android invalidations use
22 // legacy format where gmail account can be specificed. Below value is copied
23 // from Android.
24 const char kInvalidationsSenderId[] = "ipc.invalidation@gmail.com";
25 // In Android world AppId is provided by operating system and should
26 // match package name and hash of application. In desktop world these values
27 // are arbitrary and not verified/enforced by registration service (yet).
28 const char kInvalidationsAppId[] = "com.google.chrome.invalidations";
30 // Cacheinvalidation specific gcm message keys.
31 const char kContentKey[] = "content";
32 const char kEchoTokenKey[] = "echo-token";
33 } // namespace
35 // Core should be very simple class that implements GCMNetwrokChannelDelegate
36 // and passes all calls to GCMInvalidationBridge. All calls should be serialized
37 // through GCMInvalidationBridge to avoid race conditions.
38 class GCMInvalidationBridge::Core : public syncer::GCMNetworkChannelDelegate,
39 public base::NonThreadSafe {
40 public:
41 Core(base::WeakPtr<GCMInvalidationBridge> bridge,
42 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner);
43 virtual ~Core();
45 // syncer::GCMNetworkChannelDelegate implementation.
46 virtual void Initialize() OVERRIDE;
47 virtual void RequestToken(RequestTokenCallback callback) OVERRIDE;
48 virtual void InvalidateToken(const std::string& token) OVERRIDE;
49 virtual void Register(RegisterCallback callback) OVERRIDE;
50 virtual void SetMessageReceiver(MessageCallback callback) OVERRIDE;
52 void RequestTokenFinished(RequestTokenCallback callback,
53 const GoogleServiceAuthError& error,
54 const std::string& token);
56 void RegisterFinished(RegisterCallback callback,
57 const std::string& registration_id,
58 gcm::GCMClient::Result result);
60 void OnIncomingMessage(const std::string& message,
61 const std::string& echo_token);
63 private:
64 base::WeakPtr<GCMInvalidationBridge> bridge_;
65 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_;
67 MessageCallback message_callback_;
69 base::WeakPtrFactory<Core> weak_factory_;
71 DISALLOW_COPY_AND_ASSIGN(Core);
74 GCMInvalidationBridge::Core::Core(
75 base::WeakPtr<GCMInvalidationBridge> bridge,
76 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
77 : bridge_(bridge),
78 ui_thread_task_runner_(ui_thread_task_runner),
79 weak_factory_(this) {
80 // Core is created on UI thread but all calls happen on IO thread.
81 DetachFromThread();
84 GCMInvalidationBridge::Core::~Core() {}
86 void GCMInvalidationBridge::Core::Initialize() {
87 DCHECK(CalledOnValidThread());
88 // Pass core WeapPtr and TaskRunner to GCMInvalidationBridge for it to be able
89 // to post back.
90 ui_thread_task_runner_->PostTask(
91 FROM_HERE,
92 base::Bind(&GCMInvalidationBridge::CoreInitializationDone,
93 bridge_,
94 weak_factory_.GetWeakPtr(),
95 base::ThreadTaskRunnerHandle::Get()));
98 void GCMInvalidationBridge::Core::RequestToken(RequestTokenCallback callback) {
99 DCHECK(CalledOnValidThread());
100 ui_thread_task_runner_->PostTask(
101 FROM_HERE,
102 base::Bind(&GCMInvalidationBridge::RequestToken, bridge_, callback));
105 void GCMInvalidationBridge::Core::InvalidateToken(const std::string& token) {
106 DCHECK(CalledOnValidThread());
107 ui_thread_task_runner_->PostTask(
108 FROM_HERE,
109 base::Bind(&GCMInvalidationBridge::InvalidateToken, bridge_, token));
112 void GCMInvalidationBridge::Core::Register(RegisterCallback callback) {
113 DCHECK(CalledOnValidThread());
114 ui_thread_task_runner_->PostTask(
115 FROM_HERE,
116 base::Bind(&GCMInvalidationBridge::Register, bridge_, callback));
119 void GCMInvalidationBridge::Core::SetMessageReceiver(MessageCallback callback) {
120 message_callback_ = callback;
121 ui_thread_task_runner_->PostTask(
122 FROM_HERE,
123 base::Bind(&GCMInvalidationBridge::SubscribeForIncomingMessages,
124 bridge_));
127 void GCMInvalidationBridge::Core::RequestTokenFinished(
128 RequestTokenCallback callback,
129 const GoogleServiceAuthError& error,
130 const std::string& token) {
131 DCHECK(CalledOnValidThread());
132 callback.Run(error, token);
135 void GCMInvalidationBridge::Core::RegisterFinished(
136 RegisterCallback callback,
137 const std::string& registration_id,
138 gcm::GCMClient::Result result) {
139 DCHECK(CalledOnValidThread());
140 callback.Run(registration_id, result);
143 void GCMInvalidationBridge::Core::OnIncomingMessage(
144 const std::string& message,
145 const std::string& echo_token) {
146 DCHECK(!message_callback_.is_null());
147 message_callback_.Run(message, echo_token);
150 GCMInvalidationBridge::GCMInvalidationBridge(
151 gcm::GCMService* gcm_service,
152 IdentityProvider* identity_provider)
153 : OAuth2TokenService::Consumer("gcm_network_channel"),
154 gcm_service_(gcm_service),
155 identity_provider_(identity_provider),
156 subscribed_for_incoming_messages_(false),
157 weak_factory_(this) {}
159 GCMInvalidationBridge::~GCMInvalidationBridge() {
160 if (subscribed_for_incoming_messages_)
161 gcm_service_->RemoveAppHandler(kInvalidationsAppId);
164 scoped_ptr<syncer::GCMNetworkChannelDelegate>
165 GCMInvalidationBridge::CreateDelegate() {
166 DCHECK(CalledOnValidThread());
167 scoped_ptr<syncer::GCMNetworkChannelDelegate> core(new Core(
168 weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get()));
169 return core.Pass();
172 void GCMInvalidationBridge::CoreInitializationDone(
173 base::WeakPtr<Core> core,
174 scoped_refptr<base::SingleThreadTaskRunner> core_thread_task_runner) {
175 DCHECK(CalledOnValidThread());
176 core_ = core;
177 core_thread_task_runner_ = core_thread_task_runner;
180 void GCMInvalidationBridge::RequestToken(
181 syncer::GCMNetworkChannelDelegate::RequestTokenCallback callback) {
182 DCHECK(CalledOnValidThread());
183 if (access_token_request_ != NULL) {
184 // Report previous request as cancelled.
185 GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
186 std::string access_token;
187 core_thread_task_runner_->PostTask(
188 FROM_HERE,
189 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished,
190 core_,
191 request_token_callback_,
192 error,
193 access_token));
195 request_token_callback_ = callback;
196 OAuth2TokenService::ScopeSet scopes;
197 scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
198 access_token_request_ = identity_provider_->GetTokenService()->StartRequest(
199 identity_provider_->GetActiveAccountId(), scopes, this);
202 void GCMInvalidationBridge::OnGetTokenSuccess(
203 const OAuth2TokenService::Request* request,
204 const std::string& access_token,
205 const base::Time& expiration_time) {
206 DCHECK(CalledOnValidThread());
207 DCHECK_EQ(access_token_request_, request);
208 core_thread_task_runner_->PostTask(
209 FROM_HERE,
210 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished,
211 core_,
212 request_token_callback_,
213 GoogleServiceAuthError::AuthErrorNone(),
214 access_token));
215 request_token_callback_.Reset();
216 access_token_request_.reset();
219 void GCMInvalidationBridge::OnGetTokenFailure(
220 const OAuth2TokenService::Request* request,
221 const GoogleServiceAuthError& error) {
222 DCHECK(CalledOnValidThread());
223 DCHECK_EQ(access_token_request_, request);
224 core_thread_task_runner_->PostTask(
225 FROM_HERE,
226 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished,
227 core_,
228 request_token_callback_,
229 error,
230 std::string()));
231 request_token_callback_.Reset();
232 access_token_request_.reset();
235 void GCMInvalidationBridge::InvalidateToken(const std::string& token) {
236 DCHECK(CalledOnValidThread());
237 OAuth2TokenService::ScopeSet scopes;
238 scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
239 identity_provider_->GetTokenService()->InvalidateToken(
240 identity_provider_->GetActiveAccountId(), scopes, token);
243 void GCMInvalidationBridge::Register(
244 syncer::GCMNetworkChannelDelegate::RegisterCallback callback) {
245 DCHECK(CalledOnValidThread());
246 // No-op if GCMClient is disabled.
247 if (gcm_service_ == NULL)
248 return;
250 std::vector<std::string> sender_ids;
251 sender_ids.push_back(kInvalidationsSenderId);
252 gcm_service_->Register(kInvalidationsAppId,
253 sender_ids,
254 base::Bind(&GCMInvalidationBridge::RegisterFinished,
255 weak_factory_.GetWeakPtr(),
256 callback));
259 void GCMInvalidationBridge::RegisterFinished(
260 syncer::GCMNetworkChannelDelegate::RegisterCallback callback,
261 const std::string& registration_id,
262 gcm::GCMClient::Result result) {
263 DCHECK(CalledOnValidThread());
264 core_thread_task_runner_->PostTask(
265 FROM_HERE,
266 base::Bind(&GCMInvalidationBridge::Core::RegisterFinished,
267 core_,
268 callback,
269 registration_id,
270 result));
273 void GCMInvalidationBridge::SubscribeForIncomingMessages() {
274 // No-op if GCMClient is disabled.
275 if (gcm_service_ == NULL)
276 return;
278 DCHECK(!subscribed_for_incoming_messages_);
279 gcm_service_->AddAppHandler(kInvalidationsAppId, this);
280 subscribed_for_incoming_messages_ = true;
283 void GCMInvalidationBridge::ShutdownHandler() {
284 // Nothing to do.
287 void GCMInvalidationBridge::OnMessage(
288 const std::string& app_id,
289 const gcm::GCMClient::IncomingMessage& message) {
290 gcm::GCMClient::MessageData::const_iterator it;
291 std::string content;
292 std::string echo_token;
293 it = message.data.find(kContentKey);
294 if (it != message.data.end())
295 content = it->second;
296 it = message.data.find(kEchoTokenKey);
297 if (it != message.data.end())
298 echo_token = it->second;
300 core_thread_task_runner_->PostTask(
301 FROM_HERE,
302 base::Bind(&GCMInvalidationBridge::Core::OnIncomingMessage,
303 core_,
304 content,
305 echo_token));
308 void GCMInvalidationBridge::OnMessagesDeleted(const std::string& app_id) {
309 // Cacheinvalidation doesn't use long lived non-collapsable messages with GCM.
310 // Android implementation of cacheinvalidation doesn't handle MessagesDeleted
311 // callback so this should be no-op in desktop version as well.
314 void GCMInvalidationBridge::OnSendError(
315 const std::string& app_id,
316 const gcm::GCMClient::SendErrorDetails& send_error_details) {
317 // cacheinvalidation doesn't send messages over GCM.
318 NOTREACHED();
321 } // namespace invalidation