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

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/instant/search.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/browser.h" 11 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_window.h" 12 #include "chrome/browser/ui/browser_window.h"
17 #include "chrome/browser/ui/omnibox/location_bar.h" 13 #include "chrome/browser/ui/omnibox/location_bar.h"
18 #include "chrome/browser/ui/omnibox/omnibox_view.h" 14 #include "chrome/browser/ui/omnibox/omnibox_view.h"
19 #include "chrome/browser/ui/search/search_tab_helper.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h" 15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h" 16 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
22 #include "chrome/common/chrome_notification_types.h" 17 #include "chrome/common/chrome_notification_types.h"
23 #include "chrome/common/pref_names.h"
24 #include "chrome/common/url_constants.h" 18 #include "chrome/common/url_constants.h"
25 #include "components/user_prefs/pref_registry_syncable.h"
26 #include "content/public/browser/notification_service.h" 19 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/user_metrics.h" 20 #include "content/public/browser/user_metrics.h"
28 #include "grit/theme_resources.h" 21 #include "content/public/browser/web_contents.h"
29 #include "ui/gfx/color_utils.h"
30 #include "ui/gfx/sys_color_change_listener.h"
31 22
32 using content::UserMetricsAction; 23 using content::UserMetricsAction;
33 24
34 namespace chrome { 25 namespace chrome {
35 26
36 ////////////////////////////////////////////////////////////////////////////////
37 // BrowserInstantController, public:
38
39 BrowserInstantController::BrowserInstantController(Browser* browser) 27 BrowserInstantController::BrowserInstantController(Browser* browser)
40 : browser_(browser), 28 : browser_(browser),
41 instant_(ALLOW_THIS_IN_INITIALIZER_LIST(this), 29 instant_(InstantController::Create(
42 chrome::search::IsInstantExtendedAPIEnabled()), 30 ALLOW_THIS_IN_INITIALIZER_LIST(this), browser->profile())),
43 instant_unload_handler_(browser), 31 instant_unload_handler_(browser) {
44 initialized_theme_info_(false) {
45
46 // In one mode of the InstantExtended experiments, the kInstantExtendedEnabled
47 // preference's default value is set to the existing value of kInstantEnabled.
48 // Because this requires reading the value of the kInstantEnabled value, we
49 // reset the default for kInstantExtendedEnabled here.
50 chrome::search::SetInstantExtendedPrefDefault(profile());
51
52 profile_pref_registrar_.Init(profile()->GetPrefs());
53 profile_pref_registrar_.Add(
54 prefs::kInstantEnabled,
55 base::Bind(&BrowserInstantController::ResetInstant,
56 base::Unretained(this)));
57 profile_pref_registrar_.Add(
58 prefs::kInstantExtendedEnabled,
59 base::Bind(&BrowserInstantController::ResetInstant,
60 base::Unretained(this)));
61 profile_pref_registrar_.Add(
62 prefs::kSearchSuggestEnabled,
63 base::Bind(&BrowserInstantController::ResetInstant,
64 base::Unretained(this)));
65 ResetInstant(std::string());
66 browser_->search_model()->AddObserver(this);
67
68 #if defined(ENABLE_THEMES)
69 // Listen for theme installation.
70 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
71 content::Source<ThemeService>(
72 ThemeServiceFactory::GetForProfile(profile())));
73 #endif // defined(ENABLE_THEMES)
74 } 32 }
75 33
76 BrowserInstantController::~BrowserInstantController() { 34 BrowserInstantController::~BrowserInstantController() {
77 browser_->search_model()->RemoveObserver(this);
78 } 35 }
79 36
80 bool BrowserInstantController::MaybeSwapInInstantNTPContents( 37 bool BrowserInstantController::MaybeSwapInInstantNTPContents(
81 const GURL& url, 38 const GURL& url,
82 content::WebContents* source_contents, 39 content::WebContents* source_contents,
83 content::WebContents** target_contents) { 40 content::WebContents** target_contents) {
84 if (url != GURL(chrome::kChromeUINewTabURL)) 41 if (url != GURL(chrome::kChromeUINewTabURL))
85 return false; 42 return false;
86 43
87 GURL extension_url(url); 44 GURL extension_url(url);
88 if (ExtensionWebUI::HandleChromeURLOverride(&extension_url, profile())) { 45 if (ExtensionWebUI::HandleChromeURLOverride(&extension_url,
46 browser_->profile())) {
89 // 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.
90 return false; 48 return false;
91 } 49 }
92 50
93 scoped_ptr<content::WebContents> instant_ntp = instant_.ReleaseNTPContents(); 51 scoped_ptr<content::WebContents> instant_ntp = instant_->ReleaseNTPContents();
94 if (!instant_ntp) 52 if (!instant_ntp)
95 return false; 53 return false;
96 54
97 *target_contents = instant_ntp.get(); 55 *target_contents = instant_ntp.get();
56
98 if (source_contents) { 57 if (source_contents) {
99 instant_ntp->GetController().CopyStateFromAndPrune( 58 instant_ntp->GetController().CopyStateFromAndPrune(
100 &source_contents->GetController()); 59 &source_contents->GetController());
101 ReplaceWebContentsAt( 60 ReplaceWebContentsAt(
102 browser_->tab_strip_model()->GetIndexOfWebContents(source_contents), 61 browser_->tab_strip_model()->GetIndexOfWebContents(source_contents),
103 instant_ntp.Pass()); 62 instant_ntp.Pass());
104 } else { 63 } else {
105 instant_ntp->GetController().PruneAllButActive(); 64 instant_ntp->GetController().PruneAllButActive();
106 // If |source_contents| is NULL, then the caller is responsible for 65 // If |source_contents| is NULL, then the caller is responsible for
107 // inserting instant_ntp into the tabstrip and will take ownership. 66 // inserting instant_ntp into the tabstrip and will take ownership.
108 ignore_result(instant_ntp.release()); 67 ignore_result(instant_ntp.release());
109 } 68 }
110 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());
111 return true; 75 return true;
112 } 76 }
113 77
114 bool BrowserInstantController::OpenInstant(WindowOpenDisposition disposition) { 78 bool BrowserInstantController::OpenInstant(WindowOpenDisposition disposition) {
115 // Unsupported dispositions. 79 // Unsupported dispositions.
116 if (disposition == NEW_BACKGROUND_TAB || disposition == NEW_WINDOW) 80 if (disposition == NEW_BACKGROUND_TAB || disposition == NEW_WINDOW)
117 return false; 81 return false;
118 82
119 // 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
120 // 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
121 // support for the new disposition. 85 // support for the new disposition.
122 DCHECK(disposition == CURRENT_TAB || 86 DCHECK(disposition == CURRENT_TAB ||
123 disposition == NEW_FOREGROUND_TAB) << disposition; 87 disposition == NEW_FOREGROUND_TAB) << disposition;
124 88
125 return instant_.CommitIfPossible(disposition == CURRENT_TAB ? 89 return instant_->CommitIfPossible(disposition == CURRENT_TAB ?
126 INSTANT_COMMIT_PRESSED_ENTER : INSTANT_COMMIT_PRESSED_ALT_ENTER); 90 INSTANT_COMMIT_PRESSED_ENTER : INSTANT_COMMIT_PRESSED_ALT_ENTER);
127 } 91 }
128 92
129 Profile* BrowserInstantController::profile() const {
130 return browser_->profile();
131 }
132
133 void BrowserInstantController::CommitInstant( 93 void BrowserInstantController::CommitInstant(
134 scoped_ptr<content::WebContents> overlay, 94 scoped_ptr<content::WebContents> overlay,
95 content::PageTransition transition,
135 bool in_new_tab) { 96 bool in_new_tab) {
136 if (profile()->GetExtensionService()->IsInstalledApp(overlay->GetURL())) { 97 if (browser_->profile()->GetExtensionService()->IsInstalledApp(
98 overlay->GetURL())) {
137 AppLauncherHandler::RecordAppLaunchType( 99 AppLauncherHandler::RecordAppLaunchType(
138 extension_misc::APP_LAUNCH_OMNIBOX_INSTANT); 100 extension_misc::APP_LAUNCH_OMNIBOX_INSTANT);
139 } 101 }
102
103 content::WebContents* overlay_contents = overlay.get();
104
140 if (in_new_tab) { 105 if (in_new_tab) {
141 // TabStripModel takes ownership of |overlay|.
142 browser_->tab_strip_model()->AddWebContents(overlay.release(), -1, 106 browser_->tab_strip_model()->AddWebContents(overlay.release(), -1,
143 instant_.last_transition_type(), TabStripModel::ADD_ACTIVE); 107 transition, TabStripModel::ADD_ACTIVE);
144 } else { 108 } else {
145 ReplaceWebContentsAt( 109 ReplaceWebContentsAt(browser_->tab_strip_model()->active_index(),
146 browser_->tab_strip_model()->active_index(), 110 overlay.Pass());
147 overlay.Pass());
148 } 111 }
149 }
150 112
151 void BrowserInstantController::ReplaceWebContentsAt( 113 content::NotificationService::current()->Notify(
152 int index, 114 chrome::NOTIFICATION_INSTANT_COMMITTED,
153 scoped_ptr<content::WebContents> new_contents) { 115 content::Source<content::WebContents>(overlay_contents),
154 DCHECK_NE(TabStripModel::kNoTab, index); 116 content::NotificationService::NoDetails());
155 scoped_ptr<content::WebContents> old_contents(browser_->tab_strip_model()->
156 ReplaceWebContentsAt(index, new_contents.release()));
157 instant_unload_handler_.RunUnloadListenersOrDestroy(old_contents.Pass(),
158 index);
159 } 117 }
160 118
161 void BrowserInstantController::SetInstantSuggestion( 119 void BrowserInstantController::SetInstantSuggestion(
162 const InstantSuggestion& suggestion) { 120 const InstantSuggestion& suggestion) {
163 browser_->window()->GetLocationBar()->SetInstantSuggestion(suggestion); 121 browser_->window()->GetLocationBar()->GetLocationEntry()->model()->
122 SetInstantSuggestion(suggestion);
164 } 123 }
165 124
166 void BrowserInstantController::CommitSuggestedText( 125 void BrowserInstantController::CommitSuggestedText(
167 bool skip_inline_autocomplete) { 126 bool skip_inline_autocomplete) {
168 browser_->window()->GetLocationBar()->GetLocationEntry()->model()-> 127 browser_->window()->GetLocationBar()->GetLocationEntry()->model()->
169 CommitSuggestedText(skip_inline_autocomplete); 128 CommitSuggestedText(skip_inline_autocomplete);
170 } 129 }
171 130
172 gfx::Rect BrowserInstantController::GetInstantBounds() { 131 gfx::Rect BrowserInstantController::GetInstantBounds() const {
173 return browser_->window()->GetInstantBounds(); 132 return browser_->window()->GetInstantBounds();
174 } 133 }
175 134
176 void BrowserInstantController::InstantOverlayFocused() { 135 void BrowserInstantController::InstantOverlayFocused() {
177 // NOTE: This is only invoked on aura. 136 // NOTE: This is only invoked on aura.
178 browser_->window()->WebContentsFocused(instant_.GetOverlayContents()); 137 browser_->window()->WebContentsFocused(instant_->GetOverlayContents());
179 } 138 }
180 139
181 void BrowserInstantController::FocusOmnibox(bool caret_visibility) { 140 void BrowserInstantController::FocusOmnibox(bool caret_visibility) {
182 OmniboxView* omnibox_view = browser_->window()->GetLocationBar()-> 141 OmniboxView* omnibox_view =
183 GetLocationEntry(); 142 browser_->window()->GetLocationBar()->GetLocationEntry();
184 omnibox_view->SetFocus(); 143 omnibox_view->SetFocus();
185 omnibox_view->model()->SetCaretVisibility(caret_visibility); 144 omnibox_view->model()->SetCaretVisibility(caret_visibility);
186 } 145 }
187 146
188 content::WebContents* BrowserInstantController::GetActiveWebContents() const { 147 content::WebContents* BrowserInstantController::GetActiveWebContents() const {
189 return browser_->tab_strip_model()->GetActiveWebContents(); 148 return browser_->tab_strip_model()->GetActiveWebContents();
190 } 149 }
191 150
192 void BrowserInstantController::ActiveTabChanged() { 151 void BrowserInstantController::OpenURL(const GURL& url,
193 instant_.ActiveTabChanged(); 152 content::PageTransition transition,
153 WindowOpenDisposition disposition) {
154 browser_->OpenURL(content::OpenURLParams(
155 url, content::Referrer(), disposition, transition, false));
194 } 156 }
195 157
196 void BrowserInstantController::TabDeactivated(content::WebContents* contents) { 158 void BrowserInstantController::ReplaceWebContentsAt(
197 instant_.TabDeactivated(contents); 159 int index,
198 } 160 scoped_ptr<content::WebContents> new_contents) {
199 161 DCHECK_NE(TabStripModel::kNoTab, index);
200 void BrowserInstantController::UpdateThemeInfo() { 162 scoped_ptr<content::WebContents> old_contents(browser_->tab_strip_model()->
201 // Update theme background info. 163 ReplaceWebContentsAt(index, new_contents.release()));
202 // Initialize |theme_info| if necessary. 164 instant_unload_handler_.RunUnloadListenersOrDestroy(old_contents.Pass(),
203 if (!initialized_theme_info_) 165 index);
204 OnThemeChanged(ThemeServiceFactory::GetForProfile(profile()));
205 else
206 OnThemeChanged(NULL);
207 }
208
209 void BrowserInstantController::OpenURL(
210 const GURL& url,
211 content::PageTransition transition,
212 WindowOpenDisposition disposition) {
213 browser_->OpenURL(content::OpenURLParams(url,
214 content::Referrer(),
215 disposition,
216 transition,
217 false));
218 }
219
220 void BrowserInstantController::SetOmniboxBounds(const gfx::Rect& bounds) {
221 instant_.SetOmniboxBounds(bounds);
222 }
223
224 void BrowserInstantController::ResetInstant(const std::string& pref_name) {
225 // Update the default value of the kInstantExtendedEnabled pref to match the
226 // value of the kInstantEnabled pref, if necessary.
227 if (pref_name == prefs::kInstantEnabled)
228 chrome::search::SetInstantExtendedPrefDefault(profile());
229
230 bool instant_pref_enabled = chrome::search::IsInstantPrefEnabled(profile());
231 bool use_local_overlay_only = profile()->IsOffTheRecord() ||
232 (!instant_pref_enabled &&
233 !profile()->GetPrefs()->GetBoolean(prefs::kSearchSuggestEnabled));
234 instant_.SetInstantEnabled(instant_pref_enabled, use_local_overlay_only);
235 }
236
237 ////////////////////////////////////////////////////////////////////////////////
238 // BrowserInstantController, search::SearchModelObserver implementation:
239
240 void BrowserInstantController::ModeChanged(const search::Mode& old_mode,
241 const search::Mode& new_mode) {
242 // If mode is now |NTP|, send theme-related information to Instant.
243 if (new_mode.is_ntp())
244 UpdateThemeInfo();
245
246 instant_.SearchModeChanged(old_mode, new_mode);
247 }
248
249 ////////////////////////////////////////////////////////////////////////////////
250 // BrowserInstantController, content::NotificationObserver implementation:
251
252 void BrowserInstantController::Observe(
253 int type,
254 const content::NotificationSource& source,
255 const content::NotificationDetails& details) {
256 #if defined(ENABLE_THEMES)
257 DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type);
258 OnThemeChanged(content::Source<ThemeService>(source).ptr());
259 #endif // defined(ENABLE_THEMES)
260 }
261
262 void BrowserInstantController::OnThemeChanged(ThemeService* theme_service) {
263 if (theme_service) { // Get theme information from theme service.
264 theme_info_ = ThemeBackgroundInfo();
265
266 // Set theme background color.
267 SkColor background_color =
268 theme_service->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND);
269 if (gfx::IsInvertedColorScheme())
270 background_color = color_utils::InvertColor(background_color);
271 theme_info_.color_r = SkColorGetR(background_color);
272 theme_info_.color_g = SkColorGetG(background_color);
273 theme_info_.color_b = SkColorGetB(background_color);
274 theme_info_.color_a = SkColorGetA(background_color);
275
276 if (theme_service->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
277 // Set theme id for theme background image url.
278 theme_info_.theme_id = theme_service->GetThemeID();
279
280 // Set theme background image horizontal alignment.
281 int alignment = 0;
282 theme_service->GetDisplayProperty(
283 ThemeProperties::NTP_BACKGROUND_ALIGNMENT, &alignment);
284 if (alignment & ThemeProperties::ALIGN_LEFT) {
285 theme_info_.image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_LEFT;
286 } else if (alignment & ThemeProperties::ALIGN_RIGHT) {
287 theme_info_.image_horizontal_alignment = THEME_BKGRND_IMAGE_ALIGN_RIGHT;
288 } else { // ALIGN_CENTER
289 theme_info_.image_horizontal_alignment =
290 THEME_BKGRND_IMAGE_ALIGN_CENTER;
291 }
292
293 // Set theme background image vertical alignment.
294 if (alignment & ThemeProperties::ALIGN_TOP)
295 theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_TOP;
296 else if (alignment & ThemeProperties::ALIGN_BOTTOM)
297 theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_BOTTOM;
298 else // ALIGN_CENTER
299 theme_info_.image_vertical_alignment = THEME_BKGRND_IMAGE_ALIGN_CENTER;
300
301 // Set theme background image tiling.
302 int tiling = 0;
303 theme_service->GetDisplayProperty(ThemeProperties::NTP_BACKGROUND_TILING,
304 &tiling);
305 switch (tiling) {
306 case ThemeProperties::NO_REPEAT:
307 theme_info_.image_tiling = THEME_BKGRND_IMAGE_NO_REPEAT;
308 break;
309 case ThemeProperties::REPEAT_X:
310 theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT_X;
311 break;
312 case ThemeProperties::REPEAT_Y:
313 theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT_Y;
314 break;
315 case ThemeProperties::REPEAT:
316 theme_info_.image_tiling = THEME_BKGRND_IMAGE_REPEAT;
317 break;
318 }
319
320 // Set theme background image height.
321 gfx::ImageSkia* image = theme_service->GetImageSkiaNamed(
322 IDR_THEME_NTP_BACKGROUND);
323 DCHECK(image);
324 theme_info_.image_height = image->height();
325 }
326
327 initialized_theme_info_ = true;
328 }
329
330 DCHECK(initialized_theme_info_);
331
332 if (browser_->search_model()->mode().is_ntp())
333 instant_.ThemeChanged(theme_info_);
334 } 166 }
335 167
336 } // namespace chrome 168 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698