| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 "chromeos/geolocation/simple_geolocation_request.h" | 5 #include "chromeos/geolocation/simple_geolocation_request.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 UMA_HISTOGRAM_CUSTOM_TIMES(name, \ | 34 UMA_HISTOGRAM_CUSTOM_TIMES(name, \ |
| 35 sample, \ | 35 sample, \ |
| 36 base::TimeDelta::FromMilliseconds(10), \ | 36 base::TimeDelta::FromMilliseconds(10), \ |
| 37 base::TimeDelta::FromMinutes(2), \ | 37 base::TimeDelta::FromMinutes(2), \ |
| 38 50) | 38 50) |
| 39 | 39 |
| 40 namespace chromeos { | 40 namespace chromeos { |
| 41 | 41 |
| 42 namespace { | 42 namespace { |
| 43 | 43 |
| 44 // The full request text. (no parameters are supported by now) | 44 // Used if sending location signals (WiFi APs, cell towers, etc) is disabled. |
| 45 const char kSimpleGeolocationRequestBody[] = "{\"considerIp\": \"true\"}"; | 45 constexpr char kSimpleGeolocationRequestBody[] = "{\"considerIp\": \"true\"}"; |
| 46 | 46 |
| 47 // Request data | 47 // Geolocation request field keys: |
| 48 const char kConsiderIp[] = "considerIp"; | 48 // Top-level request data fields. |
| 49 const char kWifiAccessPoints[] = "wifiAccessPoints"; | 49 constexpr char kConsiderIp[] = "considerIp"; |
| 50 constexpr char kWifiAccessPoints[] = "wifiAccessPoints"; |
| 51 constexpr char kCellTowers[] = "cellTowers"; |
| 52 // Shared Wifi and Cell Tower objects. |
| 53 constexpr char kAge[] = "age"; |
| 54 constexpr char kSignalStrength[] = "signalStrength"; |
| 55 // WiFi access point objects. |
| 56 constexpr char kMacAddress[] = "macAddress"; |
| 57 constexpr char kChannel[] = "channel"; |
| 58 constexpr char kSignalToNoiseRatio[] = "signalToNoiseRatio"; |
| 59 // Cell tower objects. |
| 60 constexpr char kCellId[] = "cellId"; |
| 61 constexpr char kLocationAreaCode[] = "locationAreaCode"; |
| 62 constexpr char kMobileCountryCode[] = "mobileCountryCode"; |
| 63 constexpr char kMobileNetworkCode[] = "mobileNetworkCode"; |
| 50 | 64 |
| 51 // WiFi access point objects. | 65 // Geolocation response field keys: |
| 52 const char kMacAddress[] = "macAddress"; | 66 constexpr char kLocationString[] = "location"; |
| 53 const char kSignalStrength[] = "signalStrength"; | 67 constexpr char kLatString[] = "lat"; |
| 54 const char kAge[] = "age"; | 68 constexpr char kLngString[] = "lng"; |
| 55 const char kChannel[] = "channel"; | 69 constexpr char kAccuracyString[] = "accuracy"; |
| 56 const char kSignalToNoiseRatio[] = "signalToNoiseRatio"; | |
| 57 | 70 |
| 58 // Response data. | |
| 59 const char kLocationString[] = "location"; | |
| 60 const char kLatString[] = "lat"; | |
| 61 const char kLngString[] = "lng"; | |
| 62 const char kAccuracyString[] = "accuracy"; | |
| 63 // Error object and its contents. | 71 // Error object and its contents. |
| 64 const char kErrorString[] = "error"; | 72 constexpr char kErrorString[] = "error"; |
| 65 // "errors" array in "erorr" object is ignored. | 73 // "errors" array in "erorr" object is ignored. |
| 66 const char kCodeString[] = "code"; | 74 constexpr char kCodeString[] = "code"; |
| 67 const char kMessageString[] = "message"; | 75 constexpr char kMessageString[] = "message"; |
| 68 | 76 |
| 69 // We are using "sparse" histograms for the number of retry attempts, | 77 // We are using "sparse" histograms for the number of retry attempts, |
| 70 // so we need to explicitly limit maximum value (in case something goes wrong). | 78 // so we need to explicitly limit maximum value (in case something goes wrong). |
| 71 const size_t kMaxRetriesValueInHistograms = 20; | 79 const size_t kMaxRetriesValueInHistograms = 20; |
| 72 | 80 |
| 73 // Sleep between geolocation request retry on HTTP error. | 81 // Sleep between geolocation request retry on HTTP error. |
| 74 const unsigned int kResolveGeolocationRetrySleepOnServerErrorSeconds = 5; | 82 const unsigned int kResolveGeolocationRetrySleepOnServerErrorSeconds = 5; |
| 75 | 83 |
| 76 // Sleep between geolocation request retry on bad server response. | 84 // Sleep between geolocation request retry on bad server response. |
| 77 const unsigned int kResolveGeolocationRetrySleepBadResponseSeconds = 10; | 85 const unsigned int kResolveGeolocationRetrySleepBadResponseSeconds = 10; |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_NOT_OK); | 292 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_NOT_OK); |
| 285 return false; | 293 return false; |
| 286 } | 294 } |
| 287 | 295 |
| 288 return ParseServerResponse(server_url, response_body, position); | 296 return ParseServerResponse(server_url, response_body, position); |
| 289 } | 297 } |
| 290 | 298 |
| 291 void ReportUmaHasWiFiAccessPoints(bool value) { | 299 void ReportUmaHasWiFiAccessPoints(bool value) { |
| 292 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints", value); | 300 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints", value); |
| 293 } | 301 } |
| 302 void ReportUmaHasCellTowers(bool value) { |
| 303 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasCellTowers", value); |
| 304 } |
| 305 |
| 306 // Helpers to reformat data into dictionaries for conversion to request JSON |
| 307 std::unique_ptr<base::DictionaryValue> CreateAccessPointDictionary( |
| 308 WifiAccessPoint access_point) { |
| 309 auto access_point_dictionary = base::MakeUnique<base::DictionaryValue>(); |
| 310 |
| 311 access_point_dictionary->SetStringWithoutPathExpansion( |
| 312 kMacAddress, access_point.mac_address); |
| 313 access_point_dictionary->SetIntegerWithoutPathExpansion( |
| 314 kSignalStrength, access_point.signal_strength); |
| 315 if (!access_point.timestamp.is_null()) { |
| 316 access_point_dictionary->SetStringWithoutPathExpansion( |
| 317 kAge, |
| 318 base::Int64ToString( |
| 319 (base::Time::Now() - access_point.timestamp).InMilliseconds())); |
| 320 } |
| 321 |
| 322 access_point_dictionary->SetIntegerWithoutPathExpansion(kChannel, |
| 323 access_point.channel); |
| 324 access_point_dictionary->SetIntegerWithoutPathExpansion( |
| 325 kSignalToNoiseRatio, access_point.signal_to_noise); |
| 326 |
| 327 return access_point_dictionary; |
| 328 } |
| 329 |
| 330 std::unique_ptr<base::DictionaryValue> CreateCellTowerDictionary( |
| 331 CellTower cell_tower) { |
| 332 auto cell_tower_dictionary = base::MakeUnique<base::DictionaryValue>(); |
| 333 cell_tower_dictionary->SetStringWithoutPathExpansion(kCellId, cell_tower.ci); |
| 334 cell_tower_dictionary->SetStringWithoutPathExpansion(kLocationAreaCode, |
| 335 cell_tower.lac); |
| 336 cell_tower_dictionary->SetStringWithoutPathExpansion(kMobileCountryCode, |
| 337 cell_tower.mcc); |
| 338 cell_tower_dictionary->SetStringWithoutPathExpansion(kMobileNetworkCode, |
| 339 cell_tower.mnc); |
| 340 |
| 341 if (!cell_tower.timestamp.is_null()) { |
| 342 cell_tower_dictionary->SetStringWithoutPathExpansion( |
| 343 kAge, base::Int64ToString( |
| 344 (base::Time::Now() - cell_tower.timestamp).InMilliseconds())); |
| 345 } |
| 346 return cell_tower_dictionary; |
| 347 } |
| 294 | 348 |
| 295 } // namespace | 349 } // namespace |
| 296 | 350 |
| 297 SimpleGeolocationRequest::SimpleGeolocationRequest( | 351 SimpleGeolocationRequest::SimpleGeolocationRequest( |
| 298 net::URLRequestContextGetter* url_context_getter, | 352 net::URLRequestContextGetter* url_context_getter, |
| 299 const GURL& service_url, | 353 const GURL& service_url, |
| 300 base::TimeDelta timeout, | 354 base::TimeDelta timeout, |
| 301 std::unique_ptr<WifiAccessPointVector> wifi_data) | 355 std::unique_ptr<WifiAccessPointVector> wifi_data, |
| 356 std::unique_ptr<CellTowerVector> cell_tower_data) |
| 302 : url_context_getter_(url_context_getter), | 357 : url_context_getter_(url_context_getter), |
| 303 service_url_(service_url), | 358 service_url_(service_url), |
| 304 retry_sleep_on_server_error_(base::TimeDelta::FromSeconds( | 359 retry_sleep_on_server_error_(base::TimeDelta::FromSeconds( |
| 305 kResolveGeolocationRetrySleepOnServerErrorSeconds)), | 360 kResolveGeolocationRetrySleepOnServerErrorSeconds)), |
| 306 retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds( | 361 retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds( |
| 307 kResolveGeolocationRetrySleepBadResponseSeconds)), | 362 kResolveGeolocationRetrySleepBadResponseSeconds)), |
| 308 timeout_(timeout), | 363 timeout_(timeout), |
| 309 retries_(0), | 364 retries_(0), |
| 310 wifi_data_(wifi_data.release()) {} | 365 wifi_data_(wifi_data.release()), |
| 366 cell_tower_data_(cell_tower_data.release()) {} |
| 311 | 367 |
| 312 SimpleGeolocationRequest::~SimpleGeolocationRequest() { | 368 SimpleGeolocationRequest::~SimpleGeolocationRequest() { |
| 313 DCHECK(thread_checker_.CalledOnValidThread()); | 369 DCHECK(thread_checker_.CalledOnValidThread()); |
| 314 | 370 |
| 315 // If callback is not empty, request is cancelled. | 371 // If callback is not empty, request is cancelled. |
| 316 if (!callback_.is_null()) { | 372 if (!callback_.is_null()) { |
| 317 RecordUmaResponseTime(base::Time::Now() - request_started_at_, false); | 373 RecordUmaResponseTime(base::Time::Now() - request_started_at_, false); |
| 318 RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_); | 374 RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_); |
| 319 } | 375 } |
| 320 | 376 |
| 321 if (g_test_request_hook) | 377 if (g_test_request_hook) |
| 322 g_test_request_hook->OnRequestCreated(this); | 378 g_test_request_hook->OnRequestCreated(this); |
| 323 } | 379 } |
| 324 | 380 |
| 325 std::string SimpleGeolocationRequest::FormatRequestBody() const { | 381 std::string SimpleGeolocationRequest::FormatRequestBody() const { |
| 326 if (!wifi_data_) { | 382 if (!wifi_data_) |
| 327 ReportUmaHasWiFiAccessPoints(false); | 383 ReportUmaHasWiFiAccessPoints(false); |
| 384 |
| 385 if (!cell_tower_data_) |
| 386 ReportUmaHasCellTowers(false); |
| 387 |
| 388 if (!cell_tower_data_ && !wifi_data_) |
| 328 return std::string(kSimpleGeolocationRequestBody); | 389 return std::string(kSimpleGeolocationRequestBody); |
| 329 } | |
| 330 | 390 |
| 331 std::unique_ptr<base::DictionaryValue> request(new base::DictionaryValue); | 391 std::unique_ptr<base::DictionaryValue> request(new base::DictionaryValue); |
| 332 request->SetBooleanWithoutPathExpansion(kConsiderIp, true); | 392 request->SetBooleanWithoutPathExpansion(kConsiderIp, true); |
| 333 | 393 |
| 334 base::ListValue* wifi_access_points(new base::ListValue); | 394 if (wifi_data_) { |
| 335 request->SetWithoutPathExpansion(kWifiAccessPoints, wifi_access_points); | 395 auto wifi_access_points = base::MakeUnique<base::ListValue>(); |
| 396 for (const WifiAccessPoint& access_point : *wifi_data_) { |
| 397 wifi_access_points->Append(CreateAccessPointDictionary(access_point)); |
| 398 } |
| 399 request->SetWithoutPathExpansion(kWifiAccessPoints, |
| 400 std::move(wifi_access_points)); |
| 401 } |
| 336 | 402 |
| 337 for (const WifiAccessPoint& access_point : *wifi_data_) { | 403 if (cell_tower_data_) { |
| 338 auto access_point_dictionary = base::MakeUnique<base::DictionaryValue>(); | 404 auto cell_towers = base::MakeUnique<base::ListValue>(); |
| 405 for (const CellTower& cell_tower : *cell_tower_data_) { |
| 406 cell_towers->Append(CreateCellTowerDictionary(cell_tower)); |
| 407 } |
| 408 request->SetWithoutPathExpansion(kCellTowers, std::move(cell_towers)); |
| 409 } |
| 339 | 410 |
| 340 access_point_dictionary->SetStringWithoutPathExpansion( | |
| 341 kMacAddress, access_point.mac_address); | |
| 342 access_point_dictionary->SetIntegerWithoutPathExpansion( | |
| 343 kSignalStrength, access_point.signal_strength); | |
| 344 if (!access_point.timestamp.is_null()) { | |
| 345 access_point_dictionary->SetStringWithoutPathExpansion( | |
| 346 kAge, | |
| 347 base::Int64ToString( | |
| 348 (base::Time::Now() - access_point.timestamp).InMilliseconds())); | |
| 349 } | |
| 350 | |
| 351 access_point_dictionary->SetIntegerWithoutPathExpansion( | |
| 352 kChannel, access_point.channel); | |
| 353 access_point_dictionary->SetIntegerWithoutPathExpansion( | |
| 354 kSignalToNoiseRatio, access_point.signal_to_noise); | |
| 355 | |
| 356 wifi_access_points->Append(std::move(access_point_dictionary)); | |
| 357 } | |
| 358 std::string result; | 411 std::string result; |
| 359 if (!base::JSONWriter::Write(*request, &result)) { | 412 if (!base::JSONWriter::Write(*request, &result)) { |
| 360 ReportUmaHasWiFiAccessPoints(false); | 413 // If there's no data for a network type, we will have already reported |
| 414 // false above |
| 415 if (wifi_data_) |
| 416 ReportUmaHasWiFiAccessPoints(false); |
| 417 if (cell_tower_data_) |
| 418 ReportUmaHasCellTowers(false); |
| 419 |
| 361 return std::string(kSimpleGeolocationRequestBody); | 420 return std::string(kSimpleGeolocationRequestBody); |
| 362 } | 421 } |
| 363 ReportUmaHasWiFiAccessPoints(wifi_data_->size()); | 422 |
| 423 if (wifi_data_) |
| 424 ReportUmaHasWiFiAccessPoints(wifi_data_->size()); |
| 425 if (cell_tower_data_) |
| 426 ReportUmaHasCellTowers(cell_tower_data_->size()); |
| 364 | 427 |
| 365 return result; | 428 return result; |
| 366 } | 429 } |
| 367 | 430 |
| 368 void SimpleGeolocationRequest::StartRequest() { | 431 void SimpleGeolocationRequest::StartRequest() { |
| 369 DCHECK(thread_checker_.CalledOnValidThread()); | 432 DCHECK(thread_checker_.CalledOnValidThread()); |
| 370 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START); | 433 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START); |
| 371 ++retries_; | 434 ++retries_; |
| 372 | 435 |
| 373 const std::string request_body = FormatRequestBody(); | 436 const std::string request_body = FormatRequestBody(); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 ? SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR | 537 ? SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR |
| 475 : SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE); | 538 : SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE); |
| 476 RecordUmaResult(result, retries_); | 539 RecordUmaResult(result, retries_); |
| 477 position_.status = Geoposition::STATUS_TIMEOUT; | 540 position_.status = Geoposition::STATUS_TIMEOUT; |
| 478 const base::TimeDelta elapsed = base::Time::Now() - request_started_at_; | 541 const base::TimeDelta elapsed = base::Time::Now() - request_started_at_; |
| 479 ReplyAndDestroySelf(elapsed, true /* server_error */); | 542 ReplyAndDestroySelf(elapsed, true /* server_error */); |
| 480 // "this" is already destroyed here. | 543 // "this" is already destroyed here. |
| 481 } | 544 } |
| 482 | 545 |
| 483 } // namespace chromeos | 546 } // namespace chromeos |
| OLD | NEW |