blob: e58bcb2cf5b83bd5a78724a7cb96904626be2cf8 [file] [log] [blame]
[email protected]7acfaf92012-07-11 15:51:591// Copyright (c) 2012 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/browser_instant_controller.h"
6
7#include "chrome/browser/browser_shutdown.h"
8#include "chrome/browser/extensions/extension_service.h"
9#include "chrome/browser/instant/instant_controller.h"
[email protected]fb8fdf12012-08-21 16:28:2010#include "chrome/browser/prefs/pref_service.h"
[email protected]7acfaf92012-07-11 15:51:5911#include "chrome/browser/profiles/profile.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/browser/ui/browser_tabstrip.h"
14#include "chrome/browser/ui/browser_window.h"
15#include "chrome/browser/ui/omnibox/location_bar.h"
[email protected]0b10c9ff2012-10-09 17:31:5516#include "chrome/browser/ui/search/search_model.h"
[email protected]9d3d11702012-11-08 01:01:1217#include "chrome/browser/ui/search/search_tab_helper.h"
[email protected]7acfaf92012-07-11 15:51:5918#include "chrome/browser/ui/tabs/tab_strip_model.h"
19#include "chrome/browser/ui/tab_contents/tab_contents.h"
20#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
21#include "chrome/common/chrome_notification_types.h"
22#include "chrome/common/pref_names.h"
23#include "content/public/browser/notification_service.h"
[email protected]7acfaf92012-07-11 15:51:5924#include "content/public/browser/web_contents.h"
25
[email protected]9d3d11702012-11-08 01:01:1226namespace {
27
28// Returns true iff the search model for |tab| is in an NTP state, that is, a
29// state in which the Instant overlay may be showing custom NTP content in
30// EXTENDED mode.
[email protected]8e707792012-11-13 10:32:1231bool IsSearchModelNTP(content::WebContents* tab) {
32 if (!tab)
[email protected]9d3d11702012-11-08 01:01:1233 return false;
[email protected]9d3d11702012-11-08 01:01:1234 chrome::search::SearchModel* model =
[email protected]8e707792012-11-13 10:32:1235 chrome::search::SearchTabHelper::FromWebContents(tab)->model();
[email protected]9d3d11702012-11-08 01:01:1236 return model && model->mode().is_ntp();
37}
38
39} // namespace
40
[email protected]7acfaf92012-07-11 15:51:5941namespace chrome {
42
43////////////////////////////////////////////////////////////////////////////////
44// BrowserInstantController, public:
45
46BrowserInstantController::BrowserInstantController(Browser* browser)
[email protected]8a236702012-09-28 13:30:5747 : browser_(browser),
[email protected]c72226c82012-10-01 21:02:3248 instant_unload_handler_(browser) {
[email protected]7acfaf92012-07-11 15:51:5949 profile_pref_registrar_.Init(browser_->profile()->GetPrefs());
50 profile_pref_registrar_.Add(prefs::kInstantEnabled, this);
[email protected]c55e3b82012-08-09 15:27:0551 ResetInstant();
[email protected]7acfaf92012-07-11 15:51:5952 browser_->tab_strip_model()->AddObserver(this);
[email protected]0b10c9ff2012-10-09 17:31:5553 browser_->search_model()->AddObserver(this);
[email protected]7acfaf92012-07-11 15:51:5954}
55
56BrowserInstantController::~BrowserInstantController() {
57 browser_->tab_strip_model()->RemoveObserver(this);
[email protected]0b10c9ff2012-10-09 17:31:5558 browser_->search_model()->RemoveObserver(this);
[email protected]7acfaf92012-07-11 15:51:5959}
60
61bool BrowserInstantController::OpenInstant(WindowOpenDisposition disposition) {
[email protected]c55e3b82012-08-09 15:27:0562 // NEW_BACKGROUND_TAB results in leaving the omnibox open, so we don't attempt
63 // to use the Instant preview.
64 if (!instant() || !instant_->IsCurrent() || disposition == NEW_BACKGROUND_TAB)
[email protected]7acfaf92012-07-11 15:51:5965 return false;
[email protected]7acfaf92012-07-11 15:51:5966
[email protected]7acfaf92012-07-11 15:51:5967 // The omnibox currently doesn't use other dispositions, so we don't attempt
[email protected]c72226c82012-10-01 21:02:3268 // to handle them. If you hit this DCHECK file a bug and I'll (sky) add
[email protected]7acfaf92012-07-11 15:51:5969 // support for the new disposition.
[email protected]c72226c82012-10-01 21:02:3270 DCHECK(disposition == CURRENT_TAB ||
71 disposition == NEW_FOREGROUND_TAB) << disposition;
72
73 instant_->CommitCurrentPreview(disposition == CURRENT_TAB ?
74 INSTANT_COMMIT_PRESSED_ENTER : INSTANT_COMMIT_PRESSED_ALT_ENTER);
75 return true;
[email protected]7acfaf92012-07-11 15:51:5976}
77
[email protected]c72226c82012-10-01 21:02:3278void BrowserInstantController::CommitInstant(TabContents* preview,
79 bool in_new_tab) {
80 if (in_new_tab) {
81 // TabStripModel takes ownership of |preview|.
82 browser_->tab_strip_model()->AddTabContents(preview, -1,
83 instant_->last_transition_type(), TabStripModel::ADD_ACTIVE);
84 } else {
[email protected]59253a652012-11-20 00:17:2685 TabContents* active_tab =
86 browser_->tab_strip_model()->GetActiveTabContents();
[email protected]c72226c82012-10-01 21:02:3287 int index = browser_->tab_strip_model()->GetIndexOfTabContents(active_tab);
88 DCHECK_NE(TabStripModel::kNoTab, index);
89 // TabStripModel takes ownership of |preview|.
90 browser_->tab_strip_model()->ReplaceTabContentsAt(index, preview);
91 // InstantUnloadHandler takes ownership of |active_tab|.
92 instant_unload_handler_.RunUnloadListenersOrDestroy(active_tab, index);
[email protected]7acfaf92012-07-11 15:51:5993
[email protected]c72226c82012-10-01 21:02:3294 GURL url = preview->web_contents()->GetURL();
95 DCHECK(browser_->profile()->GetExtensionService());
96 if (browser_->profile()->GetExtensionService()->IsInstalledApp(url)) {
97 AppLauncherHandler::RecordAppLaunchType(
98 extension_misc::APP_LAUNCH_OMNIBOX_INSTANT);
99 }
[email protected]7acfaf92012-07-11 15:51:59100 }
101}
102
[email protected]93b73832012-10-18 20:18:38103void BrowserInstantController::SetInstantSuggestion(
104 const InstantSuggestion& suggestion) {
[email protected]7acfaf92012-07-11 15:51:59105 if (browser_->window()->GetLocationBar())
[email protected]93b73832012-10-18 20:18:38106 browser_->window()->GetLocationBar()->SetInstantSuggestion(suggestion);
[email protected]7acfaf92012-07-11 15:51:59107}
108
109gfx::Rect BrowserInstantController::GetInstantBounds() {
110 return browser_->window()->GetInstantBounds();
111}
112
113void BrowserInstantController::InstantPreviewFocused() {
114 // NOTE: This is only invoked on aura.
115 browser_->window()->WebContentsFocused(
116 instant_->GetPreviewContents()->web_contents());
117}
118
[email protected]c55e3b82012-08-09 15:27:05119TabContents* BrowserInstantController::GetActiveTabContents() const {
[email protected]59253a652012-11-20 00:17:26120 return browser_->tab_strip_model()->GetActiveTabContents();
[email protected]7acfaf92012-07-11 15:51:59121}
122
123////////////////////////////////////////////////////////////////////////////////
[email protected]a6a7ced2012-11-01 17:24:18124// BrowserInstantController, PrefObserver implementation:
[email protected]7acfaf92012-07-11 15:51:59125
[email protected]a6a7ced2012-11-01 17:24:18126void BrowserInstantController::OnPreferenceChanged(
127 PrefServiceBase* service,
128 const std::string& pref_name) {
129 DCHECK_EQ(std::string(prefs::kInstantEnabled), pref_name);
[email protected]c55e3b82012-08-09 15:27:05130 ResetInstant();
[email protected]7acfaf92012-07-11 15:51:59131}
132
133////////////////////////////////////////////////////////////////////////////////
134// BrowserInstantController, TabStripModelObserver implementation:
135
[email protected]9d3d11702012-11-08 01:01:12136void BrowserInstantController::ActiveTabChanged(
[email protected]8e707792012-11-13 10:32:12137 content::WebContents* old_contents,
138 content::WebContents* new_contents,
[email protected]9d3d11702012-11-08 01:01:12139 int index,
140 bool user_gesture) {
141 if (instant()) {
142 const bool old_is_ntp = IsSearchModelNTP(old_contents);
143 const bool new_is_ntp = IsSearchModelNTP(new_contents);
144 // Do not hide Instant if switching from an NTP to another NTP since that
145 // would cause custom NTP content to flicker.
146 if (!(old_is_ntp && new_is_ntp))
147 instant()->Hide();
148 }
[email protected]7acfaf92012-07-11 15:51:59149}
150
[email protected]749ce882012-11-16 04:18:01151void BrowserInstantController::TabStripEmpty() {
152 instant_.reset();
153}
154
[email protected]7acfaf92012-07-11 15:51:59155////////////////////////////////////////////////////////////////////////////////
[email protected]0b10c9ff2012-10-09 17:31:55156// BrowserInstantController, search::SearchModelObserver implementation:
157
158void BrowserInstantController::ModeChanged(const search::Mode& old_mode,
159 const search::Mode& new_mode) {
[email protected]2989f002012-11-15 05:33:20160 if (instant())
161 instant_->OnActiveTabModeChanged(new_mode);
[email protected]0b10c9ff2012-10-09 17:31:55162}
163
164////////////////////////////////////////////////////////////////////////////////
[email protected]7acfaf92012-07-11 15:51:59165// BrowserInstantController, private:
166
[email protected]c55e3b82012-08-09 15:27:05167void BrowserInstantController::ResetInstant() {
[email protected]b67d0a42012-09-04 20:57:35168 instant_.reset(
169 !browser_shutdown::ShuttingDownWithoutClosingBrowsers() &&
170 browser_->is_type_tabbed() ?
171 InstantController::CreateInstant(browser_->profile(), this) : NULL);
[email protected]e4e15dc2012-10-18 03:22:50172
173 // Notify any observers that they need to reset.
174 content::NotificationService::current()->Notify(
175 chrome::NOTIFICATION_BROWSER_INSTANT_RESET,
176 content::Source<BrowserInstantController>(this),
177 content::NotificationService::NoDetails());
[email protected]7acfaf92012-07-11 15:51:59178}
179
180} // namespace chrome