| 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/unregistration_request.h" | 5 #include "google_apis/gcm/engine/unregistration_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 "base/metrics/histogram.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 const char kAppIdKey[] = "app"; | 28 const char kAppIdKey[] = "app"; |
| 29 const char kDeleteKey[] = "delete"; | 29 const char kDeleteKey[] = "delete"; |
| 30 const char kDeleteValue[] = "true"; | 30 const char kDeleteValue[] = "true"; |
| 31 const char kDeviceIdKey[] = "device"; | 31 const char kDeviceIdKey[] = "device"; |
| 32 const char kLoginHeader[] = "AidLogin"; | 32 const char kLoginHeader[] = "AidLogin"; |
| 33 const char kUnregistrationCallerKey[] = "gcm_unreg_caller"; | 33 const char kUnregistrationCallerKey[] = "gcm_unreg_caller"; |
| 34 // We are going to set the value to "false" in order to forcefully unregister | 34 // We are going to set the value to "false" in order to forcefully unregister |
| 35 // the application. | 35 // the application. |
| 36 const char kUnregistrationCallerValue[] = "false"; | 36 const char kUnregistrationCallerValue[] = "false"; |
| 37 | 37 |
| 38 // Request keys specific to InstanceID's GetToken request. |
| 39 const char kGMSVersionKey[] = "gmsv"; |
| 40 const char kInstanceIDKey[] = "appid"; |
| 41 const char kSenderKey[] = "sender"; |
| 42 const char kScopeKey[] = "scope"; |
| 43 |
| 38 // Response constants. | 44 // Response constants. |
| 39 const char kDeletedPrefix[] = "deleted="; | 45 const char kDeletedPrefix[] = "deleted="; |
| 40 const char kErrorPrefix[] = "Error="; | 46 const char kErrorPrefix[] = "Error="; |
| 41 const char kInvalidParameters[] = "INVALID_PARAMETERS"; | 47 const char kInvalidParameters[] = "INVALID_PARAMETERS"; |
| 42 | 48 |
| 43 | 49 |
| 44 void BuildFormEncoding(const std::string& key, | 50 void BuildFormEncoding(const std::string& key, |
| 45 const std::string& value, | 51 const std::string& value, |
| 46 std::string* out) { | 52 std::string* out) { |
| 47 if (!out->empty()) | 53 if (!out->empty()) |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 return UnregistrationRequest::UNKNOWN_ERROR; | 97 return UnregistrationRequest::UNKNOWN_ERROR; |
| 92 } | 98 } |
| 93 | 99 |
| 94 DVLOG(1) << "Not able to parse a meaningful output from response body." | 100 DVLOG(1) << "Not able to parse a meaningful output from response body." |
| 95 << response; | 101 << response; |
| 96 return UnregistrationRequest::RESPONSE_PARSING_FAILED; | 102 return UnregistrationRequest::RESPONSE_PARSING_FAILED; |
| 97 } | 103 } |
| 98 | 104 |
| 99 } // namespace | 105 } // namespace |
| 100 | 106 |
| 101 UnregistrationRequest::RequestInfo::RequestInfo( | 107 UnregistrationRequest::RequestInfo::RequestInfo() {} |
| 102 uint64 android_id, | |
| 103 uint64 security_token, | |
| 104 const std::string& app_id) | |
| 105 : android_id(android_id), | |
| 106 security_token(security_token), | |
| 107 app_id(app_id) { | |
| 108 } | |
| 109 | 108 |
| 110 UnregistrationRequest::RequestInfo::~RequestInfo() {} | 109 UnregistrationRequest::RequestInfo::~RequestInfo() {} |
| 111 | 110 |
| 111 void UnregistrationRequest::RequestInfo::BuildRequestHeaders( |
| 112 std::string* extra_headers) { |
| 113 net::HttpRequestHeaders headers; |
| 114 headers.SetHeader( |
| 115 net::HttpRequestHeaders::kAuthorization, |
| 116 std::string(kLoginHeader) + " " + base::Uint64ToString(android_id) + ":" + |
| 117 base::Uint64ToString(security_token)); |
| 118 headers.SetHeader(kAppIdKey, app_id); |
| 119 *extra_headers = headers.ToString(); |
| 120 } |
| 121 |
| 122 void UnregistrationRequest::RequestInfo::BuildRequestBody(std::string* body){ |
| 123 BuildFormEncoding(kAppIdKey, app_id, body); |
| 124 BuildFormEncoding(kDeviceIdKey, base::Uint64ToString(android_id), body); |
| 125 BuildFormEncoding(kDeleteKey, kDeleteValue, body); |
| 126 } |
| 127 |
| 128 UnregistrationRequest::GCMRequestInfo::GCMRequestInfo() {} |
| 129 |
| 130 UnregistrationRequest::GCMRequestInfo::~GCMRequestInfo() {} |
| 131 |
| 132 void UnregistrationRequest::GCMRequestInfo::BuildRequestBody(std::string* body){ |
| 133 RequestInfo::BuildRequestBody(body); |
| 134 |
| 135 BuildFormEncoding(kUnregistrationCallerKey, kUnregistrationCallerValue, body); |
| 136 } |
| 137 |
| 138 UnregistrationRequest::InstanceIDRequestInfo::InstanceIDRequestInfo() {} |
| 139 |
| 140 UnregistrationRequest::InstanceIDRequestInfo::~InstanceIDRequestInfo() {} |
| 141 |
| 142 void UnregistrationRequest::InstanceIDRequestInfo::BuildRequestBody( |
| 143 std::string* body){ |
| 144 RequestInfo::BuildRequestBody(body); |
| 145 |
| 146 BuildFormEncoding(kGMSVersionKey, chrome_version, body); |
| 147 BuildFormEncoding(kInstanceIDKey, instance_id, body); |
| 148 BuildFormEncoding(kSenderKey, authorized_entity, body); |
| 149 BuildFormEncoding(kScopeKey, scope, body); |
| 150 } |
| 151 |
| 112 UnregistrationRequest::UnregistrationRequest( | 152 UnregistrationRequest::UnregistrationRequest( |
| 113 const GURL& registration_url, | 153 const GURL& registration_url, |
| 114 const RequestInfo& request_info, | 154 scoped_ptr<RequestInfo> request_info, |
| 115 const net::BackoffEntry::Policy& backoff_policy, | 155 const net::BackoffEntry::Policy& backoff_policy, |
| 116 const UnregistrationCallback& callback, | 156 const UnregistrationCallback& callback, |
| 117 scoped_refptr<net::URLRequestContextGetter> request_context_getter, | 157 scoped_refptr<net::URLRequestContextGetter> request_context_getter, |
| 118 GCMStatsRecorder* recorder) | 158 GCMStatsRecorder* recorder) |
| 119 : callback_(callback), | 159 : callback_(callback), |
| 120 request_info_(request_info), | 160 request_info_(request_info.Pass()), |
| 121 registration_url_(registration_url), | 161 registration_url_(registration_url), |
| 122 backoff_entry_(&backoff_policy), | 162 backoff_entry_(&backoff_policy), |
| 123 request_context_getter_(request_context_getter), | 163 request_context_getter_(request_context_getter), |
| 124 recorder_(recorder), | 164 recorder_(recorder), |
| 125 weak_ptr_factory_(this) { | 165 weak_ptr_factory_(this) { |
| 126 } | 166 } |
| 127 | 167 |
| 128 UnregistrationRequest::~UnregistrationRequest() {} | 168 UnregistrationRequest::~UnregistrationRequest() {} |
| 129 | 169 |
| 130 void UnregistrationRequest::Start() { | 170 void UnregistrationRequest::Start() { |
| 131 DCHECK(!callback_.is_null()); | 171 DCHECK(!callback_.is_null()); |
| 132 DCHECK(request_info_.android_id != 0UL); | 172 DCHECK(request_info_->android_id != 0UL); |
| 133 DCHECK(request_info_.security_token != 0UL); | 173 DCHECK(request_info_->security_token != 0UL); |
| 134 DCHECK(!url_fetcher_.get()); | 174 DCHECK(!url_fetcher_.get()); |
| 135 | 175 |
| 136 url_fetcher_ = | 176 url_fetcher_ = |
| 137 net::URLFetcher::Create(registration_url_, net::URLFetcher::POST, this); | 177 net::URLFetcher::Create(registration_url_, net::URLFetcher::POST, this); |
| 138 url_fetcher_->SetRequestContext(request_context_getter_.get()); | 178 url_fetcher_->SetRequestContext(request_context_getter_.get()); |
| 139 | 179 |
| 140 std::string android_id = base::Uint64ToString(request_info_.android_id); | 180 std::string extra_headers; |
| 141 std::string auth_header = | 181 request_info_->BuildRequestHeaders(&extra_headers); |
| 142 std::string(kLoginHeader) + " " + android_id + ":" + | 182 url_fetcher_->SetExtraRequestHeaders(extra_headers); |
| 143 base::Uint64ToString(request_info_.security_token); | |
| 144 net::HttpRequestHeaders headers; | |
| 145 headers.SetHeader(net::HttpRequestHeaders::kAuthorization, auth_header); | |
| 146 headers.SetHeader(kAppIdKey, request_info_.app_id); | |
| 147 url_fetcher_->SetExtraRequestHeaders(headers.ToString()); | |
| 148 | 183 |
| 149 std::string body; | 184 std::string body; |
| 150 BuildFormEncoding(kAppIdKey, request_info_.app_id, &body); | 185 request_info_->BuildRequestBody(&body); |
| 151 BuildFormEncoding(kDeviceIdKey, android_id, &body); | |
| 152 BuildFormEncoding(kDeleteKey, kDeleteValue, &body); | |
| 153 BuildFormEncoding(kUnregistrationCallerKey, | |
| 154 kUnregistrationCallerValue, | |
| 155 &body); | |
| 156 | 186 |
| 157 DVLOG(1) << "Unregistration request: " << body; | 187 DVLOG(1) << "Unregistration request: " << body; |
| 158 url_fetcher_->SetUploadData(kRequestContentType, body); | 188 url_fetcher_->SetUploadData(kRequestContentType, body); |
| 159 | 189 |
| 160 DVLOG(1) << "Performing unregistration for: " << request_info_.app_id; | 190 DVLOG(1) << "Performing unregistration for: " << request_info_->app_id; |
| 161 recorder_->RecordUnregistrationSent(request_info_.app_id); | 191 recorder_->RecordUnregistrationSent(request_info_->app_id); |
| 162 request_start_time_ = base::TimeTicks::Now(); | 192 request_start_time_ = base::TimeTicks::Now(); |
| 163 url_fetcher_->Start(); | 193 url_fetcher_->Start(); |
| 164 } | 194 } |
| 165 | 195 |
| 166 void UnregistrationRequest::RetryWithBackoff(bool update_backoff) { | 196 void UnregistrationRequest::RetryWithBackoff(bool update_backoff) { |
| 167 if (update_backoff) { | 197 if (update_backoff) { |
| 168 url_fetcher_.reset(); | 198 url_fetcher_.reset(); |
| 169 backoff_entry_.InformOfRequest(false); | 199 backoff_entry_.InformOfRequest(false); |
| 170 } | 200 } |
| 171 | 201 |
| 172 if (backoff_entry_.ShouldRejectRequest()) { | 202 if (backoff_entry_.ShouldRejectRequest()) { |
| 173 DVLOG(1) << "Delaying GCM unregistration of app: " | 203 DVLOG(1) << "Delaying GCM unregistration of app: " |
| 174 << request_info_.app_id << ", for " | 204 << request_info_->app_id << ", for " |
| 175 << backoff_entry_.GetTimeUntilRelease().InMilliseconds() | 205 << backoff_entry_.GetTimeUntilRelease().InMilliseconds() |
| 176 << " milliseconds."; | 206 << " milliseconds."; |
| 177 recorder_->RecordUnregistrationRetryDelayed( | 207 recorder_->RecordUnregistrationRetryDelayed( |
| 178 request_info_.app_id, | 208 request_info_->app_id, |
| 179 backoff_entry_.GetTimeUntilRelease().InMilliseconds()); | 209 backoff_entry_.GetTimeUntilRelease().InMilliseconds()); |
| 180 base::MessageLoop::current()->PostDelayedTask( | 210 base::MessageLoop::current()->PostDelayedTask( |
| 181 FROM_HERE, | 211 FROM_HERE, |
| 182 base::Bind(&UnregistrationRequest::RetryWithBackoff, | 212 base::Bind(&UnregistrationRequest::RetryWithBackoff, |
| 183 weak_ptr_factory_.GetWeakPtr(), | 213 weak_ptr_factory_.GetWeakPtr(), |
| 184 false), | 214 false), |
| 185 backoff_entry_.GetTimeUntilRelease()); | 215 backoff_entry_.GetTimeUntilRelease()); |
| 186 return; | 216 return; |
| 187 } | 217 } |
| 188 | 218 |
| 189 Start(); | 219 Start(); |
| 190 } | 220 } |
| 191 | 221 |
| 192 void UnregistrationRequest::OnURLFetchComplete(const net::URLFetcher* source) { | 222 void UnregistrationRequest::OnURLFetchComplete(const net::URLFetcher* source) { |
| 193 UnregistrationRequest::Status status = | 223 UnregistrationRequest::Status status = |
| 194 ParseFetcherResponse(source, request_info_.app_id); | 224 ParseFetcherResponse(source, request_info_->app_id); |
| 195 | 225 |
| 196 DVLOG(1) << "UnregistrationRequestStauts: " << status; | 226 DVLOG(1) << "UnregistrationRequestStauts: " << status; |
| 197 UMA_HISTOGRAM_ENUMERATION("GCM.UnregistrationRequestStatus", | 227 UMA_HISTOGRAM_ENUMERATION("GCM.UnregistrationRequestStatus", |
| 198 status, | 228 status, |
| 199 UNREGISTRATION_STATUS_COUNT); | 229 UNREGISTRATION_STATUS_COUNT); |
| 200 recorder_->RecordUnregistrationResponse(request_info_.app_id, status); | 230 recorder_->RecordUnregistrationResponse(request_info_->app_id, status); |
| 201 | 231 |
| 202 if (status == URL_FETCHING_FAILED || | 232 if (status == URL_FETCHING_FAILED || |
| 203 status == SERVICE_UNAVAILABLE || | 233 status == SERVICE_UNAVAILABLE || |
| 204 status == INTERNAL_SERVER_ERROR || | 234 status == INTERNAL_SERVER_ERROR || |
| 205 status == INCORRECT_APP_ID || | 235 status == INCORRECT_APP_ID || |
| 206 status == RESPONSE_PARSING_FAILED) { | 236 status == RESPONSE_PARSING_FAILED) { |
| 207 RetryWithBackoff(true); | 237 RetryWithBackoff(true); |
| 208 return; | 238 return; |
| 209 } | 239 } |
| 210 | 240 |
| 211 // status == SUCCESS || HTTP_NOT_OK || NO_RESPONSE_BODY || | 241 // status == SUCCESS || HTTP_NOT_OK || NO_RESPONSE_BODY || |
| 212 // INVALID_PARAMETERS || UNKNOWN_ERROR | 242 // INVALID_PARAMETERS || UNKNOWN_ERROR |
| 213 | 243 |
| 214 if (status == SUCCESS) { | 244 if (status == SUCCESS) { |
| 215 UMA_HISTOGRAM_COUNTS("GCM.UnregistrationRetryCount", | 245 UMA_HISTOGRAM_COUNTS("GCM.UnregistrationRetryCount", |
| 216 backoff_entry_.failure_count()); | 246 backoff_entry_.failure_count()); |
| 217 UMA_HISTOGRAM_TIMES("GCM.UnregistrationCompleteTime", | 247 UMA_HISTOGRAM_TIMES("GCM.UnregistrationCompleteTime", |
| 218 base::TimeTicks::Now() - request_start_time_); | 248 base::TimeTicks::Now() - request_start_time_); |
| 219 } | 249 } |
| 220 | 250 |
| 221 callback_.Run(status); | 251 callback_.Run(status); |
| 222 } | 252 } |
| 223 | 253 |
| 224 } // namespace gcm | 254 } // namespace gcm |
| OLD | NEW |