• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/ui/search/instant_search_prerenderer.h"
6 
7 #include "chrome/browser/autocomplete/autocomplete_match.h"
8 #include "chrome/browser/prerender/prerender_handle.h"
9 #include "chrome/browser/prerender/prerender_manager.h"
10 #include "chrome/browser/prerender/prerender_manager_factory.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/search/instant_service.h"
13 #include "chrome/browser/search/instant_service_factory.h"
14 #include "chrome/browser/search/search.h"
15 #include "chrome/browser/ui/browser_navigator.h"
16 #include "chrome/browser/ui/search/search_tab_helper.h"
17 
18 namespace {
19 
20 // Returns true if the underlying page supports Instant search.
PageSupportsInstantSearch(content::WebContents * contents)21 bool PageSupportsInstantSearch(content::WebContents* contents) {
22   // Search results page supports Instant search.
23   return SearchTabHelper::FromWebContents(contents)->IsSearchResultsPage();
24 }
25 
26 }  // namespace
27 
InstantSearchPrerenderer(Profile * profile,const GURL & url)28 InstantSearchPrerenderer::InstantSearchPrerenderer(Profile* profile,
29                                                    const GURL& url)
30     : profile_(profile),
31       prerender_url_(url) {
32 }
33 
~InstantSearchPrerenderer()34 InstantSearchPrerenderer::~InstantSearchPrerenderer() {
35   if (prerender_handle_)
36     prerender_handle_->OnCancel();
37 }
38 
39 // static
GetForProfile(Profile * profile)40 InstantSearchPrerenderer* InstantSearchPrerenderer::GetForProfile(
41     Profile* profile) {
42   DCHECK(profile);
43   InstantService* instant_service =
44       InstantServiceFactory::GetForProfile(profile);
45   return instant_service ? instant_service->instant_search_prerenderer() : NULL;
46 }
47 
Init(const content::SessionStorageNamespaceMap & session_storage_namespace_map,const gfx::Size & size)48 void InstantSearchPrerenderer::Init(
49     const content::SessionStorageNamespaceMap& session_storage_namespace_map,
50     const gfx::Size& size) {
51   // TODO(kmadhusu): Enable Instant for Incognito profile.
52   if (profile_->IsOffTheRecord())
53     return;
54 
55   // Only cancel the old prerender after starting the new one, so if the URLs
56   // are the same, the underlying prerender will be reused.
57   scoped_ptr<prerender::PrerenderHandle> old_prerender_handle(
58       prerender_handle_.release());
59   prerender::PrerenderManager* prerender_manager =
60       prerender::PrerenderManagerFactory::GetForProfile(profile_);
61   if (prerender_manager) {
62     content::SessionStorageNamespace* session_storage_namespace = NULL;
63     content::SessionStorageNamespaceMap::const_iterator it =
64         session_storage_namespace_map.find(std::string());
65     if (it != session_storage_namespace_map.end())
66       session_storage_namespace = it->second.get();
67 
68     prerender_handle_.reset(prerender_manager->AddPrerenderForInstant(
69         prerender_url_, session_storage_namespace, size));
70   }
71   if (old_prerender_handle)
72     old_prerender_handle->OnCancel();
73 }
74 
Cancel()75 void InstantSearchPrerenderer::Cancel() {
76   if (!prerender_handle_)
77     return;
78 
79   last_instant_suggestion_ = InstantSuggestion();
80   prerender_handle_->OnCancel();
81   prerender_handle_.reset();
82 }
83 
Prerender(const InstantSuggestion & suggestion)84 void InstantSearchPrerenderer::Prerender(const InstantSuggestion& suggestion) {
85   if (!prerender_handle_)
86     return;
87 
88   if (last_instant_suggestion_.text == suggestion.text)
89     return;
90 
91   if (last_instant_suggestion_.text.empty() &&
92       !prerender_handle_->IsFinishedLoading())
93     return;
94 
95   if (!prerender_contents())
96     return;
97 
98   last_instant_suggestion_ = suggestion;
99   SearchTabHelper::FromWebContents(prerender_contents())->
100       SetSuggestionToPrefetch(suggestion);
101 }
102 
Commit(const string16 & query)103 void InstantSearchPrerenderer::Commit(const string16& query) {
104   DCHECK(prerender_handle_);
105   DCHECK(prerender_contents());
106   SearchTabHelper::FromWebContents(prerender_contents())->Submit(query);
107 }
108 
CanCommitQuery(content::WebContents * source,const string16 & query) const109 bool InstantSearchPrerenderer::CanCommitQuery(content::WebContents* source,
110                                               const string16& query) const {
111   if (!source || query.empty())
112     return false;
113 
114   if (last_instant_suggestion_.text != query)
115     return false;
116 
117   if (!prerender_handle_ || !prerender_contents())
118     return false;
119 
120   // InstantSearchPrerenderer can commit query to the prerendered page only if
121   // the underlying |source| page doesn't support Instant search.
122   return !PageSupportsInstantSearch(source);
123 }
124 
UsePrerenderedPage(const GURL & url,chrome::NavigateParams * params)125 bool InstantSearchPrerenderer::UsePrerenderedPage(
126     const GURL& url,
127     chrome::NavigateParams* params) {
128   string16 search_terms = chrome::GetSearchTermsFromURL(profile_, url);
129   prerender::PrerenderManager* prerender_manager =
130       prerender::PrerenderManagerFactory::GetForProfile(profile_);
131   if (search_terms.empty() ||
132       !params->target_contents ||
133       last_instant_suggestion_.text != search_terms ||
134       !prerender_contents() ||
135       !prerender_manager) {
136     Cancel();
137     return false;
138   }
139 
140   bool success = prerender_manager->MaybeUsePrerenderedPage(
141       prerender_contents()->GetURL(), params);
142   prerender_handle_.reset();
143   return success;
144 }
145 
IsAllowed(const AutocompleteMatch & match,content::WebContents * source) const146 bool InstantSearchPrerenderer::IsAllowed(const AutocompleteMatch& match,
147                                          content::WebContents* source) const {
148   return source && AutocompleteMatch::IsSearchType(match.type) &&
149       !PageSupportsInstantSearch(source);
150 }
151 
prerender_contents() const152 content::WebContents* InstantSearchPrerenderer::prerender_contents() const {
153   return (prerender_handle_ && prerender_handle_->contents()) ?
154       prerender_handle_->contents()->prerender_contents() : NULL;
155 }
156