Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: sync/notifier/gcm_network_channel.cc

Issue 217653002: Cleanup changes in gcm_network_channel (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | sync/notifier/gcm_network_channel_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #if !defined(ANDROID) 11 #if !defined(OS_ANDROID)
12 // channel_common.proto defines ANDROID constant that conflicts with Android 12 // channel_common.proto defines ANDROID constant that conflicts with Android
13 // build. At the same time TiclInvalidationService is not used on Android so it 13 // build. At the same time TiclInvalidationService is not used on Android so it
14 // is safe to exclude these protos from Android build. 14 // is safe to exclude these protos from Android build.
15 #include "google/cacheinvalidation/android_channel.pb.h" 15 #include "google/cacheinvalidation/android_channel.pb.h"
16 #include "google/cacheinvalidation/channel_common.pb.h" 16 #include "google/cacheinvalidation/channel_common.pb.h"
17 #endif 17 #endif
18 #include "google_apis/gaia/google_service_auth_error.h" 18 #include "google_apis/gaia/google_service_auth_error.h"
19 #include "net/http/http_status_code.h" 19 #include "net/http/http_status_code.h"
20 #include "net/url_request/url_fetcher.h" 20 #include "net/url_request/url_fetcher.h"
21 #include "net/url_request/url_request_status.h" 21 #include "net/url_request/url_request_status.h"
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 } 93 }
94 94
95 void RecordOutgoingMessageStatus(OutgoingMessageStatus status) { 95 void RecordOutgoingMessageStatus(OutgoingMessageStatus status) {
96 UMA_HISTOGRAM_ENUMERATION(kOutgoingMessageStatusHistogram, 96 UMA_HISTOGRAM_ENUMERATION(kOutgoingMessageStatusHistogram,
97 MESSAGE_DISCARDED, 97 MESSAGE_DISCARDED,
98 OUTGOING_MESSAGE_STATUS_COUNT); 98 OUTGOING_MESSAGE_STATUS_COUNT);
99 } 99 }
100 100
101 } // namespace 101 } // namespace
102 102
103 GCMNetworkChannelDiagnostic::GCMNetworkChannelDiagnostic(
104 GCMNetworkChannel* parent)
105 : parent_(parent),
106 last_message_empty_echo_token_(false),
107 last_post_response_code_(0),
108 registration_result_(gcm::GCMClient::UNKNOWN_ERROR),
109 sent_messages_count_(0) {}
110
111 scoped_ptr<base::DictionaryValue>
112 GCMNetworkChannelDiagnostic::CollectDebugData() const {
113 scoped_ptr<base::DictionaryValue> status(new base::DictionaryValue);
114 status->SetString("GCMNetworkChannel.Channel", "GCM");
115 std::string reg_id_hash = base::SHA1HashString(registration_id_);
116 status->SetString("GCMNetworkChannel.HashedRegistrationID",
117 base::HexEncode(reg_id_hash.c_str(), reg_id_hash.size()));
118 status->SetString("GCMNetworkChannel.RegistrationResult",
119 GCMClientResultToString(registration_result_));
120 status->SetBoolean("GCMNetworkChannel.HadLastMessageEmptyEchoToken",
121 last_message_empty_echo_token_);
122 status->SetString(
123 "GCMNetworkChannel.LastMessageReceivedTime",
124 base::TimeFormatShortDateAndTime(last_message_received_time_));
125 status->SetInteger("GCMNetworkChannel.LastPostResponseCode",
126 last_post_response_code_);
127 status->SetInteger("GCMNetworkChannel.SentMessages", sent_messages_count_);
128 status->SetInteger("GCMNetworkChannel.ReceivedMessages",
129 parent_->GetReceivedMessagesCount());
130 return status.Pass();
131 }
132
133 std::string GCMNetworkChannelDiagnostic::GCMClientResultToString(
134 const gcm::GCMClient::Result result) const {
135 #define ENUM_CASE(x) case x: return #x; break;
136 switch (result) {
137 ENUM_CASE(gcm::GCMClient::SUCCESS);
138 ENUM_CASE(gcm::GCMClient::NETWORK_ERROR);
139 ENUM_CASE(gcm::GCMClient::SERVER_ERROR);
140 ENUM_CASE(gcm::GCMClient::TTL_EXCEEDED);
141 ENUM_CASE(gcm::GCMClient::UNKNOWN_ERROR);
142 ENUM_CASE(gcm::GCMClient::NOT_SIGNED_IN);
143 ENUM_CASE(gcm::GCMClient::INVALID_PARAMETER);
144 ENUM_CASE(gcm::GCMClient::ASYNC_OPERATION_PENDING);
145 }
146 NOTREACHED();
147 return "";
148 }
149
150 GCMNetworkChannel::GCMNetworkChannel( 103 GCMNetworkChannel::GCMNetworkChannel(
151 scoped_refptr<net::URLRequestContextGetter> request_context_getter, 104 scoped_refptr<net::URLRequestContextGetter> request_context_getter,
152 scoped_ptr<GCMNetworkChannelDelegate> delegate) 105 scoped_ptr<GCMNetworkChannelDelegate> delegate)
153 : request_context_getter_(request_context_getter), 106 : request_context_getter_(request_context_getter),
154 delegate_(delegate.Pass()), 107 delegate_(delegate.Pass()),
155 register_backoff_entry_(new net::BackoffEntry(&kRegisterBackoffPolicy)), 108 register_backoff_entry_(new net::BackoffEntry(&kRegisterBackoffPolicy)),
156 diagnostic_info_(this), 109 diagnostic_info_(this),
157 weak_factory_(this) { 110 weak_factory_(this) {
158 net::NetworkChangeNotifier::AddNetworkChangeObserver(this); 111 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
159 delegate_->Initialize(); 112 delegate_->Initialize();
160 Register(); 113 Register();
161 } 114 }
162 115
163 GCMNetworkChannel::~GCMNetworkChannel() { 116 GCMNetworkChannel::~GCMNetworkChannel() {
164 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); 117 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
165 } 118 }
166 119
167 void GCMNetworkChannel::UpdateCredentials(
168 const std::string& email,
169 const std::string& token) {
170 // Do nothing. We get access token by requesting it for every message.
171 }
172
173 void GCMNetworkChannel::RequestDetailedStatus(
174 base::Callback<void(const base::DictionaryValue&)> callback) {
175 callback.Run(*diagnostic_info_.CollectDebugData());
176 }
177
178 void GCMNetworkChannel::ResetRegisterBackoffEntryForTest(
179 const net::BackoffEntry::Policy* policy) {
180 register_backoff_entry_.reset(new net::BackoffEntry(policy));
181 }
182
183 void GCMNetworkChannel::Register() { 120 void GCMNetworkChannel::Register() {
184 delegate_->Register(base::Bind(&GCMNetworkChannel::OnRegisterComplete, 121 delegate_->Register(base::Bind(&GCMNetworkChannel::OnRegisterComplete,
185 weak_factory_.GetWeakPtr())); 122 weak_factory_.GetWeakPtr()));
186 } 123 }
187 124
188 void GCMNetworkChannel::OnRegisterComplete( 125 void GCMNetworkChannel::OnRegisterComplete(
189 const std::string& registration_id, 126 const std::string& registration_id,
190 gcm::GCMClient::Result result) { 127 gcm::GCMClient::Result result) {
191 DCHECK(CalledOnValidThread()); 128 DCHECK(CalledOnValidThread());
192 if (result == gcm::GCMClient::SUCCESS) { 129 if (result == gcm::GCMClient::SUCCESS) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 if (!cached_message_.empty()) { 165 if (!cached_message_.empty()) {
229 RecordOutgoingMessageStatus(MESSAGE_DISCARDED); 166 RecordOutgoingMessageStatus(MESSAGE_DISCARDED);
230 } 167 }
231 cached_message_ = message; 168 cached_message_ = message;
232 169
233 if (!registration_id_.empty()) { 170 if (!registration_id_.empty()) {
234 RequestAccessToken(); 171 RequestAccessToken();
235 } 172 }
236 } 173 }
237 174
238 void GCMNetworkChannel::SetMessageReceiver(
239 invalidation::MessageCallback* incoming_receiver) {
240 delegate_->SetMessageReceiver(base::Bind(
241 &GCMNetworkChannel::OnIncomingMessage, weak_factory_.GetWeakPtr()));
242 SyncNetworkChannel::SetMessageReceiver(incoming_receiver);
243 }
244
245 void GCMNetworkChannel::RequestAccessToken() { 175 void GCMNetworkChannel::RequestAccessToken() {
246 DCHECK(CalledOnValidThread()); 176 DCHECK(CalledOnValidThread());
247 delegate_->RequestToken(base::Bind(&GCMNetworkChannel::OnGetTokenComplete, 177 delegate_->RequestToken(base::Bind(&GCMNetworkChannel::OnGetTokenComplete,
248 weak_factory_.GetWeakPtr())); 178 weak_factory_.GetWeakPtr()));
249 } 179 }
250 180
251 void GCMNetworkChannel::OnGetTokenComplete( 181 void GCMNetworkChannel::OnGetTokenComplete(
252 const GoogleServiceAuthError& error, 182 const GoogleServiceAuthError& error,
253 const std::string& token) { 183 const std::string& token) {
254 DCHECK(CalledOnValidThread()); 184 DCHECK(CalledOnValidThread());
(...skipping 28 matching lines...) Expand all
283 if (!echo_token_.empty()) { 213 if (!echo_token_.empty()) {
284 const std::string echo_header("echo-token: " + echo_token_); 214 const std::string echo_header("echo-token: " + echo_token_);
285 fetcher_->AddExtraRequestHeader(echo_header); 215 fetcher_->AddExtraRequestHeader(echo_header);
286 } 216 }
287 fetcher_->SetUploadData("application/x-protobuffer", cached_message_); 217 fetcher_->SetUploadData("application/x-protobuffer", cached_message_);
288 fetcher_->Start(); 218 fetcher_->Start();
289 // Clear message to prevent accidentally resending it in the future. 219 // Clear message to prevent accidentally resending it in the future.
290 cached_message_.clear(); 220 cached_message_.clear();
291 } 221 }
292 222
223 void GCMNetworkChannel::OnURLFetchComplete(const net::URLFetcher* source) {
224 DCHECK(CalledOnValidThread());
225 DCHECK_EQ(fetcher_, source);
226 // Free fetcher at the end of function.
227 scoped_ptr<net::URLFetcher> fetcher = fetcher_.Pass();
228
229 net::URLRequestStatus status = fetcher->GetStatus();
230 diagnostic_info_.last_post_response_code_ =
231 status.is_success() ? source->GetResponseCode() : status.error();
232
233 if (status.is_success() &&
234 fetcher->GetResponseCode() == net::HTTP_UNAUTHORIZED) {
235 DVLOG(1) << "URLFetcher failure: HTTP_UNAUTHORIZED";
236 delegate_->InvalidateToken(access_token_);
237 }
238
239 if (!status.is_success() ||
240 (fetcher->GetResponseCode() != net::HTTP_OK &&
241 fetcher->GetResponseCode() != net::HTTP_NO_CONTENT)) {
242 DVLOG(1) << "URLFetcher failure";
243 RecordOutgoingMessageStatus(POST_FAILURE);
244 NotifyStateChange(TRANSIENT_INVALIDATION_ERROR);
245 return;
246 }
247
248 RecordOutgoingMessageStatus(OUTGOING_MESSAGE_SUCCESS);
249 NotifyStateChange(INVALIDATIONS_ENABLED);
250 DVLOG(2) << "URLFetcher success";
251 }
252
293 void GCMNetworkChannel::OnIncomingMessage(const std::string& message, 253 void GCMNetworkChannel::OnIncomingMessage(const std::string& message,
294 const std::string& echo_token) { 254 const std::string& echo_token) {
295 #if !defined(ANDROID) 255 #if !defined(OS_ANDROID)
296 if (!echo_token.empty()) 256 if (!echo_token.empty())
297 echo_token_ = echo_token; 257 echo_token_ = echo_token;
298 diagnostic_info_.last_message_empty_echo_token_ = echo_token.empty(); 258 diagnostic_info_.last_message_empty_echo_token_ = echo_token.empty();
299 diagnostic_info_.last_message_received_time_ = base::Time::Now(); 259 diagnostic_info_.last_message_received_time_ = base::Time::Now();
300 260
301 if (message.empty()) { 261 if (message.empty()) {
302 RecordIncomingMessageStatus(MESSAGE_EMPTY); 262 RecordIncomingMessageStatus(MESSAGE_EMPTY);
303 return; 263 return;
304 } 264 }
305 std::string data; 265 std::string data;
306 if (!Base64DecodeURLSafe(message, &data)) { 266 if (!Base64DecodeURLSafe(message, &data)) {
307 RecordIncomingMessageStatus(INVALID_ENCODING); 267 RecordIncomingMessageStatus(INVALID_ENCODING);
308 return; 268 return;
309 } 269 }
310 ipc::invalidation::AddressedAndroidMessage android_message; 270 ipc::invalidation::AddressedAndroidMessage android_message;
311 if (!android_message.ParseFromString(data) || 271 if (!android_message.ParseFromString(data) ||
312 !android_message.has_message()) { 272 !android_message.has_message()) {
313 RecordIncomingMessageStatus(INVALID_PROTO); 273 RecordIncomingMessageStatus(INVALID_PROTO);
314 return; 274 return;
315 } 275 }
316 DVLOG(2) << "Deliver incoming message"; 276 DVLOG(2) << "Deliver incoming message";
317 RecordIncomingMessageStatus(INCOMING_MESSAGE_SUCCESS); 277 RecordIncomingMessageStatus(INCOMING_MESSAGE_SUCCESS);
318 DeliverIncomingMessage(android_message.message()); 278 DeliverIncomingMessage(android_message.message());
319 #else 279 #else
320 // This code shouldn't be invoked on Android. 280 // This code shouldn't be invoked on Android.
321 NOTREACHED(); 281 NOTREACHED();
322 #endif 282 #endif
323 } 283 }
324 284
325 void GCMNetworkChannel::OnURLFetchComplete(const net::URLFetcher* source) {
326 DCHECK(CalledOnValidThread());
327 DCHECK_EQ(fetcher_, source);
328 // Free fetcher at the end of function.
329 scoped_ptr<net::URLFetcher> fetcher = fetcher_.Pass();
330
331 net::URLRequestStatus status = fetcher->GetStatus();
332 diagnostic_info_.last_post_response_code_ =
333 status.is_success() ? source->GetResponseCode() : status.error();
334
335 if (status.is_success() &&
336 fetcher->GetResponseCode() == net::HTTP_UNAUTHORIZED) {
337 DVLOG(1) << "URLFetcher failure: HTTP_UNAUTHORIZED";
338 delegate_->InvalidateToken(access_token_);
339 }
340
341 if (!status.is_success() ||
342 (fetcher->GetResponseCode() != net::HTTP_OK &&
343 fetcher->GetResponseCode() != net::HTTP_NO_CONTENT)) {
344 DVLOG(1) << "URLFetcher failure";
345 RecordOutgoingMessageStatus(POST_FAILURE);
346 NotifyStateChange(TRANSIENT_INVALIDATION_ERROR);
347 return;
348 }
349
350 RecordOutgoingMessageStatus(OUTGOING_MESSAGE_SUCCESS);
351 NotifyStateChange(INVALIDATIONS_ENABLED);
352 DVLOG(2) << "URLFetcher success";
353 }
354
355 void GCMNetworkChannel::OnNetworkChanged( 285 void GCMNetworkChannel::OnNetworkChanged(
356 net::NetworkChangeNotifier::ConnectionType connection_type) { 286 net::NetworkChangeNotifier::ConnectionType connection_type) {
357 // Network connection is restored. Let's notify cacheinvalidations so it has 287 // Network connection is restored. Let's notify cacheinvalidations so it has
358 // chance to retry. 288 // chance to retry.
359 if (connection_type != net::NetworkChangeNotifier::CONNECTION_NONE) 289 if (connection_type != net::NetworkChangeNotifier::CONNECTION_NONE)
360 NotifyStateChange(INVALIDATIONS_ENABLED); 290 NotifyStateChange(INVALIDATIONS_ENABLED);
361 } 291 }
362 292
363 GURL GCMNetworkChannel::BuildUrl(const std::string& registration_id) { 293 GURL GCMNetworkChannel::BuildUrl(const std::string& registration_id) {
364 DCHECK(!registration_id.empty()); 294 DCHECK(!registration_id.empty());
365 295
366 #if !defined(ANDROID) 296 #if !defined(OS_ANDROID)
367 ipc::invalidation::EndpointId endpoint_id; 297 ipc::invalidation::EndpointId endpoint_id;
368 endpoint_id.set_c2dm_registration_id(registration_id); 298 endpoint_id.set_c2dm_registration_id(registration_id);
369 endpoint_id.set_client_key(std::string()); 299 endpoint_id.set_client_key(std::string());
370 endpoint_id.set_package_name(kCacheInvalidationPackageName); 300 endpoint_id.set_package_name(kCacheInvalidationPackageName);
371 endpoint_id.mutable_channel_version()->set_major_version( 301 endpoint_id.mutable_channel_version()->set_major_version(
372 ipc::invalidation::INITIAL); 302 ipc::invalidation::INITIAL);
373 std::string endpoint_id_buffer; 303 std::string endpoint_id_buffer;
374 endpoint_id.SerializeToString(&endpoint_id_buffer); 304 endpoint_id.SerializeToString(&endpoint_id_buffer);
375 305
376 ipc::invalidation::NetworkEndpointId network_endpoint_id; 306 ipc::invalidation::NetworkEndpointId network_endpoint_id;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 // Add padding. 341 // Add padding.
412 size_t padded_size = (input.size() + 3) - (input.size() + 3) % 4; 342 size_t padded_size = (input.size() + 3) - (input.size() + 3) % 4;
413 std::string padded_input(input); 343 std::string padded_input(input);
414 padded_input.resize(padded_size, '='); 344 padded_input.resize(padded_size, '=');
415 // Convert to standard base64 alphabet. 345 // Convert to standard base64 alphabet.
416 base::ReplaceChars(padded_input, "-", "+", &padded_input); 346 base::ReplaceChars(padded_input, "-", "+", &padded_input);
417 base::ReplaceChars(padded_input, "_", "/", &padded_input); 347 base::ReplaceChars(padded_input, "_", "/", &padded_input);
418 return base::Base64Decode(padded_input, output); 348 return base::Base64Decode(padded_input, output);
419 } 349 }
420 350
351 void GCMNetworkChannel::SetMessageReceiver(
352 invalidation::MessageCallback* incoming_receiver) {
353 delegate_->SetMessageReceiver(base::Bind(
354 &GCMNetworkChannel::OnIncomingMessage, weak_factory_.GetWeakPtr()));
355 SyncNetworkChannel::SetMessageReceiver(incoming_receiver);
356 }
357
358 void GCMNetworkChannel::RequestDetailedStatus(
359 base::Callback<void(const base::DictionaryValue&)> callback) {
360 callback.Run(*diagnostic_info_.CollectDebugData());
361 }
362
363 void GCMNetworkChannel::UpdateCredentials(const std::string& email,
364 const std::string& token) {
365 // Do nothing. We get access token by requesting it for every message.
366 }
367
368 void GCMNetworkChannel::ResetRegisterBackoffEntryForTest(
369 const net::BackoffEntry::Policy* policy) {
370 register_backoff_entry_.reset(new net::BackoffEntry(policy));
371 }
372
373 GCMNetworkChannelDiagnostic::GCMNetworkChannelDiagnostic(
374 GCMNetworkChannel* parent)
375 : parent_(parent),
376 last_message_empty_echo_token_(false),
377 last_post_response_code_(0),
378 registration_result_(gcm::GCMClient::UNKNOWN_ERROR),
379 sent_messages_count_(0) {}
380
381 scoped_ptr<base::DictionaryValue>
382 GCMNetworkChannelDiagnostic::CollectDebugData() const {
383 scoped_ptr<base::DictionaryValue> status(new base::DictionaryValue);
384 status->SetString("GCMNetworkChannel.Channel", "GCM");
385 std::string reg_id_hash = base::SHA1HashString(registration_id_);
386 status->SetString("GCMNetworkChannel.HashedRegistrationID",
387 base::HexEncode(reg_id_hash.c_str(), reg_id_hash.size()));
388 status->SetString("GCMNetworkChannel.RegistrationResult",
389 GCMClientResultToString(registration_result_));
390 status->SetBoolean("GCMNetworkChannel.HadLastMessageEmptyEchoToken",
391 last_message_empty_echo_token_);
392 status->SetString(
393 "GCMNetworkChannel.LastMessageReceivedTime",
394 base::TimeFormatShortDateAndTime(last_message_received_time_));
395 status->SetInteger("GCMNetworkChannel.LastPostResponseCode",
396 last_post_response_code_);
397 status->SetInteger("GCMNetworkChannel.SentMessages", sent_messages_count_);
398 status->SetInteger("GCMNetworkChannel.ReceivedMessages",
399 parent_->GetReceivedMessagesCount());
400 return status.Pass();
401 }
402
403 std::string GCMNetworkChannelDiagnostic::GCMClientResultToString(
404 const gcm::GCMClient::Result result) const {
405 #define ENUM_CASE(x) case x: return #x; break;
406 switch (result) {
407 ENUM_CASE(gcm::GCMClient::SUCCESS);
408 ENUM_CASE(gcm::GCMClient::NETWORK_ERROR);
409 ENUM_CASE(gcm::GCMClient::SERVER_ERROR);
410 ENUM_CASE(gcm::GCMClient::TTL_EXCEEDED);
411 ENUM_CASE(gcm::GCMClient::UNKNOWN_ERROR);
412 ENUM_CASE(gcm::GCMClient::NOT_SIGNED_IN);
413 ENUM_CASE(gcm::GCMClient::INVALID_PARAMETER);
414 ENUM_CASE(gcm::GCMClient::ASYNC_OPERATION_PENDING);
415 }
416 NOTREACHED();
417 return "";
418 }
419
421 } // namespace syncer 420 } // namespace syncer
OLDNEW
« no previous file with comments | « no previous file | sync/notifier/gcm_network_channel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698