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

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: UMA added. 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\"}";
42 44
45 // Request data
46 // const char kHomeMobileCountryCode[] = "homeMobileCountryCode";
47 // const char kHomeMobileNetworkCode[] = "homeMobileNetworkCode";
48 // const char kRadioType[] = "radioType";
49 // const char kCarrier[] = "carrier";
stevenjb 2016/03/22 16:39:49 Remove?
Alexander Alekseev 2016/03/23 00:04:45 Done.
50 const char kConsiderIp[] = "considerIp";
51 // const char kCellTowers[] = "cellTowers";
52 const char kWifiAccessPoints[] = "wifiAccessPoints";
53
54 // WiFi access point objects.
55 const char kMacAddress[] = "macAddress";
56 const char kSignalStrength[] = "signalStrength";
57 const char kAge[] = "age";
58 const char kChannel[] = "channel";
59 const char kSignalToNoiseRatio[] = "signalToNoiseRatio";
60
43 // Response data. 61 // Response data.
44 const char kLocationString[] = "location"; 62 const char kLocationString[] = "location";
45 const char kLatString[] = "lat"; 63 const char kLatString[] = "lat";
46 const char kLngString[] = "lng"; 64 const char kLngString[] = "lng";
47 const char kAccuracyString[] = "accuracy"; 65 const char kAccuracyString[] = "accuracy";
48 // Error object and its contents. 66 // Error object and its contents.
49 const char kErrorString[] = "error"; 67 const char kErrorString[] = "error";
50 // "errors" array in "erorr" object is ignored. 68 // "errors" array in "erorr" object is ignored.
51 const char kCodeString[] = "code"; 69 const char kCodeString[] = "code";
52 const char kMessageString[] = "message"; 70 const char kMessageString[] = "message";
(...skipping 28 matching lines...) Expand all
81 // in tools/metrics/histograms/histograms.xml to keep it in sync. 99 // in tools/metrics/histograms/histograms.xml to keep it in sync.
82 SIMPLE_GEOLOCATION_REQUEST_RESULT_SUCCESS = 0, 100 SIMPLE_GEOLOCATION_REQUEST_RESULT_SUCCESS = 0,
83 SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE = 1, 101 SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE = 1,
84 SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR = 2, 102 SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR = 2,
85 SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED = 3, 103 SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED = 3,
86 104
87 // NOTE: Add entries only immediately above this line. 105 // NOTE: Add entries only immediately above this line.
88 SIMPLE_GEOLOCATION_REQUEST_RESULT_COUNT = 4 106 SIMPLE_GEOLOCATION_REQUEST_RESULT_COUNT = 4
89 }; 107 };
90 108
109 SimpleGeolocationRequestTestMonitor* g_test_request_hook = nullptr;
110
91 // Too many requests (more than 1) mean there is a problem in implementation. 111 // Too many requests (more than 1) mean there is a problem in implementation.
92 void RecordUmaEvent(SimpleGeolocationRequestEvent event) { 112 void RecordUmaEvent(SimpleGeolocationRequestEvent event) {
93 UMA_HISTOGRAM_ENUMERATION("SimpleGeolocation.Request.Event", 113 UMA_HISTOGRAM_ENUMERATION("SimpleGeolocation.Request.Event",
94 event, 114 event,
95 SIMPLE_GEOLOCATION_REQUEST_EVENT_COUNT); 115 SIMPLE_GEOLOCATION_REQUEST_EVENT_COUNT);
96 } 116 }
97 117
98 void RecordUmaResponseCode(int code) { 118 void RecordUmaResponseCode(int code) {
99 UMA_HISTOGRAM_SPARSE_SLOWLY("SimpleGeolocation.Request.ResponseCode", code); 119 UMA_HISTOGRAM_SPARSE_SLOWLY("SimpleGeolocation.Request.ResponseCode", code);
100 } 120 }
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 return true; 260 return true;
241 } 261 }
242 262
243 // Attempts to extract a position from the response. Detects and indicates 263 // Attempts to extract a position from the response. Detects and indicates
244 // various failure cases. 264 // various failure cases.
245 bool GetGeolocationFromResponse(bool http_success, 265 bool GetGeolocationFromResponse(bool http_success,
246 int status_code, 266 int status_code,
247 const std::string& response_body, 267 const std::string& response_body,
248 const GURL& server_url, 268 const GURL& server_url,
249 Geoposition* position) { 269 Geoposition* position) {
270 VLOG(1) << "GetGeolocationFromResponse(http_success=" << http_success
271 << ", status_code=" << status_code << "): response_body:\n"
272 << response_body;
250 273
251 // HttpPost can fail for a number of reasons. Most likely this is because 274 // HttpPost can fail for a number of reasons. Most likely this is because
252 // we're offline, or there was no response. 275 // we're offline, or there was no response.
253 if (!http_success) { 276 if (!http_success) {
254 PrintGeolocationError(server_url, "No response received", position); 277 PrintGeolocationError(server_url, "No response received", position);
255 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_EMPTY); 278 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_EMPTY);
256 return false; 279 return false;
257 } 280 }
258 if (status_code != net::HTTP_OK) { 281 if (status_code != net::HTTP_OK) {
259 std::string message = "Returned error code "; 282 std::string message = "Returned error code ";
260 message += base::IntToString(status_code); 283 message += base::IntToString(status_code);
261 PrintGeolocationError(server_url, message, position); 284 PrintGeolocationError(server_url, message, position);
262 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_NOT_OK); 285 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_NOT_OK);
263 return false; 286 return false;
264 } 287 }
265 288
266 return ParseServerResponse(server_url, response_body, position); 289 return ParseServerResponse(server_url, response_body, position);
267 } 290 }
268 291
269 } // namespace 292 } // namespace
270 293
271 SimpleGeolocationRequest::SimpleGeolocationRequest( 294 SimpleGeolocationRequest::SimpleGeolocationRequest(
272 net::URLRequestContextGetter* url_context_getter, 295 net::URLRequestContextGetter* url_context_getter,
273 const GURL& service_url, 296 const GURL& service_url,
274 base::TimeDelta timeout) 297 base::TimeDelta timeout,
298 scoped_ptr<WifiAccessPointVector> wifi_data)
275 : url_context_getter_(url_context_getter), 299 : url_context_getter_(url_context_getter),
276 service_url_(service_url), 300 service_url_(service_url),
277 retry_sleep_on_server_error_(base::TimeDelta::FromSeconds( 301 retry_sleep_on_server_error_(base::TimeDelta::FromSeconds(
278 kResolveGeolocationRetrySleepOnServerErrorSeconds)), 302 kResolveGeolocationRetrySleepOnServerErrorSeconds)),
279 retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds( 303 retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds(
280 kResolveGeolocationRetrySleepBadResponseSeconds)), 304 kResolveGeolocationRetrySleepBadResponseSeconds)),
281 timeout_(timeout), 305 timeout_(timeout),
282 retries_(0) { 306 retries_(0),
283 } 307 wifi_data_(wifi_data.release()) {}
284 308
285 SimpleGeolocationRequest::~SimpleGeolocationRequest() { 309 SimpleGeolocationRequest::~SimpleGeolocationRequest() {
286 DCHECK(thread_checker_.CalledOnValidThread()); 310 DCHECK(thread_checker_.CalledOnValidThread());
287 311
288 // If callback is not empty, request is cancelled. 312 // If callback is not empty, request is cancelled.
289 if (!callback_.is_null()) { 313 if (!callback_.is_null()) {
290 RecordUmaResponseTime(base::Time::Now() - request_started_at_, false); 314 RecordUmaResponseTime(base::Time::Now() - request_started_at_, false);
291 RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_); 315 RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_);
292 } 316 }
317
318 if (g_test_request_hook)
319 g_test_request_hook->OnRequestCreated(this);
320 }
321
322 std::string SimpleGeolocationRequest::FormatRequestBody() const {
323 if (!wifi_data_) {
324 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints",
325 false);
326 return std::string(kSimpleGeolocationRequestBody);
327 }
328
329 scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue);
330 request->SetBooleanWithoutPathExpansion(kConsiderIp, true);
331
332 base::ListValue* wifi_access_points(new base::ListValue);
333 request->SetWithoutPathExpansion(kWifiAccessPoints, wifi_access_points);
334
335 for (const WifiAccessPoint& access_point : *wifi_data_) {
336 base::DictionaryValue* access_point_dictionary = new base::DictionaryValue;
337 wifi_access_points->Append(access_point_dictionary);
338
339 access_point_dictionary->SetStringWithoutPathExpansion(
340 kMacAddress, access_point.mac_address);
341 access_point_dictionary->SetIntegerWithoutPathExpansion(
342 kSignalStrength, access_point.signal_strength);
343 if (!access_point.timestamp.is_null())
344 access_point_dictionary->SetStringWithoutPathExpansion(
345 kAge,
346 base::Int64ToString(
347 (base::Time::Now() - access_point.timestamp).InMilliseconds()));
stevenjb 2016/03/22 16:39:49 {}
Alexander Alekseev 2016/03/23 00:04:45 Done.
348
349 access_point_dictionary->SetIntegerWithoutPathExpansion(
350 kChannel, access_point.channel);
351 access_point_dictionary->SetIntegerWithoutPathExpansion(
352 kSignalToNoiseRatio, access_point.signal_to_noise);
353 }
354 std::string result;
355 if (!base::JSONWriter::Write(*request, &result)) {
356 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints",
357 false);
358 return std::string(kSimpleGeolocationRequestBody);
359 }
360 UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints",
361 wifi_data_->size());
362
363 return result;
293 } 364 }
294 365
295 void SimpleGeolocationRequest::StartRequest() { 366 void SimpleGeolocationRequest::StartRequest() {
296 DCHECK(thread_checker_.CalledOnValidThread()); 367 DCHECK(thread_checker_.CalledOnValidThread());
297 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START); 368 RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START);
298 ++retries_; 369 ++retries_;
299 370
371 const std::string request_body = FormatRequestBody();
372 VLOG(1) << "SimpleGeolocationRequest::StartRequest(): request body:\n"
373 << request_body;
374
300 url_fetcher_ = 375 url_fetcher_ =
301 net::URLFetcher::Create(request_url_, net::URLFetcher::POST, this); 376 net::URLFetcher::Create(request_url_, net::URLFetcher::POST, this);
302 url_fetcher_->SetRequestContext(url_context_getter_.get()); 377 url_fetcher_->SetRequestContext(url_context_getter_.get());
303 url_fetcher_->SetUploadData("application/json", 378 url_fetcher_->SetUploadData("application/json", request_body);
304 std::string(kSimpleGeolocationRequestBody));
305 url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | 379 url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE |
306 net::LOAD_DISABLE_CACHE | 380 net::LOAD_DISABLE_CACHE |
307 net::LOAD_DO_NOT_SAVE_COOKIES | 381 net::LOAD_DO_NOT_SAVE_COOKIES |
308 net::LOAD_DO_NOT_SEND_COOKIES | 382 net::LOAD_DO_NOT_SEND_COOKIES |
309 net::LOAD_DO_NOT_SEND_AUTH_DATA); 383 net::LOAD_DO_NOT_SEND_AUTH_DATA);
384
385 // Call test hook before
stevenjb 2016/03/22 16:39:49 s/before/first./ ?
Alexander Alekseev 2016/03/23 00:04:45 This is only half of the comment I was about to wr
386 if (g_test_request_hook)
387 g_test_request_hook->OnStart(this);
388
310 url_fetcher_->Start(); 389 url_fetcher_->Start();
311 } 390 }
312 391
313 void SimpleGeolocationRequest::MakeRequest(const ResponseCallback& callback) { 392 void SimpleGeolocationRequest::MakeRequest(const ResponseCallback& callback) {
314 callback_ = callback; 393 callback_ = callback;
315 request_url_ = GeolocationRequestURL(service_url_); 394 request_url_ = GeolocationRequestURL(service_url_);
316 timeout_timer_.Start( 395 timeout_timer_.Start(
317 FROM_HERE, timeout_, this, &SimpleGeolocationRequest::OnTimeout); 396 FROM_HERE, timeout_, this, &SimpleGeolocationRequest::OnTimeout);
318 request_started_at_ = base::Time::Now(); 397 request_started_at_ = base::Time::Now();
319 StartRequest(); 398 StartRequest();
320 } 399 }
321 400
401 // static
402 void SimpleGeolocationRequest::SetTestMonitor(
403 SimpleGeolocationRequestTestMonitor* monitor) {
404 g_test_request_hook = monitor;
405 }
406
407 std::string SimpleGeolocationRequest::FormatRequestBodyForTesting() const {
408 return FormatRequestBody();
409 }
410
322 void SimpleGeolocationRequest::Retry(bool server_error) { 411 void SimpleGeolocationRequest::Retry(bool server_error) {
323 base::TimeDelta delay(server_error ? retry_sleep_on_server_error_ 412 base::TimeDelta delay(server_error ? retry_sleep_on_server_error_
324 : retry_sleep_on_bad_response_); 413 : retry_sleep_on_bad_response_);
325 request_scheduled_.Start( 414 request_scheduled_.Start(
326 FROM_HERE, delay, this, &SimpleGeolocationRequest::StartRequest); 415 FROM_HERE, delay, this, &SimpleGeolocationRequest::StartRequest);
327 } 416 }
328 417
329 void SimpleGeolocationRequest::OnURLFetchComplete( 418 void SimpleGeolocationRequest::OnURLFetchComplete(
330 const net::URLFetcher* source) { 419 const net::URLFetcher* source) {
331 DCHECK_EQ(url_fetcher_.get(), source); 420 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 472 ? SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR
384 : SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE); 473 : SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE);
385 RecordUmaResult(result, retries_); 474 RecordUmaResult(result, retries_);
386 position_.status = Geoposition::STATUS_TIMEOUT; 475 position_.status = Geoposition::STATUS_TIMEOUT;
387 const base::TimeDelta elapsed = base::Time::Now() - request_started_at_; 476 const base::TimeDelta elapsed = base::Time::Now() - request_started_at_;
388 ReplyAndDestroySelf(elapsed, true /* server_error */); 477 ReplyAndDestroySelf(elapsed, true /* server_error */);
389 // "this" is already destroyed here. 478 // "this" is already destroyed here.
390 } 479 }
391 480
392 } // namespace chromeos 481 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698