Index: athena/main/url_search_provider.cc |
diff --git a/athena/main/url_search_provider.cc b/athena/main/url_search_provider.cc |
index 53452940957e343a7a23eb0d65c8bdc8f59e475c..01eb67404eb3e2dbe8be142ba98a8b85845942f3 100644 |
--- a/athena/main/url_search_provider.cc |
+++ b/athena/main/url_search_provider.cc |
@@ -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 |