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