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); | |
fgorski
2015/05/13 18:32:41
does app id need to be present in both cases?
I th
jianli
2015/05/13 22:42:57
I confirmed with Costin that this was still requir
| |
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 |