15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/engine/registration_request.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h" 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/message_loop/message_loop.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/values.h" 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "google_apis/gcm/monitoring/gcm_stats_recorder.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/escape.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/load_flags.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_request_headers.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_status_code.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_status.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "url/gurl.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace gcm { 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kRegistrationRequestContentType[] = 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "application/x-www-form-urlencoded"; 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Request constants. 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kAppIdKey[] = "app"; 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kDeviceIdKey[] = "device"; 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kLoginHeader[] = "AidLogin"; 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSenderKey[] = "sender"; 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Request validation constants. 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const size_t kMaxSenders = 100; 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Response constants. 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kErrorPrefix[] = "Error="; 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kTokenPrefix[] = "token="; 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kDeviceRegistrationError[] = "PHONE_REGISTRATION_ERROR"; 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kAuthenticationFailed[] = "AUTHENTICATION_FAILED"; 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kInvalidSender[] = "INVALID_SENDER"; 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kInvalidParameters[] = "INVALID_PARAMETERS"; 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BuildFormEncoding(const std::string& key, 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& value, 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string* out) { 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!out->empty()) 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) out->append("&"); 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) out->append(key + "=" + net::EscapeUrlEncodedData(value, true)); 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Gets correct status from the error message. 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RegistrationRequest::Status GetStatusFromError(const std::string& error) { 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(fgorski): Improve error parsing in case there is nore then just an 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Error=ERROR_STRING in response. 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (error.find(kDeviceRegistrationError) != std::string::npos) 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return RegistrationRequest::DEVICE_REGISTRATION_ERROR; 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (error.find(kAuthenticationFailed) != std::string::npos) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return RegistrationRequest::AUTHENTICATION_FAILED; 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (error.find(kInvalidSender) != std::string::npos) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return RegistrationRequest::INVALID_SENDER; 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (error.find(kInvalidParameters) != std::string::npos) 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return RegistrationRequest::INVALID_PARAMETERS; 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return RegistrationRequest::UNKNOWN_ERROR; 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Indicates whether a retry attempt should be made based on the status of the 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// last request. 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ShouldRetryWithStatus(RegistrationRequest::Status status) { 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return status == RegistrationRequest::UNKNOWN_ERROR || 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status == RegistrationRequest::AUTHENTICATION_FAILED || 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) status == RegistrationRequest::DEVICE_REGISTRATION_ERROR || 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) status == RegistrationRequest::HTTP_NOT_OK || 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) status == RegistrationRequest::URL_FETCHING_FAILED || 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) status == RegistrationRequest::RESPONSE_PARSING_FAILED; 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RecordRegistrationStatusToUMA(RegistrationRequest::Status status) { 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("GCM.RegistrationRequestStatus", status, 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RegistrationRequest::STATUS_COUNT); 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RegistrationRequest::RequestInfo::RequestInfo( 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 android_id, 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 security_token, 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id, 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<std::string>& sender_ids) 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : android_id(android_id), 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) security_token(security_token), 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_id(app_id), 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sender_ids(sender_ids) { 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RegistrationRequest::RequestInfo::~RequestInfo() {} 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RegistrationRequest::RegistrationRequest( 101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const GURL& registration_url, 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const RequestInfo& request_info, 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const net::BackoffEntry::Policy& backoff_policy, 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const RegistrationCallback& callback, 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int max_retry_count, 1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_refptr<net::URLRequestContextGetter> request_context_getter, 1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu GCMStatsRecorder* recorder) 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : callback_(callback), 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_info_(request_info), 110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) registration_url_(registration_url), 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backoff_entry_(&backoff_policy), 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_context_getter_(request_context_getter), 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) retries_left_(max_retry_count), 1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu recorder_(recorder), 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_(this) { 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_GE(max_retry_count, 0); 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RegistrationRequest::~RegistrationRequest() {} 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RegistrationRequest::Start() { 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!callback_.is_null()); 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(request_info_.android_id != 0UL); 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(request_info_.security_token != 0UL); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(0 < request_info_.sender_ids.size() && 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_info_.sender_ids.size() <= kMaxSenders); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!url_fetcher_.get()); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_fetcher_.reset(net::URLFetcher::Create( 130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) registration_url_, net::URLFetcher::POST, this)); 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url_fetcher_->SetRequestContext(request_context_getter_.get()); 132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::LOAD_DO_NOT_SAVE_COOKIES); 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string android_id = base::Uint64ToString(request_info_.android_id); 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string auth_header = 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string(net::HttpRequestHeaders::kAuthorization) + ": " + 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kLoginHeader + " " + android_id + ":" + 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Uint64ToString(request_info_.security_token); 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_fetcher_->SetExtraRequestHeaders(auth_header); 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string body; 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BuildFormEncoding(kAppIdKey, request_info_.app_id, &body); 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BuildFormEncoding(kDeviceIdKey, android_id, &body); 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string senders; 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (std::vector<std::string>::const_iterator iter = 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_info_.sender_ids.begin(); 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != request_info_.sender_ids.end(); 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++iter) { 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!iter->empty()); 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!senders.empty()) 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) senders.append(","); 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) senders.append(*iter); 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BuildFormEncoding(kSenderKey, senders, &body); 1570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.RegistrationSenderIdCount", 1580de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) request_info_.sender_ids.size()); 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Performing registration for: " << request_info_.app_id; 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Registration request: " << body; 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_fetcher_->SetUploadData(kRegistrationRequestContentType, body); 1635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu recorder_->RecordRegistrationSent(request_info_.app_id, senders); 1640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) request_start_time_ = base::TimeTicks::Now(); 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_fetcher_->Start(); 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RegistrationRequest::RetryWithBackoff(bool update_backoff) { 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (update_backoff) { 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_GT(retries_left_, 0); 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) --retries_left_; 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_fetcher_.reset(); 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backoff_entry_.InformOfRequest(false); 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (backoff_entry_.ShouldRejectRequest()) { 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Delaying GCM registration of app: " 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << request_info_.app_id << ", for " 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << backoff_entry_.GetTimeUntilRelease().InMilliseconds() 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " milliseconds."; 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&RegistrationRequest::RetryWithBackoff, 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false), 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backoff_entry_.GetTimeUntilRelease()); 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Start(); 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)RegistrationRequest::Status RegistrationRequest::ParseResponse( 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const net::URLFetcher* source, std::string* token) { 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!source->GetStatus().is_success()) { 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "URL fetching failed."; 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return URL_FETCHING_FAILED; 198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string response; 201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!source->GetResponseAsString(&response)) { 202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "Failed to parse registration response as a string."; 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return RESPONSE_PARSING_FAILED; 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (source->GetResponseCode() == net::HTTP_OK) { 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t token_pos = response.find(kTokenPrefix); 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (token_pos != std::string::npos) { 209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *token = response.substr(token_pos + arraysize(kTokenPrefix) - 1); 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return SUCCESS; 211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If we are able to parse a meaningful known error, let's do so. Some errors 215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // will have HTTP_BAD_REQUEST, some will have HTTP_OK response code. 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t error_pos = response.find(kErrorPrefix); 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (error_pos != std::string::npos) { 218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string error = response.substr( 219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) error_pos + arraysize(kErrorPrefix) - 1); 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return GetStatusFromError(error); 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If we cannot tell what the error is, but at least we know response code was 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // not OK. 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (source->GetResponseCode() != net::HTTP_OK) { 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DLOG(ERROR) << "URL fetching HTTP response code is not OK. It is " 227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << source->GetResponseCode(); 228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return HTTP_NOT_OK; 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return UNKNOWN_ERROR; 232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void RegistrationRequest::OnURLFetchComplete(const net::URLFetcher* source) { 235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string token; 236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Status status = ParseResponse(source, &token); 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RecordRegistrationStatusToUMA(status); 2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu recorder_->RecordRegistrationResponse( 2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu request_info_.app_id, 2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu request_info_.sender_ids, 2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu status); 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ShouldRetryWithStatus(status)) { 244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (retries_left_ > 0) { 2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu recorder_->RecordRegistrationRetryRequested( 2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu request_info_.app_id, 2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu request_info_.sender_ids, 2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu retries_left_); 249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RetryWithBackoff(true); 250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) status = REACHED_MAX_RETRIES; 2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu recorder_->RecordRegistrationResponse( 2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu request_info_.app_id, 2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu request_info_.sender_ids, 2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu status); 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RecordRegistrationStatusToUMA(status); 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2610de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (status == SUCCESS) { 2620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("GCM.RegistrationRetryCount", 2630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) backoff_entry_.failure_count()); 2640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) UMA_HISTOGRAM_TIMES("GCM.RegistrationCompleteTime", 2650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::TimeTicks::Now() - request_start_time_); 2660de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) callback_.Run(status, token); 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace gcm 271