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