Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(381)

Side by Side Diff: chrome/browser/ui/browser_instant_controller.cc

Issue 12386019: Instant: Use only one hidden WebContents per profile. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/browser_instant_controller.h" 5 #include "chrome/browser/ui/browser_instant_controller.h"
6 6
7 #include "base/prefs/pref_service.h"
8 #include "chrome/browser/extensions/extension_service.h" 7 #include "chrome/browser/extensions/extension_service.h"
9 #include "chrome/browser/extensions/extension_web_ui.h" 8 #include "chrome/browser/extensions/extension_web_ui.h"
10 #include "chrome/browser/prefs/pref_registry_syncable.h" 9 #include "chrome/browser/instant/instant_controller.h"
11 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/themes/theme_properties.h"
13 #include "chrome/browser/themes/theme_service.h"
14 #include "chrome/browser/themes/theme_service_factory.h"
15 #include "chrome/browser/ui/bookmarks/bookmark_bar_constants.h"
16 #include "chrome/browser/ui/browser.h" 11 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_window.h" 12 #include "chrome/browser/ui/browser_window.h"
18 #include "chrome/browser/ui/omnibox/location_bar.h" 13 #include "chrome/browser/ui/omnibox/location_bar.h"
19 #include "chrome/browser/ui/omnibox/omnibox_view.h" 14 #include "chrome/browser/ui/omnibox/omnibox_view.h"
20 #include "chrome/browser/ui/search/search.h"
21 #include "chrome/browser/ui/search/search_tab_helper.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h" 15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
23 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h" 16 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
24 #include "chrome/common/chrome_notification_types.h" 17 #include "chrome/common/chrome_notification_types.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/common/url_constants.h" 18 #include "chrome/common/url_constants.h"
27 #include "content/public/browser/notification_service.h" 19 #include "content/public/browser/notification_service.h"
28 #include "content/public/browser/user_metrics.h" 20 #include "content/public/browser/user_metrics.h"
29 #include "grit/theme_resources.h" 21 #include "content/public/browser/web_contents.h"
30 #include "ui/gfx/color_utils.h"
31 #include "ui/gfx/sys_color_change_listener.h"
32 22
33 using content::UserMetricsAction; 23 using content::UserMetricsAction;
34 24
35 namespace {
36
37 const char* GetInstantPrefName(Profile* profile) {
38 return chrome::search::IsInstantExtendedAPIEnabled(profile) ?
39 prefs::kInstantExtendedEnabled : prefs::kInstantEnabled;
40 }
41
42 } // namespace
43
44 namespace chrome { 25 namespace chrome {
45 26
46 ////////////////////////////////////////////////////////////////////////////////
47 // BrowserInstantController, public:
48
49 BrowserInstantController::BrowserInstantController(Browser* browser) 27 BrowserInstantController::BrowserInstantController(Browser* browser)
50 : browser_(browser), 28 : browser_(browser),
51 instant_(ALLOW_THIS_IN_INITIALIZER_LIST(this), 29 instant_(InstantController::GetInstance(
52 chrome::search::IsInstantExtendedAPIEnabled(profile())), 30 ALLOW_THIS_IN_INITIALIZER_LIST(this), browser->profile())),
53 instant_unload_handler_(browser), 31 instant_unload_handler_(browser) {
54 initialized_theme_info_(false) {
55 profile_pref_registrar_.Init(profile()->GetPrefs());
56 profile_pref_registrar_.Add(
57 GetInstantPrefName(profile()),
58 base::Bind(&BrowserInstantController::ResetInstant,
59 base::Unretained(this)));
60 profile_pref_registrar_.Add(
61 prefs::kSearchSuggestEnabled,
62 base::Bind(&BrowserInstantController::ResetInstant,
63 base::Unretained(this)));
64 ResetInstant();
65 browser_->search_model()->AddObserver(this);
66
67 #if defined(ENABLE_THEMES)
68 // Listen for theme installation.
69 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
70 content::Source<ThemeService>(
71 ThemeServiceFactory::GetForProfile(profile())));
72 #endif // defined(ENABLE_THEMES)
73 } 32 }
74 33
75 BrowserInstantController::~BrowserInstantController() { 34 BrowserInstantController::~BrowserInstantController() {
76 browser_->search_model()->RemoveObserver(this);
77 }
78
79 bool BrowserInstantController::IsInstantEnabled(Profile* profile) {
80 return profile && !profile->IsOffTheRecord() && profile->GetPrefs() &&
81 profile->GetPrefs()->GetBoolean(GetInstantPrefName(profile));
82 }
83
84 void BrowserInstantController::RegisterUserPrefs(
85 PrefService* prefs,
86 PrefRegistrySyncable* registry) {
87 // TODO(joi): Get rid of the need for PrefService param above.
88 registry->RegisterBooleanPref(prefs::kInstantConfirmDialogShown, false,
89 PrefRegistrySyncable::SYNCABLE_PREF);
90 registry->RegisterBooleanPref(prefs::kInstantEnabled, false,
91 PrefRegistrySyncable::SYNCABLE_PREF);
92
93 bool instant_extended_default = true;
94 switch (search::GetInstantExtendedDefaultSetting()) {
95 case search::INSTANT_DEFAULT_ON:
96 instant_extended_default = true;
97 break;
98 case search::INSTANT_USE_EXISTING:
99 instant_extended_default = prefs->GetBoolean(prefs::kInstantEnabled);
100 break;
101 case search::INSTANT_DEFAULT_OFF:
102 instant_extended_default = false;
103 break;
104 }
105
106 registry->RegisterBooleanPref(prefs::kInstantExtendedEnabled,
107 instant_extended_default,
108 PrefRegistrySyncable::SYNCABLE_PREF);
109 } 35 }
110 36
111 bool BrowserInstantController::MaybeSwapInInstantNTPContents( 37 bool BrowserInstantController::MaybeSwapInInstantNTPContents(
112 const GURL& url, 38 const GURL& url,
113 content::WebContents* source_contents, 39 content::WebContents* source_contents,
114 content::WebContents** target_contents) { 40 content::WebContents** target_contents) {
115 if (url != GURL(chrome::kChromeUINewTabURL)) 41 if (url != GURL(chrome::kChromeUINewTabURL))
116 return false; 42 return false;
117 43
118 GURL extension_url(url); 44 GURL extension_url(url);
119 if (ExtensionWebUI::HandleChromeURLOverride(&extension_url, profile())) { 45 if (ExtensionWebUI::HandleChromeURLOverride(&extension_url,
46 browser_->profile())) {
120 // If there is an extension overriding the NTP do not use the Instant NTP. 47 // If there is an extension overriding the NTP do not use the Instant NTP.
121 return false; 48 return false;
122 } 49 }
123 50
124 scoped_ptr<content::WebContents> instant_ntp = instant_.ReleaseNTPContents(); 51 scoped_ptr<content::WebContents> instant_ntp = instant_->ReleaseNTPContents();
125 if (!instant_ntp) 52 if (!instant_ntp)
126 return false; 53 return false;
127 54
128 *target_contents = instant_ntp.get(); 55 *target_contents = instant_ntp.get();
56
129 if (source_contents) { 57 if (source_contents) {
130 instant_ntp->GetController().CopyStateFromAndPrune( 58 instant_ntp->GetController().CopyStateFromAndPrune(
131 &source_contents->GetController()); 59 &source_contents->GetController());
132 ReplaceWebContentsAt( 60 ReplaceWebContentsAt(
133 browser_->tab_strip_model()->GetIndexOfWebContents(source_contents), 61 browser_->tab_strip_model()->GetIndexOfWebContents(source_contents),
134 instant_ntp.Pass()); 62 instant_ntp.Pass());
135 } else { 63 } else {
136 instant_ntp->GetController().PruneAllButActive(); 64 instant_ntp->GetController().PruneAllButActive();
137 // If |source_contents| is NULL, then the caller is responsible for 65 // If |source_contents| is NULL, then the caller is responsible for
138 // inserting instant_ntp into the tabstrip and will take ownership. 66 // inserting instant_ntp into the tabstrip and will take ownership.
139 ignore_result(instant_ntp.release()); 67 ignore_result(instant_ntp.release());
140 } 68 }
141 content::RecordAction(UserMetricsAction("InstantExtended.ShowNTP")); 69 content::RecordAction(UserMetricsAction("InstantExtended.ShowNTP"));
70
71 content::NotificationService::current()->Notify(
72 chrome::NOTIFICATION_INSTANT_COMMITTED,
73 content::Source<content::WebContents>(*target_contents),
74 content::NotificationService::NoDetails());
142 return true; 75 return true;
143 } 76 }
144 77
145 bool BrowserInstantController::OpenInstant(WindowOpenDisposition disposition) { 78 bool BrowserInstantController::OpenInstant(WindowOpenDisposition disposition) {
146 // Unsupported dispositions. 79 // Unsupported dispositions.
147 if (disposition == NEW_BACKGROUND_TAB || disposition == NEW_WINDOW) 80 if (disposition == NEW_BACKGROUND_TAB || disposition == NEW_WINDOW)
148 return false; 81 return false;
149 82
150 // The omnibox currently doesn't use other dispositions, so we don't attempt 83 // The omnibox currently doesn't use other dispositions, so we don't attempt
151 // to handle them. If you hit this DCHECK file a bug and I'll (sky) add 84 // to handle them. If you hit this DCHECK file a bug and I'll (sky) add
152 // support for the new disposition. 85 // support for the new disposition.
153 DCHECK(disposition == CURRENT_TAB || 86 DCHECK(disposition == CURRENT_TAB ||
154 disposition == NEW_FOREGROUND_TAB) << disposition; 87 disposition == NEW_FOREGROUND_TAB) << disposition;
155 88
156 return instant_.CommitIfPossible(disposition == CURRENT_TAB ? 89 return instant_->CommitIfPossible(disposition == CURRENT_TAB ?
157 INSTANT_COMMIT_PRESSED_ENTER : INSTANT_COMMIT_PRESSED_ALT_ENTER); 90 INSTANT_COMMIT_PRESSED_ENTER : INSTANT_COMMIT_PRESSED_ALT_ENTER);
158 } 91 }
159 92
160 Profile* BrowserInstantController::profile() const {
161 return browser_->profile();
162 }
163
164 void BrowserInstantController::CommitInstant( 93 void BrowserInstantController::CommitInstant(
165 scoped_ptr<content::WebContents> preview, 94 scoped_ptr<content::WebContents> overlay,
95 content::PageTransition transition,
166 bool in_new_tab) { 96 bool in_new_tab) {
167 if (profile()->GetExtensionService()->IsInstalledApp(preview->GetURL())) { 97 if (browser_->profile()->GetExtensionService()->IsInstalledApp(
98 overlay->GetURL())) {
168 AppLauncherHandler::RecordAppLaunchType( 99 AppLauncherHandler::RecordAppLaunchType(
169 extension_misc::APP_LAUNCH_OMNIBOX_INSTANT); 100 extension_misc::APP_LAUNCH_OMNIBOX_INSTANT);
170 } 101 }
102
103 content::WebContents* overlay_contents = overlay.get();
104
171 if (in_new_tab) { 105 if (in_new_tab) {
172 // TabStripModel takes ownership of |preview|. 106 browser_->tab_strip_model()->AddWebContents(overlay.release(), -1,
173 browser_->tab_strip_model()->AddWebContents(preview.release(), -1, 107 transition, TabStripModel::ADD_ACTIVE);
174 instant_.last_transition_type(), TabStripModel::ADD_ACTIVE);
175 } else { 108 } else {
176 ReplaceWebContentsAt( 109 ReplaceWebContentsAt(browser_->tab_strip_model()->active_index(),
177 browser_->tab_strip_model()->active_index(), 110 overlay.Pass());
178 preview.Pass());
179 } 111 }
180 }
181 112
182 void BrowserInstantController::ReplaceWebContentsAt( 113 content::NotificationService::current()->Notify(
183 int index, 114 chrome::NOTIFICATION_INSTANT_COMMITTED,
184 scoped_ptr<content::WebContents> new_contents) { 115 content::Source<content::WebContents>(overlay_contents),
185 DCHECK_NE(TabStripModel::kNoTab, index); 116 content::NotificationService::NoDetails());
186 scoped_ptr<content::WebContents> old_contents(browser_->tab_strip_model()->
187 ReplaceWebContentsAt(index, new_contents.release()));
188 instant_unload_handler_.RunUnloadListenersOrDestroy(old_contents.Pass(),
189 index);
190 } 117 }
191 118
192 void BrowserInstantController::SetInstantSuggestion( 119 void BrowserInstantController::SetInstantSuggestion(
193 const InstantSuggestion& suggestion) { 120 const InstantSuggestion& suggestion) {
194 browser_->window()->GetLocationBar()->SetInstantSuggestion(suggestion); 121 browser_->window()->GetLocationBar()->GetLocationEntry()->model()->
122 SetInstantSuggestion(suggestion);
195 } 123 }
196 124
197 void BrowserInstantController::CommitSuggestedText( 125 void BrowserInstantController::CommitSuggestedText(
198 bool skip_inline_autocomplete) { 126 bool skip_inline_autocomplete) {
199 browser_->window()->GetLocationBar()->GetLocationEntry()->model()-> 127 browser_->window()->GetLocationBar()->GetLocationEntry()->model()->
200 CommitSuggestedText(skip_inline_autocomplete); 128 CommitSuggestedText(skip_inline_autocomplete);
201 } 129 }
202 130
203 gfx::Rect BrowserInstantController::GetInstantBounds() { 131 gfx::Rect BrowserInstantController::GetInstantBounds() const {
204 return browser_->window()->GetInstantBounds(); 132 return browser_->window()->GetInstantBounds();
205 } 133 }
206 134
207 void BrowserInstantController::InstantPreviewFocused() { 135 void BrowserInstantController::InstantOverlayFocused() {
208 // NOTE: This is only invoked on aura. 136 // NOTE: This is only invoked on aura.
209 browser_->window()->WebContentsFocused(instant_.GetPreviewContents()); 137 browser_->window()->WebContentsFocused(instant_->GetOverlayContents());
210 } 138 }
211 139
212 void BrowserInstantController::FocusOmniboxInvisibly() { 140 void BrowserInstantController::FocusOmniboxInvisibly() {
213 OmniboxView* omnibox_view = browser_->window()->GetLocationBar()-> 141 OmniboxView* omnibox_view =
214 GetLocationEntry(); 142 browser_->window()->GetLocationBar()->GetLocationEntry();
215 omnibox_view->SetFocus(); 143 omnibox_view->SetFocus();
216 omnibox_view->model()->SetCaretVisibility(false); 144 omnibox_view->model()->SetCaretVisibility(false);
217 } 145 }
218 146
219 content::WebContents* BrowserInstantController::GetActiveWebContents() const { 147 content::WebContents* BrowserInstantController::GetActiveWebContents() const {
220 return browser_->tab_strip_model()->GetActiveWebContents(); 148 return browser_->tab_strip_model()->GetActiveWebContents();
221 } 149 }
222 150
223 void BrowserInstantController::ActiveTabChanged() { 151 void BrowserInstantController::OpenURL(const GURL& url,
224 instant_.ActiveTabChanged(); 152 content::PageTransition transition,
153 WindowOpenDisposition disposition) {
154 browser_->OpenURL(content::OpenURLParams(
155 url, content::Referrer(), disposition, transition, false));
225 } 156 }
226 157
227 void BrowserInstantController::TabDeactivated(content::WebContents* contents) { 158 void BrowserInstantController::ReplaceWebContentsAt(
228 instant_.TabDeactivated(contents); 159 int index,
229 } 160 scoped_ptr<content::WebContents> new_contents) {
230 161 DCHECK_NE(TabStripModel::kNoTab, index);
231 void BrowserInstantController::UpdateThemeInfo(bool parse_theme_info) { 162 scoped_ptr<content::WebContents> old_contents(browser_->tab_strip_model()->
232 // Update theme background info. 163 ReplaceWebContentsAt(index, new_contents.release()));
233 // Initialize or re-parse |theme_info| if necessary. 164 instant_unload_handler_.RunUnloadListenersOrDestroy(old_contents.Pass(),
234 if (!initialized_theme_info_ || parse_theme_info) 165 index);
235 OnThemeChanged(ThemeServiceFactory::GetForProfile(profile()));
236 else
237 OnThemeChanged(NULL);
238 }
239
240 void BrowserInstantController::OpenURL(
241 const GURL& url,
242 content::PageTransition transition,
243 WindowOpenDisposition disposition) {
244 browser_->OpenURL(content::OpenURLParams(url,
245 content::Referrer(),
246 disposition,
247 transition,
248 false));
249 }
250
251 void BrowserInstantController::SetOmniboxBounds(const gfx::Rect& bounds) {
252 instant_.SetOmniboxBounds(bounds);
253 }
254
255 void BrowserInstantController::ResetInstant() {
256 bool instant_enabled = IsInstantEnabled(profile());
257 bool use_local_preview_only = profile()->IsOffTheRecord() ||
258 (!instant_enabled &&
259 !profile()->GetPrefs()->GetBoolean(prefs::kSearchSuggestEnabled));
260 instant_.SetInstantEnabled(instant_enabled, use_local_preview_only);
261 }
262
263 ////////////////////////////////////////////////////////////////////////////////
264 // BrowserInstantController, search::SearchModelObserver implementation:
265
266 void BrowserInstantController::ModeChanged(const search::Mode& old_mode,
267 const search::Mode& new_mode) {
268 // If mode is now |NTP|, send theme-related information to instant.
269 if (new_mode.is_ntp())
270 UpdateThemeInfo(false);
271
272 instant_.SearchModeChanged(old_mode, new_mode);
273 }
274
275 ////////////////////////////////////////////////////////////////////////////////
276 // BrowserInstantController, content::NotificationObserver implementation:
277
278 void BrowserInstantController::Observe(
279 int type,
280 const content::NotificationSource& source,
281 const content::NotificationDetails& details) {
282 #if defined(ENABLE_THEMES)
283 DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type);
284 OnThemeChanged(content::Source<ThemeService>(source).ptr());
285 #endif // defined(ENABLE_THEMES)
286 }
287
288 void BrowserInstantController::OnThemeChanged(ThemeService* theme_service) {
289 if (theme_service) { // Get theme information from theme service.
290 theme_info_ = ThemeBackgroundInfo();
291
292 // Set theme background color.
293 SkColor background_color =
294 theme_service->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND);
295 if (gfx::IsInvertedColorScheme())
296 background_color = color_utils::InvertColor(background_color);
297 theme_info_.color_r = SkColorGetR(background_color);
298 theme_info_.color_g = SkColorGetG(background_color);
299 theme_info_.color_b = SkColorGetB(background_color);
300 theme_info_.color_a = SkColorGetA(background_color);
301
302 if (theme_service->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
303 // Set theme id for theme background image url.
304 theme_info_.theme_id = theme_service->GetThemeID();
305
306 // Set theme background image horizontal alignment.
307 int alignment = 0;
308 theme_service->GetDisplayProperty(
309 ThemeProperties::NTP_BACKGROUND_ALIGNMENT, &alignment);
310 if (alignment & ThemeProperties::ALIGN_LEFT) {
311 theme_info_.image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_LEFT;
312 } else if (alignment & ThemeProperties::ALIGN_RIGHT) {
313 theme_info_.image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_RIGHT;
314 } else { // ALIGN_CENTER
315 theme_info_.image_horizontal_alignment =
316 THEME_BKGRND_IMAGE_ALIGN_CENTER;
317 }
318
319 // Set theme background image vertical alignment.
320 if (alignment & ThemeProperties::ALIGN_TOP) {
321 theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_TOP;
322 #if !defined(OS_ANDROID)
323 // A detached bookmark bar will draw the top part of a top-aligned theme
324 // image as its background, so offset the image by the bar height.
325 if (browser_->bookmark_bar_state() == BookmarkBar::DETACHED)
326 theme_info_.image_top_offset = -chrome::kNTPBookmarkBarHeight;
327 #endif // !defined(OS_ANDROID)
328 } else if (alignment & ThemeProperties::ALIGN_BOTTOM) {
329 theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_BOTTOM;
330 } else { // ALIGN_CENTER
331 theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_CENTER;
332 }
333
334 // Set theme background image tiling.
335 int tiling = 0;
336 theme_service->GetDisplayProperty(ThemeProperties::NTP_BACKGROUND_TILING,
337 &tiling);
338 switch (tiling) {
339 case ThemeProperties::NO_REPEAT:
340 theme_info_.image_tiling = THEME_BKGRND_IMAGE_NO_REPEAT;
341 break;
342 case ThemeProperties::REPEAT_X:
343 theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT_X;
344 break;
345 case ThemeProperties::REPEAT_Y:
346 theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT_Y;
347 break;
348 case ThemeProperties::REPEAT:
349 theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT;
350 break;
351 }
352
353 // Set theme background image height.
354 gfx::ImageSkia* image = theme_service->GetImageSkiaNamed(
355 IDR_THEME_NTP_BACKGROUND);
356 DCHECK(image);
357 theme_info_.image_height = image->height();
358 }
359
360 initialized_theme_info_ = true;
361 }
362
363 DCHECK(initialized_theme_info_);
364
365 if (browser_->search_model()->mode().is_ntp())
366 instant_.ThemeChanged(theme_info_);
367 } 166 }
368 167
369 } // namespace chrome 168 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698