blob: 445ad5454f130082887234b57253f4f715fbc1f5 [file] [log] [blame]
[email protected]35d06152011-01-10 22:19:421// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]7b5dc002010-11-16 23:08:105#include "chrome/browser/ui/browser.h"
[email protected]c61db1d2009-02-06 03:39:186
[email protected]aca02cf2010-05-03 18:56:017#if defined(OS_WIN)
8#include <shellapi.h>
9#include <windows.h>
10#endif // OS_WIN
11
[email protected]5dcbc02f2010-01-26 22:32:0612#include <algorithm>
13#include <string>
14
[email protected]b02d0382009-11-30 21:19:5015#include "base/base_paths.h"
[email protected]8a53ee042009-01-21 16:41:3316#include "base/command_line.h"
[email protected]8a53ee042009-01-21 16:41:3317#include "base/logging.h"
[email protected]835d7c82010-10-14 04:38:3818#include "base/metrics/histogram.h"
[email protected]b02d0382009-11-30 21:19:5019#include "base/path_service.h"
[email protected]8a53ee042009-01-21 16:41:3320#include "base/string_util.h"
[email protected]34b99632011-01-01 01:01:0621#include "base/threading/thread.h"
22#include "base/threading/thread_restrictions.h"
[email protected]7f070d42011-03-09 20:25:3223#include "base/time.h"
[email protected]6524385ef2010-08-18 06:34:1324#include "base/utf_string_conversions.h"
[email protected]1a3aba82010-11-08 23:52:5425#include "chrome/app/chrome_command_ids.h"
[email protected]cf28ec52010-04-09 22:56:3426#include "chrome/browser/autofill/autofill_manager.h"
[email protected]2c4fb7b2011-04-02 06:33:2927#include "chrome/browser/background_contents_service.h"
[email protected]a9afddb2009-02-12 17:49:4228#include "chrome/browser/bookmarks/bookmark_model.h"
[email protected]b3ac5c82009-10-08 20:56:5429#include "chrome/browser/bookmarks/bookmark_utils.h"
[email protected]5c238752009-06-13 10:29:0730#include "chrome/browser/browser_process.h"
[email protected]c61db1d2009-02-06 03:39:1831#include "chrome/browser/browser_shutdown.h"
[email protected]1518b0d2010-04-02 18:38:5332#include "chrome/browser/browser_url_handler.h"
[email protected]40d59ce52009-03-06 23:20:1433#include "chrome/browser/character_encoding.h"
[email protected]40ecc902009-03-16 13:42:4734#include "chrome/browser/debugger/devtools_manager.h"
[email protected]2a8a98122010-07-16 11:58:4835#include "chrome/browser/debugger/devtools_toggle_action.h"
[email protected]8e48e982009-12-25 11:22:4636#include "chrome/browser/debugger/devtools_window.h"
[email protected]6c69796d2010-07-16 21:41:1637#include "chrome/browser/download/download_item.h"
[email protected]59560e0b2009-06-04 03:30:2238#include "chrome/browser/download/download_item_model.h"
[email protected]69444cc2009-04-09 20:40:0639#include "chrome/browser/download/download_manager.h"
[email protected]59560e0b2009-06-04 03:30:2240#include "chrome/browser/download/download_shelf.h"
41#include "chrome/browser/download/download_started_animation.h"
[email protected]3ea60632011-04-08 18:25:4242#include "chrome/browser/download/save_package.h"
[email protected]bb461532010-11-26 21:50:2343#include "chrome/browser/extensions/crx_installer.h"
[email protected]9fd542df2009-09-30 07:32:0144#include "chrome/browser/extensions/extension_browser_event_router.h"
[email protected]0c6da502009-08-14 22:32:3945#include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
[email protected]6d7a6042010-08-12 20:12:4246#include "chrome/browser/extensions/extension_host.h"
[email protected]10abd192010-09-30 02:03:4947#include "chrome/browser/extensions/extension_prefs.h"
[email protected]eaa7dd182010-12-14 11:09:0048#include "chrome/browser/extensions/extension_service.h"
[email protected]36fb2c7c2011-04-04 15:49:0849#include "chrome/browser/extensions/extension_tab_helper.h"
[email protected]b17d41c2011-02-17 22:09:5950#include "chrome/browser/extensions/extension_tabs_module.h"
[email protected]820735792010-07-29 23:40:0151#include "chrome/browser/first_run/first_run.h"
[email protected]f7578f52010-08-30 22:22:4952#include "chrome/browser/google/google_url_tracker.h"
53#include "chrome/browser/google/google_util.h"
[email protected]6b723f82010-10-05 20:14:2754#include "chrome/browser/instant/instant_controller.h"
[email protected]5aab5e22010-12-08 22:13:2955#include "chrome/browser/instant/instant_unload_handler.h"
[email protected]d938aed92009-01-22 19:49:3356#include "chrome/browser/metrics/user_metrics.h"
[email protected]90f39902009-10-03 04:25:3757#include "chrome/browser/net/browser_url_util.h"
[email protected]a239c3f2009-02-17 22:13:1958#include "chrome/browser/net/url_fixer_upper.h"
[email protected]2c4fb7b2011-04-02 06:33:2959#include "chrome/browser/notifications/notification_ui_manager.h"
[email protected]14a000d2010-04-29 21:44:2460#include "chrome/browser/platform_util.h"
[email protected]37858e52010-08-26 00:22:0261#include "chrome/browser/prefs/pref_service.h"
[email protected]02337592010-09-27 18:38:2562#include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
[email protected]de0ca762011-03-24 03:28:1463#include "chrome/browser/printing/print_preview_tab_controller.h"
[email protected]8ecad5e2010-12-02 21:18:3364#include "chrome/browser/profiles/profile.h"
[email protected]85e921fb82009-02-11 23:19:4465#include "chrome/browser/sessions/session_service.h"
[email protected]c61db1d2009-02-06 03:39:1866#include "chrome/browser/sessions/session_types.h"
[email protected]92926d92010-09-02 18:35:0667#include "chrome/browser/sessions/tab_restore_service.h"
[email protected]066629f2009-10-17 00:28:1368#include "chrome/browser/sync/profile_sync_service.h"
[email protected]40f047972009-11-25 03:54:4069#include "chrome/browser/sync/sync_ui_util.h"
[email protected]0b4d3382010-07-14 16:13:0470#include "chrome/browser/tab_closeable_state_watcher.h"
[email protected]2c4fb7b2011-04-02 06:33:2971#include "chrome/browser/tab_contents/background_contents.h"
[email protected]7cceebac2011-03-03 00:32:2172#include "chrome/browser/tab_contents/simple_alert_infobar_delegate.h"
[email protected]07d490bc2011-03-07 17:05:2673#include "chrome/browser/tabs/tab_finder.h"
[email protected]c848d3d92010-09-16 21:57:4574#include "chrome/browser/tabs/tab_strip_model.h"
[email protected]6768ac02011-04-06 17:41:0475#include "chrome/browser/ui/browser_list.h"
[email protected]fb7da4132011-03-15 15:51:0076#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
[email protected]00070c732011-04-09 15:31:3377#include "chrome/browser/ui/browser_window.h"
[email protected]3ea60632011-04-08 18:25:4278#include "chrome/browser/ui/download/download_tab_helper.h"
[email protected]45300ad42010-12-02 15:51:1479#include "chrome/browser/ui/find_bar/find_bar.h"
80#include "chrome/browser/ui/find_bar/find_bar_controller.h"
[email protected]c90c6ca2011-02-16 20:11:3881#include "chrome/browser/ui/find_bar/find_tab_helper.h"
[email protected]6a3ec2312010-12-02 19:30:1982#include "chrome/browser/ui/omnibox/location_bar.h"
83#include "chrome/browser/ui/options/options_window.h"
[email protected]fe90ca8e2011-04-08 20:40:4384#include "chrome/browser/ui/panels/panel.h"
85#include "chrome/browser/ui/panels/panel_manager.h"
[email protected]9219d262011-02-15 21:05:1286#include "chrome/browser/ui/search_engines/search_engine_tab_helper.h"
[email protected]6a3ec2312010-12-02 19:30:1987#include "chrome/browser/ui/status_bubble.h"
88#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
[email protected]9a800652010-12-02 17:08:4489#include "chrome/browser/ui/tabs/dock_info.h"
[email protected]6a3ec2312010-12-02 19:30:1990#include "chrome/browser/ui/tabs/tab_menu_model.h"
[email protected]f847e6082011-03-24 00:08:2691#include "chrome/browser/ui/web_applications/web_app_ui.h"
[email protected]265a1492011-02-27 05:58:0792#include "chrome/browser/ui/webui/bug_report_ui.h"
93#include "chrome/browser/ui/webui/filebrowse_ui.h"
[email protected]5c557f372011-02-26 15:09:2094#include "chrome/browser/ui/webui/options/content_settings_handler.h"
[email protected]9a800652010-12-02 17:08:4495#include "chrome/browser/ui/window_sizer.h"
[email protected]b1b73942010-05-26 20:11:5496#include "chrome/browser/upgrade_detector.h"
[email protected]86b54012009-11-19 09:18:5097#include "chrome/browser/web_applications/web_app.h"
[email protected]d938aed92009-01-22 19:49:3398#include "chrome/common/chrome_constants.h"
99#include "chrome/common/chrome_switches.h"
[email protected]9e823662010-10-13 23:36:00100#include "chrome/common/content_restriction.h"
[email protected]5b1a0e22009-05-26 19:00:58101#include "chrome/common/extensions/extension.h"
[email protected]46fd1ea42011-02-16 15:59:33102#include "chrome/common/extensions/extension_constants.h"
[email protected]8a53ee042009-01-21 16:41:33103#include "chrome/common/pref_names.h"
[email protected]7664ab32011-02-01 23:35:25104#include "chrome/common/profiling.h"
[email protected]b689fce72009-03-17 22:45:34105#include "chrome/common/url_constants.h"
[email protected]bb461532010-11-26 21:50:23106#include "chrome/common/web_apps.h"
[email protected]b6021d32011-02-26 01:25:54107#include "content/browser/host_zoom_map.h"
[email protected]a01efd22011-03-01 00:38:32108#include "content/browser/renderer_host/render_view_host.h"
109#include "content/browser/site_instance.h"
[email protected]a01efd22011-03-01 00:38:32110#include "content/browser/tab_contents/interstitial_page.h"
111#include "content/browser/tab_contents/navigation_controller.h"
112#include "content/browser/tab_contents/navigation_entry.h"
113#include "content/browser/tab_contents/tab_contents.h"
114#include "content/browser/tab_contents/tab_contents_view.h"
[email protected]7f070d42011-03-09 20:25:32115#include "content/common/notification_service.h"
[email protected]4dd57932011-03-17 06:06:12116#include "content/common/page_transition_types.h"
[email protected]a3e18c42009-03-04 23:36:05117#include "grit/chromium_strings.h"
118#include "grit/generated_resources.h"
119#include "grit/locale_settings.h"
[email protected]8a53ee042009-01-21 16:41:33120#include "net/base/cookie_monster.h"
[email protected]8a53ee042009-01-21 16:41:33121#include "net/base/net_util.h"
122#include "net/base/registry_controlled_domain.h"
[email protected]cb370a0632010-01-30 08:24:12123#include "net/base/static_cookie_policy.h"
[email protected]8a53ee042009-01-21 16:41:33124#include "net/url_request/url_request_context.h"
[email protected]f67678062011-01-07 17:33:39125#include "ui/base/animation/animation.h"
[email protected]c051a1b2011-01-21 23:30:17126#include "ui/base/l10n/l10n_util.h"
[email protected]08397d52011-02-05 01:53:38127#include "ui/gfx/point.h"
[email protected]1436beff2010-12-16 19:47:04128#include "webkit/glue/webkit_glue.h"
[email protected]d938aed92009-01-22 19:49:33129#include "webkit/glue/window_open_disposition.h"
[email protected]8a53ee042009-01-21 16:41:33130
131#if defined(OS_WIN)
[email protected]b99603c2010-12-30 22:13:32132#include "app/win/shell.h"
[email protected]36d5e5592010-11-15 20:45:59133#include "chrome/browser/autofill/autofill_ie_toolbar_import_win.h"
[email protected]37936ee2008-09-14 01:09:50134#include "chrome/browser/download/save_package.h"
[email protected]12f520c2010-01-06 18:11:15135#include "chrome/browser/shell_integration.h"
[email protected]b17d41c2011-02-17 22:09:59136#include "chrome/browser/ssl/ssl_error_info.h"
[email protected]a5d1e1e2010-09-23 19:34:12137#include "chrome/browser/task_manager/task_manager.h"
[email protected]6a3ec2312010-12-02 19:30:19138#include "chrome/browser/ui/view_ids.h"
139#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
[email protected]8a53ee042009-01-21 16:41:33140#endif // OS_WIN
[email protected]e1acf6f2008-10-27 20:43:33141
[email protected]6a4f5af22009-09-23 22:43:00142#if defined(OS_MACOSX)
[email protected]7d791652010-12-01 16:34:49143#include "chrome/browser/ui/cocoa/find_pasteboard.h"
[email protected]6a4f5af22009-09-23 22:43:00144#endif
145
[email protected]b7969202010-05-14 21:29:26146#if defined(OS_CHROMEOS)
[email protected]6a2a61d2010-11-22 03:25:35147#include "chrome/browser/chromeos/boot_times_loader.h"
[email protected]b7969202010-05-14 21:29:26148#endif
149
[email protected]8a53ee042009-01-21 16:41:33150using base::TimeDelta;
initial.commit09911bf2008-07-26 23:55:29151
[email protected]36b6dcb2008-11-12 01:19:57152///////////////////////////////////////////////////////////////////////////////
initial.commit09911bf2008-07-26 23:55:29153
[email protected]505323e22009-01-24 02:47:58154namespace {
155
[email protected]91a79232010-11-10 18:15:08156// The URL to be loaded to display Help.
[email protected]8332c162011-01-26 12:01:54157const char kHelpContentUrl[] =
[email protected]91a79232010-11-10 18:15:08158#if defined(OS_CHROMEOS)
[email protected]8332c162011-01-26 12:01:54159 #if defined(OFFICIAL_BUILD)
160 "chrome-extension://honijodknafkokifofgiaalefdiedpko/main.html";
161 #else
162 "http://www.google.com/support/chromeos/";
163 #endif
[email protected]91a79232010-11-10 18:15:08164#else
[email protected]91a79232010-11-10 18:15:08165 "http://www.google.com/support/chrome/";
166#endif
167
168// The URL to be opened when the Help link on the Autofill dialog is clicked.
169const char kAutofillHelpUrl[] =
170#if defined(OS_CHROMEOS)
171 "http://www.google.com/support/chromeos/bin/answer.py?answer=142893";
172#else
173 "http://www.google.com/support/chrome/bin/answer.py?answer=142893";
174#endif
175
176// The URL to be loaded to display the "Report a broken page" form.
177const char kBrokenPageUrl[] =
178 "http://www.google.com/support/chrome/bin/request.py?contact_type="
179 "broken_website&format=inproduct&p.page_title=$1&p.page_url=$2";
180
181// The URL for the privacy dashboard.
182const char kPrivacyDashboardUrl[] = "https://www.google.com/dashboard";
183
184// How long we wait before updating the browser chrome while loading a page.
185const int kUIUpdateCoalescingTimeMS = 200;
186
187const char kHashMark[] = "#";
188
[email protected]57b839a2010-10-04 22:49:45189#if defined(OS_CHROMEOS)
190// If a popup window is bigger than this fraction of the screen on chrome os,
191// turn it into a tab
192const float kPopupMaxWidthFactor = 0.5;
193const float kPopupMaxHeightFactor = 0.6;
194#endif
195
[email protected]505323e22009-01-24 02:47:58196} // namespace
197
[email protected]e838eaf2010-10-13 18:53:33198extern bool g_log_bug53991;
199
[email protected]36b6dcb2008-11-12 01:19:57200///////////////////////////////////////////////////////////////////////////////
201// Browser, Constructors, Creation, Showing:
initial.commit09911bf2008-07-26 23:55:29202
[email protected]299dabd2008-11-19 02:27:16203Browser::Browser(Type type, Profile* profile)
[email protected]15952e462008-11-14 00:29:05204 : type_(type),
205 profile_(profile),
[email protected]f3e99e32008-07-30 04:48:39206 window_(NULL),
[email protected]ecc523f62010-09-28 22:45:40207 ALLOW_THIS_IN_INITIALIZER_LIST(
208 tab_handler_(TabHandler::CreateTabHandler(this))),
[email protected]1fc025202009-01-20 23:03:14209 command_updater_(this),
initial.commit09911bf2008-07-26 23:55:29210 toolbar_model_(this),
[email protected]15952e462008-11-14 00:29:05211 chrome_updater_factory_(this),
212 is_attempting_to_close_browser_(false),
[email protected]69444cc2009-04-09 20:40:06213 cancel_download_confirmation_state_(NOT_PROMPTED),
[email protected]2e716622009-03-09 21:11:01214 maximized_state_(MAXIMIZED_STATE_DEFAULT),
[email protected]867125a02009-12-10 06:01:48215 method_factory_(this),
216 block_command_execution_(false),
217 last_blocked_command_id_(-1),
[email protected]eabfdae92009-12-11 06:13:51218 last_blocked_command_disposition_(CURRENT_TAB),
[email protected]fb7da4132011-03-15 15:51:00219 pending_web_app_action_(NONE),
220 ALLOW_THIS_IN_INITIALIZER_LIST(
221 tab_restore_service_delegate_(
222 new BrowserTabRestoreServiceDelegate(this))) {
[email protected]0cb94102009-05-22 19:51:21223 registrar_.Add(this, NotificationType::SSL_VISIBLE_STATE_CHANGED,
224 NotificationService::AllSources());
[email protected]0c6da502009-08-14 22:32:39225 registrar_.Add(this, NotificationType::EXTENSION_UPDATE_DISABLED,
226 NotificationService::AllSources());
[email protected]ad0c2e1b2010-01-30 00:00:10227 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
228 NotificationService::AllSources());
[email protected]0cb94102009-05-22 19:51:21229 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
230 NotificationService::AllSources());
[email protected]0dfe05c2011-02-23 23:03:36231 registrar_.Add(this, NotificationType::EXTENSION_UNINSTALLED,
232 NotificationService::AllSources());
[email protected]a4ed6282009-12-14 20:51:16233 registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED,
[email protected]371ed7a2009-08-25 15:22:46234 NotificationService::AllSources());
[email protected]e001d412009-06-26 20:53:25235 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
236 NotificationService::AllSources());
[email protected]e587a45f2009-10-30 22:34:41237 registrar_.Add(this, NotificationType::PROFILE_ERROR,
[email protected]0e30ef72009-09-05 00:05:08238 NotificationService::AllSources());
initial.commit09911bf2008-07-26 23:55:29239
[email protected]91e1bd82009-09-03 22:04:40240 // Need to know when to alert the user of theme install delay.
241 registrar_.Add(this, NotificationType::EXTENSION_READY_FOR_INSTALL,
242 NotificationService::AllSources());
243
[email protected]6e6f6cb2011-01-27 13:26:55244 // NOTE: These prefs all need to be explicitly destroyed in the destructor
245 // or you'll get a nasty surprise when you run the incognito tests.
[email protected]9e823662010-10-13 23:36:00246 PrefService* local_state = g_browser_process->local_state();
247 if (local_state)
248 printing_enabled_.Init(prefs::kPrintingEnabled, local_state, this);
[email protected]543432ee2010-10-22 16:32:13249 dev_tools_disabled_.Init(prefs::kDevToolsDisabled,
250 profile_->GetPrefs(), this);
[email protected]6e6f6cb2011-01-27 13:26:55251 incognito_mode_allowed_.Init(prefs::kIncognitoEnabled,
252 profile_->GetPrefs(), this);
[email protected]9e823662010-10-13 23:36:00253
initial.commit09911bf2008-07-26 23:55:29254 InitCommandState();
255 BrowserList::AddBrowser(this);
256
257 encoding_auto_detect_.Init(prefs::kWebKitUsesUniversalDetector,
258 profile_->GetPrefs(), NULL);
[email protected]b9c505b2010-04-30 15:05:10259 use_vertical_tabs_.Init(prefs::kUseVerticalTabs, profile_->GetPrefs(), this);
[email protected]73de26a2010-10-17 03:23:25260 instant_enabled_.Init(prefs::kInstantEnabled, profile_->GetPrefs(), this);
[email protected]b9c505b2010-04-30 15:05:10261 if (!TabMenuModel::AreVerticalTabsEnabled()) {
262 // If vertical tabs aren't enabled, explicitly turn them off. Otherwise we
263 // might show vertical tabs but not show an option to turn them off.
264 use_vertical_tabs_.SetValue(false);
265 }
[email protected]b3344872010-05-03 15:52:29266 UpdateTabStripModelInsertionPolicy();
[email protected]281918912010-05-27 22:05:13267
268 tab_restore_service_ = profile->GetTabRestoreService();
269 if (tab_restore_service_) {
270 tab_restore_service_->AddObserver(this);
271 TabRestoreServiceChanged(tab_restore_service_);
272 }
[email protected]d3b98c82010-07-14 07:45:59273
274 if (profile_->GetProfileSyncService())
275 profile_->GetProfileSyncService()->AddObserver(this);
[email protected]03bb953d2010-09-14 21:38:30276
[email protected]2031cf9d2010-10-12 05:05:37277 CreateInstantIfNecessary();
[email protected]07d490bc2011-03-07 17:05:26278
279 // Make sure TabFinder has been created. This does nothing if TabFinder is
280 // not enabled.
281 TabFinder::GetInstance();
initial.commit09911bf2008-07-26 23:55:29282}
283
284Browser::~Browser() {
[email protected]5044da82010-10-27 01:09:16285 VLOG_IF(1, g_log_bug53991) << "~Browser: " << profile_->IsOffTheRecord()
286 << "; stillActive="
287 << BrowserList::IsOffTheRecordSessionActive();
[email protected]e838eaf2010-10-13 18:53:33288
[email protected]d3b98c82010-07-14 07:45:59289 if (profile_->GetProfileSyncService())
290 profile_->GetProfileSyncService()->RemoveObserver(this);
291
initial.commit09911bf2008-07-26 23:55:29292 BrowserList::RemoveBrowser(this);
293
[email protected]fbc947b2009-06-19 13:28:24294#if defined(OS_WIN) || defined(OS_LINUX)
initial.commit09911bf2008-07-26 23:55:29295 if (!BrowserList::HasBrowserWithProfile(profile_)) {
296 // We're the last browser window with this profile. We need to nuke the
297 // TabRestoreService, which will start the shutdown of the
298 // NavigationControllers and allow for proper shutdown. If we don't do this
299 // chrome won't shutdown cleanly, and may end up crashing when some
300 // thread tries to use the IO thread (or another thread) that is no longer
301 // valid.
[email protected]fbc947b2009-06-19 13:28:24302 // This isn't a valid assumption for Mac OS, as it stays running after
303 // the last browser has closed. The Mac equivalent is in its app
304 // controller.
initial.commit09911bf2008-07-26 23:55:29305 profile_->ResetTabRestoreService();
306 }
[email protected]fbc947b2009-06-19 13:28:24307#endif
initial.commit09911bf2008-07-26 23:55:29308
309 SessionService* session_service = profile_->GetSessionService();
310 if (session_service)
311 session_service->WindowClosed(session_id_);
312
[email protected]d8375fd2008-11-25 22:45:39313 TabRestoreService* tab_restore_service = profile()->GetTabRestoreService();
314 if (tab_restore_service)
[email protected]fb7da4132011-03-15 15:51:00315 tab_restore_service->BrowserClosed(tab_restore_service_delegate());
[email protected]d8375fd2008-11-25 22:45:39316
[email protected]9a8c4022011-01-25 14:25:33317 encoding_auto_detect_.Destroy();
318 printing_enabled_.Destroy();
319 dev_tools_disabled_.Destroy();
[email protected]6e6f6cb2011-01-27 13:26:55320 incognito_mode_allowed_.Destroy();
[email protected]9a8c4022011-01-25 14:25:33321 instant_enabled_.Destroy();
322 use_vertical_tabs_.Destroy();
323
initial.commit09911bf2008-07-26 23:55:29324 if (profile_->IsOffTheRecord() &&
325 !BrowserList::IsOffTheRecordSessionActive()) {
[email protected]0d1add32011-04-07 00:06:50326 // An incognito profile is no longer needed, this indirectly
[email protected]860f55492009-03-27 19:50:59327 // frees its cache and cookies.
328 profile_->GetOriginalProfile()->DestroyOffTheRecordProfile();
initial.commit09911bf2008-07-26 23:55:29329 }
330
331 // There may be pending file dialogs, we need to tell them that we've gone
332 // away so they don't try and call back to us.
333 if (select_file_dialog_.get())
334 select_file_dialog_->ListenerDestroyed();
[email protected]281918912010-05-27 22:05:13335
336 TabRestoreServiceDestroyed(tab_restore_service_);
initial.commit09911bf2008-07-26 23:55:29337}
338
[email protected]15952e462008-11-14 00:29:05339// static
340Browser* Browser::Create(Profile* profile) {
[email protected]299dabd2008-11-19 02:27:16341 Browser* browser = new Browser(TYPE_NORMAL, profile);
[email protected]9800de5e2011-03-11 18:19:49342 browser->InitBrowserWindow();
[email protected]15952e462008-11-14 00:29:05343 return browser;
344}
[email protected]6104acf2008-11-11 22:27:34345
[email protected]15952e462008-11-14 00:29:05346// static
[email protected]1b74d2122010-10-06 16:49:16347Browser* Browser::CreateForPopup(Type type,
348 Profile* profile,
349 TabContents* new_contents,
350 const gfx::Rect& initial_bounds) {
351 DCHECK(type & TYPE_POPUP);
352 Browser* browser = new Browser(type, profile);
353 browser->set_override_bounds(initial_bounds);
[email protected]9800de5e2011-03-11 18:19:49354 browser->InitBrowserWindow();
[email protected]3c9e1872010-11-18 16:17:49355 TabContentsWrapper* wrapper = new TabContentsWrapper(new_contents);
356 browser->tabstrip_model()->AppendTabContents(wrapper, true);
[email protected]9ee17e8c2010-08-10 19:17:31357 return browser;
358}
359
360// static
361Browser* Browser::CreateForType(Type type, Profile* profile) {
362 Browser* browser = new Browser(type, profile);
[email protected]9800de5e2011-03-11 18:19:49363 browser->InitBrowserWindow();
[email protected]15952e462008-11-14 00:29:05364 return browser;
365}
366
367// static
[email protected]57ecc4b2010-08-11 03:02:51368Browser* Browser::CreateForApp(const std::string& app_name,
[email protected]94ce7252010-12-20 21:46:33369 const gfx::Size& window_size,
[email protected]f2989012010-02-04 16:08:29370 Profile* profile,
371 bool is_panel) {
[email protected]f075fe0a22010-04-26 04:06:43372 Browser::Type type = TYPE_APP;
373
[email protected]61a57ce2010-09-24 16:33:03374 if (is_panel) {
375 // TYPE_APP_PANEL is the logical choice. However, the panel UI
376 // is not fully implemented. See crbug/55943.
377 type = TYPE_APP_POPUP;
[email protected]5530ac652010-09-25 05:35:49378 }
[email protected]f075fe0a22010-04-26 04:06:43379
380 Browser* browser = new Browser(type, profile);
[email protected]15952e462008-11-14 00:29:05381 browser->app_name_ = app_name;
[email protected]605cfad2010-06-22 20:49:35382
[email protected]94ce7252010-12-20 21:46:33383 if (!window_size.IsEmpty()) {
384 gfx::Rect initial_pos(window_size);
385 browser->set_override_bounds(initial_pos);
[email protected]fbf3da12010-06-25 17:29:58386 }
[email protected]605cfad2010-06-22 20:49:35387
[email protected]9800de5e2011-03-11 18:19:49388 browser->InitBrowserWindow();
[email protected]605cfad2010-06-22 20:49:35389
[email protected]15952e462008-11-14 00:29:05390 return browser;
391}
392
[email protected]8e48e982009-12-25 11:22:46393// static
[email protected]fe90ca8e2011-04-08 20:40:43394Browser* Browser::CreateForPanel(const std::string& app_name,
395 const gfx::Size& window_size,
396 Profile* profile) {
397 // TODO(jianli): For now we just use TYPE_APP_PANEL to stand for the panel
398 // this is created from the extension when the specific command line flag
399 // is set.
400 Browser::Type type = TYPE_APP_PANEL;
401 Browser* browser = new Browser(type, profile);
402 browser->app_name_ = app_name;
403
404 if (!window_size.IsEmpty()) {
405 gfx::Rect initial_pos(window_size);
406 browser->set_override_bounds(initial_pos);
407 }
408
409 browser->window_ = PanelManager::GetInstance()->Create(browser);
410 browser->InitBrowserWindow();
411
412 return browser;
413}
414
415// static
[email protected]8e48e982009-12-25 11:22:46416Browser* Browser::CreateForDevTools(Profile* profile) {
417 Browser* browser = new Browser(TYPE_DEVTOOLS, profile);
418 browser->app_name_ = DevToolsWindow::kDevToolsApp;
[email protected]9800de5e2011-03-11 18:19:49419 browser->InitBrowserWindow();
[email protected]8e48e982009-12-25 11:22:46420 return browser;
421}
422
[email protected]9800de5e2011-03-11 18:19:49423void Browser::InitBrowserWindow() {
[email protected]15952e462008-11-14 00:29:05424 DCHECK(!window_);
[email protected]9c45b7182009-08-04 16:44:43425
[email protected]9800de5e2011-03-11 18:19:49426 window_ = CreateBrowserWindow();
[email protected]15952e462008-11-14 00:29:05427
[email protected]80cf3562009-11-17 08:17:24428#if defined(OS_WIN)
[email protected]45446a52010-11-04 17:41:00429 {
430 // TODO: This might hit the disk
431 // http://code.google.com/p/chromium/issues/detail?id=61638
432 base::ThreadRestrictions::ScopedAllowIO allow_io;
433
434 // Set the app user model id for this application to that of the application
435 // name. See http://crbug.com/7028.
[email protected]b99603c2010-12-30 22:13:32436 app::win::SetAppIdForWindow(
[email protected]45446a52010-11-04 17:41:00437 type_ & TYPE_APP ?
438 ShellIntegration::GetAppId(UTF8ToWide(app_name_), profile_->GetPath()) :
439 ShellIntegration::GetChromiumAppId(profile_->GetPath()),
440 window()->GetNativeHandle());
441 }
[email protected]80cf3562009-11-17 08:17:24442#endif
443
[email protected]14d8c66e2009-09-22 00:32:52444 NotificationService::current()->Notify(
445 NotificationType::BROWSER_WINDOW_READY,
446 Source<Browser>(this),
447 NotificationService::NoDetails());
448
[email protected]15952e462008-11-14 00:29:05449 // Show the First Run information bubble if we've been told to.
450 PrefService* local_state = g_browser_process->local_state();
[email protected]be3877f2009-01-14 15:51:10451 if (!local_state)
452 return;
[email protected]da6ce5602009-12-07 23:09:32453 if (local_state->FindPreference(prefs::kShouldShowFirstRunBubble) &&
[email protected]15952e462008-11-14 00:29:05454 local_state->GetBoolean(prefs::kShouldShowFirstRunBubble)) {
[email protected]450028dd2010-08-28 00:24:50455 FirstRun::BubbleType bubble_type = FirstRun::LARGE_BUBBLE;
[email protected]adfe1882010-04-13 23:01:07456 if (local_state->
[email protected]da6ce5602009-12-07 23:09:32457 FindPreference(prefs::kShouldUseOEMFirstRunBubble) &&
[email protected]adfe1882010-04-13 23:01:07458 local_state->GetBoolean(prefs::kShouldUseOEMFirstRunBubble)) {
[email protected]450028dd2010-08-28 00:24:50459 bubble_type = FirstRun::OEM_BUBBLE;
[email protected]adfe1882010-04-13 23:01:07460 } else if (local_state->
461 FindPreference(prefs::kShouldUseMinimalFirstRunBubble) &&
462 local_state->GetBoolean(prefs::kShouldUseMinimalFirstRunBubble)) {
[email protected]450028dd2010-08-28 00:24:50463 bubble_type = FirstRun::MINIMAL_BUBBLE;
[email protected]adfe1882010-04-13 23:01:07464 }
[email protected]15952e462008-11-14 00:29:05465 // Reset the preference so we don't show the bubble for subsequent windows.
466 local_state->ClearPref(prefs::kShouldShowFirstRunBubble);
[email protected]adfe1882010-04-13 23:01:07467 window_->GetLocationBar()->ShowFirstRunBubble(bubble_type);
initial.commit09911bf2008-07-26 23:55:29468 }
[email protected]f69c8852010-10-12 02:36:46469 if (local_state->FindPreference(
[email protected]663bd9e2011-03-21 01:07:01470 prefs::kAutofillPersonalDataManagerFirstRun) &&
471 local_state->GetBoolean(prefs::kAutofillPersonalDataManagerFirstRun)) {
[email protected]f69c8852010-10-12 02:36:46472 // Notify PDM that this is a first run.
473#if defined(OS_WIN)
474 ImportAutofillDataWin(profile_->GetPersonalDataManager());
475#endif // defined(OS_WIN)
476 // Reset the preference so we don't call it again for subsequent windows.
[email protected]663bd9e2011-03-21 01:07:01477 local_state->ClearPref(prefs::kAutofillPersonalDataManagerFirstRun);
[email protected]f69c8852010-10-12 02:36:46478 }
initial.commit09911bf2008-07-26 23:55:29479}
480
[email protected]36b6dcb2008-11-12 01:19:57481///////////////////////////////////////////////////////////////////////////////
[email protected]5c238752009-06-13 10:29:07482// Getters & Setters
483
484const std::vector<std::wstring>& Browser::user_data_dir_profiles() const {
485 return g_browser_process->user_data_dir_profiles();
486}
487
488void Browser::set_user_data_dir_profiles(
489 const std::vector<std::wstring>& profiles) {
490 g_browser_process->user_data_dir_profiles() = profiles;
491}
492
[email protected]b77cb302009-10-29 04:09:17493FindBarController* Browser::GetFindBarController() {
494 if (!find_bar_controller_.get()) {
495 FindBar* find_bar = BrowserWindow::CreateFindBar(this);
496 find_bar_controller_.reset(new FindBarController(find_bar));
497 find_bar->SetFindBarController(find_bar_controller_.get());
[email protected]9c318862011-02-01 22:27:24498 find_bar_controller_->ChangeTabContents(GetSelectedTabContentsWrapper());
[email protected]b77cb302009-10-29 04:09:17499 find_bar_controller_->find_bar()->MoveWindowIfNecessary(gfx::Rect(), true);
500 }
501 return find_bar_controller_.get();
502}
503
[email protected]24db8a072009-10-29 20:35:37504bool Browser::HasFindBarController() const {
505 return find_bar_controller_.get() != NULL;
506}
507
[email protected]5c238752009-06-13 10:29:07508///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:57509// Browser, Creation Helpers:
510
511// static
[email protected]15952e462008-11-14 00:29:05512void Browser::OpenEmptyWindow(Profile* profile) {
513 Browser* browser = Browser::Create(profile);
[email protected]36b6dcb2008-11-12 01:19:57514 browser->AddBlankTab(true);
[email protected]15952e462008-11-14 00:29:05515 browser->window()->Show();
initial.commit09911bf2008-07-26 23:55:29516}
517
[email protected]36b6dcb2008-11-12 01:19:57518// static
[email protected]fbc947b2009-06-19 13:28:24519void Browser::OpenWindowWithRestoredTabs(Profile* profile) {
520 TabRestoreService* service = profile->GetTabRestoreService();
521 if (service)
522 service->RestoreMostRecentEntry(NULL);
523}
524
525// static
[email protected]36b6dcb2008-11-12 01:19:57526void Browser::OpenURLOffTheRecord(Profile* profile, const GURL& url) {
[email protected]cecc93a2010-10-05 15:58:55527 Browser* browser = GetOrCreateTabbedBrowser(
528 profile->GetOffTheRecordProfile());
529 browser->AddSelectedTabWithURL(url, PageTransition::LINK);
[email protected]15952e462008-11-14 00:29:05530 browser->window()->Show();
[email protected]2baf83d2008-07-30 05:58:17531}
532
[email protected]36b6dcb2008-11-12 01:19:57533// static
[email protected]d83a5602010-09-16 00:22:48534TabContents* Browser::OpenApplication(
535 Profile* profile,
[email protected]9adb9692010-10-29 23:14:02536 const Extension* extension,
[email protected]24bf2022010-10-14 16:34:39537 extension_misc::LaunchContainer container,
538 TabContents* existing_tab) {
[email protected]56869382010-05-11 21:45:46539 TabContents* tab = NULL;
[email protected]4033bd92011-03-08 19:27:04540 ExtensionPrefs* prefs = profile->GetExtensionService()->extension_prefs();
541 prefs->SetActiveBit(extension->id(), true);
[email protected]e3acb7c2010-05-11 19:23:37542
[email protected]9b217652010-10-08 22:04:23543 UMA_HISTOGRAM_ENUMERATION("Extensions.AppLaunchContainer", container, 100);
544
[email protected]bbadaa782010-04-28 21:21:53545 switch (container) {
[email protected]d83a5602010-09-16 00:22:48546 case extension_misc::LAUNCH_WINDOW:
547 case extension_misc::LAUNCH_PANEL:
[email protected]bbadaa782010-04-28 21:21:53548 tab = Browser::OpenApplicationWindow(profile, extension, container,
[email protected]0e71e4152010-12-07 04:16:26549 GURL(), NULL);
[email protected]c28071ad2010-03-12 17:28:56550 break;
[email protected]d83a5602010-09-16 00:22:48551 case extension_misc::LAUNCH_TAB: {
[email protected]24bf2022010-10-14 16:34:39552 tab = Browser::OpenApplicationTab(profile, extension, existing_tab);
[email protected]c28071ad2010-03-12 17:28:56553 break;
554 }
555 default:
556 NOTREACHED();
[email protected]bbadaa782010-04-28 21:21:53557 break;
[email protected]c28071ad2010-03-12 17:28:56558 }
[email protected]bbadaa782010-04-28 21:21:53559 return tab;
[email protected]c28071ad2010-03-12 17:28:56560}
561
562// static
[email protected]bbadaa782010-04-28 21:21:53563TabContents* Browser::OpenApplicationWindow(
564 Profile* profile,
[email protected]9adb9692010-10-29 23:14:02565 const Extension* extension,
[email protected]d83a5602010-09-16 00:22:48566 extension_misc::LaunchContainer container,
[email protected]0e71e4152010-12-07 04:16:26567 const GURL& url_input,
568 Browser** app_browser) {
[email protected]f381dfa2010-04-29 04:41:37569 GURL url;
570 if (!url_input.is_empty()) {
571 if (extension)
572 DCHECK(extension->web_extent().ContainsURL(url_input));
573 url = url_input;
574 } else {
[email protected]ae5909e2011-02-23 14:34:18575 DCHECK(extension); // Empty url and no extension. Nothing to open.
[email protected]f381dfa2010-04-29 04:41:37576 url = extension->GetFullLaunchURL();
577 }
578
[email protected]2f1c09d2011-01-14 14:58:14579 std::string app_name;
580 if (extension)
581 app_name =
582 web_app::GenerateApplicationNameFromExtensionId(extension->id());
583 else
584 app_name = web_app::GenerateApplicationNameFromURL(url);
585
[email protected]f87919d72011-02-02 18:46:16586 RegisterAppPrefs(app_name, profile);
[email protected]15952e462008-11-14 00:29:05587
[email protected]d83a5602010-09-16 00:22:48588 bool as_panel = extension && (container == extension_misc::LAUNCH_PANEL);
[email protected]94ce7252010-12-20 21:46:33589
590 gfx::Size window_size;
591 if (extension)
592 window_size.SetSize(extension->launch_width(),
593 extension->launch_height());
594
[email protected]fe90ca8e2011-04-08 20:40:43595 Browser* browser;
596 if (as_panel &&
597 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePanels)) {
598 browser = Browser::CreateForPanel(app_name, window_size, profile);
599 } else {
600 browser = Browser::CreateForApp(app_name, window_size, profile, as_panel);
601 }
[email protected]0e71e4152010-12-07 04:16:26602 if (app_browser)
603 *app_browser = browser;
604
[email protected]3c9e1872010-11-18 16:17:49605 TabContentsWrapper* wrapper =
[email protected]cecc93a2010-10-05 15:58:55606 browser->AddSelectedTabWithURL(url, PageTransition::START_PAGE);
[email protected]3c9e1872010-11-18 16:17:49607 TabContents* contents = wrapper->tab_contents();
[email protected]cecc93a2010-10-05 15:58:55608 contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
609 contents->render_view_host()->SyncRendererPrefs();
610 browser->window()->Show();
[email protected]bbadaa782010-04-28 21:21:53611
[email protected]68f009f2009-02-26 19:43:35612 // TODO(jcampan): http://crbug.com/8123 we should not need to set the initial
613 // focus explicitly.
[email protected]cecc93a2010-10-05 15:58:55614 contents->view()->SetInitialFocus();
[email protected]0e71e4152010-12-07 04:16:26615 return contents;
616}
[email protected]eabfdae92009-12-11 06:13:51617
[email protected]0e71e4152010-12-07 04:16:26618TabContents* Browser::OpenAppShortcutWindow(Profile* profile,
619 const GURL& url,
620 bool update_shortcut) {
621 Browser* app_browser;
622 TabContents* tab = OpenApplicationWindow(
623 profile,
624 NULL, // this is a URL app. No extension.
625 extension_misc::LAUNCH_WINDOW,
626 url,
627 &app_browser);
628
629 if (!tab)
630 return NULL;
631
632 if (update_shortcut) {
[email protected]f45d2a72010-03-08 23:28:35633 // Set UPDATE_SHORTCUT as the pending web app action. This action is picked
634 // up in LoadingStateChanged to schedule a GetApplicationInfo. And when
635 // the web app info is available, TabContents notifies Browser via
[email protected]867a73e12010-03-19 20:45:46636 // OnDidGetApplicationInfo, which calls
637 // web_app::UpdateShortcutForTabContents when it sees UPDATE_SHORTCUT as
638 // pending web app action.
[email protected]0e71e4152010-12-07 04:16:26639 app_browser->pending_web_app_action_ = UPDATE_SHORTCUT;
[email protected]f45d2a72010-03-08 23:28:35640 }
[email protected]0e71e4152010-12-07 04:16:26641 return tab;
[email protected]c28071ad2010-03-12 17:28:56642}
643
644// static
[email protected]bbadaa782010-04-28 21:21:53645TabContents* Browser::OpenApplicationTab(Profile* profile,
[email protected]9adb9692010-10-29 23:14:02646 const Extension* extension,
[email protected]24bf2022010-10-14 16:34:39647 TabContents* existing_tab) {
[email protected]ea86bfb2011-02-08 18:15:44648 Browser* browser =
649 BrowserList::FindBrowserWithType(profile, Browser::TYPE_NORMAL, false);
[email protected]cecc93a2010-10-05 15:58:55650 TabContents* contents = NULL;
[email protected]ea86bfb2011-02-08 18:15:44651 if (!browser)
[email protected]cecc93a2010-10-05 15:58:55652 return contents;
[email protected]c28071ad2010-03-12 17:28:56653
[email protected]10abd192010-09-30 02:03:49654 // Check the prefs for overridden mode.
[email protected]eaa7dd182010-12-14 11:09:00655 ExtensionService* extensions_service = profile->GetExtensionService();
[email protected]10abd192010-09-30 02:03:49656 DCHECK(extensions_service);
[email protected]b283a7532010-08-12 21:24:59657
[email protected]10abd192010-09-30 02:03:49658 ExtensionPrefs::LaunchType launch_type =
[email protected]a3b734b2010-11-30 03:17:11659 extensions_service->extension_prefs()->GetLaunchType(
[email protected]4e595682011-02-09 17:07:02660 extension->id(), ExtensionPrefs::LAUNCH_DEFAULT);
[email protected]9b217652010-10-08 22:04:23661 UMA_HISTOGRAM_ENUMERATION("Extensions.AppTabLaunchType", launch_type, 100);
[email protected]10abd192010-09-30 02:03:49662 int add_type = TabStripModel::ADD_SELECTED;
663 if (launch_type == ExtensionPrefs::LAUNCH_PINNED)
664 add_type |= TabStripModel::ADD_PINNED;
665
[email protected]37fcf262011-01-26 19:39:15666 // For extensions lacking launch urls, determine a reasonable fallback.
667 GURL extension_url = extension->GetFullLaunchURL();
668 if (!extension_url.is_valid()) {
669 extension_url = extension->options_url();
670 if (!extension_url.is_valid())
671 extension_url = GURL(chrome::kChromeUIExtensionsURL);
672 }
673
[email protected]10abd192010-09-30 02:03:49674 // TODO(erikkay): START_PAGE doesn't seem like the right transition in all
675 // cases.
[email protected]37fcf262011-01-26 19:39:15676 browser::NavigateParams params(browser, extension_url,
[email protected]616381f02010-11-02 15:15:33677 PageTransition::START_PAGE);
678 params.tabstrip_add_types = add_type;
[email protected]24bf2022010-10-14 16:34:39679
680 // Launch the application in the existing TabContents, if it was supplied.
681 if (existing_tab) {
682 TabStripModel* model = browser->tabstrip_model();
[email protected]3c9e1872010-11-18 16:17:49683 int tab_index = model->GetWrapperIndex(existing_tab);
[email protected]24bf2022010-10-14 16:34:39684
685 existing_tab->OpenURL(extension->GetFullLaunchURL(), existing_tab->GetURL(),
686 CURRENT_TAB, PageTransition::LINK);
[email protected]616381f02010-11-02 15:15:33687 if (params.tabstrip_add_types & TabStripModel::ADD_PINNED) {
[email protected]24bf2022010-10-14 16:34:39688 model->SetTabPinned(tab_index, true);
[email protected]3c9e1872010-11-18 16:17:49689 tab_index = model->GetWrapperIndex(existing_tab);
[email protected]7dfec4212010-11-01 22:12:26690 }
[email protected]616381f02010-11-02 15:15:33691 if (params.tabstrip_add_types & TabStripModel::ADD_SELECTED)
[email protected]24bf2022010-10-14 16:34:39692 model->SelectTabContentsAt(tab_index, true);
693
694 contents = existing_tab;
695 } else {
[email protected]616381f02010-11-02 15:15:33696 params.disposition = NEW_FOREGROUND_TAB;
697 browser::Navigate(&params);
[email protected]3c9e1872010-11-18 16:17:49698 contents = params.target_contents->tab_contents();
[email protected]24bf2022010-10-14 16:34:39699 }
700
[email protected]7bd42fc2011-02-09 17:32:42701 // TODO(skerner): If we are already in full screen mode, and the user
702 // set the app to open as a regular or pinned tab, what should happen?
703 // Today we open the tab, but stay in full screen mode. Should we leave
704 // full screen mode in this case?
705 if (launch_type == ExtensionPrefs::LAUNCH_FULLSCREEN &&
706 !browser->window()->IsFullscreen())
707 browser->ToggleFullscreenMode();
[email protected]10abd192010-09-30 02:03:49708
[email protected]cecc93a2010-10-05 15:58:55709 return contents;
[email protected]c28071ad2010-03-12 17:28:56710}
711
712// static
[email protected]90a8bf252010-03-12 00:09:47713void Browser::OpenBookmarkManagerWindow(Profile* profile) {
714 Browser* browser = Browser::Create(profile);
715 browser->ShowBookmarkManagerTab();
716 browser->window()->Show();
717}
718
[email protected]057d959a2010-03-12 02:56:20719#if defined(OS_MACOSX)
[email protected]90a8bf252010-03-12 00:09:47720// static
[email protected]91a5b3e2009-10-30 19:32:22721void Browser::OpenHistoryWindow(Profile* profile) {
722 Browser* browser = Browser::Create(profile);
723 browser->ShowHistoryTab();
724 browser->window()->Show();
725}
726
727// static
728void Browser::OpenDownloadsWindow(Profile* profile) {
729 Browser* browser = Browser::Create(profile);
730 browser->ShowDownloadsTab();
731 browser->window()->Show();
732}
733
734// static
[email protected]1fdff702009-10-22 00:36:18735void Browser::OpenHelpWindow(Profile* profile) {
736 Browser* browser = Browser::Create(profile);
737 browser->OpenHelpTab();
738 browser->window()->Show();
739}
[email protected]4a42d272010-06-18 01:29:42740
[email protected]eca258132010-11-15 23:33:08741// static
[email protected]4a42d272010-06-18 01:29:42742void Browser::OpenOptionsWindow(Profile* profile) {
743 Browser* browser = Browser::Create(profile);
[email protected]fee320542011-03-02 01:30:49744 browser->OpenOptionsDialog();
[email protected]4a42d272010-06-18 01:29:42745 browser->window()->Show();
746}
[email protected]c8de64a2011-01-25 17:10:23747
748// static
749void Browser::OpenClearBrowingDataDialogWindow(Profile* profile) {
750 Browser* browser = Browser::Create(profile);
751 browser->OpenClearBrowsingDataDialog();
752 browser->window()->Show();
753}
754
755// static
756void Browser::OpenImportSettingsDialogWindow(Profile* profile) {
757 Browser* browser = Browser::Create(profile);
758 browser->OpenImportSettingsDialog();
759 browser->window()->Show();
760}
[email protected]b99081b2011-03-10 17:43:47761
762// static
763void Browser::OpenInstantConfirmDialogWindow(Profile* profile) {
764 Browser* browser = Browser::Create(profile);
765 browser->OpenInstantConfirmDialog();
766 browser->window()->Show();
767}
[email protected]1fdff702009-10-22 00:36:18768#endif
769
[email protected]ccb55cf52010-03-06 22:02:04770// static
771void Browser::OpenExtensionsWindow(Profile* profile) {
772 Browser* browser = Browser::Create(profile);
773 browser->ShowExtensionsTab();
774 browser->window()->Show();
775}
776
777
[email protected]36b6dcb2008-11-12 01:19:57778///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:57779// Browser, State Storage and Retrieval for UI:
780
[email protected]57ecc4b2010-08-11 03:02:51781std::string Browser::GetWindowPlacementKey() const {
782 std::string name(prefs::kBrowserWindowPlacement);
[email protected]36b6dcb2008-11-12 01:19:57783 if (!app_name_.empty()) {
[email protected]57ecc4b2010-08-11 03:02:51784 name.append("_");
[email protected]36b6dcb2008-11-12 01:19:57785 name.append(app_name_);
786 }
[email protected]bc9a5152008-11-15 00:32:04787 return name;
788}
[email protected]36b6dcb2008-11-12 01:19:57789
[email protected]bc9a5152008-11-15 00:32:04790bool Browser::ShouldSaveWindowPlacement() const {
[email protected]25ef2b72009-12-09 05:06:51791 // Only save the window placement of popups if they are restored.
792 return (type() & TYPE_POPUP) == 0 || browser_defaults::kRestorePopups;
[email protected]bc9a5152008-11-15 00:32:04793}
[email protected]36b6dcb2008-11-12 01:19:57794
[email protected]bc9a5152008-11-15 00:32:04795void Browser::SaveWindowPlacement(const gfx::Rect& bounds, bool maximized) {
796 // Save to the session storage service, used when reloading a past session.
797 // Note that we don't want to be the ones who cause lazy initialization of
798 // the session service. This function gets called during initial window
799 // showing, and we don't want to bring in the session service this early.
[email protected]36b6dcb2008-11-12 01:19:57800 if (profile()->HasSessionService()) {
801 SessionService* session_service = profile()->GetSessionService();
802 if (session_service)
803 session_service->SetWindowBounds(session_id_, bounds, maximized);
804 }
805}
806
[email protected]15952e462008-11-14 00:29:05807gfx::Rect Browser::GetSavedWindowBounds() const {
[email protected]bb975362009-01-21 01:00:22808 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
[email protected]15952e462008-11-14 00:29:05809 bool record_mode = parsed_command_line.HasSwitch(switches::kRecordMode);
810 bool playback_mode = parsed_command_line.HasSwitch(switches::kPlaybackMode);
811 if (record_mode || playback_mode) {
812 // In playback/record mode we always fix the size of the browser and
813 // move it to (0,0). The reason for this is two reasons: First we want
814 // resize/moves in the playback to still work, and Second we want
815 // playbacks to work (as much as possible) on machines w/ different
816 // screen sizes.
817 return gfx::Rect(0, 0, 800, 600);
818 }
819
820 gfx::Rect restored_bounds = override_bounds_;
821 bool maximized;
[email protected]f87919d72011-02-02 18:46:16822 WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, this,
[email protected]15952e462008-11-14 00:29:05823 &restored_bounds, &maximized);
824 return restored_bounds;
825}
826
827// TODO(beng): obtain maximized state some other way so we don't need to go
828// through all this hassle.
829bool Browser::GetSavedMaximizedState() const {
[email protected]bb975362009-01-21 01:00:22830 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kStartMaximized))
[email protected]15952e462008-11-14 00:29:05831 return true;
832
[email protected]2e716622009-03-09 21:11:01833 if (maximized_state_ == MAXIMIZED_STATE_MAXIMIZED)
834 return true;
835 if (maximized_state_ == MAXIMIZED_STATE_UNMAXIMIZED)
836 return false;
837
838 // An explicit maximized state was not set. Query the window sizer.
[email protected]15952e462008-11-14 00:29:05839 gfx::Rect restored_bounds;
[email protected]2e716622009-03-09 21:11:01840 bool maximized = false;
[email protected]f87919d72011-02-02 18:46:16841 WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, this,
[email protected]15952e462008-11-14 00:29:05842 &restored_bounds, &maximized);
843 return maximized;
[email protected]36b6dcb2008-11-12 01:19:57844}
845
846SkBitmap Browser::GetCurrentPageIcon() const {
[email protected]0150cfc2011-04-07 22:51:41847 TabContents* contents = GetSelectedTabContents();
[email protected]ce5348a82008-12-18 18:36:23848 // |contents| can be NULL since GetCurrentPageIcon() is called by the window
849 // during the window's creation (before tabs have been added).
[email protected]0150cfc2011-04-07 22:51:41850 return contents ? contents->GetFavicon() : SkBitmap();
[email protected]36b6dcb2008-11-12 01:19:57851}
852
[email protected]731f8a42009-07-20 22:07:32853string16 Browser::GetWindowTitleForCurrentTab() const {
[email protected]3c9e1872010-11-18 16:17:49854 TabContents* contents = GetSelectedTabContents();
[email protected]dda5dfa32009-07-10 00:33:29855 string16 title;
[email protected]c7c42332008-11-15 01:10:54856
[email protected]731f8a42009-07-20 22:07:32857 // |contents| can be NULL because GetWindowTitleForCurrentTab is called by the
858 // window during the window's creation (before tabs have been added).
[email protected]36b6dcb2008-11-12 01:19:57859 if (contents) {
[email protected]dda5dfa32009-07-10 00:33:29860 title = contents->GetTitle();
[email protected]36b6dcb2008-11-12 01:19:57861 FormatTitleForDisplay(&title);
862 }
863 if (title.empty())
[email protected]0dd3a0ab2011-02-18 08:17:44864 title = TabContentsWrapper::GetDefaultTitle();
[email protected]36b6dcb2008-11-12 01:19:57865
[email protected]16779842009-07-08 23:45:29866#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
[email protected]22a3daa2009-11-09 22:03:33867 // On Mac or ChromeOS, we don't want to suffix the page title with
868 // the application name.
[email protected]d904bc82009-07-07 00:41:04869 return title;
870#elif defined(OS_WIN) || defined(OS_LINUX)
[email protected]edb5e6a2009-04-08 23:46:17871 int string_id = IDS_BROWSER_WINDOW_TITLE_FORMAT;
[email protected]dff529732010-04-01 23:50:55872 // Don't append the app name to window titles on app frames and app popups
873 if (type_ & TYPE_APP)
[email protected]edb5e6a2009-04-08 23:46:17874 string_id = IDS_BROWSER_WINDOW_TITLE_FORMAT_NO_LOGO;
[email protected]dda5dfa32009-07-10 00:33:29875 return l10n_util::GetStringFUTF16(string_id, title);
[email protected]57e68dba2009-05-15 21:30:50876#endif
[email protected]36b6dcb2008-11-12 01:19:57877}
878
879// static
[email protected]dda5dfa32009-07-10 00:33:29880void Browser::FormatTitleForDisplay(string16* title) {
[email protected]36b6dcb2008-11-12 01:19:57881 size_t current_index = 0;
882 size_t match_index;
[email protected]57ecc4b2010-08-11 03:02:51883 while ((match_index = title->find(L'\n', current_index)) != string16::npos) {
[email protected]810a52ef2010-01-08 01:22:15884 title->replace(match_index, 1, string16());
[email protected]36b6dcb2008-11-12 01:19:57885 current_index = match_index;
886 }
887}
888
889///////////////////////////////////////////////////////////////////////////////
890// Browser, OnBeforeUnload handling:
891
[email protected]460a2942010-12-15 19:43:15892bool Browser::TabsNeedBeforeUnloadFired() {
893 if (tabs_needing_before_unload_fired_.empty()) {
894 for (int i = 0; i < tab_count(); ++i) {
895 TabContents* contents = GetTabContentsAt(i);
896 if (contents->NeedToFireBeforeUnload())
897 tabs_needing_before_unload_fired_.insert(contents);
898 }
899 }
900 return !tabs_needing_before_unload_fired_.empty();
901}
902
[email protected]36b6dcb2008-11-12 01:19:57903bool Browser::ShouldCloseWindow() {
[email protected]69444cc2009-04-09 20:40:06904 if (!CanCloseWithInProgressDownloads())
905 return false;
906
907 if (HasCompletedUnloadProcessing())
[email protected]0b4d3382010-07-14 16:13:04908 return IsClosingPermitted();
[email protected]69444cc2009-04-09 20:40:06909
[email protected]36b6dcb2008-11-12 01:19:57910 is_attempting_to_close_browser_ = true;
911
[email protected]460a2942010-12-15 19:43:15912 if (!TabsNeedBeforeUnloadFired())
[email protected]0b4d3382010-07-14 16:13:04913 return IsClosingPermitted();
[email protected]36b6dcb2008-11-12 01:19:57914
915 ProcessPendingTabs();
916 return false;
917}
918
919void Browser::OnWindowClosing() {
920 if (!ShouldCloseWindow())
921 return;
922
[email protected]911f8152010-03-18 16:46:40923 bool exiting = false;
924
[email protected]c984d9f2010-07-20 20:52:20925 // Application should shutdown on last window close if the user is explicitly
926 // trying to quit, or if there is nothing keeping the browser alive (such as
927 // AppController on the Mac, or BackgroundContentsService for background
928 // pages).
929 bool should_quit_if_last_browser =
930 browser_shutdown::IsTryingToQuit() || !BrowserList::WillKeepAlive();
[email protected]7dc8c6b2010-04-09 17:02:50931
932 if (should_quit_if_last_browser && BrowserList::size() == 1) {
[email protected]36b6dcb2008-11-12 01:19:57933 browser_shutdown::OnShutdownStarting(browser_shutdown::WINDOW_CLOSE);
[email protected]911f8152010-03-18 16:46:40934 exiting = true;
935 }
[email protected]36b6dcb2008-11-12 01:19:57936
937 // Don't use HasSessionService here, we want to force creation of the
938 // session service so that user can restore what was open.
939 SessionService* session_service = profile()->GetSessionService();
940 if (session_service)
941 session_service->WindowClosing(session_id());
942
[email protected]d8375fd2008-11-25 22:45:39943 TabRestoreService* tab_restore_service = profile()->GetTabRestoreService();
[email protected]fb7da4132011-03-15 15:51:00944 if (tab_restore_service && type() == TYPE_NORMAL && tab_count())
945 tab_restore_service->BrowserClosing(tab_restore_service_delegate());
[email protected]d8375fd2008-11-25 22:45:39946
[email protected]911f8152010-03-18 16:46:40947 // TODO(sky): convert session/tab restore to use notification.
948 NotificationService::current()->Notify(
949 NotificationType::BROWSER_CLOSING,
950 Source<Browser>(this),
951 Details<bool>(&exiting));
952
[email protected]36b6dcb2008-11-12 01:19:57953 CloseAllTabs();
954}
955
[email protected]69444cc2009-04-09 20:40:06956////////////////////////////////////////////////////////////////////////////////
957// In-progress download termination handling:
958
959void Browser::InProgressDownloadResponse(bool cancel_downloads) {
960 if (cancel_downloads) {
961 cancel_download_confirmation_state_ = RESPONSE_RECEIVED;
962 CloseWindow();
963 return;
964 }
965
966 // Sets the confirmation state to NOT_PROMPTED so that if the user tries to
967 // close again we'll show the warning again.
968 cancel_download_confirmation_state_ = NOT_PROMPTED;
969
970 // Show the download page so the user can figure-out what downloads are still
971 // in-progress.
972 ShowDownloadsTab();
973}
974
[email protected]69444cc2009-04-09 20:40:06975////////////////////////////////////////////////////////////////////////////////
[email protected]c848d3d92010-09-16 21:57:45976// Browser, TabStripModel pass-thrus:
977
978int Browser::tab_count() const {
[email protected]ecc523f62010-09-28 22:45:40979 return tab_handler_->GetTabStripModel()->count();
[email protected]c848d3d92010-09-16 21:57:45980}
981
982int Browser::selected_index() const {
[email protected]ecc523f62010-09-28 22:45:40983 return tab_handler_->GetTabStripModel()->selected_index();
[email protected]c848d3d92010-09-16 21:57:45984}
985
986int Browser::GetIndexOfController(
987 const NavigationController* controller) const {
[email protected]ecc523f62010-09-28 22:45:40988 return tab_handler_->GetTabStripModel()->GetIndexOfController(controller);
[email protected]c848d3d92010-09-16 21:57:45989}
990
[email protected]3c9e1872010-11-18 16:17:49991TabContentsWrapper* Browser::GetSelectedTabContentsWrapper() const {
992 return tabstrip_model()->GetSelectedTabContents();
993}
994TabContentsWrapper* Browser::GetTabContentsWrapperAt(int index) const {
995 return tabstrip_model()->GetTabContentsAt(index);
[email protected]c848d3d92010-09-16 21:57:45996}
997
998TabContents* Browser::GetSelectedTabContents() const {
[email protected]3c9e1872010-11-18 16:17:49999 TabContentsWrapper* wrapper = GetSelectedTabContentsWrapper();
1000 if (wrapper)
1001 return wrapper->tab_contents();
1002 return NULL;
1003}
1004
1005TabContents* Browser::GetTabContentsAt(int index) const {
1006 TabContentsWrapper* wrapper = tabstrip_model()->GetTabContentsAt(index);
1007 if (wrapper)
1008 return wrapper->tab_contents();
1009 return NULL;
[email protected]c848d3d92010-09-16 21:57:451010}
1011
1012void Browser::SelectTabContentsAt(int index, bool user_gesture) {
[email protected]ecc523f62010-09-28 22:45:401013 tab_handler_->GetTabStripModel()->SelectTabContentsAt(index, user_gesture);
[email protected]c848d3d92010-09-16 21:57:451014}
1015
[email protected]fb7da4132011-03-15 15:51:001016bool Browser::IsTabPinned(int index) const {
1017 return tabstrip_model()->IsTabPinned(index);
1018}
1019
[email protected]c848d3d92010-09-16 21:57:451020void Browser::CloseAllTabs() {
[email protected]ecc523f62010-09-28 22:45:401021 tab_handler_->GetTabStripModel()->CloseAllTabs();
[email protected]c848d3d92010-09-16 21:57:451022}
1023
1024////////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:571025// Browser, Tab adding/showing functions:
1026
[email protected]95bf8a5b2010-12-22 16:04:071027bool Browser::IsTabStripEditable() const {
1028 return window()->IsTabStripEditable();
1029}
1030
[email protected]b3344872010-05-03 15:52:291031int Browser::GetIndexForInsertionDuringRestore(int relative_index) {
[email protected]ecc523f62010-09-28 22:45:401032 return (tab_handler_->GetTabStripModel()->insertion_policy() ==
1033 TabStripModel::INSERT_AFTER) ? tab_count() : relative_index;
[email protected]b3344872010-05-03 15:52:291034}
1035
[email protected]3c9e1872010-11-18 16:17:491036TabContentsWrapper* Browser::AddSelectedTabWithURL(const GURL& url,
[email protected]cecc93a2010-10-05 15:58:551037 PageTransition::Type transition) {
[email protected]616381f02010-11-02 15:15:331038 browser::NavigateParams params(this, url, transition);
1039 params.disposition = NEW_FOREGROUND_TAB;
1040 browser::Navigate(&params);
1041 return params.target_contents;
[email protected]36b6dcb2008-11-12 01:19:571042}
1043
[email protected]3c9e1872010-11-18 16:17:491044TabContents* Browser::AddTab(TabContentsWrapper* tab_contents,
[email protected]d99cdfd2009-10-08 18:58:111045 PageTransition::Type type) {
[email protected]ecc523f62010-09-28 22:45:401046 tab_handler_->GetTabStripModel()->AddTabContents(
[email protected]4a1665442010-06-28 16:09:391047 tab_contents, -1, type, TabStripModel::ADD_SELECTED);
[email protected]3c9e1872010-11-18 16:17:491048 return tab_contents->tab_contents();
[email protected]36b6dcb2008-11-12 01:19:571049}
1050
[email protected]e0c7c262009-04-23 23:09:431051void Browser::AddTabContents(TabContents* new_contents,
1052 WindowOpenDisposition disposition,
1053 const gfx::Rect& initial_pos,
1054 bool user_gesture) {
1055 AddNewContents(NULL, new_contents, disposition, initial_pos, user_gesture);
1056}
1057
1058void Browser::CloseTabContents(TabContents* contents) {
1059 CloseContents(contents);
1060}
1061
1062void Browser::BrowserShowHtmlDialog(HtmlDialogUIDelegate* delegate,
[email protected]322f3ff2009-05-22 16:19:541063 gfx::NativeWindow parent_window) {
[email protected]e0c7c262009-04-23 23:09:431064 ShowHtmlDialog(delegate, parent_window);
1065}
1066
1067void Browser::BrowserRenderWidgetShowing() {
1068 RenderWidgetShowing();
1069}
1070
1071void Browser::ToolbarSizeChanged(bool is_animating) {
1072 ToolbarSizeChanged(NULL, is_animating);
1073}
1074
[email protected]ce3fa3c2009-04-20 19:55:571075TabContents* Browser::AddRestoredTab(
[email protected]36b6dcb2008-11-12 01:19:571076 const std::vector<TabNavigation>& navigations,
1077 int tab_index,
1078 int selected_navigation,
[email protected]98aa0b52010-05-06 17:03:081079 const std::string& extension_app_id,
[email protected]5c0e6482009-07-14 20:20:091080 bool select,
[email protected]5e369672009-11-03 23:48:301081 bool pin,
[email protected]6ee12c42010-09-14 09:36:071082 bool from_last_session,
1083 SessionStorageNamespace* session_storage_namespace) {
[email protected]3c9e1872010-11-18 16:17:491084 TabContentsWrapper* wrapper = TabContentsFactory(profile(), NULL,
1085 MSG_ROUTING_NONE,
1086 GetSelectedTabContents(),
[email protected]ecc523f62010-09-28 22:45:401087 session_storage_namespace);
[email protected]3c9e1872010-11-18 16:17:491088 TabContents* new_tab = wrapper->tab_contents();
[email protected]36fb2c7c2011-04-04 15:49:081089 wrapper->extension_tab_helper()->SetExtensionAppById(extension_app_id);
[email protected]5e369672009-11-03 23:48:301090 new_tab->controller().RestoreFromState(navigations, selected_navigation,
1091 from_last_session);
[email protected]36b6dcb2008-11-12 01:19:571092
[email protected]981b992e2011-03-28 21:05:211093 int add_types = select ? TabStripModel::ADD_SELECTED :
1094 TabStripModel::ADD_NONE;
1095 if (pin) {
1096 tab_index = std::min(tab_index, tabstrip_model()->IndexOfFirstNonMiniTab());
1097 add_types |= TabStripModel::ADD_PINNED;
1098 }
1099 tab_handler_->GetTabStripModel()->InsertTabContentsAt(tab_index, wrapper,
1100 add_types);
[email protected]c93a9dd2010-04-22 20:25:181101 if (select) {
[email protected]77bc6732009-04-20 22:01:031102 window_->Activate();
[email protected]c93a9dd2010-04-22 20:25:181103 } else {
1104 // We set the size of the view here, before WebKit does its initial
1105 // layout. If we don't, the initial layout of background tabs will be
1106 // performed with a view width of 0, which may cause script outputs and
1107 // anchor link location calculations to be incorrect even after a new
1108 // layout with proper view dimensions. TabStripModel::AddTabContents()
1109 // contains similar logic.
1110 new_tab->view()->SizeContents(window_->GetRestoredBounds().size());
1111 new_tab->HideContents();
1112 }
[email protected]36b6dcb2008-11-12 01:19:571113 if (profile_->HasSessionService()) {
1114 SessionService* session_service = profile_->GetSessionService();
1115 if (session_service)
[email protected]981b992e2011-03-28 21:05:211116 session_service->TabRestored(&new_tab->controller(), pin);
[email protected]36b6dcb2008-11-12 01:19:571117 }
[email protected]ce3fa3c2009-04-20 19:55:571118 return new_tab;
[email protected]36b6dcb2008-11-12 01:19:571119}
1120
1121void Browser::ReplaceRestoredTab(
1122 const std::vector<TabNavigation>& navigations,
[email protected]5e369672009-11-03 23:48:301123 int selected_navigation,
[email protected]fca656c2010-02-10 20:30:101124 bool from_last_session,
[email protected]6ee12c42010-09-14 09:36:071125 const std::string& extension_app_id,
1126 SessionStorageNamespace* session_storage_namespace) {
[email protected]3c9e1872010-11-18 16:17:491127 TabContentsWrapper* wrapper = TabContentsFactory(profile(), NULL,
[email protected]ecc523f62010-09-28 22:45:401128 MSG_ROUTING_NONE,
[email protected]3c9e1872010-11-18 16:17:491129 GetSelectedTabContents(),
[email protected]6ee12c42010-09-14 09:36:071130 session_storage_namespace);
[email protected]36fb2c7c2011-04-04 15:49:081131 wrapper->extension_tab_helper()->SetExtensionAppById(extension_app_id);
[email protected]3c9e1872010-11-18 16:17:491132 TabContents* replacement = wrapper->tab_contents();
[email protected]5e369672009-11-03 23:48:301133 replacement->controller().RestoreFromState(navigations, selected_navigation,
1134 from_last_session);
[email protected]36b6dcb2008-11-12 01:19:571135
[email protected]ecc523f62010-09-28 22:45:401136 tab_handler_->GetTabStripModel()->ReplaceNavigationControllerAt(
1137 tab_handler_->GetTabStripModel()->selected_index(),
[email protected]3c9e1872010-11-18 16:17:491138 wrapper);
[email protected]36b6dcb2008-11-12 01:19:571139}
1140
[email protected]a8eff102009-04-14 15:23:431141bool Browser::CanRestoreTab() {
[email protected]281918912010-05-27 22:05:131142 return command_updater_.IsCommandEnabled(IDC_RESTORE_TAB);
[email protected]a8eff102009-04-14 15:23:431143}
1144
[email protected]3698f172010-03-17 20:50:291145bool Browser::NavigateToIndexWithDisposition(int index,
1146 WindowOpenDisposition disp) {
1147 NavigationController& controller =
[email protected]cb84d642010-06-10 00:56:281148 GetOrCloneTabForDisposition(disp)->controller();
1149 if (index < 0 || index >= controller.entry_count())
[email protected]3698f172010-03-17 20:50:291150 return false;
[email protected]cb84d642010-06-10 00:56:281151 controller.GoToIndex(index);
1152 return true;
[email protected]3698f172010-03-17 20:50:291153}
1154
[email protected]fee320542011-03-02 01:30:491155browser::NavigateParams Browser::GetSingletonTabNavigateParams(
1156 const GURL& url) {
[email protected]616381f02010-11-02 15:15:331157 browser::NavigateParams params(this, url, PageTransition::AUTO_BOOKMARK);
1158 params.disposition = SINGLETON_TAB;
1159 params.show_window = true;
[email protected]fee320542011-03-02 01:30:491160 return params;
1161}
1162
1163void Browser::ShowSingletonTab(const GURL& url) {
1164 browser::NavigateParams params(GetSingletonTabNavigateParams(url));
[email protected]616381f02010-11-02 15:15:331165 browser::Navigate(&params);
[email protected]36b6dcb2008-11-12 01:19:571166}
[email protected]d938aed92009-01-22 19:49:331167
[email protected]ae2622c2009-07-30 23:47:581168void Browser::UpdateCommandsForFullscreenMode(bool is_fullscreen) {
[email protected]326464d2010-02-16 22:21:101169#if !defined(OS_MACOSX)
[email protected]ae2622c2009-07-30 23:47:581170 const bool show_main_ui = (type() == TYPE_NORMAL) && !is_fullscreen;
[email protected]326464d2010-02-16 22:21:101171#else
1172 const bool show_main_ui = (type() == TYPE_NORMAL);
1173#endif
[email protected]ae2622c2009-07-30 23:47:581174
[email protected]83548a42010-06-18 13:53:371175 bool main_not_fullscreen_or_popup =
1176 show_main_ui && !is_fullscreen && (type() & TYPE_POPUP) == 0;
1177
[email protected]ae2622c2009-07-30 23:47:581178 // Navigation commands
1179 command_updater_.UpdateCommandEnabled(IDC_OPEN_CURRENT_URL, show_main_ui);
1180
1181 // Window management commands
[email protected]ae2622c2009-07-30 23:47:581182 command_updater_.UpdateCommandEnabled(IDC_SHOW_AS_TAB,
1183 (type() & TYPE_POPUP) && !is_fullscreen);
1184
1185 // Focus various bits of UI
1186 command_updater_.UpdateCommandEnabled(IDC_FOCUS_TOOLBAR, show_main_ui);
1187 command_updater_.UpdateCommandEnabled(IDC_FOCUS_LOCATION, show_main_ui);
1188 command_updater_.UpdateCommandEnabled(IDC_FOCUS_SEARCH, show_main_ui);
[email protected]cc824372010-03-31 15:33:011189 command_updater_.UpdateCommandEnabled(
[email protected]83548a42010-06-18 13:53:371190 IDC_FOCUS_MENU_BAR, main_not_fullscreen_or_popup);
1191 command_updater_.UpdateCommandEnabled(
1192 IDC_FOCUS_NEXT_PANE, main_not_fullscreen_or_popup);
1193 command_updater_.UpdateCommandEnabled(
1194 IDC_FOCUS_PREVIOUS_PANE, main_not_fullscreen_or_popup);
1195 command_updater_.UpdateCommandEnabled(
1196 IDC_FOCUS_BOOKMARKS, main_not_fullscreen_or_popup);
1197 command_updater_.UpdateCommandEnabled(
1198 IDC_FOCUS_CHROMEOS_STATUS, main_not_fullscreen_or_popup);
[email protected]ae2622c2009-07-30 23:47:581199
1200 // Show various bits of UI
1201 command_updater_.UpdateCommandEnabled(IDC_DEVELOPER_MENU, show_main_ui);
[email protected]1c41a932010-11-22 23:41:231202 command_updater_.UpdateCommandEnabled(IDC_FEEDBACK, show_main_ui);
[email protected]4a4180a52010-08-23 06:39:481203 command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_BAR,
1204 browser_defaults::bookmarks_enabled && show_main_ui);
[email protected]ae2622c2009-07-30 23:47:581205 command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, show_main_ui);
[email protected]d3b98c82010-07-14 07:45:591206 command_updater_.UpdateCommandEnabled(IDC_SYNC_BOOKMARKS,
1207 show_main_ui && profile_->IsSyncAccessible());
[email protected]da96e54c2010-08-12 00:18:321208
[email protected]ae2622c2009-07-30 23:47:581209 command_updater_.UpdateCommandEnabled(IDC_OPTIONS, show_main_ui);
1210 command_updater_.UpdateCommandEnabled(IDC_EDIT_SEARCH_ENGINES, show_main_ui);
1211 command_updater_.UpdateCommandEnabled(IDC_VIEW_PASSWORDS, show_main_ui);
1212 command_updater_.UpdateCommandEnabled(IDC_ABOUT, show_main_ui);
[email protected]fdb98512009-08-26 01:37:101213 command_updater_.UpdateCommandEnabled(IDC_SHOW_APP_MENU, show_main_ui);
[email protected]c8b59f92010-05-28 21:45:471214 command_updater_.UpdateCommandEnabled(IDC_TOGGLE_VERTICAL_TABS, show_main_ui);
[email protected]7664ab32011-02-01 23:35:251215#if defined (ENABLE_PROFILING) && !defined(NO_TCMALLOC)
1216 command_updater_.UpdateCommandEnabled(IDC_PROFILING_ENABLED, show_main_ui);
1217#endif
[email protected]ae2622c2009-07-30 23:47:581218}
1219
[email protected]36b6dcb2008-11-12 01:19:571220///////////////////////////////////////////////////////////////////////////////
1221// Browser, Assorted browser commands:
1222
[email protected]d497b0782010-03-29 19:19:061223bool Browser::ShouldOpenNewTabForWindowDisposition(
1224 WindowOpenDisposition disposition) {
1225 return (disposition == NEW_FOREGROUND_TAB ||
1226 disposition == NEW_BACKGROUND_TAB);
1227}
1228
[email protected]cb84d642010-06-10 00:56:281229TabContents* Browser::GetOrCloneTabForDisposition(
[email protected]3698f172010-03-17 20:50:291230 WindowOpenDisposition disposition) {
[email protected]3c9e1872010-11-18 16:17:491231 TabContentsWrapper* current_tab = GetSelectedTabContentsWrapper();
[email protected]d497b0782010-03-29 19:19:061232 if (ShouldOpenNewTabForWindowDisposition(disposition)) {
[email protected]cb84d642010-06-10 00:56:281233 current_tab = current_tab->Clone();
[email protected]ecc523f62010-09-28 22:45:401234 tab_handler_->GetTabStripModel()->AddTabContents(
[email protected]4a1665442010-06-28 16:09:391235 current_tab, -1, PageTransition::LINK,
1236 disposition == NEW_FOREGROUND_TAB ? TabStripModel::ADD_SELECTED :
1237 TabStripModel::ADD_NONE);
[email protected]3698f172010-03-17 20:50:291238 }
[email protected]3c9e1872010-11-18 16:17:491239 return current_tab->tab_contents();
[email protected]3698f172010-03-17 20:50:291240}
1241
[email protected]b3344872010-05-03 15:52:291242void Browser::UpdateTabStripModelInsertionPolicy() {
[email protected]ecc523f62010-09-28 22:45:401243 tab_handler_->GetTabStripModel()->SetInsertionPolicy(UseVerticalTabs() ?
[email protected]b3344872010-05-03 15:52:291244 TabStripModel::INSERT_BEFORE : TabStripModel::INSERT_AFTER);
1245}
1246
1247void Browser::UseVerticalTabsChanged() {
1248 UpdateTabStripModelInsertionPolicy();
1249 window()->ToggleTabStripMode();
1250}
1251
[email protected]018cf362010-05-05 22:43:221252bool Browser::SupportsWindowFeatureImpl(WindowFeature feature,
1253 bool check_fullscreen) const {
1254 // On Mac, fullscreen mode has most normal things (in a slide-down panel). On
1255 // other platforms, we hide some controls when in fullscreen mode.
1256 bool hide_ui_for_fullscreen = false;
1257#if !defined(OS_MACOSX)
1258 hide_ui_for_fullscreen = check_fullscreen && window_ &&
1259 window_->IsFullscreen();
1260#endif
1261
[email protected]8b8e7c92010-08-19 18:05:561262 unsigned int features = FEATURE_INFOBAR | FEATURE_SIDEBAR;
[email protected]018cf362010-05-05 22:43:221263
1264#if !defined(OS_CHROMEOS)
1265 // Chrome OS opens a FileBrowse pop up instead of using download shelf.
1266 // So FEATURE_DOWNLOADSHELF is only added for non-chromeos platforms.
1267 features |= FEATURE_DOWNLOADSHELF;
1268#endif // !defined(OS_CHROMEOS)
1269
1270 if (type() == TYPE_NORMAL) {
1271 features |= FEATURE_BOOKMARKBAR;
[email protected]018cf362010-05-05 22:43:221272 }
1273
1274 if (!hide_ui_for_fullscreen) {
[email protected]94ce7252010-12-20 21:46:331275 if (type() != TYPE_NORMAL)
[email protected]018cf362010-05-05 22:43:221276 features |= FEATURE_TITLEBAR;
1277
[email protected]94ce7252010-12-20 21:46:331278 if (type() == TYPE_NORMAL)
[email protected]018cf362010-05-05 22:43:221279 features |= FEATURE_TABSTRIP;
1280
[email protected]94ce7252010-12-20 21:46:331281 if (type() == TYPE_NORMAL)
[email protected]018cf362010-05-05 22:43:221282 features |= FEATURE_TOOLBAR;
1283
[email protected]94ce7252010-12-20 21:46:331284 if ((type() & Browser::TYPE_APP) == 0)
[email protected]018cf362010-05-05 22:43:221285 features |= FEATURE_LOCATIONBAR;
1286 }
1287 return !!(features & feature);
1288}
1289
[email protected]0b4d3382010-07-14 16:13:041290bool Browser::IsClosingPermitted() {
1291 TabCloseableStateWatcher* watcher =
1292 g_browser_process->tab_closeable_state_watcher();
1293 bool can_close = !watcher || watcher->CanCloseBrowser(this);
1294 if (!can_close && is_attempting_to_close_browser_)
1295 CancelWindowClose();
1296 return can_close;
1297}
1298
[email protected]485fba42009-03-24 23:27:291299void Browser::GoBack(WindowOpenDisposition disposition) {
[email protected]896220042010-03-23 18:14:281300 UserMetrics::RecordAction(UserMetricsAction("Back"), profile_);
[email protected]fbd77592008-11-12 20:50:271301
[email protected]3c9e1872010-11-18 16:17:491302 TabContentsWrapper* current_tab = GetSelectedTabContentsWrapper();
[email protected]ce3fa3c2009-04-20 19:55:571303 if (current_tab->controller().CanGoBack()) {
[email protected]cb84d642010-06-10 00:56:281304 TabContents* new_tab = GetOrCloneTabForDisposition(disposition);
[email protected]d497b0782010-03-29 19:19:061305 // If we are on an interstitial page and clone the tab, it won't be copied
1306 // to the new tab, so we don't need to go back.
[email protected]3c9e1872010-11-18 16:17:491307 if (current_tab->tab_contents()->showing_interstitial_page() &&
1308 (new_tab != current_tab->tab_contents()))
[email protected]d497b0782010-03-29 19:19:061309 return;
[email protected]cb84d642010-06-10 00:56:281310 new_tab->controller().GoBack();
[email protected]485fba42009-03-24 23:27:291311 }
[email protected]36b6dcb2008-11-12 01:19:571312}
1313
[email protected]3698f172010-03-17 20:50:291314void Browser::GoForward(WindowOpenDisposition disposition) {
[email protected]896220042010-03-23 18:14:281315 UserMetrics::RecordAction(UserMetricsAction("Forward"), profile_);
[email protected]3c9e1872010-11-18 16:17:491316 if (GetSelectedTabContentsWrapper()->controller().CanGoForward())
[email protected]cb84d642010-06-10 00:56:281317 GetOrCloneTabForDisposition(disposition)->controller().GoForward();
[email protected]36b6dcb2008-11-12 01:19:571318}
1319
[email protected]cb84d642010-06-10 00:56:281320void Browser::Reload(WindowOpenDisposition disposition) {
[email protected]896220042010-03-23 18:14:281321 UserMetrics::RecordAction(UserMetricsAction("Reload"), profile_);
[email protected]cb84d642010-06-10 00:56:281322 ReloadInternal(disposition, false);
[email protected]1ccb3568d2010-02-19 10:51:161323}
[email protected]fbd77592008-11-12 20:50:271324
[email protected]cb84d642010-06-10 00:56:281325void Browser::ReloadIgnoringCache(WindowOpenDisposition disposition) {
[email protected]896220042010-03-23 18:14:281326 UserMetrics::RecordAction(UserMetricsAction("ReloadIgnoringCache"), profile_);
[email protected]cb84d642010-06-10 00:56:281327 ReloadInternal(disposition, true);
[email protected]1ccb3568d2010-02-19 10:51:161328}
1329
[email protected]cb84d642010-06-10 00:56:281330void Browser::ReloadInternal(WindowOpenDisposition disposition,
1331 bool ignore_cache) {
[email protected]36b6dcb2008-11-12 01:19:571332 // If we are showing an interstitial, treat this as an OpenURL.
1333 TabContents* current_tab = GetSelectedTabContents();
[email protected]cb84d642010-06-10 00:56:281334 if (current_tab && current_tab->showing_interstitial_page()) {
1335 NavigationEntry* entry = current_tab->controller().GetActiveEntry();
1336 DCHECK(entry); // Should exist if interstitial is showing.
1337 OpenURL(entry->url(), GURL(), disposition, PageTransition::RELOAD);
1338 return;
[email protected]36b6dcb2008-11-12 01:19:571339 }
[email protected]cb84d642010-06-10 00:56:281340
1341 // As this is caused by a user action, give the focus to the page.
[email protected]3c9e1872010-11-18 16:17:491342 TabContents* tab = GetOrCloneTabForDisposition(disposition);
1343 if (!tab->FocusLocationBarByDefault())
1344 tab->Focus();
[email protected]cb84d642010-06-10 00:56:281345 if (ignore_cache)
[email protected]3c9e1872010-11-18 16:17:491346 tab->controller().ReloadIgnoringCache(true);
[email protected]cb84d642010-06-10 00:56:281347 else
[email protected]3c9e1872010-11-18 16:17:491348 tab->controller().Reload(true);
[email protected]36b6dcb2008-11-12 01:19:571349}
1350
[email protected]485fba42009-03-24 23:27:291351void Browser::Home(WindowOpenDisposition disposition) {
[email protected]896220042010-03-23 18:14:281352 UserMetrics::RecordAction(UserMetricsAction("Home"), profile_);
[email protected]485fba42009-03-24 23:27:291353 OpenURL(GetHomePage(), GURL(), disposition, PageTransition::AUTO_BOOKMARK);
[email protected]36b6dcb2008-11-12 01:19:571354}
1355
[email protected]fbd77592008-11-12 20:50:271356void Browser::OpenCurrentURL() {
[email protected]896220042010-03-23 18:14:281357 UserMetrics::RecordAction(UserMetricsAction("LoadURL"), profile_);
[email protected]7745b822009-01-27 20:15:351358 LocationBar* location_bar = window_->GetLocationBar();
[email protected]9800de5e2011-03-11 18:19:491359 if (!location_bar)
1360 return;
1361
[email protected]9d0306ea2009-09-02 19:38:391362 WindowOpenDisposition open_disposition =
1363 location_bar->GetWindowOpenDisposition();
[email protected]6b723f82010-10-05 20:14:271364 if (OpenInstant(open_disposition))
[email protected]03bb953d2010-09-14 21:38:301365 return;
[email protected]03bb953d2010-09-14 21:38:301366
[email protected]83bf2d142009-11-06 18:19:301367 GURL url(WideToUTF8(location_bar->GetInputString()));
[email protected]07d490bc2011-03-07 17:05:261368
1369 if (open_disposition == CURRENT_TAB && TabFinder::IsEnabled()) {
1370 Browser* existing_browser = NULL;
1371 TabContents* existing_tab = TabFinder::GetInstance()->FindTab(
1372 this, url, &existing_browser);
1373 if (existing_tab) {
1374 existing_browser->ActivateContents(existing_tab);
1375 return;
1376 }
1377 }
1378
[email protected]616381f02010-11-02 15:15:331379 browser::NavigateParams params(this, url, location_bar->GetPageTransition());
1380 params.disposition = open_disposition;
[email protected]514576a2010-07-01 22:51:251381 // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
1382 // inherit the opener. In some cases the tabstrip will determine the group
1383 // should be inherited, in which case the group is inherited instead of the
1384 // opener.
[email protected]616381f02010-11-02 15:15:331385 params.tabstrip_add_types =
1386 TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
1387 browser::Navigate(&params);
[email protected]46fd1ea42011-02-16 15:59:331388
[email protected]6e37fe32011-03-02 09:06:521389 DCHECK(profile_->GetExtensionService());
1390 if (profile_->GetExtensionService()->IsInstalledApp(url)) {
[email protected]46fd1ea42011-02-16 15:59:331391 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram,
1392 extension_misc::APP_LAUNCH_OMNIBOX_LOCATION,
1393 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY);
1394 }
[email protected]fbd77592008-11-12 20:50:271395}
1396
[email protected]84214982008-12-10 18:49:101397void Browser::Stop() {
[email protected]896220042010-03-23 18:14:281398 UserMetrics::RecordAction(UserMetricsAction("Stop"), profile_);
[email protected]3c9e1872010-11-18 16:17:491399 GetSelectedTabContentsWrapper()->tab_contents()->Stop();
[email protected]84214982008-12-10 18:49:101400}
1401
1402void Browser::NewWindow() {
[email protected]047e7272010-06-03 19:53:351403 if (browser_defaults::kAlwaysOpenIncognitoWindow &&
[email protected]6e6f6cb2011-01-27 13:26:551404 CommandLine::ForCurrentProcess()->HasSwitch(switches::kIncognito) &&
1405 incognito_mode_allowed_.GetValue()) {
[email protected]047e7272010-06-03 19:53:351406 NewIncognitoWindow();
1407 return;
1408 }
[email protected]896220042010-03-23 18:14:281409 UserMetrics::RecordAction(UserMetricsAction("NewWindow"), profile_);
[email protected]c9b19942010-03-26 15:58:081410 SessionService* session_service =
1411 profile_->GetOriginalProfile()->GetSessionService();
1412 if (!session_service ||
1413 !session_service->RestoreIfNecessary(std::vector<GURL>())) {
1414 Browser::OpenEmptyWindow(profile_->GetOriginalProfile());
1415 }
[email protected]84214982008-12-10 18:49:101416}
1417
1418void Browser::NewIncognitoWindow() {
[email protected]6e6f6cb2011-01-27 13:26:551419 if (!incognito_mode_allowed_.GetValue()) {
1420 NewWindow();
1421 return;
1422 }
1423
[email protected]896220042010-03-23 18:14:281424 UserMetrics::RecordAction(UserMetricsAction("NewIncognitoWindow"), profile_);
[email protected]84214982008-12-10 18:49:101425 Browser::OpenEmptyWindow(profile_->GetOffTheRecordProfile());
1426}
1427
[email protected]84214982008-12-10 18:49:101428void Browser::CloseWindow() {
[email protected]896220042010-03-23 18:14:281429 UserMetrics::RecordAction(UserMetricsAction("CloseWindow"), profile_);
[email protected]84214982008-12-10 18:49:101430 window_->Close();
1431}
1432
[email protected]fbd77592008-11-12 20:50:271433void Browser::NewTab() {
[email protected]896220042010-03-23 18:14:281434 UserMetrics::RecordAction(UserMetricsAction("NewTab"), profile_);
[email protected]b7969202010-05-14 21:29:261435
[email protected]299dabd2008-11-19 02:27:161436 if (type() == TYPE_NORMAL) {
[email protected]fbd77592008-11-12 20:50:271437 AddBlankTab(true);
[email protected]49bb7ea32011-02-02 17:58:061438 GetSelectedTabContentsWrapper()->view()->RestoreFocus();
[email protected]fbd77592008-11-12 20:50:271439 } else {
[email protected]1a6b30a2009-08-19 03:52:111440 Browser* b = GetOrCreateTabbedBrowser(profile_);
[email protected]fbd77592008-11-12 20:50:271441 b->AddBlankTab(true);
[email protected]15952e462008-11-14 00:29:051442 b->window()->Show();
[email protected]e54f30d2009-01-14 21:17:111443 // The call to AddBlankTab above did not set the focus to the tab as its
1444 // window was not active, so we have to do it explicitly.
1445 // See http://crbug.com/6380.
[email protected]3c9e1872010-11-18 16:17:491446 b->GetSelectedTabContentsWrapper()->view()->RestoreFocus();
[email protected]fbd77592008-11-12 20:50:271447 }
1448}
1449
1450void Browser::CloseTab() {
[email protected]896220042010-03-23 18:14:281451 UserMetrics::RecordAction(UserMetricsAction("CloseTab_Accelerator"),
1452 profile_);
[email protected]90b1a7a2011-03-17 21:28:211453 if (CanCloseTab())
1454 tab_handler_->GetTabStripModel()->CloseSelectedTabs();
[email protected]fbd77592008-11-12 20:50:271455}
1456
[email protected]fbd77592008-11-12 20:50:271457void Browser::SelectNextTab() {
[email protected]896220042010-03-23 18:14:281458 UserMetrics::RecordAction(UserMetricsAction("SelectNextTab"), profile_);
[email protected]ecc523f62010-09-28 22:45:401459 tab_handler_->GetTabStripModel()->SelectNextTab();
[email protected]fbd77592008-11-12 20:50:271460}
1461
1462void Browser::SelectPreviousTab() {
[email protected]896220042010-03-23 18:14:281463 UserMetrics::RecordAction(UserMetricsAction("SelectPrevTab"), profile_);
[email protected]ecc523f62010-09-28 22:45:401464 tab_handler_->GetTabStripModel()->SelectPreviousTab();
[email protected]fbd77592008-11-12 20:50:271465}
1466
[email protected]91ac9202010-07-30 18:32:351467void Browser::OpenTabpose() {
1468#if defined(OS_MACOSX)
[email protected]aac169d2011-03-18 19:53:031469 if (!CommandLine::ForCurrentProcess()->HasSwitch(
1470 switches::kEnableExposeForTabs)) {
1471 return;
1472 }
1473
[email protected]91ac9202010-07-30 18:32:351474 UserMetrics::RecordAction(UserMetricsAction("OpenTabpose"), profile_);
1475 window()->OpenTabpose();
1476#else
1477 NOTREACHED();
1478#endif
1479}
1480
[email protected]9ac7fcb2009-09-14 18:22:521481void Browser::MoveTabNext() {
[email protected]896220042010-03-23 18:14:281482 UserMetrics::RecordAction(UserMetricsAction("MoveTabNext"), profile_);
[email protected]ecc523f62010-09-28 22:45:401483 tab_handler_->GetTabStripModel()->MoveTabNext();
[email protected]9ac7fcb2009-09-14 18:22:521484}
1485
1486void Browser::MoveTabPrevious() {
[email protected]896220042010-03-23 18:14:281487 UserMetrics::RecordAction(UserMetricsAction("MoveTabPrevious"), profile_);
[email protected]ecc523f62010-09-28 22:45:401488 tab_handler_->GetTabStripModel()->MoveTabPrevious();
[email protected]9ac7fcb2009-09-14 18:22:521489}
1490
[email protected]fbd77592008-11-12 20:50:271491void Browser::SelectNumberedTab(int index) {
1492 if (index < tab_count()) {
[email protected]896220042010-03-23 18:14:281493 UserMetrics::RecordAction(UserMetricsAction("SelectNumberedTab"),
1494 profile_);
[email protected]ecc523f62010-09-28 22:45:401495 tab_handler_->GetTabStripModel()->SelectTabContentsAt(index, true);
[email protected]fbd77592008-11-12 20:50:271496 }
1497}
1498
1499void Browser::SelectLastTab() {
[email protected]896220042010-03-23 18:14:281500 UserMetrics::RecordAction(UserMetricsAction("SelectLastTab"), profile_);
[email protected]ecc523f62010-09-28 22:45:401501 tab_handler_->GetTabStripModel()->SelectLastTab();
[email protected]fbd77592008-11-12 20:50:271502}
1503
1504void Browser::DuplicateTab() {
[email protected]896220042010-03-23 18:14:281505 UserMetrics::RecordAction(UserMetricsAction("Duplicate"), profile_);
[email protected]fbd77592008-11-12 20:50:271506 DuplicateContentsAt(selected_index());
1507}
1508
1509void Browser::RestoreTab() {
[email protected]896220042010-03-23 18:14:281510 UserMetrics::RecordAction(UserMetricsAction("RestoreTab"), profile_);
[email protected]fbd77592008-11-12 20:50:271511 TabRestoreService* service = profile_->GetTabRestoreService();
1512 if (!service)
1513 return;
1514
[email protected]fb7da4132011-03-15 15:51:001515 service->RestoreMostRecentEntry(tab_restore_service_delegate());
[email protected]fbd77592008-11-12 20:50:271516}
1517
[email protected]0c4c3882009-10-01 21:42:141518void Browser::WriteCurrentURLToClipboard() {
1519 // TODO(ericu): There isn't currently a metric for this. Should there be?
1520 // We don't appear to track the action when it comes from the
1521 // RenderContextViewMenu.
[email protected]0c4c3882009-10-01 21:42:141522
1523 TabContents* contents = GetSelectedTabContents();
1524 if (!contents->ShouldDisplayURL())
1525 return;
1526
[email protected]90f39902009-10-03 04:25:371527 chrome_browser_net::WriteURLToClipboard(
[email protected]0c4c3882009-10-01 21:42:141528 contents->GetURL(),
[email protected]9f284f132010-08-31 06:14:171529 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages),
[email protected]0c4c3882009-10-01 21:42:141530 g_browser_process->clipboard());
1531}
1532
[email protected]fbd77592008-11-12 20:50:271533void Browser::ConvertPopupToTabbedBrowser() {
[email protected]896220042010-03-23 18:14:281534 UserMetrics::RecordAction(UserMetricsAction("ShowAsTab"), profile_);
[email protected]ecc523f62010-09-28 22:45:401535 int tab_strip_index = tab_handler_->GetTabStripModel()->selected_index();
[email protected]3c9e1872010-11-18 16:17:491536 TabContentsWrapper* contents =
[email protected]ecc523f62010-09-28 22:45:401537 tab_handler_->GetTabStripModel()->DetachTabContentsAt(tab_strip_index);
[email protected]15952e462008-11-14 00:29:051538 Browser* browser = Browser::Create(profile_);
1539 browser->tabstrip_model()->AppendTabContents(contents, true);
1540 browser->window()->Show();
[email protected]fbd77592008-11-12 20:50:271541}
1542
[email protected]9282cea2009-02-18 18:49:001543void Browser::ToggleFullscreenMode() {
[email protected]34930432009-11-09 00:12:091544#if !defined(OS_MACOSX)
1545 // In kiosk mode, we always want to be fullscreen. When the browser first
1546 // starts we're not yet fullscreen, so let the initial toggle go through.
1547 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode) &&
1548 window_->IsFullscreen())
1549 return;
1550#endif
1551
[email protected]896220042010-03-23 18:14:281552 UserMetrics::RecordAction(UserMetricsAction("ToggleFullscreen"), profile_);
[email protected]9282cea2009-02-18 18:49:001553 window_->SetFullscreen(!window_->IsFullscreen());
[email protected]ae2622c2009-07-30 23:47:581554 // On Linux, setting fullscreen mode is an async call to the X server, which
1555 // may or may not support fullscreen mode.
1556#if !defined(OS_LINUX)
[email protected]9282cea2009-02-18 18:49:001557 UpdateCommandsForFullscreenMode(window_->IsFullscreen());
[email protected]ae2622c2009-07-30 23:47:581558#endif
[email protected]9282cea2009-02-18 18:49:001559}
1560
[email protected]da17b372010-01-22 23:37:221561#if defined(OS_CHROMEOS)
[email protected]f97d7f632010-06-01 21:08:331562void Browser::Search() {
1563 // If the NTP is showing, close it.
1564 if (StartsWithASCII(GetSelectedTabContents()->GetURL().spec(),
1565 chrome::kChromeUINewTabURL, true)) {
1566 CloseTab();
1567 return;
1568 }
[email protected]64559862010-09-23 19:00:161569
1570 // Exit fullscreen to show omnibox.
[email protected]ebdda9092010-10-22 17:59:101571 if (window_->IsFullscreen()) {
[email protected]64559862010-09-23 19:00:161572 ToggleFullscreenMode();
[email protected]ebdda9092010-10-22 17:59:101573 // ToggleFullscreenMode is asynchronous, so we don't have omnibox
1574 // visible at this point. Wait for next event cycle which toggles
1575 // the visibility of omnibox before creating new tab.
1576 MessageLoop::current()->PostTask(
1577 FROM_HERE, method_factory_.NewRunnableMethod(&Browser::Search));
1578 return;
1579 }
[email protected]64559862010-09-23 19:00:161580
[email protected]f97d7f632010-06-01 21:08:331581 // Otherwise just open it.
1582 NewTab();
1583}
[email protected]d14af522010-12-02 03:54:501584
1585void Browser::ShowKeyboardOverlay() {
1586 window_->ShowKeyboardOverlay(window_->GetNativeHandle());
1587}
[email protected]20d17242009-10-26 20:21:051588#endif
1589
[email protected]fbd77592008-11-12 20:50:271590void Browser::Exit() {
[email protected]896220042010-03-23 18:14:281591 UserMetrics::RecordAction(UserMetricsAction("Exit"), profile_);
[email protected]965e4c42010-09-07 21:23:351592#if defined(OS_CHROMEOS)
[email protected]6a2a61d2010-11-22 03:25:351593 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("LogoutStarted", false);
1594 // Write /tmp/uptime-logout-started as well.
1595 const char kLogoutStarted[] = "logout-started";
1596 chromeos::BootTimesLoader::Get()->RecordCurrentStats(kLogoutStarted);
[email protected]db3abe62011-02-09 15:13:251597
1598 // Login screen should show up in owner's locale.
1599 PrefService* state = g_browser_process->local_state();
1600 if (state) {
1601 std::string owner_locale = state->GetString(prefs::kOwnerLocale);
1602 if (!owner_locale.empty() &&
1603 state->GetString(prefs::kApplicationLocale) != owner_locale &&
1604 !state->IsManagedPreference(prefs::kApplicationLocale)) {
1605 state->SetString(prefs::kApplicationLocale, owner_locale);
1606 state->ScheduleSavePersistentPrefs();
1607 }
1608 }
[email protected]965e4c42010-09-07 21:23:351609#endif
[email protected]460a2942010-12-15 19:43:151610 BrowserList::Exit();
[email protected]fbd77592008-11-12 20:50:271611}
1612
[email protected]36b6dcb2008-11-12 01:19:571613void Browser::BookmarkCurrentPage() {
[email protected]896220042010-03-23 18:14:281614 UserMetrics::RecordAction(UserMetricsAction("Star"), profile_);
[email protected]fbd77592008-11-12 20:50:271615
[email protected]76624fde2009-10-09 18:13:231616 BookmarkModel* model = profile()->GetBookmarkModel();
[email protected]36b6dcb2008-11-12 01:19:571617 if (!model || !model->IsLoaded())
1618 return; // Ignore requests until bookmarks are loaded.
1619
[email protected]76624fde2009-10-09 18:13:231620 GURL url;
[email protected]261cd762010-08-20 05:45:371621 string16 title;
[email protected]0150cfc2011-04-07 22:51:411622 TabContents* tab = GetSelectedTabContents();
1623 bookmark_utils::GetURLAndTitleToBookmark(tab, &url, &title);
[email protected]c50d0d42009-03-03 17:37:441624 bool was_bookmarked = model->IsBookmarked(url);
[email protected]ef0d04c2010-12-15 23:34:211625 if (!was_bookmarked && profile_->IsOffTheRecord()) {
[email protected]2c910b72011-03-08 21:16:321626 // If we're incognito the favicon may not have been saved. Save it now
[email protected]ef0d04c2010-12-15 23:34:211627 // so that bookmarks have an icon for the page.
[email protected]0150cfc2011-04-07 22:51:411628 tab->SaveFavicon();
[email protected]ef0d04c2010-12-15 23:34:211629 }
[email protected]261cd762010-08-20 05:45:371630 model->SetURLStarred(url, title, true);
[email protected]11dbbd22009-11-06 18:55:041631 // Make sure the model actually added a bookmark before showing the star. A
1632 // bookmark isn't created if the url is invalid.
1633 if (window_->IsActive() && model->IsBookmarked(url)) {
[email protected]5f2731c52009-02-28 00:41:271634 // Only show the bubble if the window is active, otherwise we may get into
1635 // weird situations were the bubble is deleted as soon as it is shown.
[email protected]c50d0d42009-03-03 17:37:441636 window_->ShowBookmarkBubble(url, was_bookmarked);
[email protected]5f2731c52009-02-28 00:41:271637 }
[email protected]36b6dcb2008-11-12 01:19:571638}
1639
[email protected]40bdb6d92009-02-25 00:22:271640void Browser::SavePage() {
[email protected]896220042010-03-23 18:14:281641 UserMetrics::RecordAction(UserMetricsAction("SavePage"), profile_);
[email protected]15d04ae2010-10-30 01:04:501642 TabContents* current_tab = GetSelectedTabContents();
1643 if (current_tab && current_tab->contents_mime_type() == "application/pdf")
1644 UserMetrics::RecordAction(UserMetricsAction("PDF.SavePage"), profile_);
[email protected]3ea60632011-04-08 18:25:421645 GetSelectedTabContentsWrapper()->download_tab_helper()->OnSavePage();
[email protected]40bdb6d92009-02-25 00:22:271646}
1647
[email protected]77d8d622010-12-15 10:30:121648void Browser::ViewSelectedSource() {
1649 ViewSource(GetSelectedTabContentsWrapper());
[email protected]36b6dcb2008-11-12 01:19:571650}
initial.commit09911bf2008-07-26 23:55:291651
[email protected]4801ecc2009-04-05 04:52:581652void Browser::ShowFindBar() {
[email protected]b77cb302009-10-29 04:09:171653 GetFindBarController()->Show();
[email protected]4801ecc2009-04-05 04:52:581654}
1655
[email protected]a3e18c42009-03-04 23:36:051656bool Browser::SupportsWindowFeature(WindowFeature feature) const {
[email protected]018cf362010-05-05 22:43:221657 return SupportsWindowFeatureImpl(feature, true);
1658}
[email protected]f5bf8ccf2010-02-05 18:19:251659
[email protected]018cf362010-05-05 22:43:221660bool Browser::CanSupportWindowFeature(WindowFeature feature) const {
1661 return SupportsWindowFeatureImpl(feature, false);
[email protected]a3e18c42009-03-04 23:36:051662}
1663
[email protected]89d6e6e2009-12-03 23:06:511664void Browser::EmailPageLocation() {
[email protected]896220042010-03-23 18:14:281665 UserMetrics::RecordAction(UserMetricsAction("EmailPageLocation"), profile_);
[email protected]89d6e6e2009-12-03 23:06:511666 GetSelectedTabContents()->EmailPageLocation();
1667}
1668
[email protected]fbd77592008-11-12 20:50:271669void Browser::Print() {
[email protected]896220042010-03-23 18:14:281670 UserMetrics::RecordAction(UserMetricsAction("PrintPreview"), profile_);
[email protected]de0ca762011-03-24 03:28:141671 TabContents* current_tab = GetSelectedTabContents();
1672 if (CommandLine::ForCurrentProcess()->HasSwitch(
1673 switches::kEnablePrintPreview)) {
1674 printing::PrintPreviewTabController::PrintPreview(current_tab);
1675 } else {
1676 current_tab->PrintNow();
1677 }
[email protected]fbd77592008-11-12 20:50:271678}
1679
[email protected]fbd77592008-11-12 20:50:271680void Browser::ToggleEncodingAutoDetect() {
[email protected]896220042010-03-23 18:14:281681 UserMetrics::RecordAction(UserMetricsAction("AutoDetectChange"), profile_);
[email protected]fbd77592008-11-12 20:50:271682 encoding_auto_detect_.SetValue(!encoding_auto_detect_.GetValue());
[email protected]a697f4c2009-09-14 22:30:181683 // If "auto detect" is turned on, then any current override encoding
1684 // is cleared. This also implicitly performs a reload.
1685 // OTOH, if "auto detect" is turned off, we don't change the currently
1686 // active encoding.
1687 if (encoding_auto_detect_.GetValue()) {
1688 TabContents* contents = GetSelectedTabContents();
1689 if (contents)
[email protected]b2fe07d12010-02-09 14:38:081690 contents->ResetOverrideEncoding();
[email protected]a697f4c2009-09-14 22:30:181691 }
[email protected]fbd77592008-11-12 20:50:271692}
1693
1694void Browser::OverrideEncoding(int encoding_id) {
[email protected]896220042010-03-23 18:14:281695 UserMetrics::RecordAction(UserMetricsAction("OverrideEncoding"), profile_);
[email protected]41fc0322009-09-04 22:23:401696 const std::string selected_encoding =
[email protected]fbd77592008-11-12 20:50:271697 CharacterEncoding::GetCanonicalEncodingNameByCommandId(encoding_id);
[email protected]57c6a652009-05-04 07:58:341698 TabContents* contents = GetSelectedTabContents();
1699 if (!selected_encoding.empty() && contents)
[email protected]b2fe07d12010-02-09 14:38:081700 contents->SetOverrideEncoding(selected_encoding);
[email protected]fbd77592008-11-12 20:50:271701 // Update the list of recently selected encodings.
[email protected]41fc0322009-09-04 22:23:401702 std::string new_selected_encoding_list;
[email protected]ddd231e2010-06-29 20:35:191703 if (CharacterEncoding::UpdateRecentlySelectedEncoding(
1704 profile_->GetPrefs()->GetString(prefs::kRecentlySelectedEncoding),
[email protected]41fc0322009-09-04 22:23:401705 encoding_id,
1706 &new_selected_encoding_list)) {
[email protected]fbd77592008-11-12 20:50:271707 profile_->GetPrefs()->SetString(prefs::kRecentlySelectedEncoding,
[email protected]ddd231e2010-06-29 20:35:191708 new_selected_encoding_list);
[email protected]fbd77592008-11-12 20:50:271709 }
[email protected]36b6dcb2008-11-12 01:19:571710}
1711
[email protected]84214982008-12-10 18:49:101712void Browser::Cut() {
[email protected]896220042010-03-23 18:14:281713 UserMetrics::RecordAction(UserMetricsAction("Cut"), profile_);
[email protected]20012dd42010-01-25 04:46:231714 window()->Cut();
[email protected]36b6dcb2008-11-12 01:19:571715}
1716
[email protected]84214982008-12-10 18:49:101717void Browser::Copy() {
[email protected]896220042010-03-23 18:14:281718 UserMetrics::RecordAction(UserMetricsAction("Copy"), profile_);
[email protected]20012dd42010-01-25 04:46:231719 window()->Copy();
[email protected]36b6dcb2008-11-12 01:19:571720}
1721
[email protected]84214982008-12-10 18:49:101722void Browser::Paste() {
[email protected]896220042010-03-23 18:14:281723 UserMetrics::RecordAction(UserMetricsAction("Paste"), profile_);
[email protected]20012dd42010-01-25 04:46:231724 window()->Paste();
[email protected]84214982008-12-10 18:49:101725}
1726
1727void Browser::Find() {
[email protected]896220042010-03-23 18:14:281728 UserMetrics::RecordAction(UserMetricsAction("Find"), profile_);
[email protected]4f3dc372009-02-24 00:10:291729 FindInPage(false, false);
[email protected]84214982008-12-10 18:49:101730}
1731
1732void Browser::FindNext() {
[email protected]896220042010-03-23 18:14:281733 UserMetrics::RecordAction(UserMetricsAction("FindNext"), profile_);
[email protected]4f3dc372009-02-24 00:10:291734 FindInPage(true, true);
[email protected]84214982008-12-10 18:49:101735}
1736
1737void Browser::FindPrevious() {
[email protected]896220042010-03-23 18:14:281738 UserMetrics::RecordAction(UserMetricsAction("FindPrevious"), profile_);
[email protected]4f3dc372009-02-24 00:10:291739 FindInPage(true, false);
[email protected]84214982008-12-10 18:49:101740}
1741
[email protected]40bd6582009-12-04 23:49:511742void Browser::Zoom(PageZoom::Function zoom_function) {
[email protected]896220042010-03-23 18:14:281743 static const UserMetricsAction kActions[] = {
1744 UserMetricsAction("ZoomMinus"),
1745 UserMetricsAction("ZoomNormal"),
1746 UserMetricsAction("ZoomPlus")
1747 };
1748
1749 UserMetrics::RecordAction(kActions[zoom_function - PageZoom::ZOOM_OUT],
1750 profile_);
[email protected]3c9e1872010-11-18 16:17:491751 TabContentsWrapper* tab_contents = GetSelectedTabContentsWrapper();
[email protected]40bd6582009-12-04 23:49:511752 tab_contents->render_view_host()->Zoom(zoom_function);
[email protected]84214982008-12-10 18:49:101753}
1754
1755void Browser::FocusToolbar() {
[email protected]896220042010-03-23 18:14:281756 UserMetrics::RecordAction(UserMetricsAction("FocusToolbar"), profile_);
[email protected]84214982008-12-10 18:49:101757 window_->FocusToolbar();
1758}
1759
[email protected]bdb7ff62010-07-20 01:56:521760void Browser::FocusAppMenu() {
1761 UserMetrics::RecordAction(UserMetricsAction("FocusAppMenu"), profile_);
1762 window_->FocusAppMenu();
[email protected]cc824372010-03-31 15:33:011763}
1764
[email protected]84214982008-12-10 18:49:101765void Browser::FocusLocationBar() {
[email protected]896220042010-03-23 18:14:281766 UserMetrics::RecordAction(UserMetricsAction("FocusLocation"), profile_);
[email protected]a26dc362010-04-23 01:48:581767 window_->SetFocusToLocationBar(true);
[email protected]84214982008-12-10 18:49:101768}
1769
[email protected]83548a42010-06-18 13:53:371770void Browser::FocusBookmarksToolbar() {
1771 UserMetrics::RecordAction(UserMetricsAction("FocusBookmarksToolbar"),
1772 profile_);
1773 window_->FocusBookmarksToolbar();
1774}
1775
1776void Browser::FocusChromeOSStatus() {
1777 UserMetrics::RecordAction(UserMetricsAction("FocusChromeOSStatus"), profile_);
1778 window_->FocusChromeOSStatus();
1779}
1780
1781void Browser::FocusNextPane() {
1782 UserMetrics::RecordAction(UserMetricsAction("FocusNextPane"), profile_);
1783 window_->RotatePaneFocus(true);
1784}
1785
1786void Browser::FocusPreviousPane() {
1787 UserMetrics::RecordAction(UserMetricsAction("FocusPreviousPane"), profile_);
1788 window_->RotatePaneFocus(false);
1789}
1790
[email protected]84214982008-12-10 18:49:101791void Browser::FocusSearch() {
1792 // TODO(beng): replace this with FocusLocationBar
[email protected]896220042010-03-23 18:14:281793 UserMetrics::RecordAction(UserMetricsAction("FocusSearch"), profile_);
[email protected]7745b822009-01-27 20:15:351794 window_->GetLocationBar()->FocusSearch();
[email protected]84214982008-12-10 18:49:101795}
1796
1797void Browser::OpenFile() {
[email protected]896220042010-03-23 18:14:281798 UserMetrics::RecordAction(UserMetricsAction("OpenFile"), profile_);
[email protected]9d1d8ad52011-03-11 22:58:171799#if defined(OS_CHROMEOS) && !defined(FILE_MANAGER_EXTENSION)
[email protected]f59f1162010-04-23 21:19:291800 FileBrowseUI::OpenPopup(profile_,
1801 "",
1802 FileBrowseUI::kPopupWidth,
1803 FileBrowseUI::kPopupHeight);
1804#else
[email protected]84214982008-12-10 18:49:101805 if (!select_file_dialog_.get())
1806 select_file_dialog_ = SelectFileDialog::Create(this);
1807
[email protected]35896a32010-06-09 08:42:511808 const FilePath directory = profile_->last_selected_directory();
1809
[email protected]84214982008-12-10 18:49:101810 // TODO(beng): figure out how to juggle this.
[email protected]d56bcd22009-03-16 19:51:561811 gfx::NativeWindow parent_window = window_->GetNativeHandle();
[email protected]84214982008-12-10 18:49:101812 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE,
[email protected]35896a32010-06-09 08:42:511813 string16(), directory,
[email protected]b949f1112009-04-12 20:03:081814 NULL, 0, FILE_PATH_LITERAL(""),
[email protected]d56bcd22009-03-16 19:51:561815 parent_window, NULL);
[email protected]f59f1162010-04-23 21:19:291816#endif
[email protected]84214982008-12-10 18:49:101817}
1818
1819void Browser::OpenCreateShortcutsDialog() {
[email protected]896220042010-03-23 18:14:281820 UserMetrics::RecordAction(UserMetricsAction("CreateShortcut"), profile_);
[email protected]b96aa932009-08-12 21:34:491821#if defined(OS_WIN) || defined(OS_LINUX)
[email protected]3c9e1872010-11-18 16:17:491822 TabContentsWrapper* current_tab = GetSelectedTabContentsWrapper();
1823 DCHECK(current_tab &&
1824 web_app::IsValidUrl(current_tab->tab_contents()->GetURL())) <<
1825 "Menu item should be disabled.";
[email protected]ed5431872009-11-17 08:39:511826
1827 NavigationEntry* entry = current_tab->controller().GetLastCommittedEntry();
1828 if (!entry)
1829 return;
1830
[email protected]eabfdae92009-12-11 06:13:511831 // RVH's GetApplicationInfo should not be called before it returns.
1832 DCHECK(pending_web_app_action_ == NONE);
1833 pending_web_app_action_ = CREATE_SHORTCUT;
1834
[email protected]a2cf65eb2010-01-18 08:20:381835 // Start fetching web app info for CreateApplicationShortcut dialog and show
1836 // the dialog when the data is available in OnDidGetApplicationInfo.
[email protected]553602e12011-04-05 17:01:181837 current_tab->extension_tab_helper()->GetApplicationInfo(entry->page_id());
[email protected]98f6e022009-06-05 22:49:531838#else
1839 NOTIMPLEMENTED();
1840#endif
[email protected]36b6dcb2008-11-12 01:19:571841}
1842
[email protected]2a8a98122010-07-16 11:58:481843void Browser::ToggleDevToolsWindow(DevToolsToggleAction action) {
1844 std::string uma_string;
1845 switch (action) {
1846 case DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE:
1847 uma_string = "DevTools_ToggleConsole";
1848 break;
1849 case DEVTOOLS_TOGGLE_ACTION_NONE:
1850 case DEVTOOLS_TOGGLE_ACTION_INSPECT:
1851 default:
1852 uma_string = "DevTools_ToggleWindow";
1853 break;
1854 }
1855 UserMetrics::RecordAction(UserMetricsAction(uma_string.c_str()), profile_);
[email protected]3061ccf32009-07-13 14:17:491856 DevToolsManager::GetInstance()->ToggleDevToolsWindow(
[email protected]3c9e1872010-11-18 16:17:491857 GetSelectedTabContentsWrapper()->render_view_host(), action);
[email protected]fbd77592008-11-12 20:50:271858}
1859
[email protected]adb6a84d2011-02-07 16:58:401860void Browser::OpenTaskManager(bool highlight_background_resources) {
[email protected]896220042010-03-23 18:14:281861 UserMetrics::RecordAction(UserMetricsAction("TaskManager"), profile_);
[email protected]adb6a84d2011-02-07 16:58:401862 if (highlight_background_resources)
1863 window_->ShowBackgroundPages();
1864 else
1865 window_->ShowTaskManager();
[email protected]84214982008-12-10 18:49:101866}
1867
[email protected]84214982008-12-10 18:49:101868void Browser::OpenBugReportDialog() {
[email protected]86206622010-05-14 05:45:261869 UserMetrics::RecordAction(UserMetricsAction("ReportBug"), profile_);
[email protected]35d06152011-01-10 22:19:421870 browser::ShowHtmlBugReportView(this);
[email protected]84214982008-12-10 18:49:101871}
[email protected]44b2c8852009-03-18 00:57:491872
[email protected]84214982008-12-10 18:49:101873void Browser::ToggleBookmarkBar() {
[email protected]896220042010-03-23 18:14:281874 UserMetrics::RecordAction(UserMetricsAction("ShowBookmarksBar"), profile_);
[email protected]84214982008-12-10 18:49:101875 window_->ToggleBookmarkBar();
1876}
1877
[email protected]84214982008-12-10 18:49:101878void Browser::OpenBookmarkManager() {
[email protected]896220042010-03-23 18:14:281879 UserMetrics::RecordAction(UserMetricsAction("ShowBookmarkManager"), profile_);
[email protected]47e532b2010-04-23 17:46:401880 ShowBookmarkManagerTab();
[email protected]84214982008-12-10 18:49:101881}
[email protected]8bf80e922009-03-09 20:56:361882
[email protected]fdb98512009-08-26 01:37:101883void Browser::ShowAppMenu() {
[email protected]366069f2011-01-11 09:36:121884 // We record the user metric for this event in WrenchMenu::RunMenu.
[email protected]fdb98512009-08-26 01:37:101885 window_->ShowAppMenu();
1886}
1887
[email protected]6404197b2010-03-03 00:40:401888void Browser::ShowBookmarkManagerTab() {
[email protected]04f40d362010-10-11 17:52:451889 UserMetrics::RecordAction(UserMetricsAction("ShowBookmarks"), profile_);
[email protected]fee320542011-03-02 01:30:491890 ShowSingletonTab(GURL(chrome::kChromeUIBookmarksURL));
[email protected]6404197b2010-03-03 00:40:401891}
1892
[email protected]8bf80e922009-03-09 20:56:361893void Browser::ShowHistoryTab() {
[email protected]896220042010-03-23 18:14:281894 UserMetrics::RecordAction(UserMetricsAction("ShowHistory"), profile_);
[email protected]fee320542011-03-02 01:30:491895 ShowSingletonTab(GURL(chrome::kChromeUIHistoryURL));
[email protected]8bf80e922009-03-09 20:56:361896}
[email protected]84214982008-12-10 18:49:101897
1898void Browser::ShowDownloadsTab() {
[email protected]896220042010-03-23 18:14:281899 UserMetrics::RecordAction(UserMetricsAction("ShowDownloads"), profile_);
[email protected]3d037ce72011-04-04 17:43:451900 if (window()) {
1901 DownloadShelf* shelf = window()->GetDownloadShelf();
1902 if (shelf->IsShowing())
1903 shelf->Close();
1904 }
[email protected]fee320542011-03-02 01:30:491905 ShowSingletonTab(GURL(chrome::kChromeUIDownloadsURL));
[email protected]84214982008-12-10 18:49:101906}
1907
[email protected]34085a32009-11-06 22:49:481908void Browser::ShowExtensionsTab() {
[email protected]896220042010-03-23 18:14:281909 UserMetrics::RecordAction(UserMetricsAction("ShowExtensions"), profile_);
[email protected]fee320542011-03-02 01:30:491910 ShowSingletonTab(GURL(chrome::kChromeUIExtensionsURL));
[email protected]34085a32009-11-06 22:49:481911}
1912
[email protected]c1bbaa82010-11-08 11:17:051913void Browser::ShowAboutConflictsTab() {
1914 UserMetrics::RecordAction(UserMetricsAction("AboutConflicts"), profile_);
[email protected]fee320542011-03-02 01:30:491915 ShowSingletonTab(GURL(chrome::kChromeUIConflictsURL));
[email protected]c1bbaa82010-11-08 11:17:051916}
1917
[email protected]10e457c2010-04-29 03:35:231918void Browser::ShowBrokenPageTab(TabContents* contents) {
1919 UserMetrics::RecordAction(UserMetricsAction("ReportBug"), profile_);
1920 string16 page_title = contents->GetTitle();
1921 NavigationEntry* entry = contents->controller().GetActiveEntry();
1922 if (!entry)
1923 return;
1924 std::string page_url = entry->url().spec();
1925 std::vector<std::string> subst;
1926 subst.push_back(UTF16ToASCII(page_title));
1927 subst.push_back(page_url);
1928 std::string report_page_url =
1929 ReplaceStringPlaceholders(kBrokenPageUrl, subst, NULL);
[email protected]fee320542011-03-02 01:30:491930 ShowSingletonTab(GURL(report_page_url));
[email protected]10e457c2010-04-29 03:35:231931}
1932
[email protected]12e816bde2010-09-14 19:59:291933void Browser::ShowOptionsTab(const std::string& sub_page) {
[email protected]e50eeee2010-09-22 00:33:301934 GURL url(chrome::kChromeUISettingsURL + sub_page);
[email protected]fee320542011-03-02 01:30:491935 browser::NavigateParams params(GetSingletonTabNavigateParams(url));
1936 params.path_behavior = browser::NavigateParams::IGNORE_AND_NAVIGATE;
1937 browser::Navigate(&params);
[email protected]4a42d272010-06-18 01:29:421938}
1939
[email protected]84214982008-12-10 18:49:101940void Browser::OpenClearBrowsingDataDialog() {
[email protected]896220042010-03-23 18:14:281941 UserMetrics::RecordAction(UserMetricsAction("ClearBrowsingData_ShowDlg"),
1942 profile_);
[email protected]445177652011-03-09 02:04:051943 ShowOptionsTab(chrome::kClearBrowserDataSubPage);
[email protected]84214982008-12-10 18:49:101944}
1945
[email protected]84214982008-12-10 18:49:101946void Browser::OpenOptionsDialog() {
[email protected]024617a2010-08-20 05:08:051947 UserMetrics::RecordAction(UserMetricsAction("ShowOptions"), profile_);
[email protected]445177652011-03-09 02:04:051948 GURL url(chrome::kChromeUISettingsURL);
1949 browser::NavigateParams params(GetSingletonTabNavigateParams(url));
1950 params.path_behavior = browser::NavigateParams::IGNORE_AND_STAY_PUT;
1951 browser::Navigate(&params);
[email protected]fbd77592008-11-12 20:50:271952}
1953
1954void Browser::OpenPasswordManager() {
[email protected]e8ce8bb2011-03-10 03:10:041955 UserMetrics::RecordAction(UserMetricsAction("Options_ShowPasswordManager"),
1956 profile_);
1957 ShowOptionsTab(chrome::kPasswordManagerSubPage);
[email protected]fbd77592008-11-12 20:50:271958}
1959
[email protected]1bdf29e2009-05-11 23:45:251960void Browser::OpenImportSettingsDialog() {
[email protected]896220042010-03-23 18:14:281961 UserMetrics::RecordAction(UserMetricsAction("Import_ShowDlg"), profile_);
[email protected]445177652011-03-09 02:04:051962 ShowOptionsTab(chrome::kImportDataSubPage);
[email protected]1bdf29e2009-05-11 23:45:251963}
[email protected]1bdf29e2009-05-11 23:45:251964
[email protected]b99081b2011-03-10 17:43:471965void Browser::OpenInstantConfirmDialog() {
1966 ShowOptionsTab(chrome::kInstantConfirmPage);
1967}
1968
[email protected]ca38d8e2009-08-20 18:08:161969void Browser::OpenSyncMyBookmarksDialog() {
[email protected]40f047972009-11-25 03:54:401970 sync_ui_util::OpenSyncMyBookmarksDialog(
[email protected]c8de64a2011-01-25 17:10:231971 profile_, this, ProfileSyncService::START_FROM_WRENCH);
[email protected]ca38d8e2009-08-20 18:08:161972}
[email protected]ca38d8e2009-08-20 18:08:161973
[email protected]fbd77592008-11-12 20:50:271974void Browser::OpenAboutChromeDialog() {
[email protected]896220042010-03-23 18:14:281975 UserMetrics::RecordAction(UserMetricsAction("AboutChrome"), profile_);
[email protected]976e69f2010-08-13 18:28:171976#if defined(OS_CHROMEOS)
[email protected]fee320542011-03-02 01:30:491977 ShowSingletonTab(GURL(chrome::kChromeUIAboutURL));
[email protected]976e69f2010-08-13 18:28:171978#else
[email protected]2d46c842008-11-14 19:24:311979 window_->ShowAboutChromeDialog();
[email protected]976e69f2010-08-13 18:28:171980#endif
[email protected]fbd77592008-11-12 20:50:271981}
1982
[email protected]b1b73942010-05-26 20:11:541983void Browser::OpenUpdateChromeDialog() {
1984 UserMetrics::RecordAction(UserMetricsAction("UpdateChrome"), profile_);
1985 window_->ShowUpdateChromeDialog();
1986}
1987
[email protected]fbd77592008-11-12 20:50:271988void Browser::OpenHelpTab() {
[email protected]0a4a0be2010-11-09 10:42:471989 GURL help_url(kHelpContentUrl);
[email protected]0a4a0be2010-11-09 10:42:471990 GURL localized_help_url = google_util::AppendGoogleLocaleParam(help_url);
1991 AddSelectedTabWithURL(localized_help_url, PageTransition::AUTO_BOOKMARK);
[email protected]fbd77592008-11-12 20:50:271992}
1993
[email protected]403c14862009-10-28 00:00:491994void Browser::OpenThemeGalleryTabAndActivate() {
[email protected]616381f02010-11-02 15:15:331995 AddSelectedTabWithURL(GURL(l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_URL)),
1996 PageTransition::LINK);
[email protected]403c14862009-10-28 00:00:491997}
1998
[email protected]31cc1c022010-10-15 20:03:471999void Browser::OpenPrivacyDashboardTabAndActivate() {
[email protected]3e0505452010-11-02 21:45:242000 OpenURL(GURL(kPrivacyDashboardUrl), GURL(),
2001 NEW_FOREGROUND_TAB, PageTransition::LINK);
[email protected]31cc1c022010-10-15 20:03:472002 window_->Activate();
2003}
2004
[email protected]663bd9e2011-03-21 01:07:012005void Browser::OpenAutofillHelpTabAndActivate() {
[email protected]91a79232010-11-10 18:15:082006 GURL help_url = google_util::AppendGoogleLocaleParam(GURL(kAutofillHelpUrl));
2007 AddSelectedTabWithURL(help_url, PageTransition::LINK);
[email protected]bb8fe2d2010-06-28 20:04:222008}
2009
[email protected]024617a2010-08-20 05:08:052010void Browser::OpenSearchEngineOptionsDialog() {
[email protected]445177652011-03-09 02:04:052011 UserMetrics::RecordAction(UserMetricsAction("EditSearchEngines"), profile_);
[email protected]445177652011-03-09 02:04:052012 ShowOptionsTab(chrome::kSearchEnginesSubPage);
[email protected]024617a2010-08-20 05:08:052013}
2014
[email protected]16779842009-07-08 23:45:292015#if defined(OS_CHROMEOS)
[email protected]5dcbc02f2010-01-26 22:32:062016void Browser::OpenSystemOptionsDialog() {
[email protected]896220042010-03-23 18:14:282017 UserMetrics::RecordAction(UserMetricsAction("OpenSystemOptionsDialog"),
2018 profile_);
[email protected]445177652011-03-09 02:04:052019 ShowOptionsTab(chrome::kSystemOptionsSubPage);
[email protected]5dcbc02f2010-01-26 22:32:062020}
2021
2022void Browser::OpenInternetOptionsDialog() {
[email protected]896220042010-03-23 18:14:282023 UserMetrics::RecordAction(UserMetricsAction("OpenInternetOptionsDialog"),
2024 profile_);
[email protected]445177652011-03-09 02:04:052025 ShowOptionsTab(chrome::kInternetOptionsSubPage);
[email protected]024617a2010-08-20 05:08:052026}
2027
2028void Browser::OpenLanguageOptionsDialog() {
2029 UserMetrics::RecordAction(UserMetricsAction("OpenLanguageOptionsDialog"),
2030 profile_);
[email protected]445177652011-03-09 02:04:052031 ShowOptionsTab(chrome::kLanguageOptionsSubPage);
[email protected]be715072009-07-07 15:43:202032}
[email protected]46b92f852010-10-06 13:12:052033
2034void Browser::OpenSystemTabAndActivate() {
2035 OpenURL(GURL(chrome::kChromeUISystemInfoURL), GURL(),
2036 NEW_FOREGROUND_TAB, PageTransition::LINK);
2037 window_->Activate();
2038}
2039
[email protected]38017612010-10-13 18:46:002040void Browser::OpenMobilePlanTabAndActivate() {
2041 OpenURL(GURL(chrome::kChromeUIMobileSetupURL), GURL(),
2042 NEW_FOREGROUND_TAB, PageTransition::LINK);
2043 window_->Activate();
2044}
[email protected]be715072009-07-07 15:43:202045#endif
2046
[email protected]a003d8e2010-10-02 21:03:352047void Browser::OpenPluginsTabAndActivate() {
2048 OpenURL(GURL(chrome::kAboutPluginsURL), GURL(),
2049 NEW_FOREGROUND_TAB, PageTransition::LINK);
2050 window_->Activate();
2051}
2052
[email protected]36b6dcb2008-11-12 01:19:572053///////////////////////////////////////////////////////////////////////////////
2054
2055// static
[email protected]79117172009-08-28 16:11:442056void Browser::SetNewHomePagePrefs(PrefService* prefs) {
[email protected]8fe6e1c2010-05-27 08:21:542057 const PrefService::Preference* home_page_pref =
2058 prefs->FindPreference(prefs::kHomePage);
2059 if (home_page_pref &&
2060 !home_page_pref->IsManaged() &&
[email protected]ddd231e2010-06-29 20:35:192061 !prefs->HasPrefPath(prefs::kHomePage)) {
[email protected]b41eb732009-09-30 16:49:332062 prefs->SetString(prefs::kHomePage,
[email protected]ddd231e2010-06-29 20:35:192063 GoogleURLTracker::kDefaultGoogleHomepage);
2064 }
[email protected]8fe6e1c2010-05-27 08:21:542065 const PrefService::Preference* home_page_is_new_tab_page_pref =
2066 prefs->FindPreference(prefs::kHomePageIsNewTabPage);
2067 if (home_page_is_new_tab_page_pref &&
2068 !home_page_is_new_tab_page_pref->IsManaged() &&
2069 !prefs->HasPrefPath(prefs::kHomePageIsNewTabPage))
[email protected]b41eb732009-09-30 16:49:332070 prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
[email protected]79117172009-08-28 16:11:442071}
2072
2073// static
[email protected]36b6dcb2008-11-12 01:19:572074void Browser::RegisterPrefs(PrefService* prefs) {
[email protected]36b6dcb2008-11-12 01:19:572075 prefs->RegisterIntegerPref(prefs::kOptionsWindowLastTabIndex, 0);
[email protected]8b8e7c92010-08-19 18:05:562076 prefs->RegisterIntegerPref(prefs::kExtensionSidebarWidth, -1);
[email protected]f87919d72011-02-02 18:46:162077 prefs->RegisterIntegerPref(prefs::kMultipleProfilePrefMigration, 0);
[email protected]09d81f82010-12-15 16:46:422078 // Educated guess: Chrome has a bundled Flash version supporting
2079 // clearing LSO data, Chromium hasn't.
2080#if defined(GOOGLE_CHROME_BUILD)
2081 prefs->RegisterBooleanPref(prefs::kClearPluginLSODataEnabled, true);
2082#else
2083 prefs->RegisterBooleanPref(prefs::kClearPluginLSODataEnabled, false);
2084#endif
[email protected]36b6dcb2008-11-12 01:19:572085}
2086
2087// static
2088void Browser::RegisterUserPrefs(PrefService* prefs) {
[email protected]0d220832009-11-06 00:45:182089 prefs->RegisterStringPref(prefs::kHomePage,
[email protected]20ce516d2010-06-18 02:20:042090 chrome::kChromeUINewTabURL);
[email protected]36b6dcb2008-11-12 01:19:572091 prefs->RegisterBooleanPref(prefs::kHomePageIsNewTabPage, true);
[email protected]36b6dcb2008-11-12 01:19:572092 prefs->RegisterBooleanPref(prefs::kShowHomeButton, false);
[email protected]93a2c7242009-07-07 18:43:092093#if defined(OS_MACOSX)
2094 // This really belongs in platform code, but there's no good place to
2095 // initialize it between the time when the AppController is created
2096 // (where there's no profile) and the time the controller gets another
2097 // crack at the start of the main event loop. By that time, BrowserInit
2098 // has already created the browser window, and it's too late: we need the
2099 // pref to be already initialized. Doing it here also saves us from having
2100 // to hard-code pref registration in the several unit tests that use
2101 // this preference.
[email protected]a99fce0e2011-03-21 20:58:482102 prefs->RegisterBooleanPref(prefs::kConfirmToQuitEnabled, false);
[email protected]eee9f552009-11-28 22:05:112103 prefs->RegisterBooleanPref(prefs::kShowUpdatePromotionInfoBar, true);
[email protected]93a2c7242009-07-07 18:43:092104#endif
[email protected]36b6dcb2008-11-12 01:19:572105 prefs->RegisterBooleanPref(prefs::kDeleteBrowsingHistory, true);
2106 prefs->RegisterBooleanPref(prefs::kDeleteDownloadHistory, true);
2107 prefs->RegisterBooleanPref(prefs::kDeleteCache, true);
2108 prefs->RegisterBooleanPref(prefs::kDeleteCookies, true);
2109 prefs->RegisterBooleanPref(prefs::kDeletePasswords, false);
[email protected]18f92d4f2010-10-19 00:14:582110 prefs->RegisterBooleanPref(prefs::kDeleteFormData, false);
[email protected]36b6dcb2008-11-12 01:19:572111 prefs->RegisterIntegerPref(prefs::kDeleteTimePeriod, 0);
[email protected]48b47ffa2009-05-02 07:18:302112 prefs->RegisterBooleanPref(prefs::kCheckDefaultBrowser, true);
[email protected]c8865482009-07-23 20:40:102113 prefs->RegisterBooleanPref(prefs::kShowOmniboxSearchHint, true);
[email protected]ed5431872009-11-17 08:39:512114 prefs->RegisterBooleanPref(prefs::kWebAppCreateOnDesktop, true);
2115 prefs->RegisterBooleanPref(prefs::kWebAppCreateInAppsMenu, true);
2116 prefs->RegisterBooleanPref(prefs::kWebAppCreateInQuickLaunchBar, true);
[email protected]b9c505b2010-04-30 15:05:102117 prefs->RegisterBooleanPref(prefs::kUseVerticalTabs, false);
[email protected]0908acd92010-02-26 17:42:132118 prefs->RegisterBooleanPref(prefs::kEnableTranslate, true);
[email protected]e96bf0c52010-08-23 23:20:572119 prefs->RegisterBooleanPref(prefs::kRemotingHasSetupCompleted, false);
[email protected]02337592010-09-27 18:38:252120 prefs->RegisterStringPref(prefs::kCloudPrintEmail, std::string());
[email protected]06c17322011-02-02 22:41:552121 prefs->RegisterBooleanPref(prefs::kCloudPrintProxyEnabled, true);
[email protected]543432ee2010-10-22 16:32:132122 prefs->RegisterBooleanPref(prefs::kDevToolsDisabled, false);
[email protected]6e6f6cb2011-01-27 13:26:552123 prefs->RegisterBooleanPref(prefs::kIncognitoEnabled, true);
[email protected]f87919d72011-02-02 18:46:162124 prefs->RegisterIntegerPref(prefs::kDevToolsSplitLocation, -1);
2125 prefs->RegisterDictionaryPref(prefs::kBrowserWindowPlacement);
[email protected]0d277d682011-02-08 18:04:422126 prefs->RegisterDictionaryPref(prefs::kPreferencesWindowPlacement);
[email protected]2bf2bd92011-03-31 07:12:442127 // We need to register the type of these preferences in order to query
2128 // them even though they're only typically controlled via policy.
[email protected]97123dc2010-12-21 02:12:332129 prefs->RegisterBooleanPref(prefs::kDisable3DAPIs, false);
[email protected]2bf2bd92011-03-31 07:12:442130 prefs->RegisterBooleanPref(prefs::kPluginsAllowOutdated, false);
[email protected]36b6dcb2008-11-12 01:19:572131}
2132
2133// static
[email protected]ecc523f62010-09-28 22:45:402134bool Browser::RunUnloadEventsHelper(TabContents* contents) {
2135 // If the TabContents is not connected yet, then there's no unload
2136 // handler we can fire even if the TabContents has an unload listener.
2137 // One case where we hit this is in a tab that has an infinite loop
2138 // before load.
[email protected]5aab5e22010-12-08 22:13:292139 if (contents->NeedToFireBeforeUnload()) {
[email protected]ecc523f62010-09-28 22:45:402140 // If the page has unload listeners, then we tell the renderer to fire
2141 // them. Once they have fired, we'll get a message back saying whether
2142 // to proceed closing the page or not, which sends us back to this method
[email protected]5aab5e22010-12-08 22:13:292143 // with the NeedToFireBeforeUnload bit cleared.
[email protected]ecc523f62010-09-28 22:45:402144 contents->render_view_host()->FirePageBeforeUnload(false);
2145 return true;
2146 }
2147 return false;
2148}
2149
2150// static
[email protected]36b6dcb2008-11-12 01:19:572151Browser* Browser::GetBrowserForController(
2152 const NavigationController* controller, int* index_result) {
2153 BrowserList::const_iterator it;
2154 for (it = BrowserList::begin(); it != BrowserList::end(); ++it) {
[email protected]ecc523f62010-09-28 22:45:402155 int index = (*it)->tab_handler_->GetTabStripModel()->GetIndexOfController(
2156 controller);
[email protected]36b6dcb2008-11-12 01:19:572157 if (index != TabStripModel::kNoTab) {
2158 if (index_result)
2159 *index_result = index;
2160 return *it;
2161 }
2162 }
2163
2164 return NULL;
2165}
2166
[email protected]485fba42009-03-24 23:27:292167void Browser::ExecuteCommandWithDisposition(
2168 int id, WindowOpenDisposition disposition) {
[email protected]1fc025202009-01-20 23:03:142169 // No commands are enabled if there is not yet any selected tab.
2170 // TODO(pkasting): It seems like we should not need this, because either
2171 // most/all commands should not have been enabled yet anyway or the ones that
2172 // are enabled should be global, or safe themselves against having no selected
2173 // tab. However, Ben says he tried removing this before and got lots of
2174 // crashes, e.g. from Windows sending WM_COMMANDs at random times during
2175 // window construction. This probably could use closer examination someday.
[email protected]3c9e1872010-11-18 16:17:492176 if (!GetSelectedTabContentsWrapper())
[email protected]1fc025202009-01-20 23:03:142177 return;
2178
[email protected]59c9f002010-11-19 00:38:052179 DCHECK(command_updater_.IsCommandEnabled(id)) << "Invalid/disabled command "
2180 << id;
[email protected]36b6dcb2008-11-12 01:19:572181
[email protected]867125a02009-12-10 06:01:482182 // If command execution is blocked then just record the command and return.
2183 if (block_command_execution_) {
2184 // We actually only allow no more than one blocked command, otherwise some
2185 // commands maybe lost.
[email protected]5dcbc02f2010-01-26 22:32:062186 DCHECK_EQ(last_blocked_command_id_, -1);
[email protected]867125a02009-12-10 06:01:482187 last_blocked_command_id_ = id;
2188 last_blocked_command_disposition_ = disposition;
2189 return;
2190 }
2191
[email protected]fbd77592008-11-12 20:50:272192 // The order of commands in this switch statement must match the function
2193 // declaration order in browser.h!
[email protected]36b6dcb2008-11-12 01:19:572194 switch (id) {
[email protected]84214982008-12-10 18:49:102195 // Navigation commands
[email protected]cb84d642010-06-10 00:56:282196 case IDC_BACK: GoBack(disposition); break;
2197 case IDC_FORWARD: GoForward(disposition); break;
2198 case IDC_RELOAD: Reload(disposition); break;
2199 case IDC_RELOAD_IGNORING_CACHE: ReloadIgnoringCache(disposition); break;
2200 case IDC_HOME: Home(disposition); break;
2201 case IDC_OPEN_CURRENT_URL: OpenCurrentURL(); break;
[email protected]cb84d642010-06-10 00:56:282202 case IDC_STOP: Stop(); break;
[email protected]36b6dcb2008-11-12 01:19:572203
[email protected]84214982008-12-10 18:49:102204 // Window management commands
[email protected]cb84d642010-06-10 00:56:282205 case IDC_NEW_WINDOW: NewWindow(); break;
2206 case IDC_NEW_INCOGNITO_WINDOW: NewIncognitoWindow(); break;
[email protected]cb84d642010-06-10 00:56:282207 case IDC_CLOSE_WINDOW: CloseWindow(); break;
2208 case IDC_NEW_TAB: NewTab(); break;
2209 case IDC_CLOSE_TAB: CloseTab(); break;
2210 case IDC_SELECT_NEXT_TAB: SelectNextTab(); break;
2211 case IDC_SELECT_PREVIOUS_TAB: SelectPreviousTab(); break;
[email protected]91ac9202010-07-30 18:32:352212 case IDC_TABPOSE: OpenTabpose(); break;
[email protected]cb84d642010-06-10 00:56:282213 case IDC_MOVE_TAB_NEXT: MoveTabNext(); break;
2214 case IDC_MOVE_TAB_PREVIOUS: MoveTabPrevious(); break;
[email protected]36b6dcb2008-11-12 01:19:572215 case IDC_SELECT_TAB_0:
2216 case IDC_SELECT_TAB_1:
2217 case IDC_SELECT_TAB_2:
2218 case IDC_SELECT_TAB_3:
2219 case IDC_SELECT_TAB_4:
2220 case IDC_SELECT_TAB_5:
2221 case IDC_SELECT_TAB_6:
[email protected]cb525c82008-12-08 23:04:542222 case IDC_SELECT_TAB_7: SelectNumberedTab(id - IDC_SELECT_TAB_0);
[email protected]cb84d642010-06-10 00:56:282223 break;
2224 case IDC_SELECT_LAST_TAB: SelectLastTab(); break;
2225 case IDC_DUPLICATE_TAB: DuplicateTab(); break;
2226 case IDC_RESTORE_TAB: RestoreTab(); break;
2227 case IDC_COPY_URL: WriteCurrentURLToClipboard(); break;
2228 case IDC_SHOW_AS_TAB: ConvertPopupToTabbedBrowser(); break;
2229 case IDC_FULLSCREEN: ToggleFullscreenMode(); break;
2230 case IDC_EXIT: Exit(); break;
2231 case IDC_TOGGLE_VERTICAL_TABS: ToggleUseVerticalTabs(); break;
[email protected]da17b372010-01-22 23:37:222232#if defined(OS_CHROMEOS)
[email protected]cb84d642010-06-10 00:56:282233 case IDC_SEARCH: Search(); break;
[email protected]d14af522010-12-02 03:54:502234 case IDC_SHOW_KEYBOARD_OVERLAY: ShowKeyboardOverlay(); break;
[email protected]20d17242009-10-26 20:21:052235#endif
[email protected]36b6dcb2008-11-12 01:19:572236
[email protected]84214982008-12-10 18:49:102237 // Page-related commands
[email protected]cb84d642010-06-10 00:56:282238 case IDC_SAVE_PAGE: SavePage(); break;
2239 case IDC_BOOKMARK_PAGE: BookmarkCurrentPage(); break;
2240 case IDC_BOOKMARK_ALL_TABS: BookmarkAllTabs(); break;
[email protected]77d8d622010-12-15 10:30:122241 case IDC_VIEW_SOURCE: ViewSelectedSource(); break;
[email protected]cb84d642010-06-10 00:56:282242 case IDC_EMAIL_PAGE_LOCATION: EmailPageLocation(); break;
2243 case IDC_PRINT: Print(); break;
2244 case IDC_ENCODING_AUTO_DETECT: ToggleEncodingAutoDetect(); break;
[email protected]36b6dcb2008-11-12 01:19:572245 case IDC_ENCODING_UTF8:
2246 case IDC_ENCODING_UTF16LE:
2247 case IDC_ENCODING_ISO88591:
2248 case IDC_ENCODING_WINDOWS1252:
[email protected]1c5bf632008-12-11 20:30:492249 case IDC_ENCODING_GBK:
[email protected]36b6dcb2008-11-12 01:19:572250 case IDC_ENCODING_GB18030:
2251 case IDC_ENCODING_BIG5HKSCS:
2252 case IDC_ENCODING_BIG5:
2253 case IDC_ENCODING_KOREAN:
2254 case IDC_ENCODING_SHIFTJIS:
2255 case IDC_ENCODING_ISO2022JP:
2256 case IDC_ENCODING_EUCJP:
2257 case IDC_ENCODING_THAI:
2258 case IDC_ENCODING_ISO885915:
2259 case IDC_ENCODING_MACINTOSH:
2260 case IDC_ENCODING_ISO88592:
2261 case IDC_ENCODING_WINDOWS1250:
2262 case IDC_ENCODING_ISO88595:
2263 case IDC_ENCODING_WINDOWS1251:
2264 case IDC_ENCODING_KOI8R:
2265 case IDC_ENCODING_KOI8U:
2266 case IDC_ENCODING_ISO88597:
2267 case IDC_ENCODING_WINDOWS1253:
2268 case IDC_ENCODING_ISO88594:
2269 case IDC_ENCODING_ISO885913:
2270 case IDC_ENCODING_WINDOWS1257:
2271 case IDC_ENCODING_ISO88593:
2272 case IDC_ENCODING_ISO885910:
2273 case IDC_ENCODING_ISO885914:
2274 case IDC_ENCODING_ISO885916:
[email protected]36b6dcb2008-11-12 01:19:572275 case IDC_ENCODING_WINDOWS1254:
2276 case IDC_ENCODING_ISO88596:
2277 case IDC_ENCODING_WINDOWS1256:
2278 case IDC_ENCODING_ISO88598:
[email protected]e13271f2009-03-07 00:26:002279 case IDC_ENCODING_ISO88598I:
[email protected]36b6dcb2008-11-12 01:19:572280 case IDC_ENCODING_WINDOWS1255:
[email protected]cb84d642010-06-10 00:56:282281 case IDC_ENCODING_WINDOWS1258: OverrideEncoding(id); break;
[email protected]36b6dcb2008-11-12 01:19:572282
[email protected]84214982008-12-10 18:49:102283 // Clipboard commands
[email protected]cb84d642010-06-10 00:56:282284 case IDC_CUT: Cut(); break;
2285 case IDC_COPY: Copy(); break;
2286 case IDC_PASTE: Paste(); break;
[email protected]84214982008-12-10 18:49:102287
2288 // Find-in-page
[email protected]cb84d642010-06-10 00:56:282289 case IDC_FIND: Find(); break;
2290 case IDC_FIND_NEXT: FindNext(); break;
2291 case IDC_FIND_PREVIOUS: FindPrevious(); break;
[email protected]84214982008-12-10 18:49:102292
2293 // Zoom
[email protected]cb84d642010-06-10 00:56:282294 case IDC_ZOOM_PLUS: Zoom(PageZoom::ZOOM_IN); break;
2295 case IDC_ZOOM_NORMAL: Zoom(PageZoom::RESET); break;
2296 case IDC_ZOOM_MINUS: Zoom(PageZoom::ZOOM_OUT); break;
[email protected]84214982008-12-10 18:49:102297
2298 // Focus various bits of UI
[email protected]cb84d642010-06-10 00:56:282299 case IDC_FOCUS_TOOLBAR: FocusToolbar(); break;
2300 case IDC_FOCUS_LOCATION: FocusLocationBar(); break;
2301 case IDC_FOCUS_SEARCH: FocusSearch(); break;
[email protected]bdb7ff62010-07-20 01:56:522302 case IDC_FOCUS_MENU_BAR: FocusAppMenu(); break;
[email protected]83548a42010-06-18 13:53:372303 case IDC_FOCUS_BOOKMARKS: FocusBookmarksToolbar(); break;
2304 case IDC_FOCUS_CHROMEOS_STATUS: FocusChromeOSStatus(); break;
2305 case IDC_FOCUS_NEXT_PANE: FocusNextPane(); break;
2306 case IDC_FOCUS_PREVIOUS_PANE: FocusPreviousPane(); break;
[email protected]84214982008-12-10 18:49:102307
2308 // Show various bits of UI
[email protected]cb84d642010-06-10 00:56:282309 case IDC_OPEN_FILE: OpenFile(); break;
2310 case IDC_CREATE_SHORTCUTS: OpenCreateShortcutsDialog(); break;
[email protected]2a8a98122010-07-16 11:58:482311 case IDC_DEV_TOOLS: ToggleDevToolsWindow(
2312 DEVTOOLS_TOGGLE_ACTION_NONE);
2313 break;
2314 case IDC_DEV_TOOLS_CONSOLE: ToggleDevToolsWindow(
2315 DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE);
2316 break;
2317 case IDC_DEV_TOOLS_INSPECT: ToggleDevToolsWindow(
2318 DEVTOOLS_TOGGLE_ACTION_INSPECT);
2319 break;
[email protected]adb6a84d2011-02-07 16:58:402320 case IDC_TASK_MANAGER: OpenTaskManager(false); break;
2321 case IDC_VIEW_BACKGROUND_PAGES: OpenTaskManager(true); break;
[email protected]1c41a932010-11-22 23:41:232322 case IDC_FEEDBACK: OpenBugReportDialog(); break;
[email protected]44b2c8852009-03-18 00:57:492323
[email protected]cb84d642010-06-10 00:56:282324 case IDC_SHOW_BOOKMARK_BAR: ToggleBookmarkBar(); break;
[email protected]7664ab32011-02-01 23:35:252325 case IDC_PROFILING_ENABLED: Profiling::Toggle(); break;
[email protected]44b2c8852009-03-18 00:57:492326
[email protected]cb84d642010-06-10 00:56:282327 case IDC_SHOW_BOOKMARK_MANAGER: OpenBookmarkManager(); break;
2328 case IDC_SHOW_APP_MENU: ShowAppMenu(); break;
[email protected]cb84d642010-06-10 00:56:282329 case IDC_SHOW_HISTORY: ShowHistoryTab(); break;
2330 case IDC_SHOW_DOWNLOADS: ShowDownloadsTab(); break;
2331 case IDC_MANAGE_EXTENSIONS: ShowExtensionsTab(); break;
2332 case IDC_SYNC_BOOKMARKS: OpenSyncMyBookmarksDialog(); break;
2333 case IDC_OPTIONS: OpenOptionsDialog(); break;
[email protected]445177652011-03-09 02:04:052334 case IDC_EDIT_SEARCH_ENGINES: OpenSearchEngineOptionsDialog(); break;
[email protected]cb84d642010-06-10 00:56:282335 case IDC_VIEW_PASSWORDS: OpenPasswordManager(); break;
2336 case IDC_CLEAR_BROWSING_DATA: OpenClearBrowsingDataDialog(); break;
2337 case IDC_IMPORT_SETTINGS: OpenImportSettingsDialog(); break;
[email protected]b21d6912010-08-31 19:22:412338 case IDC_ABOUT: OpenAboutChromeDialog(); break;
2339 case IDC_UPGRADE_DIALOG: OpenUpdateChromeDialog(); break;
[email protected]c1bbaa82010-11-08 11:17:052340 case IDC_VIEW_INCOMPATIBILITIES: ShowAboutConflictsTab(); break;
[email protected]cb84d642010-06-10 00:56:282341 case IDC_HELP_PAGE: OpenHelpTab(); break;
[email protected]16779842009-07-08 23:45:292342#if defined(OS_CHROMEOS)
[email protected]cb84d642010-06-10 00:56:282343 case IDC_SYSTEM_OPTIONS: OpenSystemOptionsDialog(); break;
2344 case IDC_INTERNET_OPTIONS: OpenInternetOptionsDialog(); break;
[email protected]024617a2010-08-20 05:08:052345 case IDC_LANGUAGE_OPTIONS: OpenLanguageOptionsDialog(); break;
[email protected]be715072009-07-07 15:43:202346#endif
[email protected]d938aed92009-01-22 19:49:332347
[email protected]36b6dcb2008-11-12 01:19:572348 default:
[email protected]84214982008-12-10 18:49:102349 LOG(WARNING) << "Received Unimplemented Command: " << id;
[email protected]fbd77592008-11-12 20:50:272350 break;
[email protected]36b6dcb2008-11-12 01:19:572351 }
2352}
2353
[email protected]3ab6796d32010-12-21 23:56:072354bool Browser::ExecuteCommandIfEnabled(int id) {
2355 if (command_updater_.SupportsCommand(id) &&
2356 command_updater_.IsCommandEnabled(id)) {
2357 ExecuteCommand(id);
2358 return true;
2359 }
2360 return false;
2361}
2362
[email protected]06181422011-02-09 17:44:212363bool Browser::IsReservedCommandOrKey(int command_id,
2364 const NativeWebKeyboardEvent& event) {
[email protected]06181422011-02-09 17:44:212365#if defined(OS_CHROMEOS)
2366 // Chrome OS's top row of keys produces F1-10. Make sure that web pages
2367 // aren't able to block Chrome from performing the standard actions for F1-F4
2368 // (F5-7 are grabbed by other X clients and hence don't need this protection,
2369 // and F8-10 are handled separately in Chrome via a GDK event filter, but
2370 // let's future-proof this).
2371 ui::KeyboardCode key_code =
[email protected]6a1ae6cd2011-02-11 20:06:092372 static_cast<ui::KeyboardCode>(event.windowsKeyCode);
[email protected]06181422011-02-09 17:44:212373 if (key_code == ui::VKEY_F1 ||
2374 key_code == ui::VKEY_F2 ||
2375 key_code == ui::VKEY_F3 ||
2376 key_code == ui::VKEY_F4 ||
2377 key_code == ui::VKEY_F5 ||
2378 key_code == ui::VKEY_F6 ||
2379 key_code == ui::VKEY_F7 ||
2380 key_code == ui::VKEY_F8 ||
2381 key_code == ui::VKEY_F9 ||
2382 key_code == ui::VKEY_F10) {
[email protected]6a1ae6cd2011-02-11 20:06:092383 return true;
[email protected]06181422011-02-09 17:44:212384 }
2385#endif
2386
[email protected]6a1ae6cd2011-02-11 20:06:092387 return command_id == IDC_CLOSE_TAB ||
[email protected]867125a02009-12-10 06:01:482388 command_id == IDC_CLOSE_WINDOW ||
2389 command_id == IDC_NEW_INCOGNITO_WINDOW ||
2390 command_id == IDC_NEW_TAB ||
2391 command_id == IDC_NEW_WINDOW ||
2392 command_id == IDC_RESTORE_TAB ||
2393 command_id == IDC_SELECT_NEXT_TAB ||
2394 command_id == IDC_SELECT_PREVIOUS_TAB ||
[email protected]c1d0d812010-07-27 20:21:552395 command_id == IDC_TABPOSE ||
[email protected]f97d7f632010-06-01 21:08:332396 command_id == IDC_EXIT ||
2397 command_id == IDC_SEARCH;
[email protected]867125a02009-12-10 06:01:482398}
2399
2400void Browser::SetBlockCommandExecution(bool block) {
2401 block_command_execution_ = block;
2402 if (block) {
2403 last_blocked_command_id_ = -1;
2404 last_blocked_command_disposition_ = CURRENT_TAB;
2405 }
2406}
2407
2408int Browser::GetLastBlockedCommand(WindowOpenDisposition* disposition) {
2409 if (disposition)
2410 *disposition = last_blocked_command_disposition_;
2411 return last_blocked_command_id_;
2412}
2413
[email protected]3c9e1872010-11-18 16:17:492414void Browser::UpdateUIForNavigationInTab(TabContentsWrapper* contents,
[email protected]19d9f3a2010-10-14 21:49:362415 PageTransition::Type transition,
2416 bool user_initiated) {
2417 tabstrip_model()->TabNavigating(contents, transition);
2418
[email protected]3c9e1872010-11-18 16:17:492419 bool contents_is_selected = contents == GetSelectedTabContentsWrapper();
[email protected]19d9f3a2010-10-14 21:49:362420 if (user_initiated && contents_is_selected && window()->GetLocationBar()) {
2421 // Forcibly reset the location bar if the url is going to change in the
2422 // current tab, since otherwise it won't discard any ongoing user edits,
2423 // since it doesn't realize this is a user-initiated action.
2424 window()->GetLocationBar()->Revert();
2425 }
2426
2427 if (GetStatusBubble())
2428 GetStatusBubble()->Hide();
2429
2430 // Update the location bar. This is synchronous. We specifically don't
2431 // update the load state since the load hasn't started yet and updating it
2432 // will put it out of sync with the actual state like whether we're
2433 // displaying a favicon, which controls the throbber. If we updated it here,
2434 // the throbber will show the default favicon for a split second when
2435 // navigating away from the new tab page.
[email protected]3c9e1872010-11-18 16:17:492436 ScheduleUIUpdate(contents->tab_contents(), TabContents::INVALIDATE_URL);
[email protected]19d9f3a2010-10-14 21:49:362437
2438 if (contents_is_selected)
[email protected]3c9e1872010-11-18 16:17:492439 contents->tab_contents()->Focus();
[email protected]19d9f3a2010-10-14 21:49:362440}
2441
2442GURL Browser::GetHomePage() const {
2443 // --homepage overrides any preferences.
2444 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
2445 if (command_line.HasSwitch(switches::kHomePage)) {
[email protected]a8e4b5a82010-10-27 00:05:472446 // TODO(evanm): clean up usage of DIR_CURRENT.
2447 // http://code.google.com/p/chromium/issues/detail?id=60630
2448 // For now, allow this code to call getcwd().
2449 base::ThreadRestrictions::ScopedAllowIO allow_io;
2450
[email protected]19d9f3a2010-10-14 21:49:362451 FilePath browser_directory;
2452 PathService::Get(base::DIR_CURRENT, &browser_directory);
2453 GURL home_page(URLFixerUpper::FixupRelativeFile(browser_directory,
2454 command_line.GetSwitchValuePath(switches::kHomePage)));
2455 if (home_page.is_valid())
2456 return home_page;
2457 }
2458
2459 if (profile_->GetPrefs()->GetBoolean(prefs::kHomePageIsNewTabPage))
2460 return GURL(chrome::kChromeUINewTabURL);
2461 GURL home_page(URLFixerUpper::FixupURL(
2462 profile_->GetPrefs()->GetString(prefs::kHomePage),
2463 std::string()));
2464 if (!home_page.is_valid())
2465 return GURL(chrome::kChromeUINewTabURL);
2466 return home_page;
2467}
2468
[email protected]36b6dcb2008-11-12 01:19:572469///////////////////////////////////////////////////////////////////////////////
[email protected]ecc523f62010-09-28 22:45:402470// Browser, PageNavigator implementation:
[email protected]19d9f3a2010-10-14 21:49:362471
[email protected]ecc523f62010-09-28 22:45:402472void Browser::OpenURL(const GURL& url, const GURL& referrer,
2473 WindowOpenDisposition disposition,
2474 PageTransition::Type transition) {
2475 OpenURLFromTab(NULL, url, referrer, disposition, transition);
2476}
2477
2478///////////////////////////////////////////////////////////////////////////////
[email protected]485fba42009-03-24 23:27:292479// Browser, CommandUpdater::CommandUpdaterDelegate implementation:
2480
2481void Browser::ExecuteCommand(int id) {
2482 ExecuteCommandWithDisposition(id, CURRENT_TAB);
2483}
2484
2485///////////////////////////////////////////////////////////////////////////////
[email protected]ecc523f62010-09-28 22:45:402486// Browser, TabHandlerDelegate implementation:
2487
2488Profile* Browser::GetProfile() const {
2489 return profile();
2490}
2491
2492Browser* Browser::AsBrowser() {
2493 return this;
2494}
2495
2496///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:572497// Browser, TabStripModelDelegate implementation:
2498
[email protected]3c9e1872010-11-18 16:17:492499TabContentsWrapper* Browser::AddBlankTab(bool foreground) {
[email protected]22735af62009-04-07 21:09:582500 return AddBlankTabAt(-1, foreground);
2501}
2502
[email protected]3c9e1872010-11-18 16:17:492503TabContentsWrapper* Browser::AddBlankTabAt(int index, bool foreground) {
[email protected]3f8eb7f2009-10-02 23:58:052504 // Time new tab page creation time. We keep track of the timing data in
2505 // TabContents, but we want to include the time it takes to create the
2506 // TabContents object too.
2507 base::TimeTicks new_tab_start_time = base::TimeTicks::Now();
[email protected]616381f02010-11-02 15:15:332508 browser::NavigateParams params(this, GURL(chrome::kChromeUINewTabURL),
2509 PageTransition::TYPED);
[email protected]616381f02010-11-02 15:15:332510 params.disposition = foreground ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
2511 params.tabstrip_index = index;
2512 browser::Navigate(&params);
[email protected]3c9e1872010-11-18 16:17:492513 params.target_contents->tab_contents()->set_new_tab_start_time(
2514 new_tab_start_time);
[email protected]616381f02010-11-02 15:15:332515 return params.target_contents;
[email protected]15952e462008-11-14 00:29:052516}
2517
[email protected]3c9e1872010-11-18 16:17:492518Browser* Browser::CreateNewStripWithContents(
2519 TabContentsWrapper* detached_contents,
2520 const gfx::Rect& window_bounds,
2521 const DockInfo& dock_info,
2522 bool maximize) {
[email protected]018cf362010-05-05 22:43:222523 DCHECK(CanSupportWindowFeature(FEATURE_TABSTRIP));
[email protected]adf650f2008-12-09 16:10:062524
[email protected]5e495462008-11-20 23:07:412525 gfx::Rect new_window_bounds = window_bounds;
[email protected]5e495462008-11-20 23:07:412526 if (dock_info.GetNewWindowBounds(&new_window_bounds, &maximize))
2527 dock_info.AdjustOtherWindowBounds();
2528
[email protected]36b6dcb2008-11-12 01:19:572529 // Create an empty new browser window the same size as the old one.
[email protected]299dabd2008-11-19 02:27:162530 Browser* browser = new Browser(TYPE_NORMAL, profile_);
[email protected]5e495462008-11-20 23:07:412531 browser->set_override_bounds(new_window_bounds);
[email protected]2e716622009-03-09 21:11:012532 browser->set_maximized_state(
2533 maximize ? MAXIMIZED_STATE_MAXIMIZED : MAXIMIZED_STATE_UNMAXIMIZED);
[email protected]9800de5e2011-03-11 18:19:492534 browser->InitBrowserWindow();
[email protected]15952e462008-11-14 00:29:052535 browser->tabstrip_model()->AppendTabContents(detached_contents, true);
[email protected]159f7762008-12-19 14:58:272536 // Make sure the loading state is updated correctly, otherwise the throbber
2537 // won't start if the page is loading.
[email protected]3c9e1872010-11-18 16:17:492538 browser->LoadingStateChanged(detached_contents->tab_contents());
[email protected]3d1104f2009-03-26 15:30:282539 return browser;
[email protected]36b6dcb2008-11-12 01:19:572540}
2541
2542int Browser::GetDragActions() const {
[email protected]ecc523f62010-09-28 22:45:402543 return TabStripModelDelegate::TAB_TEAROFF_ACTION | (tab_count() > 1 ?
2544 TabStripModelDelegate::TAB_MOVE_ACTION : 0);
[email protected]36b6dcb2008-11-12 01:19:572545}
2546
[email protected]3c9e1872010-11-18 16:17:492547TabContentsWrapper* Browser::CreateTabContentsForURL(
[email protected]36b6dcb2008-11-12 01:19:572548 const GURL& url, const GURL& referrer, Profile* profile,
2549 PageTransition::Type transition, bool defer_load,
2550 SiteInstance* instance) const {
[email protected]3c9e1872010-11-18 16:17:492551 TabContentsWrapper* contents = TabContentsFactory(profile, instance,
[email protected]ecc523f62010-09-28 22:45:402552 MSG_ROUTING_NONE,
[email protected]3c9e1872010-11-18 16:17:492553 GetSelectedTabContents(), NULL);
[email protected]36b6dcb2008-11-12 01:19:572554 if (!defer_load) {
2555 // Load the initial URL before adding the new tab contents to the tab strip
2556 // so that the tab contents has navigation state.
[email protected]ce3fa3c2009-04-20 19:55:572557 contents->controller().LoadURL(url, referrer, transition);
[email protected]36b6dcb2008-11-12 01:19:572558 }
2559
2560 return contents;
2561}
2562
2563bool Browser::CanDuplicateContentsAt(int index) {
[email protected]ce3fa3c2009-04-20 19:55:572564 NavigationController& nc = GetTabContentsAt(index)->controller();
2565 return nc.tab_contents() && nc.GetLastCommittedEntry();
[email protected]36b6dcb2008-11-12 01:19:572566}
2567
2568void Browser::DuplicateContentsAt(int index) {
[email protected]3c9e1872010-11-18 16:17:492569 TabContentsWrapper* contents = GetTabContentsWrapperAt(index);
[email protected]94ce7252010-12-20 21:46:332570 CHECK(contents);
[email protected]77d8d622010-12-15 10:30:122571 TabContentsWrapper* contents_dupe = contents->Clone();
[email protected]47b309f2010-12-28 17:35:562572 TabContents* new_contents = contents_dupe->tab_contents();
2573
2574 bool pinned = false;
2575 if (CanSupportWindowFeature(FEATURE_TABSTRIP)) {
2576 // If this is a tabbed browser, just create a duplicate tab inside the same
2577 // window next to the tab being duplicated.
2578 int index = tab_handler_->GetTabStripModel()->
2579 GetIndexOfTabContents(contents);
2580 pinned = tab_handler_->GetTabStripModel()->IsTabPinned(index);
2581 int add_types = TabStripModel::ADD_SELECTED |
2582 TabStripModel::ADD_INHERIT_GROUP |
2583 (pinned ? TabStripModel::ADD_PINNED : 0);
2584 tab_handler_->GetTabStripModel()->InsertTabContentsAt(index + 1,
2585 contents_dupe,
2586 add_types);
2587 } else {
2588 Browser* browser = NULL;
2589 if (type_ & TYPE_APP) {
2590 CHECK((type_ & TYPE_POPUP) == 0);
2591 CHECK(type_ != TYPE_APP_PANEL);
2592 browser = Browser::CreateForApp(app_name_, gfx::Size(), profile_,
2593 false);
2594 } else if (type_ == TYPE_POPUP) {
2595 browser = Browser::CreateForType(TYPE_POPUP, profile_);
2596 }
2597
2598 // Preserve the size of the original window. The new window has already
2599 // been given an offset by the OS, so we shouldn't copy the old bounds.
2600 BrowserWindow* new_window = browser->window();
2601 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
2602 window()->GetRestoredBounds().size()));
2603
[email protected]4e595682011-02-09 17:07:022604 // We need to show the browser now. Otherwise ContainerWin assumes the
[email protected]47b309f2010-12-28 17:35:562605 // TabContents is invisible and won't size it.
2606 browser->window()->Show();
2607
2608 // The page transition below is only for the purpose of inserting the tab.
2609 browser->AddTab(contents_dupe, PageTransition::LINK);
2610 }
2611
2612 if (profile_->HasSessionService()) {
2613 SessionService* session_service = profile_->GetSessionService();
2614 if (session_service)
2615 session_service->TabRestored(&new_contents->controller(), pinned);
2616 }
[email protected]36b6dcb2008-11-12 01:19:572617}
2618
[email protected]36b6dcb2008-11-12 01:19:572619void Browser::CloseFrameAfterDragSession() {
[email protected]9aefecc92009-06-10 21:31:322620#if defined(OS_WIN) || defined(OS_LINUX)
[email protected]36b6dcb2008-11-12 01:19:572621 // This is scheduled to run after we return to the message loop because
2622 // otherwise the frame will think the drag session is still active and ignore
2623 // the request.
[email protected]d6a3c772009-01-27 19:41:202624 // TODO(port): figure out what is required here in a cross-platform world
[email protected]0586b0e2010-02-12 21:38:372625 MessageLoop::current()->PostTask(
2626 FROM_HERE, method_factory_.NewRunnableMethod(&Browser::CloseFrame));
[email protected]d6a3c772009-01-27 19:41:202627#endif
initial.commit09911bf2008-07-26 23:55:292628}
2629
[email protected]3c9e1872010-11-18 16:17:492630void Browser::CreateHistoricalTab(TabContentsWrapper* contents) {
[email protected]505323e22009-01-24 02:47:582631 // We don't create historical tabs for incognito windows or windows without
2632 // profiles.
2633 if (!profile() || profile()->IsOffTheRecord() ||
2634 !profile()->GetTabRestoreService()) {
2635 return;
2636 }
2637
[email protected]fb5ff422010-05-03 20:46:102638 // We only create historical tab entries for tabbed browser windows.
[email protected]018cf362010-05-05 22:43:222639 if (CanSupportWindowFeature(FEATURE_TABSTRIP)) {
[email protected]505323e22009-01-24 02:47:582640 profile()->GetTabRestoreService()->CreateHistoricalTab(
[email protected]fb7da4132011-03-15 15:51:002641 &contents->controller(),
2642 tab_handler_->GetTabStripModel()->GetIndexOfTabContents(contents));
[email protected]505323e22009-01-24 02:47:582643 }
2644}
2645
[email protected]3c9e1872010-11-18 16:17:492646bool Browser::RunUnloadListenerBeforeClosing(TabContentsWrapper* contents) {
2647 return Browser::RunUnloadEventsHelper(contents->tab_contents());
[email protected]505323e22009-01-24 02:47:582648}
2649
[email protected]8e48e982009-12-25 11:22:462650bool Browser::CanReloadContents(TabContents* source) const {
2651 return type() != TYPE_DEVTOOLS;
2652}
2653
[email protected]940ccb22009-04-30 17:11:102654bool Browser::CanCloseContentsAt(int index) {
[email protected]0b4d3382010-07-14 16:13:042655 if (!CanCloseTab())
2656 return false;
[email protected]ecc523f62010-09-28 22:45:402657 if (tab_handler_->GetTabStripModel()->count() > 1)
[email protected]940ccb22009-04-30 17:11:102658 return true;
2659 // We are closing the last tab for this browser. Make sure to check for
2660 // in-progress downloads.
2661 // Note that the next call when it returns false will ask the user for
2662 // confirmation before closing the browser if the user decides so.
2663 return CanCloseWithInProgressDownloads();
2664}
[email protected]d6a3c772009-01-27 19:41:202665
[email protected]a206b442009-10-08 23:20:202666bool Browser::CanBookmarkAllTabs() const {
2667 BookmarkModel* model = profile()->GetBookmarkModel();
[email protected]76624fde2009-10-09 18:13:232668 return (model && model->IsLoaded() && (tab_count() > 1));
[email protected]a206b442009-10-08 23:20:202669}
2670
[email protected]b3ac5c82009-10-08 20:56:542671void Browser::BookmarkAllTabs() {
[email protected]ec12ffe2009-10-16 22:28:442672 BookmarkModel* model = profile()->GetBookmarkModel();
2673 DCHECK(model && model->IsLoaded());
2674
2675 BookmarkEditor::EditDetails details;
2676 details.type = BookmarkEditor::EditDetails::NEW_FOLDER;
2677 bookmark_utils::GetURLsForOpenTabs(this, &(details.urls));
2678 DCHECK(!details.urls.empty());
[email protected]b3ac5c82009-10-08 20:56:542679
[email protected]b3ac5c82009-10-08 20:56:542680 BookmarkEditor::Show(window()->GetNativeHandle(), profile_,
[email protected]ec12ffe2009-10-16 22:28:442681 model->GetParentForNewNodes(), details,
[email protected]97a056462010-04-28 16:46:352682 BookmarkEditor::SHOW_TREE);
[email protected]b3ac5c82009-10-08 20:56:542683}
2684
[email protected]0b4d3382010-07-14 16:13:042685bool Browser::CanCloseTab() const {
2686 TabCloseableStateWatcher* watcher =
2687 g_browser_process->tab_closeable_state_watcher();
2688 return !watcher || watcher->CanCloseTab(this);
2689}
2690
[email protected]b9c505b2010-04-30 15:05:102691void Browser::ToggleUseVerticalTabs() {
2692 use_vertical_tabs_.SetValue(!UseVerticalTabs());
[email protected]b3344872010-05-03 15:52:292693 UseVerticalTabsChanged();
[email protected]b9c505b2010-04-30 15:05:102694}
2695
[email protected]b283a7532010-08-12 21:24:592696bool Browser::LargeIconsPermitted() const {
[email protected]af801acd2010-08-20 20:27:442697 // We don't show the big icons in tabs for TYPE_EXTENSION_APP windows because
2698 // for those windows, we already have a big icon in the top-left outside any
2699 // tab. Having big tab icons too looks kinda redonk.
[email protected]94ce7252010-12-20 21:46:332700 return true;
[email protected]b283a7532010-08-12 21:24:592701}
2702
[email protected]2d46c842008-11-14 19:24:312703///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:572704// Browser, TabStripModelObserver implementation:
2705
[email protected]3c9e1872010-11-18 16:17:492706void Browser::TabInsertedAt(TabContentsWrapper* contents,
[email protected]36b6dcb2008-11-12 01:19:572707 int index,
2708 bool foreground) {
[email protected]9219d262011-02-15 21:05:122709 SetAsDelegate(contents, this);
[email protected]ce3fa3c2009-04-20 19:55:572710 contents->controller().SetWindowID(session_id());
[email protected]36b6dcb2008-11-12 01:19:572711
[email protected]e524ff92011-03-30 13:26:582712 // Each renderer holds the ID of the window that hosts it. Notify the
2713 // renderer that the window ID changed.
2714 contents->render_view_host()->UpdateBrowserWindowId(
2715 contents->controller().window_id().id());
2716
[email protected]c37e3b62010-01-22 00:15:172717 SyncHistoryWithTabs(index);
[email protected]36b6dcb2008-11-12 01:19:572718
[email protected]159f7762008-12-19 14:58:272719 // Make sure the loading state is updated correctly, otherwise the throbber
2720 // won't start if the page is loading.
[email protected]3c9e1872010-11-18 16:17:492721 LoadingStateChanged(contents->tab_contents());
[email protected]159f7762008-12-19 14:58:272722
[email protected]36b6dcb2008-11-12 01:19:572723 // If the tab crashes in the beforeunload or unload handler, it won't be
2724 // able to ack. But we know we can close it.
[email protected]0cb94102009-05-22 19:51:212725 registrar_.Add(this, NotificationType::TAB_CONTENTS_DISCONNECTED,
[email protected]3c9e1872010-11-18 16:17:492726 Source<TabContentsWrapper>(contents));
[email protected]36b6dcb2008-11-12 01:19:572727}
2728
[email protected]f2cc7382010-10-15 18:03:052729void Browser::TabClosingAt(TabStripModel* tab_strip_model,
[email protected]3c9e1872010-11-18 16:17:492730 TabContentsWrapper* contents,
[email protected]f2cc7382010-10-15 18:03:052731 int index) {
[email protected]bfd04a62009-02-01 18:16:562732 NotificationService::current()->Notify(
2733 NotificationType::TAB_CLOSING,
[email protected]ce3fa3c2009-04-20 19:55:572734 Source<NavigationController>(&contents->controller()),
[email protected]bfd04a62009-02-01 18:16:562735 NotificationService::NoDetails());
[email protected]36b6dcb2008-11-12 01:19:572736
2737 // Sever the TabContents' connection back to us.
[email protected]9219d262011-02-15 21:05:122738 SetAsDelegate(contents, NULL);
[email protected]36b6dcb2008-11-12 01:19:572739}
2740
[email protected]3c9e1872010-11-18 16:17:492741void Browser::TabDetachedAt(TabContentsWrapper* contents, int index) {
[email protected]c37e3b62010-01-22 00:15:172742 TabDetachedAtImpl(contents, index, DETACH_TYPE_DETACH);
[email protected]36b6dcb2008-11-12 01:19:572743}
2744
[email protected]2ab3fa92011-02-27 21:46:512745void Browser::TabDeselected(TabContentsWrapper* contents) {
[email protected]6b723f82010-10-05 20:14:272746 if (instant())
2747 instant()->DestroyPreviewContents();
[email protected]03bb953d2010-09-14 21:38:302748
[email protected]85ff2c42009-05-29 21:22:032749 // Save what the user's currently typing, so it can be restored when we
2750 // switch back to this tab.
[email protected]3c9e1872010-11-18 16:17:492751 window_->GetLocationBar()->SaveStateToContents(contents->tab_contents());
[email protected]85ff2c42009-05-29 21:22:032752}
2753
[email protected]3c9e1872010-11-18 16:17:492754void Browser::TabSelectedAt(TabContentsWrapper* old_contents,
2755 TabContentsWrapper* new_contents,
[email protected]36b6dcb2008-11-12 01:19:572756 int index,
2757 bool user_gesture) {
[email protected]02cd2bf2011-03-02 21:45:562758 if (old_contents == new_contents)
2759 return;
[email protected]36b6dcb2008-11-12 01:19:572760
[email protected]a8f024392011-01-13 21:50:162761 // On some platforms we want to automatically reload tabs that are
2762 // killed when the user selects them.
2763 if (user_gesture && new_contents->tab_contents()->crashed_status() ==
2764 base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
2765 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
[email protected]f8a35772011-02-02 23:17:562766 if (parsed_command_line.HasSwitch(switches::kReloadKilledTabs)) {
[email protected]a8f024392011-01-13 21:50:162767 Reload(CURRENT_TAB);
[email protected]f8a35772011-02-02 23:17:562768 return;
2769 }
[email protected]a8f024392011-01-13 21:50:162770 }
2771
[email protected]36b6dcb2008-11-12 01:19:572772 // If we have any update pending, do it now.
2773 if (!chrome_updater_factory_.empty() && old_contents)
2774 ProcessPendingUIUpdates();
2775
[email protected]36b6dcb2008-11-12 01:19:572776 // Propagate the profile to the location bar.
2777 UpdateToolbar(true);
2778
[email protected]943d8122010-06-11 02:13:452779 // Update reload/stop state.
[email protected]3c9e1872010-11-18 16:17:492780 UpdateReloadStopState(new_contents->tab_contents()->is_loading(), true);
[email protected]36b6dcb2008-11-12 01:19:572781
[email protected]84214982008-12-10 18:49:102782 // Update commands to reflect current state.
2783 UpdateCommandsForTabState();
[email protected]36b6dcb2008-11-12 01:19:572784
2785 // Reset the status bubble.
[email protected]be3877f2009-01-14 15:51:102786 StatusBubble* status_bubble = GetStatusBubble();
2787 if (status_bubble) {
2788 status_bubble->Hide();
[email protected]36b6dcb2008-11-12 01:19:572789
[email protected]be3877f2009-01-14 15:51:102790 // Show the loading state (if any).
[email protected]0dd3a0ab2011-02-18 08:17:442791 status_bubble->SetStatus(GetSelectedTabContentsWrapper()->GetStatusText());
[email protected]be3877f2009-01-14 15:51:102792 }
[email protected]36b6dcb2008-11-12 01:19:572793
[email protected]24db8a072009-10-29 20:35:372794 if (HasFindBarController()) {
[email protected]9c318862011-02-01 22:27:242795 find_bar_controller_->ChangeTabContents(new_contents);
[email protected]b77cb302009-10-29 04:09:172796 find_bar_controller_->find_bar()->MoveWindowIfNecessary(gfx::Rect(), true);
[email protected]4801ecc2009-04-05 04:52:582797 }
2798
[email protected]36b6dcb2008-11-12 01:19:572799 // Update sessions. Don't force creation of sessions. If sessions doesn't
2800 // exist, the change will be picked up by sessions when created.
2801 if (profile_->HasSessionService()) {
2802 SessionService* session_service = profile_->GetSessionService();
[email protected]ecc523f62010-09-28 22:45:402803 if (session_service && !tab_handler_->GetTabStripModel()->closing_all()) {
[email protected]2d46c842008-11-14 19:24:312804 session_service->SetSelectedTabInWindow(
[email protected]ecc523f62010-09-28 22:45:402805 session_id(), tab_handler_->GetTabStripModel()->selected_index());
[email protected]36b6dcb2008-11-12 01:19:572806 }
2807 }
2808}
2809
[email protected]3c9e1872010-11-18 16:17:492810void Browser::TabMoved(TabContentsWrapper* contents,
[email protected]36b6dcb2008-11-12 01:19:572811 int from_index,
[email protected]1a242c32010-02-02 21:20:542812 int to_index) {
[email protected]36b6dcb2008-11-12 01:19:572813 DCHECK(from_index >= 0 && to_index >= 0);
2814 // Notify the history service.
2815 SyncHistoryWithTabs(std::min(from_index, to_index));
2816}
2817
[email protected]da25dd52011-01-11 19:06:302818void Browser::TabReplacedAt(TabStripModel* tab_strip_model,
2819 TabContentsWrapper* old_contents,
[email protected]3c9e1872010-11-18 16:17:492820 TabContentsWrapper* new_contents,
[email protected]8a34e6602010-10-02 17:29:432821 int index) {
[email protected]c37e3b62010-01-22 00:15:172822 TabDetachedAtImpl(old_contents, index, DETACH_TYPE_REPLACE);
2823 TabInsertedAt(new_contents, index,
[email protected]ecc523f62010-09-28 22:45:402824 (index == tab_handler_->GetTabStripModel()->selected_index()));
[email protected]c37e3b62010-01-22 00:15:172825
2826 int entry_count = new_contents->controller().entry_count();
2827 if (entry_count > 0) {
2828 // Send out notification so that observers are updated appropriately.
2829 new_contents->controller().NotifyEntryChanged(
2830 new_contents->controller().GetEntryAtIndex(entry_count - 1),
2831 entry_count - 1);
2832 }
[email protected]47e020a2010-10-15 14:43:372833
2834 SessionService* session_service = profile()->GetSessionService();
2835 if (session_service) {
2836 // The new_contents may end up with a different navigation stack. Force
2837 // the session service to update itself.
2838 session_service->TabRestored(
2839 &new_contents->controller(),
2840 tab_handler_->GetTabStripModel()->IsTabPinned(index));
2841 }
[email protected]2914600d2011-01-31 23:25:142842
2843 DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
2844 if (devtools_manager) // NULL in unit tests.
2845 devtools_manager->TabReplaced(old_contents, new_contents);
[email protected]c37e3b62010-01-22 00:15:172846}
2847
[email protected]3c9e1872010-11-18 16:17:492848void Browser::TabPinnedStateChanged(TabContentsWrapper* contents, int index) {
[email protected]5c0e6482009-07-14 20:20:092849 if (!profile()->HasSessionService())
2850 return;
2851 SessionService* session_service = profile()->GetSessionService();
2852 if (session_service) {
2853 session_service->SetPinnedState(
2854 session_id(),
2855 GetTabContentsAt(index)->controller().session_id(),
[email protected]ecc523f62010-09-28 22:45:402856 tab_handler_->GetTabStripModel()->IsTabPinned(index));
[email protected]5c0e6482009-07-14 20:20:092857 }
2858}
2859
[email protected]36b6dcb2008-11-12 01:19:572860void Browser::TabStripEmpty() {
2861 // Close the frame after we return to the message loop (not immediately,
2862 // otherwise it will destroy this object before the stack has a chance to
2863 // cleanly unwind.)
2864 // Note: This will be called several times if TabStripEmpty is called several
2865 // times. This is because it does not close the window if tabs are
2866 // still present.
2867 // NOTE: If you change to be immediate (no invokeLater) then you'll need to
2868 // update BrowserList::CloseAllBrowsers.
[email protected]0586b0e2010-02-12 21:38:372869 MessageLoop::current()->PostTask(
2870 FROM_HERE, method_factory_.NewRunnableMethod(&Browser::CloseFrame));
[email protected]36b6dcb2008-11-12 01:19:572871}
2872
2873///////////////////////////////////////////////////////////////////////////////
2874// Browser, TabContentsDelegate implementation:
initial.commit09911bf2008-07-26 23:55:292875
2876void Browser::OpenURLFromTab(TabContents* source,
[email protected]1f7d7e92009-06-02 20:55:042877 const GURL& url,
2878 const GURL& referrer,
initial.commit09911bf2008-07-26 23:55:292879 WindowOpenDisposition disposition,
[email protected]e38f40152008-09-12 23:08:302880 PageTransition::Type transition) {
[email protected]616381f02010-11-02 15:15:332881 browser::NavigateParams params(this, url, transition);
[email protected]3c9e1872010-11-18 16:17:492882 params.source_contents =
2883 tabstrip_model()->GetTabContentsAt(
2884 tabstrip_model()->GetWrapperIndex(source));
[email protected]616381f02010-11-02 15:15:332885 params.referrer = referrer;
2886 params.disposition = disposition;
2887 params.tabstrip_add_types = TabStripModel::ADD_NONE;
[email protected]caee0792010-11-19 21:19:362888 params.show_window = true;
[email protected]616381f02010-11-02 15:15:332889 browser::Navigate(&params);
initial.commit09911bf2008-07-26 23:55:292890}
2891
2892void Browser::NavigationStateChanged(const TabContents* source,
2893 unsigned changed_flags) {
initial.commit09911bf2008-07-26 23:55:292894 // Only update the UI when something visible has changed.
[email protected]e83f1682008-09-07 23:57:402895 if (changed_flags)
initial.commit09911bf2008-07-26 23:55:292896 ScheduleUIUpdate(source, changed_flags);
2897
[email protected]84214982008-12-10 18:49:102898 // We don't schedule updates to commands since they will only change once per
2899 // navigation, so we don't have to worry about flickering.
[email protected]e83f1682008-09-07 23:57:402900 if (changed_flags & TabContents::INVALIDATE_URL)
[email protected]84214982008-12-10 18:49:102901 UpdateCommandsForTabState();
initial.commit09911bf2008-07-26 23:55:292902}
2903
initial.commit09911bf2008-07-26 23:55:292904void Browser::AddNewContents(TabContents* source,
2905 TabContents* new_contents,
2906 WindowOpenDisposition disposition,
2907 const gfx::Rect& initial_pos,
2908 bool user_gesture) {
[email protected]616381f02010-11-02 15:15:332909 // No code for this yet
2910 DCHECK(disposition != SAVE_TO_DISK);
2911 // Can't create a new contents for the current tab - invalid case.
2912 DCHECK(disposition != CURRENT_TAB);
initial.commit09911bf2008-07-26 23:55:292913
[email protected]616381f02010-11-02 15:15:332914 // TODO(beng): This belongs behind the platform-specific View interface.
[email protected]a29c08e72011-04-08 21:44:462915 // That's why it's there. http://crbug.com/78853
[email protected]57b839a2010-10-04 22:49:452916#if defined(OS_CHROMEOS)
[email protected]616381f02010-11-02 15:15:332917 if (disposition == NEW_POPUP) {
2918 // If the popup is bigger than a given factor of the screen, then
2919 // turn it into a foreground tab (on chrome os only)
2920 // Also check for width or height == 0, which would otherwise indicate
2921 // a tab sized popup window.
2922 GdkScreen* screen = gdk_screen_get_default();
2923 int max_width = gdk_screen_get_width(screen) * kPopupMaxWidthFactor;
2924 int max_height = gdk_screen_get_height(screen) * kPopupMaxHeightFactor;
2925 if (initial_pos.width() > max_width || initial_pos.width() == 0 ||
2926 initial_pos.height() > max_height || initial_pos.height() == 0) {
2927 disposition = NEW_FOREGROUND_TAB;
[email protected]57b839a2010-10-04 22:49:452928 }
[email protected]616381f02010-11-02 15:15:332929 }
[email protected]57b839a2010-10-04 22:49:452930#endif
2931
[email protected]3c9e1872010-11-18 16:17:492932 TabContentsWrapper* wrapper = new TabContentsWrapper(new_contents);
2933 browser::NavigateParams params(this, wrapper);
2934 params.source_contents =
2935 tabstrip_model()->GetTabContentsAt(
2936 tabstrip_model()->GetWrapperIndex(source));
2937 params.disposition = disposition;
2938 params.window_bounds = initial_pos;
[email protected]caee0792010-11-19 21:19:362939 params.show_window = true;
[email protected]3c9e1872010-11-18 16:17:492940 browser::Navigate(&params);
initial.commit09911bf2008-07-26 23:55:292941}
2942
initial.commit09911bf2008-07-26 23:55:292943void Browser::ActivateContents(TabContents* contents) {
[email protected]ecc523f62010-09-28 22:45:402944 tab_handler_->GetTabStripModel()->SelectTabContentsAt(
[email protected]3c9e1872010-11-18 16:17:492945 tab_handler_->GetTabStripModel()->GetWrapperIndex(contents), false);
[email protected]f3e99e32008-07-30 04:48:392946 window_->Activate();
initial.commit09911bf2008-07-26 23:55:292947}
2948
[email protected]ea42e7782010-08-23 23:58:122949void Browser::DeactivateContents(TabContents* contents) {
2950 window_->Deactivate();
2951}
2952
initial.commit09911bf2008-07-26 23:55:292953void Browser::LoadingStateChanged(TabContents* source) {
[email protected]ecc523f62010-09-28 22:45:402954 window_->UpdateLoadingAnimations(
2955 tab_handler_->GetTabStripModel()->TabsAreLoading());
[email protected]f3e99e32008-07-30 04:48:392956 window_->UpdateTitleBar();
initial.commit09911bf2008-07-26 23:55:292957
[email protected]3c9e1872010-11-18 16:17:492958 TabContents* selected_contents = GetSelectedTabContents();
2959 if (source == selected_contents) {
[email protected]943d8122010-06-11 02:13:452960 UpdateReloadStopState(source->is_loading(), false);
[email protected]43d259d2010-09-03 21:37:462961 if (GetStatusBubble()) {
[email protected]0dd3a0ab2011-02-18 08:17:442962 GetStatusBubble()->SetStatus(
2963 GetSelectedTabContentsWrapper()->GetStatusText());
[email protected]43d259d2010-09-03 21:37:462964 }
[email protected]eabfdae92009-12-11 06:13:512965
2966 if (!source->is_loading() &&
2967 pending_web_app_action_ == UPDATE_SHORTCUT) {
[email protected]867dff82010-04-23 21:30:332968 // Schedule a shortcut update when web application info is available if
2969 // last committed entry is not NULL. Last committed entry could be NULL
2970 // when an interstitial page is injected (e.g. bad https certificate,
2971 // malware site etc). When this happens, we abort the shortcut update.
[email protected]eabfdae92009-12-11 06:13:512972 NavigationEntry* entry = source->controller().GetLastCommittedEntry();
2973 if (entry) {
[email protected]553602e12011-04-05 17:01:182974 TabContentsWrapper::GetCurrentWrapperForContents(source)->
2975 extension_tab_helper()->GetApplicationInfo(entry->page_id());
[email protected]eabfdae92009-12-11 06:13:512976 } else {
2977 pending_web_app_action_ = NONE;
[email protected]eabfdae92009-12-11 06:13:512978 }
2979 }
initial.commit09911bf2008-07-26 23:55:292980 }
2981}
2982
2983void Browser::CloseContents(TabContents* source) {
[email protected]04b4a6c2008-08-02 00:44:472984 if (is_attempting_to_close_browser_) {
2985 // If we're trying to close the browser, just clear the state related to
[email protected]adf650f2008-12-09 16:10:062986 // waiting for unload to fire. Don't actually try to close the tab as it
[email protected]04b4a6c2008-08-02 00:44:472987 // will go down the slow shutdown path instead of the fast path of killing
2988 // all the renderer processes.
[email protected]08f0d612011-01-13 23:58:212989 ClearUnloadState(source, true);
[email protected]04b4a6c2008-08-02 00:44:472990 return;
2991 }
2992
[email protected]3c9e1872010-11-18 16:17:492993 int index = tab_handler_->GetTabStripModel()->GetWrapperIndex(source);
initial.commit09911bf2008-07-26 23:55:292994 if (index == TabStripModel::kNoTab) {
2995 NOTREACHED() << "CloseContents called for tab not in our strip";
2996 return;
2997 }
[email protected]ecc523f62010-09-28 22:45:402998 tab_handler_->GetTabStripModel()->CloseTabContentsAt(
[email protected]0cce15f2010-05-21 16:58:392999 index,
3000 TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
initial.commit09911bf2008-07-26 23:55:293001}
3002
[email protected]15e8abe2008-08-20 22:40:403003void Browser::MoveContents(TabContents* source, const gfx::Rect& pos) {
[email protected]d5fbc002009-02-27 22:12:583004 if ((type() & TYPE_POPUP) == 0) {
initial.commit09911bf2008-07-26 23:55:293005 NOTREACHED() << "moving invalid browser type";
3006 return;
3007 }
[email protected]e561e202010-03-24 17:57:123008 window_->SetBounds(pos);
initial.commit09911bf2008-07-26 23:55:293009}
3010
[email protected]b6c874582009-05-08 19:38:313011void Browser::DetachContents(TabContents* source) {
[email protected]3c9e1872010-11-18 16:17:493012 int index = tab_handler_->GetTabStripModel()->GetWrapperIndex(source);
[email protected]b6c874582009-05-08 19:38:313013 if (index >= 0)
[email protected]ecc523f62010-09-28 22:45:403014 tab_handler_->GetTabStripModel()->DetachTabContentsAt(index);
[email protected]b6c874582009-05-08 19:38:313015}
3016
[email protected]be04582b2010-07-26 21:56:563017bool Browser::IsPopup(const TabContents* source) const {
initial.commit09911bf2008-07-26 23:55:293018 // A non-tabbed BROWSER is an unconstrained popup.
[email protected]d6df2e32009-10-31 04:39:453019 return !!(type() & TYPE_POPUP);
initial.commit09911bf2008-07-26 23:55:293020}
3021
[email protected]36b6dcb2008-11-12 01:19:573022void Browser::ToolbarSizeChanged(TabContents* source, bool is_animating) {
3023 if (source == GetSelectedTabContents() || source == NULL) {
3024 // This will refresh the shelf if needed.
3025 window_->SelectedTabToolbarSizeChanged(is_animating);
3026 }
3027}
3028
[email protected]b8595e92009-11-14 01:18:003029void Browser::ContentsMouseEvent(
3030 TabContents* source, const gfx::Point& location, bool motion) {
[email protected]be3877f2009-01-14 15:51:103031 if (!GetStatusBubble())
3032 return;
3033
[email protected]36b6dcb2008-11-12 01:19:573034 if (source == GetSelectedTabContents()) {
[email protected]b8595e92009-11-14 01:18:003035 GetStatusBubble()->MouseMoved(location, !motion);
3036 if (!motion)
[email protected]43d259d2010-09-03 21:37:463037 GetStatusBubble()->SetURL(GURL(), string16());
[email protected]36b6dcb2008-11-12 01:19:573038 }
3039}
3040
3041void Browser::UpdateTargetURL(TabContents* source, const GURL& url) {
[email protected]be3877f2009-01-14 15:51:103042 if (!GetStatusBubble())
3043 return;
3044
[email protected]36b6dcb2008-11-12 01:19:573045 if (source == GetSelectedTabContents()) {
3046 PrefService* prefs = profile_->GetPrefs();
[email protected]ddd231e2010-06-29 20:35:193047 GetStatusBubble()->SetURL(
[email protected]43d259d2010-09-03 21:37:463048 url, UTF8ToUTF16(prefs->GetString(prefs::kAcceptLanguages)));
[email protected]36b6dcb2008-11-12 01:19:573049 }
3050}
3051
[email protected]3a6a3b62009-05-27 21:36:203052void Browser::UpdateDownloadShelfVisibility(bool visible) {
[email protected]9b032bf2009-07-21 17:34:233053 if (GetStatusBubble())
3054 GetStatusBubble()->UpdateDownloadShelfVisibility(visible);
[email protected]3a6a3b62009-05-27 21:36:203055}
3056
[email protected]aa02fff12010-07-21 19:55:253057bool Browser::UseVerticalTabs() const {
3058 return use_vertical_tabs_.GetValue();
3059}
3060
[email protected]36b6dcb2008-11-12 01:19:573061void Browser::ContentsZoomChange(bool zoom_in) {
[email protected]b75b8292010-10-01 07:28:253062 ExecuteCommand(zoom_in ? IDC_ZOOM_PLUS : IDC_ZOOM_MINUS);
[email protected]36b6dcb2008-11-12 01:19:573063}
3064
[email protected]20ad6a92010-04-21 14:07:243065void Browser::OnContentSettingsChange(TabContents* source) {
[email protected]9800de5e2011-03-11 18:19:493066 if (source == GetSelectedTabContents()) {
3067 LocationBar* location_bar = window()->GetLocationBar();
3068 if (location_bar)
3069 location_bar->UpdateContentSettingsIcons();
3070 }
[email protected]8cc8d492010-02-02 10:40:493071}
3072
[email protected]fa1cf0b82010-01-15 21:49:443073void Browser::SetTabContentBlocked(TabContents* contents, bool blocked) {
[email protected]3c9e1872010-11-18 16:17:493074 int index = tabstrip_model()->GetWrapperIndex(contents);
[email protected]fa1cf0b82010-01-15 21:49:443075 if (index == TabStripModel::kNoTab) {
3076 NOTREACHED();
3077 return;
3078 }
3079 tabstrip_model()->SetTabBlocked(index, blocked);
3080}
3081
[email protected]7e383692009-06-12 19:14:543082void Browser::TabContentsFocused(TabContents* tab_content) {
3083 window_->TabContentsFocused(tab_content);
3084}
3085
[email protected]130efb02009-09-18 18:54:353086bool Browser::TakeFocus(bool reverse) {
3087 NotificationService::current()->Notify(
3088 NotificationType::FOCUS_RETURNED_TO_BROWSER,
3089 Source<Browser>(this),
3090 NotificationService::NoDetails());
3091 return false;
3092}
3093
[email protected]36b6dcb2008-11-12 01:19:573094bool Browser::IsApplication() const {
[email protected]d5fbc002009-02-27 22:12:583095 return (type_ & TYPE_APP) != 0;
[email protected]36b6dcb2008-11-12 01:19:573096}
3097
3098void Browser::ConvertContentsToApplication(TabContents* contents) {
[email protected]ce3fa3c2009-04-20 19:55:573099 const GURL& url = contents->controller().GetActiveEntry()->url();
[email protected]57ecc4b2010-08-11 03:02:513100 std::string app_name = web_app::GenerateApplicationNameFromURL(url);
[email protected]f87919d72011-02-02 18:46:163101 RegisterAppPrefs(app_name, contents->profile());
[email protected]36b6dcb2008-11-12 01:19:573102
[email protected]b6c874582009-05-08 19:38:313103 DetachContents(contents);
[email protected]94ce7252010-12-20 21:46:333104 Browser* app_browser = Browser::CreateForApp(
3105 app_name, gfx::Size(), profile_, false);
[email protected]3c9e1872010-11-18 16:17:493106 TabContentsWrapper* wrapper = new TabContentsWrapper(contents);
[email protected]75aef122010-12-06 21:48:323107 app_browser->tabstrip_model()->AppendTabContents(wrapper, true);
3108
3109 contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
3110 contents->render_view_host()->SyncRendererPrefs();
3111 app_browser->window()->Show();
[email protected]36b6dcb2008-11-12 01:19:573112}
3113
[email protected]36b6dcb2008-11-12 01:19:573114bool Browser::ShouldDisplayURLField() {
3115 return !IsApplication();
3116}
3117
3118void Browser::BeforeUnloadFired(TabContents* tab,
3119 bool proceed,
3120 bool* proceed_to_fire_unload) {
3121 if (!is_attempting_to_close_browser_) {
3122 *proceed_to_fire_unload = proceed;
[email protected]0cce15f2010-05-21 16:58:393123 if (!proceed)
3124 tab->set_closed_by_user_gesture(false);
[email protected]36b6dcb2008-11-12 01:19:573125 return;
3126 }
3127
3128 if (!proceed) {
3129 CancelWindowClose();
3130 *proceed_to_fire_unload = false;
[email protected]0cce15f2010-05-21 16:58:393131 tab->set_closed_by_user_gesture(false);
[email protected]36b6dcb2008-11-12 01:19:573132 return;
3133 }
3134
[email protected]06b42f032008-12-03 18:43:053135 if (RemoveFromSet(&tabs_needing_before_unload_fired_, tab)) {
[email protected]2d46c842008-11-14 19:24:313136 // Now that beforeunload has fired, put the tab on the queue to fire
3137 // unload.
[email protected]06b42f032008-12-03 18:43:053138 tabs_needing_unload_fired_.insert(tab);
[email protected]36b6dcb2008-11-12 01:19:573139 ProcessPendingTabs();
[email protected]adf650f2008-12-09 16:10:063140 // We want to handle firing the unload event ourselves since we want to
[email protected]36b6dcb2008-11-12 01:19:573141 // fire all the beforeunload events before attempting to fire the unload
3142 // events should the user cancel closing the browser.
3143 *proceed_to_fire_unload = false;
3144 return;
3145 }
3146
3147 *proceed_to_fire_unload = true;
3148}
3149
[email protected]4acc19a62009-04-03 03:05:113150void Browser::ShowHtmlDialog(HtmlDialogUIDelegate* delegate,
[email protected]322f3ff2009-05-22 16:19:543151 gfx::NativeWindow parent_window) {
[email protected]2d46c842008-11-14 19:24:313152 window_->ShowHTMLDialog(delegate, parent_window);
initial.commit09911bf2008-07-26 23:55:293153}
3154
[email protected]a26dc362010-04-23 01:48:583155void Browser::SetFocusToLocationBar(bool select_all) {
[email protected]1a380622009-02-17 17:33:133156 // Two differences between this and FocusLocationBar():
3157 // (1) This doesn't get recorded in user metrics, since it's called
3158 // internally.
3159 // (2) This checks whether the location bar can be focused, and if not, clears
3160 // the focus. FocusLocationBar() is only reached when the location bar is
3161 // focusable, but this may be reached at other times, e.g. while in
3162 // fullscreen mode, where we need to leave focus in a consistent state.
[email protected]a26dc362010-04-23 01:48:583163 window_->SetFocusToLocationBar(select_all);
[email protected]4bcefee2009-01-29 15:57:573164}
3165
[email protected]7d5925a2009-03-03 02:59:123166void Browser::RenderWidgetShowing() {
3167 window_->DisableInactiveFrame();
3168}
[email protected]a239c3f2009-02-17 22:13:193169
[email protected]0a2aeb82009-05-15 21:52:483170int Browser::GetExtraRenderViewHeight() const {
3171 return window_->GetExtraRenderViewHeight();
3172}
3173
[email protected]5b928b62010-08-03 11:46:513174void Browser::OnStartDownload(DownloadItem* download, TabContents* tab) {
[email protected]d0cc9fb52009-06-23 02:26:163175 if (!window())
3176 return;
3177
[email protected]f5bf8ccf2010-02-05 18:19:253178#if defined(OS_CHROMEOS)
[email protected]52c45d62010-06-17 16:26:563179 // Don't show content browser for extension/theme downloads from gallery.
[email protected]d3071992010-10-08 15:24:073180 if (download->is_extension_install()) {
[email protected]eaa7dd182010-12-14 11:09:003181 ExtensionService* service = profile_->GetExtensionService();
[email protected]d3071992010-10-08 15:24:073182 if (service && service->IsDownloadFromGallery(download->url(),
3183 download->referrer_url())) {
3184 return;
3185 }
3186 }
[email protected]52c45d62010-06-17 16:26:563187
[email protected]f5bf8ccf2010-02-05 18:19:253188 // skip the download shelf and just open the file browser in chromeos
3189 std::string arg = download->full_path().DirName().value();
[email protected]467293292010-04-16 19:41:563190 FileBrowseUI::OpenPopup(profile_,
3191 arg,
3192 FileBrowseUI::kPopupWidth,
3193 FileBrowseUI::kPopupHeight);
[email protected]f5bf8ccf2010-02-05 18:19:253194
3195#else
[email protected]d0cc9fb52009-06-23 02:26:163196 // GetDownloadShelf creates the download shelf if it was not yet created.
3197 window()->GetDownloadShelf()->AddDownload(new DownloadItemModel(download));
3198
[email protected]d0cc9fb52009-06-23 02:26:163199 // Don't show the animation for "Save file" downloads.
[email protected]e00778c2009-12-18 02:17:243200 if (download->total_bytes() <= 0)
3201 return;
[email protected]8e48e982009-12-25 11:22:463202
[email protected]e00778c2009-12-18 02:17:243203 // For non-theme extensions, we don't show the download animation.
[email protected]a60c8ae2009-12-25 06:50:573204 if (download->is_extension_install() &&
[email protected]eaa7dd182010-12-14 11:09:003205 !ExtensionService::IsDownloadFromMiniGallery(download->url()))
[email protected]e00778c2009-12-18 02:17:243206 return;
3207
3208 TabContents* current_tab = GetSelectedTabContents();
3209 // We make this check for the case of minimized windows, unit tests, etc.
3210 if (platform_util::IsVisible(current_tab->GetNativeView()) &&
[email protected]f67678062011-01-07 17:33:393211 ui::Animation::ShouldRenderRichAnimation()) {
[email protected]e00778c2009-12-18 02:17:243212 DownloadStartedAnimation::Show(current_tab);
[email protected]f5bf8ccf2010-02-05 18:19:253213 }
3214#endif
[email protected]5b928b62010-08-03 11:46:513215
3216 // If the download occurs in a new tab, close it
3217 if (tab->controller().IsInitialNavigation() &&
3218 GetConstrainingContents(tab) == tab && tab_count() > 1) {
3219 CloseContents(tab);
3220 }
[email protected]d0cc9fb52009-06-23 02:26:163221}
3222
[email protected]bb678332009-07-21 00:15:503223void Browser::ShowPageInfo(Profile* profile,
[email protected]4d677202009-07-19 07:37:123224 const GURL& url,
3225 const NavigationEntry::SSLStatus& ssl,
3226 bool show_history) {
[email protected]bb678332009-07-21 00:15:503227 window()->ShowPageInfo(profile, url, ssl, show_history);
[email protected]4d677202009-07-19 07:37:123228}
3229
[email protected]1788e772010-12-15 16:40:503230void Browser::ViewSourceForTab(TabContents* source, const GURL& page_url) {
3231 DCHECK(source);
3232 int index = tabstrip_model()->GetWrapperIndex(source);
[email protected]77d8d622010-12-15 10:30:123233 TabContentsWrapper* wrapper = tabstrip_model()->GetTabContentsAt(index);
3234 ViewSource(wrapper);
3235}
3236
[email protected]932b7a12011-03-09 12:50:273237void Browser::ViewSourceForFrame(TabContents* source,
3238 const GURL& frame_url,
3239 const std::string& frame_content_state) {
3240 DCHECK(source);
3241 int index = tabstrip_model()->GetWrapperIndex(source);
3242 TabContentsWrapper* wrapper = tabstrip_model()->GetTabContentsAt(index);
3243 ViewSource(wrapper, frame_url, frame_content_state);
3244}
3245
[email protected]867125a02009-12-10 06:01:483246bool Browser::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
3247 bool* is_keyboard_shortcut) {
3248 return window()->PreHandleKeyboardEvent(event, is_keyboard_shortcut);
3249}
[email protected]97df4b332009-10-02 01:25:413250
[email protected]867125a02009-12-10 06:01:483251void Browser::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
3252 window()->HandleKeyboardEvent(event);
[email protected]97df4b332009-10-02 01:25:413253}
3254
[email protected]14f3408a2009-08-31 20:53:533255void Browser::ShowRepostFormWarningDialog(TabContents *tab_contents) {
3256 window()->ShowRepostFormWarningDialog(tab_contents);
3257}
3258
[email protected]579e3192011-03-11 22:37:453259void Browser::ShowContentSettingsPage(ContentSettingsType content_type) {
[email protected]445177652011-03-09 02:04:053260 ShowOptionsTab(
3261 chrome::kContentSettingsExceptionsSubPage + std::string(kHashMark) +
3262 ContentSettingsHandler::ContentSettingsTypeToGroupName(content_type));
[email protected]63543142010-02-09 23:22:203263}
3264
[email protected]a503c97c2010-07-16 13:05:483265void Browser::ShowCollectedCookiesDialog(TabContents *tab_contents) {
3266 window()->ShowCollectedCookiesDialog(tab_contents);
3267}
3268
[email protected]ec0b6c42010-08-26 03:16:583269bool Browser::ShouldAddNavigationToHistory(
3270 const history::HistoryAddPageArgs& add_page_args,
3271 NavigationType::Type navigation_type) {
[email protected]2e29d922009-10-22 22:13:353272 // Don't update history if running as app.
3273 return !IsApplication();
3274}
3275
[email protected]9e823662010-10-13 23:36:003276void Browser::ContentRestrictionsChanged(TabContents* source) {
3277 UpdateCommandsForContentRestrictionState();
3278}
3279
[email protected]0dd3a0ab2011-02-18 08:17:443280void Browser::WorkerCrashed() {
3281 TabContents* tab_contents = GetSelectedTabContents();
3282 if (!tab_contents)
3283 return;
3284 tab_contents->AddInfoBar(new SimpleAlertInfoBarDelegate(tab_contents, NULL,
3285 l10n_util::GetStringUTF16(IDS_WEBWORKER_CRASHED_PROMPT), true));
3286}
3287
[email protected]36b6dcb2008-11-12 01:19:573288///////////////////////////////////////////////////////////////////////////////
[email protected]a0366a52011-02-04 20:04:213289// Browser, TabContentsWrapperDelegate implementation:
3290
3291void Browser::URLStarredChanged(TabContentsWrapper* source, bool starred) {
3292 if (source == GetSelectedTabContentsWrapper())
3293 window_->SetStarredState(starred);
3294}
3295
[email protected]553602e12011-04-05 17:01:183296void Browser::OnDidGetApplicationInfo(TabContentsWrapper* source,
3297 int32 page_id) {
3298 if (GetSelectedTabContentsWrapper() != source)
3299 return;
3300
3301 NavigationEntry* entry = source->controller().GetLastCommittedEntry();
3302 if (!entry || (entry->page_id() != page_id))
3303 return;
3304
3305 switch (pending_web_app_action_) {
3306 case CREATE_SHORTCUT: {
3307 window()->ShowCreateWebAppShortcutsDialog(source);
3308 break;
3309 }
3310 case UPDATE_SHORTCUT: {
3311 web_app::UpdateShortcutForTabContents(source);
3312 break;
3313 }
3314 default:
3315 NOTREACHED();
3316 break;
3317 }
3318
3319 pending_web_app_action_ = NONE;
3320}
3321
3322void Browser::OnInstallApplication(TabContentsWrapper* source,
3323 const WebApplicationInfo& web_app) {
3324 ExtensionService* extensions_service = profile()->GetExtensionService();
3325 if (!extensions_service)
3326 return;
3327
3328 scoped_refptr<CrxInstaller> installer(
3329 new CrxInstaller(extensions_service,
3330 extensions_service->show_extensions_prompts() ?
3331 new ExtensionInstallUI(profile()) : NULL));
3332 installer->InstallWebApp(web_app);
3333}
3334
[email protected]c90c6ca2011-02-16 20:11:383335///////////////////////////////////////////////////////////////////////////////
3336// Browser, SearchEngineTabHelperDelegate implementation:
3337
[email protected]9219d262011-02-15 21:05:123338void Browser::ConfirmSetDefaultSearchProvider(
[email protected]b5a1d11c2011-02-17 03:09:423339 TabContents* tab_contents,
[email protected]9219d262011-02-15 21:05:123340 TemplateURL* template_url,
3341 TemplateURLModel* template_url_model) {
3342 window()->ConfirmSetDefaultSearchProvider(tab_contents, template_url,
3343 template_url_model);
3344}
3345
3346void Browser::ConfirmAddSearchProvider(const TemplateURL* template_url,
3347 Profile* profile) {
3348 window()->ConfirmAddSearchProvider(template_url, profile);
3349}
3350
[email protected]a0366a52011-02-04 20:04:213351///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:573352// Browser, SelectFileDialog::Listener implementation:
3353
[email protected]561abe62009-04-06 18:08:343354void Browser::FileSelected(const FilePath& path, int index, void* params) {
[email protected]35896a32010-06-09 08:42:513355 profile_->set_last_selected_directory(path.DirName());
[email protected]72cbd322009-04-07 10:17:123356 GURL file_url = net::FilePathToFileURL(path);
[email protected]36b6dcb2008-11-12 01:19:573357 if (!file_url.is_empty())
3358 OpenURL(file_url, GURL(), CURRENT_TAB, PageTransition::TYPED);
3359}
3360
3361///////////////////////////////////////////////////////////////////////////////
3362// Browser, NotificationObserver implementation:
3363
initial.commit09911bf2008-07-26 23:55:293364void Browser::Observe(NotificationType type,
3365 const NotificationSource& source,
3366 const NotificationDetails& details) {
[email protected]bfd04a62009-02-01 18:16:563367 switch (type.value) {
[email protected]57c6a652009-05-04 07:58:343368 case NotificationType::TAB_CONTENTS_DISCONNECTED:
[email protected]e83f1682008-09-07 23:57:403369 if (is_attempting_to_close_browser_) {
[email protected]08f0d612011-01-13 23:58:213370 // Pass in false so that we delay processing. We need to delay the
3371 // processing as it may close the tab, which is currently on the call
3372 // stack above us.
3373 ClearUnloadState(Source<TabContents>(source).ptr(), false);
[email protected]e83f1682008-09-07 23:57:403374 }
3375 break;
3376
[email protected]b4a19ea2009-03-17 10:08:243377 case NotificationType::SSL_VISIBLE_STATE_CHANGED:
[email protected]e83f1682008-09-07 23:57:403378 // When the current tab's SSL state changes, we need to update the URL
[email protected]90e8d062008-09-08 02:26:323379 // bar to reflect the new state. Note that it's possible for the selected
3380 // tab contents to be NULL. This is because we listen for all sources
3381 // (NavigationControllers) for convenience, so the notification could
3382 // actually be for a different window while we're doing asynchronous
3383 // closing of this one.
3384 if (GetSelectedTabContents() &&
[email protected]ce3fa3c2009-04-20 19:55:573385 &GetSelectedTabContents()->controller() ==
[email protected]e83f1682008-09-07 23:57:403386 Source<NavigationController>(source).ptr())
[email protected]36b6dcb2008-11-12 01:19:573387 UpdateToolbar(false);
[email protected]e83f1682008-09-07 23:57:403388 break;
3389
[email protected]0c6da502009-08-14 22:32:393390 case NotificationType::EXTENSION_UPDATE_DISABLED: {
[email protected]e6090e42010-03-23 22:44:083391 // Show the UI if the extension was disabled for escalated permissions.
[email protected]24e7a9d2009-11-04 11:11:343392 Profile* profile = Source<Profile>(source).ptr();
[email protected]bc535ee52010-08-31 18:40:323393 if (profile_->IsSameProfile(profile)) {
[email protected]eaa7dd182010-12-14 11:09:003394 ExtensionService* service = profile->GetExtensionService();
[email protected]bc535ee52010-08-31 18:40:323395 DCHECK(service);
[email protected]9adb9692010-10-29 23:14:023396 const Extension* extension = Details<const Extension>(details).ptr();
[email protected]bc535ee52010-08-31 18:40:323397 if (service->extension_prefs()->DidExtensionEscalatePermissions(
3398 extension->id()))
3399 ShowExtensionDisabledUI(service, profile_, extension);
3400 }
[email protected]0c6da502009-08-14 22:32:393401 break;
3402 }
3403
[email protected]a9f39a312010-12-23 22:14:273404 case NotificationType::EXTENSION_UNLOADED: {
[email protected]b723ee82009-11-20 16:42:503405 window()->GetLocationBar()->UpdatePageActions();
[email protected]57f71b92009-09-11 19:31:383406
[email protected]894bb502009-05-21 22:39:573407 // Close any tabs from the unloaded extension.
[email protected]a9f39a312010-12-23 22:14:273408 const Extension* extension =
3409 Details<UnloadedExtensionInfo>(details)->extension;
[email protected]ecc523f62010-09-28 22:45:403410 TabStripModel* model = tab_handler_->GetTabStripModel();
3411 for (int i = model->count() - 1; i >= 0; --i) {
[email protected]3c9e1872010-11-18 16:17:493412 TabContents* tc = model->GetTabContentsAt(i)->tab_contents();
[email protected]894bb502009-05-21 22:39:573413 if (tc->GetURL().SchemeIs(chrome::kExtensionScheme) &&
3414 tc->GetURL().host() == extension->id()) {
3415 CloseTabContents(tc);
[email protected]894bb502009-05-21 22:39:573416 }
3417 }
[email protected]9fd542df2009-09-30 07:32:013418
[email protected]894bb502009-05-21 22:39:573419 break;
3420 }
3421
[email protected]a4ed6282009-12-14 20:51:163422 case NotificationType::EXTENSION_PROCESS_TERMINATED: {
[email protected]57f71b92009-09-11 19:31:383423 window()->GetLocationBar()->InvalidatePageActions();
[email protected]371ed7a2009-08-25 15:22:463424 break;
3425 }
3426
[email protected]0dfe05c2011-02-23 23:03:363427 case NotificationType::EXTENSION_UNINSTALLED: {
3428 window()->GetLocationBar()->UpdatePageActions();
3429
[email protected]2c4fb7b2011-04-02 06:33:293430 // Remove any "This extension has crashed" balloons.
[email protected]0dfe05c2011-02-23 23:03:363431 const UninstalledExtensionInfo* uninstalled_extension =
3432 Details<const UninstalledExtensionInfo>(details).ptr();
[email protected]2c4fb7b2011-04-02 06:33:293433 RemoveCrashedExtensionBalloon(uninstalled_extension->extension_id);
[email protected]0dfe05c2011-02-23 23:03:363434 break;
3435 }
3436
[email protected]ad0c2e1b2010-01-30 00:00:103437 case NotificationType::EXTENSION_LOADED: {
[email protected]26571792010-05-19 21:04:483438 window()->GetLocationBar()->UpdatePageActions();
3439
[email protected]2c4fb7b2011-04-02 06:33:293440 // Remove any "This extension has crashed" balloons.
[email protected]9adb9692010-10-29 23:14:023441 const Extension* extension = Details<const Extension>(details).ptr();
[email protected]2c4fb7b2011-04-02 06:33:293442 RemoveCrashedExtensionBalloon(extension->id());
[email protected]ad0c2e1b2010-01-30 00:00:103443 break;
3444 }
3445
[email protected]e001d412009-06-26 20:53:253446 case NotificationType::BROWSER_THEME_CHANGED:
3447 window()->UserChangedTheme();
3448 break;
3449
[email protected]91e1bd82009-09-03 22:04:403450 case NotificationType::EXTENSION_READY_FOR_INSTALL: {
[email protected]a65bce4e2010-06-09 16:00:153451 // Handle EXTENSION_READY_FOR_INSTALL for last active normal browser.
3452 if (BrowserList::FindBrowserWithType(profile(),
3453 Browser::TYPE_NORMAL,
[email protected]074e4f42010-06-23 16:12:063454 true) != this)
[email protected]91e1bd82009-09-03 22:04:403455 break;
[email protected]ac025282009-12-16 19:16:383456
3457 // We only want to show the loading dialog for themes, but we don't want
3458 // to wait until unpack to find out an extension is a theme, so we test
3459 // the download_url GURL instead. This means that themes in the extensions
3460 // gallery won't get the loading dialog.
3461 GURL download_url = *(Details<GURL>(details).ptr());
[email protected]eaa7dd182010-12-14 11:09:003462 if (ExtensionService::IsDownloadFromMiniGallery(download_url))
[email protected]ac025282009-12-16 19:16:383463 window()->ShowThemeInstallBubble();
[email protected]91e1bd82009-09-03 22:04:403464 break;
3465 }
3466
[email protected]e587a45f2009-10-30 22:34:413467 case NotificationType::PROFILE_ERROR: {
[email protected]0e30ef72009-09-05 00:05:083468 if (BrowserList::GetLastActive() != this)
3469 break;
[email protected]e587a45f2009-10-30 22:34:413470 int* message_id = Details<int>(details).ptr();
3471 window()->ShowProfileErrorDialog(*message_id);
[email protected]0e30ef72009-09-05 00:05:083472 break;
3473 }
[email protected]91e1bd82009-09-03 22:04:403474
[email protected]b9c505b2010-04-30 15:05:103475 case NotificationType::PREF_CHANGED: {
[email protected]2a7e7c152010-10-01 20:12:093476 const std::string& pref_name = *Details<std::string>(details).ptr();
3477 if (pref_name == prefs::kUseVerticalTabs) {
[email protected]b3344872010-05-03 15:52:293478 UseVerticalTabsChanged();
[email protected]2a7e7c152010-10-01 20:12:093479 } else if (pref_name == prefs::kPrintingEnabled) {
[email protected]9e823662010-10-13 23:36:003480 UpdatePrintingState(0);
[email protected]73de26a2010-10-17 03:23:253481 } else if (pref_name == prefs::kInstantEnabled) {
3482 if (!InstantController::IsEnabled(profile())) {
3483 if (instant()) {
3484 instant()->DestroyPreviewContents();
[email protected]5aab5e22010-12-08 22:13:293485 instant_.reset();
3486 instant_unload_handler_.reset();
[email protected]73de26a2010-10-17 03:23:253487 }
3488 } else {
3489 CreateInstantIfNecessary();
3490 }
[email protected]543432ee2010-10-22 16:32:133491 } else if (pref_name == prefs::kDevToolsDisabled) {
3492 UpdateCommandsForDevTools();
3493 if (dev_tools_disabled_.GetValue())
3494 g_browser_process->devtools_manager()->CloseAllClientHosts();
[email protected]8f8300212011-02-03 09:49:373495 } else if (pref_name == prefs::kIncognitoEnabled) {
3496 break; // No further action is required.
[email protected]2a7e7c152010-10-01 20:12:093497 } else {
[email protected]b9c505b2010-04-30 15:05:103498 NOTREACHED();
[email protected]2a7e7c152010-10-01 20:12:093499 }
[email protected]b9c505b2010-04-30 15:05:103500 break;
3501 }
3502
[email protected]e83f1682008-09-07 23:57:403503 default:
3504 NOTREACHED() << "Got a notification we didn't register for.";
initial.commit09911bf2008-07-26 23:55:293505 }
3506}
3507
[email protected]2c4fb7b2011-04-02 06:33:293508void Browser::RemoveCrashedExtensionBalloon(const std::string& extension_id) {
3509 g_browser_process->notification_ui_manager()->CancelAllBySourceOrigin(
3510 Extension::GetBaseURLFromExtensionId(extension_id));
[email protected]0dfe05c2011-02-23 23:03:363511}
3512
[email protected]d3b98c82010-07-14 07:45:593513///////////////////////////////////////////////////////////////////////////////
3514// Browser, ProfileSyncServiceObserver implementation:
3515
3516void Browser::OnStateChanged() {
3517 DCHECK(profile_->GetProfileSyncService());
3518
3519#if !defined(OS_MACOSX)
3520 const bool show_main_ui = (type() == TYPE_NORMAL) && !window_->IsFullscreen();
3521#else
3522 const bool show_main_ui = (type() == TYPE_NORMAL);
3523#endif
3524
3525 command_updater_.UpdateCommandEnabled(IDC_SYNC_BOOKMARKS,
3526 show_main_ui && profile_->IsSyncAccessible());
3527}
[email protected]88d74942009-01-21 22:04:443528
[email protected]36b6dcb2008-11-12 01:19:573529///////////////////////////////////////////////////////////////////////////////
[email protected]6b723f82010-10-05 20:14:273530// Browser, InstantDelegate implementation:
[email protected]03bb953d2010-09-14 21:38:303531
[email protected]36d5e5592010-11-15 20:45:593532void Browser::PrepareForInstant() {
3533 window_->PrepareForInstant();
3534}
3535
[email protected]3c9e1872010-11-18 16:17:493536void Browser::ShowInstant(TabContentsWrapper* preview_contents) {
3537 DCHECK(instant_->tab_contents() == GetSelectedTabContentsWrapper());
[email protected]e3690ed2011-03-25 20:25:143538 window_->ShowInstant(preview_contents);
[email protected]03bb953d2010-09-14 21:38:303539}
3540
[email protected]6b723f82010-10-05 20:14:273541void Browser::HideInstant() {
[email protected]1946c932010-12-15 00:07:383542 window_->HideInstant(instant_->is_active());
[email protected]03bb953d2010-09-14 21:38:303543}
3544
[email protected]3c9e1872010-11-18 16:17:493545void Browser::CommitInstant(TabContentsWrapper* preview_contents) {
3546 TabContentsWrapper* tab_contents = instant_->tab_contents();
3547 int index =
3548 tab_handler_->GetTabStripModel()->GetIndexOfTabContents(tab_contents);
3549 DCHECK_NE(TabStripModel::kNoTab, index);
[email protected]03bb953d2010-09-14 21:38:303550 // TabStripModel takes ownership of preview_contents.
[email protected]43032342011-03-21 14:10:313551 tab_handler_->GetTabStripModel()->ReplaceTabContentsAt(
3552 index, preview_contents);
3553 // InstantUnloadHandler takes ownership of tab_contents.
3554 instant_unload_handler_->RunUnloadListenersOrDestroy(tab_contents, index);
[email protected]46fd1ea42011-02-16 15:59:333555
3556 GURL url = preview_contents->tab_contents()->GetURL();
[email protected]6e37fe32011-03-02 09:06:523557 DCHECK(profile_->GetExtensionService());
3558 if (profile_->GetExtensionService()->IsInstalledApp(url)) {
[email protected]46fd1ea42011-02-16 15:59:333559 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram,
3560 extension_misc::APP_LAUNCH_OMNIBOX_INSTANT,
3561 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY);
3562 }
[email protected]03bb953d2010-09-14 21:38:303563}
3564
[email protected]33b8b8e2011-03-15 14:51:553565void Browser::SetSuggestedText(const string16& text,
3566 InstantCompleteBehavior behavior) {
3567 window()->GetLocationBar()->SetSuggestedText(text, behavior);
[email protected]03bb953d2010-09-14 21:38:303568}
3569
[email protected]6b723f82010-10-05 20:14:273570gfx::Rect Browser::GetInstantBounds() {
3571 return window()->GetInstantBounds();
[email protected]46fe8e92010-09-22 03:32:473572}
3573
[email protected]03bb953d2010-09-14 21:38:303574///////////////////////////////////////////////////////////////////////////////
[email protected]9800de5e2011-03-11 18:19:493575// Browser, protected:
3576
3577BrowserWindow* Browser::CreateBrowserWindow() {
3578 return BrowserWindow::CreateBrowserWindow(this);
3579}
3580
3581
3582///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:573583// Browser, Command and state updating (private):
3584
3585void Browser::InitCommandState() {
3586 // All browser commands whose state isn't set automagically some other way
3587 // (like Back & Forward with initial page load) must have their state
3588 // initialized here, otherwise they will be forever disabled.
3589
[email protected]84214982008-12-10 18:49:103590 // Navigation commands
[email protected]1fc025202009-01-20 23:03:143591 command_updater_.UpdateCommandEnabled(IDC_RELOAD, true);
[email protected]1ccb3568d2010-02-19 10:51:163592 command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE, true);
[email protected]84214982008-12-10 18:49:103593
3594 // Window management commands
[email protected]1fc025202009-01-20 23:03:143595 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW, true);
[email protected]6e6f6cb2011-01-27 13:26:553596 command_updater_.UpdateCommandEnabled(IDC_NEW_INCOGNITO_WINDOW,
3597 incognito_mode_allowed_.GetValue());
[email protected]1fc025202009-01-20 23:03:143598 command_updater_.UpdateCommandEnabled(IDC_CLOSE_WINDOW, true);
3599 command_updater_.UpdateCommandEnabled(IDC_NEW_TAB, true);
3600 command_updater_.UpdateCommandEnabled(IDC_CLOSE_TAB, true);
3601 command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB, true);
[email protected]281918912010-05-27 22:05:133602 command_updater_.UpdateCommandEnabled(IDC_RESTORE_TAB, false);
[email protected]1fc025202009-01-20 23:03:143603 command_updater_.UpdateCommandEnabled(IDC_EXIT, true);
[email protected]c8b59f92010-05-28 21:45:473604 command_updater_.UpdateCommandEnabled(IDC_TOGGLE_VERTICAL_TABS, true);
[email protected]84214982008-12-10 18:49:103605
3606 // Page-related commands
[email protected]89d6e6e2009-12-03 23:06:513607 command_updater_.UpdateCommandEnabled(IDC_EMAIL_PAGE_LOCATION, true);
[email protected]1fc025202009-01-20 23:03:143608 command_updater_.UpdateCommandEnabled(IDC_ENCODING_AUTO_DETECT, true);
3609 command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF8, true);
3610 command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF16LE, true);
3611 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88591, true);
3612 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1252, true);
3613 command_updater_.UpdateCommandEnabled(IDC_ENCODING_GBK, true);
3614 command_updater_.UpdateCommandEnabled(IDC_ENCODING_GB18030, true);
3615 command_updater_.UpdateCommandEnabled(IDC_ENCODING_BIG5HKSCS, true);
3616 command_updater_.UpdateCommandEnabled(IDC_ENCODING_BIG5, true);
3617 command_updater_.UpdateCommandEnabled(IDC_ENCODING_THAI, true);
3618 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOREAN, true);
3619 command_updater_.UpdateCommandEnabled(IDC_ENCODING_SHIFTJIS, true);
3620 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO2022JP, true);
3621 command_updater_.UpdateCommandEnabled(IDC_ENCODING_EUCJP, true);
3622 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885915, true);
3623 command_updater_.UpdateCommandEnabled(IDC_ENCODING_MACINTOSH, true);
3624 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88592, true);
3625 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1250, true);
3626 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88595, true);
3627 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1251, true);
3628 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8R, true);
3629 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8U, true);
3630 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88597, true);
3631 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1253, true);
3632 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88594, true);
3633 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885913, true);
3634 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1257, true);
3635 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88593, true);
3636 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885910, true);
3637 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885914, true);
3638 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885916, true);
3639 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1254, true);
3640 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88596, true);
3641 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1256, true);
3642 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598, true);
[email protected]e13271f2009-03-07 00:26:003643 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598I, true);
[email protected]1fc025202009-01-20 23:03:143644 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1255, true);
3645 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1258, true);
[email protected]84214982008-12-10 18:49:103646
[email protected]63b02932009-06-05 09:40:513647 // Zoom
3648 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MENU, true);
3649 command_updater_.UpdateCommandEnabled(IDC_ZOOM_PLUS, true);
3650 command_updater_.UpdateCommandEnabled(IDC_ZOOM_NORMAL, true);
3651 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MINUS, true);
3652
[email protected]84214982008-12-10 18:49:103653 // Show various bits of UI
[email protected]1fc025202009-01-20 23:03:143654 command_updater_.UpdateCommandEnabled(IDC_OPEN_FILE, true);
3655 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS, false);
[email protected]543432ee2010-10-22 16:32:133656 UpdateCommandsForDevTools();
[email protected]1fc025202009-01-20 23:03:143657 command_updater_.UpdateCommandEnabled(IDC_TASK_MANAGER, true);
[email protected]1fc025202009-01-20 23:03:143658 command_updater_.UpdateCommandEnabled(IDC_SHOW_HISTORY, true);
[email protected]4a4180a52010-08-23 06:39:483659 command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER,
3660 browser_defaults::bookmarks_enabled);
[email protected]1fc025202009-01-20 23:03:143661 command_updater_.UpdateCommandEnabled(IDC_SHOW_DOWNLOADS, true);
3662 command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE, true);
[email protected]4aee5652009-11-19 18:59:213663 command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, true);
[email protected]9cd51a02009-10-23 22:30:293664
[email protected]96e34672010-02-09 21:40:293665#if defined(OS_CHROMEOS)
[email protected]f97d7f632010-06-01 21:08:333666 command_updater_.UpdateCommandEnabled(IDC_SEARCH, true);
[email protected]d14af522010-12-02 03:54:503667 command_updater_.UpdateCommandEnabled(IDC_SHOW_KEYBOARD_OVERLAY, true);
[email protected]c8b59f92010-05-28 21:45:473668 command_updater_.UpdateCommandEnabled(IDC_SYSTEM_OPTIONS, true);
3669 command_updater_.UpdateCommandEnabled(IDC_INTERNET_OPTIONS, true);
[email protected]96e34672010-02-09 21:40:293670#endif
[email protected]c8b59f92010-05-28 21:45:473671
[email protected]eaa7dd182010-12-14 11:09:003672 ExtensionService* extensions_service = profile()->GetExtensionService();
[email protected]9cd51a02009-10-23 22:30:293673 bool enable_extensions =
3674 extensions_service && extensions_service->extensions_enabled();
3675 command_updater_.UpdateCommandEnabled(IDC_MANAGE_EXTENSIONS,
3676 enable_extensions);
3677
[email protected]64ff7942008-12-17 18:11:233678 // Initialize other commands based on the window type.
[email protected]11f4857282009-11-13 19:56:173679 bool normal_window = type() == TYPE_NORMAL;
[email protected]fc33e9992010-04-08 19:40:133680 bool non_devtools_window = type() != TYPE_DEVTOOLS;
[email protected]64ff7942008-12-17 18:11:233681
[email protected]11f4857282009-11-13 19:56:173682 // Navigation commands
3683 command_updater_.UpdateCommandEnabled(IDC_HOME, normal_window);
[email protected]64ff7942008-12-17 18:11:233684
[email protected]11f4857282009-11-13 19:56:173685 // Window management commands
[email protected]cf299bc2010-08-12 20:27:093686 command_updater_.UpdateCommandEnabled(IDC_FULLSCREEN,
3687 type() != TYPE_APP_PANEL);
[email protected]11f4857282009-11-13 19:56:173688 command_updater_.UpdateCommandEnabled(IDC_SELECT_NEXT_TAB, normal_window);
3689 command_updater_.UpdateCommandEnabled(IDC_SELECT_PREVIOUS_TAB,
3690 normal_window);
3691 command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_NEXT, normal_window);
3692 command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_PREVIOUS, normal_window);
3693 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_0, normal_window);
3694 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_1, normal_window);
3695 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_2, normal_window);
3696 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_3, normal_window);
3697 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_4, normal_window);
3698 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_5, normal_window);
3699 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_6, normal_window);
3700 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_7, normal_window);
3701 command_updater_.UpdateCommandEnabled(IDC_SELECT_LAST_TAB, normal_window);
[email protected]c1d0d812010-07-27 20:21:553702#if defined(OS_MACOSX)
3703 command_updater_.UpdateCommandEnabled(IDC_TABPOSE, normal_window);
3704#endif
[email protected]e662ade2009-06-08 18:20:143705
[email protected]11f4857282009-11-13 19:56:173706 // Page-related commands
[email protected]4a4180a52010-08-23 06:39:483707 command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_PAGE,
3708 browser_defaults::bookmarks_enabled && normal_window);
[email protected]76624fde2009-10-09 18:13:233709
[email protected]fc33e9992010-04-08 19:40:133710 // Clipboard commands
3711 command_updater_.UpdateCommandEnabled(IDC_COPY_URL, non_devtools_window);
3712
3713 // Find-in-page
3714 command_updater_.UpdateCommandEnabled(IDC_FIND, non_devtools_window);
3715 command_updater_.UpdateCommandEnabled(IDC_FIND_NEXT, non_devtools_window);
3716 command_updater_.UpdateCommandEnabled(IDC_FIND_PREVIOUS, non_devtools_window);
3717
[email protected]663bd9e2011-03-21 01:07:013718 // Autofill
[email protected]cf28ec52010-04-09 22:56:343719 command_updater_.UpdateCommandEnabled(IDC_AUTOFILL_DEFAULT,
3720 non_devtools_window);
3721
[email protected]11f4857282009-11-13 19:56:173722 // Show various bits of UI
[email protected]fc33e9992010-04-08 19:40:133723 command_updater_.UpdateCommandEnabled(IDC_CLEAR_BROWSING_DATA, normal_window);
[email protected]9282cea2009-02-18 18:49:003724
[email protected]c1bbaa82010-11-08 11:17:053725 // The upgrade entry and the view incompatibility entry should always be
3726 // enabled. Whether they are visible is a separate matter determined on menu
3727 // show.
[email protected]b21d6912010-08-31 19:22:413728 command_updater_.UpdateCommandEnabled(IDC_UPGRADE_DIALOG, true);
[email protected]c1bbaa82010-11-08 11:17:053729 command_updater_.UpdateCommandEnabled(IDC_VIEW_INCOMPATIBILITIES, true);
[email protected]b21d6912010-08-31 19:22:413730
[email protected]b569c112010-11-22 20:53:443731 // View Background Pages entry is always enabled, but is hidden if there are
3732 // no background pages.
3733 command_updater_.UpdateCommandEnabled(IDC_VIEW_BACKGROUND_PAGES, true);
3734
[email protected]9282cea2009-02-18 18:49:003735 // Initialize other commands whose state changes based on fullscreen mode.
3736 UpdateCommandsForFullscreenMode(false);
[email protected]9e823662010-10-13 23:36:003737
3738 UpdateCommandsForContentRestrictionState();
[email protected]36b6dcb2008-11-12 01:19:573739}
3740
[email protected]84214982008-12-10 18:49:103741void Browser::UpdateCommandsForTabState() {
[email protected]c7c42332008-11-15 01:10:543742 TabContents* current_tab = GetSelectedTabContents();
[email protected]a0366a52011-02-04 20:04:213743 TabContentsWrapper* current_tab_wrapper = GetSelectedTabContentsWrapper();
3744 if (!current_tab || !current_tab_wrapper) // May be NULL during tab restore.
[email protected]d8375fd2008-11-25 22:45:393745 return;
[email protected]d8375fd2008-11-25 22:45:393746
[email protected]84214982008-12-10 18:49:103747 // Navigation commands
[email protected]ce3fa3c2009-04-20 19:55:573748 NavigationController& nc = current_tab->controller();
3749 command_updater_.UpdateCommandEnabled(IDC_BACK, nc.CanGoBack());
3750 command_updater_.UpdateCommandEnabled(IDC_FORWARD, nc.CanGoForward());
[email protected]fc33e9992010-04-08 19:40:133751 command_updater_.UpdateCommandEnabled(IDC_RELOAD,
3752 CanReloadContents(current_tab));
3753 command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE,
3754 CanReloadContents(current_tab));
initial.commit09911bf2008-07-26 23:55:293755
[email protected]84214982008-12-10 18:49:103756 // Window management commands
[email protected]fc33e9992010-04-08 19:40:133757 bool non_app_window = !(type() & TYPE_APP);
[email protected]1fc025202009-01-20 23:03:143758 command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB,
[email protected]fc33e9992010-04-08 19:40:133759 non_app_window && CanDuplicateContentsAt(selected_index()));
[email protected]84214982008-12-10 18:49:103760
[email protected]57c6a652009-05-04 07:58:343761 // Page-related commands
[email protected]a0366a52011-02-04 20:04:213762 window_->SetStarredState(current_tab_wrapper->is_starred());
[email protected]a206b442009-10-08 23:20:203763 command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_ALL_TABS,
[email protected]4a4180a52010-08-23 06:39:483764 browser_defaults::bookmarks_enabled && CanBookmarkAllTabs());
[email protected]57c6a652009-05-04 07:58:343765 command_updater_.UpdateCommandEnabled(IDC_VIEW_SOURCE,
[email protected]31682282010-01-15 18:05:163766 current_tab->controller().CanViewSource());
[email protected]151666e2010-10-21 17:05:253767 command_updater_.UpdateCommandEnabled(IDC_EMAIL_PAGE_LOCATION,
3768 current_tab->ShouldDisplayURL() && current_tab->GetURL().is_valid());
3769
3770 // Changing the encoding is not possible on Chrome-internal webpages.
[email protected]4d07cdc2009-08-22 16:09:393771 // Instead of using GetURL here, we use url() (which is the "real" url of the
3772 // page) from the NavigationEntry because its reflects their origin rather
3773 // than the display one (returned by GetURL) which may be different (like
3774 // having "view-source:" on the front).
[email protected]fc33e9992010-04-08 19:40:133775 NavigationEntry* active_entry = nc.GetActiveEntry();
[email protected]c0f82ec52010-07-27 14:22:143776 bool is_chrome_internal = (active_entry ?
3777 active_entry->url().SchemeIs(chrome::kChromeUIScheme) : false);
3778 command_updater_.UpdateCommandEnabled(IDC_ENCODING_MENU,
3779 !is_chrome_internal && SavePackage::IsSavableContents(
3780 current_tab->contents_mime_type()));
3781
[email protected]57c6a652009-05-04 07:58:343782 // Show various bits of UI
[email protected]c065fa072010-01-20 23:12:253783 // TODO(pinkerton): Disable app-mode in the model until we implement it
3784 // on the Mac. Be sure to remove both ifdefs. http://crbug.com/13148
3785#if !defined(OS_MACOSX)
[email protected]57c6a652009-05-04 07:58:343786 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS,
[email protected]12ea22a2009-11-19 07:17:233787 web_app::IsValidUrl(current_tab->GetURL()));
[email protected]c065fa072010-01-20 23:12:253788#endif
[email protected]9e823662010-10-13 23:36:003789
3790 UpdateCommandsForContentRestrictionState();
3791}
3792
3793void Browser::UpdateCommandsForContentRestrictionState() {
3794 int restrictions = 0;
3795 TabContents* current_tab = GetSelectedTabContents();
[email protected]151666e2010-10-21 17:05:253796 if (current_tab) {
[email protected]9e823662010-10-13 23:36:003797 restrictions = current_tab->content_restrictions();
[email protected]151666e2010-10-21 17:05:253798 NavigationEntry* active_entry = current_tab->controller().GetActiveEntry();
3799 // See comment in UpdateCommandsForTabState about why we call url().
3800 if (!SavePackage::IsSavableURL(active_entry ? active_entry->url() : GURL()))
3801 restrictions |= CONTENT_RESTRICTION_SAVE;
3802 }
[email protected]9e823662010-10-13 23:36:003803
3804 command_updater_.UpdateCommandEnabled(
3805 IDC_COPY, !(restrictions & CONTENT_RESTRICTION_COPY));
3806 command_updater_.UpdateCommandEnabled(
3807 IDC_CUT, !(restrictions & CONTENT_RESTRICTION_CUT));
3808 command_updater_.UpdateCommandEnabled(
3809 IDC_PASTE, !(restrictions & CONTENT_RESTRICTION_PASTE));
[email protected]151666e2010-10-21 17:05:253810 command_updater_.UpdateCommandEnabled(
3811 IDC_SAVE_PAGE, !(restrictions & CONTENT_RESTRICTION_SAVE));
[email protected]9e823662010-10-13 23:36:003812 UpdatePrintingState(restrictions);
3813}
3814
3815void Browser::UpdatePrintingState(int content_restrictions) {
3816 bool enabled = true;
3817 if (content_restrictions & CONTENT_RESTRICTION_PRINT) {
3818 enabled = false;
3819 } else if (g_browser_process->local_state()) {
3820 enabled = printing_enabled_.GetValue();
3821 }
3822 command_updater_.UpdateCommandEnabled(IDC_PRINT, enabled);
initial.commit09911bf2008-07-26 23:55:293823}
3824
[email protected]943d8122010-06-11 02:13:453825void Browser::UpdateReloadStopState(bool is_loading, bool force) {
3826 window_->UpdateReloadStopState(is_loading, force);
[email protected]1fc025202009-01-20 23:03:143827 command_updater_.UpdateCommandEnabled(IDC_STOP, is_loading);
[email protected]64ff7942008-12-17 18:11:233828}
3829
[email protected]543432ee2010-10-22 16:32:133830void Browser::UpdateCommandsForDevTools() {
3831 bool dev_tools_enabled = !dev_tools_disabled_.GetValue();
3832 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS,
3833 dev_tools_enabled);
3834 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_CONSOLE,
3835 dev_tools_enabled);
3836 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_INSPECT,
3837 dev_tools_enabled);
3838}
3839
[email protected]36b6dcb2008-11-12 01:19:573840///////////////////////////////////////////////////////////////////////////////
3841// Browser, UI update coalescing and handling (private):
3842
3843void Browser::UpdateToolbar(bool should_restore_state) {
[email protected]3c9e1872010-11-18 16:17:493844 window_->UpdateToolbar(GetSelectedTabContentsWrapper(), should_restore_state);
initial.commit09911bf2008-07-26 23:55:293845}
3846
[email protected]36b6dcb2008-11-12 01:19:573847void Browser::ScheduleUIUpdate(const TabContents* source,
3848 unsigned changed_flags) {
[email protected]a5231662009-09-26 00:56:003849 if (!source)
3850 return;
3851
[email protected]2b4355c2009-04-04 17:55:463852 // Do some synchronous updates.
[email protected]36b6dcb2008-11-12 01:19:573853 if (changed_flags & TabContents::INVALIDATE_URL &&
3854 source == GetSelectedTabContents()) {
3855 // Only update the URL for the current tab. Note that we do not update
3856 // the navigation commands since those would have already been updated
3857 // synchronously by NavigationStateChanged.
3858 UpdateToolbar(false);
[email protected]8030f012009-09-25 18:09:373859 changed_flags &= ~TabContents::INVALIDATE_URL;
[email protected]36b6dcb2008-11-12 01:19:573860 }
[email protected]a5231662009-09-26 00:56:003861 if (changed_flags & TabContents::INVALIDATE_LOAD) {
[email protected]6ebdc9b2010-09-27 16:55:573862 // Update the loading state synchronously. This is so the throbber will
3863 // immediately start/stop, which gives a more snappy feel. We want to do
[email protected]a5231662009-09-26 00:56:003864 // this for any tab so they start & stop quickly.
[email protected]ecc523f62010-09-28 22:45:403865 tab_handler_->GetTabStripModel()->UpdateTabContentsStateAt(
3866 tab_handler_->GetTabStripModel()->GetIndexOfController(
3867 &source->controller()),
[email protected]6ebdc9b2010-09-27 16:55:573868 TabStripModelObserver::LOADING_ONLY);
3869 // The status bubble needs to be updated during INVALIDATE_LOAD too, but
3870 // we do that asynchronously by not stripping INVALIDATE_LOAD from
3871 // changed_flags.
[email protected]8030f012009-09-25 18:09:373872 }
3873
[email protected]f1cd5e82009-10-23 17:19:033874 if (changed_flags & TabContents::INVALIDATE_TITLE && !source->is_loading()) {
3875 // To correctly calculate whether the title changed while not loading
3876 // we need to process the update synchronously. This state only matters for
3877 // the TabStripModel, so we notify the TabStripModel now and notify others
3878 // asynchronously.
[email protected]ecc523f62010-09-28 22:45:403879 tab_handler_->GetTabStripModel()->UpdateTabContentsStateAt(
3880 tab_handler_->GetTabStripModel()->GetIndexOfController(
3881 &source->controller()),
[email protected]f1cd5e82009-10-23 17:19:033882 TabStripModelObserver::TITLE_NOT_LOADING);
3883 }
3884
[email protected]6d7a6042010-08-12 20:12:423885 if (changed_flags & TabContents::INVALIDATE_BOOKMARK_BAR) {
[email protected]8030f012009-09-25 18:09:373886 window()->ShelfVisibilityChanged();
[email protected]6d7a6042010-08-12 20:12:423887 changed_flags &= ~TabContents::INVALIDATE_BOOKMARK_BAR;
[email protected]2b4355c2009-04-04 17:55:463888 }
3889
3890 // If the only updates were synchronously handled above, we're done.
[email protected]8030f012009-09-25 18:09:373891 if (changed_flags == 0)
[email protected]2b4355c2009-04-04 17:55:463892 return;
[email protected]36b6dcb2008-11-12 01:19:573893
3894 // Save the dirty bits.
[email protected]85354982009-09-25 19:58:403895 scheduled_updates_[source] |= changed_flags;
[email protected]36b6dcb2008-11-12 01:19:573896
3897 if (chrome_updater_factory_.empty()) {
3898 // No task currently scheduled, start another.
[email protected]0586b0e2010-02-12 21:38:373899 MessageLoop::current()->PostDelayedTask(
3900 FROM_HERE,
[email protected]36b6dcb2008-11-12 01:19:573901 chrome_updater_factory_.NewRunnableMethod(
3902 &Browser::ProcessPendingUIUpdates),
[email protected]6ebdc9b2010-09-27 16:55:573903 kUIUpdateCoalescingTimeMS);
[email protected]36b6dcb2008-11-12 01:19:573904 }
3905}
3906
3907void Browser::ProcessPendingUIUpdates() {
3908#ifndef NDEBUG
3909 // Validate that all tabs we have pending updates for exist. This is scary
3910 // because the pending list must be kept in sync with any detached or
[email protected]a5231662009-09-26 00:56:003911 // deleted tabs.
[email protected]85354982009-09-25 19:58:403912 for (UpdateMap::const_iterator i = scheduled_updates_.begin();
3913 i != scheduled_updates_.end(); ++i) {
[email protected]36b6dcb2008-11-12 01:19:573914 bool found = false;
3915 for (int tab = 0; tab < tab_count(); tab++) {
[email protected]a5231662009-09-26 00:56:003916 if (GetTabContentsAt(tab) == i->first) {
[email protected]36b6dcb2008-11-12 01:19:573917 found = true;
3918 break;
3919 }
3920 }
3921 DCHECK(found);
3922 }
3923#endif
3924
3925 chrome_updater_factory_.RevokeAll();
3926
[email protected]85354982009-09-25 19:58:403927 for (UpdateMap::const_iterator i = scheduled_updates_.begin();
3928 i != scheduled_updates_.end(); ++i) {
[email protected]36b6dcb2008-11-12 01:19:573929 // Do not dereference |contents|, it may be out-of-date!
[email protected]85354982009-09-25 19:58:403930 const TabContents* contents = i->first;
3931 unsigned flags = i->second;
[email protected]36b6dcb2008-11-12 01:19:573932
[email protected]a5231662009-09-26 00:56:003933 if (contents == GetSelectedTabContents()) {
3934 // Updates that only matter when the tab is selected go here.
[email protected]f7f3a5f2009-05-01 22:02:343935
[email protected]9800de5e2011-03-11 18:19:493936 if (flags & TabContents::INVALIDATE_PAGE_ACTIONS) {
3937 LocationBar* location_bar = window()->GetLocationBar();
3938 if (location_bar)
3939 location_bar->UpdatePageActions();
3940 }
[email protected]6ebdc9b2010-09-27 16:55:573941 // Updating the URL happens synchronously in ScheduleUIUpdate.
[email protected]0dd3a0ab2011-02-18 08:17:443942 if (flags & TabContents::INVALIDATE_LOAD && GetStatusBubble()) {
3943 GetStatusBubble()->SetStatus(
3944 GetSelectedTabContentsWrapper()->GetStatusText());
3945 }
[email protected]a5231662009-09-26 00:56:003946
[email protected]f1cd5e82009-10-23 17:19:033947 if (flags & (TabContents::INVALIDATE_TAB |
3948 TabContents::INVALIDATE_TITLE)) {
[email protected]c065fa072010-01-20 23:12:253949// TODO(pinkerton): Disable app-mode in the model until we implement it
3950// on the Mac. Be sure to remove both ifdefs. http://crbug.com/13148
3951#if !defined(OS_MACOSX)
[email protected]a5231662009-09-26 00:56:003952 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS,
[email protected]12ea22a2009-11-19 07:17:233953 web_app::IsValidUrl(contents->GetURL()));
[email protected]c065fa072010-01-20 23:12:253954#endif
[email protected]a5231662009-09-26 00:56:003955 window_->UpdateTitleBar();
3956 }
[email protected]4d34e2e2009-05-26 22:55:283957 }
[email protected]36b6dcb2008-11-12 01:19:573958
[email protected]a5231662009-09-26 00:56:003959 // Updates that don't depend upon the selected state go here.
[email protected]f1cd5e82009-10-23 17:19:033960 if (flags & (TabContents::INVALIDATE_TAB | TabContents::INVALIDATE_TITLE)) {
[email protected]ecc523f62010-09-28 22:45:403961 tab_handler_->GetTabStripModel()->UpdateTabContentsStateAt(
[email protected]3c9e1872010-11-18 16:17:493962 tab_handler_->GetTabStripModel()->GetWrapperIndex(contents),
[email protected]f1cd5e82009-10-23 17:19:033963 TabStripModelObserver::ALL);
[email protected]36b6dcb2008-11-12 01:19:573964 }
3965
3966 // We don't need to process INVALIDATE_STATE, since that's not visible.
3967 }
3968
3969 scheduled_updates_.clear();
3970}
3971
3972void Browser::RemoveScheduledUpdatesFor(TabContents* contents) {
3973 if (!contents)
3974 return;
3975
[email protected]85354982009-09-25 19:58:403976 UpdateMap::iterator i = scheduled_updates_.find(contents);
3977 if (i != scheduled_updates_.end())
3978 scheduled_updates_.erase(i);
initial.commit09911bf2008-07-26 23:55:293979}
3980
[email protected]d938aed92009-01-22 19:49:333981
[email protected]36b6dcb2008-11-12 01:19:573982///////////////////////////////////////////////////////////////////////////////
3983// Browser, Getters for UI (private):
initial.commit09911bf2008-07-26 23:55:293984
[email protected]36b6dcb2008-11-12 01:19:573985StatusBubble* Browser::GetStatusBubble() {
[email protected]34930432009-11-09 00:12:093986#if !defined(OS_MACOSX)
3987 // In kiosk mode, we want to always hide the status bubble.
3988 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
3989 return NULL;
3990#endif
[email protected]9b032bf2009-07-21 17:34:233991 return window_ ? window_->GetStatusBubble() : NULL;
initial.commit09911bf2008-07-26 23:55:293992}
3993
[email protected]36b6dcb2008-11-12 01:19:573994///////////////////////////////////////////////////////////////////////////////
3995// Browser, Session restore functions (private):
initial.commit09911bf2008-07-26 23:55:293996
3997void Browser::SyncHistoryWithTabs(int index) {
3998 if (!profile()->HasSessionService())
3999 return;
4000 SessionService* session_service = profile()->GetSessionService();
4001 if (session_service) {
4002 for (int i = index; i < tab_count(); ++i) {
4003 TabContents* contents = GetTabContentsAt(i);
4004 if (contents) {
4005 session_service->SetTabIndexInWindow(
[email protected]ce3fa3c2009-04-20 19:55:574006 session_id(), contents->controller().session_id(), i);
[email protected]ecc523f62010-09-28 22:45:404007 session_service->SetPinnedState(
4008 session_id(),
4009 contents->controller().session_id(),
4010 tab_handler_->GetTabStripModel()->IsTabPinned(i));
initial.commit09911bf2008-07-26 23:55:294011 }
4012 }
4013 }
4014}
4015
[email protected]36b6dcb2008-11-12 01:19:574016///////////////////////////////////////////////////////////////////////////////
4017// Browser, OnBeforeUnload handling (private):
initial.commit09911bf2008-07-26 23:55:294018
[email protected]04b4a6c2008-08-02 00:44:474019void Browser::ProcessPendingTabs() {
[email protected]08f0d612011-01-13 23:58:214020 if (!is_attempting_to_close_browser_) {
4021 // Because we might invoke this after a delay it's possible for the value of
4022 // is_attempting_to_close_browser_ to have changed since we scheduled the
4023 // task.
4024 return;
4025 }
initial.commit09911bf2008-07-26 23:55:294026
[email protected]04b4a6c2008-08-02 00:44:474027 if (HasCompletedUnloadProcessing()) {
4028 // We've finished all the unload events and can proceed to close the
4029 // browser.
4030 OnWindowClosing();
initial.commit09911bf2008-07-26 23:55:294031 return;
4032 }
4033
[email protected]04b4a6c2008-08-02 00:44:474034 // Process beforeunload tabs first. When that queue is empty, process
4035 // unload tabs.
[email protected]04b4a6c2008-08-02 00:44:474036 if (!tabs_needing_before_unload_fired_.empty()) {
[email protected]06b42f032008-12-03 18:43:054037 TabContents* tab = *(tabs_needing_before_unload_fired_.begin());
[email protected]22484622009-06-10 21:17:244038 // Null check render_view_host here as this gets called on a PostTask and
4039 // the tab's render_view_host may have been nulled out.
4040 if (tab->render_view_host()) {
[email protected]ae23c272009-07-27 20:15:404041 tab->render_view_host()->FirePageBeforeUnload(false);
[email protected]22484622009-06-10 21:17:244042 } else {
[email protected]08f0d612011-01-13 23:58:214043 ClearUnloadState(tab, true);
[email protected]22484622009-06-10 21:17:244044 }
[email protected]04b4a6c2008-08-02 00:44:474045 } else if (!tabs_needing_unload_fired_.empty()) {
initial.commit09911bf2008-07-26 23:55:294046 // We've finished firing all beforeunload events and can proceed with unload
4047 // events.
4048 // TODO(ojan): We should add a call to browser_shutdown::OnShutdownStarting
4049 // somewhere around here so that we have accurate measurements of shutdown
4050 // time.
[email protected]04b4a6c2008-08-02 00:44:474051 // TODO(ojan): We can probably fire all the unload events in parallel and
4052 // get a perf benefit from that in the cases where the tab hangs in it's
4053 // unload handler or takes a long time to page in.
[email protected]06b42f032008-12-03 18:43:054054 TabContents* tab = *(tabs_needing_unload_fired_.begin());
[email protected]22484622009-06-10 21:17:244055 // Null check render_view_host here as this gets called on a PostTask and
4056 // the tab's render_view_host may have been nulled out.
4057 if (tab->render_view_host()) {
[email protected]eb6b87a2009-07-24 15:57:394058 tab->render_view_host()->ClosePage(false, -1, -1);
[email protected]22484622009-06-10 21:17:244059 } else {
[email protected]08f0d612011-01-13 23:58:214060 ClearUnloadState(tab, true);
[email protected]22484622009-06-10 21:17:244061 }
initial.commit09911bf2008-07-26 23:55:294062 } else {
[email protected]04b4a6c2008-08-02 00:44:474063 NOTREACHED();
initial.commit09911bf2008-07-26 23:55:294064 }
4065}
4066
[email protected]d043c2cc2009-03-25 18:30:454067bool Browser::HasCompletedUnloadProcessing() const {
[email protected]04b4a6c2008-08-02 00:44:474068 return is_attempting_to_close_browser_ &&
4069 tabs_needing_before_unload_fired_.empty() &&
4070 tabs_needing_unload_fired_.empty();
4071}
4072
4073void Browser::CancelWindowClose() {
[email protected]0b4d3382010-07-14 16:13:044074 // Closing of window can be canceled from:
4075 // - canceling beforeunload
4076 // - disallowing closing from IsClosingPermitted.
[email protected]04b4a6c2008-08-02 00:44:474077 DCHECK(is_attempting_to_close_browser_);
[email protected]8f673f3a2008-08-05 22:34:284078 tabs_needing_before_unload_fired_.clear();
4079 tabs_needing_unload_fired_.clear();
[email protected]04b4a6c2008-08-02 00:44:474080 is_attempting_to_close_browser_ = false;
[email protected]0b4d3382010-07-14 16:13:044081
4082 // Inform TabCloseableStateWatcher that closing of window has been canceled.
4083 TabCloseableStateWatcher* watcher =
4084 g_browser_process->tab_closeable_state_watcher();
4085 if (watcher)
4086 watcher->OnWindowCloseCanceled(this);
[email protected]04b4a6c2008-08-02 00:44:474087}
4088
[email protected]06b42f032008-12-03 18:43:054089bool Browser::RemoveFromSet(UnloadListenerSet* set, TabContents* tab) {
[email protected]04b4a6c2008-08-02 00:44:474090 DCHECK(is_attempting_to_close_browser_);
4091
[email protected]06b42f032008-12-03 18:43:054092 UnloadListenerSet::iterator iter = std::find(set->begin(), set->end(), tab);
4093 if (iter != set->end()) {
4094 set->erase(iter);
4095 return true;
[email protected]04b4a6c2008-08-02 00:44:474096 }
4097 return false;
4098}
initial.commit09911bf2008-07-26 23:55:294099
[email protected]08f0d612011-01-13 23:58:214100void Browser::ClearUnloadState(TabContents* tab, bool process_now) {
[email protected]0b4d3382010-07-14 16:13:044101 // Closing of browser could be canceled (via IsClosingPermitted) between the
4102 // time when request was initiated and when this method is called, so check
4103 // for is_attempting_to_close_browser_ flag before proceeding.
4104 if (is_attempting_to_close_browser_) {
4105 RemoveFromSet(&tabs_needing_before_unload_fired_, tab);
4106 RemoveFromSet(&tabs_needing_unload_fired_, tab);
[email protected]08f0d612011-01-13 23:58:214107 if (process_now) {
4108 ProcessPendingTabs();
4109 } else {
4110 MessageLoop::current()->PostTask(
4111 FROM_HERE,
4112 method_factory_.NewRunnableMethod(&Browser::ProcessPendingTabs));
4113 }
[email protected]0b4d3382010-07-14 16:13:044114 }
initial.commit09911bf2008-07-26 23:55:294115}
4116
[email protected]36b6dcb2008-11-12 01:19:574117///////////////////////////////////////////////////////////////////////////////
[email protected]69444cc2009-04-09 20:40:064118// Browser, In-progress download termination handling (private):
4119
[email protected]460a2942010-12-15 19:43:154120void Browser::CheckDownloadsInProgress(bool* normal_downloads_are_present,
4121 bool* incognito_downloads_are_present) {
4122 *normal_downloads_are_present = false;
4123 *incognito_downloads_are_present = false;
4124
4125 // If there are no download in-progress, our job is done.
4126 DownloadManager* download_manager = NULL;
4127 // But first we need to check for the existance of the download manager, as
4128 // GetDownloadManager() will unnecessarily try to create one if it does not
4129 // exist.
4130 if (profile()->HasCreatedDownloadManager())
4131 download_manager = profile()->GetDownloadManager();
4132 if (profile()->IsOffTheRecord()) {
4133 // Browser is incognito and so download_manager if present is for incognito
4134 // downloads.
4135 *incognito_downloads_are_present =
4136 (download_manager && download_manager->in_progress_count() != 0);
4137 // Check original profile.
4138 if (profile()->GetOriginalProfile()->HasCreatedDownloadManager())
4139 download_manager = profile()->GetOriginalProfile()->GetDownloadManager();
4140 }
4141
4142 *normal_downloads_are_present =
4143 (download_manager && download_manager->in_progress_count() != 0);
4144}
4145
[email protected]69444cc2009-04-09 20:40:064146bool Browser::CanCloseWithInProgressDownloads() {
4147 if (cancel_download_confirmation_state_ != NOT_PROMPTED) {
[email protected]7a22201c2009-10-16 16:50:374148 if (cancel_download_confirmation_state_ == WAITING_FOR_RESPONSE) {
4149 // We need to hear from the user before we can close.
4150 return false;
4151 }
4152 // RESPONSE_RECEIVED case, the user decided to go along with the closing.
[email protected]69444cc2009-04-09 20:40:064153 return true;
4154 }
[email protected]446295a2010-04-19 23:43:004155 // Indicated that normal (non-incognito) downloads are pending.
4156 bool normal_downloads_are_present = false;
4157 bool incognito_downloads_are_present = false;
[email protected]460a2942010-12-15 19:43:154158 CheckDownloadsInProgress(&normal_downloads_are_present,
4159 &incognito_downloads_are_present);
[email protected]446295a2010-04-19 23:43:004160 if (!normal_downloads_are_present && !incognito_downloads_are_present)
4161 return true;
4162
4163 if (is_attempting_to_close_browser_)
4164 return true;
4165
4166 if ((!normal_downloads_are_present && !profile()->IsOffTheRecord()) ||
4167 (!incognito_downloads_are_present && profile()->IsOffTheRecord()))
[email protected]69444cc2009-04-09 20:40:064168 return true;
4169
4170 // Let's figure out if we are the last window for our profile.
4171 // Note that we cannot just use BrowserList::GetBrowserCount as browser
4172 // windows closing is delayed and the returned count might include windows
4173 // that are being closed.
[email protected]446295a2010-04-19 23:43:004174 // The browser allowed to be closed only if:
4175 // 1. It is a regular browser and there are no regular downloads present or
4176 // this is not the last regular browser window.
4177 // 2. It is an incognito browser and there are no incognito downloads present
4178 // or this is not the last incognito browser window.
[email protected]69444cc2009-04-09 20:40:064179 int count = 0;
4180 for (BrowserList::const_iterator iter = BrowserList::begin();
4181 iter != BrowserList::end(); ++iter) {
4182 // Don't count this browser window or any other in the process of closing.
[email protected]460a2942010-12-15 19:43:154183 // Only consider normal browser windows, not popups.
4184 Browser* const browser = *iter;
4185 if (browser == this
4186 || browser->is_attempting_to_close_browser_
4187 || browser->type() != Browser::TYPE_NORMAL)
[email protected]69444cc2009-04-09 20:40:064188 continue;
4189
[email protected]446295a2010-04-19 23:43:004190 // Verify that this is not the last non-incognito or incognito browser,
4191 // depending on the pending downloads.
4192 if (normal_downloads_are_present && !profile()->IsOffTheRecord() &&
[email protected]460a2942010-12-15 19:43:154193 browser->profile()->IsOffTheRecord())
[email protected]446295a2010-04-19 23:43:004194 continue;
4195 if (incognito_downloads_are_present && profile()->IsOffTheRecord() &&
[email protected]460a2942010-12-15 19:43:154196 !browser->profile()->IsOffTheRecord())
[email protected]446295a2010-04-19 23:43:004197 continue;
4198
[email protected]69444cc2009-04-09 20:40:064199 // We test the original profile, because an incognito browser window keeps
4200 // the original profile alive (and its DownloadManager).
4201 // We also need to test explicitly the profile directly so that 2 incognito
4202 // profiles count as a match.
4203 if ((*iter)->profile() == profile() ||
4204 (*iter)->profile()->GetOriginalProfile() == profile())
4205 count++;
4206 }
4207 if (count > 0)
4208 return true;
4209
4210 cancel_download_confirmation_state_ = WAITING_FOR_RESPONSE;
4211 window_->ConfirmBrowserCloseWithPendingDownloads();
4212
4213 // Return false so the browser does not close. We'll close if the user
4214 // confirms in the dialog.
4215 return false;
4216}
4217
4218///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:574219// Browser, Assorted utility functions (private):
initial.commit09911bf2008-07-26 23:55:294220
[email protected]1a6b30a2009-08-19 03:52:114221// static
[email protected]de4e7632010-09-01 06:24:044222Browser* Browser::GetTabbedBrowser(Profile* profile, bool match_incognito) {
4223 return BrowserList::FindBrowserWithType(profile, TYPE_NORMAL,
4224 match_incognito);
4225}
4226
4227// static
[email protected]1a6b30a2009-08-19 03:52:114228Browser* Browser::GetOrCreateTabbedBrowser(Profile* profile) {
[email protected]de4e7632010-09-01 06:24:044229 Browser* browser = GetTabbedBrowser(profile, false);
[email protected]15952e462008-11-14 00:29:054230 if (!browser)
[email protected]1a6b30a2009-08-19 03:52:114231 browser = Browser::Create(profile);
initial.commit09911bf2008-07-26 23:55:294232 return browser;
4233}
4234
[email protected]9219d262011-02-15 21:05:124235void Browser::SetAsDelegate(TabContentsWrapper* tab, Browser* delegate) {
4236 tab->tab_contents()->set_delegate(delegate);
4237 tab->set_delegate(delegate);
4238 tab->search_engine_tab_helper()->set_delegate(delegate);
4239}
4240
[email protected]4f3dc372009-02-24 00:10:294241void Browser::FindInPage(bool find_next, bool forward_direction) {
[email protected]4801ecc2009-04-05 04:52:584242 ShowFindBar();
[email protected]4f3dc372009-02-24 00:10:294243 if (find_next) {
[email protected]6a4f5af22009-09-23 22:43:004244 string16 find_text;
4245#if defined(OS_MACOSX)
4246 // We always want to search for the contents of the find pasteboard on OS X.
4247 find_text = GetFindPboardText();
4248#endif
[email protected]9c318862011-02-01 22:27:244249 GetSelectedTabContentsWrapper()->
[email protected]c90c6ca2011-02-16 20:11:384250 find_tab_helper()->StartFinding(find_text,
4251 forward_direction,
4252 false); // Not case sensitive.
[email protected]4f3dc372009-02-24 00:10:294253 }
[email protected]fbd77592008-11-12 20:50:274254}
[email protected]cb17f7f2009-02-06 18:14:484255
[email protected]36b6dcb2008-11-12 01:19:574256void Browser::CloseFrame() {
4257 window_->Close();
initial.commit09911bf2008-07-26 23:55:294258}
4259
[email protected]3c9e1872010-11-18 16:17:494260void Browser::TabDetachedAtImpl(TabContentsWrapper* contents, int index,
[email protected]c37e3b62010-01-22 00:15:174261 DetachType type) {
4262 if (type == DETACH_TYPE_DETACH) {
[email protected]56580852010-11-17 16:09:154263 // Save the current location bar state, but only if the tab being detached
4264 // is the selected tab. Because saving state can conditionally revert the
4265 // location bar, saving the current tab's location bar state to a
4266 // non-selected tab can corrupt both tabs.
[email protected]9800de5e2011-03-11 18:19:494267 if (contents == GetSelectedTabContentsWrapper()) {
4268 LocationBar* location_bar = window()->GetLocationBar();
4269 if (location_bar)
4270 location_bar->SaveStateToContents(contents->tab_contents());
4271 }
[email protected]c37e3b62010-01-22 00:15:174272
[email protected]ecc523f62010-09-28 22:45:404273 if (!tab_handler_->GetTabStripModel()->closing_all())
[email protected]c37e3b62010-01-22 00:15:174274 SyncHistoryWithTabs(0);
4275 }
4276
[email protected]9219d262011-02-15 21:05:124277 SetAsDelegate(contents, NULL);
[email protected]3c9e1872010-11-18 16:17:494278 RemoveScheduledUpdatesFor(contents->tab_contents());
[email protected]c37e3b62010-01-22 00:15:174279
[email protected]ecc523f62010-09-28 22:45:404280 if (find_bar_controller_.get() &&
4281 index == tab_handler_->GetTabStripModel()->selected_index()) {
[email protected]c37e3b62010-01-22 00:15:174282 find_bar_controller_->ChangeTabContents(NULL);
[email protected]ecc523f62010-09-28 22:45:404283 }
[email protected]c37e3b62010-01-22 00:15:174284
[email protected]08f0d612011-01-13 23:58:214285 if (is_attempting_to_close_browser_) {
4286 // If this is the last tab with unload handlers, then ProcessPendingTabs
4287 // would call back into the TabStripModel (which is invoking this method on
4288 // us). Avoid that by passing in false so that the call to
4289 // ProcessPendingTabs is delayed.
4290 ClearUnloadState(contents->tab_contents(), false);
4291 }
4292
[email protected]c37e3b62010-01-22 00:15:174293 registrar_.Remove(this, NotificationType::TAB_CONTENTS_DISCONNECTED,
[email protected]3c9e1872010-11-18 16:17:494294 Source<TabContentsWrapper>(contents));
[email protected]c37e3b62010-01-22 00:15:174295}
4296
initial.commit09911bf2008-07-26 23:55:294297// static
[email protected]f87919d72011-02-02 18:46:164298void Browser::RegisterAppPrefs(const std::string& app_name, Profile* profile) {
initial.commit09911bf2008-07-26 23:55:294299 // A set of apps that we've already started.
[email protected]57ecc4b2010-08-11 03:02:514300 static std::set<std::string>* g_app_names = NULL;
initial.commit09911bf2008-07-26 23:55:294301
4302 if (!g_app_names)
[email protected]57ecc4b2010-08-11 03:02:514303 g_app_names = new std::set<std::string>;
initial.commit09911bf2008-07-26 23:55:294304
4305 // Only register once for each app name.
4306 if (g_app_names->find(app_name) != g_app_names->end())
4307 return;
4308 g_app_names->insert(app_name);
4309
4310 // We need to register the window position pref.
[email protected]57ecc4b2010-08-11 03:02:514311 std::string window_pref(prefs::kBrowserWindowPlacement);
4312 window_pref.append("_");
initial.commit09911bf2008-07-26 23:55:294313 window_pref.append(app_name);
[email protected]f87919d72011-02-02 18:46:164314 profile->GetPrefs()->RegisterDictionaryPref(window_pref.c_str());
initial.commit09911bf2008-07-26 23:55:294315}
[email protected]5c238752009-06-13 10:29:074316
[email protected]281918912010-05-27 22:05:134317void Browser::TabRestoreServiceChanged(TabRestoreService* service) {
4318 command_updater_.UpdateCommandEnabled(IDC_RESTORE_TAB,
4319 !service->entries().empty());
4320}
4321
4322void Browser::TabRestoreServiceDestroyed(TabRestoreService* service) {
4323 if (!tab_restore_service_)
4324 return;
4325
4326 DCHECK_EQ(tab_restore_service_, service);
4327 tab_restore_service_->RemoveObserver(this);
4328 tab_restore_service_ = NULL;
4329}
[email protected]97b6c4f2010-09-27 19:31:264330
[email protected]3c9e1872010-11-18 16:17:494331// Centralized method for creating a TabContents, configuring and installing
4332// all its supporting objects and observers.
4333TabContentsWrapper* Browser::TabContentsFactory(
4334 Profile* profile,
4335 SiteInstance* site_instance,
4336 int routing_id,
4337 const TabContents* base_tab_contents,
4338 SessionStorageNamespace* session_storage_namespace) {
4339 TabContents* new_contents = new TabContents(profile, site_instance,
4340 routing_id, base_tab_contents,
4341 session_storage_namespace);
4342 TabContentsWrapper* wrapper = new TabContentsWrapper(new_contents);
4343 return wrapper;
4344}
4345
[email protected]6b723f82010-10-05 20:14:274346bool Browser::OpenInstant(WindowOpenDisposition disposition) {
[email protected]35242602011-01-06 16:38:534347 if (!instant() || !instant()->is_active() || !instant()->IsCurrent() ||
4348 disposition == NEW_BACKGROUND_TAB) {
4349 // NEW_BACKGROUND_TAB results in leaving the omnibox open, so we don't
4350 // attempt to use the instant preview.
[email protected]97b6c4f2010-09-27 19:31:264351 return false;
[email protected]35242602011-01-06 16:38:534352 }
[email protected]97b6c4f2010-09-27 19:31:264353
4354 if (disposition == CURRENT_TAB) {
[email protected]6b723f82010-10-05 20:14:274355 instant()->CommitCurrentPreview(INSTANT_COMMIT_PRESSED_ENTER);
[email protected]97b6c4f2010-09-27 19:31:264356 return true;
4357 }
[email protected]35242602011-01-06 16:38:534358 if (disposition == NEW_FOREGROUND_TAB) {
[email protected]3c9e1872010-11-18 16:17:494359 TabContentsWrapper* preview_contents = instant()->ReleasePreviewContents(
[email protected]6b723f82010-10-05 20:14:274360 INSTANT_COMMIT_PRESSED_ENTER);
[email protected]a0df03c122011-01-05 00:22:554361 // HideInstant is invoked after release so that InstantController is not
4362 // active when HideInstant asks it for its state.
4363 HideInstant();
[email protected]97b6c4f2010-09-27 19:31:264364 preview_contents->controller().PruneAllButActive();
[email protected]ecc523f62010-09-28 22:45:404365 tab_handler_->GetTabStripModel()->AddTabContents(
[email protected]97b6c4f2010-09-27 19:31:264366 preview_contents,
4367 -1,
[email protected]6b723f82010-10-05 20:14:274368 instant()->last_transition_type(),
[email protected]3c2db4f2011-03-11 00:07:184369 TabStripModel::ADD_SELECTED);
[email protected]3c9e1872010-11-18 16:17:494370 instant()->CompleteRelease(preview_contents->tab_contents());
[email protected]97b6c4f2010-09-27 19:31:264371 return true;
4372 }
4373 // The omnibox currently doesn't use other dispositions, so we don't attempt
4374 // to handle them. If you hit this NOTREACHED file a bug and I'll (sky) add
4375 // support for the new disposition.
4376 NOTREACHED();
4377 return false;
4378}
[email protected]2031cf9d2010-10-12 05:05:374379
4380void Browser::CreateInstantIfNecessary() {
[email protected]73de26a2010-10-17 03:23:254381 if (type() == TYPE_NORMAL && InstantController::IsEnabled(profile()) &&
[email protected]2031cf9d2010-10-12 05:05:374382 !profile()->IsOffTheRecord()) {
[email protected]fdf773c52010-11-01 20:58:194383 instant_.reset(new InstantController(profile_, this));
[email protected]5aab5e22010-12-08 22:13:294384 instant_unload_handler_.reset(new InstantUnloadHandler(this));
[email protected]2031cf9d2010-10-12 05:05:374385 }
4386}
[email protected]77d8d622010-12-15 10:30:124387
4388void Browser::ViewSource(TabContentsWrapper* contents) {
[email protected]932b7a12011-03-09 12:50:274389 DCHECK(contents);
4390
4391 NavigationEntry* active_entry = contents->controller().GetActiveEntry();
4392 if (!active_entry)
4393 return;
4394
4395 ViewSource(contents, active_entry->url(), active_entry->content_state());
4396}
4397
4398void Browser::ViewSource(TabContentsWrapper* contents,
4399 const GURL& url,
4400 const std::string& content_state) {
[email protected]77d8d622010-12-15 10:30:124401 UserMetrics::RecordAction(UserMetricsAction("ViewSource"), profile_);
4402 DCHECK(contents);
4403
4404 TabContentsWrapper* view_source_contents = contents->Clone();
4405 view_source_contents->controller().PruneAllButActive();
4406 NavigationEntry* active_entry =
4407 view_source_contents->controller().GetActiveEntry();
[email protected]1788e772010-12-15 16:40:504408 if (!active_entry)
4409 return;
4410
[email protected]932b7a12011-03-09 12:50:274411 GURL view_source_url = GURL(chrome::kViewSourceScheme + std::string(":") +
4412 url.spec());
4413 active_entry->set_virtual_url(view_source_url);
[email protected]1436beff2010-12-16 19:47:044414
[email protected]932b7a12011-03-09 12:50:274415 // Do not restore scroller position.
4416 active_entry->set_content_state(
4417 webkit_glue::RemoveScrollOffsetFromHistoryState(content_state));
4418
[email protected]cd3d50d2010-12-18 21:03:294419 // Do not restore title, derive it from the url.
4420 active_entry->set_title(string16());
[email protected]77d8d622010-12-15 10:30:124421
[email protected]47b309f2010-12-28 17:35:564422 // Now show view-source entry.
[email protected]77d8d622010-12-15 10:30:124423 if (CanSupportWindowFeature(FEATURE_TABSTRIP)) {
4424 // If this is a tabbed browser, just create a duplicate tab inside the same
4425 // window next to the tab being duplicated.
4426 int index = tab_handler_->GetTabStripModel()->
4427 GetIndexOfTabContents(contents);
[email protected]77d8d622010-12-15 10:30:124428 int add_types = TabStripModel::ADD_SELECTED |
[email protected]47b309f2010-12-28 17:35:564429 TabStripModel::ADD_INHERIT_GROUP;
[email protected]77d8d622010-12-15 10:30:124430 tab_handler_->GetTabStripModel()->InsertTabContentsAt(index + 1,
[email protected]47b309f2010-12-28 17:35:564431 view_source_contents,
[email protected]77d8d622010-12-15 10:30:124432 add_types);
4433 } else {
[email protected]47b309f2010-12-28 17:35:564434 Browser* browser = Browser::CreateForType(TYPE_NORMAL, profile_);
[email protected]77d8d622010-12-15 10:30:124435
4436 // Preserve the size of the original window. The new window has already
4437 // been given an offset by the OS, so we shouldn't copy the old bounds.
4438 BrowserWindow* new_window = browser->window();
4439 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
4440 window()->GetRestoredBounds().size()));
4441
4442 // We need to show the browser now. Otherwise ContainerWin assumes the
4443 // TabContents is invisible and won't size it.
4444 browser->window()->Show();
4445
4446 // The page transition below is only for the purpose of inserting the tab.
[email protected]47b309f2010-12-28 17:35:564447 browser->AddTab(view_source_contents, PageTransition::LINK);
[email protected]77d8d622010-12-15 10:30:124448 }
4449
4450 if (profile_->HasSessionService()) {
4451 SessionService* session_service = profile_->GetSessionService();
4452 if (session_service)
[email protected]47b309f2010-12-28 17:35:564453 session_service->TabRestored(&view_source_contents->controller(), false);
[email protected]77d8d622010-12-15 10:30:124454 }
4455}