Add abhijeet.k@samsung.com to AUTHORS list.
[chromium-blink-merge.git] / components / signin / core / browser / refresh_token_annotation_request.cc
blob108ba47cd16d5e6ac55dce4175ae7578ccc313f2
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
3 // found in the LICENSE file.
5 #include "components/signin/core/browser/refresh_token_annotation_request.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/rand_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/time/time.h"
13 #include "components/signin/core/browser/signin_client.h"
14 #include "components/signin/core/common/signin_pref_names.h"
15 #include "google_apis/gaia/gaia_constants.h"
16 #include "google_apis/gaia/gaia_urls.h"
17 #include "net/base/escape.h"
18 #include "net/url_request/url_request_context_getter.h"
20 namespace {
22 void RecordRequestStatusHistogram(bool success) {
23 UMA_HISTOGRAM_BOOLEAN("Signin.RefreshTokenAnnotationRequest", success);
27 RefreshTokenAnnotationRequest::RefreshTokenAnnotationRequest(
28 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
29 const std::string& product_version,
30 const std::string& device_id,
31 const std::string& client_id,
32 const base::Closure& request_callback)
33 : OAuth2TokenService::Consumer("refresh_token_annotation"),
34 request_context_getter_(request_context_getter),
35 product_version_(product_version),
36 device_id_(device_id),
37 client_id_(client_id),
38 request_callback_(request_callback) {
41 RefreshTokenAnnotationRequest::~RefreshTokenAnnotationRequest() {
42 DCHECK(CalledOnValidThread());
45 // static
46 scoped_ptr<RefreshTokenAnnotationRequest>
47 RefreshTokenAnnotationRequest::SendIfNeeded(
48 PrefService* pref_service,
49 OAuth2TokenService* token_service,
50 SigninClient* signin_client,
51 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
52 const std::string& account_id,
53 const base::Closure& request_callback) {
54 scoped_ptr<RefreshTokenAnnotationRequest> request;
56 if (!ShouldSendNow(pref_service))
57 return request.Pass();
59 // Don't send request if device_id is disabled.
60 std::string device_id = signin_client->GetSigninScopedDeviceId();
61 if (device_id.empty())
62 return request.Pass();
64 request.reset(new RefreshTokenAnnotationRequest(
65 request_context_getter, signin_client->GetProductVersion(), device_id,
66 GaiaUrls::GetInstance()->oauth2_chrome_client_id(), request_callback));
67 request->RequestAccessToken(token_service, account_id);
68 return request.Pass();
71 // static
72 bool RefreshTokenAnnotationRequest::ShouldSendNow(PrefService* pref_service) {
73 bool should_send_now = false;
74 // Read scheduled time from prefs.
75 base::Time scheduled_time =
76 base::Time::FromInternalValue(pref_service->GetInt64(
77 prefs::kGoogleServicesRefreshTokenAnnotateScheduledTime));
79 if (!scheduled_time.is_null() && scheduled_time <= base::Time::Now()) {
80 DVLOG(2) << "Sending RefreshTokenAnnotationRequest";
81 should_send_now = true;
82 // Reset scheduled_time so that it gets rescheduled later in the function.
83 scheduled_time = base::Time();
86 if (scheduled_time.is_null()) {
87 // Random delay in interval [0, 20] days.
88 double delay_in_sec = base::RandDouble() * 20.0 * 24.0 * 3600.0;
89 scheduled_time =
90 base::Time::Now() + base::TimeDelta::FromSecondsD(delay_in_sec);
91 DVLOG(2) << "RefreshTokenAnnotationRequest scheduled for "
92 << scheduled_time;
93 pref_service->SetInt64(
94 prefs::kGoogleServicesRefreshTokenAnnotateScheduledTime,
95 scheduled_time.ToInternalValue());
97 return should_send_now;
100 void RefreshTokenAnnotationRequest::RequestAccessToken(
101 OAuth2TokenService* token_service,
102 const std::string& account_id) {
103 DCHECK(CalledOnValidThread());
104 OAuth2TokenService::ScopeSet scopes;
105 scopes.insert(GaiaConstants::kOAuth1LoginScope);
106 access_token_request_ = token_service->StartRequest(account_id, scopes, this);
109 void RefreshTokenAnnotationRequest::OnGetTokenSuccess(
110 const OAuth2TokenService::Request* request,
111 const std::string& access_token,
112 const base::Time& expiration_time) {
113 DCHECK(CalledOnValidThread());
114 DVLOG(2) << "Got access token";
115 Start(request_context_getter_.get(), access_token);
118 void RefreshTokenAnnotationRequest::OnGetTokenFailure(
119 const OAuth2TokenService::Request* request,
120 const GoogleServiceAuthError& error) {
121 DCHECK(CalledOnValidThread());
122 DVLOG(2) << "Failed to get access token";
123 RecordRequestStatusHistogram(false);
124 base::MessageLoop::current()->PostTask(FROM_HERE, request_callback_);
125 request_callback_.Reset();
128 GURL RefreshTokenAnnotationRequest::CreateApiCallUrl() {
129 return GaiaUrls::GetInstance()->oauth2_issue_token_url();
132 std::string RefreshTokenAnnotationRequest::CreateApiCallBody() {
133 // response_type=none means we don't want any token back, just record that
134 // this request was sent.
135 const char kIssueTokenBodyFormat[] =
136 "force=true"
137 "&response_type=none"
138 "&scope=%s"
139 "&client_id=%s"
140 "&device_id=%s"
141 "&device_type=chrome"
142 "&lib_ver=%s";
144 // It doesn't matter which scope to use for IssueToken request, any common
145 // scope would do. In this case I'm using "userinfo.email".
146 return base::StringPrintf(
147 kIssueTokenBodyFormat,
148 net::EscapeUrlEncodedData(GaiaConstants::kGoogleUserInfoEmail, true)
149 .c_str(),
150 net::EscapeUrlEncodedData(client_id_, true).c_str(),
151 net::EscapeUrlEncodedData(device_id_, true).c_str(),
152 net::EscapeUrlEncodedData(product_version_, true).c_str());
155 void RefreshTokenAnnotationRequest::ProcessApiCallSuccess(
156 const net::URLFetcher* source) {
157 DCHECK(CalledOnValidThread());
158 DVLOG(2) << "Request succeeded";
159 RecordRequestStatusHistogram(true);
160 base::MessageLoop::current()->PostTask(FROM_HERE, request_callback_);
161 request_callback_.Reset();
164 void RefreshTokenAnnotationRequest::ProcessApiCallFailure(
165 const net::URLFetcher* source) {
166 DCHECK(CalledOnValidThread());
167 DVLOG(2) << "Request failed";
168 RecordRequestStatusHistogram(false);
169 base::MessageLoop::current()->PostTask(FROM_HERE, request_callback_);
170 request_callback_.Reset();