Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / ui / search / instant_search_prerenderer.cc
blob69bb402f7138b47d1c78b0e2bf2156c0a314e2b8
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/search/instant_search_prerenderer.h"
7 #include "chrome/browser/prerender/prerender_handle.h"
8 #include "chrome/browser/prerender/prerender_manager.h"
9 #include "chrome/browser/prerender/prerender_manager_factory.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/search/instant_service.h"
12 #include "chrome/browser/search/instant_service_factory.h"
13 #include "chrome/browser/search/search.h"
14 #include "chrome/browser/search_engines/template_url_service_factory.h"
15 #include "chrome/browser/ui/browser_navigator.h"
16 #include "chrome/browser/ui/search/search_tab_helper.h"
17 #include "components/omnibox/autocomplete_match.h"
18 #include "components/search_engines/template_url_service.h"
20 namespace {
22 // Returns true if the underlying page supports Instant search.
23 bool PageSupportsInstantSearch(content::WebContents* contents) {
24 // Search results page supports Instant search.
25 return SearchTabHelper::FromWebContents(contents)->IsSearchResultsPage();
28 // Returns true if |match| is associated with the default search provider.
29 bool MatchIsFromDefaultSearchProvider(const AutocompleteMatch& match,
30 Profile* profile) {
31 DCHECK(profile);
32 TemplateURLService* template_url_service =
33 TemplateURLServiceFactory::GetForProfile(profile);
34 return match.GetTemplateURL(template_url_service, false) ==
35 template_url_service->GetDefaultSearchProvider();
38 } // namespace
40 InstantSearchPrerenderer::InstantSearchPrerenderer(Profile* profile,
41 const GURL& url)
42 : profile_(profile),
43 prerender_url_(url) {
46 InstantSearchPrerenderer::~InstantSearchPrerenderer() {
47 if (prerender_handle_)
48 prerender_handle_->OnCancel();
51 // static
52 InstantSearchPrerenderer* InstantSearchPrerenderer::GetForProfile(
53 Profile* profile) {
54 DCHECK(profile);
55 InstantService* instant_service =
56 InstantServiceFactory::GetForProfile(profile);
57 return instant_service ? instant_service->instant_search_prerenderer() : NULL;
60 void InstantSearchPrerenderer::Init(
61 content::SessionStorageNamespace* session_storage_namespace,
62 const gfx::Size& size) {
63 // TODO(kmadhusu): Enable Instant for Incognito profile.
64 if (profile_->IsOffTheRecord())
65 return;
67 // Only cancel the old prerender after starting the new one, so if the URLs
68 // are the same, the underlying prerender will be reused.
69 scoped_ptr<prerender::PrerenderHandle> old_prerender_handle(
70 prerender_handle_.release());
71 prerender::PrerenderManager* prerender_manager =
72 prerender::PrerenderManagerFactory::GetForProfile(profile_);
73 if (prerender_manager) {
74 prerender_handle_.reset(prerender_manager->AddPrerenderForInstant(
75 prerender_url_, session_storage_namespace, size));
77 if (old_prerender_handle)
78 old_prerender_handle->OnCancel();
81 void InstantSearchPrerenderer::Cancel() {
82 if (!prerender_handle_)
83 return;
85 last_instant_suggestion_ = InstantSuggestion();
86 prerender_handle_->OnCancel();
87 prerender_handle_.reset();
90 void InstantSearchPrerenderer::Prerender(const InstantSuggestion& suggestion) {
91 if (!prerender_handle_)
92 return;
94 if (last_instant_suggestion_.text == suggestion.text)
95 return;
97 if (last_instant_suggestion_.text.empty() &&
98 !prerender_handle_->IsFinishedLoading())
99 return;
101 if (!prerender_contents())
102 return;
104 last_instant_suggestion_ = suggestion;
105 SearchTabHelper::FromWebContents(prerender_contents())->
106 SetSuggestionToPrefetch(suggestion);
109 void InstantSearchPrerenderer::Commit(
110 const base::string16& query,
111 const EmbeddedSearchRequestParams& params) {
112 DCHECK(prerender_handle_);
113 DCHECK(prerender_contents());
114 SearchTabHelper::FromWebContents(prerender_contents())->Submit(query, params);
117 bool InstantSearchPrerenderer::CanCommitQuery(
118 content::WebContents* source,
119 const base::string16& query) const {
120 if (!source || query.empty() || !prerender_handle_ ||
121 !prerender_handle_->IsFinishedLoading() ||
122 !prerender_contents() || !QueryMatchesPrefetch(query)) {
123 return false;
126 // InstantSearchPrerenderer can commit query to the prerendered page only if
127 // the underlying |source| page doesn't support Instant search.
128 return !PageSupportsInstantSearch(source);
131 bool InstantSearchPrerenderer::UsePrerenderedPage(
132 const GURL& url,
133 chrome::NavigateParams* params) {
134 base::string16 search_terms =
135 chrome::ExtractSearchTermsFromURL(profile_, url);
136 prerender::PrerenderManager* prerender_manager =
137 prerender::PrerenderManagerFactory::GetForProfile(profile_);
138 if (search_terms.empty() || !params->target_contents ||
139 !prerender_contents() || !prerender_manager ||
140 !QueryMatchesPrefetch(search_terms) ||
141 params->disposition != CURRENT_TAB) {
142 Cancel();
143 return false;
146 // Do not use prerendered page for renderer initiated search requests.
147 if (params->is_renderer_initiated &&
148 params->transition == ui::PAGE_TRANSITION_LINK) {
149 Cancel();
150 return false;
153 bool success = prerender_manager->MaybeUsePrerenderedPage(
154 prerender_contents()->GetURL(), params);
155 prerender_handle_.reset();
156 return success;
159 bool InstantSearchPrerenderer::IsAllowed(const AutocompleteMatch& match,
160 content::WebContents* source) const {
161 // We block prerendering for anything but search-type matches associated with
162 // the default search provider.
164 // This is more restrictive than necessary. All that's really needed to be
165 // able to successfully prerender is that the |destination_url| of |match| be
166 // from the same origin and path as the default search engine, and the params
167 // to be sent to the server be a subset of the params we can pass to the
168 // prerenderer. So for example, if we normally prerender search URLs like
169 // https://google.com/search?q=foo&x=bar, then any match with a URL like that,
170 // potentially with the q and/or x params omitted, is prerenderable.
172 // However, if the URL has other params _not_ normally in the prerendered URL,
173 // there's no way to pass them to the prerendered page, and worse, if the URL
174 // does something like specifying params in both the query and ref sections of
175 // the URL (as Google URLs often do), it can quickly become impossible to
176 // figure out how to correctly tease out the right param names and values to
177 // send. Rather than try and write parsing code to deal with all these kinds
178 // of cases, for various different search engines, including accommodating
179 // changing behavior over time, we do the simple restriction described above.
180 // This handles the by-far-the-most-common cases while still being simple and
181 // maintainable.
182 return source && AutocompleteMatch::IsSearchType(match.type) &&
183 MatchIsFromDefaultSearchProvider(match, profile_) &&
184 !PageSupportsInstantSearch(source);
187 content::WebContents* InstantSearchPrerenderer::prerender_contents() const {
188 return (prerender_handle_ && prerender_handle_->contents()) ?
189 prerender_handle_->contents()->prerender_contents() : NULL;
192 bool InstantSearchPrerenderer::QueryMatchesPrefetch(
193 const base::string16& query) const {
194 if (chrome::ShouldReuseInstantSearchBasePage())
195 return true;
196 return last_instant_suggestion_.text == query;