Add search suggestions fetched from the server

Fix athena::AppListViewDelegate to show multiple results.
Use SearchSuggestionParser in UrlSearchProvider

BUG=399561

Review URL: https://codereview.chromium.org/438023002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287504 0039d316-1c4b-4281-b951-d872f2087c98
parent e99871ce
......@@ -51,9 +51,12 @@ void AppListViewDelegate::SearchResultChanged() {
app_list::SearchProvider* search_provider = search_providers_[0];
std::vector<app_list::SearchResult*> results;
search_provider->ReleaseResult(&results);
model_->results()->DeleteAll();
for (size_t i = 0; i < results.size(); ++i)
model_->results()->Add(results[i]);
if (results.empty()) {
model_->results()->DeleteAll();
} else {
for (size_t i = 0; i < results.size(); ++i)
model_->results()->Add(results[i]);
}
}
bool AppListViewDelegate::ForceNativeDesktop() const {
......
......@@ -7,14 +7,19 @@
#include "athena/activity/public/activity_factory.h"
#include "athena/activity/public/activity_manager.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "components/autocomplete/autocomplete_input.h"
#include "components/autocomplete/autocomplete_scheme_classifier.h"
#include "components/autocomplete/search_suggestion_parser.h"
#include "components/metrics/proto/omnibox_event.pb.h"
#include "components/metrics/proto/omnibox_input_type.pb.h"
#include "components/search_engines/search_terms_data.h"
#include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_service.h"
#include "components/search_engines/template_url_service_client.h"
#include "content/public/browser/browser_context.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request.h"
#include "ui/app_list/search_result.h"
#include "url/gurl.h"
......@@ -23,6 +28,15 @@ namespace athena {
namespace {
// The SearchTermsData implementation for Athena.
class AthenaSearchTermsData : public SearchTermsData {
public:
// SearchTermsData:
virtual std::string GetSuggestClient() const OVERRIDE {
return "chrome";
}
};
// The AutocompleteSchemeClassifier implementation for Athena.
// TODO(mukai): Introduce supports of normal schemes like about: or blob:
class AthenaSchemeClassifier : public AutocompleteSchemeClassifier {
......@@ -64,57 +78,63 @@ class AthenaTemplateURLServiceClient : public TemplateURLServiceClient {
class UrlSearchResult : public app_list::SearchResult {
public:
UrlSearchResult(content::BrowserContext* browser_context,
TemplateURLService* template_url_service,
const base::string16& query)
const GURL& url,
const base::string16& title)
: browser_context_(browser_context),
template_url_service_(template_url_service),
input_(query,
base::string16::npos /* cursor_position */,
base::string16() /* desired_tld */,
GURL() /* current_url */,
metrics::OmniboxEventProto::INVALID_SPEC,
false /* prevent_inline_autocomplete */,
false /* prefer_keyword */,
true /* allow_extract_keyword_match */,
true /* want_asynchronous_matches */,
AthenaSchemeClassifier()) {
set_title(query);
app_list::SearchResult::Tags title_tags;
if (input_.type() == metrics::OmniboxInputType::URL) {
title_tags.push_back(app_list::SearchResult::Tag(
app_list::SearchResult::Tag::URL, 0, query.size()));
}
title_tags.push_back(app_list::SearchResult::Tag(
app_list::SearchResult::Tag::MATCH, 0, query.size()));
set_title_tags(title_tags);
set_id(base::UTF16ToUTF8(query));
url_(url) {
set_title(title);
set_id(url_.spec());
}
private:
// Overriddenn from app_list::SearchResult:
virtual void Open(int event_flags) OVERRIDE {
GURL url;
if (input_.type() == metrics::OmniboxInputType::URL) {
url = input_.canonicalized_url();
} else {
TemplateURL* template_url =
template_url_service_->GetDefaultSearchProvider();
const TemplateURLRef& search_url = template_url->url_ref();
TemplateURLRef::SearchTermsArgs search_terms_args(input_.text());
url = GURL(search_url.ReplaceSearchTerms(
search_terms_args, template_url_service_->search_terms_data()));
}
ActivityManager::Get()->AddActivity(
ActivityFactory::Get()->CreateWebActivity(browser_context_, url));
ActivityFactory::Get()->CreateWebActivity(browser_context_, url_));
}
content::BrowserContext* browser_context_;
TemplateURLService* template_url_service_;
AutocompleteInput input_;
GURL url_;
DISALLOW_COPY_AND_ASSIGN(UrlSearchResult);
};
scoped_ptr<app_list::SearchResult> CreateResultForSearchQuery(
content::BrowserContext* browser_context,
TemplateURLService* template_url_service,
const base::string16& search_query) {
TemplateURL* template_url =
template_url_service->GetDefaultSearchProvider();
const TemplateURLRef& search_url = template_url->url_ref();
TemplateURLRef::SearchTermsArgs search_terms_args(search_query);
return scoped_ptr<app_list::SearchResult>(new UrlSearchResult(
browser_context,
GURL(search_url.ReplaceSearchTerms(
search_terms_args, template_url_service->search_terms_data())),
search_query));
}
scoped_ptr<app_list::SearchResult> CreateResultForInput(
content::BrowserContext* browser_context,
TemplateURLService* template_url_service,
const AutocompleteInput& input) {
scoped_ptr<app_list::SearchResult> result;
app_list::SearchResult::Tags title_tags;
if (input.type() == metrics::OmniboxInputType::URL) {
result.reset(new UrlSearchResult(
browser_context, input.canonicalized_url(), input.text()));
title_tags.push_back(app_list::SearchResult::Tag(
app_list::SearchResult::Tag::URL, 0, input.text().size()));
} else {
result = CreateResultForSearchQuery(
browser_context, template_url_service, input.text());
}
title_tags.push_back(app_list::SearchResult::Tag(
app_list::SearchResult::Tag::MATCH, 0, input.text().size()));
result->set_title_tags(title_tags);
return result.Pass();
}
} // namespace
UrlSearchProvider::UrlSearchProvider(content::BrowserContext* browser_context)
......@@ -122,13 +142,15 @@ UrlSearchProvider::UrlSearchProvider(content::BrowserContext* browser_context)
// TODO(mukai): introduce the real parameters when it's necessary.
template_url_service_(
new TemplateURLService(NULL /* prefs */,
make_scoped_ptr(new SearchTermsData()),
scoped_ptr<SearchTermsData>(
new AthenaSearchTermsData()),
NULL /* KeywordWebDataService */,
scoped_ptr<TemplateURLServiceClient>(
new AthenaTemplateURLServiceClient()),
NULL /*GoogleURLTracker */,
NULL /* RapporService */,
base::Closure() /* dsp_change_callback */)) {
base::Closure() /* dsp_change_callback */)),
should_fetch_suggestions_again_(false) {
template_url_service_->Load();
}
......@@ -136,12 +158,90 @@ UrlSearchProvider::~UrlSearchProvider() {
}
void UrlSearchProvider::Start(const base::string16& query) {
input_ = AutocompleteInput(query,
base::string16::npos /* cursor_position */,
base::string16() /* desired_tld */,
GURL() /* current_url */,
metrics::OmniboxEventProto::INVALID_SPEC,
false /* prevent_inline_autocomplete */,
false /* prefer_keyword */,
true /* allow_extract_keyword_match */,
true /* want_asynchronous_matches */,
AthenaSchemeClassifier());
ClearResults();
Add(scoped_ptr<app_list::SearchResult>(new UrlSearchResult(
browser_context_, template_url_service_.get(), query)));
Add(CreateResultForInput(browser_context_, template_url_service_.get(),
input_));
StartFetchingSuggestions();
}
void UrlSearchProvider::Stop() {
suggestion_fetcher_.reset();
}
void UrlSearchProvider::OnURLFetchComplete(const net::URLFetcher* source) {
DCHECK_EQ(suggestion_fetcher_.get(), source);
if (source->GetStatus().is_success() && source->GetResponseCode() == 200) {
std::string json_data = SearchSuggestionParser::ExtractJsonData(source);
scoped_ptr<base::Value> data(
SearchSuggestionParser::DeserializeJsonData(json_data));
if (data) {
const int kDefaultRelevance = 0;
SearchSuggestionParser::Results results;
if (SearchSuggestionParser::ParseSuggestResults(
*data, input_, AthenaSchemeClassifier(), kDefaultRelevance,
std::string(), // languages
false, // is_keyword_result
&results)) {
ClearResults();
Add(CreateResultForInput(browser_context_, template_url_service_.get(),
input_));
for (size_t i = 0; i < results.suggest_results.size(); ++i) {
const SearchSuggestionParser::SuggestResult& result =
results.suggest_results[i];
Add(CreateResultForSearchQuery(browser_context_,
template_url_service_.get(),
result.suggestion()));
}
for (size_t i = 0; i < results.navigation_results.size(); ++i) {
const SearchSuggestionParser::NavigationResult& result =
results.navigation_results[i];
Add(scoped_ptr<app_list::SearchResult>(
new UrlSearchResult(browser_context_, result.url(),
result.description())));
}
}
}
}
suggestion_fetcher_.reset();
if (should_fetch_suggestions_again_)
StartFetchingSuggestions();
}
void UrlSearchProvider::StartFetchingSuggestions() {
if (suggestion_fetcher_) {
should_fetch_suggestions_again_ = true;
return;
}
should_fetch_suggestions_again_ = false;
// Bail if the suggestion URL is invalid with the given replacements.
TemplateURL* template_url = template_url_service_->GetDefaultSearchProvider();
TemplateURLRef::SearchTermsArgs search_term_args(input_.text());
search_term_args.input_type = input_.type();
search_term_args.cursor_position = input_.cursor_position();
search_term_args.page_classification = input_.current_page_classification();
GURL suggest_url(template_url->suggestions_url_ref().ReplaceSearchTerms(
search_term_args, template_url_service_->search_terms_data()));
if (!suggest_url.is_valid()) {
DLOG(ERROR) << "Invalid URL: " << suggest_url;
return;
}
suggestion_fetcher_.reset(
net::URLFetcher::Create(suggest_url, net::URLFetcher::GET, this));
suggestion_fetcher_->SetRequestContext(browser_context_->GetRequestContext());
suggestion_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
suggestion_fetcher_->Start();
}
} // namespace athena
......@@ -6,6 +6,8 @@
#define ATHENA_MAIN_URL_SEARCH_PROVIDER_H_
#include "base/memory/scoped_ptr.h"
#include "components/autocomplete/autocomplete_input.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "ui/app_list/search_provider.h"
class TemplateURLService;
......@@ -17,7 +19,8 @@ class BrowserContext;
namespace athena {
// A sample search provider.
class UrlSearchProvider : public app_list::SearchProvider {
class UrlSearchProvider : public app_list::SearchProvider,
public net::URLFetcherDelegate {
public:
UrlSearchProvider(content::BrowserContext* browser_context);
virtual ~UrlSearchProvider();
......@@ -26,12 +29,21 @@ class UrlSearchProvider : public app_list::SearchProvider {
virtual void Start(const base::string16& query) OVERRIDE;
virtual void Stop() OVERRIDE;
// Overridden from net::URLFetcherDelegate.
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
private:
void StartFetchingSuggestions();
content::BrowserContext* browser_context_;
// TODO(mukai): This should be provided through BrowserContextKeyedService.
scoped_ptr<TemplateURLService> template_url_service_;
AutocompleteInput input_;
scoped_ptr<net::URLFetcher> suggestion_fetcher_;
bool should_fetch_suggestions_again_;
DISALLOW_COPY_AND_ASSIGN(UrlSearchProvider);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment