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

Unified Diff: chrome/browser/chromeos/geolocation/simple_geolocation_request.cc

Issue 786693002: Move chrome/browser/chromeos/geolocation to chromeos/geolocation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add DEPS Created 6 years 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/geolocation/simple_geolocation_request.cc
diff --git a/chrome/browser/chromeos/geolocation/simple_geolocation_request.cc b/chrome/browser/chromeos/geolocation/simple_geolocation_request.cc
deleted file mode 100644
index 96d05004e54dfd9a4685410b10da4266a7a89e96..0000000000000000000000000000000000000000
--- a/chrome/browser/chromeos/geolocation/simple_geolocation_request.cc
+++ /dev/null
@@ -1,392 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/geolocation/simple_geolocation_request.h"
-
-#include <algorithm>
-#include <string>
-
-#include "base/json/json_reader.h"
-#include "base/metrics/histogram.h"
-#include "base/metrics/sparse_histogram.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/time/time.h"
-#include "base/values.h"
-#include "chrome/browser/chromeos/geolocation/geoposition.h"
-#include "chrome/browser/chromeos/geolocation/simple_geolocation_provider.h"
-#include "google_apis/google_api_keys.h"
-#include "net/base/escape.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_status_code.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_status.h"
-
-// Location resolve timeout is usually 1 minute, so 2 minutes with 50 buckets
-// should be enough.
-#define UMA_HISTOGRAM_LOCATION_RESPONSE_TIMES(name, sample) \
- UMA_HISTOGRAM_CUSTOM_TIMES(name, \
- sample, \
- base::TimeDelta::FromMilliseconds(10), \
- base::TimeDelta::FromMinutes(2), \
- 50)
-
-namespace chromeos {
-
-namespace {
-
-// The full request text. (no parameters are supported by now)
-const char kSimpleGeolocationRequestBody[] = "{\"considerIP\": \"true\"}";
-
-// Response data.
-const char kLocationString[] = "location";
-const char kLatString[] = "lat";
-const char kLngString[] = "lng";
-const char kAccuracyString[] = "accuracy";
-// Error object and its contents.
-const char kErrorString[] = "error";
-// "errors" array in "erorr" object is ignored.
-const char kCodeString[] = "code";
-const char kMessageString[] = "message";
-
-// We are using "sparse" histograms for the number of retry attempts,
-// so we need to explicitly limit maximum value (in case something goes wrong).
-const size_t kMaxRetriesValueInHistograms = 20;
-
-// Sleep between geolocation request retry on HTTP error.
-const unsigned int kResolveGeolocationRetrySleepOnServerErrorSeconds = 5;
-
-// Sleep between geolocation request retry on bad server response.
-const unsigned int kResolveGeolocationRetrySleepBadResponseSeconds = 10;
-
-enum SimpleGeolocationRequestEvent {
- // NOTE: Do not renumber these as that would confuse interpretation of
- // previously logged data. When making changes, also update the enum list
- // in tools/metrics/histograms/histograms.xml to keep it in sync.
- SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START = 0,
- SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_SUCCESS = 1,
- SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_NOT_OK = 2,
- SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_EMPTY = 3,
- SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_MALFORMED = 4,
-
- // NOTE: Add entries only immediately above this line.
- SIMPLE_GEOLOCATION_REQUEST_EVENT_COUNT = 5
-};
-
-enum SimpleGeolocationRequestResult {
- // NOTE: Do not renumber these as that would confuse interpretation of
- // previously logged data. When making changes, also update the enum list
- // in tools/metrics/histograms/histograms.xml to keep it in sync.
- SIMPLE_GEOLOCATION_REQUEST_RESULT_SUCCESS = 0,
- SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE = 1,
- SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR = 2,
- SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED = 3,
-
- // NOTE: Add entries only immediately above this line.
- SIMPLE_GEOLOCATION_REQUEST_RESULT_COUNT = 4
-};
-
-// Too many requests (more than 1) mean there is a problem in implementation.
-void RecordUmaEvent(SimpleGeolocationRequestEvent event) {
- UMA_HISTOGRAM_ENUMERATION("SimpleGeolocation.Request.Event",
- event,
- SIMPLE_GEOLOCATION_REQUEST_EVENT_COUNT);
-}
-
-void RecordUmaResponseCode(int code) {
- UMA_HISTOGRAM_SPARSE_SLOWLY("SimpleGeolocation.Request.ResponseCode", code);
-}
-
-// Slow geolocation resolve leads to bad user experience.
-void RecordUmaResponseTime(base::TimeDelta elapsed, bool success) {
- if (success) {
- UMA_HISTOGRAM_LOCATION_RESPONSE_TIMES(
- "SimpleGeolocation.Request.ResponseSuccessTime", elapsed);
- } else {
- UMA_HISTOGRAM_LOCATION_RESPONSE_TIMES(
- "SimpleGeolocation.Request.ResponseFailureTime", elapsed);
- }
-}
-
-void RecordUmaResult(SimpleGeolocationRequestResult result, size_t retries) {
- UMA_HISTOGRAM_ENUMERATION("SimpleGeolocation.Request.Result",
- result,
- SIMPLE_GEOLOCATION_REQUEST_RESULT_COUNT);
- UMA_HISTOGRAM_SPARSE_SLOWLY("SimpleGeolocation.Request.Retries",
- std::min(retries, kMaxRetriesValueInHistograms));
-}
-
-// Creates the request url to send to the server.
-GURL GeolocationRequestURL(const GURL& url) {
- if (url != SimpleGeolocationProvider::DefaultGeolocationProviderURL())
- return url;
-
- std::string api_key = google_apis::GetAPIKey();
- if (api_key.empty())
- return url;
-
- std::string query(url.query());
- if (!query.empty())
- query += "&";
- query += "key=" + net::EscapeQueryParamValue(api_key, true);
- GURL::Replacements replacements;
- replacements.SetQueryStr(query);
- return url.ReplaceComponents(replacements);
-}
-
-void PrintGeolocationError(const GURL& server_url,
- const std::string& message,
- Geoposition* position) {
- position->status = Geoposition::STATUS_SERVER_ERROR;
- position->error_message =
- base::StringPrintf("SimpleGeolocation provider at '%s' : %s.",
- server_url.GetOrigin().spec().c_str(),
- message.c_str());
- VLOG(1) << "SimpleGeolocationRequest::GetGeolocationFromResponse() : "
- << position->error_message;
-}
-
-// Parses the server response body. Returns true if parsing was successful.
-// Sets |*position| to the parsed Geolocation if a valid position was received,
-// otherwise leaves it unchanged.
-bool ParseServerResponse(const GURL& server_url,
- const std::string& response_body,
- Geoposition* position) {
- DCHECK(position);
-
- if (response_body.empty()) {
- PrintGeolocationError(
- server_url, "Server returned empty response", position);
- RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_EMPTY);
- return false;
- }
- VLOG(1) << "SimpleGeolocationRequest::ParseServerResponse() : "
- "Parsing response '" << response_body << "'";
-
- // Parse the response, ignoring comments.
- std::string error_msg;
- scoped_ptr<base::Value> response_value(base::JSONReader::ReadAndReturnError(
- response_body, base::JSON_PARSE_RFC, NULL, &error_msg));
- if (response_value == NULL) {
- PrintGeolocationError(
- server_url, "JSONReader failed: " + error_msg, position);
- RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_MALFORMED);
- return false;
- }
-
- base::DictionaryValue* response_object = NULL;
- if (!response_value->GetAsDictionary(&response_object)) {
- PrintGeolocationError(
- server_url,
- "Unexpected response type : " +
- base::StringPrintf("%u", response_value->GetType()),
- position);
- RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_MALFORMED);
- return false;
- }
-
- base::DictionaryValue* error_object = NULL;
- base::DictionaryValue* location_object = NULL;
- response_object->GetDictionaryWithoutPathExpansion(kLocationString,
- &location_object);
- response_object->GetDictionaryWithoutPathExpansion(kErrorString,
- &error_object);
-
- position->timestamp = base::Time::Now();
-
- if (error_object) {
- if (!error_object->GetStringWithoutPathExpansion(
- kMessageString, &(position->error_message))) {
- position->error_message = "Server returned error without message.";
- }
-
- // Ignore result (code defaults to zero).
- error_object->GetIntegerWithoutPathExpansion(kCodeString,
- &(position->error_code));
- } else {
- position->error_message.erase();
- }
-
- if (location_object) {
- if (!location_object->GetDoubleWithoutPathExpansion(
- kLatString, &(position->latitude))) {
- PrintGeolocationError(server_url, "Missing 'lat' attribute.", position);
- RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_MALFORMED);
- return false;
- }
- if (!location_object->GetDoubleWithoutPathExpansion(
- kLngString, &(position->longitude))) {
- PrintGeolocationError(server_url, "Missing 'lon' attribute.", position);
- RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_MALFORMED);
- return false;
- }
- if (!response_object->GetDoubleWithoutPathExpansion(
- kAccuracyString, &(position->accuracy))) {
- PrintGeolocationError(
- server_url, "Missing 'accuracy' attribute.", position);
- RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_MALFORMED);
- return false;
- }
- }
-
- if (error_object) {
- position->status = Geoposition::STATUS_SERVER_ERROR;
- return false;
- }
- // Empty response is STATUS_OK but not Valid().
- position->status = Geoposition::STATUS_OK;
- return true;
-}
-
-// Attempts to extract a position from the response. Detects and indicates
-// various failure cases.
-bool GetGeolocationFromResponse(bool http_success,
- int status_code,
- const std::string& response_body,
- const GURL& server_url,
- Geoposition* position) {
-
- // HttpPost can fail for a number of reasons. Most likely this is because
- // we're offline, or there was no response.
- if (!http_success) {
- PrintGeolocationError(server_url, "No response received", position);
- RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_EMPTY);
- return false;
- }
- if (status_code != net::HTTP_OK) {
- std::string message = "Returned error code ";
- message += base::IntToString(status_code);
- PrintGeolocationError(server_url, message, position);
- RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_RESPONSE_NOT_OK);
- return false;
- }
-
- return ParseServerResponse(server_url, response_body, position);
-}
-
-} // namespace
-
-SimpleGeolocationRequest::SimpleGeolocationRequest(
- net::URLRequestContextGetter* url_context_getter,
- const GURL& service_url,
- base::TimeDelta timeout)
- : url_context_getter_(url_context_getter),
- service_url_(service_url),
- retry_sleep_on_server_error_(base::TimeDelta::FromSeconds(
- kResolveGeolocationRetrySleepOnServerErrorSeconds)),
- retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds(
- kResolveGeolocationRetrySleepBadResponseSeconds)),
- timeout_(timeout),
- retries_(0) {
-}
-
-SimpleGeolocationRequest::~SimpleGeolocationRequest() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // If callback is not empty, request is cancelled.
- if (!callback_.is_null()) {
- RecordUmaResponseTime(base::Time::Now() - request_started_at_, false);
- RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_);
- }
-}
-
-void SimpleGeolocationRequest::StartRequest() {
- DCHECK(thread_checker_.CalledOnValidThread());
- RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START);
- ++retries_;
-
- url_fetcher_.reset(
- net::URLFetcher::Create(request_url_, net::URLFetcher::POST, this));
- url_fetcher_->SetRequestContext(url_context_getter_.get());
- url_fetcher_->SetUploadData("application/json",
- std::string(kSimpleGeolocationRequestBody));
- url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE |
- net::LOAD_DISABLE_CACHE |
- net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DO_NOT_SEND_AUTH_DATA);
- url_fetcher_->Start();
-}
-
-void SimpleGeolocationRequest::MakeRequest(const ResponseCallback& callback) {
- callback_ = callback;
- request_url_ = GeolocationRequestURL(service_url_);
- timeout_timer_.Start(
- FROM_HERE, timeout_, this, &SimpleGeolocationRequest::OnTimeout);
- request_started_at_ = base::Time::Now();
- StartRequest();
-}
-
-void SimpleGeolocationRequest::Retry(bool server_error) {
- base::TimeDelta delay(server_error ? retry_sleep_on_server_error_
- : retry_sleep_on_bad_response_);
- request_scheduled_.Start(
- FROM_HERE, delay, this, &SimpleGeolocationRequest::StartRequest);
-}
-
-void SimpleGeolocationRequest::OnURLFetchComplete(
- const net::URLFetcher* source) {
- DCHECK_EQ(url_fetcher_.get(), source);
-
- net::URLRequestStatus status = source->GetStatus();
- int response_code = source->GetResponseCode();
- RecordUmaResponseCode(response_code);
-
- std::string data;
- source->GetResponseAsString(&data);
- const bool parse_success = GetGeolocationFromResponse(
- status.is_success(), response_code, data, source->GetURL(), &position_);
- const bool server_error =
- !status.is_success() || (response_code >= 500 && response_code < 600);
- const bool success = parse_success && position_.Valid();
- url_fetcher_.reset();
-
- DVLOG(1) << "SimpleGeolocationRequest::OnURLFetchComplete(): position={"
- << position_.ToString() << "}";
-
- if (!success) {
- Retry(server_error);
- return;
- }
- const base::TimeDelta elapsed = base::Time::Now() - request_started_at_;
- RecordUmaResponseTime(elapsed, success);
-
- RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_SUCCESS, retries_);
-
- ReplyAndDestroySelf(elapsed, server_error);
- // "this" is already destroyed here.
-}
-
-void SimpleGeolocationRequest::ReplyAndDestroySelf(
- const base::TimeDelta elapsed,
- bool server_error) {
- url_fetcher_.reset();
- timeout_timer_.Stop();
- request_scheduled_.Stop();
-
- ResponseCallback callback = callback_;
-
- // Empty callback is used to identify "completed or not yet started request".
- callback_.Reset();
-
- // callback.Run() usually destroys SimpleGeolocationRequest, because this is
- // the way callback is implemented in GeolocationProvider.
- callback.Run(position_, server_error, elapsed);
- // "this" is already destroyed here.
-}
-
-void SimpleGeolocationRequest::OnTimeout() {
- const SimpleGeolocationRequestResult result =
- (position_.status == Geoposition::STATUS_SERVER_ERROR
- ? SIMPLE_GEOLOCATION_REQUEST_RESULT_SERVER_ERROR
- : SIMPLE_GEOLOCATION_REQUEST_RESULT_FAILURE);
- RecordUmaResult(result, retries_);
- position_.status = Geoposition::STATUS_TIMEOUT;
- const base::TimeDelta elapsed = base::Time::Now() - request_started_at_;
- ReplyAndDestroySelf(elapsed, true /* server_error */);
- // "this" is already destroyed here.
-}
-
-} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698