Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(563)

Side by Side Diff: chromeos/geolocation/simple_geolocation_request.cc

Issue 2624843003: Add support for cellular geolocation (Closed)
Patch Set: address comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 24 matching lines...) Expand all
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 // The full request text. (no parameters are supported by now)
45 const char kSimpleGeolocationRequestBody[] = "{\"considerIp\": \"true\"}"; 45 constexpr char kSimpleGeolocationRequestBody[] = "{\"considerIp\": \"true\"}";
46 46
47 // Request data 47 // TODO(skylarc): kill these and use dbus-constants instead?
Alexander Alekseev 2017/02/06 23:24:53 I think that dbus-constants could be used for DBUS
can Skylar cook 2017/02/07 21:32:39 Good point -- they're technically *not* dbus const
stevenjb 2017/02/07 21:39:38 I agree that dbus-constants should be used for key
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
53 // Shared Wifi and Cell Tower objects
54 constexpr char kAge[] = "age";
55 constexpr char kSignalStrength[] = "signalStrength";
50 56
51 // WiFi access point objects. 57 // WiFi access point objects.
52 const char kMacAddress[] = "macAddress"; 58 constexpr char kMacAddress[] = "macAddress";
53 const char kSignalStrength[] = "signalStrength"; 59 constexpr char kChannel[] = "channel";
54 const char kAge[] = "age"; 60 constexpr char kSignalToNoiseRatio[] = "signalToNoiseRatio";
55 const char kChannel[] = "channel"; 61
56 const char kSignalToNoiseRatio[] = "signalToNoiseRatio"; 62 // Cell tower objects
63 constexpr char kCellId[] = "cellId";
64 constexpr char kLocationAreaCode[] = "locationAreaCode";
65 constexpr char kMobileCountryCode[] = "mobileCountryCode";
66 constexpr char kMobileNetworkCode[] = "mobileNetworkCode";
57 67
58 // Response data. 68 // Response data.
59 const char kLocationString[] = "location"; 69 constexpr char kLocationString[] = "location";
60 const char kLatString[] = "lat"; 70 constexpr char kLatString[] = "lat";
61 const char kLngString[] = "lng"; 71 constexpr char kLngString[] = "lng";
62 const char kAccuracyString[] = "accuracy"; 72 constexpr char kAccuracyString[] = "accuracy";
63 // Error object and its contents. 73 // Error object and its contents.
64 const char kErrorString[] = "error"; 74 constexpr char kErrorString[] = "error";
65 // "errors" array in "erorr" object is ignored. 75 // "errors" array in "erorr" object is ignored.
66 const char kCodeString[] = "code"; 76 constexpr char kCodeString[] = "code";
67 const char kMessageString[] = "message"; 77 constexpr char kMessageString[] = "message";
68 78
69 // We are using "sparse" histograms for the number of retry attempts, 79 // 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). 80 // so we need to explicitly limit maximum value (in case something goes wrong).
71 const size_t kMaxRetriesValueInHistograms = 20; 81 const size_t kMaxRetriesValueInHistograms = 20;
72 82
73 // Sleep between geolocation request retry on HTTP error. 83 // Sleep between geolocation request retry on HTTP error.
74 const unsigned int kResolveGeolocationRetrySleepOnServerErrorSeconds = 5; 84 const unsigned int kResolveGeolocationRetrySleepOnServerErrorSeconds = 5;
75 85
76 // Sleep between geolocation request retry on bad server response. 86 // Sleep between geolocation request retry on bad server response.
77 const unsigned int kResolveGeolocationRetrySleepBadResponseSeconds = 10; 87 const unsigned int kResolveGeolocationRetrySleepBadResponseSeconds = 10;
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_NOT_OK); 294 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_NOT_OK);
285 return false; 295 return false;
286 } 296 }
287 297
288 return ParseServerResponse(server_url, response_body, position); 298 return ParseServerResponse(server_url, response_body, position);
289 } 299 }
290 300
291 void ReportUmaHasWiFiAccessPoints(bool value) { 301 void ReportUmaHasWiFiAccessPoints(bool value) {
292 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints", value); 302 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints", value);
293 } 303 }
304 void ReportUmaHasCellTowers(bool value) {
305 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasCellTowers", value);
306 }
294 307
295 } // namespace 308 } // namespace
296 309
297 SimpleGeolocationRequest::SimpleGeolocationRequest( 310 SimpleGeolocationRequest::SimpleGeolocationRequest(
298 net::URLRequestContextGetter* url_context_getter, 311 net::URLRequestContextGetter* url_context_getter,
299 const GURL& service_url, 312 const GURL& service_url,
300 base::TimeDelta timeout, 313 base::TimeDelta timeout,
301 std::unique_ptr<WifiAccessPointVector> wifi_data) 314 std::unique_ptr<WifiAccessPointVector> wifi_data,
315 std::unique_ptr<CellTowerVector> cell_tower_data)
302 : url_context_getter_(url_context_getter), 316 : url_context_getter_(url_context_getter),
303 service_url_(service_url), 317 service_url_(service_url),
304 retry_sleep_on_server_error_(base::TimeDelta::FromSeconds( 318 retry_sleep_on_server_error_(base::TimeDelta::FromSeconds(
305 kResolveGeolocationRetrySleepOnServerErrorSeconds)), 319 kResolveGeolocationRetrySleepOnServerErrorSeconds)),
306 retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds( 320 retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds(
307 kResolveGeolocationRetrySleepBadResponseSeconds)), 321 kResolveGeolocationRetrySleepBadResponseSeconds)),
308 timeout_(timeout), 322 timeout_(timeout),
309 retries_(0), 323 retries_(0),
310 wifi_data_(wifi_data.release()) {} 324 wifi_data_(wifi_data.release()),
325 cell_tower_data_(cell_tower_data.release()) {}
311 326
312 SimpleGeolocationRequest::~SimpleGeolocationRequest() { 327 SimpleGeolocationRequest::~SimpleGeolocationRequest() {
313 DCHECK(thread_checker_.CalledOnValidThread()); 328 DCHECK(thread_checker_.CalledOnValidThread());
314 329
315 // If callback is not empty, request is cancelled. 330 // If callback is not empty, request is cancelled.
316 if (!callback_.is_null()) { 331 if (!callback_.is_null()) {
317 RecordUmaResponseTime(base::Time::Now() - request_started_at_, false); 332 RecordUmaResponseTime(base::Time::Now() - request_started_at_, false);
318 RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_); 333 RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_);
319 } 334 }
320 335
321 if (g_test_request_hook) 336 if (g_test_request_hook)
322 g_test_request_hook->OnRequestCreated(this); 337 g_test_request_hook->OnRequestCreated(this);
323 } 338 }
324 339
325 std::string SimpleGeolocationRequest::FormatRequestBody() const { 340 std::string SimpleGeolocationRequest::FormatRequestBody() const {
326 if (!wifi_data_) { 341 if (!wifi_data_)
327 ReportUmaHasWiFiAccessPoints(false); 342 ReportUmaHasWiFiAccessPoints(false);
343
344 if (!cell_tower_data_)
345 ReportUmaHasCellTowers(false);
346
347 if (!cell_tower_data_ && !wifi_data_)
328 return std::string(kSimpleGeolocationRequestBody); 348 return std::string(kSimpleGeolocationRequestBody);
329 }
330 349
331 std::unique_ptr<base::DictionaryValue> request(new base::DictionaryValue); 350 std::unique_ptr<base::DictionaryValue> request(new base::DictionaryValue);
332 request->SetBooleanWithoutPathExpansion(kConsiderIp, true); 351 request->SetBooleanWithoutPathExpansion(kConsiderIp, true);
333 352
334 base::ListValue* wifi_access_points(new base::ListValue); 353 if (wifi_data_) {
335 request->SetWithoutPathExpansion(kWifiAccessPoints, wifi_access_points); 354 auto wifi_access_points = base::MakeUnique<base::ListValue>();
355 for (const WifiAccessPoint& access_point : *wifi_data_) {
356 wifi_access_points->Append(CreateAccessPointDictionary(access_point));
357 }
358 request->SetWithoutPathExpansion(kWifiAccessPoints,
359 std::move(wifi_access_points));
360 }
336 361
337 for (const WifiAccessPoint& access_point : *wifi_data_) { 362 if (cell_tower_data_) {
338 auto access_point_dictionary = base::MakeUnique<base::DictionaryValue>(); 363 auto cell_towers = base::MakeUnique<base::ListValue>();
364 for (const CellTower& cell_tower : *cell_tower_data_) {
365 cell_towers->Append(CreateCellTowerDictionary(cell_tower));
366 }
367 request->SetWithoutPathExpansion(kCellTowers, std::move(cell_towers));
368 }
339 369
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; 370 std::string result;
359 if (!base::JSONWriter::Write(*request, &result)) { 371 if (!base::JSONWriter::Write(*request, &result)) {
360 ReportUmaHasWiFiAccessPoints(false); 372 // If there's no data for a network type, we will have already reported
373 // false above
374 if (wifi_data_)
375 ReportUmaHasWiFiAccessPoints(false);
376 if (cell_tower_data_)
377 ReportUmaHasCellTowers(false);
378
361 return std::string(kSimpleGeolocationRequestBody); 379 return std::string(kSimpleGeolocationRequestBody);
362 } 380 }
363 ReportUmaHasWiFiAccessPoints(wifi_data_->size()); 381
382 if (wifi_data_)
383 ReportUmaHasWiFiAccessPoints(wifi_data_->size());
384 if (cell_tower_data_)
385 ReportUmaHasCellTowers(cell_tower_data_->size());
364 386
365 return result; 387 return result;
366 } 388 }
367 389
390 std::unique_ptr<base::DictionaryValue>
391 SimpleGeolocationRequest::CreateAccessPointDictionary(
392 WifiAccessPoint access_point) const {
393 auto access_point_dictionary = base::MakeUnique<base::DictionaryValue>();
394
395 access_point_dictionary->SetStringWithoutPathExpansion(
396 kMacAddress, access_point.mac_address);
397 access_point_dictionary->SetIntegerWithoutPathExpansion(
398 kSignalStrength, access_point.signal_strength);
399 if (!access_point.timestamp.is_null()) {
400 access_point_dictionary->SetStringWithoutPathExpansion(
401 kAge,
402 base::Int64ToString(
403 (base::Time::Now() - access_point.timestamp).InMilliseconds()));
404 }
405
406 access_point_dictionary->SetIntegerWithoutPathExpansion(kChannel,
407 access_point.channel);
408 access_point_dictionary->SetIntegerWithoutPathExpansion(
409 kSignalToNoiseRatio, access_point.signal_to_noise);
410
411 return access_point_dictionary;
412 }
413
414 std::unique_ptr<base::DictionaryValue>
415 SimpleGeolocationRequest::CreateCellTowerDictionary(
416 CellTower cell_tower) const {
417 auto cell_tower_dictionary = base::MakeUnique<base::DictionaryValue>();
418 cell_tower_dictionary->SetStringWithoutPathExpansion(kCellId, cell_tower.ci);
419 cell_tower_dictionary->SetStringWithoutPathExpansion(kLocationAreaCode,
420 cell_tower.lac);
421 cell_tower_dictionary->SetStringWithoutPathExpansion(kMobileCountryCode,
422 cell_tower.mcc);
423 cell_tower_dictionary->SetStringWithoutPathExpansion(kMobileNetworkCode,
424 cell_tower.mnc);
425
426 if (!cell_tower.timestamp.is_null()) {
427 cell_tower_dictionary->SetStringWithoutPathExpansion(
428 kAge, base::Int64ToString(
429 (base::Time::Now() - cell_tower.timestamp).InMilliseconds()));
430 }
431 return cell_tower_dictionary;
432 }
433
368 void SimpleGeolocationRequest::StartRequest() { 434 void SimpleGeolocationRequest::StartRequest() {
369 DCHECK(thread_checker_.CalledOnValidThread()); 435 DCHECK(thread_checker_.CalledOnValidThread());
370 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START); 436 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START);
371 ++retries_; 437 ++retries_;
372 438
373 const std::string request_body = FormatRequestBody(); 439 const std::string request_body = FormatRequestBody();
374 VLOG(1) << "SimpleGeolocationRequest::StartRequest(): request body:\n" 440 VLOG(1) << "SimpleGeolocationRequest::StartRequest(): request body:\n"
375 << request_body; 441 << request_body;
376 442
377 url_fetcher_ = 443 url_fetcher_ =
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 ? SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR 540 ? SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR
475 : SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE); 541 : SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE);
476 RecordUmaResult(result, retries_); 542 RecordUmaResult(result, retries_);
477 position_.status = Geoposition::STATUS_TIMEOUT; 543 position_.status = Geoposition::STATUS_TIMEOUT;
478 const base::TimeDelta elapsed = base::Time::Now() - request_started_at_; 544 const base::TimeDelta elapsed = base::Time::Now() - request_started_at_;
479 ReplyAndDestroySelf(elapsed, true /* server_error */); 545 ReplyAndDestroySelf(elapsed, true /* server_error */);
480 // "this" is already destroyed here. 546 // "this" is already destroyed here.
481 } 547 }
482 548
483 } // namespace chromeos 549 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698