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

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

Issue 1819173002: SimpleGeolocation should support sending WiFi AP data. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update after review. Created 4 years, 9 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>
11 11
12 #include "base/json/json_reader.h" 12 #include "base/json/json_reader.h"
13 #include "base/json/json_writer.h"
13 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
14 #include "base/metrics/sparse_histogram.h" 15 #include "base/metrics/sparse_histogram.h"
15 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
17 #include "base/time/time.h" 18 #include "base/time/time.h"
18 #include "base/values.h" 19 #include "base/values.h"
19 #include "chromeos/geolocation/simple_geolocation_provider.h" 20 #include "chromeos/geolocation/simple_geolocation_provider.h"
21 #include "chromeos/geolocation/simple_geolocation_request_test_monitor.h"
20 #include "google_apis/google_api_keys.h" 22 #include "google_apis/google_api_keys.h"
21 #include "net/base/escape.h" 23 #include "net/base/escape.h"
22 #include "net/base/load_flags.h" 24 #include "net/base/load_flags.h"
23 #include "net/http/http_status_code.h" 25 #include "net/http/http_status_code.h"
24 #include "net/url_request/url_request_context_getter.h" 26 #include "net/url_request/url_request_context_getter.h"
25 #include "net/url_request/url_request_status.h" 27 #include "net/url_request/url_request_status.h"
26 28
27 // Location resolve timeout is usually 1 minute, so 2 minutes with 50 buckets 29 // Location resolve timeout is usually 1 minute, so 2 minutes with 50 buckets
28 // should be enough. 30 // should be enough.
29 #define UMA_HISTOGRAM_LOCATION_RESPONSE_TIMES(name, sample) \ 31 #define UMA_HISTOGRAM_LOCATION_RESPONSE_TIMES(name, sample) \
30 UMA_HISTOGRAM_CUSTOM_TIMES(name, \ 32 UMA_HISTOGRAM_CUSTOM_TIMES(name, \
31 sample, \ 33 sample, \
32 base::TimeDelta::FromMilliseconds(10), \ 34 base::TimeDelta::FromMilliseconds(10), \
33 base::TimeDelta::FromMinutes(2), \ 35 base::TimeDelta::FromMinutes(2), \
34 50) 36 50)
35 37
36 namespace chromeos { 38 namespace chromeos {
37 39
38 namespace { 40 namespace {
39 41
40 // The full request text. (no parameters are supported by now) 42 // The full request text. (no parameters are supported by now)
41 const char kSimpleGeolocationRequestBody[] = "{\"considerIP\": \"true\"}"; 43 const char kSimpleGeolocationRequestBody[] = "{\"considerIp\": \"true\"}";
44
45 // Request data
46 const char kConsiderIp[] = "considerIp";
47 const char kWifiAccessPoints[] = "wifiAccessPoints";
48
49 // WiFi access point objects.
50 const char kMacAddress[] = "macAddress";
51 const char kSignalStrength[] = "signalStrength";
52 const char kAge[] = "age";
53 const char kChannel[] = "channel";
54 const char kSignalToNoiseRatio[] = "signalToNoiseRatio";
42 55
43 // Response data. 56 // Response data.
44 const char kLocationString[] = "location"; 57 const char kLocationString[] = "location";
45 const char kLatString[] = "lat"; 58 const char kLatString[] = "lat";
46 const char kLngString[] = "lng"; 59 const char kLngString[] = "lng";
47 const char kAccuracyString[] = "accuracy"; 60 const char kAccuracyString[] = "accuracy";
48 // Error object and its contents. 61 // Error object and its contents.
49 const char kErrorString[] = "error"; 62 const char kErrorString[] = "error";
50 // "errors" array in "erorr" object is ignored. 63 // "errors" array in "erorr" object is ignored.
51 const char kCodeString[] = "code"; 64 const char kCodeString[] = "code";
(...skipping 29 matching lines...) Expand all
81 // in tools/metrics/histograms/histograms.xml to keep it in sync. 94 // in tools/metrics/histograms/histograms.xml to keep it in sync.
82 SIMPLE_GEOLOCATION_REQUEST_RESULT_SUCCESS = 0, 95 SIMPLE_GEOLOCATION_REQUEST_RESULT_SUCCESS = 0,
83 SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE = 1, 96 SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE = 1,
84 SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR = 2, 97 SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR = 2,
85 SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED = 3, 98 SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED = 3,
86 99
87 // NOTE: Add entries only immediately above this line. 100 // NOTE: Add entries only immediately above this line.
88 SIMPLE_GEOLOCATION_REQUEST_RESULT_COUNT = 4 101 SIMPLE_GEOLOCATION_REQUEST_RESULT_COUNT = 4
89 }; 102 };
90 103
104 SimpleGeolocationRequestTestMonitor* g_test_request_hook = nullptr;
105
91 // Too many requests (more than 1) mean there is a problem in implementation. 106 // Too many requests (more than 1) mean there is a problem in implementation.
92 void RecordUmaEvent(SimpleGeolocationRequestEvent event) { 107 void RecordUmaEvent(SimpleGeolocationRequestEvent event) {
93 UMA_HISTOGRAM_ENUMERATION("SimpleGeolocation.Request.Event", 108 UMA_HISTOGRAM_ENUMERATION("SimpleGeolocation.Request.Event",
94 event, 109 event,
95 SIMPLE_GEOLOCATION_REQUEST_EVENT_COUNT); 110 SIMPLE_GEOLOCATION_REQUEST_EVENT_COUNT);
96 } 111 }
97 112
98 void RecordUmaResponseCode(int code) { 113 void RecordUmaResponseCode(int code) {
99 UMA_HISTOGRAM_SPARSE_SLOWLY("SimpleGeolocation.Request.ResponseCode", code); 114 UMA_HISTOGRAM_SPARSE_SLOWLY("SimpleGeolocation.Request.ResponseCode", code);
100 } 115 }
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 return true; 255 return true;
241 } 256 }
242 257
243 // Attempts to extract a position from the response. Detects and indicates 258 // Attempts to extract a position from the response. Detects and indicates
244 // various failure cases. 259 // various failure cases.
245 bool GetGeolocationFromResponse(bool http_success, 260 bool GetGeolocationFromResponse(bool http_success,
246 int status_code, 261 int status_code,
247 const std::string& response_body, 262 const std::string& response_body,
248 const GURL& server_url, 263 const GURL& server_url,
249 Geoposition* position) { 264 Geoposition* position) {
265 VLOG(1) << "GetGeolocationFromResponse(http_success=" << http_success
266 << ", status_code=" << status_code << "): response_body:\n"
267 << response_body;
250 268
251 // HttpPost can fail for a number of reasons. Most likely this is because 269 // HttpPost can fail for a number of reasons. Most likely this is because
252 // we're offline, or there was no response. 270 // we're offline, or there was no response.
253 if (!http_success) { 271 if (!http_success) {
254 PrintGeolocationError(server_url, "No response received", position); 272 PrintGeolocationError(server_url, "No response received", position);
255 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_EMPTY); 273 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_EMPTY);
256 return false; 274 return false;
257 } 275 }
258 if (status_code != net::HTTP_OK) { 276 if (status_code != net::HTTP_OK) {
259 std::string message = "Returned error code "; 277 std::string message = "Returned error code ";
260 message += base::IntToString(status_code); 278 message += base::IntToString(status_code);
261 PrintGeolocationError(server_url, message, position); 279 PrintGeolocationError(server_url, message, position);
262 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_NOT_OK); 280 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_NOT_OK);
263 return false; 281 return false;
264 } 282 }
265 283
266 return ParseServerResponse(server_url, response_body, position); 284 return ParseServerResponse(server_url, response_body, position);
267 } 285 }
268 286
287 void ReportUmaHasWiFiAccessPoints(bool value) {
288 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints", value);
289 }
290
269 } // namespace 291 } // namespace
270 292
271 SimpleGeolocationRequest::SimpleGeolocationRequest( 293 SimpleGeolocationRequest::SimpleGeolocationRequest(
272 net::URLRequestContextGetter* url_context_getter, 294 net::URLRequestContextGetter* url_context_getter,
273 const GURL& service_url, 295 const GURL& service_url,
274 base::TimeDelta timeout) 296 base::TimeDelta timeout,
297 scoped_ptr<WifiAccessPointVector> wifi_data)
275 : url_context_getter_(url_context_getter), 298 : url_context_getter_(url_context_getter),
276 service_url_(service_url), 299 service_url_(service_url),
277 retry_sleep_on_server_error_(base::TimeDelta::FromSeconds( 300 retry_sleep_on_server_error_(base::TimeDelta::FromSeconds(
278 kResolveGeolocationRetrySleepOnServerErrorSeconds)), 301 kResolveGeolocationRetrySleepOnServerErrorSeconds)),
279 retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds( 302 retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds(
280 kResolveGeolocationRetrySleepBadResponseSeconds)), 303 kResolveGeolocationRetrySleepBadResponseSeconds)),
281 timeout_(timeout), 304 timeout_(timeout),
282 retries_(0) { 305 retries_(0),
283 } 306 wifi_data_(wifi_data.release()) {}
284 307
285 SimpleGeolocationRequest::~SimpleGeolocationRequest() { 308 SimpleGeolocationRequest::~SimpleGeolocationRequest() {
286 DCHECK(thread_checker_.CalledOnValidThread()); 309 DCHECK(thread_checker_.CalledOnValidThread());
287 310
288 // If callback is not empty, request is cancelled. 311 // If callback is not empty, request is cancelled.
289 if (!callback_.is_null()) { 312 if (!callback_.is_null()) {
290 RecordUmaResponseTime(base::Time::Now() - request_started_at_, false); 313 RecordUmaResponseTime(base::Time::Now() - request_started_at_, false);
291 RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_); 314 RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_);
292 } 315 }
316
317 if (g_test_request_hook)
318 g_test_request_hook->OnRequestCreated(this);
319 }
320
321 std::string SimpleGeolocationRequest::FormatRequestBody() const {
322 if (!wifi_data_) {
323 ReportUmaHasWiFiAccessPoints(false);
324 return std::string(kSimpleGeolocationRequestBody);
325 }
326
327 scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue);
328 request->SetBooleanWithoutPathExpansion(kConsiderIp, true);
329
330 base::ListValue* wifi_access_points(new base::ListValue);
331 request->SetWithoutPathExpansion(kWifiAccessPoints, wifi_access_points);
332
333 for (const WifiAccessPoint& access_point : *wifi_data_) {
334 base::DictionaryValue* access_point_dictionary = new base::DictionaryValue;
335 wifi_access_points->Append(access_point_dictionary);
336
337 access_point_dictionary->SetStringWithoutPathExpansion(
338 kMacAddress, access_point.mac_address);
339 access_point_dictionary->SetIntegerWithoutPathExpansion(
340 kSignalStrength, access_point.signal_strength);
341 if (!access_point.timestamp.is_null()) {
342 access_point_dictionary->SetStringWithoutPathExpansion(
343 kAge,
344 base::Int64ToString(
345 (base::Time::Now() - access_point.timestamp).InMilliseconds()));
346 }
347
348 access_point_dictionary->SetIntegerWithoutPathExpansion(
349 kChannel, access_point.channel);
350 access_point_dictionary->SetIntegerWithoutPathExpansion(
351 kSignalToNoiseRatio, access_point.signal_to_noise);
352 }
353 std::string result;
354 if (!base::JSONWriter::Write(*request, &result)) {
355 ReportUmaHasWiFiAccessPoints(false);
356 return std::string(kSimpleGeolocationRequestBody);
357 }
358 ReportUmaHasWiFiAccessPoints(wifi_data_->size());
359
360 return result;
293 } 361 }
294 362
295 void SimpleGeolocationRequest::StartRequest() { 363 void SimpleGeolocationRequest::StartRequest() {
296 DCHECK(thread_checker_.CalledOnValidThread()); 364 DCHECK(thread_checker_.CalledOnValidThread());
297 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START); 365 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START);
298 ++retries_; 366 ++retries_;
299 367
368 const std::string request_body = FormatRequestBody();
369 VLOG(1) << "SimpleGeolocationRequest::StartRequest(): request body:\n"
370 << request_body;
371
300 url_fetcher_ = 372 url_fetcher_ =
301 net::URLFetcher::Create(request_url_, net::URLFetcher::POST, this); 373 net::URLFetcher::Create(request_url_, net::URLFetcher::POST, this);
302 url_fetcher_->SetRequestContext(url_context_getter_.get()); 374 url_fetcher_->SetRequestContext(url_context_getter_.get());
303 url_fetcher_->SetUploadData("application/json", 375 url_fetcher_->SetUploadData("application/json", request_body);
304 std::string(kSimpleGeolocationRequestBody));
305 url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | 376 url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE |
306 net::LOAD_DISABLE_CACHE | 377 net::LOAD_DISABLE_CACHE |
307 net::LOAD_DO_NOT_SAVE_COOKIES | 378 net::LOAD_DO_NOT_SAVE_COOKIES |
308 net::LOAD_DO_NOT_SEND_COOKIES | 379 net::LOAD_DO_NOT_SEND_COOKIES |
309 net::LOAD_DO_NOT_SEND_AUTH_DATA); 380 net::LOAD_DO_NOT_SEND_AUTH_DATA);
381
382 // Call test hook before asynchronous request actually starts.
383 if (g_test_request_hook)
384 g_test_request_hook->OnStart(this);
385
310 url_fetcher_->Start(); 386 url_fetcher_->Start();
311 } 387 }
312 388
313 void SimpleGeolocationRequest::MakeRequest(const ResponseCallback& callback) { 389 void SimpleGeolocationRequest::MakeRequest(const ResponseCallback& callback) {
314 callback_ = callback; 390 callback_ = callback;
315 request_url_ = GeolocationRequestURL(service_url_); 391 request_url_ = GeolocationRequestURL(service_url_);
316 timeout_timer_.Start( 392 timeout_timer_.Start(
317 FROM_HERE, timeout_, this, &SimpleGeolocationRequest::OnTimeout); 393 FROM_HERE, timeout_, this, &SimpleGeolocationRequest::OnTimeout);
318 request_started_at_ = base::Time::Now(); 394 request_started_at_ = base::Time::Now();
319 StartRequest(); 395 StartRequest();
320 } 396 }
321 397
398 // static
399 void SimpleGeolocationRequest::SetTestMonitor(
400 SimpleGeolocationRequestTestMonitor* monitor) {
401 g_test_request_hook = monitor;
402 }
403
404 std::string SimpleGeolocationRequest::FormatRequestBodyForTesting() const {
405 return FormatRequestBody();
406 }
407
322 void SimpleGeolocationRequest::Retry(bool server_error) { 408 void SimpleGeolocationRequest::Retry(bool server_error) {
323 base::TimeDelta delay(server_error ? retry_sleep_on_server_error_ 409 base::TimeDelta delay(server_error ? retry_sleep_on_server_error_
324 : retry_sleep_on_bad_response_); 410 : retry_sleep_on_bad_response_);
325 request_scheduled_.Start( 411 request_scheduled_.Start(
326 FROM_HERE, delay, this, &SimpleGeolocationRequest::StartRequest); 412 FROM_HERE, delay, this, &SimpleGeolocationRequest::StartRequest);
327 } 413 }
328 414
329 void SimpleGeolocationRequest::OnURLFetchComplete( 415 void SimpleGeolocationRequest::OnURLFetchComplete(
330 const net::URLFetcher* source) { 416 const net::URLFetcher* source) {
331 DCHECK_EQ(url_fetcher_.get(), source); 417 DCHECK_EQ(url_fetcher_.get(), source);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 ? SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR 469 ? SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR
384 : SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE); 470 : SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE);
385 RecordUmaResult(result, retries_); 471 RecordUmaResult(result, retries_);
386 position_.status = Geoposition::STATUS_TIMEOUT; 472 position_.status = Geoposition::STATUS_TIMEOUT;
387 const base::TimeDelta elapsed = base::Time::Now() - request_started_at_; 473 const base::TimeDelta elapsed = base::Time::Now() - request_started_at_;
388 ReplyAndDestroySelf(elapsed, true /* server_error */); 474 ReplyAndDestroySelf(elapsed, true /* server_error */);
389 // "this" is already destroyed here. 475 // "this" is already destroyed here.
390 } 476 }
391 477
392 } // namespace chromeos 478 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/geolocation/simple_geolocation_request.h ('k') | chromeos/geolocation/simple_geolocation_request_test_monitor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698