OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/browser/geolocation/network_location_request.h" | 5 #include "content/browser/geolocation/network_location_request.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
(...skipping 13 matching lines...) Expand all Loading... | |
24 | 24 |
25 namespace content { | 25 namespace content { |
26 namespace { | 26 namespace { |
27 | 27 |
28 const char kAccessTokenString[] = "accessToken"; | 28 const char kAccessTokenString[] = "accessToken"; |
29 const char kLocationString[] = "location"; | 29 const char kLocationString[] = "location"; |
30 const char kLatitudeString[] = "lat"; | 30 const char kLatitudeString[] = "lat"; |
31 const char kLongitudeString[] = "lng"; | 31 const char kLongitudeString[] = "lng"; |
32 const char kAccuracyString[] = "accuracy"; | 32 const char kAccuracyString[] = "accuracy"; |
33 | 33 |
34 // NOTE: Never remove or reorder any of these as that would confuse | |
35 // interpretation of previously logged data. Make sure to update the enum list | |
36 // in tools/metrics/histograms/histograms.xml to keep it in sync. | |
timvolodine
2013/09/30 16:38:49
side-note: to slightly help this problem we could
Michael van Ouwerkerk
2013/09/30 17:02:22
Done.
| |
37 enum NetworkLocationRequestEvent { | |
38 NETWORK_LOCATION_REQUEST_EVENT_REQUEST_START, | |
39 NETWORK_LOCATION_REQUEST_EVENT_REQUEST_CANCEL, | |
40 NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_SUCCESS, | |
41 NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_NOT_OK, | |
42 NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_EMPTY, | |
43 NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_MALFORMED, | |
44 NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_INVALID_FIX, | |
45 | |
46 // NOTE: Add entries only immediately above this line. | |
47 NETWORK_LOCATION_REQUEST_EVENT_COUNT | |
48 }; | |
49 | |
50 void RecordUmaEvent(NetworkLocationRequestEvent event) { | |
51 UMA_HISTOGRAM_ENUMERATION("Geolocation.NetworkLocationRequest.Event", | |
52 event, NETWORK_LOCATION_REQUEST_EVENT_COUNT); | |
timvolodine
2013/09/30 16:38:49
indent
Michael van Ouwerkerk
2013/09/30 17:02:22
Done.
| |
53 } | |
54 | |
55 const int kCodeRangeStart = 100; // Range start is inclusive. | |
56 const int kCodeRangeEnd = 600; // Range end is exclusive. | |
57 const int kCodeBuckets = 502; // 500 codes, underflow, and overflow. | |
58 void RecordUmaResponseCode(int code) { | |
59 UMA_HISTOGRAM_CUSTOM_COUNTS("Geolocation.NetworkLocationRequest.ResponseCode", | |
60 code, kCodeRangeStart, kCodeRangeEnd, kCodeBuckets); | |
61 } | |
62 | |
34 // Local functions | 63 // Local functions |
35 // Creates the request url to send to the server. | 64 // Creates the request url to send to the server. |
36 GURL FormRequestURL(const GURL& url); | 65 GURL FormRequestURL(const GURL& url); |
37 | 66 |
38 void FormUploadData(const WifiData& wifi_data, | 67 void FormUploadData(const WifiData& wifi_data, |
39 const base::Time& timestamp, | 68 const base::Time& timestamp, |
40 const string16& access_token, | 69 const string16& access_token, |
41 std::string* upload_data); | 70 std::string* upload_data); |
42 | 71 |
43 // Parsers the server response. | 72 // Attempts to extract a position from the response. Detects and indicates |
73 // various failure cases. | |
44 void GetLocationFromResponse(bool http_post_result, | 74 void GetLocationFromResponse(bool http_post_result, |
45 int status_code, | 75 int status_code, |
46 const std::string& response_body, | 76 const std::string& response_body, |
47 const base::Time& timestamp, | 77 const base::Time& timestamp, |
48 const GURL& server_url, | 78 const GURL& server_url, |
49 Geoposition* position, | 79 Geoposition* position, |
50 string16* access_token); | 80 string16* access_token); |
51 | 81 |
52 // Parses the server response body. Returns true if parsing was successful. | 82 // Parses the server response body. Returns true if parsing was successful. |
53 // Sets |*position| to the parsed location if a valid fix was received, | 83 // Sets |*position| to the parsed location if a valid fix was received, |
(...skipping 17 matching lines...) Expand all Loading... | |
71 callback_(callback), | 101 callback_(callback), |
72 url_(url) { | 102 url_(url) { |
73 } | 103 } |
74 | 104 |
75 NetworkLocationRequest::~NetworkLocationRequest() { | 105 NetworkLocationRequest::~NetworkLocationRequest() { |
76 } | 106 } |
77 | 107 |
78 bool NetworkLocationRequest::MakeRequest(const string16& access_token, | 108 bool NetworkLocationRequest::MakeRequest(const string16& access_token, |
79 const WifiData& wifi_data, | 109 const WifiData& wifi_data, |
80 const base::Time& timestamp) { | 110 const base::Time& timestamp) { |
111 RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_REQUEST_START); | |
81 if (url_fetcher_ != NULL) { | 112 if (url_fetcher_ != NULL) { |
82 DVLOG(1) << "NetworkLocationRequest : Cancelling pending request"; | 113 DVLOG(1) << "NetworkLocationRequest : Cancelling pending request"; |
114 RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_REQUEST_CANCEL); | |
83 url_fetcher_.reset(); | 115 url_fetcher_.reset(); |
84 } | 116 } |
85 wifi_data_ = wifi_data; | 117 wifi_data_ = wifi_data; |
86 timestamp_ = timestamp; | 118 timestamp_ = timestamp; |
87 | 119 |
88 GURL request_url = FormRequestURL(url_); | 120 GURL request_url = FormRequestURL(url_); |
89 url_fetcher_.reset(net::URLFetcher::Create( | 121 url_fetcher_.reset(net::URLFetcher::Create( |
90 url_fetcher_id_for_tests, request_url, net::URLFetcher::POST, this)); | 122 url_fetcher_id_for_tests, request_url, net::URLFetcher::POST, this)); |
91 url_fetcher_->SetRequestContext(url_context_.get()); | 123 url_fetcher_->SetRequestContext(url_context_.get()); |
92 std::string upload_data; | 124 std::string upload_data; |
93 FormUploadData(wifi_data, timestamp, access_token, &upload_data); | 125 FormUploadData(wifi_data, timestamp, access_token, &upload_data); |
94 url_fetcher_->SetUploadData("application/json", upload_data); | 126 url_fetcher_->SetUploadData("application/json", upload_data); |
95 url_fetcher_->SetLoadFlags( | 127 url_fetcher_->SetLoadFlags( |
96 net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE | | 128 net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE | |
97 net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES | | 129 net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES | |
98 net::LOAD_DO_NOT_SEND_AUTH_DATA); | 130 net::LOAD_DO_NOT_SEND_AUTH_DATA); |
99 | 131 |
100 start_time_ = base::TimeTicks::Now(); | 132 start_time_ = base::TimeTicks::Now(); |
101 url_fetcher_->Start(); | 133 url_fetcher_->Start(); |
102 return true; | 134 return true; |
103 } | 135 } |
104 | 136 |
105 void NetworkLocationRequest::OnURLFetchComplete( | 137 void NetworkLocationRequest::OnURLFetchComplete( |
106 const net::URLFetcher* source) { | 138 const net::URLFetcher* source) { |
107 DCHECK_EQ(url_fetcher_.get(), source); | 139 DCHECK_EQ(url_fetcher_.get(), source); |
108 | 140 |
109 net::URLRequestStatus status = source->GetStatus(); | 141 net::URLRequestStatus status = source->GetStatus(); |
110 int response_code = source->GetResponseCode(); | 142 int response_code = source->GetResponseCode(); |
143 RecordUmaResponseCode(response_code); | |
111 | 144 |
112 Geoposition position; | 145 Geoposition position; |
113 string16 access_token; | 146 string16 access_token; |
114 std::string data; | 147 std::string data; |
115 source->GetResponseAsString(&data); | 148 source->GetResponseAsString(&data); |
116 GetLocationFromResponse(status.is_success(), | 149 GetLocationFromResponse(status.is_success(), |
117 response_code, | 150 response_code, |
118 data, | 151 data, |
119 timestamp_, | 152 timestamp_, |
120 source->GetURL(), | 153 source->GetURL(), |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
252 const GURL& server_url, | 285 const GURL& server_url, |
253 Geoposition* position, | 286 Geoposition* position, |
254 string16* access_token) { | 287 string16* access_token) { |
255 DCHECK(position); | 288 DCHECK(position); |
256 DCHECK(access_token); | 289 DCHECK(access_token); |
257 | 290 |
258 // HttpPost can fail for a number of reasons. Most likely this is because | 291 // HttpPost can fail for a number of reasons. Most likely this is because |
259 // we're offline, or there was no response. | 292 // we're offline, or there was no response. |
260 if (!http_post_result) { | 293 if (!http_post_result) { |
261 FormatPositionError(server_url, "No response received", position); | 294 FormatPositionError(server_url, "No response received", position); |
295 RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_EMPTY); | |
262 return; | 296 return; |
263 } | 297 } |
264 if (status_code != 200) { // HTTP OK. | 298 if (status_code != 200) { // HTTP OK. |
265 std::string message = "Returned error code "; | 299 std::string message = "Returned error code "; |
266 message += base::IntToString(status_code); | 300 message += base::IntToString(status_code); |
267 FormatPositionError(server_url, message, position); | 301 FormatPositionError(server_url, message, position); |
302 RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_NOT_OK); | |
268 return; | 303 return; |
269 } | 304 } |
270 // We use the timestamp from the wifi data that was used to generate | 305 // We use the timestamp from the wifi data that was used to generate |
271 // this position fix. | 306 // this position fix. |
272 if (!ParseServerResponse(response_body, timestamp, position, access_token)) { | 307 if (!ParseServerResponse(response_body, timestamp, position, access_token)) { |
273 // We failed to parse the repsonse. | 308 // We failed to parse the repsonse. |
274 FormatPositionError(server_url, "Response was malformed", position); | 309 FormatPositionError(server_url, "Response was malformed", position); |
310 RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_MALFORMED); | |
275 return; | 311 return; |
276 } | 312 } |
277 // The response was successfully parsed, but it may not be a valid | 313 // The response was successfully parsed, but it may not be a valid |
278 // position fix. | 314 // position fix. |
279 if (!position->Validate()) { | 315 if (!position->Validate()) { |
280 FormatPositionError(server_url, | 316 FormatPositionError(server_url, |
281 "Did not provide a good position fix", position); | 317 "Did not provide a good position fix", position); |
318 RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_INVALID_FIX); | |
282 return; | 319 return; |
283 } | 320 } |
321 RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_SUCCESS); | |
322 return; | |
bulach
2013/09/30 16:27:21
nit: remove return
Michael van Ouwerkerk
2013/09/30 17:02:22
Oops, experiment leftover. Done.
| |
284 } | 323 } |
285 | 324 |
286 // Numeric values without a decimal point have type integer and IsDouble() will | 325 // Numeric values without a decimal point have type integer and IsDouble() will |
287 // return false. This is convenience function for detecting integer or floating | 326 // return false. This is convenience function for detecting integer or floating |
288 // point numeric values. Note that isIntegral() includes boolean values, which | 327 // point numeric values. Note that isIntegral() includes boolean values, which |
289 // is not what we want. | 328 // is not what we want. |
290 bool GetAsDouble(const base::DictionaryValue& object, | 329 bool GetAsDouble(const base::DictionaryValue& object, |
291 const std::string& property_name, | 330 const std::string& property_name, |
292 double* out) { | 331 double* out) { |
293 DCHECK(out); | 332 DCHECK(out); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 | 416 |
378 // Other fields are optional. | 417 // Other fields are optional. |
379 GetAsDouble(*response_object, kAccuracyString, &position->accuracy); | 418 GetAsDouble(*response_object, kAccuracyString, &position->accuracy); |
380 | 419 |
381 return true; | 420 return true; |
382 } | 421 } |
383 | 422 |
384 } // namespace | 423 } // namespace |
385 | 424 |
386 } // namespace content | 425 } // namespace content |
OLD | NEW |