OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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. | |
4 | |
5 #include "components/signin/core/browser/device_activity_fetcher.h" | |
6 | |
7 #include "base/strings/stringprintf.h" | |
8 #include "components/signin/core/browser/signin_client.h" | |
9 #include "google_apis/gaia/gaia_auth_fetcher.h" | |
10 #include "google_apis/gaia/gaia_constants.h" | |
11 #include "google_apis/gaia/gaia_urls.h" | |
12 #include "google_apis/gaia/google_service_auth_error.h" | |
13 #include "net/http/http_status_code.h" | |
14 #include "net/url_request/url_fetcher.h" | |
15 | |
16 namespace { | |
17 | |
18 const char* kSyncListDevicesScope = | |
19 "https://www.googleapis.com/auth/chromesynclistdevices"; | |
20 const char* kChromeDomain = "http://www.chrome.com"; | |
21 const char* kListDevicesEndpoint = "http://127.0.0.1"; | |
22 // Template for optional authorization header when using an OAuth access token. | |
23 const char kAuthorizationHeader[] = "Authorization: Bearer %s"; | |
24 | |
25 // In case of an error while fetching using the GaiaAuthFetcher, retry with | |
26 // exponential backoff. Try up to 9 times within 10 minutes. | |
27 const net::BackoffEntry::Policy kBackoffPolicy = { | |
28 // Number of initial errors (in sequence) to ignore before applying | |
29 // exponential back-off rules. | |
30 0, | |
31 // Initial delay for exponential backoff in ms. | |
32 1000, | |
33 // Factor by which the waiting time will be multiplied. | |
34 2, | |
35 // Fuzzing percentage. ex: 10% will spread requests randomly | |
36 // between 90%-100% of the calculated time. | |
37 0.1, // 10% | |
38 // Maximum amount of time we are willing to delay our request in ms. | |
39 1000 * 60 * 15, // 15 minutes. | |
40 // Time to keep an entry from being discarded even when it | |
41 // has no significant state, -1 to never discard. | |
42 -1, | |
43 // Don't use initial delay unless the last request was an error. | |
44 false, | |
45 }; | |
46 | |
47 const int kMaxFetcherRetries = 9; | |
48 | |
49 bool IsTransientError(const GoogleServiceAuthError& error) { | |
50 return error.IsTransientError() || | |
51 error.state() == GoogleServiceAuthError::REQUEST_CANCELED; | |
Roger Tawa OOO till Jul 10th
2015/05/15 16:01:40
Hmm, from our discussion this morning :-) Still n
Mike Lerman
2015/05/15 20:47:34
That's a good point. With the addition of a Stop()
| |
52 } | |
53 | |
54 } // namespace | |
55 | |
56 DeviceActivityFetcher::DeviceActivityFetcher( | |
57 SigninClient* signin_client, | |
58 DeviceActivityFetcher::Observer* observer) | |
59 : fetcher_backoff_(&kBackoffPolicy), | |
60 fetcher_retries_(0), | |
61 signin_client_(signin_client), | |
62 observer_(observer) {} | |
63 | |
64 DeviceActivityFetcher::~DeviceActivityFetcher() { | |
65 } | |
66 | |
67 void DeviceActivityFetcher::Start() { | |
68 fetcher_retries_ = 0; | |
69 login_hint_ = std::string(); | |
70 StartFetchingListIdpSessions(); | |
71 } | |
72 | |
73 void DeviceActivityFetcher::StartFetchingListIdpSessions() { | |
74 gaia_auth_fetcher_.reset(new GaiaAuthFetcher(this, | |
75 GaiaConstants::kChromeSource, signin_client_->GetURLRequestContext())); | |
76 gaia_auth_fetcher_->StartListIDPSessions(kSyncListDevicesScope, | |
77 kChromeDomain); | |
78 } | |
79 | |
80 void DeviceActivityFetcher::StartFetchingGetTokenResponse() { | |
81 gaia_auth_fetcher_.reset(new GaiaAuthFetcher(this, | |
82 GaiaConstants::kChromeSource, signin_client_->GetURLRequestContext())); | |
83 gaia_auth_fetcher_->StartGetTokenResponse(kSyncListDevicesScope, | |
84 kChromeDomain, | |
85 login_hint_); | |
86 } | |
87 | |
88 void DeviceActivityFetcher::StartFetchingListDevices() { | |
89 // Call the Sync Endpoint. | |
90 url_fetcher_ = net::URLFetcher::Create(GURL(kListDevicesEndpoint), | |
91 net::URLFetcher::GET, | |
92 this); | |
93 url_fetcher_->SetRequestContext(signin_client_->GetURLRequestContext()); | |
94 if (!access_token_.empty()) { | |
95 url_fetcher_->SetExtraRequestHeaders( | |
96 base::StringPrintf(kAuthorizationHeader, access_token_.c_str())); | |
97 } | |
98 url_fetcher_->Start(); | |
99 } | |
100 | |
101 void DeviceActivityFetcher::OnURLFetchComplete(const net::URLFetcher* source) { | |
102 // TODO(mlerman): Uncomment the code below once we have a working proto. | |
103 | |
104 // std::string response_string; | |
105 // ListDevices list_devices; | |
106 | |
107 // if (!source->GetStatus().is_success()) { | |
108 // VLOG(1) << "Failed to fetch listdevices response. Retrying."; | |
109 // if (++fetcher_retries_ < kMaxFetcherRetries) { | |
110 // fetcher_backoff_.InformOfRequest(false); | |
111 // fetcher_timer_.Start( | |
112 // FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(), this, | |
113 // &DeviceActivityFetcher::StartFetchingListDevices); | |
114 // return; | |
115 // } else { | |
116 // observer_->OnFetchDeviceActivityFailure(); | |
117 // return; | |
118 // } | |
119 // } | |
120 | |
121 // net::HttpStatusCode response_status = static_cast<net::HttpStatusCode>( | |
122 // source->GetResponseCode()); | |
123 // if (response_status == net::HTTP_BAD_REQUEST || | |
124 // response_status == net::HTTP_UNAUTHORIZED) { | |
125 // // BAD_REQUEST indicates that the request was malformed. | |
126 // // UNAUTHORIZED indicates that security token didn't match the id. | |
127 // VLOG(1) << "No point retrying the checkin with status: " | |
128 // << response_status << ". Checkin failed."; | |
129 // CheckinRequestStatus status = response_status == net::HTTP_BAD_REQUEST ? | |
130 // HTTP_BAD_REQUEST : HTTP_UNAUTHORIZED; | |
131 // RecordCheckinStatusAndReportUMA(status, recorder_, false); | |
132 // callback_.Run(response_proto); | |
133 // return; | |
134 // } | |
135 | |
136 // if (response_status != net::HTTP_OK || | |
137 // !source->GetResponseAsString(&response_string) || | |
138 // !list_devices.ParseFromString(response_string)) { | |
139 // LOG(ERROR) << "Failed to get list devices response. HTTP Status: " | |
140 // << response_status; | |
141 // if (++fetcher_retries_ < kMaxFetcherRetries) { | |
142 // fetcher_backoff_.InformOfRequest(false); | |
143 // fetcher_timer_.Start( | |
144 // FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(), this, | |
145 // &DeviceActivityFetcher::StartFetchingListDevices); | |
146 // return; | |
147 // } else { | |
148 // observer_->OnFetchDeviceActivityFailure(); | |
149 // return; | |
150 // } | |
151 // } | |
152 | |
153 std::vector<DeviceActivity> devices; | |
154 // TODO(mlerman): Fill |devices| from the proto in |source|. | |
155 | |
156 observer_->OnFetchDeviceActivitySuccess(devices); | |
157 } | |
158 | |
159 | |
160 void DeviceActivityFetcher::OnListIdpSessionsSuccess( | |
161 const std::string& login_hint) { | |
162 fetcher_backoff_.InformOfRequest(true); | |
163 login_hint_ = login_hint; | |
164 access_token_ = std::string(); | |
165 StartFetchingGetTokenResponse(); | |
166 } | |
167 | |
168 void DeviceActivityFetcher::OnListIdpSessionsError( | |
169 const GoogleServiceAuthError& error) { | |
170 if (++fetcher_retries_ < kMaxFetcherRetries && | |
171 IsTransientError(error)) { | |
172 fetcher_backoff_.InformOfRequest(false); | |
173 fetcher_timer_.Start( | |
174 FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(), this, | |
175 &DeviceActivityFetcher::StartFetchingListIdpSessions); | |
176 return; | |
177 } | |
178 observer_->OnFetchDeviceActivityFailure(); | |
179 } | |
180 | |
181 void DeviceActivityFetcher::OnGetTokenResponseSuccess( | |
182 const ClientOAuthResult& result) { | |
183 fetcher_backoff_.InformOfRequest(true); | |
184 access_token_ = result.access_token; | |
185 StartFetchingListDevices(); | |
186 } | |
187 | |
188 void DeviceActivityFetcher::OnGetTokenResponseError( | |
189 const GoogleServiceAuthError& error) { | |
190 if (++fetcher_retries_ < kMaxFetcherRetries && IsTransientError(error)) { | |
191 fetcher_backoff_.InformOfRequest(false); | |
192 fetcher_timer_.Start( | |
193 FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(), this, | |
194 &DeviceActivityFetcher::StartFetchingGetTokenResponse); | |
195 return; | |
196 } | |
197 observer_->OnFetchDeviceActivityFailure(); | |
198 } | |
OLD | NEW |