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

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
269 } // namespace 287 } // namespace
270 288
271 SimpleGeolocationRequest::SimpleGeolocationRequest( 289 SimpleGeolocationRequest::SimpleGeolocationRequest(
272 net::URLRequestContextGetter* url_context_getter, 290 net::URLRequestContextGetter* url_context_getter,
273 const GURL& service_url, 291 const GURL& service_url,
274 base::TimeDelta timeout) 292 base::TimeDelta timeout,
293 scoped_ptr<WifiAccessPointVector> wifi_data)
275 : url_context_getter_(url_context_getter), 294 : url_context_getter_(url_context_getter),
276 service_url_(service_url), 295 service_url_(service_url),
277 retry_sleep_on_server_error_(base::TimeDelta::FromSeconds( 296 retry_sleep_on_server_error_(base::TimeDelta::FromSeconds(
278 kResolveGeolocationRetrySleepOnServerErrorSeconds)), 297 kResolveGeolocationRetrySleepOnServerErrorSeconds)),
279 retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds( 298 retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds(
280 kResolveGeolocationRetrySleepBadResponseSeconds)), 299 kResolveGeolocationRetrySleepBadResponseSeconds)),
281 timeout_(timeout), 300 timeout_(timeout),
282 retries_(0) { 301 retries_(0),
283 } 302 wifi_data_(wifi_data.release()) {}
284 303
285 SimpleGeolocationRequest::~SimpleGeolocationRequest() { 304 SimpleGeolocationRequest::~SimpleGeolocationRequest() {
286 DCHECK(thread_checker_.CalledOnValidThread()); 305 DCHECK(thread_checker_.CalledOnValidThread());
287 306
288 // If callback is not empty, request is cancelled. 307 // If callback is not empty, request is cancelled.
289 if (!callback_.is_null()) { 308 if (!callback_.is_null()) {
290 RecordUmaResponseTime(base::Time::Now() - request_started_at_, false); 309 RecordUmaResponseTime(base::Time::Now() - request_started_at_, false);
291 RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_); 310 RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_);
292 } 311 }
312
313 if (g_test_request_hook)
314 g_test_request_hook->OnRequestCreated(this);
315 }
316
317 std::string SimpleGeolocationRequest::FormatRequestBody() const {
318 if (!wifi_data_) {
319 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints",
Steven Holte 2016/03/23 18:41:46 It would be better to wrap a function call around
Alexander Alekseev 2016/03/23 22:08:23 Done.
320 false);
321 return std::string(kSimpleGeolocationRequestBody);
322 }
323
324 scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue);
325 request->SetBooleanWithoutPathExpansion(kConsiderIp, true);
326
327 base::ListValue* wifi_access_points(new base::ListValue);
328 request->SetWithoutPathExpansion(kWifiAccessPoints, wifi_access_points);
329
330 for (const WifiAccessPoint& access_point : *wifi_data_) {
331 base::DictionaryValue* access_point_dictionary = new base::DictionaryValue;
332 wifi_access_points->Append(access_point_dictionary);
333
334 access_point_dictionary->SetStringWithoutPathExpansion(
335 kMacAddress, access_point.mac_address);
336 access_point_dictionary->SetIntegerWithoutPathExpansion(
337 kSignalStrength, access_point.signal_strength);
338 if (!access_point.timestamp.is_null()) {
339 access_point_dictionary->SetStringWithoutPathExpansion(
340 kAge,
341 base::Int64ToString(
342 (base::Time::Now() - access_point.timestamp).InMilliseconds()));
343 }
344
345 access_point_dictionary->SetIntegerWithoutPathExpansion(
346 kChannel, access_point.channel);
347 access_point_dictionary->SetIntegerWithoutPathExpansion(
348 kSignalToNoiseRatio, access_point.signal_to_noise);
349 }
350 std::string result;
351 if (!base::JSONWriter::Write(*request, &result)) {
352 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints",
353 false);
354 return std::string(kSimpleGeolocationRequestBody);
355 }
356 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints",
357 wifi_data_->size());
358
359 return result;
293 } 360 }
294 361
295 void SimpleGeolocationRequest::StartRequest() { 362 void SimpleGeolocationRequest::StartRequest() {
296 DCHECK(thread_checker_.CalledOnValidThread()); 363 DCHECK(thread_checker_.CalledOnValidThread());
297 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START); 364 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START);
298 ++retries_; 365 ++retries_;
299 366
367 const std::string request_body = FormatRequestBody();
368 VLOG(1) << "SimpleGeolocationRequest::StartRequest(): request body:\n"
369 << request_body;
370
300 url_fetcher_ = 371 url_fetcher_ =
301 net::URLFetcher::Create(request_url_, net::URLFetcher::POST, this); 372 net::URLFetcher::Create(request_url_, net::URLFetcher::POST, this);
302 url_fetcher_->SetRequestContext(url_context_getter_.get()); 373 url_fetcher_->SetRequestContext(url_context_getter_.get());
303 url_fetcher_->SetUploadData("application/json", 374 url_fetcher_->SetUploadData("application/json", request_body);
304 std::string(kSimpleGeolocationRequestBody));
305 url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | 375 url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE |
306 net::LOAD_DISABLE_CACHE | 376 net::LOAD_DISABLE_CACHE |
307 net::LOAD_DO_NOT_SAVE_COOKIES | 377 net::LOAD_DO_NOT_SAVE_COOKIES |
308 net::LOAD_DO_NOT_SEND_COOKIES | 378 net::LOAD_DO_NOT_SEND_COOKIES |
309 net::LOAD_DO_NOT_SEND_AUTH_DATA); 379 net::LOAD_DO_NOT_SEND_AUTH_DATA);
380
381 // Call test hook before asynchronous request actually starts.
382 if (g_test_request_hook)
383 g_test_request_hook->OnStart(this);
384
310 url_fetcher_->Start(); 385 url_fetcher_->Start();
311 } 386 }
312 387
313 void SimpleGeolocationRequest::MakeRequest(const ResponseCallback& callback) { 388 void SimpleGeolocationRequest::MakeRequest(const ResponseCallback& callback) {
314 callback_ = callback; 389 callback_ = callback;
315 request_url_ = GeolocationRequestURL(service_url_); 390 request_url_ = GeolocationRequestURL(service_url_);
316 timeout_timer_.Start( 391 timeout_timer_.Start(
317 FROM_HERE, timeout_, this, &SimpleGeolocationRequest::OnTimeout); 392 FROM_HERE, timeout_, this, &SimpleGeolocationRequest::OnTimeout);
318 request_started_at_ = base::Time::Now(); 393 request_started_at_ = base::Time::Now();
319 StartRequest(); 394 StartRequest();
320 } 395 }
321 396
397 // static
398 void SimpleGeolocationRequest::SetTestMonitor(
399 SimpleGeolocationRequestTestMonitor* monitor) {
400 g_test_request_hook = monitor;
401 }
402
403 std::string SimpleGeolocationRequest::FormatRequestBodyForTesting() const {
404 return FormatRequestBody();
405 }
406
322 void SimpleGeolocationRequest::Retry(bool server_error) { 407 void SimpleGeolocationRequest::Retry(bool server_error) {
323 base::TimeDelta delay(server_error ? retry_sleep_on_server_error_ 408 base::TimeDelta delay(server_error ? retry_sleep_on_server_error_
324 : retry_sleep_on_bad_response_); 409 : retry_sleep_on_bad_response_);
325 request_scheduled_.Start( 410 request_scheduled_.Start(
326 FROM_HERE, delay, this, &SimpleGeolocationRequest::StartRequest); 411 FROM_HERE, delay, this, &SimpleGeolocationRequest::StartRequest);
327 } 412 }
328 413
329 void SimpleGeolocationRequest::OnURLFetchComplete( 414 void SimpleGeolocationRequest::OnURLFetchComplete(
330 const net::URLFetcher* source) { 415 const net::URLFetcher* source) {
331 DCHECK_EQ(url_fetcher_.get(), source); 416 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 468 ? SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR
384 : SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE); 469 : SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE);
385 RecordUmaResult(result, retries_); 470 RecordUmaResult(result, retries_);
386 position_.status = Geoposition::STATUS_TIMEOUT; 471 position_.status = Geoposition::STATUS_TIMEOUT;
387 const base::TimeDelta elapsed = base::Time::Now() - request_started_at_; 472 const base::TimeDelta elapsed = base::Time::Now() - request_started_at_;
388 ReplyAndDestroySelf(elapsed, true /* server_error */); 473 ReplyAndDestroySelf(elapsed, true /* server_error */);
389 // "this" is already destroyed here. 474 // "this" is already destroyed here.
390 } 475 }
391 476
392 } // namespace chromeos 477 } // 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