blob: b9ae09679f37a877b76d1ac93bd91c65989ed32e [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]7acfaf92012-07-11 15:51:597#include "chrome/browser/extensions/extension_service.h"
[email protected]fb8fdf12012-08-21 16:28:208#include "chrome/browser/prefs/pref_service.h"
[email protected]7acfaf92012-07-11 15:51:599#include "chrome/browser/profiles/profile.h"
[email protected]a6827652012-11-20 23:41:0810#include "chrome/browser/themes/theme_service.h"
11#include "chrome/browser/themes/theme_service_factory.h"
[email protected]7acfaf92012-07-11 15:51:5912#include "chrome/browser/ui/browser.h"
[email protected]7acfaf92012-07-11 15:51:5913#include "chrome/browser/ui/browser_window.h"
14#include "chrome/browser/ui/omnibox/location_bar.h"
[email protected]e41982a72012-11-20 07:16:5115#include "chrome/browser/ui/search/search.h"
[email protected]9d3d11702012-11-08 01:01:1216#include "chrome/browser/ui/search/search_tab_helper.h"
[email protected]7acfaf92012-07-11 15:51:5917#include "chrome/browser/ui/tab_contents/tab_contents.h"
[email protected]e41982a72012-11-20 07:16:5118#include "chrome/browser/ui/tabs/tab_strip_model.h"
[email protected]7acfaf92012-07-11 15:51:5919#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
20#include "chrome/common/chrome_notification_types.h"
21#include "chrome/common/pref_names.h"
22#include "content/public/browser/notification_service.h"
[email protected]a6827652012-11-20 23:41:0823#include "grit/theme_resources.h"
24#include "ui/gfx/color_utils.h"
25#include "ui/gfx/sys_color_change_listener.h"
26
[email protected]7acfaf92012-07-11 15:51:5927
[email protected]7acfaf92012-07-11 15:51:5928namespace chrome {
29
30////////////////////////////////////////////////////////////////////////////////
31// BrowserInstantController, public:
32
33BrowserInstantController::BrowserInstantController(Browser* browser)
[email protected]8a236702012-09-28 13:30:5734 : browser_(browser),
[email protected]e41982a72012-11-20 07:16:5135 instant_(ALLOW_THIS_IN_INITIALIZER_LIST(this),
36 chrome::search::IsInstantExtendedAPIEnabled(browser->profile())),
[email protected]a6827652012-11-20 23:41:0837 instant_unload_handler_(browser),
38 initialized_theme_info_(false),
39 theme_area_height_(0) {
[email protected]7acfaf92012-07-11 15:51:5940 profile_pref_registrar_.Init(browser_->profile()->GetPrefs());
[email protected]0b3fa502012-11-21 13:57:4641 profile_pref_registrar_.Add(
42 prefs::kInstantEnabled,
43 base::Bind(&BrowserInstantController::ResetInstant,
44 base::Unretained(this)));
45 ResetInstant();
[email protected]0b10c9ff2012-10-09 17:31:5546 browser_->search_model()->AddObserver(this);
[email protected]a6827652012-11-20 23:41:0847
48#if defined(ENABLE_THEMES)
49 // Listen for theme installation.
50 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
51 content::Source<ThemeService>(
52 ThemeServiceFactory::GetForProfile(browser_->profile())));
53#endif // defined(ENABLE_THEMES)
[email protected]7acfaf92012-07-11 15:51:5954}
55
56BrowserInstantController::~BrowserInstantController() {
[email protected]0b10c9ff2012-10-09 17:31:5557 browser_->search_model()->RemoveObserver(this);
[email protected]7acfaf92012-07-11 15:51:5958}
59
[email protected]e41982a72012-11-20 07:16:5160bool BrowserInstantController::IsInstantEnabled(Profile* profile) {
61 return profile && !profile->IsOffTheRecord() && profile->GetPrefs() &&
62 profile->GetPrefs()->GetBoolean(prefs::kInstantEnabled);
63}
64
65void BrowserInstantController::RegisterUserPrefs(PrefService* prefs) {
66 prefs->RegisterBooleanPref(prefs::kInstantConfirmDialogShown, false,
67 PrefService::SYNCABLE_PREF);
68 prefs->RegisterBooleanPref(prefs::kInstantEnabled, false,
69 PrefService::SYNCABLE_PREF);
70}
71
[email protected]7acfaf92012-07-11 15:51:5972bool BrowserInstantController::OpenInstant(WindowOpenDisposition disposition) {
[email protected]e41982a72012-11-20 07:16:5173 // Unsupported dispositions.
74 if (disposition == NEW_BACKGROUND_TAB || disposition == NEW_WINDOW)
[email protected]7acfaf92012-07-11 15:51:5975 return false;
[email protected]7acfaf92012-07-11 15:51:5976
[email protected]7acfaf92012-07-11 15:51:5977 // The omnibox currently doesn't use other dispositions, so we don't attempt
[email protected]c72226c82012-10-01 21:02:3278 // to handle them. If you hit this DCHECK file a bug and I'll (sky) add
[email protected]7acfaf92012-07-11 15:51:5979 // support for the new disposition.
[email protected]c72226c82012-10-01 21:02:3280 DCHECK(disposition == CURRENT_TAB ||
81 disposition == NEW_FOREGROUND_TAB) << disposition;
82
[email protected]e41982a72012-11-20 07:16:5183 return instant_.CommitIfCurrent(disposition == CURRENT_TAB ?
[email protected]c72226c82012-10-01 21:02:3284 INSTANT_COMMIT_PRESSED_ENTER : INSTANT_COMMIT_PRESSED_ALT_ENTER);
[email protected]7acfaf92012-07-11 15:51:5985}
86
[email protected]cd533bf2012-12-04 19:14:5987void BrowserInstantController::CommitInstant(content::WebContents* preview,
[email protected]c72226c82012-10-01 21:02:3288 bool in_new_tab) {
89 if (in_new_tab) {
90 // TabStripModel takes ownership of |preview|.
[email protected]cd533bf2012-12-04 19:14:5991 browser_->tab_strip_model()->AddWebContents(preview, -1,
[email protected]e41982a72012-11-20 07:16:5192 instant_.last_transition_type(), TabStripModel::ADD_ACTIVE);
[email protected]c72226c82012-10-01 21:02:3293 } else {
[email protected]cd533bf2012-12-04 19:14:5994 content::WebContents* active_tab =
95 browser_->tab_strip_model()->GetActiveWebContents();
96 int index = browser_->tab_strip_model()->GetIndexOfWebContents(active_tab);
[email protected]c72226c82012-10-01 21:02:3297 DCHECK_NE(TabStripModel::kNoTab, index);
98 // TabStripModel takes ownership of |preview|.
[email protected]cd533bf2012-12-04 19:14:5999 browser_->tab_strip_model()->ReplaceTabContentsAt(index,
100 TabContents::FromWebContents(preview));
[email protected]c72226c82012-10-01 21:02:32101 // InstantUnloadHandler takes ownership of |active_tab|.
102 instant_unload_handler_.RunUnloadListenersOrDestroy(active_tab, index);
[email protected]7acfaf92012-07-11 15:51:59103
[email protected]cd533bf2012-12-04 19:14:59104 GURL url = preview->GetURL();
[email protected]c72226c82012-10-01 21:02:32105 DCHECK(browser_->profile()->GetExtensionService());
106 if (browser_->profile()->GetExtensionService()->IsInstalledApp(url)) {
107 AppLauncherHandler::RecordAppLaunchType(
108 extension_misc::APP_LAUNCH_OMNIBOX_INSTANT);
109 }
[email protected]7acfaf92012-07-11 15:51:59110 }
111}
112
[email protected]93b73832012-10-18 20:18:38113void BrowserInstantController::SetInstantSuggestion(
114 const InstantSuggestion& suggestion) {
[email protected]7acfaf92012-07-11 15:51:59115 if (browser_->window()->GetLocationBar())
[email protected]93b73832012-10-18 20:18:38116 browser_->window()->GetLocationBar()->SetInstantSuggestion(suggestion);
[email protected]7acfaf92012-07-11 15:51:59117}
118
119gfx::Rect BrowserInstantController::GetInstantBounds() {
120 return browser_->window()->GetInstantBounds();
121}
122
123void BrowserInstantController::InstantPreviewFocused() {
124 // NOTE: This is only invoked on aura.
[email protected]cd533bf2012-12-04 19:14:59125 browser_->window()->WebContentsFocused(instant_.GetPreviewContents());
[email protected]7acfaf92012-07-11 15:51:59126}
127
[email protected]cd533bf2012-12-04 19:14:59128content::WebContents* BrowserInstantController::GetActiveWebContents() const {
129 return browser_->tab_strip_model()->GetActiveWebContents();
[email protected]7acfaf92012-07-11 15:51:59130}
131
[email protected]e41982a72012-11-20 07:16:51132void BrowserInstantController::ActiveTabChanged() {
133 instant_.ActiveTabChanged();
134}
135
[email protected]a6827652012-11-20 23:41:08136void BrowserInstantController::SetContentHeight(int height) {
137 OnThemeAreaHeightChanged(height);
138}
139
140void BrowserInstantController::UpdateThemeInfoForPreview() {
141 // Update theme background info and theme area height.
142 // Initialize |theme_info| if necessary.
143 // |OnThemeChanged| also updates theme area height if necessary.
144 if (!initialized_theme_info_)
145 OnThemeChanged(ThemeServiceFactory::GetForProfile(browser_->profile()));
146 else
147 OnThemeChanged(NULL);
148}
149
[email protected]0b3fa502012-11-21 13:57:46150void BrowserInstantController::ResetInstant() {
[email protected]e41982a72012-11-20 07:16:51151 instant_.SetInstantEnabled(IsInstantEnabled(browser_->profile()));
[email protected]749ce882012-11-16 04:18:01152}
153
[email protected]7acfaf92012-07-11 15:51:59154////////////////////////////////////////////////////////////////////////////////
[email protected]0b10c9ff2012-10-09 17:31:55155// BrowserInstantController, search::SearchModelObserver implementation:
156
157void BrowserInstantController::ModeChanged(const search::Mode& old_mode,
158 const search::Mode& new_mode) {
[email protected]a6827652012-11-20 23:41:08159 // If mode is now |NTP|, send theme-related information to instant.
160 if (new_mode.is_ntp())
161 UpdateThemeInfoForPreview();
162
[email protected]e41982a72012-11-20 07:16:51163 instant_.SearchModeChanged(old_mode, new_mode);
[email protected]7acfaf92012-07-11 15:51:59164}
165
[email protected]a6827652012-11-20 23:41:08166////////////////////////////////////////////////////////////////////////////////
167// BrowserInstantController, content::NotificationObserver implementation:
168
169void BrowserInstantController::Observe(
170 int type,
171 const content::NotificationSource& source,
172 const content::NotificationDetails& details) {
173#if defined(ENABLE_THEMES)
174 DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type);
175 OnThemeChanged(content::Source<ThemeService>(source).ptr());
176#endif // defined(ENABLE_THEMES)
177}
178
179void BrowserInstantController::OnThemeChanged(ThemeService* theme_service) {
180 if (theme_service) { // Get theme information from theme service.
181 theme_info_ = ThemeBackgroundInfo();
182
183 // Set theme background color.
184 SkColor background_color =
185 theme_service->GetColor(ThemeService::COLOR_NTP_BACKGROUND);
186 if (gfx::IsInvertedColorScheme())
187 background_color = color_utils::InvertColor(background_color);
188 theme_info_.color_r = SkColorGetR(background_color);
189 theme_info_.color_g = SkColorGetG(background_color);
190 theme_info_.color_b = SkColorGetB(background_color);
191 theme_info_.color_a = SkColorGetA(background_color);
192
193 if (theme_service->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
194 // Set theme id for theme background image url.
195 theme_info_.theme_id = theme_service->GetThemeID();
196
197 // Set theme background image horizontal alignment.
198 int alignment = 0;
199 theme_service->GetDisplayProperty(ThemeService::NTP_BACKGROUND_ALIGNMENT,
200 &alignment);
201 if (alignment & ThemeService::ALIGN_LEFT) {
202 theme_info_.image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_LEFT;
203 } else if (alignment & ThemeService::ALIGN_RIGHT) {
204 theme_info_.image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_RIGHT;
205 } else { // ALIGN_CENTER
206 theme_info_.image_horizontal_alignment =
207 THEME_BKGRND_IMAGE_ALIGN_CENTER;
208 }
209
210 // Set theme background image vertical alignment.
211 if (alignment & ThemeService::ALIGN_TOP)
212 theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_TOP;
213 else if (alignment & ThemeService::ALIGN_BOTTOM)
214 theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_BOTTOM;
215 else // ALIGN_CENTER
216 theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_CENTER;
217
218 // Set theme background image tiling.
219 int tiling = 0;
220 theme_service->GetDisplayProperty(ThemeService::NTP_BACKGROUND_TILING,
221 &tiling);
222 switch (tiling) {
223 case ThemeService::NO_REPEAT:
224 theme_info_.image_tiling = THEME_BKGRND_IMAGE_NO_REPEAT;
225 break;
226 case ThemeService::REPEAT_X:
227 theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT_X;
228 break;
229 case ThemeService::REPEAT_Y:
230 theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT_Y;
231 break;
232 case ThemeService::REPEAT:
233 theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT;
234 break;
235 }
236
237 // Set theme background image height.
238 gfx::ImageSkia* image = theme_service->GetImageSkiaNamed(
239 IDR_THEME_NTP_BACKGROUND);
240 DCHECK(image);
241 theme_info_.image_height = image->height();
242 }
243
244 initialized_theme_info_ = true;
245 }
246
247 DCHECK(initialized_theme_info_);
248
249 if (browser_->search_model()->mode().is_ntp()) {
250 instant_.ThemeChanged(theme_info_);
251
252 // Theme area height is only sent to preview for non-top-aligned images;
253 // new theme may have a different alignment that requires preview to know
254 // theme area height.
255 OnThemeAreaHeightChanged(theme_area_height_);
256 }
257}
258
259void BrowserInstantController::OnThemeAreaHeightChanged(int height) {
260 theme_area_height_ = height;
261
262 // Notify preview only if mode is |NTP| and theme background image is not top-
263 // aligned; top-aligned images don't need theme area height to determine which
264 // part of the image overlay should draw, 'cos the origin is top-left.
265 if (!browser_->search_model()->mode().is_ntp() ||
266 theme_info_.theme_id.empty() ||
267 theme_info_.image_vertical_alignment == THEME_BKGRND_IMAGE_ALIGN_TOP) {
268 return;
269 }
270 instant_.ThemeAreaHeightChanged(theme_area_height_);
271}
272
[email protected]7acfaf92012-07-11 15:51:59273} // namespace chrome