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 |