| 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 "google_apis/gcm/engine/checkin_request.h" | 5 #include "google_apis/gcm/engine/checkin_request.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/metrics/histogram.h" |
| 9 #include "google_apis/gcm/protocol/checkin.pb.h" | 10 #include "google_apis/gcm/protocol/checkin.pb.h" |
| 10 #include "net/http/http_status_code.h" | 11 #include "net/http/http_status_code.h" |
| 11 #include "net/url_request/url_fetcher.h" | 12 #include "net/url_request/url_fetcher.h" |
| 12 #include "net/url_request/url_request_status.h" | 13 #include "net/url_request/url_request_status.h" |
| 13 #include "url/gurl.h" | 14 #include "url/gurl.h" |
| 14 | 15 |
| 15 namespace gcm { | 16 namespace gcm { |
| 16 | 17 |
| 17 namespace { | 18 namespace { |
| 18 const char kCheckinURL[] = "https://android.clients.google.com/checkin"; | 19 const char kCheckinURL[] = "https://android.clients.google.com/checkin"; |
| 19 const char kRequestContentType[] = "application/x-protobuf"; | 20 const char kRequestContentType[] = "application/x-protobuf"; |
| 20 const int kRequestVersionValue = 2; | 21 const int kRequestVersionValue = 2; |
| 21 const int kDefaultUserSerialNumber = 0; | 22 const int kDefaultUserSerialNumber = 0; |
| 23 |
| 24 // This enum is also used in an UMA histogram (GCMCheckinRequestStatus |
| 25 // enum defined in tools/metrics/histograms/histogram.xml). Hence the entries |
| 26 // here shouldn't be deleted or re-ordered and new ones should be added to |
| 27 // the end. |
| 28 enum CheckinRequestStatus { |
| 29 SUCCESS, // Checkin completed successfully. |
| 30 URL_FETCHING_FAILED, // URL fetching failed. |
| 31 HTTP_BAD_REQUEST, // The request was malformed. |
| 32 HTTP_UNAUTHORIZED, // The security token didn't match the android id. |
| 33 HTTP_NOT_OK, // HTTP status was not OK. |
| 34 RESPONSE_PARSING_FAILED, // Check in response parsing failed. |
| 35 ZERO_ID_OR_TOKEN, // Either returned android id or security token |
| 36 // was zero. |
| 37 // NOTE: always keep this entry at the end. Add new status types only |
| 38 // immediately above this line. Make sure to update the corresponding |
| 39 // histogram enum accordingly. |
| 40 STATUS_COUNT |
| 41 }; |
| 42 |
| 43 void RecordCheckinStatusToUMA(CheckinRequestStatus status) { |
| 44 UMA_HISTOGRAM_ENUMERATION("GCM.CheckinRequestStatus", status, STATUS_COUNT); |
| 45 } |
| 46 |
| 22 } // namespace | 47 } // namespace |
| 23 | 48 |
| 24 CheckinRequest::CheckinRequest( | 49 CheckinRequest::CheckinRequest( |
| 25 const CheckinRequestCallback& callback, | 50 const CheckinRequestCallback& callback, |
| 26 const net::BackoffEntry::Policy& backoff_policy, | 51 const net::BackoffEntry::Policy& backoff_policy, |
| 27 const checkin_proto::ChromeBuildProto& chrome_build_proto, | 52 const checkin_proto::ChromeBuildProto& chrome_build_proto, |
| 28 uint64 android_id, | 53 uint64 android_id, |
| 29 uint64 security_token, | 54 uint64 security_token, |
| 30 net::URLRequestContextGetter* request_context_getter) | 55 net::URLRequestContextGetter* request_context_getter) |
| 31 : request_context_getter_(request_context_getter), | 56 : request_context_getter_(request_context_getter), |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 } | 111 } |
| 87 | 112 |
| 88 Start(); | 113 Start(); |
| 89 } | 114 } |
| 90 | 115 |
| 91 void CheckinRequest::OnURLFetchComplete(const net::URLFetcher* source) { | 116 void CheckinRequest::OnURLFetchComplete(const net::URLFetcher* source) { |
| 92 std::string response_string; | 117 std::string response_string; |
| 93 checkin_proto::AndroidCheckinResponse response_proto; | 118 checkin_proto::AndroidCheckinResponse response_proto; |
| 94 if (!source->GetStatus().is_success()) { | 119 if (!source->GetStatus().is_success()) { |
| 95 LOG(ERROR) << "Failed to get checkin response. Fetcher failed. Retrying."; | 120 LOG(ERROR) << "Failed to get checkin response. Fetcher failed. Retrying."; |
| 121 RecordCheckinStatusToUMA(URL_FETCHING_FAILED); |
| 96 RetryWithBackoff(true); | 122 RetryWithBackoff(true); |
| 97 return; | 123 return; |
| 98 } | 124 } |
| 99 | 125 |
| 100 net::HttpStatusCode response_status = static_cast<net::HttpStatusCode>( | 126 net::HttpStatusCode response_status = static_cast<net::HttpStatusCode>( |
| 101 source->GetResponseCode()); | 127 source->GetResponseCode()); |
| 102 if (response_status == net::HTTP_BAD_REQUEST || | 128 if (response_status == net::HTTP_BAD_REQUEST || |
| 103 response_status == net::HTTP_UNAUTHORIZED) { | 129 response_status == net::HTTP_UNAUTHORIZED) { |
| 104 // BAD_REQUEST indicates that the request was malformed. | 130 // BAD_REQUEST indicates that the request was malformed. |
| 105 // UNAUTHORIZED indicates that security token didn't match the android id. | 131 // UNAUTHORIZED indicates that security token didn't match the android id. |
| 106 LOG(ERROR) << "No point retrying the checkin with status: " | 132 LOG(ERROR) << "No point retrying the checkin with status: " |
| 107 << response_status << ". Checkin failed."; | 133 << response_status << ". Checkin failed."; |
| 134 RecordCheckinStatusToUMA(response_status == net::HTTP_BAD_REQUEST ? |
| 135 HTTP_BAD_REQUEST : HTTP_UNAUTHORIZED); |
| 108 callback_.Run(0,0); | 136 callback_.Run(0,0); |
| 109 return; | 137 return; |
| 110 } | 138 } |
| 111 | 139 |
| 112 if (response_status != net::HTTP_OK || | 140 if (response_status != net::HTTP_OK || |
| 113 !source->GetResponseAsString(&response_string) || | 141 !source->GetResponseAsString(&response_string) || |
| 114 !response_proto.ParseFromString(response_string)) { | 142 !response_proto.ParseFromString(response_string)) { |
| 115 LOG(ERROR) << "Failed to get checkin response. HTTP Status: " | 143 LOG(ERROR) << "Failed to get checkin response. HTTP Status: " |
| 116 << response_status << ". Retrying."; | 144 << response_status << ". Retrying."; |
| 145 RecordCheckinStatusToUMA(response_status != net::HTTP_OK ? |
| 146 HTTP_NOT_OK : RESPONSE_PARSING_FAILED); |
| 117 RetryWithBackoff(true); | 147 RetryWithBackoff(true); |
| 118 return; | 148 return; |
| 119 } | 149 } |
| 120 | 150 |
| 121 if (!response_proto.has_android_id() || | 151 if (!response_proto.has_android_id() || |
| 122 !response_proto.has_security_token() || | 152 !response_proto.has_security_token() || |
| 123 response_proto.android_id() == 0 || | 153 response_proto.android_id() == 0 || |
| 124 response_proto.security_token() == 0) { | 154 response_proto.security_token() == 0) { |
| 125 LOG(ERROR) << "Android ID or security token is 0. Retrying."; | 155 LOG(ERROR) << "Android ID or security token is 0. Retrying."; |
| 156 RecordCheckinStatusToUMA(ZERO_ID_OR_TOKEN); |
| 126 RetryWithBackoff(true); | 157 RetryWithBackoff(true); |
| 127 return; | 158 return; |
| 128 } | 159 } |
| 129 | 160 |
| 161 RecordCheckinStatusToUMA(SUCCESS); |
| 130 callback_.Run(response_proto.android_id(), response_proto.security_token()); | 162 callback_.Run(response_proto.android_id(), response_proto.security_token()); |
| 131 } | 163 } |
| 132 | 164 |
| 133 } // namespace gcm | 165 } // namespace gcm |
| OLD | NEW |