| OLD | NEW |
| 1 // Copyright 2014 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 "base/base64.h" | 5 #include "base/base64.h" |
| 6 #include "base/i18n/time_formatting.h" | 6 #include "base/i18n/time_formatting.h" |
| 7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "base/sha1.h" | 8 #include "base/sha1.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 } | 100 } |
| 101 | 101 |
| 102 } // namespace | 102 } // namespace |
| 103 | 103 |
| 104 GCMNetworkChannel::GCMNetworkChannel( | 104 GCMNetworkChannel::GCMNetworkChannel( |
| 105 scoped_refptr<net::URLRequestContextGetter> request_context_getter, | 105 scoped_refptr<net::URLRequestContextGetter> request_context_getter, |
| 106 scoped_ptr<GCMNetworkChannelDelegate> delegate) | 106 scoped_ptr<GCMNetworkChannelDelegate> delegate) |
| 107 : request_context_getter_(request_context_getter), | 107 : request_context_getter_(request_context_getter), |
| 108 delegate_(delegate.Pass()), | 108 delegate_(delegate.Pass()), |
| 109 register_backoff_entry_(new net::BackoffEntry(&kRegisterBackoffPolicy)), | 109 register_backoff_entry_(new net::BackoffEntry(&kRegisterBackoffPolicy)), |
| 110 gcm_channel_online_(false), |
| 111 http_channel_online_(false), |
| 110 diagnostic_info_(this), | 112 diagnostic_info_(this), |
| 111 weak_factory_(this) { | 113 weak_factory_(this) { |
| 112 net::NetworkChangeNotifier::AddNetworkChangeObserver(this); | 114 net::NetworkChangeNotifier::AddNetworkChangeObserver(this); |
| 113 delegate_->Initialize(base::Bind(&GCMNetworkChannel::OnConnectionStateChanged, | 115 delegate_->Initialize(base::Bind(&GCMNetworkChannel::OnConnectionStateChanged, |
| 114 weak_factory_.GetWeakPtr())); | 116 weak_factory_.GetWeakPtr())); |
| 115 Register(); | 117 Register(); |
| 116 } | 118 } |
| 117 | 119 |
| 118 GCMNetworkChannel::~GCMNetworkChannel() { | 120 GCMNetworkChannel::~GCMNetworkChannel() { |
| 119 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); | 121 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 // Nothing to do. | 190 // Nothing to do. |
| 189 return; | 191 return; |
| 190 } | 192 } |
| 191 | 193 |
| 192 if (error.state() != GoogleServiceAuthError::NONE) { | 194 if (error.state() != GoogleServiceAuthError::NONE) { |
| 193 // Requesting access token failed. Persistent errors will be reported by | 195 // Requesting access token failed. Persistent errors will be reported by |
| 194 // token service. Just drop this request, cacheinvalidations will retry | 196 // token service. Just drop this request, cacheinvalidations will retry |
| 195 // sending message and at that time we'll retry requesting access token. | 197 // sending message and at that time we'll retry requesting access token. |
| 196 DVLOG(1) << "RequestAccessToken failed: " << error.ToString(); | 198 DVLOG(1) << "RequestAccessToken failed: " << error.ToString(); |
| 197 RecordOutgoingMessageStatus(ACCESS_TOKEN_FAILURE); | 199 RecordOutgoingMessageStatus(ACCESS_TOKEN_FAILURE); |
| 198 // Message won't get sent because of connection failure. Let's retry once | 200 // Message won't get sent. Notify that http channel doesn't work. |
| 199 // connection is restored. | 201 UpdateHttpChannelState(false); |
| 200 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) | |
| 201 NotifyStateChange(TRANSIENT_INVALIDATION_ERROR); | |
| 202 cached_message_.clear(); | 202 cached_message_.clear(); |
| 203 return; | 203 return; |
| 204 } | 204 } |
| 205 DCHECK(!token.empty()); | 205 DCHECK(!token.empty()); |
| 206 // Save access token in case POST fails and we need to invalidate it. | 206 // Save access token in case POST fails and we need to invalidate it. |
| 207 access_token_ = token; | 207 access_token_ = token; |
| 208 | 208 |
| 209 DVLOG(2) << "Got access token, sending message"; | 209 DVLOG(2) << "Got access token, sending message"; |
| 210 fetcher_.reset(net::URLFetcher::Create( | 210 fetcher_.reset(net::URLFetcher::Create( |
| 211 BuildUrl(registration_id_), net::URLFetcher::POST, this)); | 211 BuildUrl(registration_id_), net::URLFetcher::POST, this)); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 236 fetcher->GetResponseCode() == net::HTTP_UNAUTHORIZED) { | 236 fetcher->GetResponseCode() == net::HTTP_UNAUTHORIZED) { |
| 237 DVLOG(1) << "URLFetcher failure: HTTP_UNAUTHORIZED"; | 237 DVLOG(1) << "URLFetcher failure: HTTP_UNAUTHORIZED"; |
| 238 delegate_->InvalidateToken(access_token_); | 238 delegate_->InvalidateToken(access_token_); |
| 239 } | 239 } |
| 240 | 240 |
| 241 if (!status.is_success() || | 241 if (!status.is_success() || |
| 242 (fetcher->GetResponseCode() != net::HTTP_OK && | 242 (fetcher->GetResponseCode() != net::HTTP_OK && |
| 243 fetcher->GetResponseCode() != net::HTTP_NO_CONTENT)) { | 243 fetcher->GetResponseCode() != net::HTTP_NO_CONTENT)) { |
| 244 DVLOG(1) << "URLFetcher failure"; | 244 DVLOG(1) << "URLFetcher failure"; |
| 245 RecordOutgoingMessageStatus(POST_FAILURE); | 245 RecordOutgoingMessageStatus(POST_FAILURE); |
| 246 NotifyStateChange(TRANSIENT_INVALIDATION_ERROR); | 246 // POST failed. Notify that http channel doesn't work. |
| 247 UpdateHttpChannelState(false); |
| 247 return; | 248 return; |
| 248 } | 249 } |
| 249 | 250 |
| 250 RecordOutgoingMessageStatus(OUTGOING_MESSAGE_SUCCESS); | 251 RecordOutgoingMessageStatus(OUTGOING_MESSAGE_SUCCESS); |
| 251 NotifyStateChange(INVALIDATIONS_ENABLED); | 252 // Successfully sent message. Http channel works. |
| 253 UpdateHttpChannelState(true); |
| 252 DVLOG(2) << "URLFetcher success"; | 254 DVLOG(2) << "URLFetcher success"; |
| 253 } | 255 } |
| 254 | 256 |
| 255 void GCMNetworkChannel::OnIncomingMessage(const std::string& message, | 257 void GCMNetworkChannel::OnIncomingMessage(const std::string& message, |
| 256 const std::string& echo_token) { | 258 const std::string& echo_token) { |
| 257 #if !defined(OS_ANDROID) | 259 #if !defined(OS_ANDROID) |
| 258 if (!echo_token.empty()) | 260 if (!echo_token.empty()) |
| 259 echo_token_ = echo_token; | 261 echo_token_ = echo_token; |
| 260 diagnostic_info_.last_message_empty_echo_token_ = echo_token.empty(); | 262 diagnostic_info_.last_message_empty_echo_token_ = echo_token.empty(); |
| 261 diagnostic_info_.last_message_received_time_ = base::Time::Now(); | 263 diagnostic_info_.last_message_received_time_ = base::Time::Now(); |
| 262 | 264 |
| 263 if (message.empty()) { | 265 if (message.empty()) { |
| 264 RecordIncomingMessageStatus(MESSAGE_EMPTY); | 266 RecordIncomingMessageStatus(MESSAGE_EMPTY); |
| 265 return; | 267 return; |
| 266 } | 268 } |
| 267 std::string data; | 269 std::string data; |
| 268 if (!Base64DecodeURLSafe(message, &data)) { | 270 if (!Base64DecodeURLSafe(message, &data)) { |
| 269 RecordIncomingMessageStatus(INVALID_ENCODING); | 271 RecordIncomingMessageStatus(INVALID_ENCODING); |
| 270 return; | 272 return; |
| 271 } | 273 } |
| 272 ipc::invalidation::AddressedAndroidMessage android_message; | 274 ipc::invalidation::AddressedAndroidMessage android_message; |
| 273 if (!android_message.ParseFromString(data) || | 275 if (!android_message.ParseFromString(data) || |
| 274 !android_message.has_message()) { | 276 !android_message.has_message()) { |
| 275 RecordIncomingMessageStatus(INVALID_PROTO); | 277 RecordIncomingMessageStatus(INVALID_PROTO); |
| 276 return; | 278 return; |
| 277 } | 279 } |
| 278 DVLOG(2) << "Deliver incoming message"; | 280 DVLOG(2) << "Deliver incoming message"; |
| 279 RecordIncomingMessageStatus(INCOMING_MESSAGE_SUCCESS); | 281 RecordIncomingMessageStatus(INCOMING_MESSAGE_SUCCESS); |
| 282 UpdateGcmChannelState(true); |
| 280 DeliverIncomingMessage(android_message.message()); | 283 DeliverIncomingMessage(android_message.message()); |
| 281 #else | 284 #else |
| 282 // This code shouldn't be invoked on Android. | 285 // This code shouldn't be invoked on Android. |
| 283 NOTREACHED(); | 286 NOTREACHED(); |
| 284 #endif | 287 #endif |
| 285 } | 288 } |
| 286 | 289 |
| 287 void GCMNetworkChannel::OnConnectionStateChanged( | 290 void GCMNetworkChannel::OnConnectionStateChanged(bool online) { |
| 288 GCMNetworkChannelDelegate::ConnectionState connection_state) { | 291 UpdateGcmChannelState(online); |
| 289 switch (connection_state) { | |
| 290 case GCMNetworkChannelDelegate::CONNECTION_STATE_OFFLINE: { | |
| 291 NotifyStateChange(TRANSIENT_INVALIDATION_ERROR); | |
| 292 break; | |
| 293 } | |
| 294 case GCMNetworkChannelDelegate::CONNECTION_STATE_ONLINE: { | |
| 295 NotifyStateChange(INVALIDATIONS_ENABLED); | |
| 296 break; | |
| 297 } | |
| 298 default: { | |
| 299 NOTREACHED(); | |
| 300 break; | |
| 301 } | |
| 302 } | |
| 303 } | 292 } |
| 304 | 293 |
| 305 void GCMNetworkChannel::OnNetworkChanged( | 294 void GCMNetworkChannel::OnNetworkChanged( |
| 306 net::NetworkChangeNotifier::ConnectionType connection_type) { | 295 net::NetworkChangeNotifier::ConnectionType connection_type) { |
| 307 // Network connection is restored. Let's notify cacheinvalidations so it has | 296 // Network connection is restored. Let's notify cacheinvalidations so it has |
| 308 // chance to retry. | 297 // chance to retry. |
| 309 if (connection_type != net::NetworkChangeNotifier::CONNECTION_NONE) | 298 NotifyNetworkStatusChange( |
| 310 NotifyStateChange(INVALIDATIONS_ENABLED); | 299 connection_type != net::NetworkChangeNotifier::CONNECTION_NONE); |
| 300 } |
| 301 |
| 302 void GCMNetworkChannel::UpdateGcmChannelState(bool online) { |
| 303 if (gcm_channel_online_ == online) |
| 304 return; |
| 305 gcm_channel_online_ = online; |
| 306 InvalidatorState channel_state = TRANSIENT_INVALIDATION_ERROR; |
| 307 if (gcm_channel_online_ && http_channel_online_) |
| 308 channel_state = INVALIDATIONS_ENABLED; |
| 309 NotifyChannelStateChange(channel_state); |
| 310 } |
| 311 |
| 312 void GCMNetworkChannel::UpdateHttpChannelState(bool online) { |
| 313 if (http_channel_online_ == online) |
| 314 return; |
| 315 http_channel_online_ = online; |
| 316 InvalidatorState channel_state = TRANSIENT_INVALIDATION_ERROR; |
| 317 if (gcm_channel_online_ && http_channel_online_) |
| 318 channel_state = INVALIDATIONS_ENABLED; |
| 319 NotifyChannelStateChange(channel_state); |
| 311 } | 320 } |
| 312 | 321 |
| 313 GURL GCMNetworkChannel::BuildUrl(const std::string& registration_id) { | 322 GURL GCMNetworkChannel::BuildUrl(const std::string& registration_id) { |
| 314 DCHECK(!registration_id.empty()); | 323 DCHECK(!registration_id.empty()); |
| 315 | 324 |
| 316 #if !defined(OS_ANDROID) | 325 #if !defined(OS_ANDROID) |
| 317 ipc::invalidation::EndpointId endpoint_id; | 326 ipc::invalidation::EndpointId endpoint_id; |
| 318 endpoint_id.set_c2dm_registration_id(registration_id); | 327 endpoint_id.set_c2dm_registration_id(registration_id); |
| 319 endpoint_id.set_client_key(std::string()); | 328 endpoint_id.set_client_key(std::string()); |
| 320 endpoint_id.set_package_name(kCacheInvalidationPackageName); | 329 endpoint_id.set_package_name(kCacheInvalidationPackageName); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 ENUM_CASE(gcm::GCMClient::NOT_SIGNED_IN); | 449 ENUM_CASE(gcm::GCMClient::NOT_SIGNED_IN); |
| 441 ENUM_CASE(gcm::GCMClient::INVALID_PARAMETER); | 450 ENUM_CASE(gcm::GCMClient::INVALID_PARAMETER); |
| 442 ENUM_CASE(gcm::GCMClient::ASYNC_OPERATION_PENDING); | 451 ENUM_CASE(gcm::GCMClient::ASYNC_OPERATION_PENDING); |
| 443 ENUM_CASE(gcm::GCMClient::GCM_DISABLED); | 452 ENUM_CASE(gcm::GCMClient::GCM_DISABLED); |
| 444 } | 453 } |
| 445 NOTREACHED(); | 454 NOTREACHED(); |
| 446 return ""; | 455 return ""; |
| 447 } | 456 } |
| 448 | 457 |
| 449 } // namespace syncer | 458 } // namespace syncer |
| OLD | NEW |