OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // 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 | 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.h" | 5 #include "chrome/browser/ui/browser_command_controller.h" |
6 | 6 |
7 #if defined(OS_WIN) | |
8 #include <windows.h> | |
9 #include <shellapi.h> | |
10 #endif // OS_WIN | |
11 | |
12 #include <algorithm> | |
13 #include <string> | |
14 | |
15 #include "base/base_paths.h" | |
16 #include "base/bind.h" | |
17 #include "base/command_line.h" | |
18 #include "base/logging.h" | |
19 #include "base/metrics/field_trial.h" | |
20 #include "base/metrics/histogram.h" | |
21 #include "base/path_service.h" | |
22 #include "base/string_number_conversions.h" | |
23 #include "base/string_util.h" | |
24 #include "base/stringprintf.h" | |
25 #include "base/threading/thread.h" | |
26 #include "base/threading/thread_restrictions.h" | |
27 #include "base/time.h" | |
28 #include "base/utf_string_conversions.h" | |
29 #include "chrome/app/chrome_command_ids.h" | 7 #include "chrome/app/chrome_command_ids.h" |
30 #include "chrome/browser/autofill/personal_data_manager_factory.h" | |
31 #include "chrome/browser/background/background_contents_service.h" | |
32 #include "chrome/browser/background/background_contents_service_factory.h" | |
33 #include "chrome/browser/bookmarks/bookmark_model.h" | |
34 #include "chrome/browser/bookmarks/bookmark_utils.h" | |
35 #include "chrome/browser/browser_process.h" | 8 #include "chrome/browser/browser_process.h" |
36 #include "chrome/browser/browser_shutdown.h" | 9 #include "chrome/browser/defaults.h" |
37 #include "chrome/browser/character_encoding.h" | |
38 #include "chrome/browser/chrome_page_zoom.h" | |
39 #include "chrome/browser/content_settings/host_content_settings_map.h" | |
40 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" | |
41 #include "chrome/browser/custom_handlers/register_protocol_handler_infobar_deleg
ate.h" | |
42 #include "chrome/browser/debugger/devtools_toggle_action.h" | |
43 #include "chrome/browser/debugger/devtools_window.h" | |
44 #include "chrome/browser/download/download_crx_util.h" | |
45 #include "chrome/browser/download/download_item_model.h" | |
46 #include "chrome/browser/download/download_service.h" | |
47 #include "chrome/browser/download/download_service_factory.h" | |
48 #include "chrome/browser/download/download_shelf.h" | |
49 #include "chrome/browser/download/download_started_animation.h" | |
50 #include "chrome/browser/download/download_util.h" | |
51 #include "chrome/browser/extensions/browser_extension_window_controller.h" | |
52 #include "chrome/browser/extensions/crx_installer.h" | |
53 #include "chrome/browser/extensions/default_apps_trial.h" | |
54 #include "chrome/browser/extensions/extension_prefs.h" | |
55 #include "chrome/browser/extensions/extension_service.h" | 10 #include "chrome/browser/extensions/extension_service.h" |
56 #include "chrome/browser/extensions/extension_tab_helper.h" | |
57 #include "chrome/browser/favicon/favicon_tab_helper.h" | |
58 #include "chrome/browser/file_select_helper.h" | |
59 #include "chrome/browser/first_run/first_run.h" | |
60 #include "chrome/browser/google/google_url_tracker.h" | |
61 #include "chrome/browser/infobars/infobar_tab_helper.h" | |
62 #include "chrome/browser/instant/instant_controller.h" | |
63 #include "chrome/browser/instant/instant_unload_handler.h" | |
64 #include "chrome/browser/intents/register_intent_handler_infobar_delegate.h" | |
65 #include "chrome/browser/intents/web_intents_util.h" | |
66 #include "chrome/browser/lifetime/application_lifetime.h" | |
67 #include "chrome/browser/media/media_stream_devices_controller.h" | |
68 #include "chrome/browser/net/url_fixer_upper.h" | |
69 #include "chrome/browser/notifications/notification_ui_manager.h" | |
70 #include "chrome/browser/platform_util.h" | |
71 #include "chrome/browser/prefs/incognito_mode_prefs.h" | 11 #include "chrome/browser/prefs/incognito_mode_prefs.h" |
72 #include "chrome/browser/prefs/pref_service.h" | 12 #include "chrome/browser/prefs/pref_service.h" |
73 #include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h" | |
74 #include "chrome/browser/printing/print_preview_tab_controller.h" | 13 #include "chrome/browser/printing/print_preview_tab_controller.h" |
75 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
76 #include "chrome/browser/profiles/profile_destroyer.h" | |
77 #include "chrome/browser/profiles/profile_manager.h" | 15 #include "chrome/browser/profiles/profile_manager.h" |
78 #include "chrome/browser/profiles/profile_metrics.h" | |
79 #include "chrome/browser/repost_form_warning_controller.h" | |
80 #include "chrome/browser/sessions/restore_tab_helper.h" | |
81 #include "chrome/browser/sessions/session_service.h" | |
82 #include "chrome/browser/sessions/session_service_factory.h" | |
83 #include "chrome/browser/sessions/session_types.h" | |
84 #include "chrome/browser/sessions/tab_restore_service.h" | 16 #include "chrome/browser/sessions/tab_restore_service.h" |
85 #include "chrome/browser/sessions/tab_restore_service_factory.h" | 17 #include "chrome/browser/sessions/tab_restore_service_factory.h" |
86 #include "chrome/browser/sync/profile_sync_service.h" | 18 #include "chrome/browser/sync/profile_sync_service.h" |
87 #include "chrome/browser/sync/profile_sync_service_factory.h" | 19 #include "chrome/browser/sync/profile_sync_service_factory.h" |
88 #include "chrome/browser/sync/sync_ui_util.h" | |
89 #include "chrome/browser/tab_contents/background_contents.h" | |
90 #include "chrome/browser/tab_contents/retargeting_details.h" | |
91 #include "chrome/browser/tab_contents/simple_alert_infobar_delegate.h" | |
92 #include "chrome/browser/tab_contents/tab_util.h" | |
93 #include "chrome/browser/themes/theme_service.h" | |
94 #include "chrome/browser/themes/theme_service_factory.h" | |
95 #include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_creator.h" | |
96 #include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h" | |
97 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h" | 20 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h" |
| 21 #include "chrome/browser/ui/browser.h" |
98 #include "chrome/browser/ui/browser_commands.h" | 22 #include "chrome/browser/ui/browser_commands.h" |
99 #include "chrome/browser/ui/browser_content_setting_bubble_model_delegate.h" | |
100 #include "chrome/browser/ui/browser_dialogs.h" | |
101 #include "chrome/browser/ui/browser_finder.h" | |
102 #include "chrome/browser/ui/browser_list.h" | |
103 #include "chrome/browser/ui/browser_navigator.h" | |
104 #include "chrome/browser/ui/browser_tab_restore_service_delegate.h" | |
105 #include "chrome/browser/ui/browser_toolbar_model_delegate.h" | |
106 #include "chrome/browser/ui/browser_ui_prefs.h" | |
107 #include "chrome/browser/ui/browser_window.h" | 23 #include "chrome/browser/ui/browser_window.h" |
108 #include "chrome/browser/ui/chrome_pages.h" | 24 #include "chrome/browser/ui/chrome_pages.h" |
109 #include "chrome/browser/ui/constrained_window_tab_helper.h" | |
110 #include "chrome/browser/ui/extensions/shell_window.h" | |
111 #include "chrome/browser/ui/find_bar/find_bar.h" | |
112 #include "chrome/browser/ui/find_bar/find_bar_controller.h" | |
113 #include "chrome/browser/ui/find_bar/find_tab_helper.h" | |
114 #include "chrome/browser/ui/fullscreen_controller.h" | |
115 #include "chrome/browser/ui/global_error.h" | |
116 #include "chrome/browser/ui/global_error_service.h" | |
117 #include "chrome/browser/ui/global_error_service_factory.h" | |
118 #include "chrome/browser/ui/hung_plugin_tab_helper.h" | |
119 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" | |
120 #include "chrome/browser/ui/media_stream_infobar_delegate.h" | |
121 #include "chrome/browser/ui/omnibox/location_bar.h" | |
122 #include "chrome/browser/ui/panels/panel.h" | |
123 #include "chrome/browser/ui/panels/panel_manager.h" | |
124 #include "chrome/browser/ui/search/search.h" | |
125 #include "chrome/browser/ui/search/search_delegate.h" | |
126 #include "chrome/browser/ui/search/search_model.h" | |
127 #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h" | |
128 #include "chrome/browser/ui/singleton_tabs.h" | |
129 #include "chrome/browser/ui/status_bubble.h" | |
130 #include "chrome/browser/ui/sync/browser_synced_window_delegate.h" | |
131 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" | |
132 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 25 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
133 #include "chrome/browser/ui/tabs/dock_info.h" | |
134 #include "chrome/browser/ui/tabs/tab_menu_model.h" | |
135 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 26 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
136 #include "chrome/browser/ui/web_applications/web_app_ui.h" | 27 #include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h" |
137 #include "chrome/browser/ui/webui/feedback_ui.h" | |
138 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h" | |
139 #include "chrome/browser/ui/webui/signin/login_ui_service.h" | |
140 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" | |
141 #include "chrome/browser/ui/window_sizer.h" | |
142 #include "chrome/browser/upgrade_detector.h" | |
143 #include "chrome/browser/web_applications/web_app.h" | |
144 #include "chrome/common/chrome_constants.h" | |
145 #include "chrome/common/chrome_notification_types.h" | 28 #include "chrome/common/chrome_notification_types.h" |
146 #include "chrome/common/chrome_switches.h" | |
147 #include "chrome/common/custom_handlers/protocol_handler.h" | |
148 #include "chrome/common/extensions/extension.h" | |
149 #include "chrome/common/extensions/extension_constants.h" | |
150 #include "chrome/common/pref_names.h" | 29 #include "chrome/common/pref_names.h" |
151 #include "chrome/common/profiling.h" | 30 #include "chrome/common/profiling.h" |
152 #include "chrome/common/url_constants.h" | 31 #include "content/public/browser/native_web_keyboard_event.h" |
153 #include "chrome/common/web_apps.h" | |
154 #include "content/public/browser/color_chooser.h" | |
155 #include "content/public/browser/devtools_manager.h" | |
156 #include "content/public/browser/download_item.h" | |
157 #include "content/public/browser/download_manager.h" | |
158 #include "content/public/browser/interstitial_page.h" | |
159 #include "content/public/browser/invalidate_type.h" | |
160 #include "content/public/browser/navigation_controller.h" | 32 #include "content/public/browser/navigation_controller.h" |
161 #include "content/public/browser/navigation_entry.h" | 33 #include "content/public/browser/navigation_entry.h" |
162 #include "content/public/browser/notification_details.h" | 34 #include "content/public/browser/notification_details.h" |
163 #include "content/public/browser/notification_service.h" | 35 #include "content/public/browser/notification_source.h" |
164 #include "content/public/browser/plugin_service.h" | |
165 #include "content/public/browser/render_process_host.h" | |
166 #include "content/public/browser/render_view_host.h" | |
167 #include "content/public/browser/site_instance.h" | |
168 #include "content/public/browser/user_metrics.h" | |
169 #include "content/public/browser/web_contents.h" | 36 #include "content/public/browser/web_contents.h" |
170 #include "content/public/browser/web_contents_view.h" | |
171 #include "content/public/browser/web_intents_dispatcher.h" | |
172 #include "content/public/common/content_restriction.h" | 37 #include "content/public/common/content_restriction.h" |
173 #include "content/public/common/content_switches.h" | 38 #include "content/public/common/url_constants.h" |
174 #include "content/public/common/page_zoom.h" | 39 #include "ui/base/keycodes/keyboard_codes.h" |
175 #include "content/public/common/renderer_preferences.h" | |
176 #include "grit/chromium_strings.h" | |
177 #include "grit/generated_resources.h" | |
178 #include "grit/locale_settings.h" | |
179 #include "grit/theme_resources_standard.h" | |
180 #include "net/base/net_util.h" | |
181 #include "net/base/registry_controlled_domain.h" | |
182 #include "net/cookies/cookie_monster.h" | |
183 #include "net/url_request/url_request_context.h" | |
184 #include "ui/base/animation/animation.h" | |
185 #include "ui/base/l10n/l10n_util.h" | |
186 #include "ui/gfx/point.h" | |
187 #include "webkit/glue/web_intent_data.h" | |
188 #include "webkit/glue/web_intent_service_data.h" | |
189 #include "webkit/glue/webkit_glue.h" | |
190 #include "webkit/glue/window_open_disposition.h" | |
191 #include "webkit/plugins/webplugininfo.h" | |
192 | 40 |
193 #if defined(OS_WIN) | 41 #if defined(OS_WIN) |
194 #include "base/win/metro.h" | 42 #include "base/win/metro.h" |
195 #include "chrome/browser/autofill/autofill_ie_toolbar_import_win.h" | |
196 #include "chrome/browser/shell_integration.h" | |
197 #include "chrome/browser/ssl/ssl_error_info.h" | |
198 #include "chrome/browser/task_manager/task_manager.h" | |
199 #include "chrome/browser/ui/view_ids.h" | |
200 #include "ui/base/win/shell.h" | |
201 #endif // OS_WIN | |
202 | |
203 #if defined(OS_CHROMEOS) | |
204 #include "chrome/browser/chromeos/gdata/gdata_util.h" | |
205 #endif | 43 #endif |
206 | 44 |
207 #if defined(USE_ASH) | 45 using content::WebContents; |
208 #include "ash/ash_switches.h" | 46 using content::NavigationEntry; |
209 #endif | |
210 | |
211 using base::TimeDelta; | |
212 using content::NativeWebKeyboardEvent; | |
213 using content::NavigationController; | 47 using content::NavigationController; |
214 using content::NavigationEntry; | |
215 using content::OpenURLParams; | |
216 using content::PluginService; | |
217 using content::Referrer; | |
218 using content::SiteInstance; | |
219 using content::UserMetricsAction; | |
220 using content::WebContents; | 48 using content::WebContents; |
221 using extensions::Extension; | |
222 using ui::WebDialogDelegate; | |
223 | |
224 /////////////////////////////////////////////////////////////////////////////// | |
225 | 49 |
226 namespace { | 50 namespace { |
227 | 51 |
228 // The URL to be loaded to display the "Report a broken page" form. | |
229 const char kBrokenPageUrl[] = | |
230 "https://www.google.com/support/chrome/bin/request.py?contact_type=" | |
231 "broken_website&format=inproduct&p.page_title=$1&p.page_url=$2"; | |
232 | |
233 // The URL for the privacy dashboard. | |
234 const char kPrivacyDashboardUrl[] = "https://www.google.com/dashboard"; | |
235 | |
236 // How long we wait before updating the browser chrome while loading a page. | |
237 const int kUIUpdateCoalescingTimeMS = 200; | |
238 | |
239 // Returns |true| if entry has an internal chrome:// URL, |false| otherwise. | 52 // Returns |true| if entry has an internal chrome:// URL, |false| otherwise. |
240 bool HasInternalURL(const NavigationEntry* entry) { | 53 bool HasInternalURL(const NavigationEntry* entry) { |
241 if (!entry) | 54 if (!entry) |
242 return false; | 55 return false; |
243 | 56 |
244 // Check the |virtual_url()| first. This catches regular chrome:// URLs | 57 // Check the |virtual_url()| first. This catches regular chrome:// URLs |
245 // including URLs that were rewritten (such as chrome://bookmarks). | 58 // including URLs that were rewritten (such as chrome://bookmarks). |
246 if (entry->GetVirtualURL().SchemeIs(chrome::kChromeUIScheme)) | 59 if (entry->GetVirtualURL().SchemeIs(chrome::kChromeUIScheme)) |
247 return true; | 60 return true; |
248 | 61 |
249 // If the |virtual_url()| isn't a chrome:// URL, check if it's actually | 62 // If the |virtual_url()| isn't a chrome:// URL, check if it's actually |
250 // view-source: of a chrome:// URL. | 63 // view-source: of a chrome:// URL. |
251 if (entry->GetVirtualURL().SchemeIs(chrome::kViewSourceScheme)) | 64 if (entry->GetVirtualURL().SchemeIs(chrome::kViewSourceScheme)) |
252 return entry->GetURL().SchemeIs(chrome::kChromeUIScheme); | 65 return entry->GetURL().SchemeIs(chrome::kChromeUIScheme); |
253 | 66 |
254 return false; | 67 return false; |
255 } | 68 } |
256 | 69 |
257 bool AllowPanels(const std::string& app_name) { | |
258 return PanelManager::ShouldUsePanels( | |
259 web_app::GetExtensionIdFromApplicationName(app_name)); | |
260 } | |
261 | |
262 } // namespace | 70 } // namespace |
263 | 71 |
264 //////////////////////////////////////////////////////////////////////////////// | 72 namespace chrome { |
265 // Browser, CreateParams: | |
266 | |
267 Browser::CreateParams::CreateParams() | |
268 : type(TYPE_TABBED), | |
269 profile(NULL), | |
270 initial_show_state(ui::SHOW_STATE_DEFAULT), | |
271 is_session_restore(false) { | |
272 } | |
273 | |
274 Browser::CreateParams::CreateParams(Type type, Profile* profile) | |
275 : type(type), | |
276 profile(profile), | |
277 app_type(APP_TYPE_HOST), | |
278 initial_show_state(ui::SHOW_STATE_DEFAULT), | |
279 is_session_restore(false) { | |
280 } | |
281 | |
282 // static | |
283 Browser::CreateParams Browser::CreateParams::CreateForApp( | |
284 Type type, | |
285 const std::string& app_name, | |
286 const gfx::Rect& window_bounds, | |
287 Profile* profile) { | |
288 DCHECK(type != TYPE_TABBED); | |
289 DCHECK(!app_name.empty()); | |
290 | |
291 if (type == TYPE_PANEL && !AllowPanels(app_name)) | |
292 type = TYPE_POPUP; | |
293 | |
294 CreateParams params(type, profile); | |
295 params.app_name = app_name; | |
296 params.app_type = APP_TYPE_CHILD; | |
297 params.initial_bounds = window_bounds; | |
298 | |
299 return params; | |
300 } | |
301 | |
302 // static | |
303 Browser::CreateParams Browser::CreateParams::CreateForDevTools( | |
304 Profile* profile) { | |
305 CreateParams params(TYPE_POPUP, profile); | |
306 params.app_name = DevToolsWindow::kDevToolsApp; | |
307 return params; | |
308 } | |
309 | 73 |
310 /////////////////////////////////////////////////////////////////////////////// | 74 /////////////////////////////////////////////////////////////////////////////// |
311 // Browser, Constructors, Creation, Showing: | 75 // BrowserCommandController, public: |
312 | 76 |
313 Browser::Browser(Type type, Profile* profile) | 77 BrowserCommandController::BrowserCommandController(Browser* browser) |
314 : type_(type), | 78 : browser_(browser), |
315 profile_(profile), | 79 ALLOW_THIS_IN_INITIALIZER_LIST(command_updater_(this)), |
316 window_(NULL), | |
317 ALLOW_THIS_IN_INITIALIZER_LIST( | |
318 tab_strip_model_(new TabStripModel(this, profile))), | |
319 command_updater_(this), | |
320 app_type_(APP_TYPE_HOST), | |
321 chrome_updater_factory_(this), | |
322 is_attempting_to_close_browser_(false), | |
323 cancel_download_confirmation_state_(NOT_PROMPTED), | |
324 initial_show_state_(ui::SHOW_STATE_DEFAULT), | |
325 is_session_restore_(false), | |
326 weak_factory_(this), | |
327 block_command_execution_(false), | 80 block_command_execution_(false), |
328 last_blocked_command_id_(-1), | 81 last_blocked_command_id_(-1), |
329 last_blocked_command_disposition_(CURRENT_TAB), | 82 last_blocked_command_disposition_(CURRENT_TAB) { |
330 pending_web_app_action_(NONE), | 83 browser_->tab_strip_model()->AddObserver(this); |
331 ALLOW_THIS_IN_INITIALIZER_LIST( | |
332 content_setting_bubble_model_delegate_( | |
333 new BrowserContentSettingBubbleModelDelegate(this))), | |
334 ALLOW_THIS_IN_INITIALIZER_LIST( | |
335 toolbar_model_delegate_( | |
336 new BrowserToolbarModelDelegate(this))), | |
337 ALLOW_THIS_IN_INITIALIZER_LIST( | |
338 tab_restore_service_delegate_( | |
339 new BrowserTabRestoreServiceDelegate(this))), | |
340 ALLOW_THIS_IN_INITIALIZER_LIST( | |
341 synced_window_delegate_( | |
342 new BrowserSyncedWindowDelegate(this))), | |
343 bookmark_bar_state_(BookmarkBar::HIDDEN), | |
344 window_has_shown_(false) { | |
345 tab_strip_model_->AddObserver(this); | |
346 | |
347 toolbar_model_.reset(new ToolbarModel(toolbar_model_delegate_.get())); | |
348 search_model_.reset(new chrome::search::SearchModel(NULL)); | |
349 search_delegate_.reset( | |
350 new chrome::search::SearchDelegate(search_model_.get())); | |
351 | |
352 registrar_.Add(this, content::NOTIFICATION_SSL_VISIBLE_STATE_CHANGED, | |
353 content::NotificationService::AllSources()); | |
354 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, | |
355 content::Source<Profile>(profile_->GetOriginalProfile())); | |
356 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | |
357 content::Source<Profile>(profile_->GetOriginalProfile())); | |
358 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, | |
359 content::Source<Profile>(profile_->GetOriginalProfile())); | |
360 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, | |
361 content::NotificationService::AllSources()); | |
362 #if defined(ENABLE_THEMES) | |
363 registrar_.Add( | |
364 this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, | |
365 content::Source<ThemeService>( | |
366 ThemeServiceFactory::GetForProfile(profile_))); | |
367 #endif | |
368 registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, | |
369 content::NotificationService::AllSources()); | |
370 | |
371 PrefService* local_state = g_browser_process->local_state(); | 84 PrefService* local_state = g_browser_process->local_state(); |
372 if (local_state) { | 85 if (local_state) { |
373 local_pref_registrar_.Init(local_state); | 86 local_pref_registrar_.Init(local_state); |
374 local_pref_registrar_.Add(prefs::kPrintingEnabled, this); | 87 local_pref_registrar_.Add(prefs::kPrintingEnabled, this); |
375 local_pref_registrar_.Add(prefs::kAllowFileSelectionDialogs, this); | 88 local_pref_registrar_.Add(prefs::kAllowFileSelectionDialogs, this); |
376 local_pref_registrar_.Add(prefs::kInManagedMode, this); | 89 local_pref_registrar_.Add(prefs::kInManagedMode, this); |
377 } | 90 } |
378 | 91 |
379 profile_pref_registrar_.Init(profile_->GetPrefs()); | 92 profile_pref_registrar_.Init(profile()->GetPrefs()); |
380 profile_pref_registrar_.Add(prefs::kDevToolsDisabled, this); | 93 profile_pref_registrar_.Add(prefs::kDevToolsDisabled, this); |
381 profile_pref_registrar_.Add(prefs::kEditBookmarksEnabled, this); | 94 profile_pref_registrar_.Add(prefs::kEditBookmarksEnabled, this); |
382 profile_pref_registrar_.Add(prefs::kShowBookmarkBar, this); | 95 profile_pref_registrar_.Add(prefs::kShowBookmarkBar, this); |
383 profile_pref_registrar_.Add(prefs::kHomePage, this); | |
384 profile_pref_registrar_.Add(prefs::kInstantEnabled, this); | |
385 profile_pref_registrar_.Add(prefs::kIncognitoModeAvailability, this); | 96 profile_pref_registrar_.Add(prefs::kIncognitoModeAvailability, this); |
386 | 97 |
387 InitCommandState(); | 98 InitCommandState(); |
388 BrowserList::AddBrowser(this); | |
389 | 99 |
390 // NOTE: These prefs all need to be explicitly destroyed in the destructor | 100 TabRestoreService* tab_restore_service = |
391 // or you'll get a nasty surprise when you run the incognito tests. | 101 TabRestoreServiceFactory::GetForProfile(profile()); |
392 encoding_auto_detect_.Init(prefs::kWebKitUsesUniversalDetector, | 102 if (tab_restore_service) { |
393 profile_->GetPrefs(), NULL); | 103 tab_restore_service->AddObserver(this); |
394 | 104 TabRestoreServiceChanged(tab_restore_service); |
395 tab_restore_service_ = TabRestoreServiceFactory::GetForProfile(profile); | |
396 if (tab_restore_service_) { | |
397 tab_restore_service_->AddObserver(this); | |
398 TabRestoreServiceChanged(tab_restore_service_); | |
399 } | 105 } |
400 | 106 |
401 ProfileSyncService* service = | 107 ProfileSyncService* service = |
402 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_); | 108 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile()); |
403 if (service) | 109 if (service) |
404 service->AddObserver(this); | 110 service->AddObserver(this); |
405 | |
406 CreateInstantIfNecessary(); | |
407 | |
408 UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_INIT); | |
409 | |
410 FilePath profile_path = profile->GetPath(); | |
411 ProfileMetrics::LogProfileLaunch(profile_path); | |
412 } | 111 } |
413 | 112 |
414 Browser::~Browser() { | 113 BrowserCommandController::~BrowserCommandController() { |
415 ProfileSyncService* service = | 114 ProfileSyncService* service = |
416 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_); | 115 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile()); |
417 if (service) | 116 if (service) |
418 service->RemoveObserver(this); | 117 service->RemoveObserver(this); |
419 | 118 |
420 // The tab strip should not have any tabs at this point. | |
421 if (!browser_shutdown::ShuttingDownWithoutClosingBrowsers()) | |
422 DCHECK(tab_strip_model_->empty()); | |
423 tab_strip_model_->RemoveObserver(this); | |
424 | |
425 BrowserList::RemoveBrowser(this); | |
426 | |
427 SessionService* session_service = | |
428 SessionServiceFactory::GetForProfile(profile_); | |
429 if (session_service) | |
430 session_service->WindowClosed(session_id_); | |
431 | |
432 TabRestoreService* tab_restore_service = | 119 TabRestoreService* tab_restore_service = |
433 TabRestoreServiceFactory::GetForProfile(profile()); | 120 TabRestoreServiceFactory::GetForProfile(profile()); |
434 if (tab_restore_service) | 121 if (tab_restore_service) |
435 tab_restore_service->BrowserClosed(tab_restore_service_delegate()); | 122 tab_restore_service->RemoveObserver(this); |
436 | |
437 #if !defined(OS_MACOSX) | |
438 if (!browser::GetBrowserCount(profile_)) { | |
439 // We're the last browser window with this profile. We need to nuke the | |
440 // TabRestoreService, which will start the shutdown of the | |
441 // NavigationControllers and allow for proper shutdown. If we don't do this | |
442 // chrome won't shutdown cleanly, and may end up crashing when some | |
443 // thread tries to use the IO thread (or another thread) that is no longer | |
444 // valid. | |
445 // This isn't a valid assumption for Mac OS, as it stays running after | |
446 // the last browser has closed. The Mac equivalent is in its app | |
447 // controller. | |
448 TabRestoreServiceFactory::ResetForProfile(profile_); | |
449 } | |
450 #endif | |
451 | |
452 profile_pref_registrar_.RemoveAll(); | 123 profile_pref_registrar_.RemoveAll(); |
453 local_pref_registrar_.RemoveAll(); | 124 local_pref_registrar_.RemoveAll(); |
454 | 125 browser_->tab_strip_model()->RemoveObserver(this); |
455 encoding_auto_detect_.Destroy(); | |
456 | |
457 if (profile_->IsOffTheRecord() && | |
458 !BrowserList::IsOffTheRecordSessionActiveForProfile(profile_)) { | |
459 // An incognito profile is no longer needed, this indirectly frees | |
460 // its cache and cookies once it gets destroyed at the appropriate time. | |
461 ProfileDestroyer::DestroyProfileWhenAppropriate(profile_); | |
462 } | |
463 | |
464 // There may be pending file dialogs, we need to tell them that we've gone | |
465 // away so they don't try and call back to us. | |
466 if (select_file_dialog_.get()) | |
467 select_file_dialog_->ListenerDestroyed(); | |
468 | |
469 TabRestoreServiceDestroyed(tab_restore_service_); | |
470 } | 126 } |
471 | 127 |
472 // static | 128 bool BrowserCommandController::IsReservedCommandOrKey( |
473 Browser* Browser::Create(Profile* profile) { | 129 int command_id, |
474 Browser* browser = new Browser(TYPE_TABBED, profile); | 130 const content::NativeWebKeyboardEvent& event) { |
475 browser->InitBrowserWindow(); | |
476 return browser; | |
477 } | |
478 | |
479 // static | |
480 Browser* Browser::CreateWithParams(const CreateParams& params) { | |
481 if (!params.app_name.empty()) | |
482 chrome::RegisterAppPrefs(params.app_name, params.profile); | |
483 | |
484 Browser* browser = new Browser(params.type, params.profile); | |
485 browser->app_name_ = params.app_name; | |
486 browser->app_type_ = params.app_type; | |
487 browser->set_override_bounds(params.initial_bounds); | |
488 browser->set_initial_show_state(params.initial_show_state); | |
489 browser->set_is_session_restore(params.is_session_restore); | |
490 | |
491 browser->InitBrowserWindow(); | |
492 return browser; | |
493 } | |
494 | |
495 void Browser::InitBrowserWindow() { | |
496 DCHECK(!window_); | |
497 | |
498 window_ = CreateBrowserWindow(); | |
499 fullscreen_controller_ = new FullscreenController(window_, profile_, this); | |
500 | |
501 #if defined(OS_WIN) && !defined(USE_AURA) | |
502 // Set the app user model id for this application to that of the application | |
503 // name. See http://crbug.com/7028. | |
504 ui::win::SetAppIdForWindow( | |
505 is_app() && !is_type_panel() ? | |
506 ShellIntegration::GetAppModelIdForProfile(UTF8ToWide(app_name_), | |
507 profile_->GetPath()) : | |
508 ShellIntegration::GetChromiumModelIdForProfile(profile_->GetPath()), | |
509 window()->GetNativeWindow()); | |
510 | |
511 if (is_type_panel()) { | |
512 ui::win::SetAppIconForWindow(ShellIntegration::GetChromiumIconPath(), | |
513 window()->GetNativeWindow()); | |
514 } | |
515 #endif | |
516 | |
517 // Create the extension window controller before sending notifications. | |
518 extension_window_controller_.reset( | |
519 new BrowserExtensionWindowController(this)); | |
520 | |
521 content::NotificationService::current()->Notify( | |
522 chrome::NOTIFICATION_BROWSER_WINDOW_READY, | |
523 content::Source<Browser>(this), | |
524 content::NotificationService::NoDetails()); | |
525 | |
526 PrefService* local_state = g_browser_process->local_state(); | |
527 if (local_state && local_state->FindPreference( | |
528 prefs::kAutofillPersonalDataManagerFirstRun) && | |
529 local_state->GetBoolean(prefs::kAutofillPersonalDataManagerFirstRun)) { | |
530 // Notify PDM that this is a first run. | |
531 #if defined(OS_WIN) | |
532 ImportAutofillDataWin(PersonalDataManagerFactory::GetForProfile(profile_)); | |
533 #endif // defined(OS_WIN) | |
534 // Reset the preference so we don't call it again for subsequent windows. | |
535 local_state->ClearPref(prefs::kAutofillPersonalDataManagerFirstRun); | |
536 } | |
537 } | |
538 | |
539 void Browser::SetWindowForTesting(BrowserWindow* window) { | |
540 DCHECK(!window_); | |
541 window_ = window; | |
542 fullscreen_controller_ = new FullscreenController(window_, profile_, this); | |
543 } | |
544 | |
545 /////////////////////////////////////////////////////////////////////////////// | |
546 // Getters & Setters | |
547 | |
548 FindBarController* Browser::GetFindBarController() { | |
549 if (!find_bar_controller_.get()) { | |
550 FindBar* find_bar = window_->CreateFindBar(); | |
551 find_bar_controller_.reset(new FindBarController(find_bar)); | |
552 find_bar->SetFindBarController(find_bar_controller_.get()); | |
553 find_bar_controller_->ChangeTabContents(GetActiveTabContents()); | |
554 find_bar_controller_->find_bar()->MoveWindowIfNecessary(gfx::Rect(), true); | |
555 } | |
556 return find_bar_controller_.get(); | |
557 } | |
558 | |
559 bool Browser::HasFindBarController() const { | |
560 return find_bar_controller_.get() != NULL; | |
561 } | |
562 | |
563 bool Browser::is_app() const { | |
564 return !app_name_.empty(); | |
565 } | |
566 | |
567 bool Browser::is_devtools() const { | |
568 return app_name_ == DevToolsWindow::kDevToolsApp; | |
569 } | |
570 | |
571 /////////////////////////////////////////////////////////////////////////////// | |
572 // Browser, State Storage and Retrieval for UI: | |
573 | |
574 SkBitmap Browser::GetCurrentPageIcon() const { | |
575 TabContents* contents = GetActiveTabContents(); | |
576 // |contents| can be NULL since GetCurrentPageIcon() is called by the window | |
577 // during the window's creation (before tabs have been added). | |
578 return contents ? contents->favicon_tab_helper()->GetFavicon() : SkBitmap(); | |
579 } | |
580 | |
581 string16 Browser::GetWindowTitleForCurrentTab() const { | |
582 WebContents* contents = GetActiveWebContents(); | |
583 string16 title; | |
584 | |
585 // |contents| can be NULL because GetWindowTitleForCurrentTab is called by the | |
586 // window during the window's creation (before tabs have been added). | |
587 if (contents) { | |
588 title = contents->GetTitle(); | |
589 FormatTitleForDisplay(&title); | |
590 } | |
591 if (title.empty()) | |
592 title = CoreTabHelper::GetDefaultTitle(); | |
593 | |
594 #if defined(OS_MACOSX) || defined(USE_ASH) | |
595 // On Mac or Ash, we don't want to suffix the page title with | |
596 // the application name. | |
597 return title; | |
598 #else | |
599 int string_id = IDS_BROWSER_WINDOW_TITLE_FORMAT; | |
600 // Don't append the app name to window titles on app frames and app popups | |
601 if (is_app()) | |
602 string_id = IDS_BROWSER_WINDOW_TITLE_FORMAT_NO_LOGO; | |
603 return l10n_util::GetStringFUTF16(string_id, title); | |
604 #endif | |
605 } | |
606 | |
607 // static | |
608 void Browser::FormatTitleForDisplay(string16* title) { | |
609 size_t current_index = 0; | |
610 size_t match_index; | |
611 while ((match_index = title->find(L'\n', current_index)) != string16::npos) { | |
612 title->replace(match_index, 1, string16()); | |
613 current_index = match_index; | |
614 } | |
615 } | |
616 | |
617 /////////////////////////////////////////////////////////////////////////////// | |
618 // Browser, OnBeforeUnload handling: | |
619 | |
620 bool Browser::ShouldCloseWindow() { | |
621 if (!CanCloseWithInProgressDownloads()) | |
622 return false; | |
623 | |
624 if (HasCompletedUnloadProcessing()) | |
625 return true; | |
626 | |
627 is_attempting_to_close_browser_ = true; | |
628 | |
629 if (!TabsNeedBeforeUnloadFired()) | |
630 return true; | |
631 | |
632 ProcessPendingTabs(); | |
633 return false; | |
634 } | |
635 | |
636 void Browser::OnWindowClosing() { | |
637 if (!ShouldCloseWindow()) | |
638 return; | |
639 | |
640 bool exiting = false; | |
641 | |
642 // Application should shutdown on last window close if the user is explicitly | |
643 // trying to quit, or if there is nothing keeping the browser alive (such as | |
644 // AppController on the Mac, or BackgroundContentsService for background | |
645 // pages). | |
646 bool should_quit_if_last_browser = | |
647 browser_shutdown::IsTryingToQuit() || !browser::WillKeepAlive(); | |
648 | |
649 if (should_quit_if_last_browser && BrowserList::size() == 1) { | |
650 browser_shutdown::OnShutdownStarting(browser_shutdown::WINDOW_CLOSE); | |
651 exiting = true; | |
652 } | |
653 | |
654 // Don't use GetForProfileIfExisting here, we want to force creation of the | |
655 // session service so that user can restore what was open. | |
656 SessionService* session_service = | |
657 SessionServiceFactory::GetForProfile(profile()); | |
658 if (session_service) | |
659 session_service->WindowClosing(session_id()); | |
660 | |
661 TabRestoreService* tab_restore_service = | |
662 TabRestoreServiceFactory::GetForProfile(profile()); | |
663 | |
664 #if defined(USE_AURA) | |
665 if (tab_restore_service && is_app()) | |
666 tab_restore_service->BrowserClosing(tab_restore_service_delegate()); | |
667 #endif | |
668 | |
669 if (tab_restore_service && is_type_tabbed() && tab_count()) | |
670 tab_restore_service->BrowserClosing(tab_restore_service_delegate()); | |
671 | |
672 // TODO(sky): convert session/tab restore to use notification. | |
673 content::NotificationService::current()->Notify( | |
674 chrome::NOTIFICATION_BROWSER_CLOSING, | |
675 content::Source<Browser>(this), | |
676 content::Details<bool>(&exiting)); | |
677 | |
678 CloseAllTabs(); | |
679 } | |
680 | |
681 void Browser::OnWindowActivated() { | |
682 // On some platforms we want to automatically reload tabs that are | |
683 // killed when the user selects them. | |
684 WebContents* contents = GetActiveWebContents(); | |
685 if (contents && contents->GetCrashedStatus() == | |
686 base::TERMINATION_STATUS_PROCESS_WAS_KILLED) { | |
687 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
688 switches::kReloadKilledTabs)) { | |
689 chrome::Reload(this, CURRENT_TAB); | |
690 } | |
691 } | |
692 } | |
693 | |
694 //////////////////////////////////////////////////////////////////////////////// | |
695 // In-progress download termination handling: | |
696 | |
697 void Browser::InProgressDownloadResponse(bool cancel_downloads) { | |
698 if (cancel_downloads) { | |
699 cancel_download_confirmation_state_ = RESPONSE_RECEIVED; | |
700 chrome::CloseWindow(this); | |
701 return; | |
702 } | |
703 | |
704 // Sets the confirmation state to NOT_PROMPTED so that if the user tries to | |
705 // close again we'll show the warning again. | |
706 cancel_download_confirmation_state_ = NOT_PROMPTED; | |
707 | |
708 // Show the download page so the user can figure-out what downloads are still | |
709 // in-progress. | |
710 chrome::ShowDownloads(this); | |
711 } | |
712 | |
713 Browser::DownloadClosePreventionType Browser::OkToCloseWithInProgressDownloads( | |
714 int* num_downloads_blocking) const { | |
715 DCHECK(num_downloads_blocking); | |
716 *num_downloads_blocking = 0; | |
717 | |
718 if (is_attempting_to_close_browser_) | |
719 return DOWNLOAD_CLOSE_OK; | |
720 | |
721 // If we're not running a full browser process with a profile manager | |
722 // (testing), it's ok to close the browser. | |
723 if (!g_browser_process->profile_manager()) | |
724 return DOWNLOAD_CLOSE_OK; | |
725 | |
726 int total_download_count = DownloadService::DownloadCountAllProfiles(); | |
727 if (total_download_count == 0) | |
728 return DOWNLOAD_CLOSE_OK; // No downloads; can definitely close. | |
729 | |
730 // Figure out how many windows are open total, and associated with this | |
731 // profile, that are relevant for the ok-to-close decision. | |
732 int profile_window_count = 0; | |
733 int total_window_count = 0; | |
734 for (BrowserList::const_iterator iter = BrowserList::begin(); | |
735 iter != BrowserList::end(); ++iter) { | |
736 // Don't count this browser window or any other in the process of closing. | |
737 Browser* const browser = *iter; | |
738 // Check is_attempting_to_close_browser_ as window closing may be | |
739 // delayed, and windows that are in the process of closing don't | |
740 // count against our totals. | |
741 if (browser == this || browser->is_attempting_to_close_browser_) | |
742 continue; | |
743 | |
744 if ((*iter)->profile() == profile()) | |
745 profile_window_count++; | |
746 total_window_count++; | |
747 } | |
748 | |
749 // If there aren't any other windows, we're at browser shutdown, | |
750 // which would cancel all current downloads. | |
751 if (total_window_count == 0) { | |
752 *num_downloads_blocking = total_download_count; | |
753 return DOWNLOAD_CLOSE_BROWSER_SHUTDOWN; | |
754 } | |
755 | |
756 // If there aren't any other windows on our profile, and we're an incognito | |
757 // profile, and there are downloads associated with that profile, | |
758 // those downloads would be cancelled by our window (-> profile) close. | |
759 DownloadService* download_service = | |
760 DownloadServiceFactory::GetForProfile(profile()); | |
761 if (profile_window_count == 0 && download_service->DownloadCount() > 0 && | |
762 profile()->IsOffTheRecord()) { | |
763 *num_downloads_blocking = download_service->DownloadCount(); | |
764 return DOWNLOAD_CLOSE_LAST_WINDOW_IN_INCOGNITO_PROFILE; | |
765 } | |
766 | |
767 // Those are the only conditions under which we will block shutdown. | |
768 return DOWNLOAD_CLOSE_OK; | |
769 } | |
770 | |
771 //////////////////////////////////////////////////////////////////////////////// | |
772 // Browser, TabStripModel pass-thrus: | |
773 | |
774 int Browser::tab_count() const { | |
775 return tab_strip_model_->count(); | |
776 } | |
777 | |
778 int Browser::active_index() const { | |
779 return tab_strip_model_->active_index(); | |
780 } | |
781 | |
782 int Browser::GetIndexOfController( | |
783 const NavigationController* controller) const { | |
784 return tab_strip_model_->GetIndexOfController(controller); | |
785 } | |
786 | |
787 TabContents* Browser::GetActiveTabContents() const { | |
788 return tab_strip_model_->GetActiveTabContents(); | |
789 } | |
790 | |
791 WebContents* Browser::GetActiveWebContents() const { | |
792 TabContents* tab_contents = GetActiveTabContents(); | |
793 return tab_contents ? tab_contents->web_contents() : NULL; | |
794 } | |
795 | |
796 TabContents* Browser::GetTabContentsAt(int index) const { | |
797 return tab_strip_model_->GetTabContentsAt(index); | |
798 } | |
799 | |
800 WebContents* Browser::GetWebContentsAt(int index) const { | |
801 TabContents* tab_contents = GetTabContentsAt(index); | |
802 if (tab_contents) | |
803 return tab_contents->web_contents(); | |
804 return NULL; | |
805 } | |
806 | |
807 void Browser::ActivateTabAt(int index, bool user_gesture) { | |
808 tab_strip_model_->ActivateTabAt(index, user_gesture); | |
809 } | |
810 | |
811 bool Browser::IsTabPinned(int index) const { | |
812 return tab_strip_model_->IsTabPinned(index); | |
813 } | |
814 | |
815 bool Browser::IsTabDiscarded(int index) const { | |
816 return tab_strip_model_->IsTabDiscarded(index); | |
817 } | |
818 | |
819 void Browser::CloseAllTabs() { | |
820 tab_strip_model_->CloseAllTabs(); | |
821 } | |
822 | |
823 //////////////////////////////////////////////////////////////////////////////// | |
824 // Browser, Tab adding/showing functions: | |
825 | |
826 bool Browser::IsTabStripEditable() const { | |
827 return window()->IsTabStripEditable(); | |
828 } | |
829 | |
830 int Browser::GetIndexForInsertionDuringRestore(int relative_index) { | |
831 return (tab_strip_model_->insertion_policy() == TabStripModel::INSERT_AFTER) ? | |
832 tab_count() : relative_index; | |
833 } | |
834 | |
835 TabContents* Browser::AddSelectedTabWithURL( | |
836 const GURL& url, | |
837 content::PageTransition transition) { | |
838 browser::NavigateParams params(this, url, transition); | |
839 params.disposition = NEW_FOREGROUND_TAB; | |
840 browser::Navigate(¶ms); | |
841 return params.target_contents; | |
842 } | |
843 | |
844 WebContents* Browser::AddTab(TabContents* tab_contents, | |
845 content::PageTransition type) { | |
846 tab_strip_model_->AddTabContents(tab_contents, -1, type, | |
847 TabStripModel::ADD_ACTIVE); | |
848 return tab_contents->web_contents(); | |
849 } | |
850 | |
851 WebContents* Browser::AddRestoredTab( | |
852 const std::vector<TabNavigation>& navigations, | |
853 int tab_index, | |
854 int selected_navigation, | |
855 const std::string& extension_app_id, | |
856 bool select, | |
857 bool pin, | |
858 bool from_last_session, | |
859 content::SessionStorageNamespace* session_storage_namespace) { | |
860 GURL restore_url = navigations.at(selected_navigation).virtual_url(); | |
861 TabContents* tab_contents = TabContentsFactory( | |
862 profile(), | |
863 tab_util::GetSiteInstanceForNewTab(profile_, restore_url), | |
864 MSG_ROUTING_NONE, | |
865 GetActiveWebContents(), | |
866 session_storage_namespace); | |
867 WebContents* new_tab = tab_contents->web_contents(); | |
868 tab_contents->extension_tab_helper()->SetExtensionAppById(extension_app_id); | |
869 std::vector<NavigationEntry*> entries; | |
870 TabNavigation::CreateNavigationEntriesFromTabNavigations( | |
871 profile_, navigations, &entries); | |
872 new_tab->GetController().Restore( | |
873 selected_navigation, from_last_session, &entries); | |
874 DCHECK_EQ(0u, entries.size()); | |
875 | |
876 int add_types = select ? TabStripModel::ADD_ACTIVE : | |
877 TabStripModel::ADD_NONE; | |
878 if (pin) { | |
879 int first_mini_tab_idx = tab_strip_model_->IndexOfFirstNonMiniTab(); | |
880 tab_index = std::min(tab_index, first_mini_tab_idx); | |
881 add_types |= TabStripModel::ADD_PINNED; | |
882 } | |
883 tab_strip_model_->InsertTabContentsAt(tab_index, tab_contents, add_types); | |
884 if (select) { | |
885 window_->Activate(); | |
886 } else { | |
887 // We set the size of the view here, before WebKit does its initial | |
888 // layout. If we don't, the initial layout of background tabs will be | |
889 // performed with a view width of 0, which may cause script outputs and | |
890 // anchor link location calculations to be incorrect even after a new | |
891 // layout with proper view dimensions. TabStripModel::AddTabContents() | |
892 // contains similar logic. | |
893 new_tab->GetView()->SizeContents(window_->GetRestoredBounds().size()); | |
894 new_tab->WasHidden(); | |
895 } | |
896 SessionService* session_service = | |
897 SessionServiceFactory::GetForProfileIfExisting(profile_); | |
898 if (session_service) | |
899 session_service->TabRestored(tab_contents, pin); | |
900 return new_tab; | |
901 } | |
902 | |
903 void Browser::AddWebContents(WebContents* new_contents, | |
904 WindowOpenDisposition disposition, | |
905 const gfx::Rect& initial_pos, | |
906 bool user_gesture) { | |
907 AddNewContents(NULL, new_contents, disposition, initial_pos, user_gesture); | |
908 } | |
909 | |
910 void Browser::CloseTabContents(WebContents* contents) { | |
911 CloseContents(contents); | |
912 } | |
913 | |
914 void Browser::ReplaceRestoredTab( | |
915 const std::vector<TabNavigation>& navigations, | |
916 int selected_navigation, | |
917 bool from_last_session, | |
918 const std::string& extension_app_id, | |
919 content::SessionStorageNamespace* session_storage_namespace) { | |
920 GURL restore_url = navigations.at(selected_navigation).virtual_url(); | |
921 TabContents* tab_contents = TabContentsFactory( | |
922 profile(), | |
923 tab_util::GetSiteInstanceForNewTab(profile_, restore_url), | |
924 MSG_ROUTING_NONE, | |
925 GetActiveWebContents(), | |
926 session_storage_namespace); | |
927 tab_contents->extension_tab_helper()->SetExtensionAppById(extension_app_id); | |
928 WebContents* replacement = tab_contents->web_contents(); | |
929 std::vector<NavigationEntry*> entries; | |
930 TabNavigation::CreateNavigationEntriesFromTabNavigations( | |
931 profile_, navigations, &entries); | |
932 replacement->GetController().Restore( | |
933 selected_navigation, from_last_session, &entries); | |
934 DCHECK_EQ(0u, entries.size()); | |
935 | |
936 tab_strip_model_->ReplaceNavigationControllerAt(active_index(), tab_contents); | |
937 } | |
938 | |
939 void Browser::WindowFullscreenStateChanged() { | |
940 fullscreen_controller_->WindowFullscreenStateChanged(); | |
941 FullScreenMode fullscreen_mode = FULLSCREEN_DISABLED; | |
942 if (window_->IsFullscreen()) { | |
943 #if defined(OS_WIN) | |
944 fullscreen_mode = window_->IsInMetroSnapMode() ? FULLSCREEN_METRO_SNAP : | |
945 FULLSCREEN_NORMAL; | |
946 #else | |
947 fullscreen_mode = FULLSCREEN_NORMAL; | |
948 #endif | |
949 } | |
950 UpdateCommandsForFullscreenMode(fullscreen_mode); | |
951 UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TOGGLE_FULLSCREEN); | |
952 } | |
953 | |
954 /////////////////////////////////////////////////////////////////////////////// | |
955 // Browser, Assorted browser commands: | |
956 | |
957 void Browser::ToggleFullscreenMode() { | |
958 fullscreen_controller_->ToggleFullscreenMode(); | |
959 } | |
960 | |
961 void Browser::ToggleFullscreenModeWithExtension(const GURL& extension_url) { | |
962 fullscreen_controller_->ToggleFullscreenModeWithExtension(extension_url); | |
963 } | |
964 | |
965 #if defined(OS_MACOSX) | |
966 void Browser::TogglePresentationMode() { | |
967 fullscreen_controller_->TogglePresentationMode(); | |
968 } | |
969 #endif | |
970 | |
971 bool Browser::SupportsWindowFeature(WindowFeature feature) const { | |
972 return SupportsWindowFeatureImpl(feature, true); | |
973 } | |
974 | |
975 bool Browser::CanSupportWindowFeature(WindowFeature feature) const { | |
976 return SupportsWindowFeatureImpl(feature, false); | |
977 } | |
978 | |
979 void Browser::ToggleEncodingAutoDetect() { | |
980 content::RecordAction(UserMetricsAction("AutoDetectChange")); | |
981 encoding_auto_detect_.SetValue(!encoding_auto_detect_.GetValue()); | |
982 // If "auto detect" is turned on, then any current override encoding | |
983 // is cleared. This also implicitly performs a reload. | |
984 // OTOH, if "auto detect" is turned off, we don't change the currently | |
985 // active encoding. | |
986 if (encoding_auto_detect_.GetValue()) { | |
987 WebContents* contents = GetActiveWebContents(); | |
988 if (contents) | |
989 contents->ResetOverrideEncoding(); | |
990 } | |
991 } | |
992 | |
993 void Browser::OverrideEncoding(int encoding_id) { | |
994 content::RecordAction(UserMetricsAction("OverrideEncoding")); | |
995 const std::string selected_encoding = | |
996 CharacterEncoding::GetCanonicalEncodingNameByCommandId(encoding_id); | |
997 WebContents* contents = GetActiveWebContents(); | |
998 if (!selected_encoding.empty() && contents) | |
999 contents->SetOverrideEncoding(selected_encoding); | |
1000 // Update the list of recently selected encodings. | |
1001 std::string new_selected_encoding_list; | |
1002 if (CharacterEncoding::UpdateRecentlySelectedEncoding( | |
1003 profile_->GetPrefs()->GetString(prefs::kRecentlySelectedEncoding), | |
1004 encoding_id, | |
1005 &new_selected_encoding_list)) { | |
1006 profile_->GetPrefs()->SetString(prefs::kRecentlySelectedEncoding, | |
1007 new_selected_encoding_list); | |
1008 } | |
1009 } | |
1010 | |
1011 void Browser::OpenFile() { | |
1012 content::RecordAction(UserMetricsAction("OpenFile")); | |
1013 if (!select_file_dialog_.get()) | |
1014 select_file_dialog_ = SelectFileDialog::Create(this); | |
1015 | |
1016 const FilePath directory = profile_->last_selected_directory(); | |
1017 | |
1018 // TODO(beng): figure out how to juggle this. | |
1019 gfx::NativeWindow parent_window = window_->GetNativeWindow(); | |
1020 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE, | |
1021 string16(), directory, | |
1022 NULL, 0, FILE_PATH_LITERAL(""), | |
1023 GetActiveWebContents(), | |
1024 parent_window, NULL); | |
1025 } | |
1026 | |
1027 void Browser::OpenCreateShortcutsDialog() { | |
1028 content::RecordAction(UserMetricsAction("CreateShortcut")); | |
1029 #if !defined(OS_MACOSX) | |
1030 TabContents* current_tab = GetActiveTabContents(); | |
1031 DCHECK(current_tab && | |
1032 web_app::IsValidUrl(current_tab->web_contents()->GetURL())) << | |
1033 "Menu item should be disabled."; | |
1034 | |
1035 NavigationEntry* entry = | |
1036 current_tab->web_contents()->GetController().GetLastCommittedEntry(); | |
1037 if (!entry) | |
1038 return; | |
1039 | |
1040 // RVH's GetApplicationInfo should not be called before it returns. | |
1041 DCHECK(pending_web_app_action_ == NONE); | |
1042 pending_web_app_action_ = CREATE_SHORTCUT; | |
1043 | |
1044 // Start fetching web app info for CreateApplicationShortcut dialog and show | |
1045 // the dialog when the data is available in OnDidGetApplicationInfo. | |
1046 current_tab->extension_tab_helper()->GetApplicationInfo(entry->GetPageID()); | |
1047 #else | |
1048 NOTIMPLEMENTED(); | |
1049 #endif | |
1050 } | |
1051 | |
1052 void Browser::UpdateDownloadShelfVisibility(bool visible) { | |
1053 if (GetStatusBubble()) | |
1054 GetStatusBubble()->UpdateDownloadShelfVisibility(visible); | |
1055 } | |
1056 | |
1057 bool Browser::OpenInstant(WindowOpenDisposition disposition) { | |
1058 if (!instant() || !instant()->PrepareForCommit() || | |
1059 disposition == NEW_BACKGROUND_TAB) { | |
1060 // NEW_BACKGROUND_TAB results in leaving the omnibox open, so we don't | |
1061 // attempt to use the instant preview. | |
1062 return false; | |
1063 } | |
1064 | |
1065 if (disposition == CURRENT_TAB) { | |
1066 content::NotificationService::current()->Notify( | |
1067 chrome::NOTIFICATION_INSTANT_COMMITTED, | |
1068 content::Source<TabContents>(instant()->CommitCurrentPreview( | |
1069 INSTANT_COMMIT_PRESSED_ENTER)), | |
1070 content::NotificationService::NoDetails()); | |
1071 return true; | |
1072 } | |
1073 if (disposition == NEW_FOREGROUND_TAB) { | |
1074 TabContents* preview_contents = instant()->ReleasePreviewContents( | |
1075 INSTANT_COMMIT_PRESSED_ENTER, NULL); | |
1076 // HideInstant is invoked after release so that InstantController is not | |
1077 // active when HideInstant asks it for its state. | |
1078 HideInstant(); | |
1079 preview_contents->web_contents()->GetController().PruneAllButActive(); | |
1080 tab_strip_model_->AddTabContents( | |
1081 preview_contents, | |
1082 -1, | |
1083 instant()->last_transition_type(), | |
1084 TabStripModel::ADD_ACTIVE); | |
1085 instant()->CompleteRelease(preview_contents); | |
1086 content::NotificationService::current()->Notify( | |
1087 chrome::NOTIFICATION_INSTANT_COMMITTED, | |
1088 content::Source<TabContents>(preview_contents), | |
1089 content::NotificationService::NoDetails()); | |
1090 return true; | |
1091 } | |
1092 // The omnibox currently doesn't use other dispositions, so we don't attempt | |
1093 // to handle them. If you hit this NOTREACHED file a bug and I'll (sky) add | |
1094 // support for the new disposition. | |
1095 NOTREACHED(); | |
1096 return false; | |
1097 } | |
1098 | |
1099 /////////////////////////////////////////////////////////////////////////////// | |
1100 | |
1101 // static | |
1102 bool Browser::RunUnloadEventsHelper(WebContents* contents) { | |
1103 // If the WebContents is not connected yet, then there's no unload | |
1104 // handler we can fire even if the WebContents has an unload listener. | |
1105 // One case where we hit this is in a tab that has an infinite loop | |
1106 // before load. | |
1107 if (contents->NeedToFireBeforeUnload()) { | |
1108 // If the page has unload listeners, then we tell the renderer to fire | |
1109 // them. Once they have fired, we'll get a message back saying whether | |
1110 // to proceed closing the page or not, which sends us back to this method | |
1111 // with the NeedToFireBeforeUnload bit cleared. | |
1112 contents->GetRenderViewHost()->FirePageBeforeUnload(false); | |
1113 return true; | |
1114 } | |
1115 return false; | |
1116 } | |
1117 | |
1118 // static | |
1119 void Browser::JSOutOfMemoryHelper(WebContents* web_contents) { | |
1120 TabContents* tab_contents = TabContents::FromWebContents(web_contents); | |
1121 if (!tab_contents) | |
1122 return; | |
1123 | |
1124 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper(); | |
1125 infobar_helper->AddInfoBar(new SimpleAlertInfoBarDelegate( | |
1126 infobar_helper, | |
1127 NULL, | |
1128 l10n_util::GetStringUTF16(IDS_JS_OUT_OF_MEMORY_PROMPT), | |
1129 true)); | |
1130 } | |
1131 | |
1132 // static | |
1133 void Browser::RegisterProtocolHandlerHelper(WebContents* web_contents, | |
1134 const std::string& protocol, | |
1135 const GURL& url, | |
1136 const string16& title, | |
1137 bool user_gesture) { | |
1138 TabContents* tab_contents = TabContents::FromWebContents(web_contents); | |
1139 if (!tab_contents || tab_contents->profile()->IsOffTheRecord()) | |
1140 return; | |
1141 | |
1142 ProtocolHandler handler = | |
1143 ProtocolHandler::CreateProtocolHandler(protocol, url, title); | |
1144 | |
1145 ProtocolHandlerRegistry* registry = | |
1146 tab_contents->profile()->GetProtocolHandlerRegistry(); | |
1147 | |
1148 if (!registry->SilentlyHandleRegisterHandlerRequest(handler)) { | |
1149 content::RecordAction( | |
1150 UserMetricsAction("RegisterProtocolHandler.InfoBar_Shown")); | |
1151 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper(); | |
1152 | |
1153 RegisterProtocolHandlerInfoBarDelegate* rph_delegate = | |
1154 new RegisterProtocolHandlerInfoBarDelegate(infobar_helper, | |
1155 registry, | |
1156 handler); | |
1157 | |
1158 for (size_t i = 0; i < infobar_helper->infobar_count(); i++) { | |
1159 InfoBarDelegate* delegate = infobar_helper->GetInfoBarDelegateAt(i); | |
1160 RegisterProtocolHandlerInfoBarDelegate* cast_delegate = | |
1161 delegate->AsRegisterProtocolHandlerInfoBarDelegate(); | |
1162 if (cast_delegate != NULL && cast_delegate->IsReplacedBy(rph_delegate)) { | |
1163 infobar_helper->ReplaceInfoBar(cast_delegate, rph_delegate); | |
1164 rph_delegate = NULL; | |
1165 break; | |
1166 } | |
1167 } | |
1168 | |
1169 if (rph_delegate != NULL) | |
1170 infobar_helper->AddInfoBar(rph_delegate); | |
1171 } | |
1172 } | |
1173 | |
1174 // static | |
1175 void Browser::FindReplyHelper(WebContents* web_contents, | |
1176 int request_id, | |
1177 int number_of_matches, | |
1178 const gfx::Rect& selection_rect, | |
1179 int active_match_ordinal, | |
1180 bool final_update) { | |
1181 TabContents* tab_contents = TabContents::FromWebContents(web_contents); | |
1182 if (!tab_contents || !tab_contents->find_tab_helper()) | |
1183 return; | |
1184 | |
1185 tab_contents->find_tab_helper()->HandleFindReply(request_id, | |
1186 number_of_matches, | |
1187 selection_rect, | |
1188 active_match_ordinal, | |
1189 final_update); | |
1190 } | |
1191 | |
1192 void Browser::ExecuteCommand(int id) { | |
1193 ExecuteCommandWithDisposition(id, CURRENT_TAB); | |
1194 } | |
1195 | |
1196 void Browser::ExecuteCommand(int id, int event_flags) { | |
1197 ExecuteCommandWithDisposition( | |
1198 id, browser::DispositionFromEventFlags(event_flags)); | |
1199 } | |
1200 | |
1201 bool Browser::ExecuteCommandIfEnabled(int id) { | |
1202 if (command_updater_.SupportsCommand(id) && | |
1203 command_updater_.IsCommandEnabled(id)) { | |
1204 ExecuteCommand(id); | |
1205 return true; | |
1206 } | |
1207 return false; | |
1208 } | |
1209 | |
1210 bool Browser::IsReservedCommandOrKey(int command_id, | |
1211 const NativeWebKeyboardEvent& event) { | |
1212 // In Apps mode, no keys are reserved. | 131 // In Apps mode, no keys are reserved. |
1213 if (is_app()) | 132 if (browser_->is_app()) |
1214 return false; | 133 return false; |
1215 | 134 |
1216 #if defined(OS_CHROMEOS) | 135 #if defined(OS_CHROMEOS) |
1217 // Chrome OS's top row of keys produces F1-10. Make sure that web pages | 136 // Chrome OS's top row of keys produces F1-10. Make sure that web pages |
1218 // aren't able to block Chrome from performing the standard actions for F1-F4. | 137 // aren't able to block Chrome from performing the standard actions for F1-F4. |
1219 // We should not handle F5-10 here since they are processed by Ash. See also: | 138 // We should not handle F5-10 here since they are processed by Ash. See also: |
1220 // crbug.com/127333#c8 | 139 // crbug.com/127333#c8 |
1221 ui::KeyboardCode key_code = | 140 ui::KeyboardCode key_code = |
1222 static_cast<ui::KeyboardCode>(event.windowsKeyCode); | 141 static_cast<ui::KeyboardCode>(event.windowsKeyCode); |
1223 if ((key_code == ui::VKEY_F1 || | 142 if ((key_code == ui::VKEY_F1 || |
1224 key_code == ui::VKEY_F2 || | 143 key_code == ui::VKEY_F2 || |
1225 key_code == ui::VKEY_F3 || | 144 key_code == ui::VKEY_F3 || |
1226 key_code == ui::VKEY_F4) && | 145 key_code == ui::VKEY_F4) && |
1227 // Make sure it's a browser shortcut (i.e. not an Ash one like Alt+F4). | 146 // Make sure it's a browser shortcut (i.e. not an Ash one like Alt+F4). |
1228 command_id != -1) { | 147 command_id != -1) { |
1229 return true; | 148 return true; |
1230 } | 149 } |
1231 #endif | 150 #endif |
1232 | 151 |
1233 if (window_->IsFullscreen() && command_id == IDC_FULLSCREEN) | 152 if (window()->IsFullscreen() && command_id == IDC_FULLSCREEN) |
1234 return true; | 153 return true; |
1235 return command_id == IDC_CLOSE_TAB || | 154 return command_id == IDC_CLOSE_TAB || |
1236 command_id == IDC_CLOSE_WINDOW || | 155 command_id == IDC_CLOSE_WINDOW || |
1237 command_id == IDC_NEW_INCOGNITO_WINDOW || | 156 command_id == IDC_NEW_INCOGNITO_WINDOW || |
1238 command_id == IDC_NEW_TAB || | 157 command_id == IDC_NEW_TAB || |
1239 command_id == IDC_NEW_WINDOW || | 158 command_id == IDC_NEW_WINDOW || |
1240 command_id == IDC_RESTORE_TAB || | 159 command_id == IDC_RESTORE_TAB || |
1241 command_id == IDC_SELECT_NEXT_TAB || | 160 command_id == IDC_SELECT_NEXT_TAB || |
1242 command_id == IDC_SELECT_PREVIOUS_TAB || | 161 command_id == IDC_SELECT_PREVIOUS_TAB || |
1243 command_id == IDC_TABPOSE || | 162 command_id == IDC_TABPOSE || |
1244 command_id == IDC_EXIT || | 163 command_id == IDC_EXIT || |
1245 command_id == IDC_SEARCH; | 164 command_id == IDC_SEARCH; |
1246 } | 165 } |
1247 | 166 |
1248 void Browser::SetBlockCommandExecution(bool block) { | 167 void BrowserCommandController::SetBlockCommandExecution(bool block) { |
1249 block_command_execution_ = block; | 168 block_command_execution_ = block; |
1250 if (block) { | 169 if (block) { |
1251 last_blocked_command_id_ = -1; | 170 last_blocked_command_id_ = -1; |
1252 last_blocked_command_disposition_ = CURRENT_TAB; | 171 last_blocked_command_disposition_ = CURRENT_TAB; |
1253 } | 172 } |
1254 } | 173 } |
1255 | 174 |
1256 int Browser::GetLastBlockedCommand(WindowOpenDisposition* disposition) { | 175 int BrowserCommandController::GetLastBlockedCommand( |
| 176 WindowOpenDisposition* disposition) { |
1257 if (disposition) | 177 if (disposition) |
1258 *disposition = last_blocked_command_disposition_; | 178 *disposition = last_blocked_command_disposition_; |
1259 return last_blocked_command_id_; | 179 return last_blocked_command_id_; |
1260 } | 180 } |
1261 | 181 |
1262 void Browser::UpdateUIForNavigationInTab(TabContents* contents, | 182 void BrowserCommandController::TabStateChanged() { |
1263 content::PageTransition transition, | 183 UpdateCommandsForTabState(); |
1264 bool user_initiated) { | |
1265 tab_strip_model_->TabNavigating(contents, transition); | |
1266 | |
1267 bool contents_is_selected = contents == GetActiveTabContents(); | |
1268 if (user_initiated && contents_is_selected && window()->GetLocationBar()) { | |
1269 // Forcibly reset the location bar if the url is going to change in the | |
1270 // current tab, since otherwise it won't discard any ongoing user edits, | |
1271 // since it doesn't realize this is a user-initiated action. | |
1272 window()->GetLocationBar()->Revert(); | |
1273 } | |
1274 | |
1275 if (GetStatusBubble()) | |
1276 GetStatusBubble()->Hide(); | |
1277 | |
1278 // Update the location bar. This is synchronous. We specifically don't | |
1279 // update the load state since the load hasn't started yet and updating it | |
1280 // will put it out of sync with the actual state like whether we're | |
1281 // displaying a favicon, which controls the throbber. If we updated it here, | |
1282 // the throbber will show the default favicon for a split second when | |
1283 // navigating away from the new tab page. | |
1284 ScheduleUIUpdate(contents->web_contents(), content::INVALIDATE_TYPE_URL); | |
1285 | |
1286 if (contents_is_selected) | |
1287 contents->web_contents()->Focus(); | |
1288 } | 184 } |
1289 | 185 |
1290 /////////////////////////////////////////////////////////////////////////////// | 186 void BrowserCommandController::ContentRestrictionsChanged() { |
1291 // Browser, PageNavigator implementation: | 187 UpdateCommandsForContentRestrictionState(); |
1292 | |
1293 WebContents* Browser::OpenURL(const OpenURLParams& params) { | |
1294 return OpenURLFromTab(NULL, params); | |
1295 } | 188 } |
1296 | 189 |
1297 /////////////////////////////////////////////////////////////////////////////// | 190 void BrowserCommandController::FullscreenStateChanged() { |
1298 // Browser, CommandUpdater::CommandUpdaterDelegate implementation: | 191 FullScreenMode fullscreen_mode = FULLSCREEN_DISABLED; |
| 192 if (window()->IsFullscreen()) { |
| 193 #if defined(OS_WIN) |
| 194 fullscreen_mode = window()->IsInMetroSnapMode() ? FULLSCREEN_METRO_SNAP : |
| 195 FULLSCREEN_NORMAL; |
| 196 #else |
| 197 fullscreen_mode = FULLSCREEN_NORMAL; |
| 198 #endif |
| 199 } |
| 200 UpdateCommandsForFullscreenMode(fullscreen_mode); |
| 201 } |
1299 | 202 |
1300 void Browser::ExecuteCommandWithDisposition( | 203 void BrowserCommandController::PrintingStateChanged() { |
| 204 UpdatePrintingState(); |
| 205 } |
| 206 |
| 207 void BrowserCommandController::LoadingStateChanged(bool is_loading, |
| 208 bool force) { |
| 209 UpdateReloadStopState(is_loading, force); |
| 210 } |
| 211 |
| 212 void BrowserCommandController::SendToMobileStateChanged( |
| 213 bool send_to_mobile_available) { |
| 214 command_updater_.UpdateCommandEnabled(IDC_CHROME_TO_MOBILE_PAGE, |
| 215 send_to_mobile_available); |
| 216 } |
| 217 |
| 218 //////////////////////////////////////////////////////////////////////////////// |
| 219 // BrowserCommandController, |
| 220 // CommandUpdater::CommandUpdaterDelegate implementation: |
| 221 |
| 222 void BrowserCommandController::ExecuteCommandWithDisposition( |
1301 int id, WindowOpenDisposition disposition) { | 223 int id, WindowOpenDisposition disposition) { |
1302 // No commands are enabled if there is not yet any selected tab. | 224 // No commands are enabled if there is not yet any selected tab. |
1303 // TODO(pkasting): It seems like we should not need this, because either | 225 // TODO(pkasting): It seems like we should not need this, because either |
1304 // most/all commands should not have been enabled yet anyway or the ones that | 226 // most/all commands should not have been enabled yet anyway or the ones that |
1305 // are enabled should be global, or safe themselves against having no selected | 227 // are enabled should be global, or safe themselves against having no selected |
1306 // tab. However, Ben says he tried removing this before and got lots of | 228 // tab. However, Ben says he tried removing this before and got lots of |
1307 // crashes, e.g. from Windows sending WM_COMMANDs at random times during | 229 // crashes, e.g. from Windows sending WM_COMMANDs at random times during |
1308 // window construction. This probably could use closer examination someday. | 230 // window construction. This probably could use closer examination someday. |
1309 if (!GetActiveTabContents()) | 231 if (!browser_->GetActiveTabContents()) |
1310 return; | 232 return; |
1311 | 233 |
1312 DCHECK(command_updater_.IsCommandEnabled(id)) << "Invalid/disabled command " | 234 DCHECK(command_updater_.IsCommandEnabled(id)) << "Invalid/disabled command " |
1313 << id; | 235 << id; |
1314 | 236 |
1315 // If command execution is blocked then just record the command and return. | 237 // If command execution is blocked then just record the command and return. |
1316 if (block_command_execution_) { | 238 if (block_command_execution_) { |
1317 // We actually only allow no more than one blocked command, otherwise some | 239 // We actually only allow no more than one blocked command, otherwise some |
1318 // commands maybe lost. | 240 // commands maybe lost. |
1319 DCHECK_EQ(last_blocked_command_id_, -1); | 241 DCHECK_EQ(last_blocked_command_id_, -1); |
1320 last_blocked_command_id_ = id; | 242 last_blocked_command_id_ = id; |
1321 last_blocked_command_disposition_ = disposition; | 243 last_blocked_command_disposition_ = disposition; |
1322 return; | 244 return; |
1323 } | 245 } |
1324 | 246 |
1325 // The order of commands in this switch statement must match the function | 247 // The order of commands in this switch statement must match the function |
1326 // declaration order in browser.h! | 248 // declaration order in browser.h! |
1327 switch (id) { | 249 switch (id) { |
1328 // Navigation commands | 250 // Navigation commands |
1329 case IDC_BACK: chrome::GoBack(this, disposition);break; | 251 case IDC_BACK: |
| 252 GoBack(browser_, disposition); |
| 253 break; |
1330 case IDC_FORWARD: | 254 case IDC_FORWARD: |
1331 chrome::GoForward(this, disposition); | 255 GoForward(browser_, disposition); |
1332 break; | 256 break; |
1333 case IDC_RELOAD: chrome::Reload(this, disposition);break; | 257 case IDC_RELOAD: |
| 258 Reload(browser_, disposition); |
| 259 break; |
1334 case IDC_RELOAD_IGNORING_CACHE: | 260 case IDC_RELOAD_IGNORING_CACHE: |
1335 chrome::ReloadIgnoringCache(this, disposition); | 261 ReloadIgnoringCache(browser_, disposition); |
1336 break; | 262 break; |
1337 case IDC_HOME: chrome::Home(this, disposition); break; | 263 case IDC_HOME: |
1338 case IDC_OPEN_CURRENT_URL: chrome::OpenCurrentURL(this); break; | 264 Home(browser_, disposition); |
1339 case IDC_STOP: chrome::Stop(this); break; | 265 break; |
| 266 case IDC_OPEN_CURRENT_URL: |
| 267 OpenCurrentURL(browser_); |
| 268 break; |
| 269 case IDC_STOP: |
| 270 Stop(browser_); |
| 271 break; |
1340 | 272 |
1341 // Window management commands | 273 // Window management commands |
1342 case IDC_NEW_WINDOW: chrome::NewWindow(this); break; | 274 case IDC_NEW_WINDOW: |
1343 case IDC_NEW_INCOGNITO_WINDOW: chrome::NewIncognitoWindow(this); break; | 275 NewWindow(browser_); |
1344 case IDC_CLOSE_WINDOW: chrome::CloseWindow(this); break; | 276 break; |
1345 case IDC_NEW_TAB: chrome::NewTab(this); break; | 277 case IDC_NEW_INCOGNITO_WINDOW: |
1346 case IDC_CLOSE_TAB: chrome::CloseTab(this); break; | 278 NewIncognitoWindow(browser_); |
1347 case IDC_SELECT_NEXT_TAB: chrome::SelectNextTab(this); break; | 279 break; |
1348 case IDC_SELECT_PREVIOUS_TAB: chrome::SelectPreviousTab(this); break; | 280 case IDC_CLOSE_WINDOW: |
1349 case IDC_TABPOSE: chrome::OpenTabpose(this); break; | 281 CloseWindow(browser_); |
1350 case IDC_MOVE_TAB_NEXT: chrome::MoveTabNext(this); break; | 282 break; |
1351 case IDC_MOVE_TAB_PREVIOUS: chrome::MoveTabPrevious(this); break; | 283 case IDC_NEW_TAB: |
| 284 NewTab(browser_); |
| 285 break; |
| 286 case IDC_CLOSE_TAB: |
| 287 CloseTab(browser_); |
| 288 break; |
| 289 case IDC_SELECT_NEXT_TAB: |
| 290 SelectNextTab(browser_); |
| 291 break; |
| 292 case IDC_SELECT_PREVIOUS_TAB: |
| 293 SelectPreviousTab(browser_); |
| 294 break; |
| 295 case IDC_TABPOSE: |
| 296 OpenTabpose(browser_); |
| 297 break; |
| 298 case IDC_MOVE_TAB_NEXT: |
| 299 MoveTabNext(browser_); |
| 300 break; |
| 301 case IDC_MOVE_TAB_PREVIOUS: |
| 302 MoveTabPrevious(browser_); |
| 303 break; |
1352 case IDC_SELECT_TAB_0: | 304 case IDC_SELECT_TAB_0: |
1353 case IDC_SELECT_TAB_1: | 305 case IDC_SELECT_TAB_1: |
1354 case IDC_SELECT_TAB_2: | 306 case IDC_SELECT_TAB_2: |
1355 case IDC_SELECT_TAB_3: | 307 case IDC_SELECT_TAB_3: |
1356 case IDC_SELECT_TAB_4: | 308 case IDC_SELECT_TAB_4: |
1357 case IDC_SELECT_TAB_5: | 309 case IDC_SELECT_TAB_5: |
1358 case IDC_SELECT_TAB_6: | 310 case IDC_SELECT_TAB_6: |
1359 case IDC_SELECT_TAB_7: | 311 case IDC_SELECT_TAB_7: |
1360 chrome::SelectNumberedTab(this, id - IDC_SELECT_TAB_0); | 312 SelectNumberedTab(browser_, id - IDC_SELECT_TAB_0); |
1361 break; | 313 break; |
1362 case IDC_SELECT_LAST_TAB: chrome::SelectLastTab(this); break; | 314 case IDC_SELECT_LAST_TAB: |
1363 case IDC_DUPLICATE_TAB: chrome::DuplicateTab(this); break; | 315 SelectLastTab(browser_); |
1364 case IDC_RESTORE_TAB: RestoreTab(); break; | 316 break; |
| 317 case IDC_DUPLICATE_TAB: |
| 318 DuplicateTab(browser_); |
| 319 break; |
| 320 case IDC_RESTORE_TAB: |
| 321 RestoreTab(browser_); |
| 322 break; |
1365 case IDC_COPY_URL: | 323 case IDC_COPY_URL: |
1366 chrome::WriteCurrentURLToClipboard(this); | 324 WriteCurrentURLToClipboard(browser_); |
1367 break; | 325 break; |
1368 case IDC_SHOW_AS_TAB: | 326 case IDC_SHOW_AS_TAB: |
1369 chrome::ConvertPopupToTabbedBrowser(this); | 327 ConvertPopupToTabbedBrowser(browser_); |
1370 break; | 328 break; |
1371 case IDC_FULLSCREEN: ToggleFullscreenMode(); break; | 329 case IDC_FULLSCREEN: |
| 330 browser_->ToggleFullscreenMode(); |
| 331 break; |
1372 #if defined(OS_WIN) | 332 #if defined(OS_WIN) |
1373 case IDC_METRO_SNAP_ENABLE: SetMetroSnapMode(true); break; | 333 case IDC_METRO_SNAP_ENABLE: |
1374 case IDC_METRO_SNAP_DISABLE: SetMetroSnapMode(false); break; | 334 browser_->SetMetroSnapMode(true); |
| 335 break; |
| 336 case IDC_METRO_SNAP_DISABLE: |
| 337 browser_->SetMetroSnapMode(false); |
| 338 break; |
1375 #endif | 339 #endif |
1376 #if defined(OS_MACOSX) | 340 #if defined(OS_MACOSX) |
1377 case IDC_PRESENTATION_MODE: TogglePresentationMode(); break; | 341 case IDC_PRESENTATION_MODE: |
| 342 browser_->TogglePresentationMode(); |
| 343 break; |
1378 #endif | 344 #endif |
1379 case IDC_EXIT: chrome::Exit(); break; | 345 case IDC_EXIT: |
| 346 Exit(); |
| 347 break; |
1380 | 348 |
1381 // Page-related commands | 349 // Page-related commands |
1382 case IDC_SAVE_PAGE: chrome::SavePage(this); break; | 350 case IDC_SAVE_PAGE: |
1383 case IDC_BOOKMARK_PAGE: chrome::BookmarkCurrentPage(this);break; | 351 SavePage(browser_); |
| 352 break; |
| 353 case IDC_BOOKMARK_PAGE: |
| 354 BookmarkCurrentPage(browser_); |
| 355 break; |
1384 case IDC_PIN_TO_START_SCREEN: | 356 case IDC_PIN_TO_START_SCREEN: |
1385 chrome::PinCurrentPageToStartScreen(this); | 357 PinCurrentPageToStartScreen(browser_); |
1386 break; | 358 break; |
1387 case IDC_BOOKMARK_ALL_TABS: BookmarkAllTabs(); break; | 359 case IDC_BOOKMARK_ALL_TABS: |
1388 case IDC_VIEW_SOURCE: chrome::ViewSelectedSource(this); break; | 360 BookmarkAllTabs(browser_); |
1389 case IDC_EMAIL_PAGE_LOCATION: chrome::EmailPageLocation(this); break; | 361 break; |
1390 case IDC_PRINT: chrome::Print(this); break; | 362 case IDC_VIEW_SOURCE: |
1391 case IDC_ADVANCED_PRINT: chrome::AdvancedPrint(this); break; | 363 ViewSelectedSource(browser_); |
| 364 break; |
| 365 case IDC_EMAIL_PAGE_LOCATION: |
| 366 EmailPageLocation(browser_); |
| 367 break; |
| 368 case IDC_PRINT: |
| 369 Print(browser_); |
| 370 break; |
| 371 case IDC_ADVANCED_PRINT: |
| 372 AdvancedPrint(browser_); |
| 373 break; |
1392 case IDC_CHROME_TO_MOBILE_PAGE: | 374 case IDC_CHROME_TO_MOBILE_PAGE: |
1393 chrome::ShowChromeToMobileBubble(this); | 375 ShowChromeToMobileBubble(browser_); |
1394 break; | 376 break; |
1395 case IDC_ENCODING_AUTO_DETECT: ToggleEncodingAutoDetect(); break; | 377 case IDC_ENCODING_AUTO_DETECT: |
| 378 browser_->ToggleEncodingAutoDetect(); |
| 379 break; |
1396 case IDC_ENCODING_UTF8: | 380 case IDC_ENCODING_UTF8: |
1397 case IDC_ENCODING_UTF16LE: | 381 case IDC_ENCODING_UTF16LE: |
1398 case IDC_ENCODING_ISO88591: | 382 case IDC_ENCODING_ISO88591: |
1399 case IDC_ENCODING_WINDOWS1252: | 383 case IDC_ENCODING_WINDOWS1252: |
1400 case IDC_ENCODING_GBK: | 384 case IDC_ENCODING_GBK: |
1401 case IDC_ENCODING_GB18030: | 385 case IDC_ENCODING_GB18030: |
1402 case IDC_ENCODING_BIG5HKSCS: | 386 case IDC_ENCODING_BIG5HKSCS: |
1403 case IDC_ENCODING_BIG5: | 387 case IDC_ENCODING_BIG5: |
1404 case IDC_ENCODING_KOREAN: | 388 case IDC_ENCODING_KOREAN: |
1405 case IDC_ENCODING_SHIFTJIS: | 389 case IDC_ENCODING_SHIFTJIS: |
(...skipping 16 matching lines...) Expand all Loading... |
1422 case IDC_ENCODING_ISO88593: | 406 case IDC_ENCODING_ISO88593: |
1423 case IDC_ENCODING_ISO885910: | 407 case IDC_ENCODING_ISO885910: |
1424 case IDC_ENCODING_ISO885914: | 408 case IDC_ENCODING_ISO885914: |
1425 case IDC_ENCODING_ISO885916: | 409 case IDC_ENCODING_ISO885916: |
1426 case IDC_ENCODING_WINDOWS1254: | 410 case IDC_ENCODING_WINDOWS1254: |
1427 case IDC_ENCODING_ISO88596: | 411 case IDC_ENCODING_ISO88596: |
1428 case IDC_ENCODING_WINDOWS1256: | 412 case IDC_ENCODING_WINDOWS1256: |
1429 case IDC_ENCODING_ISO88598: | 413 case IDC_ENCODING_ISO88598: |
1430 case IDC_ENCODING_ISO88598I: | 414 case IDC_ENCODING_ISO88598I: |
1431 case IDC_ENCODING_WINDOWS1255: | 415 case IDC_ENCODING_WINDOWS1255: |
1432 case IDC_ENCODING_WINDOWS1258: OverrideEncoding(id); break; | 416 case IDC_ENCODING_WINDOWS1258: |
| 417 browser_->OverrideEncoding(id); |
| 418 break; |
1433 | 419 |
1434 // Clipboard commands | 420 // Clipboard commands |
1435 case IDC_CUT: chrome::Cut(this); break; | 421 case IDC_CUT: |
1436 case IDC_COPY: chrome::Copy(this); break; | 422 Cut(browser_); |
1437 case IDC_PASTE: chrome::Paste(this); break; | 423 break; |
| 424 case IDC_COPY: |
| 425 Copy(browser_); |
| 426 break; |
| 427 case IDC_PASTE: |
| 428 Paste(browser_); |
| 429 break; |
1438 | 430 |
1439 // Find-in-page | 431 // Find-in-page |
1440 case IDC_FIND: chrome::Find(this); break; | 432 case IDC_FIND: |
1441 case IDC_FIND_NEXT: chrome::FindNext(this); break; | 433 Find(browser_); |
1442 case IDC_FIND_PREVIOUS: chrome::FindPrevious(this); break; | 434 break; |
| 435 case IDC_FIND_NEXT: |
| 436 FindNext(browser_); |
| 437 break; |
| 438 case IDC_FIND_PREVIOUS: |
| 439 FindPrevious(browser_); |
| 440 break; |
1443 | 441 |
1444 // Zoom | 442 // Zoom |
1445 case IDC_ZOOM_PLUS: | 443 case IDC_ZOOM_PLUS: |
1446 chrome::Zoom(this, content::PAGE_ZOOM_IN); | 444 Zoom(browser_, content::PAGE_ZOOM_IN); |
1447 break; | 445 break; |
1448 case IDC_ZOOM_NORMAL: | 446 case IDC_ZOOM_NORMAL: |
1449 chrome::Zoom(this, content::PAGE_ZOOM_RESET); | 447 Zoom(browser_, content::PAGE_ZOOM_RESET); |
1450 break; | 448 break; |
1451 case IDC_ZOOM_MINUS: | 449 case IDC_ZOOM_MINUS: |
1452 chrome::Zoom(this, content::PAGE_ZOOM_OUT); | 450 Zoom(browser_, content::PAGE_ZOOM_OUT); |
1453 break; | 451 break; |
1454 | 452 |
1455 // Focus various bits of UI | 453 // Focus various bits of UI |
1456 case IDC_FOCUS_TOOLBAR: chrome::FocusToolbar(this); break; | 454 case IDC_FOCUS_TOOLBAR: |
1457 case IDC_FOCUS_LOCATION: chrome::FocusLocationBar(this); break; | 455 FocusToolbar(browser_); |
1458 case IDC_FOCUS_SEARCH: chrome::FocusSearch(this); break; | 456 break; |
1459 case IDC_FOCUS_MENU_BAR: chrome::FocusAppMenu(this); break; | 457 case IDC_FOCUS_LOCATION: |
| 458 FocusLocationBar(browser_); |
| 459 break; |
| 460 case IDC_FOCUS_SEARCH: |
| 461 FocusSearch(browser_); |
| 462 break; |
| 463 case IDC_FOCUS_MENU_BAR: |
| 464 FocusAppMenu(browser_); |
| 465 break; |
1460 case IDC_FOCUS_BOOKMARKS: | 466 case IDC_FOCUS_BOOKMARKS: |
1461 chrome::FocusBookmarksToolbar(this); | 467 FocusBookmarksToolbar(browser_); |
1462 break; | 468 break; |
1463 case IDC_FOCUS_NEXT_PANE: chrome::FocusNextPane(this); break; | 469 case IDC_FOCUS_NEXT_PANE: |
1464 case IDC_FOCUS_PREVIOUS_PANE: chrome::FocusPreviousPane(this); break; | 470 FocusNextPane(browser_); |
| 471 break; |
| 472 case IDC_FOCUS_PREVIOUS_PANE: |
| 473 FocusPreviousPane(browser_); |
| 474 break; |
1465 | 475 |
1466 // Show various bits of UI | 476 // Show various bits of UI |
1467 case IDC_OPEN_FILE: OpenFile(); break; | 477 case IDC_OPEN_FILE: |
1468 case IDC_CREATE_SHORTCUTS: OpenCreateShortcutsDialog(); break; | 478 browser_->OpenFile(); |
| 479 break; |
| 480 case IDC_CREATE_SHORTCUTS: |
| 481 browser_->OpenCreateShortcutsDialog(); |
| 482 break; |
1469 case IDC_DEV_TOOLS: | 483 case IDC_DEV_TOOLS: |
1470 chrome::ToggleDevToolsWindow(this, DEVTOOLS_TOGGLE_ACTION_NONE); | 484 ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_NONE); |
1471 break; | 485 break; |
1472 case IDC_DEV_TOOLS_CONSOLE: | 486 case IDC_DEV_TOOLS_CONSOLE: |
1473 chrome::ToggleDevToolsWindow(this, DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE); | 487 ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE); |
1474 break; | 488 break; |
1475 case IDC_DEV_TOOLS_INSPECT: | 489 case IDC_DEV_TOOLS_INSPECT: |
1476 chrome::ToggleDevToolsWindow(this, DEVTOOLS_TOGGLE_ACTION_INSPECT); | 490 ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_INSPECT); |
1477 break; | 491 break; |
1478 case IDC_TASK_MANAGER: | 492 case IDC_TASK_MANAGER: |
1479 chrome::OpenTaskManager(this, false); | 493 OpenTaskManager(browser_, false); |
1480 break; | 494 break; |
1481 case IDC_VIEW_BACKGROUND_PAGES: | 495 case IDC_VIEW_BACKGROUND_PAGES: |
1482 chrome::OpenTaskManager(this, true); | 496 OpenTaskManager(browser_, true); |
1483 break; | 497 break; |
1484 case IDC_FEEDBACK: | 498 case IDC_FEEDBACK: |
1485 chrome::OpenFeedbackDialog(this); | 499 OpenFeedbackDialog(browser_); |
1486 break; | 500 break; |
1487 | 501 |
1488 case IDC_SHOW_BOOKMARK_BAR: chrome::ToggleBookmarkBar(this); break; | 502 case IDC_SHOW_BOOKMARK_BAR: |
1489 case IDC_PROFILING_ENABLED: Profiling::Toggle(); break; | 503 ToggleBookmarkBar(browser_); |
| 504 break; |
| 505 case IDC_PROFILING_ENABLED: |
| 506 Profiling::Toggle(); |
| 507 break; |
1490 | 508 |
1491 case IDC_SHOW_BOOKMARK_MANAGER: chrome::ShowBookmarkManager(this);break; | 509 case IDC_SHOW_BOOKMARK_MANAGER: |
1492 case IDC_SHOW_APP_MENU: chrome::ShowAppMenu(this); break; | 510 ShowBookmarkManager(browser_); |
1493 case IDC_SHOW_AVATAR_MENU: chrome::ShowAvatarMenu(this); break; | 511 break; |
1494 case IDC_SHOW_HISTORY: chrome::ShowHistory(this); break; | 512 case IDC_SHOW_APP_MENU: |
1495 case IDC_SHOW_DOWNLOADS: chrome::ShowDownloads(this); break; | 513 ShowAppMenu(browser_); |
1496 case IDC_MANAGE_EXTENSIONS: chrome::ShowExtensions(this); break; | 514 break; |
1497 case IDC_OPTIONS: chrome::ShowSettings(this); break; | 515 case IDC_SHOW_AVATAR_MENU: |
| 516 ShowAvatarMenu(browser_); |
| 517 break; |
| 518 case IDC_SHOW_HISTORY: |
| 519 ShowHistory(browser_); |
| 520 break; |
| 521 case IDC_SHOW_DOWNLOADS: |
| 522 ShowDownloads(browser_); |
| 523 break; |
| 524 case IDC_MANAGE_EXTENSIONS: |
| 525 ShowExtensions(browser_); |
| 526 break; |
| 527 case IDC_OPTIONS: |
| 528 ShowSettings(browser_); |
| 529 break; |
1498 case IDC_EDIT_SEARCH_ENGINES: | 530 case IDC_EDIT_SEARCH_ENGINES: |
1499 chrome::ShowSearchEngineSettings(this); | 531 ShowSearchEngineSettings(browser_); |
1500 break; | 532 break; |
1501 case IDC_VIEW_PASSWORDS: chrome::ShowPasswordManager(this);break; | 533 case IDC_VIEW_PASSWORDS: |
| 534 ShowPasswordManager(browser_); |
| 535 break; |
1502 case IDC_CLEAR_BROWSING_DATA: | 536 case IDC_CLEAR_BROWSING_DATA: |
1503 chrome::ShowClearBrowsingDataDialog(this); | 537 ShowClearBrowsingDataDialog(browser_); |
1504 break; | 538 break; |
1505 case IDC_IMPORT_SETTINGS: chrome::ShowImportDialog(this); break; | 539 case IDC_IMPORT_SETTINGS: |
1506 case IDC_ABOUT: chrome::ShowAboutChrome(this); break; | 540 ShowImportDialog(browser_); |
| 541 break; |
| 542 case IDC_ABOUT: |
| 543 ShowAboutChrome(browser_); |
| 544 break; |
1507 case IDC_UPGRADE_DIALOG: | 545 case IDC_UPGRADE_DIALOG: |
1508 chrome::OpenUpdateChromeDialog(this); | 546 OpenUpdateChromeDialog(browser_); |
1509 break; | 547 break; |
1510 case IDC_VIEW_INCOMPATIBILITIES: | 548 case IDC_VIEW_INCOMPATIBILITIES: |
1511 chrome::ShowConflicts(this); | 549 ShowConflicts(browser_); |
1512 break; | 550 break; |
1513 case IDC_HELP_PAGE_VIA_KEYBOARD: | 551 case IDC_HELP_PAGE_VIA_KEYBOARD: |
1514 chrome::ShowHelp(this, chrome::HELP_SOURCE_KEYBOARD); | 552 ShowHelp(browser_, HELP_SOURCE_KEYBOARD); |
1515 break; | 553 break; |
1516 case IDC_HELP_PAGE_VIA_MENU: | 554 case IDC_HELP_PAGE_VIA_MENU: |
1517 chrome::ShowHelp(this, chrome::HELP_SOURCE_MENU); | 555 ShowHelp(browser_, HELP_SOURCE_MENU); |
1518 break; | 556 break; |
1519 case IDC_SHOW_SYNC_SETUP: | 557 case IDC_SHOW_SYNC_SETUP: |
1520 chrome::ShowSyncSetup(this, SyncPromoUI::SOURCE_MENU); | 558 ShowSyncSetup(browser_, SyncPromoUI::SOURCE_MENU); |
1521 break; | 559 break; |
1522 case IDC_TOGGLE_SPEECH_INPUT: chrome::ToggleSpeechInput(this); break; | 560 case IDC_TOGGLE_SPEECH_INPUT: |
| 561 ToggleSpeechInput(browser_); |
| 562 break; |
1523 | 563 |
1524 default: | 564 default: |
1525 LOG(WARNING) << "Received Unimplemented Command: " << id; | 565 LOG(WARNING) << "Received Unimplemented Command: " << id; |
1526 break; | 566 break; |
1527 } | 567 } |
1528 } | 568 } |
1529 | 569 |
1530 //////////////////////////////////////////////////////////////////////////////// | 570 //////////////////////////////////////////////////////////////////////////////// |
1531 // Browser, TabRestoreServiceObserver: | 571 // BrowserCommandController, content::NotificationObserver implementation: |
1532 | 572 |
1533 void Browser::TabRestoreServiceChanged(TabRestoreService* service) { | 573 void BrowserCommandController::Observe( |
1534 command_updater_.UpdateCommandEnabled(IDC_RESTORE_TAB, | 574 int type, |
1535 !service->entries().empty()); | 575 const content::NotificationSource& source, |
1536 } | 576 const content::NotificationDetails& details) { |
1537 | |
1538 void Browser::TabRestoreServiceDestroyed(TabRestoreService* service) { | |
1539 if (!tab_restore_service_) | |
1540 return; | |
1541 | |
1542 DCHECK_EQ(tab_restore_service_, service); | |
1543 tab_restore_service_->RemoveObserver(this); | |
1544 tab_restore_service_ = NULL; | |
1545 } | |
1546 | |
1547 // Centralized method for creating a TabContents, configuring and | |
1548 // installing all its supporting objects and observers. | |
1549 TabContents* Browser::TabContentsFactory( | |
1550 Profile* profile, | |
1551 SiteInstance* site_instance, | |
1552 int routing_id, | |
1553 const WebContents* base_web_contents, | |
1554 content::SessionStorageNamespace* session_storage_namespace) { | |
1555 WebContents* new_contents = WebContents::Create( | |
1556 profile, site_instance, routing_id, base_web_contents, | |
1557 session_storage_namespace); | |
1558 TabContents* tab_contents = new TabContents(new_contents); | |
1559 return tab_contents; | |
1560 } | |
1561 | |
1562 /////////////////////////////////////////////////////////////////////////////// | |
1563 // Browser, TabStripModelDelegate implementation: | |
1564 | |
1565 TabContents* Browser::AddBlankTab(bool foreground) { | |
1566 return AddBlankTabAt(-1, foreground); | |
1567 } | |
1568 | |
1569 TabContents* Browser::AddBlankTabAt(int index, bool foreground) { | |
1570 // Time new tab page creation time. We keep track of the timing data in | |
1571 // WebContents, but we want to include the time it takes to create the | |
1572 // WebContents object too. | |
1573 base::TimeTicks new_tab_start_time = base::TimeTicks::Now(); | |
1574 browser::NavigateParams params(this, GURL(chrome::kChromeUINewTabURL), | |
1575 content::PAGE_TRANSITION_TYPED); | |
1576 params.disposition = foreground ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB; | |
1577 params.tabstrip_index = index; | |
1578 browser::Navigate(¶ms); | |
1579 params.target_contents->web_contents()->SetNewTabStartTime( | |
1580 new_tab_start_time); | |
1581 return params.target_contents; | |
1582 } | |
1583 | |
1584 Browser* Browser::CreateNewStripWithContents( | |
1585 TabContents* detached_contents, | |
1586 const gfx::Rect& window_bounds, | |
1587 const DockInfo& dock_info, | |
1588 bool maximize) { | |
1589 DCHECK(CanSupportWindowFeature(FEATURE_TABSTRIP)); | |
1590 | |
1591 gfx::Rect new_window_bounds = window_bounds; | |
1592 if (dock_info.GetNewWindowBounds(&new_window_bounds, &maximize)) | |
1593 dock_info.AdjustOtherWindowBounds(); | |
1594 | |
1595 // Create an empty new browser window the same size as the old one. | |
1596 Browser* browser = new Browser(TYPE_TABBED, profile_); | |
1597 browser->set_override_bounds(new_window_bounds); | |
1598 browser->set_initial_show_state( | |
1599 maximize ? ui::SHOW_STATE_MAXIMIZED : ui::SHOW_STATE_NORMAL); | |
1600 browser->InitBrowserWindow(); | |
1601 browser->tab_strip_model()->AppendTabContents(detached_contents, true); | |
1602 // Make sure the loading state is updated correctly, otherwise the throbber | |
1603 // won't start if the page is loading. | |
1604 browser->LoadingStateChanged(detached_contents->web_contents()); | |
1605 return browser; | |
1606 } | |
1607 | |
1608 int Browser::GetDragActions() const { | |
1609 return TabStripModelDelegate::TAB_TEAROFF_ACTION | (tab_count() > 1 ? | |
1610 TabStripModelDelegate::TAB_MOVE_ACTION : 0); | |
1611 } | |
1612 | |
1613 TabContents* Browser::CreateTabContentsForURL( | |
1614 const GURL& url, const content::Referrer& referrer, Profile* profile, | |
1615 content::PageTransition transition, bool defer_load, | |
1616 SiteInstance* instance) const { | |
1617 TabContents* contents = TabContentsFactory(profile, instance, | |
1618 MSG_ROUTING_NONE, GetActiveWebContents(), NULL); | |
1619 if (!defer_load) { | |
1620 // Load the initial URL before adding the new tab contents to the tab strip | |
1621 // so that the tab contents has navigation state. | |
1622 contents->web_contents()->GetController().LoadURL( | |
1623 url, referrer, transition, std::string()); | |
1624 } | |
1625 | |
1626 return contents; | |
1627 } | |
1628 | |
1629 bool Browser::CanDuplicateContentsAt(int index) { | |
1630 NavigationController& nc = GetWebContentsAt(index)->GetController(); | |
1631 return nc.GetWebContents() && nc.GetLastCommittedEntry(); | |
1632 } | |
1633 | |
1634 void Browser::DuplicateContentsAt(int index) { | |
1635 TabContents* contents = GetTabContentsAt(index); | |
1636 CHECK(contents); | |
1637 TabContents* contents_dupe = contents->Clone(); | |
1638 | |
1639 bool pinned = false; | |
1640 if (CanSupportWindowFeature(FEATURE_TABSTRIP)) { | |
1641 // If this is a tabbed browser, just create a duplicate tab inside the same | |
1642 // window next to the tab being duplicated. | |
1643 int index = tab_strip_model_->GetIndexOfTabContents(contents); | |
1644 pinned = IsTabPinned(index); | |
1645 int add_types = TabStripModel::ADD_ACTIVE | | |
1646 TabStripModel::ADD_INHERIT_GROUP | | |
1647 (pinned ? TabStripModel::ADD_PINNED : 0); | |
1648 tab_strip_model_->InsertTabContentsAt(index + 1, contents_dupe, add_types); | |
1649 } else { | |
1650 Browser* browser = NULL; | |
1651 if (is_app()) { | |
1652 CHECK(!is_type_popup()); | |
1653 CHECK(!is_type_panel()); | |
1654 browser = Browser::CreateWithParams( | |
1655 Browser::CreateParams::CreateForApp( | |
1656 TYPE_POPUP, app_name_, gfx::Rect(),profile_)); | |
1657 } else if (is_type_popup()) { | |
1658 browser = Browser::CreateWithParams( | |
1659 Browser::CreateParams(TYPE_POPUP, profile_)); | |
1660 } | |
1661 | |
1662 // Preserve the size of the original window. The new window has already | |
1663 // been given an offset by the OS, so we shouldn't copy the old bounds. | |
1664 BrowserWindow* new_window = browser->window(); | |
1665 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(), | |
1666 window()->GetRestoredBounds().size())); | |
1667 | |
1668 // We need to show the browser now. Otherwise ContainerWin assumes the | |
1669 // WebContents is invisible and won't size it. | |
1670 browser->window()->Show(); | |
1671 | |
1672 // The page transition below is only for the purpose of inserting the tab. | |
1673 browser->AddTab(contents_dupe, content::PAGE_TRANSITION_LINK); | |
1674 } | |
1675 | |
1676 SessionService* session_service = | |
1677 SessionServiceFactory::GetForProfileIfExisting(profile_); | |
1678 if (session_service) | |
1679 session_service->TabRestored(contents_dupe, pinned); | |
1680 } | |
1681 | |
1682 void Browser::CloseFrameAfterDragSession() { | |
1683 #if !defined(OS_MACOSX) | |
1684 // This is scheduled to run after we return to the message loop because | |
1685 // otherwise the frame will think the drag session is still active and ignore | |
1686 // the request. | |
1687 // TODO(port): figure out what is required here in a cross-platform world | |
1688 MessageLoop::current()->PostTask( | |
1689 FROM_HERE, base::Bind(&Browser::CloseFrame, weak_factory_.GetWeakPtr())); | |
1690 #endif | |
1691 } | |
1692 | |
1693 void Browser::CreateHistoricalTab(TabContents* contents) { | |
1694 // We don't create historical tabs for incognito windows or windows without | |
1695 // profiles. | |
1696 if (!profile() || profile()->IsOffTheRecord()) | |
1697 return; | |
1698 | |
1699 // We don't create historical tabs for print preview tabs. | |
1700 if (contents->web_contents()->GetURL() == GURL(chrome::kChromeUIPrintURL)) | |
1701 return; | |
1702 | |
1703 TabRestoreService* service = | |
1704 TabRestoreServiceFactory::GetForProfile(profile()); | |
1705 | |
1706 // We only create historical tab entries for tabbed browser windows. | |
1707 if (service && CanSupportWindowFeature(FEATURE_TABSTRIP)) { | |
1708 service->CreateHistoricalTab(contents->web_contents(), | |
1709 tab_strip_model_->GetIndexOfTabContents(contents)); | |
1710 } | |
1711 } | |
1712 | |
1713 bool Browser::RunUnloadListenerBeforeClosing(TabContents* contents) { | |
1714 return Browser::RunUnloadEventsHelper(contents->web_contents()); | |
1715 } | |
1716 | |
1717 bool Browser::CanBookmarkAllTabs() const { | |
1718 BookmarkModel* model = profile()->GetBookmarkModel(); | |
1719 return (model && model->IsLoaded()) && | |
1720 tab_count() > 1 && | |
1721 profile()->GetPrefs()->GetBoolean(prefs::kEditBookmarksEnabled); | |
1722 } | |
1723 | |
1724 void Browser::BookmarkAllTabs() { | |
1725 BookmarkEditor::ShowBookmarkAllTabsDialog(this); | |
1726 } | |
1727 | |
1728 bool Browser::CanRestoreTab() { | |
1729 return command_updater_.IsCommandEnabled(IDC_RESTORE_TAB); | |
1730 } | |
1731 | |
1732 void Browser::RestoreTab() { | |
1733 content::RecordAction(UserMetricsAction("RestoreTab")); | |
1734 TabRestoreService* service = | |
1735 TabRestoreServiceFactory::GetForProfile(profile_); | |
1736 if (!service) | |
1737 return; | |
1738 | |
1739 service->RestoreMostRecentEntry(tab_restore_service_delegate()); | |
1740 } | |
1741 | |
1742 /////////////////////////////////////////////////////////////////////////////// | |
1743 // Browser, TabStripModelObserver implementation: | |
1744 | |
1745 void Browser::TabInsertedAt(TabContents* contents, | |
1746 int index, | |
1747 bool foreground) { | |
1748 SetAsDelegate(contents, this); | |
1749 contents->restore_tab_helper()->SetWindowID(session_id()); | |
1750 | |
1751 SyncHistoryWithTabs(index); | |
1752 | |
1753 // Make sure the loading state is updated correctly, otherwise the throbber | |
1754 // won't start if the page is loading. | |
1755 LoadingStateChanged(contents->web_contents()); | |
1756 | |
1757 // If the tab crashes in the beforeunload or unload handler, it won't be | |
1758 // able to ack. But we know we can close it. | |
1759 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, | |
1760 content::Source<WebContents>(contents->web_contents())); | |
1761 | |
1762 registrar_.Add(this, content::NOTIFICATION_INTERSTITIAL_ATTACHED, | |
1763 content::Source<WebContents>(contents->web_contents())); | |
1764 | |
1765 registrar_.Add(this, content::NOTIFICATION_INTERSTITIAL_DETACHED, | |
1766 content::Source<WebContents>(contents->web_contents())); | |
1767 } | |
1768 | |
1769 void Browser::TabClosingAt(TabStripModel* tab_strip_model, | |
1770 TabContents* contents, | |
1771 int index) { | |
1772 fullscreen_controller_->OnTabClosing(contents->web_contents()); | |
1773 content::NotificationService::current()->Notify( | |
1774 chrome::NOTIFICATION_TAB_CLOSING, | |
1775 content::Source<NavigationController>( | |
1776 &contents->web_contents()->GetController()), | |
1777 content::NotificationService::NoDetails()); | |
1778 | |
1779 // Sever the WebContents' connection back to us. | |
1780 SetAsDelegate(contents, NULL); | |
1781 } | |
1782 | |
1783 void Browser::TabDetachedAt(TabContents* contents, int index) { | |
1784 TabDetachedAtImpl(contents, index, DETACH_TYPE_DETACH); | |
1785 } | |
1786 | |
1787 void Browser::TabDeactivated(TabContents* contents) { | |
1788 fullscreen_controller_->OnTabDeactivated(contents); | |
1789 search_delegate_->OnTabDeactivated(contents); | |
1790 | |
1791 if (instant()) | |
1792 instant()->Hide(); | |
1793 | |
1794 // Save what the user's currently typing, so it can be restored when we | |
1795 // switch back to this tab. | |
1796 window_->GetLocationBar()->SaveStateToContents(contents->web_contents()); | |
1797 } | |
1798 | |
1799 void Browser::ActiveTabChanged(TabContents* old_contents, | |
1800 TabContents* new_contents, | |
1801 int index, | |
1802 bool user_gesture) { | |
1803 // On some platforms we want to automatically reload tabs that are | |
1804 // killed when the user selects them. | |
1805 bool did_reload = false; | |
1806 if (user_gesture && new_contents->web_contents()->GetCrashedStatus() == | |
1807 base::TERMINATION_STATUS_PROCESS_WAS_KILLED) { | |
1808 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); | |
1809 if (parsed_command_line.HasSwitch(switches::kReloadKilledTabs)) { | |
1810 LOG(WARNING) << "Reloading killed tab at " << index; | |
1811 static int reload_count = 0; | |
1812 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
1813 "Tabs.SadTab.ReloadCount", ++reload_count, 1, 1000, 50); | |
1814 chrome::Reload(this, CURRENT_TAB); | |
1815 did_reload = true; | |
1816 } | |
1817 } | |
1818 | |
1819 // Discarded tabs always get reloaded. | |
1820 if (!did_reload && IsTabDiscarded(index)) { | |
1821 LOG(WARNING) << "Reloading discarded tab at " << index; | |
1822 static int reload_count = 0; | |
1823 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
1824 "Tabs.Discard.ReloadCount", ++reload_count, 1, 1000, 50); | |
1825 chrome::Reload(this, CURRENT_TAB); | |
1826 } | |
1827 | |
1828 // If we have any update pending, do it now. | |
1829 if (chrome_updater_factory_.HasWeakPtrs() && old_contents) | |
1830 ProcessPendingUIUpdates(); | |
1831 | |
1832 // Propagate the profile to the location bar. | |
1833 UpdateToolbar(true); | |
1834 | |
1835 // Propagate tab state to toolbar, tab-strip, etc. | |
1836 UpdateSearchState(new_contents); | |
1837 | |
1838 // Update reload/stop state. | |
1839 UpdateReloadStopState(new_contents->web_contents()->IsLoading(), true); | |
1840 | |
1841 // Update commands to reflect current state. | |
1842 UpdateCommandsForTabState(); | |
1843 | |
1844 // Reset the status bubble. | |
1845 StatusBubble* status_bubble = GetStatusBubble(); | |
1846 if (status_bubble) { | |
1847 status_bubble->Hide(); | |
1848 | |
1849 // Show the loading state (if any). | |
1850 status_bubble->SetStatus( | |
1851 GetActiveTabContents()->core_tab_helper()->GetStatusText()); | |
1852 } | |
1853 | |
1854 if (HasFindBarController()) { | |
1855 find_bar_controller_->ChangeTabContents(new_contents); | |
1856 find_bar_controller_->find_bar()->MoveWindowIfNecessary(gfx::Rect(), true); | |
1857 } | |
1858 | |
1859 // Update sessions. Don't force creation of sessions. If sessions doesn't | |
1860 // exist, the change will be picked up by sessions when created. | |
1861 SessionService* session_service = | |
1862 SessionServiceFactory::GetForProfileIfExisting(profile_); | |
1863 if (session_service && !tab_strip_model_->closing_all()) { | |
1864 session_service->SetSelectedTabInWindow(session_id(), active_index()); | |
1865 } | |
1866 | |
1867 UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_SWITCH); | |
1868 } | |
1869 | |
1870 void Browser::TabMoved(TabContents* contents, | |
1871 int from_index, | |
1872 int to_index) { | |
1873 DCHECK(from_index >= 0 && to_index >= 0); | |
1874 // Notify the history service. | |
1875 SyncHistoryWithTabs(std::min(from_index, to_index)); | |
1876 } | |
1877 | |
1878 void Browser::TabReplacedAt(TabStripModel* tab_strip_model, | |
1879 TabContents* old_contents, | |
1880 TabContents* new_contents, | |
1881 int index) { | |
1882 TabDetachedAtImpl(old_contents, index, DETACH_TYPE_REPLACE); | |
1883 TabInsertedAt(new_contents, index, (index == active_index())); | |
1884 | |
1885 int entry_count = | |
1886 new_contents->web_contents()->GetController().GetEntryCount(); | |
1887 if (entry_count > 0) { | |
1888 // Send out notification so that observers are updated appropriately. | |
1889 new_contents->web_contents()->GetController().NotifyEntryChanged( | |
1890 new_contents->web_contents()->GetController().GetEntryAtIndex( | |
1891 entry_count - 1), | |
1892 entry_count - 1); | |
1893 } | |
1894 | |
1895 SessionService* session_service = | |
1896 SessionServiceFactory::GetForProfile(profile()); | |
1897 if (session_service) { | |
1898 // The new_contents may end up with a different navigation stack. Force | |
1899 // the session service to update itself. | |
1900 session_service->TabRestored(new_contents, IsTabPinned(index)); | |
1901 } | |
1902 | |
1903 content::DevToolsManager::GetInstance()->ContentsReplaced( | |
1904 old_contents->web_contents(), new_contents->web_contents()); | |
1905 } | |
1906 | |
1907 void Browser::TabPinnedStateChanged(TabContents* contents, int index) { | |
1908 SessionService* session_service = | |
1909 SessionServiceFactory::GetForProfileIfExisting(profile()); | |
1910 if (session_service) { | |
1911 session_service->SetPinnedState( | |
1912 session_id(), | |
1913 GetTabContentsAt(index)->restore_tab_helper()->session_id(), | |
1914 IsTabPinned(index)); | |
1915 } | |
1916 } | |
1917 | |
1918 void Browser::TabStripEmpty() { | |
1919 // Close the frame after we return to the message loop (not immediately, | |
1920 // otherwise it will destroy this object before the stack has a chance to | |
1921 // cleanly unwind.) | |
1922 // Note: This will be called several times if TabStripEmpty is called several | |
1923 // times. This is because it does not close the window if tabs are | |
1924 // still present. | |
1925 MessageLoop::current()->PostTask( | |
1926 FROM_HERE, base::Bind(&Browser::CloseFrame, weak_factory_.GetWeakPtr())); | |
1927 // Set is_attempting_to_close_browser_ here, so that extensions, etc, do not | |
1928 // attempt to add tabs to the browser before it closes. | |
1929 is_attempting_to_close_browser_ = true; | |
1930 } | |
1931 | |
1932 bool Browser::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, | |
1933 bool* is_keyboard_shortcut) { | |
1934 // Escape exits tabbed fullscreen mode. | |
1935 // TODO(koz): Write a test for this http://crbug.com/100441. | |
1936 if (event.windowsKeyCode == 27 && | |
1937 fullscreen_controller_->HandleUserPressedEscape()) { | |
1938 return true; | |
1939 } | |
1940 return window()->PreHandleKeyboardEvent(event, is_keyboard_shortcut); | |
1941 } | |
1942 | |
1943 void Browser::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { | |
1944 window()->HandleKeyboardEvent(event); | |
1945 } | |
1946 | |
1947 void Browser::OnAcceptFullscreenPermission( | |
1948 const GURL& url, | |
1949 FullscreenExitBubbleType bubble_type) { | |
1950 fullscreen_controller_->OnAcceptFullscreenPermission(url, bubble_type); | |
1951 } | |
1952 | |
1953 void Browser::OnDenyFullscreenPermission(FullscreenExitBubbleType bubble_type) { | |
1954 fullscreen_controller_->OnDenyFullscreenPermission(bubble_type); | |
1955 } | |
1956 | |
1957 bool Browser::TabsNeedBeforeUnloadFired() { | |
1958 if (tabs_needing_before_unload_fired_.empty()) { | |
1959 for (int i = 0; i < tab_count(); ++i) { | |
1960 WebContents* contents = GetTabContentsAt(i)->web_contents(); | |
1961 if (contents->NeedToFireBeforeUnload()) | |
1962 tabs_needing_before_unload_fired_.insert(contents); | |
1963 } | |
1964 } | |
1965 return !tabs_needing_before_unload_fired_.empty(); | |
1966 } | |
1967 | |
1968 bool Browser::IsFullscreenForTabOrPending() const { | |
1969 return fullscreen_controller_->IsFullscreenForTabOrPending(); | |
1970 } | |
1971 | |
1972 bool Browser::IsMouseLocked() const { | |
1973 return fullscreen_controller_->IsMouseLocked(); | |
1974 } | |
1975 | |
1976 void Browser::OnWindowDidShow() { | |
1977 if (window_has_shown_) | |
1978 return; | |
1979 window_has_shown_ = true; | |
1980 | |
1981 // Nothing to do for non-tabbed windows. | |
1982 if (!is_type_tabbed()) | |
1983 return; | |
1984 | |
1985 // Show any pending global error bubble. | |
1986 GlobalErrorService* service = | |
1987 GlobalErrorServiceFactory::GetForProfile(profile()); | |
1988 GlobalError* error = service->GetFirstGlobalErrorWithBubbleView(); | |
1989 if (error) | |
1990 error->ShowBubbleView(this); | |
1991 } | |
1992 | |
1993 void Browser::ShowFirstRunBubble() { | |
1994 window()->GetLocationBar()->ShowFirstRunBubble(); | |
1995 } | |
1996 | |
1997 /////////////////////////////////////////////////////////////////////////////// | |
1998 // Browser, protected: | |
1999 | |
2000 BrowserWindow* Browser::CreateBrowserWindow() { | |
2001 bool create_panel = false; | |
2002 #if defined(USE_ASH) | |
2003 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
2004 ash::switches::kAuraPanelManager)) | |
2005 create_panel = is_type_panel(); | |
2006 #elif !defined(OS_CHROMEOS) | |
2007 create_panel = is_type_panel(); | |
2008 #endif | |
2009 if (create_panel) | |
2010 return PanelManager::GetInstance()->CreatePanel(this)->browser_window(); | |
2011 | |
2012 return BrowserWindow::CreateBrowserWindow(this); | |
2013 } | |
2014 | |
2015 /////////////////////////////////////////////////////////////////////////////// | |
2016 // Browser, content::WebContentsDelegate implementation: | |
2017 | |
2018 WebContents* Browser::OpenURLFromTab(WebContents* source, | |
2019 const OpenURLParams& params) { | |
2020 browser::NavigateParams nav_params(this, params.url, params.transition); | |
2021 nav_params.source_contents = GetTabContentsAt( | |
2022 tab_strip_model_->GetIndexOfWebContents(source)); | |
2023 nav_params.referrer = params.referrer; | |
2024 nav_params.disposition = params.disposition; | |
2025 nav_params.tabstrip_add_types = TabStripModel::ADD_NONE; | |
2026 nav_params.window_action = browser::NavigateParams::SHOW_WINDOW; | |
2027 nav_params.user_gesture = true; | |
2028 nav_params.override_encoding = params.override_encoding; | |
2029 nav_params.is_renderer_initiated = params.is_renderer_initiated; | |
2030 nav_params.transferred_global_request_id = | |
2031 params.transferred_global_request_id; | |
2032 browser::Navigate(&nav_params); | |
2033 | |
2034 return nav_params.target_contents ? | |
2035 nav_params.target_contents->web_contents() : NULL; | |
2036 } | |
2037 | |
2038 void Browser::NavigationStateChanged(const WebContents* source, | |
2039 unsigned changed_flags) { | |
2040 // Only update the UI when something visible has changed. | |
2041 if (changed_flags) | |
2042 ScheduleUIUpdate(source, changed_flags); | |
2043 | |
2044 // We can synchronously update commands since they will only change once per | |
2045 // navigation, so we don't have to worry about flickering. We do, however, | |
2046 // need to update the command state early on load to always present usable | |
2047 // actions in the face of slow-to-commit pages. | |
2048 if (changed_flags & (content::INVALIDATE_TYPE_URL | | |
2049 content::INVALIDATE_TYPE_LOAD)) | |
2050 UpdateCommandsForTabState(); | |
2051 } | |
2052 | |
2053 void Browser::AddNewContents(WebContents* source, | |
2054 WebContents* new_contents, | |
2055 WindowOpenDisposition disposition, | |
2056 const gfx::Rect& initial_pos, | |
2057 bool user_gesture) { | |
2058 // No code for this yet. | |
2059 DCHECK(disposition != SAVE_TO_DISK); | |
2060 // Can't create a new contents for the current tab - invalid case. | |
2061 DCHECK(disposition != CURRENT_TAB); | |
2062 | |
2063 TabContents* source_tab_contents = NULL; | |
2064 BlockedContentTabHelper* source_blocked_content = NULL; | |
2065 TabContents* new_tab_contents = TabContents::FromWebContents(new_contents); | |
2066 if (!new_tab_contents) { | |
2067 new_tab_contents = new TabContents(new_contents); | |
2068 } | |
2069 if (source) { | |
2070 source_tab_contents = TabContents::FromWebContents(source); | |
2071 source_blocked_content = source_tab_contents->blocked_content_tab_helper(); | |
2072 } | |
2073 | |
2074 if (source_tab_contents) { | |
2075 // Handle blocking of all contents. | |
2076 if (source_blocked_content->all_contents_blocked()) { | |
2077 source_blocked_content->AddTabContents(new_tab_contents, | |
2078 disposition, | |
2079 initial_pos, | |
2080 user_gesture); | |
2081 return; | |
2082 } | |
2083 | |
2084 // Handle blocking of popups. | |
2085 if ((disposition == NEW_POPUP) && !user_gesture && | |
2086 !CommandLine::ForCurrentProcess()->HasSwitch( | |
2087 switches::kDisablePopupBlocking)) { | |
2088 // Unrequested popups from normal pages are constrained unless they're in | |
2089 // the whitelist. The popup owner will handle checking this. | |
2090 GetConstrainingTabContents(source_tab_contents)-> | |
2091 blocked_content_tab_helper()-> | |
2092 AddPopup(new_tab_contents, initial_pos, user_gesture); | |
2093 return; | |
2094 } | |
2095 | |
2096 new_contents->GetRenderViewHost()->DisassociateFromPopupCount(); | |
2097 } | |
2098 | |
2099 browser::NavigateParams params(this, new_tab_contents); | |
2100 params.source_contents = source ? | |
2101 GetTabContentsAt(tab_strip_model_->GetIndexOfWebContents(source)): NULL; | |
2102 params.disposition = disposition; | |
2103 params.window_bounds = initial_pos; | |
2104 params.window_action = browser::NavigateParams::SHOW_WINDOW; | |
2105 params.user_gesture = user_gesture; | |
2106 browser::Navigate(¶ms); | |
2107 } | |
2108 | |
2109 void Browser::ActivateContents(WebContents* contents) { | |
2110 ActivateTabAt(tab_strip_model_->GetIndexOfWebContents(contents), false); | |
2111 window_->Activate(); | |
2112 } | |
2113 | |
2114 void Browser::DeactivateContents(WebContents* contents) { | |
2115 window_->Deactivate(); | |
2116 } | |
2117 | |
2118 void Browser::LoadingStateChanged(WebContents* source) { | |
2119 window_->UpdateLoadingAnimations(tab_strip_model_->TabsAreLoading()); | |
2120 window_->UpdateTitleBar(); | |
2121 | |
2122 WebContents* selected_contents = GetActiveWebContents(); | |
2123 if (source == selected_contents) { | |
2124 bool is_loading = source->IsLoading(); | |
2125 UpdateReloadStopState(is_loading, false); | |
2126 if (GetStatusBubble()) { | |
2127 GetStatusBubble()->SetStatus( | |
2128 GetActiveTabContents()->core_tab_helper()->GetStatusText()); | |
2129 } | |
2130 | |
2131 if (!is_loading && pending_web_app_action_ == UPDATE_SHORTCUT) { | |
2132 // Schedule a shortcut update when web application info is available if | |
2133 // last committed entry is not NULL. Last committed entry could be NULL | |
2134 // when an interstitial page is injected (e.g. bad https certificate, | |
2135 // malware site etc). When this happens, we abort the shortcut update. | |
2136 NavigationEntry* entry = source->GetController().GetLastCommittedEntry(); | |
2137 if (entry) { | |
2138 TabContents::FromWebContents(source)-> | |
2139 extension_tab_helper()->GetApplicationInfo(entry->GetPageID()); | |
2140 } else { | |
2141 pending_web_app_action_ = NONE; | |
2142 } | |
2143 } | |
2144 } | |
2145 } | |
2146 | |
2147 void Browser::CloseContents(WebContents* source) { | |
2148 if (is_attempting_to_close_browser_) { | |
2149 // If we're trying to close the browser, just clear the state related to | |
2150 // waiting for unload to fire. Don't actually try to close the tab as it | |
2151 // will go down the slow shutdown path instead of the fast path of killing | |
2152 // all the renderer processes. | |
2153 ClearUnloadState(source, true); | |
2154 return; | |
2155 } | |
2156 | |
2157 int index = tab_strip_model_->GetIndexOfWebContents(source); | |
2158 if (index == TabStripModel::kNoTab) { | |
2159 NOTREACHED() << "CloseContents called for tab not in our strip"; | |
2160 return; | |
2161 } | |
2162 tab_strip_model_->CloseTabContentsAt(index, | |
2163 TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); | |
2164 } | |
2165 | |
2166 void Browser::MoveContents(WebContents* source, const gfx::Rect& pos) { | |
2167 if (!IsPopupOrPanel(source)) { | |
2168 NOTREACHED() << "moving invalid browser type"; | |
2169 return; | |
2170 } | |
2171 window_->SetBounds(pos); | |
2172 } | |
2173 | |
2174 void Browser::DetachContents(WebContents* source) { | |
2175 int index = tab_strip_model_->GetIndexOfWebContents(source); | |
2176 if (index >= 0) | |
2177 tab_strip_model_->DetachTabContentsAt(index); | |
2178 } | |
2179 | |
2180 bool Browser::IsPopupOrPanel(const WebContents* source) const { | |
2181 // A non-tabbed BROWSER is an unconstrained popup. | |
2182 return is_type_popup() || is_type_panel(); | |
2183 } | |
2184 | |
2185 void Browser::UpdateTargetURL(WebContents* source, int32 page_id, | |
2186 const GURL& url) { | |
2187 if (!GetStatusBubble()) | |
2188 return; | |
2189 | |
2190 if (source == GetActiveWebContents()) { | |
2191 PrefService* prefs = profile_->GetPrefs(); | |
2192 GetStatusBubble()->SetURL(url, prefs->GetString(prefs::kAcceptLanguages)); | |
2193 } | |
2194 } | |
2195 | |
2196 void Browser::ContentsMouseEvent( | |
2197 WebContents* source, const gfx::Point& location, bool motion) { | |
2198 if (!GetStatusBubble()) | |
2199 return; | |
2200 | |
2201 if (source == GetActiveWebContents()) { | |
2202 GetStatusBubble()->MouseMoved(location, !motion); | |
2203 if (!motion) | |
2204 GetStatusBubble()->SetURL(GURL(), std::string()); | |
2205 } | |
2206 } | |
2207 | |
2208 void Browser::ContentsZoomChange(bool zoom_in) { | |
2209 ExecuteCommand(zoom_in ? IDC_ZOOM_PLUS : IDC_ZOOM_MINUS); | |
2210 } | |
2211 | |
2212 void Browser::WebContentsFocused(WebContents* contents) { | |
2213 window_->WebContentsFocused(contents); | |
2214 } | |
2215 | |
2216 bool Browser::TakeFocus(bool reverse) { | |
2217 content::NotificationService::current()->Notify( | |
2218 chrome::NOTIFICATION_FOCUS_RETURNED_TO_BROWSER, | |
2219 content::Source<Browser>(this), | |
2220 content::NotificationService::NoDetails()); | |
2221 return false; | |
2222 } | |
2223 | |
2224 bool Browser::IsApplication() const { | |
2225 return is_app(); | |
2226 } | |
2227 | |
2228 void Browser::ConvertContentsToApplication(WebContents* contents) { | |
2229 const GURL& url = contents->GetController().GetActiveEntry()->GetURL(); | |
2230 std::string app_name = web_app::GenerateApplicationNameFromURL(url); | |
2231 | |
2232 DetachContents(contents); | |
2233 Browser* app_browser = Browser::CreateWithParams( | |
2234 Browser::CreateParams::CreateForApp( | |
2235 TYPE_POPUP, app_name, gfx::Rect(), profile_)); | |
2236 TabContents* tab_contents = TabContents::FromWebContents(contents); | |
2237 if (!tab_contents) | |
2238 tab_contents = new TabContents(contents); | |
2239 app_browser->tab_strip_model()->AppendTabContents(tab_contents, true); | |
2240 | |
2241 contents->GetMutableRendererPrefs()->can_accept_load_drops = false; | |
2242 contents->GetRenderViewHost()->SyncRendererPrefs(); | |
2243 app_browser->window()->Show(); | |
2244 } | |
2245 | |
2246 gfx::Rect Browser::GetRootWindowResizerRect() const { | |
2247 return window_->GetRootWindowResizerRect(); | |
2248 } | |
2249 | |
2250 void Browser::BeforeUnloadFired(WebContents* web_contents, | |
2251 bool proceed, | |
2252 bool* proceed_to_fire_unload) { | |
2253 if (!is_attempting_to_close_browser_) { | |
2254 *proceed_to_fire_unload = proceed; | |
2255 if (!proceed) | |
2256 web_contents->SetClosedByUserGesture(false); | |
2257 return; | |
2258 } | |
2259 | |
2260 if (!proceed) { | |
2261 CancelWindowClose(); | |
2262 *proceed_to_fire_unload = false; | |
2263 web_contents->SetClosedByUserGesture(false); | |
2264 return; | |
2265 } | |
2266 | |
2267 if (RemoveFromSet(&tabs_needing_before_unload_fired_, web_contents)) { | |
2268 // Now that beforeunload has fired, put the tab on the queue to fire | |
2269 // unload. | |
2270 tabs_needing_unload_fired_.insert(web_contents); | |
2271 ProcessPendingTabs(); | |
2272 // We want to handle firing the unload event ourselves since we want to | |
2273 // fire all the beforeunload events before attempting to fire the unload | |
2274 // events should the user cancel closing the browser. | |
2275 *proceed_to_fire_unload = false; | |
2276 return; | |
2277 } | |
2278 | |
2279 *proceed_to_fire_unload = true; | |
2280 } | |
2281 | |
2282 void Browser::SetFocusToLocationBar(bool select_all) { | |
2283 // Two differences between this and FocusLocationBar(): | |
2284 // (1) This doesn't get recorded in user metrics, since it's called | |
2285 // internally. | |
2286 // (2) This checks whether the location bar can be focused, and if not, clears | |
2287 // the focus. FocusLocationBar() is only reached when the location bar is | |
2288 // focusable, but this may be reached at other times, e.g. while in | |
2289 // fullscreen mode, where we need to leave focus in a consistent state. | |
2290 window_->SetFocusToLocationBar(select_all); | |
2291 } | |
2292 | |
2293 void Browser::RenderWidgetShowing() { | |
2294 window_->DisableInactiveFrame(); | |
2295 } | |
2296 | |
2297 int Browser::GetExtraRenderViewHeight() const { | |
2298 return window_->GetExtraRenderViewHeight(); | |
2299 } | |
2300 | |
2301 void Browser::OnStartDownload(WebContents* source, | |
2302 content::DownloadItem* download) { | |
2303 TabContents* tab_contents = TabContents::FromWebContents(source); | |
2304 TabContents* constrained = GetConstrainingTabContents(tab_contents); | |
2305 if (constrained != tab_contents) { | |
2306 // Download in a constrained popup is shown in the tab that opened it. | |
2307 WebContents* constrained_tab = constrained->web_contents(); | |
2308 constrained_tab->GetDelegate()->OnStartDownload(constrained_tab, download); | |
2309 return; | |
2310 } | |
2311 | |
2312 if (!window()) | |
2313 return; | |
2314 | |
2315 // GetDownloadShelf creates the download shelf if it was not yet created. | |
2316 DownloadShelf* shelf = window()->GetDownloadShelf(); | |
2317 shelf->AddDownload(new DownloadItemModel(download)); | |
2318 // Don't show the animation for "Save file" downloads. | |
2319 // For non-theme extensions, we don't show the download animation. | |
2320 // Show animation in same window as the download shelf. Download shelf | |
2321 // may not be in the same window that initiated the download, e.g. | |
2322 // Panels. | |
2323 // Don't show the animation if the selected tab is not visible (i.e. the | |
2324 // window is minimized, we're in a unit test, etc.). | |
2325 WebContents* shelf_tab = shelf->browser()->GetActiveWebContents(); | |
2326 if ((download->GetTotalBytes() > 0) && | |
2327 !download_crx_util::IsExtensionDownload(*download) && | |
2328 platform_util::IsVisible(shelf_tab->GetNativeView()) && | |
2329 ui::Animation::ShouldRenderRichAnimation()) { | |
2330 DownloadStartedAnimation::Show(shelf_tab); | |
2331 } | |
2332 | |
2333 // If the download occurs in a new tab, close it. | |
2334 if (source->GetController().IsInitialNavigation() && tab_count() > 1) | |
2335 CloseContents(source); | |
2336 } | |
2337 | |
2338 void Browser::ViewSourceForTab(WebContents* source, const GURL& page_url) { | |
2339 DCHECK(source); | |
2340 TabContents* tab_contents = GetTabContentsAt( | |
2341 tab_strip_model_->GetIndexOfWebContents(source)); | |
2342 chrome::ViewSource(this, tab_contents); | |
2343 } | |
2344 | |
2345 void Browser::ViewSourceForFrame(WebContents* source, | |
2346 const GURL& frame_url, | |
2347 const std::string& frame_content_state) { | |
2348 DCHECK(source); | |
2349 TabContents* tab_contents = GetTabContentsAt( | |
2350 tab_strip_model_->GetIndexOfWebContents(source)); | |
2351 chrome::ViewSource(this, tab_contents, frame_url, frame_content_state); | |
2352 } | |
2353 | |
2354 void Browser::ShowRepostFormWarningDialog(WebContents* source) { | |
2355 browser::ShowTabModalConfirmDialog( | |
2356 new RepostFormWarningController(source), | |
2357 TabContents::FromWebContents(source)); | |
2358 } | |
2359 | |
2360 bool Browser::ShouldAddNavigationToHistory( | |
2361 const history::HistoryAddPageArgs& add_page_args, | |
2362 content::NavigationType navigation_type) { | |
2363 // Don't update history if running as app. | |
2364 return !IsApplication(); | |
2365 } | |
2366 | |
2367 bool Browser::ShouldCreateWebContents( | |
2368 WebContents* web_contents, | |
2369 int route_id, | |
2370 WindowContainerType window_container_type, | |
2371 const string16& frame_name, | |
2372 const GURL& target_url) { | |
2373 if (window_container_type == WINDOW_CONTAINER_TYPE_BACKGROUND) { | |
2374 // If a BackgroundContents is created, suppress the normal WebContents. | |
2375 return !MaybeCreateBackgroundContents( | |
2376 route_id, web_contents, frame_name, target_url); | |
2377 } | |
2378 | |
2379 return true; | |
2380 } | |
2381 | |
2382 void Browser::WebContentsCreated(WebContents* source_contents, | |
2383 int64 source_frame_id, | |
2384 const GURL& target_url, | |
2385 WebContents* new_contents) { | |
2386 // Create a TabContents now, so all observers are in place, as the network | |
2387 // requests for its initial navigation will start immediately. The WebContents | |
2388 // will later be inserted into this browser using Browser::Navigate via | |
2389 // AddNewContents. The latter will retrieve the newly created TabContents from | |
2390 // WebContents object. | |
2391 new TabContents(new_contents); | |
2392 | |
2393 // Notify. | |
2394 RetargetingDetails details; | |
2395 details.source_web_contents = source_contents; | |
2396 details.source_frame_id = source_frame_id; | |
2397 details.target_url = target_url; | |
2398 details.target_web_contents = new_contents; | |
2399 details.not_yet_in_tabstrip = true; | |
2400 content::NotificationService::current()->Notify( | |
2401 chrome::NOTIFICATION_RETARGETING, | |
2402 content::Source<Profile>(profile_), | |
2403 content::Details<RetargetingDetails>(&details)); | |
2404 } | |
2405 | |
2406 void Browser::ContentRestrictionsChanged(WebContents* source) { | |
2407 UpdateCommandsForContentRestrictionState(); | |
2408 } | |
2409 | |
2410 void Browser::RendererUnresponsive(WebContents* source) { | |
2411 // Ignore hangs if print preview is open. | |
2412 TabContents* tab_contents = TabContents::FromWebContents(source); | |
2413 if (tab_contents) { | |
2414 printing::PrintPreviewTabController* controller = | |
2415 printing::PrintPreviewTabController::GetInstance(); | |
2416 if (controller) { | |
2417 TabContents* preview_tab = | |
2418 controller->GetPrintPreviewForTab(tab_contents); | |
2419 if (preview_tab && preview_tab != tab_contents) { | |
2420 return; | |
2421 } | |
2422 } | |
2423 } | |
2424 | |
2425 browser::ShowHungRendererDialog(source); | |
2426 } | |
2427 | |
2428 void Browser::RendererResponsive(WebContents* source) { | |
2429 browser::HideHungRendererDialog(source); | |
2430 } | |
2431 | |
2432 void Browser::WorkerCrashed(WebContents* source) { | |
2433 TabContents* tab_contents = TabContents::FromWebContents(source); | |
2434 InfoBarTabHelper* infobar_helper = tab_contents->infobar_tab_helper(); | |
2435 infobar_helper->AddInfoBar(new SimpleAlertInfoBarDelegate( | |
2436 infobar_helper, | |
2437 NULL, | |
2438 l10n_util::GetStringUTF16(IDS_WEBWORKER_CRASHED_PROMPT), | |
2439 true)); | |
2440 } | |
2441 | |
2442 void Browser::DidNavigateMainFramePostCommit(WebContents* web_contents) { | |
2443 if (web_contents == GetActiveWebContents()) | |
2444 UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE); | |
2445 } | |
2446 | |
2447 void Browser::DidNavigateToPendingEntry(WebContents* web_contents) { | |
2448 if (web_contents == GetActiveWebContents()) | |
2449 UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE); | |
2450 } | |
2451 | |
2452 content::JavaScriptDialogCreator* Browser::GetJavaScriptDialogCreator() { | |
2453 return GetJavaScriptDialogCreatorInstance(); | |
2454 } | |
2455 | |
2456 content::ColorChooser* Browser::OpenColorChooser(WebContents* web_contents, | |
2457 int color_chooser_id, | |
2458 SkColor color) { | |
2459 #if defined(OS_WIN) | |
2460 // On Windows, only create a color chooser if one doesn't exist, because we | |
2461 // can't close the old color chooser dialog. | |
2462 if (!color_chooser_.get()) | |
2463 color_chooser_.reset(content::ColorChooser::Create(color_chooser_id, | |
2464 web_contents, | |
2465 color)); | |
2466 #else | |
2467 if (color_chooser_.get()) | |
2468 color_chooser_->End(); | |
2469 color_chooser_.reset(content::ColorChooser::Create(color_chooser_id, | |
2470 web_contents, | |
2471 color)); | |
2472 #endif | |
2473 return color_chooser_.get(); | |
2474 } | |
2475 | |
2476 void Browser::DidEndColorChooser() { | |
2477 color_chooser_.reset(); | |
2478 } | |
2479 | |
2480 void Browser::RunFileChooser(WebContents* web_contents, | |
2481 const content::FileChooserParams& params) { | |
2482 FileSelectHelper::RunFileChooser(web_contents, params); | |
2483 } | |
2484 | |
2485 void Browser::EnumerateDirectory(WebContents* web_contents, | |
2486 int request_id, | |
2487 const FilePath& path) { | |
2488 FileSelectHelper::EnumerateDirectory(web_contents, request_id, path); | |
2489 } | |
2490 | |
2491 void Browser::ToggleFullscreenModeForTab(WebContents* web_contents, | |
2492 bool enter_fullscreen) { | |
2493 fullscreen_controller_->ToggleFullscreenModeForTab(web_contents, | |
2494 enter_fullscreen); | |
2495 } | |
2496 | |
2497 bool Browser::IsFullscreenForTabOrPending( | |
2498 const WebContents* web_contents) const { | |
2499 return fullscreen_controller_->IsFullscreenForTabOrPending(web_contents); | |
2500 } | |
2501 | |
2502 void Browser::JSOutOfMemory(WebContents* web_contents) { | |
2503 JSOutOfMemoryHelper(web_contents); | |
2504 } | |
2505 | |
2506 void Browser::RegisterProtocolHandler(WebContents* web_contents, | |
2507 const std::string& protocol, | |
2508 const GURL& url, | |
2509 const string16& title, | |
2510 bool user_gesture) { | |
2511 RegisterProtocolHandlerHelper( | |
2512 web_contents, protocol, url, title, user_gesture); | |
2513 } | |
2514 | |
2515 void Browser::RegisterIntentHandler( | |
2516 WebContents* web_contents, | |
2517 const webkit_glue::WebIntentServiceData& data, | |
2518 bool user_gesture) { | |
2519 RegisterIntentHandlerHelper(web_contents, data, user_gesture); | |
2520 } | |
2521 | |
2522 void Browser::WebIntentDispatch( | |
2523 WebContents* web_contents, | |
2524 content::WebIntentsDispatcher* intents_dispatcher) { | |
2525 if (!web_intents::IsWebIntentsEnabledForProfile(profile_)) | |
2526 return; | |
2527 | |
2528 UMA_HISTOGRAM_COUNTS("WebIntents.Dispatch", 1); | |
2529 | |
2530 TabContents* tab_contents = TabContents::FromWebContents(web_contents); | |
2531 tab_contents->web_intent_picker_controller()->SetIntentsDispatcher( | |
2532 intents_dispatcher); | |
2533 tab_contents->web_intent_picker_controller()->ShowDialog( | |
2534 intents_dispatcher->GetIntent().action, | |
2535 intents_dispatcher->GetIntent().type); | |
2536 } | |
2537 | |
2538 void Browser::UpdatePreferredSize(WebContents* source, | |
2539 const gfx::Size& pref_size) { | |
2540 window_->UpdatePreferredSize(source, pref_size); | |
2541 } | |
2542 | |
2543 void Browser::ResizeDueToAutoResize(WebContents* source, | |
2544 const gfx::Size& new_size) { | |
2545 window_->ResizeDueToAutoResize(source, new_size); | |
2546 } | |
2547 | |
2548 void Browser::FindReply(WebContents* web_contents, | |
2549 int request_id, | |
2550 int number_of_matches, | |
2551 const gfx::Rect& selection_rect, | |
2552 int active_match_ordinal, | |
2553 bool final_update) { | |
2554 FindReplyHelper(web_contents, request_id, number_of_matches, selection_rect, | |
2555 active_match_ordinal, final_update); | |
2556 } | |
2557 | |
2558 void Browser::RequestToLockMouse(WebContents* web_contents, | |
2559 bool user_gesture, | |
2560 bool last_unlocked_by_target) { | |
2561 fullscreen_controller_->RequestToLockMouse(web_contents, | |
2562 user_gesture, | |
2563 last_unlocked_by_target); | |
2564 } | |
2565 | |
2566 void Browser::LostMouseLock() { | |
2567 fullscreen_controller_->LostMouseLock(); | |
2568 } | |
2569 | |
2570 void Browser::RequestMediaAccessPermission( | |
2571 content::WebContents* web_contents, | |
2572 const content::MediaStreamRequest* request, | |
2573 const content::MediaResponseCallback& callback) { | |
2574 TabContents* tab = TabContents::FromWebContents(web_contents); | |
2575 DCHECK(tab); | |
2576 | |
2577 scoped_ptr<MediaStreamDevicesController> | |
2578 controller(new MediaStreamDevicesController(tab->profile(), | |
2579 request, | |
2580 callback)); | |
2581 if (!controller->DismissInfoBarAndTakeActionOnSettings()) { | |
2582 InfoBarTabHelper* infobar_helper = tab->infobar_tab_helper(); | |
2583 InfoBarDelegate* old_infobar = NULL; | |
2584 for (size_t i = 0; i < infobar_helper->infobar_count(); ++i) { | |
2585 old_infobar = infobar_helper->GetInfoBarDelegateAt(i)-> | |
2586 AsMediaStreamInfoBarDelegate(); | |
2587 if (old_infobar) | |
2588 break; | |
2589 } | |
2590 | |
2591 InfoBarDelegate* infobar = | |
2592 new MediaStreamInfoBarDelegate(infobar_helper, controller.release()); | |
2593 if (old_infobar) | |
2594 infobar_helper->ReplaceInfoBar(old_infobar, infobar); | |
2595 else | |
2596 infobar_helper->AddInfoBar(infobar); | |
2597 } | |
2598 } | |
2599 | |
2600 /////////////////////////////////////////////////////////////////////////////// | |
2601 // Browser, CoreTabHelperDelegate implementation: | |
2602 | |
2603 void Browser::SwapTabContents(TabContents* old_tab_contents, | |
2604 TabContents* new_tab_contents) { | |
2605 int index = tab_strip_model_->GetIndexOfTabContents(old_tab_contents); | |
2606 DCHECK_NE(TabStripModel::kNoTab, index); | |
2607 tab_strip_model_->ReplaceTabContentsAt(index, new_tab_contents); | |
2608 } | |
2609 | |
2610 bool Browser::CanReloadContents(TabContents* source) const { | |
2611 return !is_devtools(); | |
2612 } | |
2613 | |
2614 bool Browser::CanSaveContents(TabContents* source) const { | |
2615 return !is_devtools(); | |
2616 } | |
2617 | |
2618 /////////////////////////////////////////////////////////////////////////////// | |
2619 // Browser, SearchEngineTabHelperDelegate implementation: | |
2620 | |
2621 void Browser::ConfirmAddSearchProvider(TemplateURL* template_url, | |
2622 Profile* profile) { | |
2623 window()->ConfirmAddSearchProvider(template_url, profile); | |
2624 } | |
2625 | |
2626 /////////////////////////////////////////////////////////////////////////////// | |
2627 // Browser, ConstrainedWindowTabHelperDelegate implementation: | |
2628 | |
2629 void Browser::SetTabContentBlocked(TabContents* tab_contents, bool blocked) { | |
2630 int index = tab_strip_model_->GetIndexOfTabContents(tab_contents); | |
2631 if (index == TabStripModel::kNoTab) { | |
2632 NOTREACHED(); | |
2633 return; | |
2634 } | |
2635 tab_strip_model_->SetTabBlocked(index, blocked); | |
2636 UpdatePrintingState(tab_contents->web_contents()->GetContentRestrictions()); | |
2637 if (!blocked && GetActiveTabContents() == tab_contents) | |
2638 tab_contents->web_contents()->Focus(); | |
2639 } | |
2640 | |
2641 /////////////////////////////////////////////////////////////////////////////// | |
2642 // Browser, BlockedContentTabHelperDelegate implementation: | |
2643 | |
2644 TabContents* Browser::GetConstrainingTabContents(TabContents* source) { | |
2645 return source; | |
2646 } | |
2647 | |
2648 /////////////////////////////////////////////////////////////////////////////// | |
2649 // Browser, BookmarkTabHelperDelegate implementation: | |
2650 | |
2651 void Browser::URLStarredChanged(TabContents* source, bool starred) { | |
2652 if (source == GetActiveTabContents()) | |
2653 window_->SetStarredState(starred); | |
2654 } | |
2655 | |
2656 /////////////////////////////////////////////////////////////////////////////// | |
2657 // Browser, ZoomObserver implementation: | |
2658 | |
2659 void Browser::OnZoomIconChanged(TabContents* source, | |
2660 ZoomController::ZoomIconState state) { | |
2661 if (source == GetActiveTabContents()) | |
2662 window_->SetZoomIconState(state); | |
2663 } | |
2664 | |
2665 void Browser::OnZoomChanged(TabContents* source, | |
2666 int zoom_percent, | |
2667 bool can_show_bubble) { | |
2668 if (source == GetActiveTabContents()) { | |
2669 window_->SetZoomIconTooltipPercent(zoom_percent); | |
2670 | |
2671 // Only show the zoom bubble for zoom changes in the active window. | |
2672 if (can_show_bubble && window_->IsActive()) | |
2673 window_->ShowZoomBubble(zoom_percent); | |
2674 } | |
2675 } | |
2676 | |
2677 /////////////////////////////////////////////////////////////////////////////// | |
2678 // Browser, ExtensionTabHelperDelegate implementation: | |
2679 | |
2680 void Browser::OnDidGetApplicationInfo(TabContents* source, | |
2681 int32 page_id) { | |
2682 if (GetActiveTabContents() != source) | |
2683 return; | |
2684 | |
2685 NavigationEntry* entry = | |
2686 source->web_contents()->GetController().GetLastCommittedEntry(); | |
2687 if (!entry || (entry->GetPageID() != page_id)) | |
2688 return; | |
2689 | |
2690 switch (pending_web_app_action_) { | |
2691 case CREATE_SHORTCUT: { | |
2692 window()->ShowCreateWebAppShortcutsDialog(source); | |
2693 break; | |
2694 } | |
2695 case UPDATE_SHORTCUT: { | |
2696 web_app::UpdateShortcutForTabContents(source); | |
2697 break; | |
2698 } | |
2699 default: | |
2700 NOTREACHED(); | |
2701 break; | |
2702 } | |
2703 | |
2704 pending_web_app_action_ = NONE; | |
2705 } | |
2706 | |
2707 void Browser::OnInstallApplication(TabContents* source, | |
2708 const WebApplicationInfo& web_app) { | |
2709 ExtensionService* extension_service = profile()->GetExtensionService(); | |
2710 if (!extension_service) | |
2711 return; | |
2712 | |
2713 scoped_refptr<CrxInstaller> installer(CrxInstaller::Create( | |
2714 extension_service, | |
2715 extension_service->show_extensions_prompts() ? | |
2716 new ExtensionInstallPrompt(this) : NULL)); | |
2717 installer->InstallWebApp(web_app); | |
2718 } | |
2719 | |
2720 /////////////////////////////////////////////////////////////////////////////// | |
2721 // Browser, SelectFileDialog::Listener implementation: | |
2722 | |
2723 void Browser::FileSelected(const FilePath& path, int index, void* params) { | |
2724 profile_->set_last_selected_directory(path.DirName()); | |
2725 GURL file_url = net::FilePathToFileURL(path); | |
2726 | |
2727 #if defined(OS_CHROMEOS) | |
2728 gdata::util::ModifyGDataFileResourceUrl(profile_, path, &file_url); | |
2729 #endif | |
2730 | |
2731 if (file_url.is_empty()) | |
2732 return; | |
2733 | |
2734 OpenURL(OpenURLParams( | |
2735 file_url, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED, | |
2736 false)); | |
2737 } | |
2738 | |
2739 /////////////////////////////////////////////////////////////////////////////// | |
2740 // Browser, content::NotificationObserver implementation: | |
2741 | |
2742 void Browser::Observe(int type, | |
2743 const content::NotificationSource& source, | |
2744 const content::NotificationDetails& details) { | |
2745 switch (type) { | 577 switch (type) { |
2746 case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED: | 578 case NOTIFICATION_PREF_CHANGED: { |
2747 if (is_attempting_to_close_browser_) { | |
2748 // Pass in false so that we delay processing. We need to delay the | |
2749 // processing as it may close the tab, which is currently on the call | |
2750 // stack above us. | |
2751 ClearUnloadState(content::Source<WebContents>(source).ptr(), false); | |
2752 } | |
2753 break; | |
2754 | |
2755 case content::NOTIFICATION_SSL_VISIBLE_STATE_CHANGED: | |
2756 // When the current tab's SSL state changes, we need to update the URL | |
2757 // bar to reflect the new state. Note that it's possible for the selected | |
2758 // tab contents to be NULL. This is because we listen for all sources | |
2759 // (NavigationControllers) for convenience, so the notification could | |
2760 // actually be for a different window while we're doing asynchronous | |
2761 // closing of this one. | |
2762 if (GetActiveWebContents() && | |
2763 &GetActiveWebContents()->GetController() == | |
2764 content::Source<NavigationController>(source).ptr()) | |
2765 UpdateToolbar(false); | |
2766 break; | |
2767 | |
2768 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | |
2769 if (window()->GetLocationBar()) | |
2770 window()->GetLocationBar()->UpdatePageActions(); | |
2771 | |
2772 // Close any tabs from the unloaded extension, unless it's terminated, | |
2773 // in which case let the sad tabs remain. | |
2774 if (content::Details<extensions::UnloadedExtensionInfo>( | |
2775 details)->reason != extension_misc::UNLOAD_REASON_TERMINATE) { | |
2776 const Extension* extension = | |
2777 content::Details<extensions::UnloadedExtensionInfo>( | |
2778 details)->extension; | |
2779 for (int i = tab_strip_model_->count() - 1; i >= 0; --i) { | |
2780 WebContents* tc = | |
2781 tab_strip_model_->GetTabContentsAt(i)->web_contents(); | |
2782 bool close_tab_contents = | |
2783 tc->GetURL().SchemeIs(chrome::kExtensionScheme) && | |
2784 tc->GetURL().host() == extension->id(); | |
2785 // We want to close all panels originated by the unloaded extension. | |
2786 close_tab_contents = close_tab_contents || | |
2787 (type_ == TYPE_PANEL && | |
2788 (web_app::GetExtensionIdFromApplicationName(app_name_) == | |
2789 extension->id())); | |
2790 if (close_tab_contents) { | |
2791 CloseTabContents(tc); | |
2792 } | |
2793 } | |
2794 } | |
2795 break; | |
2796 } | |
2797 | |
2798 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: { | |
2799 Profile* profile = content::Source<Profile>(source).ptr(); | |
2800 if (profile_->IsSameProfile(profile) && window()->GetLocationBar()) | |
2801 window()->GetLocationBar()->InvalidatePageActions(); | |
2802 break; | |
2803 } | |
2804 | |
2805 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: | |
2806 case chrome::NOTIFICATION_EXTENSION_LOADED: | |
2807 // During window creation on Windows we may end up calling into | |
2808 // SHAppBarMessage, which internally spawns a nested message loop. This | |
2809 // makes it possible for us to end up here before window creation has | |
2810 // completed,at which point window_ is NULL. See 94752 for details. | |
2811 if (window() && window()->GetLocationBar()) | |
2812 window()->GetLocationBar()->UpdatePageActions(); | |
2813 break; | |
2814 | |
2815 #if defined(ENABLE_THEMES) | |
2816 case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: | |
2817 window()->UserChangedTheme(); | |
2818 break; | |
2819 #endif | |
2820 | |
2821 case chrome::NOTIFICATION_PREF_CHANGED: { | |
2822 const std::string& pref_name = | 579 const std::string& pref_name = |
2823 *content::Details<std::string>(details).ptr(); | 580 *content::Details<std::string>(details).ptr(); |
2824 if (pref_name == prefs::kPrintingEnabled) { | 581 if (pref_name == prefs::kPrintingEnabled) { |
2825 UpdatePrintingState(GetContentRestrictionsForSelectedTab()); | 582 UpdatePrintingState(); |
2826 } else if (pref_name == prefs::kInstantEnabled) { | |
2827 if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() || | |
2828 !InstantController::IsEnabled(profile())) { | |
2829 if (instant()) { | |
2830 instant()->DestroyPreviewContents(); | |
2831 instant_.reset(); | |
2832 instant_unload_handler_.reset(); | |
2833 } | |
2834 } else { | |
2835 CreateInstantIfNecessary(); | |
2836 } | |
2837 } else if (pref_name == prefs::kIncognitoModeAvailability) { | 583 } else if (pref_name == prefs::kIncognitoModeAvailability) { |
2838 UpdateCommandsForIncognitoAvailability(); | 584 UpdateCommandsForIncognitoAvailability(); |
2839 } else if (pref_name == prefs::kDevToolsDisabled) { | 585 } else if (pref_name == prefs::kDevToolsDisabled) { |
2840 UpdateCommandsForDevTools(); | 586 UpdateCommandsForDevTools(); |
2841 if (profile_->GetPrefs()->GetBoolean(prefs::kDevToolsDisabled)) | |
2842 content::DevToolsManager::GetInstance()->CloseAllClientHosts(); | |
2843 } else if (pref_name == prefs::kEditBookmarksEnabled) { | 587 } else if (pref_name == prefs::kEditBookmarksEnabled) { |
2844 UpdateCommandsForBookmarkEditing(); | 588 UpdateCommandsForBookmarkEditing(); |
2845 } else if (pref_name == prefs::kShowBookmarkBar) { | 589 } else if (pref_name == prefs::kShowBookmarkBar) { |
2846 UpdateCommandsForBookmarkBar(); | 590 UpdateCommandsForBookmarkBar(); |
2847 UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_PREF_CHANGE); | |
2848 } else if (pref_name == prefs::kHomePage) { | |
2849 PrefService* pref_service = content::Source<PrefService>(source).ptr(); | |
2850 MarkHomePageAsChanged(pref_service); | |
2851 } else if (pref_name == prefs::kAllowFileSelectionDialogs) { | 591 } else if (pref_name == prefs::kAllowFileSelectionDialogs) { |
2852 UpdateSaveAsState(GetContentRestrictionsForSelectedTab()); | 592 UpdateSaveAsState(); |
2853 UpdateOpenFileState(); | 593 UpdateOpenFileState(); |
2854 } else if (pref_name == prefs::kInManagedMode) { | 594 } else if (pref_name == prefs::kInManagedMode) { |
2855 UpdateCommandsForMultipleProfiles(); | 595 UpdateCommandsForMultipleProfiles(); |
2856 } else { | 596 } else { |
2857 NOTREACHED(); | 597 NOTREACHED(); |
2858 } | 598 } |
2859 break; | 599 break; |
2860 } | 600 } |
2861 | |
2862 case chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED: { | |
2863 WebContents* web_contents = content::Source<WebContents>(source).ptr(); | |
2864 if (web_contents == GetActiveWebContents()) { | |
2865 LocationBar* location_bar = window()->GetLocationBar(); | |
2866 if (location_bar) | |
2867 location_bar->UpdateContentSettingsIcons(); | |
2868 } | |
2869 break; | |
2870 } | |
2871 | |
2872 case content::NOTIFICATION_INTERSTITIAL_ATTACHED: | 601 case content::NOTIFICATION_INTERSTITIAL_ATTACHED: |
2873 UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE); | |
2874 UpdateCommandsForTabState(); | 602 UpdateCommandsForTabState(); |
2875 break; | 603 break; |
2876 | 604 |
2877 case content::NOTIFICATION_INTERSTITIAL_DETACHED: | 605 case content::NOTIFICATION_INTERSTITIAL_DETACHED: |
2878 UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE); | |
2879 UpdateCommandsForTabState(); | 606 UpdateCommandsForTabState(); |
2880 break; | 607 break; |
2881 | 608 |
2882 default: | 609 default: |
2883 NOTREACHED() << "Got a notification we didn't register for."; | 610 NOTREACHED() << "Got a notification we didn't register for."; |
2884 } | 611 } |
2885 } | 612 } |
2886 | 613 |
2887 /////////////////////////////////////////////////////////////////////////////// | 614 //////////////////////////////////////////////////////////////////////////////// |
2888 // Browser, ProfileSyncServiceObserver implementation: | 615 // BrowserCommandController, TabStripModelObserver implementation: |
2889 | 616 |
2890 void Browser::OnStateChanged() { | 617 void BrowserCommandController::TabInsertedAt(TabContents* contents, |
2891 DCHECK(ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService( | 618 int index, |
2892 profile_)); | 619 bool foreground) { |
2893 // For unit tests, we don't have a window. | 620 AddInterstitialObservers(contents); |
2894 if (!window_) | |
2895 return; | |
2896 const bool show_main_ui = IsShowingMainUI(window_->IsFullscreen()); | |
2897 command_updater_.UpdateCommandEnabled(IDC_SHOW_SYNC_SETUP, | |
2898 show_main_ui && profile_->GetOriginalProfile()->IsSyncAccessible()); | |
2899 } | 621 } |
2900 | 622 |
2901 /////////////////////////////////////////////////////////////////////////////// | 623 void BrowserCommandController::TabDetachedAt(TabContents* contents, int index) { |
2902 // Browser, InstantDelegate implementation: | 624 RemoveInterstitialObservers(contents); |
2903 | |
2904 void Browser::ShowInstant(TabContents* preview_contents) { | |
2905 window_->ShowInstant(preview_contents); | |
2906 | |
2907 // TODO(beng): investigate if we can avoid this and instead rely on the | |
2908 // visibility of the WebContentsView | |
2909 GetActiveWebContents()->WasHidden(); | |
2910 preview_contents->web_contents()->WasRestored(); | |
2911 } | 625 } |
2912 | 626 |
2913 void Browser::HideInstant() { | 627 void BrowserCommandController::TabReplacedAt(TabStripModel* tab_strip_model, |
2914 window_->HideInstant(); | 628 TabContents* old_contents, |
2915 if (GetActiveWebContents()) | 629 TabContents* new_contents, |
2916 GetActiveWebContents()->WasRestored(); | 630 int index) { |
2917 if (instant_->GetPreviewContents()) | 631 RemoveInterstitialObservers(old_contents); |
2918 instant_->GetPreviewContents()->web_contents()->WasHidden(); | 632 AddInterstitialObservers(new_contents); |
2919 } | 633 } |
2920 | 634 |
2921 void Browser::CommitInstant(TabContents* preview_contents) { | 635 //////////////////////////////////////////////////////////////////////////////// |
2922 TabContents* tab_contents = GetActiveTabContents(); | 636 // BrowserCommandController, TabRestoreServiceObserver implementation: |
2923 int index = tab_strip_model_->GetIndexOfTabContents(tab_contents); | |
2924 DCHECK_NE(TabStripModel::kNoTab, index); | |
2925 // TabStripModel takes ownership of preview_contents. | |
2926 tab_strip_model_->ReplaceTabContentsAt(index, preview_contents); | |
2927 // InstantUnloadHandler takes ownership of tab_contents. | |
2928 instant_unload_handler_->RunUnloadListenersOrDestroy(tab_contents, index); | |
2929 | 637 |
2930 GURL url = preview_contents->web_contents()->GetURL(); | 638 void BrowserCommandController::TabRestoreServiceChanged( |
2931 DCHECK(profile_->GetExtensionService()); | 639 TabRestoreService* service) { |
2932 if (profile_->GetExtensionService()->IsInstalledApp(url)) { | 640 command_updater_.UpdateCommandEnabled(IDC_RESTORE_TAB, |
2933 AppLauncherHandler::RecordAppLaunchType( | 641 CanRestoreTab(browser_)); |
2934 extension_misc::APP_LAUNCH_OMNIBOX_INSTANT); | |
2935 } | |
2936 } | 642 } |
2937 | 643 |
2938 void Browser::SetSuggestedText(const string16& text, | 644 void BrowserCommandController::TabRestoreServiceDestroyed( |
2939 InstantCompleteBehavior behavior) { | 645 TabRestoreService* service) { |
2940 if (window()->GetLocationBar()) | 646 service->RemoveObserver(this); |
2941 window()->GetLocationBar()->SetSuggestedText(text, behavior); | |
2942 } | 647 } |
2943 | 648 |
2944 gfx::Rect Browser::GetInstantBounds() { | 649 //////////////////////////////////////////////////////////////////////////////// |
2945 return window()->GetInstantBounds(); | 650 // BrowserCommandController, ProfileSyncServiceObserver implementation: |
| 651 |
| 652 void BrowserCommandController::OnStateChanged() { |
| 653 DCHECK(ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService( |
| 654 profile())); |
| 655 // For unit tests, we don't have a window. |
| 656 if (!window()) |
| 657 return; |
| 658 const bool show_main_ui = IsShowingMainUI(window()->IsFullscreen()); |
| 659 command_updater_.UpdateCommandEnabled(IDC_SHOW_SYNC_SETUP, |
| 660 show_main_ui && profile()->GetOriginalProfile()->IsSyncAccessible()); |
2946 } | 661 } |
2947 | 662 |
2948 void Browser::InstantPreviewFocused() { | 663 //////////////////////////////////////////////////////////////////////////////// |
2949 // NOTE: This is only invoked on aura. | 664 // BrowserCommandController, private: |
2950 window_->WebContentsFocused(instant_->GetPreviewContents()->web_contents()); | |
2951 } | |
2952 | 665 |
2953 TabContents* Browser::GetInstantHostTabContents() const { | 666 bool BrowserCommandController::IsShowingMainUI(bool is_fullscreen) { |
2954 return GetActiveTabContents(); | |
2955 } | |
2956 | |
2957 /////////////////////////////////////////////////////////////////////////////// | |
2958 // Browser, Command and state updating (private): | |
2959 | |
2960 bool Browser::IsShowingMainUI(bool is_fullscreen) { | |
2961 #if !defined(OS_MACOSX) | 667 #if !defined(OS_MACOSX) |
2962 return is_type_tabbed() && !is_fullscreen; | 668 return browser_->is_type_tabbed() && !is_fullscreen; |
2963 #else | 669 #else |
2964 return is_type_tabbed(); | 670 return browser_->is_type_tabbed(); |
2965 #endif | 671 #endif |
2966 } | 672 } |
2967 | 673 |
2968 void Browser::InitCommandState() { | 674 void BrowserCommandController::InitCommandState() { |
2969 // All browser commands whose state isn't set automagically some other way | 675 // All browser commands whose state isn't set automagically some other way |
2970 // (like Back & Forward with initial page load) must have their state | 676 // (like Back & Forward with initial page load) must have their state |
2971 // initialized here, otherwise they will be forever disabled. | 677 // initialized here, otherwise they will be forever disabled. |
2972 | 678 |
2973 // Navigation commands | 679 // Navigation commands |
2974 command_updater_.UpdateCommandEnabled(IDC_RELOAD, true); | 680 command_updater_.UpdateCommandEnabled(IDC_RELOAD, true); |
2975 command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE, true); | 681 command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE, true); |
2976 | 682 |
2977 // Window management commands | 683 // Window management commands |
2978 command_updater_.UpdateCommandEnabled(IDC_CLOSE_WINDOW, true); | 684 command_updater_.UpdateCommandEnabled(IDC_CLOSE_WINDOW, true); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3027 // Zoom | 733 // Zoom |
3028 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MENU, true); | 734 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MENU, true); |
3029 command_updater_.UpdateCommandEnabled(IDC_ZOOM_PLUS, true); | 735 command_updater_.UpdateCommandEnabled(IDC_ZOOM_PLUS, true); |
3030 command_updater_.UpdateCommandEnabled(IDC_ZOOM_NORMAL, true); | 736 command_updater_.UpdateCommandEnabled(IDC_ZOOM_NORMAL, true); |
3031 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MINUS, true); | 737 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MINUS, true); |
3032 | 738 |
3033 // Show various bits of UI | 739 // Show various bits of UI |
3034 UpdateOpenFileState(); | 740 UpdateOpenFileState(); |
3035 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS, false); | 741 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS, false); |
3036 UpdateCommandsForDevTools(); | 742 UpdateCommandsForDevTools(); |
3037 command_updater_.UpdateCommandEnabled(IDC_TASK_MANAGER, | 743 command_updater_.UpdateCommandEnabled(IDC_TASK_MANAGER, CanOpenTaskManager()); |
3038 chrome::CanOpenTaskManager()); | |
3039 command_updater_.UpdateCommandEnabled(IDC_SHOW_HISTORY, true); | 744 command_updater_.UpdateCommandEnabled(IDC_SHOW_HISTORY, true); |
3040 command_updater_.UpdateCommandEnabled(IDC_SHOW_DOWNLOADS, true); | 745 command_updater_.UpdateCommandEnabled(IDC_SHOW_DOWNLOADS, true); |
3041 command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE_VIA_KEYBOARD, true); | 746 command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE_VIA_KEYBOARD, true); |
3042 command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE_VIA_MENU, true); | 747 command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE_VIA_MENU, true); |
3043 command_updater_.UpdateCommandEnabled(IDC_BOOKMARKS_MENU, true); | 748 command_updater_.UpdateCommandEnabled(IDC_BOOKMARKS_MENU, true); |
3044 | 749 |
3045 command_updater_.UpdateCommandEnabled( | 750 command_updater_.UpdateCommandEnabled( |
3046 IDC_SHOW_SYNC_SETUP, profile_->GetOriginalProfile()->IsSyncAccessible()); | 751 IDC_SHOW_SYNC_SETUP, profile()->GetOriginalProfile()->IsSyncAccessible()); |
3047 | 752 |
3048 // Initialize other commands based on the window type. | 753 // Initialize other commands based on the window type. |
3049 bool normal_window = is_type_tabbed(); | 754 bool normal_window = browser_->is_type_tabbed(); |
3050 | 755 |
3051 // Navigation commands | 756 // Navigation commands |
3052 command_updater_.UpdateCommandEnabled(IDC_HOME, normal_window); | 757 command_updater_.UpdateCommandEnabled(IDC_HOME, normal_window); |
3053 | 758 |
3054 // Window management commands | 759 // Window management commands |
3055 // TODO(rohitrao): Disable fullscreen on non-Lion? | 760 // TODO(rohitrao): Disable fullscreen on non-Lion? |
3056 command_updater_.UpdateCommandEnabled(IDC_FULLSCREEN, | 761 command_updater_.UpdateCommandEnabled(IDC_FULLSCREEN, |
3057 !(is_type_panel() && is_app())); | 762 !(browser_->is_type_panel() && browser_->is_app())); |
3058 command_updater_.UpdateCommandEnabled(IDC_SELECT_NEXT_TAB, normal_window); | 763 command_updater_.UpdateCommandEnabled(IDC_SELECT_NEXT_TAB, normal_window); |
3059 command_updater_.UpdateCommandEnabled(IDC_SELECT_PREVIOUS_TAB, | 764 command_updater_.UpdateCommandEnabled(IDC_SELECT_PREVIOUS_TAB, |
3060 normal_window); | 765 normal_window); |
3061 command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_NEXT, normal_window); | 766 command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_NEXT, normal_window); |
3062 command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_PREVIOUS, normal_window); | 767 command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_PREVIOUS, normal_window); |
3063 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_0, normal_window); | 768 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_0, normal_window); |
3064 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_1, normal_window); | 769 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_1, normal_window); |
3065 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_2, normal_window); | 770 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_2, normal_window); |
3066 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_3, normal_window); | 771 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_3, normal_window); |
3067 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_4, normal_window); | 772 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_4, normal_window); |
3068 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_5, normal_window); | 773 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_5, normal_window); |
3069 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_6, normal_window); | 774 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_6, normal_window); |
3070 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_7, normal_window); | 775 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_7, normal_window); |
3071 command_updater_.UpdateCommandEnabled(IDC_SELECT_LAST_TAB, normal_window); | 776 command_updater_.UpdateCommandEnabled(IDC_SELECT_LAST_TAB, normal_window); |
3072 #if defined(OS_WIN) | 777 #if defined(OS_WIN) |
3073 const bool metro_mode = base::win::IsMetroProcess(); | 778 const bool metro_mode = base::win::IsMetroProcess(); |
3074 command_updater_.UpdateCommandEnabled(IDC_METRO_SNAP_ENABLE, metro_mode); | 779 command_updater_.UpdateCommandEnabled(IDC_METRO_SNAP_ENABLE, metro_mode); |
3075 command_updater_.UpdateCommandEnabled(IDC_METRO_SNAP_DISABLE, metro_mode); | 780 command_updater_.UpdateCommandEnabled(IDC_METRO_SNAP_DISABLE, metro_mode); |
3076 #endif | 781 #endif |
3077 #if defined(OS_MACOSX) | 782 #if defined(OS_MACOSX) |
3078 command_updater_.UpdateCommandEnabled(IDC_TABPOSE, normal_window); | 783 command_updater_.UpdateCommandEnabled(IDC_TABPOSE, normal_window); |
3079 command_updater_.UpdateCommandEnabled(IDC_PRESENTATION_MODE, | 784 command_updater_.UpdateCommandEnabled(IDC_PRESENTATION_MODE, |
3080 !(is_type_panel() && is_app())); | 785 !(browser_->is_type_panel() && browser_->is_app())); |
3081 #endif | 786 #endif |
3082 | 787 |
3083 // Clipboard commands | 788 // Clipboard commands |
3084 command_updater_.UpdateCommandEnabled(IDC_COPY_URL, !is_devtools()); | 789 command_updater_.UpdateCommandEnabled(IDC_COPY_URL, !browser_->is_devtools()); |
3085 | 790 |
3086 // Find-in-page | 791 // Find-in-page |
3087 command_updater_.UpdateCommandEnabled(IDC_FIND, !is_devtools()); | 792 command_updater_.UpdateCommandEnabled(IDC_FIND, !browser_->is_devtools()); |
3088 command_updater_.UpdateCommandEnabled(IDC_FIND_NEXT, !is_devtools()); | 793 command_updater_.UpdateCommandEnabled(IDC_FIND_NEXT, |
3089 command_updater_.UpdateCommandEnabled(IDC_FIND_PREVIOUS, !is_devtools()); | 794 !browser_->is_devtools()); |
| 795 command_updater_.UpdateCommandEnabled(IDC_FIND_PREVIOUS, |
| 796 !browser_->is_devtools()); |
3090 | 797 |
3091 // Show various bits of UI | 798 // Show various bits of UI |
3092 command_updater_.UpdateCommandEnabled(IDC_CLEAR_BROWSING_DATA, normal_window); | 799 command_updater_.UpdateCommandEnabled(IDC_CLEAR_BROWSING_DATA, normal_window); |
3093 | 800 |
3094 // The upgrade entry and the view incompatibility entry should always be | 801 // The upgrade entry and the view incompatibility entry should always be |
3095 // enabled. Whether they are visible is a separate matter determined on menu | 802 // enabled. Whether they are visible is a separate matter determined on menu |
3096 // show. | 803 // show. |
3097 command_updater_.UpdateCommandEnabled(IDC_UPGRADE_DIALOG, true); | 804 command_updater_.UpdateCommandEnabled(IDC_UPGRADE_DIALOG, true); |
3098 command_updater_.UpdateCommandEnabled(IDC_VIEW_INCOMPATIBILITIES, true); | 805 command_updater_.UpdateCommandEnabled(IDC_VIEW_INCOMPATIBILITIES, true); |
3099 | 806 |
3100 // View Background Pages entry is always enabled, but is hidden if there are | 807 // View Background Pages entry is always enabled, but is hidden if there are |
3101 // no background pages. | 808 // no background pages. |
3102 command_updater_.UpdateCommandEnabled(IDC_VIEW_BACKGROUND_PAGES, true); | 809 command_updater_.UpdateCommandEnabled(IDC_VIEW_BACKGROUND_PAGES, true); |
3103 | 810 |
3104 // Toggle speech input | 811 // Toggle speech input |
3105 command_updater_.UpdateCommandEnabled(IDC_TOGGLE_SPEECH_INPUT, true); | 812 command_updater_.UpdateCommandEnabled(IDC_TOGGLE_SPEECH_INPUT, true); |
3106 | 813 |
3107 // Initialize other commands whose state changes based on fullscreen mode. | 814 // Initialize other commands whose state changes based on fullscreen mode. |
3108 UpdateCommandsForFullscreenMode(FULLSCREEN_DISABLED); | 815 UpdateCommandsForFullscreenMode(FULLSCREEN_DISABLED); |
3109 | 816 |
3110 UpdateCommandsForContentRestrictionState(); | 817 UpdateCommandsForContentRestrictionState(); |
3111 | 818 |
3112 UpdateCommandsForBookmarkEditing(); | 819 UpdateCommandsForBookmarkEditing(); |
3113 | 820 |
3114 UpdateCommandsForIncognitoAvailability(); | 821 UpdateCommandsForIncognitoAvailability(); |
3115 } | 822 } |
3116 | 823 |
3117 void Browser::UpdateCommandsForIncognitoAvailability() { | 824 void BrowserCommandController::UpdateCommandsForIncognitoAvailability() { |
3118 IncognitoModePrefs::Availability incognito_availability = | 825 IncognitoModePrefs::Availability incognito_availability = |
3119 IncognitoModePrefs::GetAvailability(profile_->GetPrefs()); | 826 IncognitoModePrefs::GetAvailability(profile()->GetPrefs()); |
3120 command_updater_.UpdateCommandEnabled( | 827 command_updater_.UpdateCommandEnabled( |
3121 IDC_NEW_WINDOW, | 828 IDC_NEW_WINDOW, |
3122 incognito_availability != IncognitoModePrefs::FORCED); | 829 incognito_availability != IncognitoModePrefs::FORCED); |
3123 command_updater_.UpdateCommandEnabled( | 830 command_updater_.UpdateCommandEnabled( |
3124 IDC_NEW_INCOGNITO_WINDOW, | 831 IDC_NEW_INCOGNITO_WINDOW, |
3125 incognito_availability != IncognitoModePrefs::DISABLED); | 832 incognito_availability != IncognitoModePrefs::DISABLED); |
3126 | 833 |
3127 // Bookmark manager and settings page/subpages are forced to open in normal | 834 // Bookmark manager and settings page/subpages are forced to open in normal |
3128 // mode. For this reason we disable these commands when incognito is forced. | 835 // mode. For this reason we disable these commands when incognito is forced. |
3129 const bool command_enabled = | 836 const bool command_enabled = |
3130 incognito_availability != IncognitoModePrefs::FORCED; | 837 incognito_availability != IncognitoModePrefs::FORCED; |
3131 command_updater_.UpdateCommandEnabled( | 838 command_updater_.UpdateCommandEnabled( |
3132 IDC_SHOW_BOOKMARK_MANAGER, | 839 IDC_SHOW_BOOKMARK_MANAGER, |
3133 browser_defaults::bookmarks_enabled && command_enabled); | 840 browser_defaults::bookmarks_enabled && command_enabled); |
3134 ExtensionService* extension_service = profile()->GetExtensionService(); | 841 ExtensionService* extension_service = profile()->GetExtensionService(); |
3135 bool enable_extensions = | 842 bool enable_extensions = |
3136 extension_service && extension_service->extensions_enabled(); | 843 extension_service && extension_service->extensions_enabled(); |
3137 command_updater_.UpdateCommandEnabled(IDC_MANAGE_EXTENSIONS, | 844 command_updater_.UpdateCommandEnabled(IDC_MANAGE_EXTENSIONS, |
3138 enable_extensions && command_enabled); | 845 enable_extensions && command_enabled); |
3139 | 846 |
3140 const bool show_main_ui = IsShowingMainUI(window_ && window_->IsFullscreen()); | 847 const bool show_main_ui = |
| 848 IsShowingMainUI(window() && window()->IsFullscreen()); |
3141 command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, | 849 command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, |
3142 show_main_ui && command_enabled); | 850 show_main_ui && command_enabled); |
3143 command_updater_.UpdateCommandEnabled(IDC_OPTIONS, | 851 command_updater_.UpdateCommandEnabled(IDC_OPTIONS, |
3144 show_main_ui && command_enabled); | 852 show_main_ui && command_enabled); |
3145 } | 853 } |
3146 | 854 |
3147 void Browser::UpdateCommandsForTabState() { | 855 void BrowserCommandController::UpdateCommandsForTabState() { |
3148 TabContents* current_tab_contents = GetActiveTabContents(); | 856 TabContents* current_tab_contents = browser_->GetActiveTabContents(); |
3149 if (!current_tab_contents) // May be NULL during tab restore. | 857 if (!current_tab_contents) // May be NULL during tab restore. |
3150 return; | 858 return; |
3151 WebContents* current_web_contents = current_tab_contents->web_contents(); | 859 WebContents* current_web_contents = current_tab_contents->web_contents(); |
3152 | 860 |
3153 // Navigation commands | 861 // Navigation commands |
3154 NavigationController& nc = current_web_contents->GetController(); | 862 command_updater_.UpdateCommandEnabled(IDC_BACK, CanGoBack(browser_)); |
3155 command_updater_.UpdateCommandEnabled(IDC_BACK, nc.CanGoBack()); | 863 command_updater_.UpdateCommandEnabled(IDC_FORWARD, CanGoForward(browser_)); |
3156 command_updater_.UpdateCommandEnabled(IDC_FORWARD, nc.CanGoForward()); | 864 command_updater_.UpdateCommandEnabled(IDC_RELOAD, CanReload(browser_)); |
3157 command_updater_.UpdateCommandEnabled( | 865 command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE, |
3158 IDC_RELOAD, CanReloadContents(current_tab_contents)); | 866 CanReload(browser_)); |
3159 command_updater_.UpdateCommandEnabled( | |
3160 IDC_RELOAD_IGNORING_CACHE, CanReloadContents(current_tab_contents)); | |
3161 | 867 |
3162 // Window management commands | 868 // Window management commands |
3163 command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB, | 869 command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB, |
3164 !is_app() && CanDuplicateContentsAt(active_index())); | 870 !browser_->is_app() && CanDuplicateTab(browser_)); |
3165 | 871 |
3166 // Page-related commands | 872 // Page-related commands |
3167 window_->SetStarredState( | 873 window()->SetStarredState( |
3168 current_tab_contents->bookmark_tab_helper()->is_starred()); | 874 current_tab_contents->bookmark_tab_helper()->is_starred()); |
3169 window_->SetZoomIconState( | 875 window()->SetZoomIconState( |
3170 current_tab_contents->zoom_controller()->zoom_icon_state()); | 876 current_tab_contents->zoom_controller()->zoom_icon_state()); |
3171 window_->SetZoomIconTooltipPercent( | 877 window()->SetZoomIconTooltipPercent( |
3172 current_tab_contents->zoom_controller()->zoom_percent()); | 878 current_tab_contents->zoom_controller()->zoom_percent()); |
3173 command_updater_.UpdateCommandEnabled(IDC_VIEW_SOURCE, | 879 command_updater_.UpdateCommandEnabled(IDC_VIEW_SOURCE, |
3174 current_web_contents->GetController().CanViewSource()); | 880 CanViewSource(browser_)); |
3175 command_updater_.UpdateCommandEnabled(IDC_EMAIL_PAGE_LOCATION, | 881 command_updater_.UpdateCommandEnabled(IDC_EMAIL_PAGE_LOCATION, |
3176 toolbar_model_->ShouldDisplayURL() && | 882 CanEmailPageLocation(browser_)); |
3177 current_web_contents->GetURL().is_valid()); | 883 if (browser_->is_devtools()) |
3178 if (is_devtools()) | 884 command_updater_.UpdateCommandEnabled(IDC_OPEN_FILE, false); |
3179 command_updater_.UpdateCommandEnabled(IDC_OPEN_FILE, false); | |
3180 | 885 |
3181 // Changing the encoding is not possible on Chrome-internal webpages. | 886 // Changing the encoding is not possible on Chrome-internal webpages. |
| 887 NavigationController& nc = current_web_contents->GetController(); |
3182 bool is_chrome_internal = HasInternalURL(nc.GetActiveEntry()) || | 888 bool is_chrome_internal = HasInternalURL(nc.GetActiveEntry()) || |
3183 current_web_contents->ShowingInterstitialPage(); | 889 current_web_contents->ShowingInterstitialPage(); |
3184 command_updater_.UpdateCommandEnabled(IDC_ENCODING_MENU, | 890 command_updater_.UpdateCommandEnabled(IDC_ENCODING_MENU, |
3185 !is_chrome_internal && current_web_contents->IsSavable()); | 891 !is_chrome_internal && current_web_contents->IsSavable()); |
3186 | 892 |
3187 // Show various bits of UI | 893 // Show various bits of UI |
3188 // TODO(pinkerton): Disable app-mode in the model until we implement it | 894 // TODO(pinkerton): Disable app-mode in the model until we implement it |
3189 // on the Mac. Be sure to remove both ifdefs. http://crbug.com/13148 | 895 // on the Mac. Be sure to remove both ifdefs. http://crbug.com/13148 |
3190 #if !defined(OS_MACOSX) | 896 #if !defined(OS_MACOSX) |
3191 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS, | 897 command_updater_.UpdateCommandEnabled( |
3192 web_app::IsValidUrl(current_web_contents->GetURL())); | 898 IDC_CREATE_SHORTCUTS, |
| 899 CanCreateApplicationShortcuts(browser_)); |
3193 #endif | 900 #endif |
3194 | 901 |
3195 UpdateCommandsForContentRestrictionState(); | 902 UpdateCommandsForContentRestrictionState(); |
3196 UpdateCommandsForBookmarkEditing(); | 903 UpdateCommandsForBookmarkEditing(); |
3197 } | 904 } |
3198 | 905 |
3199 void Browser::UpdateCommandsForContentRestrictionState() { | 906 void BrowserCommandController::UpdateCommandsForContentRestrictionState() { |
3200 int restrictions = GetContentRestrictionsForSelectedTab(); | 907 int restrictions = GetContentRestrictions(browser_); |
3201 | 908 |
3202 command_updater_.UpdateCommandEnabled( | 909 command_updater_.UpdateCommandEnabled( |
3203 IDC_COPY, !(restrictions & content::CONTENT_RESTRICTION_COPY)); | 910 IDC_COPY, !(restrictions & content::CONTENT_RESTRICTION_COPY)); |
3204 command_updater_.UpdateCommandEnabled( | 911 command_updater_.UpdateCommandEnabled( |
3205 IDC_CUT, !(restrictions & content::CONTENT_RESTRICTION_CUT)); | 912 IDC_CUT, !(restrictions & content::CONTENT_RESTRICTION_CUT)); |
3206 command_updater_.UpdateCommandEnabled( | 913 command_updater_.UpdateCommandEnabled( |
3207 IDC_PASTE, !(restrictions & content::CONTENT_RESTRICTION_PASTE)); | 914 IDC_PASTE, !(restrictions & content::CONTENT_RESTRICTION_PASTE)); |
3208 UpdateSaveAsState(restrictions); | 915 UpdateSaveAsState(); |
3209 UpdatePrintingState(restrictions); | 916 UpdatePrintingState(); |
3210 } | 917 } |
3211 | 918 |
3212 void Browser::UpdateCommandsForDevTools() { | 919 void BrowserCommandController::UpdateCommandsForDevTools() { |
3213 bool dev_tools_enabled = | 920 bool dev_tools_enabled = |
3214 !profile_->GetPrefs()->GetBoolean(prefs::kDevToolsDisabled); | 921 !profile()->GetPrefs()->GetBoolean(prefs::kDevToolsDisabled); |
3215 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS, | 922 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS, |
3216 dev_tools_enabled); | 923 dev_tools_enabled); |
3217 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_CONSOLE, | 924 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_CONSOLE, |
3218 dev_tools_enabled); | 925 dev_tools_enabled); |
3219 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_INSPECT, | 926 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_INSPECT, |
3220 dev_tools_enabled); | 927 dev_tools_enabled); |
3221 } | 928 } |
3222 | 929 |
3223 void Browser::UpdateCommandsForBookmarkEditing() { | 930 void BrowserCommandController::UpdateCommandsForBookmarkEditing() { |
3224 bool enabled = | |
3225 profile_->GetPrefs()->GetBoolean(prefs::kEditBookmarksEnabled) && | |
3226 browser_defaults::bookmarks_enabled; | |
3227 | |
3228 command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_PAGE, | 931 command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_PAGE, |
3229 enabled && is_type_tabbed()); | 932 CanBookmarkCurrentPage(browser_)); |
3230 command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_ALL_TABS, | 933 command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_ALL_TABS, |
3231 enabled && CanBookmarkAllTabs()); | 934 CanBookmarkAllTabs(browser_)); |
3232 command_updater_.UpdateCommandEnabled(IDC_PIN_TO_START_SCREEN, | 935 command_updater_.UpdateCommandEnabled(IDC_PIN_TO_START_SCREEN, |
3233 true); | 936 true); |
3234 } | 937 } |
3235 | 938 |
3236 void Browser::UpdateCommandsForBookmarkBar() { | 939 void BrowserCommandController::UpdateCommandsForBookmarkBar() { |
3237 const bool show_main_ui = IsShowingMainUI(window_ && window_->IsFullscreen()); | 940 const bool show_main_ui = |
| 941 IsShowingMainUI(window() && window()->IsFullscreen()); |
3238 command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_BAR, | 942 command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_BAR, |
3239 browser_defaults::bookmarks_enabled && | 943 browser_defaults::bookmarks_enabled && |
3240 !profile_->GetPrefs()->IsManagedPreference(prefs::kShowBookmarkBar) && | 944 !profile()->GetPrefs()->IsManagedPreference(prefs::kShowBookmarkBar) && |
3241 show_main_ui); | 945 show_main_ui); |
3242 } | 946 } |
3243 | 947 |
3244 void Browser::MarkHomePageAsChanged(PrefService* pref_service) { | 948 void BrowserCommandController::UpdateCommandsForFullscreenMode( |
3245 pref_service->SetBoolean(prefs::kHomePageChanged, true); | 949 FullScreenMode fullscreen_mode) { |
3246 } | |
3247 | |
3248 void Browser::UpdateCommandsForFullscreenMode(FullScreenMode fullscreen_mode) { | |
3249 const bool show_main_ui = | 950 const bool show_main_ui = |
3250 IsShowingMainUI(fullscreen_mode != FULLSCREEN_DISABLED); | 951 IsShowingMainUI(fullscreen_mode != FULLSCREEN_DISABLED); |
3251 bool main_not_fullscreen = show_main_ui && | 952 bool main_not_fullscreen = show_main_ui && |
3252 (fullscreen_mode == FULLSCREEN_DISABLED); | 953 (fullscreen_mode == FULLSCREEN_DISABLED); |
3253 | 954 |
3254 // Navigation commands | 955 // Navigation commands |
3255 command_updater_.UpdateCommandEnabled(IDC_OPEN_CURRENT_URL, show_main_ui); | 956 command_updater_.UpdateCommandEnabled(IDC_OPEN_CURRENT_URL, show_main_ui); |
3256 | 957 |
3257 // Window management commands | 958 // Window management commands |
3258 command_updater_.UpdateCommandEnabled(IDC_SHOW_AS_TAB, | 959 command_updater_.UpdateCommandEnabled( |
3259 type_ != TYPE_TABBED && (fullscreen_mode == FULLSCREEN_DISABLED)); | 960 IDC_SHOW_AS_TAB, |
| 961 !browser_->is_type_tabbed() && fullscreen_mode == FULLSCREEN_DISABLED); |
3260 | 962 |
3261 // Focus various bits of UI | 963 // Focus various bits of UI |
3262 command_updater_.UpdateCommandEnabled(IDC_FOCUS_TOOLBAR, show_main_ui); | 964 command_updater_.UpdateCommandEnabled(IDC_FOCUS_TOOLBAR, show_main_ui); |
3263 command_updater_.UpdateCommandEnabled(IDC_FOCUS_LOCATION, show_main_ui); | 965 command_updater_.UpdateCommandEnabled(IDC_FOCUS_LOCATION, show_main_ui); |
3264 command_updater_.UpdateCommandEnabled(IDC_FOCUS_SEARCH, show_main_ui); | 966 command_updater_.UpdateCommandEnabled(IDC_FOCUS_SEARCH, show_main_ui); |
3265 command_updater_.UpdateCommandEnabled( | 967 command_updater_.UpdateCommandEnabled( |
3266 IDC_FOCUS_MENU_BAR, main_not_fullscreen); | 968 IDC_FOCUS_MENU_BAR, main_not_fullscreen); |
3267 command_updater_.UpdateCommandEnabled( | 969 command_updater_.UpdateCommandEnabled( |
3268 IDC_FOCUS_NEXT_PANE, main_not_fullscreen); | 970 IDC_FOCUS_NEXT_PANE, main_not_fullscreen); |
3269 command_updater_.UpdateCommandEnabled( | 971 command_updater_.UpdateCommandEnabled( |
3270 IDC_FOCUS_PREVIOUS_PANE, main_not_fullscreen); | 972 IDC_FOCUS_PREVIOUS_PANE, main_not_fullscreen); |
3271 command_updater_.UpdateCommandEnabled( | 973 command_updater_.UpdateCommandEnabled( |
3272 IDC_FOCUS_BOOKMARKS, main_not_fullscreen); | 974 IDC_FOCUS_BOOKMARKS, main_not_fullscreen); |
3273 | 975 |
3274 // Show various bits of UI | 976 // Show various bits of UI |
3275 command_updater_.UpdateCommandEnabled(IDC_DEVELOPER_MENU, show_main_ui); | 977 command_updater_.UpdateCommandEnabled(IDC_DEVELOPER_MENU, show_main_ui); |
3276 command_updater_.UpdateCommandEnabled(IDC_FEEDBACK, show_main_ui); | 978 command_updater_.UpdateCommandEnabled(IDC_FEEDBACK, show_main_ui); |
3277 command_updater_.UpdateCommandEnabled(IDC_SHOW_SYNC_SETUP, | 979 command_updater_.UpdateCommandEnabled(IDC_SHOW_SYNC_SETUP, |
3278 show_main_ui && profile_->GetOriginalProfile()->IsSyncAccessible()); | 980 show_main_ui && profile()->GetOriginalProfile()->IsSyncAccessible()); |
3279 | 981 |
3280 // Settings page/subpages are forced to open in normal mode. We disable these | 982 // Settings page/subpages are forced to open in normal mode. We disable these |
3281 // commands when incognito is forced. | 983 // commands when incognito is forced. |
3282 const bool options_enabled = show_main_ui && | 984 const bool options_enabled = show_main_ui && |
3283 IncognitoModePrefs::GetAvailability( | 985 IncognitoModePrefs::GetAvailability( |
3284 profile_->GetPrefs()) != IncognitoModePrefs::FORCED; | 986 profile()->GetPrefs()) != IncognitoModePrefs::FORCED; |
3285 command_updater_.UpdateCommandEnabled(IDC_OPTIONS, options_enabled); | 987 command_updater_.UpdateCommandEnabled(IDC_OPTIONS, options_enabled); |
3286 command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, options_enabled); | 988 command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, options_enabled); |
3287 | 989 |
3288 command_updater_.UpdateCommandEnabled(IDC_EDIT_SEARCH_ENGINES, show_main_ui); | 990 command_updater_.UpdateCommandEnabled(IDC_EDIT_SEARCH_ENGINES, show_main_ui); |
3289 command_updater_.UpdateCommandEnabled(IDC_VIEW_PASSWORDS, show_main_ui); | 991 command_updater_.UpdateCommandEnabled(IDC_VIEW_PASSWORDS, show_main_ui); |
3290 command_updater_.UpdateCommandEnabled(IDC_ABOUT, show_main_ui); | 992 command_updater_.UpdateCommandEnabled(IDC_ABOUT, show_main_ui); |
3291 command_updater_.UpdateCommandEnabled(IDC_SHOW_APP_MENU, show_main_ui); | 993 command_updater_.UpdateCommandEnabled(IDC_SHOW_APP_MENU, show_main_ui); |
3292 #if defined (ENABLE_PROFILING) && !defined(NO_TCMALLOC) | 994 #if defined (ENABLE_PROFILING) && !defined(NO_TCMALLOC) |
3293 command_updater_.UpdateCommandEnabled(IDC_PROFILING_ENABLED, show_main_ui); | 995 command_updater_.UpdateCommandEnabled(IDC_PROFILING_ENABLED, show_main_ui); |
3294 #endif | 996 #endif |
3295 | 997 |
3296 // Disable explicit fullscreen toggling when in metro snap mode. | 998 // Disable explicit fullscreen toggling when in metro snap mode. |
3297 command_updater_.UpdateCommandEnabled( | 999 command_updater_.UpdateCommandEnabled( |
3298 IDC_FULLSCREEN, | 1000 IDC_FULLSCREEN, |
3299 fullscreen_mode != FULLSCREEN_METRO_SNAP); | 1001 fullscreen_mode != FULLSCREEN_METRO_SNAP); |
3300 | 1002 |
3301 UpdateCommandsForBookmarkBar(); | 1003 UpdateCommandsForBookmarkBar(); |
3302 UpdateCommandsForMultipleProfiles(); | 1004 UpdateCommandsForMultipleProfiles(); |
3303 } | 1005 } |
3304 | 1006 |
3305 void Browser::UpdateCommandsForMultipleProfiles() { | 1007 void BrowserCommandController::UpdateCommandsForMultipleProfiles() { |
3306 bool show_main_ui = IsShowingMainUI(window_ && window_->IsFullscreen()); | 1008 bool show_main_ui = IsShowingMainUI(window() && window()->IsFullscreen()); |
3307 command_updater_.UpdateCommandEnabled(IDC_SHOW_AVATAR_MENU, | 1009 command_updater_.UpdateCommandEnabled(IDC_SHOW_AVATAR_MENU, |
3308 show_main_ui && | 1010 show_main_ui && |
3309 !profile()->IsOffTheRecord() && | 1011 !profile()->IsOffTheRecord() && |
3310 ProfileManager::IsMultipleProfilesEnabled()); | 1012 ProfileManager::IsMultipleProfilesEnabled()); |
3311 } | 1013 } |
3312 | 1014 |
3313 void Browser::UpdatePrintingState(int content_restrictions) { | 1015 void BrowserCommandController::UpdatePrintingState() { |
3314 bool print_enabled = true; | 1016 command_updater_.UpdateCommandEnabled(IDC_PRINT, CanPrint(browser_)); |
3315 bool advanced_print_enabled = true; | |
3316 if (g_browser_process->local_state()) { | |
3317 print_enabled = | |
3318 g_browser_process->local_state()->GetBoolean(prefs::kPrintingEnabled); | |
3319 advanced_print_enabled = print_enabled; | |
3320 } | |
3321 if (print_enabled) { | |
3322 // Do not print when a constrained window is showing. It's confusing. | |
3323 TabContents* tab_contents = GetActiveTabContents(); | |
3324 bool has_constrained_window = | |
3325 tab_contents && | |
3326 tab_contents->constrained_window_tab_helper()-> | |
3327 constrained_window_count(); | |
3328 if (has_constrained_window || | |
3329 content_restrictions & content::CONTENT_RESTRICTION_PRINT) { | |
3330 print_enabled = false; | |
3331 advanced_print_enabled = false; | |
3332 } | |
3333 | |
3334 // The exception is print preview, | |
3335 // where advanced printing is always enabled. | |
3336 printing::PrintPreviewTabController* controller = | |
3337 printing::PrintPreviewTabController::GetInstance(); | |
3338 if (controller && (controller->GetPrintPreviewForTab(tab_contents) || | |
3339 controller->is_creating_print_preview_tab())) { | |
3340 advanced_print_enabled = true; | |
3341 } | |
3342 } | |
3343 command_updater_.UpdateCommandEnabled(IDC_PRINT, print_enabled); | |
3344 command_updater_.UpdateCommandEnabled(IDC_ADVANCED_PRINT, | 1017 command_updater_.UpdateCommandEnabled(IDC_ADVANCED_PRINT, |
3345 advanced_print_enabled); | 1018 CanAdvancedPrint(browser_)); |
3346 } | 1019 } |
3347 | 1020 |
3348 void Browser::UpdateSaveAsState(int content_restrictions) { | 1021 void BrowserCommandController::UpdateSaveAsState() { |
3349 bool enabled = !(content_restrictions & content::CONTENT_RESTRICTION_SAVE); | 1022 command_updater_.UpdateCommandEnabled(IDC_SAVE_PAGE, CanSavePage(browser_)); |
3350 enabled = enabled && CanSaveContents(GetActiveTabContents()); | |
3351 PrefService* state = g_browser_process->local_state(); | |
3352 if (state) | |
3353 enabled = enabled && state->GetBoolean(prefs::kAllowFileSelectionDialogs); | |
3354 | |
3355 command_updater_.UpdateCommandEnabled(IDC_SAVE_PAGE, enabled); | |
3356 } | 1023 } |
3357 | 1024 |
3358 void Browser::UpdateOpenFileState() { | 1025 void BrowserCommandController::UpdateOpenFileState() { |
3359 bool enabled = true; | 1026 bool enabled = true; |
3360 PrefService* local_state = g_browser_process->local_state(); | 1027 PrefService* local_state = g_browser_process->local_state(); |
3361 if (local_state) | 1028 if (local_state) |
3362 enabled = local_state->GetBoolean(prefs::kAllowFileSelectionDialogs); | 1029 enabled = local_state->GetBoolean(prefs::kAllowFileSelectionDialogs); |
3363 | 1030 |
3364 command_updater_.UpdateCommandEnabled(IDC_OPEN_FILE, enabled); | 1031 command_updater_.UpdateCommandEnabled(IDC_OPEN_FILE, enabled); |
3365 } | 1032 } |
3366 | 1033 |
3367 void Browser::UpdateReloadStopState(bool is_loading, bool force) { | 1034 void BrowserCommandController::UpdateReloadStopState(bool is_loading, |
3368 window_->UpdateReloadStopState(is_loading, force); | 1035 bool force) { |
| 1036 window()->UpdateReloadStopState(is_loading, force); |
3369 command_updater_.UpdateCommandEnabled(IDC_STOP, is_loading); | 1037 command_updater_.UpdateCommandEnabled(IDC_STOP, is_loading); |
3370 } | 1038 } |
3371 | 1039 |
3372 /////////////////////////////////////////////////////////////////////////////// | 1040 void BrowserCommandController::AddInterstitialObservers(TabContents* contents) { |
3373 // Browser, UI update coalescing and handling (private): | 1041 registrar_.Add(this, content::NOTIFICATION_INTERSTITIAL_ATTACHED, |
3374 | 1042 content::Source<WebContents>(contents->web_contents())); |
3375 void Browser::UpdateToolbar(bool should_restore_state) { | 1043 registrar_.Add(this, content::NOTIFICATION_INTERSTITIAL_DETACHED, |
3376 window_->UpdateToolbar(GetActiveTabContents(), should_restore_state); | 1044 content::Source<WebContents>(contents->web_contents())); |
3377 } | 1045 } |
3378 | 1046 |
3379 void Browser::UpdateSearchState(TabContents* contents) { | 1047 void BrowserCommandController::RemoveInterstitialObservers( |
3380 if (chrome::search::IsInstantExtendedAPIEnabled(profile_)) | 1048 TabContents* contents) { |
3381 search_delegate_->OnTabActivated(contents); | |
3382 } | |
3383 | |
3384 void Browser::ScheduleUIUpdate(const WebContents* source, | |
3385 unsigned changed_flags) { | |
3386 if (!source) | |
3387 return; | |
3388 | |
3389 // Do some synchronous updates. | |
3390 if (changed_flags & content::INVALIDATE_TYPE_URL && | |
3391 source == GetActiveWebContents()) { | |
3392 // Only update the URL for the current tab. Note that we do not update | |
3393 // the navigation commands since those would have already been updated | |
3394 // synchronously by NavigationStateChanged. | |
3395 UpdateToolbar(false); | |
3396 changed_flags &= ~content::INVALIDATE_TYPE_URL; | |
3397 } | |
3398 if (changed_flags & content::INVALIDATE_TYPE_LOAD) { | |
3399 // Update the loading state synchronously. This is so the throbber will | |
3400 // immediately start/stop, which gives a more snappy feel. We want to do | |
3401 // this for any tab so they start & stop quickly. | |
3402 tab_strip_model_->UpdateTabContentsStateAt( | |
3403 GetIndexOfController(&source->GetController()), | |
3404 TabStripModelObserver::LOADING_ONLY); | |
3405 // The status bubble needs to be updated during INVALIDATE_TYPE_LOAD too, | |
3406 // but we do that asynchronously by not stripping INVALIDATE_TYPE_LOAD from | |
3407 // changed_flags. | |
3408 } | |
3409 | |
3410 if (changed_flags & content::INVALIDATE_TYPE_TITLE && !source->IsLoading()) { | |
3411 // To correctly calculate whether the title changed while not loading | |
3412 // we need to process the update synchronously. This state only matters for | |
3413 // the TabStripModel, so we notify the TabStripModel now and notify others | |
3414 // asynchronously. | |
3415 tab_strip_model_->UpdateTabContentsStateAt( | |
3416 GetIndexOfController(&source->GetController()), | |
3417 TabStripModelObserver::TITLE_NOT_LOADING); | |
3418 } | |
3419 | |
3420 // If the only updates were synchronously handled above, we're done. | |
3421 if (changed_flags == 0) | |
3422 return; | |
3423 | |
3424 // Save the dirty bits. | |
3425 scheduled_updates_[source] |= changed_flags; | |
3426 | |
3427 if (!chrome_updater_factory_.HasWeakPtrs()) { | |
3428 // No task currently scheduled, start another. | |
3429 MessageLoop::current()->PostDelayedTask( | |
3430 FROM_HERE, | |
3431 base::Bind(&Browser::ProcessPendingUIUpdates, | |
3432 chrome_updater_factory_.GetWeakPtr()), | |
3433 base::TimeDelta::FromMilliseconds(kUIUpdateCoalescingTimeMS)); | |
3434 } | |
3435 } | |
3436 | |
3437 void Browser::ProcessPendingUIUpdates() { | |
3438 #ifndef NDEBUG | |
3439 // Validate that all tabs we have pending updates for exist. This is scary | |
3440 // because the pending list must be kept in sync with any detached or | |
3441 // deleted tabs. | |
3442 for (UpdateMap::const_iterator i = scheduled_updates_.begin(); | |
3443 i != scheduled_updates_.end(); ++i) { | |
3444 bool found = false; | |
3445 for (int tab = 0; tab < tab_count(); tab++) { | |
3446 if (GetWebContentsAt(tab) == i->first) { | |
3447 found = true; | |
3448 break; | |
3449 } | |
3450 } | |
3451 DCHECK(found); | |
3452 } | |
3453 #endif | |
3454 | |
3455 chrome_updater_factory_.InvalidateWeakPtrs(); | |
3456 | |
3457 for (UpdateMap::const_iterator i = scheduled_updates_.begin(); | |
3458 i != scheduled_updates_.end(); ++i) { | |
3459 // Do not dereference |contents|, it may be out-of-date! | |
3460 const WebContents* contents = i->first; | |
3461 unsigned flags = i->second; | |
3462 | |
3463 if (contents == GetActiveWebContents()) { | |
3464 // Updates that only matter when the tab is selected go here. | |
3465 | |
3466 if (flags & content::INVALIDATE_TYPE_PAGE_ACTIONS) { | |
3467 LocationBar* location_bar = window()->GetLocationBar(); | |
3468 if (location_bar) | |
3469 location_bar->UpdatePageActions(); | |
3470 } | |
3471 // Updating the URL happens synchronously in ScheduleUIUpdate. | |
3472 if (flags & content::INVALIDATE_TYPE_LOAD && GetStatusBubble()) { | |
3473 GetStatusBubble()->SetStatus( | |
3474 GetActiveTabContents()-> | |
3475 core_tab_helper()->GetStatusText()); | |
3476 } | |
3477 | |
3478 if (flags & (content::INVALIDATE_TYPE_TAB | | |
3479 content::INVALIDATE_TYPE_TITLE)) { | |
3480 // TODO(pinkerton): Disable app-mode in the model until we implement it | |
3481 // on the Mac. Be sure to remove both ifdefs. http://crbug.com/13148 | |
3482 #if !defined(OS_MACOSX) | |
3483 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS, | |
3484 web_app::IsValidUrl(contents->GetURL())); | |
3485 #endif | |
3486 window_->UpdateTitleBar(); | |
3487 } | |
3488 } | |
3489 | |
3490 // Updates that don't depend upon the selected state go here. | |
3491 if (flags & | |
3492 (content::INVALIDATE_TYPE_TAB | content::INVALIDATE_TYPE_TITLE)) { | |
3493 tab_strip_model_->UpdateTabContentsStateAt( | |
3494 tab_strip_model_->GetIndexOfWebContents(contents), | |
3495 TabStripModelObserver::ALL); | |
3496 } | |
3497 | |
3498 // We don't need to process INVALIDATE_STATE, since that's not visible. | |
3499 } | |
3500 | |
3501 scheduled_updates_.clear(); | |
3502 } | |
3503 | |
3504 void Browser::RemoveScheduledUpdatesFor(WebContents* contents) { | |
3505 if (!contents) | |
3506 return; | |
3507 | |
3508 UpdateMap::iterator i = scheduled_updates_.find(contents); | |
3509 if (i != scheduled_updates_.end()) | |
3510 scheduled_updates_.erase(i); | |
3511 } | |
3512 | |
3513 | |
3514 /////////////////////////////////////////////////////////////////////////////// | |
3515 // Browser, Getters for UI (private): | |
3516 | |
3517 StatusBubble* Browser::GetStatusBubble() { | |
3518 #if !defined(OS_MACOSX) | |
3519 // In kiosk mode, we want to always hide the status bubble. | |
3520 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) | |
3521 return NULL; | |
3522 #endif | |
3523 return window_ ? window_->GetStatusBubble() : NULL; | |
3524 } | |
3525 | |
3526 /////////////////////////////////////////////////////////////////////////////// | |
3527 // Browser, Session restore functions (private): | |
3528 | |
3529 void Browser::SyncHistoryWithTabs(int index) { | |
3530 SessionService* session_service = | |
3531 SessionServiceFactory::GetForProfileIfExisting(profile()); | |
3532 if (session_service) { | |
3533 for (int i = index; i < tab_count(); ++i) { | |
3534 TabContents* tab = GetTabContentsAt(i); | |
3535 if (tab) { | |
3536 session_service->SetTabIndexInWindow( | |
3537 session_id(), tab->restore_tab_helper()->session_id(), i); | |
3538 session_service->SetPinnedState( | |
3539 session_id(), | |
3540 tab->restore_tab_helper()->session_id(), | |
3541 IsTabPinned(i)); | |
3542 } | |
3543 } | |
3544 } | |
3545 } | |
3546 | |
3547 /////////////////////////////////////////////////////////////////////////////// | |
3548 // Browser, OnBeforeUnload handling (private): | |
3549 | |
3550 void Browser::ProcessPendingTabs() { | |
3551 if (!is_attempting_to_close_browser_) { | |
3552 // Because we might invoke this after a delay it's possible for the value of | |
3553 // is_attempting_to_close_browser_ to have changed since we scheduled the | |
3554 // task. | |
3555 return; | |
3556 } | |
3557 | |
3558 if (HasCompletedUnloadProcessing()) { | |
3559 // We've finished all the unload events and can proceed to close the | |
3560 // browser. | |
3561 OnWindowClosing(); | |
3562 return; | |
3563 } | |
3564 | |
3565 // Process beforeunload tabs first. When that queue is empty, process | |
3566 // unload tabs. | |
3567 if (!tabs_needing_before_unload_fired_.empty()) { | |
3568 WebContents* web_contents = *(tabs_needing_before_unload_fired_.begin()); | |
3569 // Null check render_view_host here as this gets called on a PostTask and | |
3570 // the tab's render_view_host may have been nulled out. | |
3571 if (web_contents->GetRenderViewHost()) { | |
3572 web_contents->GetRenderViewHost()->FirePageBeforeUnload(false); | |
3573 } else { | |
3574 ClearUnloadState(web_contents, true); | |
3575 } | |
3576 } else if (!tabs_needing_unload_fired_.empty()) { | |
3577 // We've finished firing all beforeunload events and can proceed with unload | |
3578 // events. | |
3579 // TODO(ojan): We should add a call to browser_shutdown::OnShutdownStarting | |
3580 // somewhere around here so that we have accurate measurements of shutdown | |
3581 // time. | |
3582 // TODO(ojan): We can probably fire all the unload events in parallel and | |
3583 // get a perf benefit from that in the cases where the tab hangs in it's | |
3584 // unload handler or takes a long time to page in. | |
3585 WebContents* web_contents = *(tabs_needing_unload_fired_.begin()); | |
3586 // Null check render_view_host here as this gets called on a PostTask and | |
3587 // the tab's render_view_host may have been nulled out. | |
3588 if (web_contents->GetRenderViewHost()) { | |
3589 web_contents->GetRenderViewHost()->ClosePage(); | |
3590 } else { | |
3591 ClearUnloadState(web_contents, true); | |
3592 } | |
3593 } else { | |
3594 NOTREACHED(); | |
3595 } | |
3596 } | |
3597 | |
3598 bool Browser::HasCompletedUnloadProcessing() const { | |
3599 return is_attempting_to_close_browser_ && | |
3600 tabs_needing_before_unload_fired_.empty() && | |
3601 tabs_needing_unload_fired_.empty(); | |
3602 } | |
3603 | |
3604 void Browser::CancelWindowClose() { | |
3605 // Closing of window can be canceled from a beforeunload handler. | |
3606 DCHECK(is_attempting_to_close_browser_); | |
3607 tabs_needing_before_unload_fired_.clear(); | |
3608 tabs_needing_unload_fired_.clear(); | |
3609 is_attempting_to_close_browser_ = false; | |
3610 | |
3611 content::NotificationService::current()->Notify( | |
3612 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, | |
3613 content::Source<Browser>(this), | |
3614 content::NotificationService::NoDetails()); | |
3615 } | |
3616 | |
3617 bool Browser::RemoveFromSet(UnloadListenerSet* set, WebContents* web_contents) { | |
3618 DCHECK(is_attempting_to_close_browser_); | |
3619 | |
3620 UnloadListenerSet::iterator iter = | |
3621 std::find(set->begin(), set->end(), web_contents); | |
3622 if (iter != set->end()) { | |
3623 set->erase(iter); | |
3624 return true; | |
3625 } | |
3626 return false; | |
3627 } | |
3628 | |
3629 void Browser::ClearUnloadState(WebContents* web_contents, bool process_now) { | |
3630 if (is_attempting_to_close_browser_) { | |
3631 RemoveFromSet(&tabs_needing_before_unload_fired_, web_contents); | |
3632 RemoveFromSet(&tabs_needing_unload_fired_, web_contents); | |
3633 if (process_now) { | |
3634 ProcessPendingTabs(); | |
3635 } else { | |
3636 MessageLoop::current()->PostTask( | |
3637 FROM_HERE, | |
3638 base::Bind(&Browser::ProcessPendingTabs, weak_factory_.GetWeakPtr())); | |
3639 } | |
3640 } | |
3641 } | |
3642 | |
3643 /////////////////////////////////////////////////////////////////////////////// | |
3644 // Browser, In-progress download termination handling (private): | |
3645 | |
3646 bool Browser::CanCloseWithInProgressDownloads() { | |
3647 // If we've prompted, we need to hear from the user before we | |
3648 // can close. | |
3649 if (cancel_download_confirmation_state_ != NOT_PROMPTED) | |
3650 return cancel_download_confirmation_state_ != WAITING_FOR_RESPONSE; | |
3651 | |
3652 int num_downloads_blocking; | |
3653 if (DOWNLOAD_CLOSE_OK == | |
3654 OkToCloseWithInProgressDownloads(&num_downloads_blocking)) | |
3655 return true; | |
3656 | |
3657 // Closing this window will kill some downloads; prompt to make sure | |
3658 // that's ok. | |
3659 cancel_download_confirmation_state_ = WAITING_FOR_RESPONSE; | |
3660 window_->ConfirmBrowserCloseWithPendingDownloads(); | |
3661 | |
3662 // Return false so the browser does not close. We'll close if the user | |
3663 // confirms in the dialog. | |
3664 return false; | |
3665 } | |
3666 | |
3667 /////////////////////////////////////////////////////////////////////////////// | |
3668 // Browser, Assorted utility functions (private): | |
3669 | |
3670 void Browser::SetAsDelegate(TabContents* tab, Browser* delegate) { | |
3671 // WebContents... | |
3672 tab->web_contents()->SetDelegate(delegate); | |
3673 | |
3674 // ...and all the helpers. | |
3675 tab->blocked_content_tab_helper()->set_delegate(delegate); | |
3676 tab->bookmark_tab_helper()->set_delegate(delegate); | |
3677 tab->zoom_controller()->set_observer(delegate); | |
3678 tab->constrained_window_tab_helper()->set_delegate(delegate); | |
3679 tab->core_tab_helper()->set_delegate(delegate); | |
3680 tab->extension_tab_helper()->set_delegate(delegate); | |
3681 tab->search_engine_tab_helper()->set_delegate(delegate); | |
3682 } | |
3683 | |
3684 void Browser::CloseFrame() { | |
3685 window_->Close(); | |
3686 } | |
3687 | |
3688 void Browser::TabDetachedAtImpl(TabContents* contents, int index, | |
3689 DetachType type) { | |
3690 if (type == DETACH_TYPE_DETACH) { | |
3691 // Save the current location bar state, but only if the tab being detached | |
3692 // is the selected tab. Because saving state can conditionally revert the | |
3693 // location bar, saving the current tab's location bar state to a | |
3694 // non-selected tab can corrupt both tabs. | |
3695 if (contents == GetActiveTabContents()) { | |
3696 LocationBar* location_bar = window()->GetLocationBar(); | |
3697 if (location_bar) | |
3698 location_bar->SaveStateToContents(contents->web_contents()); | |
3699 } | |
3700 | |
3701 if (!tab_strip_model_->closing_all()) | |
3702 SyncHistoryWithTabs(0); | |
3703 } | |
3704 | |
3705 SetAsDelegate(contents, NULL); | |
3706 RemoveScheduledUpdatesFor(contents->web_contents()); | |
3707 | |
3708 if (find_bar_controller_.get() && index == active_index()) { | |
3709 find_bar_controller_->ChangeTabContents(NULL); | |
3710 } | |
3711 | |
3712 if (is_attempting_to_close_browser_) { | |
3713 // If this is the last tab with unload handlers, then ProcessPendingTabs | |
3714 // would call back into the TabStripModel (which is invoking this method on | |
3715 // us). Avoid that by passing in false so that the call to | |
3716 // ProcessPendingTabs is delayed. | |
3717 ClearUnloadState(contents->web_contents(), false); | |
3718 } | |
3719 | |
3720 // Stop observing search model changes for this tab. | |
3721 search_delegate_->OnTabDetached(contents); | |
3722 | |
3723 registrar_.Remove(this, content::NOTIFICATION_INTERSTITIAL_ATTACHED, | 1049 registrar_.Remove(this, content::NOTIFICATION_INTERSTITIAL_ATTACHED, |
3724 content::Source<WebContents>(contents->web_contents())); | 1050 content::Source<WebContents>(contents->web_contents())); |
3725 registrar_.Remove(this, content::NOTIFICATION_INTERSTITIAL_DETACHED, | 1051 registrar_.Remove(this, content::NOTIFICATION_INTERSTITIAL_DETACHED, |
3726 content::Source<WebContents>(contents->web_contents())); | 1052 content::Source<WebContents>(contents->web_contents())); |
3727 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, | |
3728 content::Source<WebContents>(contents->web_contents())); | |
3729 } | 1053 } |
3730 | 1054 |
3731 bool Browser::SupportsWindowFeatureImpl(WindowFeature feature, | 1055 BrowserWindow* BrowserCommandController::window() { |
3732 bool check_fullscreen) const { | 1056 return browser_->window(); |
3733 // On Mac, fullscreen mode has most normal things (in a slide-down panel). On | |
3734 // other platforms, we hide some controls when in fullscreen mode. | |
3735 bool hide_ui_for_fullscreen = false; | |
3736 #if !defined(OS_MACOSX) | |
3737 hide_ui_for_fullscreen = check_fullscreen && window_ && | |
3738 window_->IsFullscreen(); | |
3739 #endif | |
3740 | |
3741 unsigned int features = FEATURE_INFOBAR | FEATURE_DOWNLOADSHELF; | |
3742 | |
3743 if (is_type_tabbed()) | |
3744 features |= FEATURE_BOOKMARKBAR; | |
3745 | |
3746 if (!hide_ui_for_fullscreen) { | |
3747 if (!is_type_tabbed()) | |
3748 features |= FEATURE_TITLEBAR; | |
3749 | |
3750 if (is_type_tabbed()) | |
3751 features |= FEATURE_TABSTRIP; | |
3752 | |
3753 if (is_type_tabbed()) | |
3754 features |= FEATURE_TOOLBAR; | |
3755 | |
3756 if (!is_app()) | |
3757 features |= FEATURE_LOCATIONBAR; | |
3758 } | |
3759 return !!(features & feature); | |
3760 } | 1057 } |
3761 | 1058 |
3762 void Browser::CreateInstantIfNecessary() { | 1059 Profile* BrowserCommandController::profile() { |
3763 if (is_type_tabbed() && InstantController::IsEnabled(profile()) && | 1060 return browser_->profile(); |
3764 !profile()->IsOffTheRecord()) { | |
3765 instant_.reset(new InstantController(this, InstantController::INSTANT)); | |
3766 instant_unload_handler_.reset(new InstantUnloadHandler(this)); | |
3767 } | |
3768 } | 1061 } |
3769 | 1062 |
3770 int Browser::GetContentRestrictionsForSelectedTab() { | 1063 } // namespace chrome |
3771 int content_restrictions = 0; | |
3772 WebContents* current_tab = GetActiveWebContents(); | |
3773 if (current_tab) { | |
3774 content_restrictions = current_tab->GetContentRestrictions(); | |
3775 NavigationEntry* active_entry = | |
3776 current_tab->GetController().GetActiveEntry(); | |
3777 // See comment in UpdateCommandsForTabState about why we call url(). | |
3778 if (!download_util::IsSavableURL( | |
3779 active_entry ? active_entry->GetURL() : GURL()) | |
3780 || current_tab->ShowingInterstitialPage()) | |
3781 content_restrictions |= content::CONTENT_RESTRICTION_SAVE; | |
3782 if (current_tab->ShowingInterstitialPage()) | |
3783 content_restrictions |= content::CONTENT_RESTRICTION_PRINT; | |
3784 } | |
3785 return content_restrictions; | |
3786 } | |
3787 | |
3788 void Browser::UpdateBookmarkBarState(BookmarkBarStateChangeReason reason) { | |
3789 BookmarkBar::State state; | |
3790 // The bookmark bar is hidden in fullscreen mode, unless on the new tab page. | |
3791 if (browser_defaults::bookmarks_enabled && | |
3792 profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar) && | |
3793 (!window_ || !window_->IsFullscreen())) { | |
3794 state = BookmarkBar::SHOW; | |
3795 } else { | |
3796 TabContents* tab = GetActiveTabContents(); | |
3797 if (tab && tab->bookmark_tab_helper()->ShouldShowBookmarkBar()) | |
3798 state = BookmarkBar::DETACHED; | |
3799 else | |
3800 state = BookmarkBar::HIDDEN; | |
3801 } | |
3802 | |
3803 // Only allow the bookmark bar to be shown in default mode. | |
3804 if (!search_model_->mode().is_default()) | |
3805 state = BookmarkBar::HIDDEN; | |
3806 | |
3807 if (state == bookmark_bar_state_) | |
3808 return; | |
3809 | |
3810 bookmark_bar_state_ = state; | |
3811 | |
3812 if (!window_) | |
3813 return; // This is called from the constructor when window_ is NULL. | |
3814 | |
3815 if (reason == BOOKMARK_BAR_STATE_CHANGE_TAB_SWITCH) { | |
3816 // Don't notify BrowserWindow on a tab switch as at the time this is invoked | |
3817 // BrowserWindow hasn't yet switched tabs. The BrowserWindow implementations | |
3818 // end up querying state once they process the tab switch. | |
3819 return; | |
3820 } | |
3821 | |
3822 BookmarkBar::AnimateChangeType animate_type = | |
3823 (reason == BOOKMARK_BAR_STATE_CHANGE_PREF_CHANGE) ? | |
3824 BookmarkBar::ANIMATE_STATE_CHANGE : | |
3825 BookmarkBar::DONT_ANIMATE_STATE_CHANGE; | |
3826 window_->BookmarkBarStateChanged(animate_type); | |
3827 } | |
3828 | |
3829 bool Browser::MaybeCreateBackgroundContents(int route_id, | |
3830 WebContents* opener_web_contents, | |
3831 const string16& frame_name, | |
3832 const GURL& target_url) { | |
3833 GURL opener_url = opener_web_contents->GetURL(); | |
3834 ExtensionService* extensions_service = profile_->GetExtensionService(); | |
3835 | |
3836 if (!opener_url.is_valid() || | |
3837 frame_name.empty() || | |
3838 !extensions_service || | |
3839 !extensions_service->is_ready()) | |
3840 return false; | |
3841 | |
3842 // Only hosted apps have web extents, so this ensures that only hosted apps | |
3843 // can create BackgroundContents. We don't have to check for background | |
3844 // permission as that is checked in RenderMessageFilter when the CreateWindow | |
3845 // message is processed. | |
3846 const Extension* extension = | |
3847 extensions_service->extensions()->GetHostedAppByURL( | |
3848 ExtensionURLInfo(opener_url)); | |
3849 if (!extension) | |
3850 return false; | |
3851 | |
3852 // No BackgroundContents allowed if BackgroundContentsService doesn't exist. | |
3853 BackgroundContentsService* service = | |
3854 BackgroundContentsServiceFactory::GetForProfile(profile_); | |
3855 if (!service) | |
3856 return false; | |
3857 | |
3858 // Ensure that we're trying to open this from the extension's process. | |
3859 SiteInstance* opener_site_instance = opener_web_contents->GetSiteInstance(); | |
3860 extensions::ProcessMap* process_map = extensions_service->process_map(); | |
3861 if (!opener_site_instance->GetProcess() || | |
3862 !process_map->Contains( | |
3863 extension->id(), opener_site_instance->GetProcess()->GetID())) { | |
3864 return false; | |
3865 } | |
3866 | |
3867 // Only allow a single background contents per app. | |
3868 bool allow_js_access = extension->allow_background_js_access(); | |
3869 BackgroundContents* existing = | |
3870 service->GetAppBackgroundContents(ASCIIToUTF16(extension->id())); | |
3871 if (existing) { | |
3872 // For non-scriptable background contents, ignore the request altogether, | |
3873 // (returning true, so that a regular WebContents isn't created either). | |
3874 if (!allow_js_access) | |
3875 return true; | |
3876 // For scriptable background pages, if one already exists, close it (even | |
3877 // if it was specified in the manifest). | |
3878 DLOG(INFO) << "Closing existing BackgroundContents for " << opener_url; | |
3879 delete existing; | |
3880 } | |
3881 | |
3882 // If script access is not allowed, create the the background contents in a | |
3883 // new SiteInstance, so that a separate process is used. | |
3884 scoped_refptr<content::SiteInstance> site_instance = | |
3885 allow_js_access ? | |
3886 opener_site_instance : | |
3887 content::SiteInstance::Create(opener_web_contents->GetBrowserContext()); | |
3888 | |
3889 // Passed all the checks, so this should be created as a BackgroundContents. | |
3890 BackgroundContents* contents = service->CreateBackgroundContents( | |
3891 site_instance, | |
3892 route_id, | |
3893 profile_, | |
3894 frame_name, | |
3895 ASCIIToUTF16(extension->id())); | |
3896 | |
3897 // When a separate process is used, the original renderer cannot access the | |
3898 // new window later, thus we need to navigate the window now. | |
3899 if (contents && !allow_js_access) { | |
3900 contents->web_contents()->GetController().LoadURL( | |
3901 target_url, | |
3902 content::Referrer(), | |
3903 content::PAGE_TRANSITION_LINK, | |
3904 std::string()); // No extra headers. | |
3905 } | |
3906 | |
3907 return contents != NULL; | |
3908 } | |
OLD | NEW |