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