This source file includes following definitions.
- LogResponseState
- GetExperimentParam
- DispatchRequestsAndClear
- IsEnabled
- FetchSuggestionsData
- OnURLFetchComplete
- Shutdown
#include "chrome/browser/search/suggestions/suggestions_service.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/strings/string_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/history/history_types.h"
#include "chrome/browser/metrics/variations/variations_http_header_provider.h"
#include "chrome/browser/profiles/profile.h"
#include "components/variations/variations_associated_data.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"
namespace suggestions {
namespace {
enum SuggestionsResponseState {
RESPONSE_EMPTY,
RESPONSE_INVALID,
RESPONSE_VALID,
RESPONSE_STATE_SIZE
};
void LogResponseState(SuggestionsResponseState state) {
UMA_HISTOGRAM_ENUMERATION("Suggestions.ResponseState", state,
RESPONSE_STATE_SIZE);
}
std::string GetExperimentParam(const std::string& key) {
return chrome_variations::GetVariationParamValue(kSuggestionsFieldTrialName,
key);
}
void DispatchRequestsAndClear(
const SuggestionsProfile& suggestions,
std::vector<SuggestionsService::ResponseCallback>* requestors) {
std::vector<SuggestionsService::ResponseCallback>::iterator it;
for (it = requestors->begin(); it != requestors->end(); ++it) {
it->Run(suggestions);
}
std::vector<SuggestionsService::ResponseCallback>().swap(*requestors);
}
}
const char kSuggestionsFieldTrialName[] = "ChromeSuggestions";
const char kSuggestionsFieldTrialURLParam[] = "url";
const char kSuggestionsFieldTrialStateParam[] = "state";
const char kSuggestionsFieldTrialStateEnabled[] = "enabled";
SuggestionsService::SuggestionsService(Profile* profile)
: profile_(profile) {
suggestions_url_ = GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam));
}
SuggestionsService::~SuggestionsService() {
}
bool SuggestionsService::IsEnabled() {
return GetExperimentParam(kSuggestionsFieldTrialStateParam) ==
kSuggestionsFieldTrialStateEnabled;
}
void SuggestionsService::FetchSuggestionsData(
SuggestionsService::ResponseCallback callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (pending_request_.get()) {
waiting_requestors_.push_back(callback);
return;
}
DCHECK(waiting_requestors_.empty());
waiting_requestors_.push_back(callback);
pending_request_.reset(net::URLFetcher::Create(
0, suggestions_url_, net::URLFetcher::GET, this));
pending_request_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
pending_request_->SetRequestContext(profile_->GetRequestContext());
net::HttpRequestHeaders headers;
chrome_variations::VariationsHttpHeaderProvider::GetInstance()->
AppendHeaders(pending_request_->GetOriginalURL(),
profile_->IsOffTheRecord(), false, &headers);
pending_request_->SetExtraRequestHeaders(headers.ToString());
pending_request_->Start();
last_request_started_time_ = base::TimeTicks::Now();
}
void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK_EQ(pending_request_.get(), source);
scoped_ptr<const net::URLFetcher> request(pending_request_.release());
const net::URLRequestStatus& request_status = request->GetStatus();
if (request_status.status() != net::URLRequestStatus::SUCCESS) {
UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode",
-request_status.error());
DVLOG(1) << "Suggestions server request failed with error: "
<< request_status.error() << ": "
<< net::ErrorToString(request_status.error());
DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_);
return;
}
const int response_code = request->GetResponseCode();
UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FetchResponseCode",
response_code);
if (response_code != net::HTTP_OK) {
DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_);
return;
}
const base::TimeDelta latency =
base::TimeTicks::Now() - last_request_started_time_;
UMA_HISTOGRAM_MEDIUM_TIMES("Suggestions.FetchSuccessLatency", latency);
std::string suggestions_data;
bool success = request->GetResponseAsString(&suggestions_data);
DCHECK(success);
SuggestionsProfile suggestions;
if (suggestions_data.empty()) {
LogResponseState(RESPONSE_EMPTY);
} else if (suggestions.ParseFromString(suggestions_data)) {
LogResponseState(RESPONSE_VALID);
} else {
LogResponseState(RESPONSE_INVALID);
}
DispatchRequestsAndClear(suggestions, &waiting_requestors_);
}
void SuggestionsService::Shutdown() {
pending_request_.reset(NULL);
DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_);
}
}