| 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/string_number_conversions.h" | 12 #include "base/string_number_conversions.h" |
| 13 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
| 14 #include "base/values.h" | 14 #include "base/values.h" |
| 15 #include "content/browser/geolocation/location_arbitrator.h" |
| 15 #include "content/public/common/geoposition.h" | 16 #include "content/public/common/geoposition.h" |
| 17 #include "google_apis/google_api_keys.h" |
| 16 #include "net/base/escape.h" | 18 #include "net/base/escape.h" |
| 17 #include "net/base/load_flags.h" | 19 #include "net/base/load_flags.h" |
| 18 #include "net/url_request/url_fetcher.h" | 20 #include "net/url_request/url_fetcher.h" |
| 19 #include "net/url_request/url_request_context_getter.h" | 21 #include "net/url_request/url_request_context_getter.h" |
| 20 #include "net/url_request/url_request_status.h" | 22 #include "net/url_request/url_request_status.h" |
| 21 | 23 |
| 22 namespace { | 24 namespace { |
| 23 | 25 |
| 24 const size_t kMaxRequestLength = 2048; | 26 const size_t kMaxRequestLength = 2048; |
| 25 | 27 |
| 26 const char kAccessTokenString[] = "access_token"; | 28 const char kAccessTokenString[] = "accessToken"; |
| 27 const char kLocationString[] = "location"; | 29 const char kLocationString[] = "location"; |
| 28 const char kLatitudeString[] = "lat"; | 30 const char kLatitudeString[] = "lat"; |
| 29 const char kLongitudeString[] = "lng"; | 31 const char kLongitudeString[] = "lng"; |
| 30 const char kAccuracyString[] = "accuracy"; | 32 const char kAccuracyString[] = "accuracy"; |
| 31 const char kStatusString[] = "status"; | 33 const char kStatusString[] = "status"; |
| 32 const char kStatusOKString[] = "OK"; | 34 const char kStatusOKString[] = "OK"; |
| 33 | 35 |
| 34 // Local functions | 36 // Local functions |
| 35 // Creates the request url to send to the server. | 37 // Creates the request url to send to the server. |
| 36 GURL FormRequestURL(const std::string& url, | 38 GURL FormRequestURL(const GURL& url); |
| 39 |
| 40 void FormUploadData(const WifiData& wifi_data, |
| 41 const base::Time& timestamp, |
| 37 const string16& access_token, | 42 const string16& access_token, |
| 38 const WifiData& wifi_data, | 43 std::string* upload_data); |
| 39 const base::Time& timestamp); | |
| 40 | 44 |
| 41 // Parsers the server response. | 45 // Parsers the server response. |
| 42 void GetLocationFromResponse(bool http_post_result, | 46 void GetLocationFromResponse(bool http_post_result, |
| 43 int status_code, | 47 int status_code, |
| 44 const std::string& response_body, | 48 const std::string& response_body, |
| 45 const base::Time& timestamp, | 49 const base::Time& timestamp, |
| 46 const GURL& server_url, | 50 const GURL& server_url, |
| 47 content::Geoposition* position, | 51 content::Geoposition* position, |
| 48 string16* access_token); | 52 string16* access_token); |
| 49 | 53 |
| 50 // Parses the server response body. Returns true if parsing was successful. | 54 // Parses the server response body. Returns true if parsing was successful. |
| 51 // Sets |*position| to the parsed location if a valid fix was received, | 55 // Sets |*position| to the parsed location if a valid fix was received, |
| 52 // otherwise leaves it unchanged. | 56 // otherwise leaves it unchanged. |
| 53 bool ParseServerResponse(const std::string& response_body, | 57 bool ParseServerResponse(const std::string& response_body, |
| 54 const base::Time& timestamp, | 58 const base::Time& timestamp, |
| 55 content::Geoposition* position, | 59 content::Geoposition* position, |
| 56 string16* access_token); | 60 string16* access_token); |
| 57 void AddWifiData(const WifiData& wifi_data, | 61 void AddWifiData(const WifiData& wifi_data, |
| 58 int age_milliseconds, | 62 int age_milliseconds, |
| 59 std::vector<std::string>* params); | 63 base::DictionaryValue* request); |
| 60 } // namespace | 64 } // namespace |
| 61 | 65 |
| 62 int NetworkLocationRequest::url_fetcher_id_for_tests = 0; | 66 int NetworkLocationRequest::url_fetcher_id_for_tests = 0; |
| 63 | 67 |
| 64 NetworkLocationRequest::NetworkLocationRequest( | 68 NetworkLocationRequest::NetworkLocationRequest( |
| 65 net::URLRequestContextGetter* context, | 69 net::URLRequestContextGetter* context, |
| 66 const GURL& url, | 70 const GURL& url, |
| 67 ListenerInterface* listener) | 71 ListenerInterface* listener) |
| 68 : url_context_(context), listener_(listener), | 72 : url_context_(context), listener_(listener), |
| 69 url_(url) { | 73 url_(url) { |
| 70 DCHECK(listener); | 74 DCHECK(listener); |
| 71 } | 75 } |
| 72 | 76 |
| 73 NetworkLocationRequest::~NetworkLocationRequest() { | 77 NetworkLocationRequest::~NetworkLocationRequest() { |
| 74 } | 78 } |
| 75 | 79 |
| 76 bool NetworkLocationRequest::MakeRequest(const string16& access_token, | 80 bool NetworkLocationRequest::MakeRequest(const string16& access_token, |
| 77 const WifiData& wifi_data, | 81 const WifiData& wifi_data, |
| 78 const base::Time& timestamp) { | 82 const base::Time& timestamp) { |
| 79 if (url_fetcher_ != NULL) { | 83 if (url_fetcher_ != NULL) { |
| 80 DVLOG(1) << "NetworkLocationRequest : Cancelling pending request"; | 84 DVLOG(1) << "NetworkLocationRequest : Cancelling pending request"; |
| 81 url_fetcher_.reset(); | 85 url_fetcher_.reset(); |
| 82 } | 86 } |
| 83 wifi_data_ = wifi_data; | 87 wifi_data_ = wifi_data; |
| 84 timestamp_ = timestamp; | 88 timestamp_ = timestamp; |
| 85 | 89 |
| 86 GURL request_url = FormRequestURL(url_.spec(), access_token, | 90 GURL request_url = FormRequestURL(url_); |
| 87 wifi_data, timestamp_); | |
| 88 url_fetcher_.reset(net::URLFetcher::Create( | 91 url_fetcher_.reset(net::URLFetcher::Create( |
| 89 url_fetcher_id_for_tests, request_url, net::URLFetcher::GET, this)); | 92 url_fetcher_id_for_tests, request_url, net::URLFetcher::POST, this)); |
| 90 url_fetcher_->SetRequestContext(url_context_); | 93 url_fetcher_->SetRequestContext(url_context_); |
| 94 std::string upload_data; |
| 95 FormUploadData(wifi_data, timestamp, access_token, &upload_data); |
| 96 url_fetcher_->SetUploadData("application/json", upload_data); |
| 91 url_fetcher_->SetLoadFlags( | 97 url_fetcher_->SetLoadFlags( |
| 92 net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE | | 98 net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE | |
| 93 net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES | | 99 net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES | |
| 94 net::LOAD_DO_NOT_SEND_AUTH_DATA); | 100 net::LOAD_DO_NOT_SEND_AUTH_DATA); |
| 95 | 101 |
| 96 url_fetcher_->Start(); | 102 url_fetcher_->Start(); |
| 97 return true; | 103 return true; |
| 98 } | 104 } |
| 99 | 105 |
| 100 void NetworkLocationRequest::OnURLFetchComplete( | 106 void NetworkLocationRequest::OnURLFetchComplete( |
| (...skipping 27 matching lines...) Expand all Loading... |
| 128 // Local functions. | 134 // Local functions. |
| 129 namespace { | 135 namespace { |
| 130 | 136 |
| 131 struct AccessPointLess { | 137 struct AccessPointLess { |
| 132 bool operator()(const AccessPointData* ap1, | 138 bool operator()(const AccessPointData* ap1, |
| 133 const AccessPointData* ap2) const { | 139 const AccessPointData* ap2) const { |
| 134 return ap2->radio_signal_strength < ap1->radio_signal_strength; | 140 return ap2->radio_signal_strength < ap1->radio_signal_strength; |
| 135 } | 141 } |
| 136 }; | 142 }; |
| 137 | 143 |
| 138 GURL FormRequestURL(const std::string& url, | 144 GURL FormRequestURL(const GURL& url) { |
| 145 if (url == GeolocationArbitrator::DefaultNetworkProviderURL()) { |
| 146 std::string api_key = google_apis::GetAPIKey(); |
| 147 if (!api_key.empty()) { |
| 148 std::string query(url.query()); |
| 149 if (!query.empty()) |
| 150 query += "&"; |
| 151 query += "key=" + net::EscapeQueryParamValue(api_key, true); |
| 152 GURL::Replacements replacements; |
| 153 replacements.SetQueryStr(query); |
| 154 return url.ReplaceComponents(replacements); |
| 155 } |
| 156 } |
| 157 return url; |
| 158 } |
| 159 |
| 160 void FormUploadData(const WifiData& wifi_data, |
| 161 const base::Time& timestamp, |
| 139 const string16& access_token, | 162 const string16& access_token, |
| 140 const WifiData& wifi_data, | 163 std::string* upload_data) { |
| 141 const base::Time& timestamp) { | |
| 142 int age = kint32min; // Invalid so AddInteger() will ignore. | 164 int age = kint32min; // Invalid so AddInteger() will ignore. |
| 143 if (!timestamp.is_null()) { | 165 if (!timestamp.is_null()) { |
| 144 // Convert absolute timestamps into a relative age. | 166 // Convert absolute timestamps into a relative age. |
| 145 int64 delta_ms = (base::Time::Now() - timestamp).InMilliseconds(); | 167 int64 delta_ms = (base::Time::Now() - timestamp).InMilliseconds(); |
| 146 if (delta_ms >= 0 && delta_ms < kint32max) | 168 if (delta_ms >= 0 && delta_ms < kint32max) |
| 147 age = static_cast<int>(delta_ms); | 169 age = static_cast<int>(delta_ms); |
| 148 } | 170 } |
| 149 | 171 |
| 150 std::vector<std::string> params; | 172 base::DictionaryValue request; |
| 151 #if defined(GOOGLE_CHROME_BUILD) | 173 AddWifiData(wifi_data, age, &request); |
| 152 params.push_back("browser=googlechrome"); | |
| 153 #else | |
| 154 params.push_back("browser=chromium"); | |
| 155 #endif | |
| 156 | |
| 157 params.push_back("sensor=true"); | |
| 158 if (!access_token.empty()) | 174 if (!access_token.empty()) |
| 159 params.push_back("token=" + UTF16ToUTF8(access_token)); | 175 request.SetString(kAccessTokenString, access_token); |
| 160 AddWifiData(wifi_data, age, ¶ms); | 176 base::JSONWriter::Write(&request, upload_data); |
| 161 | |
| 162 std::string request_string = url + '?' + JoinString(params, '&'); | |
| 163 if (request_string.length() > kMaxRequestLength) { | |
| 164 size_t last_param_pos = | |
| 165 request_string.find_last_of('&', kMaxRequestLength); | |
| 166 CHECK_NE(std::string::npos, last_param_pos); | |
| 167 request_string.erase(last_param_pos); | |
| 168 } | |
| 169 | |
| 170 return GURL(request_string); | |
| 171 } | 177 } |
| 172 | 178 |
| 173 void AddString(const std::string& property_name, const std::string& value, | 179 void AddString(const std::string& property_name, const std::string& value, |
| 174 std::string* wifi_params) { | 180 base::DictionaryValue* dict) { |
| 175 DCHECK(wifi_params); | 181 DCHECK(dict); |
| 176 if (!value.empty()) { | 182 if (!value.empty()) |
| 177 if (!wifi_params->empty()) | 183 dict->SetString(property_name, value); |
| 178 *wifi_params += '|'; | |
| 179 *wifi_params += property_name; | |
| 180 *wifi_params += value; | |
| 181 } | |
| 182 } | 184 } |
| 183 | 185 |
| 184 void AddInteger(const std::string& property_name, int value, | 186 void AddInteger(const std::string& property_name, int value, |
| 185 std::string* wifi_params) { | 187 base::DictionaryValue* dict) { |
| 186 DCHECK(wifi_params); | 188 DCHECK(dict); |
| 187 if (value != kint32min) { | 189 if (value != kint32min) |
| 188 if (!wifi_params->empty()) | 190 dict->SetInteger(property_name, value); |
| 189 *wifi_params += '|'; | |
| 190 *wifi_params += property_name; | |
| 191 *wifi_params += base::IntToString(value); | |
| 192 } | |
| 193 } | 191 } |
| 194 | 192 |
| 195 void AddWifiData(const WifiData& wifi_data, | 193 void AddWifiData(const WifiData& wifi_data, |
| 196 int age_milliseconds, | 194 int age_milliseconds, |
| 197 std::vector<std::string>* params) { | 195 base::DictionaryValue* request) { |
| 198 DCHECK(params); | 196 DCHECK(request); |
| 199 | 197 |
| 200 if (wifi_data.access_point_data.empty()) | 198 if (wifi_data.access_point_data.empty()) |
| 201 return; | 199 return; |
| 202 | 200 |
| 203 typedef std::multiset<const AccessPointData*, AccessPointLess> AccessPointSet; | 201 typedef std::multiset<const AccessPointData*, AccessPointLess> AccessPointSet; |
| 204 AccessPointSet access_points_by_signal_strength; | 202 AccessPointSet access_points_by_signal_strength; |
| 205 | 203 |
| 206 for (WifiData::AccessPointDataSet::const_iterator iter = | 204 for (WifiData::AccessPointDataSet::const_iterator iter = |
| 207 wifi_data.access_point_data.begin(); | 205 wifi_data.access_point_data.begin(); |
| 208 iter != wifi_data.access_point_data.end(); | 206 iter != wifi_data.access_point_data.end(); |
| 209 ++iter) { | 207 ++iter) { |
| 210 access_points_by_signal_strength.insert(&(*iter)); | 208 access_points_by_signal_strength.insert(&(*iter)); |
| 211 } | 209 } |
| 212 | 210 |
| 211 base::ListValue* wifi_access_point_list = new base::ListValue(); |
| 213 for (AccessPointSet::iterator iter = | 212 for (AccessPointSet::iterator iter = |
| 214 access_points_by_signal_strength.begin(); | 213 access_points_by_signal_strength.begin(); |
| 215 iter != access_points_by_signal_strength.end(); | 214 iter != access_points_by_signal_strength.end(); |
| 216 ++iter) { | 215 ++iter) { |
| 217 std::string wifi_params; | 216 base::DictionaryValue* wifi_dict = new base::DictionaryValue(); |
| 218 AddString("mac:", UTF16ToUTF8((*iter)->mac_address), &wifi_params); | 217 AddString("macAddress", UTF16ToUTF8((*iter)->mac_address), wifi_dict); |
| 219 AddInteger("ss:", (*iter)->radio_signal_strength, &wifi_params); | 218 AddInteger("signalStrength", (*iter)->radio_signal_strength, wifi_dict); |
| 220 AddInteger("age:", age_milliseconds, &wifi_params); | 219 AddInteger("age", age_milliseconds, wifi_dict); |
| 221 AddInteger("chan:", (*iter)->channel, &wifi_params); | 220 AddInteger("channel", (*iter)->channel, wifi_dict); |
| 222 AddInteger("snr:", (*iter)->signal_to_noise, &wifi_params); | 221 AddInteger("signalToNoiseRatio", (*iter)->signal_to_noise, wifi_dict); |
| 223 std::string ssid = UTF16ToUTF8((*iter)->ssid); | 222 wifi_access_point_list->Append(wifi_dict); |
| 224 // Backslash characters in the ssid need backslash-escaping to avoid | |
| 225 // escaping a following wifi parameter separator. | |
| 226 ReplaceSubstringsAfterOffset(&ssid, 0, "\\", "\\\\"); | |
| 227 // Pipe characters in the ssid need backslash-escaping to avoid being | |
| 228 // interpreted as the wifi parameter separator. | |
| 229 ReplaceSubstringsAfterOffset(&ssid, 0, "|", "\\|"); | |
| 230 AddString("ssid:", ssid, &wifi_params); | |
| 231 params->push_back( | |
| 232 "wifi=" + net::EscapeQueryParamValue(wifi_params, false)); | |
| 233 } | 223 } |
| 224 request->Set("wifiAccessPoints", wifi_access_point_list); |
| 234 } | 225 } |
| 235 | 226 |
| 236 void FormatPositionError(const GURL& server_url, | 227 void FormatPositionError(const GURL& server_url, |
| 237 const std::string& message, | 228 const std::string& message, |
| 238 content::Geoposition* position) { | 229 content::Geoposition* position) { |
| 239 position->error_code = | 230 position->error_code = |
| 240 content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; | 231 content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; |
| 241 position->error_message = "Network location provider at '"; | 232 position->error_message = "Network location provider at '"; |
| 242 position->error_message += server_url.possibly_invalid_spec(); | 233 position->error_message += server_url.GetOrigin().spec(); |
| 243 position->error_message += "' : "; | 234 position->error_message += "' : "; |
| 244 position->error_message += message; | 235 position->error_message += message; |
| 245 position->error_message += "."; | 236 position->error_message += "."; |
| 246 VLOG(1) << "NetworkLocationRequest::GetLocationFromResponse() : " | 237 VLOG(1) << "NetworkLocationRequest::GetLocationFromResponse() : " |
| 247 << position->error_message; | 238 << position->error_message; |
| 248 } | 239 } |
| 249 | 240 |
| 250 void GetLocationFromResponse(bool http_post_result, | 241 void GetLocationFromResponse(bool http_post_result, |
| 251 int status_code, | 242 int status_code, |
| 252 const std::string& response_body, | 243 const std::string& response_body, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 282 FormatPositionError(server_url, | 273 FormatPositionError(server_url, |
| 283 "Did not provide a good position fix", position); | 274 "Did not provide a good position fix", position); |
| 284 return; | 275 return; |
| 285 } | 276 } |
| 286 } | 277 } |
| 287 | 278 |
| 288 // Numeric values without a decimal point have type integer and IsDouble() will | 279 // Numeric values without a decimal point have type integer and IsDouble() will |
| 289 // return false. This is convenience function for detecting integer or floating | 280 // return false. This is convenience function for detecting integer or floating |
| 290 // point numeric values. Note that isIntegral() includes boolean values, which | 281 // point numeric values. Note that isIntegral() includes boolean values, which |
| 291 // is not what we want. | 282 // is not what we want. |
| 292 bool GetAsDouble(const DictionaryValue& object, | 283 bool GetAsDouble(const base::DictionaryValue& object, |
| 293 const std::string& property_name, | 284 const std::string& property_name, |
| 294 double* out) { | 285 double* out) { |
| 295 DCHECK(out); | 286 DCHECK(out); |
| 296 const Value* value = NULL; | 287 const Value* value = NULL; |
| 297 if (!object.Get(property_name, &value)) | 288 if (!object.Get(property_name, &value)) |
| 298 return false; | 289 return false; |
| 299 int value_as_int; | 290 int value_as_int; |
| 300 DCHECK(value); | 291 DCHECK(value); |
| 301 if (value->GetAsInteger(&value_as_int)) { | 292 if (value->GetAsInteger(&value_as_int)) { |
| 302 *out = value_as_int; | 293 *out = value_as_int; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 329 LOG(WARNING) << "ParseServerResponse() : JSONReader failed : " | 320 LOG(WARNING) << "ParseServerResponse() : JSONReader failed : " |
| 330 << error_msg; | 321 << error_msg; |
| 331 return false; | 322 return false; |
| 332 } | 323 } |
| 333 | 324 |
| 334 if (!response_value->IsType(Value::TYPE_DICTIONARY)) { | 325 if (!response_value->IsType(Value::TYPE_DICTIONARY)) { |
| 335 VLOG(1) << "ParseServerResponse() : Unexpected response type " | 326 VLOG(1) << "ParseServerResponse() : Unexpected response type " |
| 336 << response_value->GetType(); | 327 << response_value->GetType(); |
| 337 return false; | 328 return false; |
| 338 } | 329 } |
| 339 const DictionaryValue* response_object = | 330 const base::DictionaryValue* response_object = |
| 340 static_cast<DictionaryValue*>(response_value.get()); | 331 static_cast<base::DictionaryValue*>(response_value.get()); |
| 341 | |
| 342 // Check the status code. | |
| 343 const Value* status_value = NULL; | |
| 344 if (!response_object->Get(kStatusString, &status_value)) { | |
| 345 VLOG(1) << "ParseServerResponse() : Missing status attribute."; | |
| 346 // The status attribute is required. | |
| 347 return false; | |
| 348 } | |
| 349 DCHECK(status_value); | |
| 350 | |
| 351 if (!status_value->IsType(Value::TYPE_STRING)) { | |
| 352 VLOG(1) << "ParseServerResponse() : Unexpected status type " | |
| 353 << status_value->GetType(); | |
| 354 // The status attribute is required to be a string. | |
| 355 return false; | |
| 356 } | |
| 357 const StringValue* status_object = | |
| 358 static_cast<const StringValue*>(status_value); | |
| 359 | |
| 360 std::string status; | |
| 361 if (!status_object->GetAsString(&status)) { | |
| 362 VLOG(1) << "ParseServerResponse() : Error parsing the status value."; | |
| 363 return false; | |
| 364 } | |
| 365 | |
| 366 if (status != kStatusOKString) { | |
| 367 VLOG(1) << "ParseServerResponse() : Request failed with status " | |
| 368 << status; | |
| 369 return false; | |
| 370 } | |
| 371 | 332 |
| 372 // Get the access token, if any. | 333 // Get the access token, if any. |
| 373 response_object->GetString(kAccessTokenString, access_token); | 334 response_object->GetString(kAccessTokenString, access_token); |
| 374 | 335 |
| 375 // Get the location | 336 // Get the location |
| 376 const Value* location_value = NULL; | 337 const Value* location_value = NULL; |
| 377 if (!response_object->Get(kLocationString, &location_value)) { | 338 if (!response_object->Get(kLocationString, &location_value)) { |
| 378 VLOG(1) << "ParseServerResponse() : Missing location attribute."; | 339 VLOG(1) << "ParseServerResponse() : Missing location attribute."; |
| 379 // GLS returns a response with no location property to represent | 340 // GLS returns a response with no location property to represent |
| 380 // no fix available; return true to indicate successful parse. | 341 // no fix available; return true to indicate successful parse. |
| 381 return true; | 342 return true; |
| 382 } | 343 } |
| 383 DCHECK(location_value); | 344 DCHECK(location_value); |
| 384 | 345 |
| 385 if (!location_value->IsType(Value::TYPE_DICTIONARY)) { | 346 if (!location_value->IsType(Value::TYPE_DICTIONARY)) { |
| 386 if (!location_value->IsType(Value::TYPE_NULL)) { | 347 if (!location_value->IsType(Value::TYPE_NULL)) { |
| 387 VLOG(1) << "ParseServerResponse() : Unexpected location type " | 348 VLOG(1) << "ParseServerResponse() : Unexpected location type " |
| 388 << location_value->GetType(); | 349 << location_value->GetType(); |
| 389 // If the network provider was unable to provide a position fix, it should | 350 // If the network provider was unable to provide a position fix, it should |
| 390 // return a HTTP 200, with "location" : null. Otherwise it's an error. | 351 // return a HTTP 200, with "location" : null. Otherwise it's an error. |
| 391 return false; | 352 return false; |
| 392 } | 353 } |
| 393 return true; // Successfully parsed response containing no fix. | 354 return true; // Successfully parsed response containing no fix. |
| 394 } | 355 } |
| 395 const DictionaryValue* location_object = | 356 const base::DictionaryValue* location_object = |
| 396 static_cast<const DictionaryValue*>(location_value); | 357 static_cast<const base::DictionaryValue*>(location_value); |
| 397 | 358 |
| 398 // latitude and longitude fields are always required. | 359 // latitude and longitude fields are always required. |
| 399 double latitude, longitude; | 360 double latitude, longitude; |
| 400 if (!GetAsDouble(*location_object, kLatitudeString, &latitude) || | 361 if (!GetAsDouble(*location_object, kLatitudeString, &latitude) || |
| 401 !GetAsDouble(*location_object, kLongitudeString, &longitude)) { | 362 !GetAsDouble(*location_object, kLongitudeString, &longitude)) { |
| 402 VLOG(1) << "ParseServerResponse() : location lacks lat and/or long."; | 363 VLOG(1) << "ParseServerResponse() : location lacks lat and/or long."; |
| 403 return false; | 364 return false; |
| 404 } | 365 } |
| 405 // All error paths covered: now start actually modifying postion. | 366 // All error paths covered: now start actually modifying postion. |
| 406 position->latitude = latitude; | 367 position->latitude = latitude; |
| 407 position->longitude = longitude; | 368 position->longitude = longitude; |
| 408 position->timestamp = timestamp; | 369 position->timestamp = timestamp; |
| 409 | 370 |
| 410 // Other fields are optional. | 371 // Other fields are optional. |
| 411 GetAsDouble(*response_object, kAccuracyString, &position->accuracy); | 372 GetAsDouble(*response_object, kAccuracyString, &position->accuracy); |
| 412 | 373 |
| 413 return true; | 374 return true; |
| 414 } | 375 } |
| 415 | 376 |
| 416 } // namespace | 377 } // namespace |
| 378 |
| OLD | NEW |