blob: 8625b58bb63930aaf6a7d31a9154cf05ca1e8bdd [file] [log] [blame]
[email protected]e41982a72012-11-20 07:16:511// Copyright 2012 The Chromium Authors. All rights reserved.
[email protected]7acfaf92012-07-11 15:51:592// 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/browser_instant_controller.h"
6
[email protected]0a46856e2013-04-24 00:33:027#include "base/bind.h"
sky4bdad242014-09-18 20:22:208#include "chrome/browser/infobars/infobar_service.h"
[email protected]7acfaf92012-07-11 15:51:599#include "chrome/browser/profiles/profile.h"
[email protected]0a46856e2013-04-24 00:33:0210#include "chrome/browser/search/instant_service.h"
11#include "chrome/browser/search/instant_service_factory.h"
[email protected]a7b8e43d2013-03-18 18:52:4312#include "chrome/browser/search/search.h"
[email protected]7acfaf92012-07-11 15:51:5913#include "chrome/browser/ui/browser.h"
[email protected]7acfaf92012-07-11 15:51:5914#include "chrome/browser/ui/browser_window.h"
[email protected]d57ce6a2014-07-03 15:39:2315#include "chrome/browser/ui/location_bar/location_bar.h"
[email protected]e97887c2013-12-11 01:27:3116#include "chrome/browser/ui/search/instant_search_prerenderer.h"
[email protected]4066a695d2013-06-20 14:08:5417#include "chrome/browser/ui/search/search_model.h"
[email protected]9d3d11702012-11-08 01:01:1218#include "chrome/browser/ui/search/search_tab_helper.h"
[email protected]e41982a72012-11-20 07:16:5119#include "chrome/browser/ui/tabs/tab_strip_model.h"
kmadhusu562c49c82014-11-18 02:08:0320#include "chrome/common/instant_types.h"
[email protected]0c9406632013-02-08 01:13:3321#include "chrome/common/url_constants.h"
blundell7dbd3792015-08-05 15:14:1922#include "components/omnibox/browser/omnibox_popup_model.h"
23#include "components/omnibox/browser/omnibox_view.h"
treib75d66152016-01-14 18:19:4024#include "content/public/browser/browser_thread.h"
mathp880d3282015-02-20 00:10:0525#include "content/public/browser/navigation_controller.h"
[email protected]0a46856e2013-04-24 00:33:0226#include "content/public/browser/render_process_host.h"
[email protected]233f0f962013-02-27 21:14:1927#include "content/public/browser/user_metrics.h"
[email protected]0a46856e2013-04-24 00:33:0228#include "content/public/browser/web_contents.h"
treib75d66152016-01-14 18:19:4029#include "content/public/browser/web_contents_user_data.h"
mathp880d3282015-02-20 00:10:0530#include "content/public/common/referrer.h"
31#include "ui/base/page_transition_types.h"
[email protected]c4b2af22014-05-11 19:48:5332
33// Helpers --------------------------------------------------------------------
[email protected]233f0f962013-02-27 21:14:1934
[email protected]e97887c2013-12-11 01:27:3135namespace {
36
37InstantSearchPrerenderer* GetInstantSearchPrerenderer(Profile* profile) {
38 DCHECK(profile);
39 InstantService* instant_service =
40 InstantServiceFactory::GetForProfile(profile);
41 return instant_service ? instant_service->instant_search_prerenderer() : NULL;
42}
43
treib75d66152016-01-14 18:19:4044// Helper class for posting a task to reload a tab, to avoid doing a re-entrant
45// navigation, since it can be called when starting a navigation. This class
46// makes sure to only execute the reload if the WebContents still exists.
47class TabReloader : public content::WebContentsUserData<TabReloader> {
48 public:
49 static void Reload(content::WebContents* web_contents) {
50 TabReloader::CreateForWebContents(web_contents);
51 }
52
53 private:
54 friend class content::WebContentsUserData<TabReloader>;
55
56 explicit TabReloader(content::WebContents* web_contents)
57 : web_contents_(web_contents), weak_ptr_factory_(this) {
58 content::BrowserThread::PostTask(
59 content::BrowserThread::UI,
60 FROM_HERE,
61 base::Bind(&TabReloader::ReloadImpl, weak_ptr_factory_.GetWeakPtr()));
62 }
63 ~TabReloader() override {}
64
65 void ReloadImpl() {
66 web_contents_->GetController().Reload(false);
67
68 // As the reload was not triggered by the user we don't want to close any
69 // infobars. We have to tell the InfoBarService after the reload,
70 // otherwise it would ignore this call when
71 // WebContentsObserver::DidStartNavigationToPendingEntry is invoked.
72 InfoBarService::FromWebContents(web_contents_)->set_ignore_next_reload();
73
74 web_contents_->RemoveUserData(UserDataKey());
75 }
76
77 content::WebContents* web_contents_;
78 base::WeakPtrFactory<TabReloader> weak_ptr_factory_;
79};
80
[email protected]e97887c2013-12-11 01:27:3181} // namespace
82
treib75d66152016-01-14 18:19:4083DEFINE_WEB_CONTENTS_USER_DATA_KEY(TabReloader);
84
[email protected]c4b2af22014-05-11 19:48:5385
86// BrowserInstantController ---------------------------------------------------
[email protected]7acfaf92012-07-11 15:51:5987
88BrowserInstantController::BrowserInstantController(Browser* browser)
[email protected]8a236702012-09-28 13:30:5789 : browser_(browser),
[email protected]777590052014-01-17 22:11:5490 instant_(this) {
[email protected]0b10c9ff2012-10-09 17:31:5591 browser_->search_model()->AddObserver(this);
[email protected]4ff347e2013-07-22 19:39:0092
93 InstantService* instant_service =
94 InstantServiceFactory::GetForProfile(profile());
[email protected]c8a118e2013-09-24 21:33:4095 instant_service->AddObserver(this);
[email protected]7acfaf92012-07-11 15:51:5996}
97
98BrowserInstantController::~BrowserInstantController() {
[email protected]0b10c9ff2012-10-09 17:31:5599 browser_->search_model()->RemoveObserver(this);
[email protected]4ff347e2013-07-22 19:39:00100
101 InstantService* instant_service =
102 InstantServiceFactory::GetForProfile(profile());
[email protected]c8a118e2013-09-24 21:33:40103 instant_service->RemoveObserver(this);
[email protected]0c9406632013-02-08 01:13:33104}
105
[email protected]413558cb2013-06-10 16:44:45106bool BrowserInstantController::OpenInstant(WindowOpenDisposition disposition,
107 const GURL& url) {
[email protected]e41982a72012-11-20 07:16:51108 // Unsupported dispositions.
[email protected]413558cb2013-06-10 16:44:45109 if (disposition == NEW_BACKGROUND_TAB || disposition == NEW_WINDOW ||
110 disposition == NEW_FOREGROUND_TAB)
[email protected]7acfaf92012-07-11 15:51:59111 return false;
[email protected]7acfaf92012-07-11 15:51:59112
[email protected]7acfaf92012-07-11 15:51:59113 // The omnibox currently doesn't use other dispositions, so we don't attempt
[email protected]c72226c82012-10-01 21:02:32114 // to handle them. If you hit this DCHECK file a bug and I'll (sky) add
[email protected]7acfaf92012-07-11 15:51:59115 // support for the new disposition.
[email protected]413558cb2013-06-10 16:44:45116 DCHECK(disposition == CURRENT_TAB) << disposition;
[email protected]c72226c82012-10-01 21:02:32117
[email protected]dcd0249872013-12-06 23:58:45118 const base::string16& search_terms =
sdefresne51bbec7b2015-08-03 14:18:13119 search::ExtractSearchTermsFromURL(profile(), url);
kmadhusu562c49c82014-11-18 02:08:03120 EmbeddedSearchRequestParams request_params(url);
[email protected]413558cb2013-06-10 16:44:45121 if (search_terms.empty())
122 return false;
123
[email protected]e97887c2013-12-11 01:27:31124 InstantSearchPrerenderer* prerenderer =
125 GetInstantSearchPrerenderer(profile());
[email protected]f028cf5b2014-01-24 07:36:03126 if (prerenderer) {
127 if (prerenderer->CanCommitQuery(GetActiveWebContents(), search_terms)) {
128 // Submit query to render the prefetched results. Browser will swap the
129 // prerendered contents with the active tab contents.
kmadhusu562c49c82014-11-18 02:08:03130 prerenderer->Commit(search_terms, request_params);
[email protected]f028cf5b2014-01-24 07:36:03131 return false;
132 } else {
133 prerenderer->Cancel();
134 }
[email protected]e97887c2013-12-11 01:27:31135 }
136
[email protected]50da1902014-02-14 02:40:19137 // If we will not be replacing search terms from this URL, don't send to
138 // InstantController.
sdefresne51bbec7b2015-08-03 14:18:13139 if (!search::IsQueryExtractionAllowedForURL(profile(), url))
[email protected]50da1902014-02-14 02:40:19140 return false;
kmadhusu562c49c82014-11-18 02:08:03141 return instant_.SubmitQuery(search_terms, request_params);
[email protected]7acfaf92012-07-11 15:51:59142}
143
[email protected]0c9406632013-02-08 01:13:33144Profile* BrowserInstantController::profile() const {
145 return browser_->profile();
146}
147
[email protected]cd533bf2012-12-04 19:14:59148content::WebContents* BrowserInstantController::GetActiveWebContents() const {
149 return browser_->tab_strip_model()->GetActiveWebContents();
[email protected]7acfaf92012-07-11 15:51:59150}
151
[email protected]e41982a72012-11-20 07:16:51152void BrowserInstantController::ActiveTabChanged() {
153 instant_.ActiveTabChanged();
154}
155
[email protected]3d6a8952012-12-14 03:18:07156void BrowserInstantController::TabDeactivated(content::WebContents* contents) {
157 instant_.TabDeactivated(contents);
[email protected]e97887c2013-12-11 01:27:31158
159 InstantSearchPrerenderer* prerenderer =
160 GetInstantSearchPrerenderer(profile());
161 if (prerenderer)
162 prerenderer->Cancel();
[email protected]3d6a8952012-12-14 03:18:07163}
164
[email protected]5ee671f2013-03-19 11:23:05165void BrowserInstantController::ModelChanged(
[email protected]165fe422013-03-27 06:34:03166 const SearchModel::State& old_state,
167 const SearchModel::State& new_state) {
[email protected]4066a695d2013-06-20 14:08:54168 if (old_state.mode != new_state.mode) {
169 const SearchMode& new_mode = new_state.mode;
[email protected]5ee671f2013-03-19 11:23:05170
[email protected]a780c7b22013-08-02 18:36:59171 // Record some actions corresponding to the mode change. Note that to get
172 // the full story, it's necessary to look at other UMA actions as well,
173 // such as tab switches.
174 if (new_mode.is_search_results())
[email protected]c4b2af22014-05-11 19:48:53175 content::RecordAction(base::UserMetricsAction("InstantExtended.ShowSRP"));
[email protected]a780c7b22013-08-02 18:36:59176 else if (new_mode.is_ntp())
[email protected]c4b2af22014-05-11 19:48:53177 content::RecordAction(base::UserMetricsAction("InstantExtended.ShowNTP"));
[email protected]5ee671f2013-03-19 11:23:05178
[email protected]4066a695d2013-06-20 14:08:54179 instant_.SearchModeChanged(old_state.mode, new_mode);
[email protected]c19ba1042013-03-11 17:17:13180 }
181
[email protected]4066a695d2013-06-20 14:08:54182 if (old_state.instant_support != new_state.instant_support)
183 instant_.InstantSupportChanged(new_state.instant_support);
[email protected]7acfaf92012-07-11 15:51:59184}
185
mathp880d3282015-02-20 00:10:05186void BrowserInstantController::DefaultSearchProviderChanged(
187 bool google_base_url_domain_changed) {
[email protected]0a46856e2013-04-24 00:33:02188 InstantService* instant_service =
[email protected]c8a118e2013-09-24 21:33:40189 InstantServiceFactory::GetForProfile(profile());
[email protected]0a46856e2013-04-24 00:33:02190 if (!instant_service)
191 return;
192
193 TabStripModel* tab_model = browser_->tab_strip_model();
194 int count = tab_model->count();
195 for (int index = 0; index < count; ++index) {
196 content::WebContents* contents = tab_model->GetWebContentsAt(index);
197 if (!contents)
198 continue;
199
[email protected]2309e912013-10-01 01:33:30200 // Send new search URLs to the renderer.
201 content::RenderProcessHost* rph = contents->GetRenderProcessHost();
202 instant_service->SendSearchURLsToRenderer(rph);
[email protected]0a46856e2013-04-24 00:33:02203
[email protected]2309e912013-10-01 01:33:30204 if (!instant_service->IsInstantProcess(rph->GetID()))
205 continue;
sky4bdad242014-09-18 20:22:20206
mathp880d3282015-02-20 00:10:05207 if (google_base_url_domain_changed &&
208 SearchTabHelper::FromWebContents(contents)->model()->mode().is_ntp()) {
209 // Replace the server NTP with the local NTP.
sdefresne51bbec7b2015-08-03 14:18:13210 content::NavigationController::LoadURLParams params(
211 search::GetLocalInstantURL(profile()));
mathp880d3282015-02-20 00:10:05212 params.should_replace_current_entry = true;
213 params.referrer = content::Referrer();
214 params.transition_type = ui::PAGE_TRANSITION_RELOAD;
215 contents->GetController().LoadURLWithParams(params);
216 } else {
217 // Reload the contents to ensure that it gets assigned to a
treib75d66152016-01-14 18:19:40218 // non-privileged renderer.
219 TabReloader::Reload(contents);
mathp880d3282015-02-20 00:10:05220 }
[email protected]0a46856e2013-04-24 00:33:02221 }
[email protected]0a46856e2013-04-24 00:33:02222}