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