blob: c145042fae97d23517a4cf97e744ff8123e9a7cf [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]a9afddb2009-02-12 17:49:4227#include "chrome/browser/bookmarks/bookmark_model.h"
[email protected]b3ac5c82009-10-08 20:56:5428#include "chrome/browser/bookmarks/bookmark_utils.h"
[email protected]8a53ee042009-01-21 16:41:3329#include "chrome/browser/browser_list.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]b17d41c2011-02-17 22:09:5933#include "chrome/browser/browser_window.h"
[email protected]40d59ce52009-03-06 23:20:1434#include "chrome/browser/character_encoding.h"
[email protected]40ecc902009-03-16 13:42:4735#include "chrome/browser/debugger/devtools_manager.h"
[email protected]2a8a98122010-07-16 11:58:4836#include "chrome/browser/debugger/devtools_toggle_action.h"
[email protected]8e48e982009-12-25 11:22:4637#include "chrome/browser/debugger/devtools_window.h"
[email protected]6c69796d2010-07-16 21:41:1638#include "chrome/browser/download/download_item.h"
[email protected]59560e0b2009-06-04 03:30:2239#include "chrome/browser/download/download_item_model.h"
[email protected]69444cc2009-04-09 20:40:0640#include "chrome/browser/download/download_manager.h"
[email protected]59560e0b2009-06-04 03:30:2241#include "chrome/browser/download/download_shelf.h"
42#include "chrome/browser/download/download_started_animation.h"
[email protected]371ed7a2009-08-25 15:22:4643#include "chrome/browser/extensions/crashed_extension_infobar.h"
[email protected]bb461532010-11-26 21:50:2344#include "chrome/browser/extensions/crx_installer.h"
[email protected]9fd542df2009-09-30 07:32:0145#include "chrome/browser/extensions/extension_browser_event_router.h"
[email protected]0c6da502009-08-14 22:32:3946#include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
[email protected]6d7a6042010-08-12 20:12:4247#include "chrome/browser/extensions/extension_host.h"
[email protected]10abd192010-09-30 02:03:4948#include "chrome/browser/extensions/extension_prefs.h"
[email protected]eaa7dd182010-12-14 11:09:0049#include "chrome/browser/extensions/extension_service.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]14a000d2010-04-29 21:44:2459#include "chrome/browser/platform_util.h"
[email protected]37858e52010-08-26 00:22:0260#include "chrome/browser/prefs/pref_service.h"
[email protected]02337592010-09-27 18:38:2561#include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
[email protected]8ecad5e2010-12-02 21:18:3362#include "chrome/browser/profiles/profile.h"
[email protected]85e921fb82009-02-11 23:19:4463#include "chrome/browser/sessions/session_service.h"
[email protected]c61db1d2009-02-06 03:39:1864#include "chrome/browser/sessions/session_types.h"
[email protected]92926d92010-09-02 18:35:0665#include "chrome/browser/sessions/tab_restore_service.h"
[email protected]066629f2009-10-17 00:28:1366#include "chrome/browser/sync/profile_sync_service.h"
[email protected]40f047972009-11-25 03:54:4067#include "chrome/browser/sync/sync_ui_util.h"
[email protected]0b4d3382010-07-14 16:13:0468#include "chrome/browser/tab_closeable_state_watcher.h"
[email protected]7cceebac2011-03-03 00:32:2169#include "chrome/browser/tab_contents/simple_alert_infobar_delegate.h"
[email protected]07d490bc2011-03-07 17:05:2670#include "chrome/browser/tabs/tab_finder.h"
[email protected]c848d3d92010-09-16 21:57:4571#include "chrome/browser/tabs/tab_strip_model.h"
[email protected]45300ad42010-12-02 15:51:1472#include "chrome/browser/ui/find_bar/find_bar.h"
73#include "chrome/browser/ui/find_bar/find_bar_controller.h"
[email protected]c90c6ca2011-02-16 20:11:3874#include "chrome/browser/ui/find_bar/find_tab_helper.h"
[email protected]6a3ec2312010-12-02 19:30:1975#include "chrome/browser/ui/omnibox/location_bar.h"
76#include "chrome/browser/ui/options/options_window.h"
[email protected]9219d262011-02-15 21:05:1277#include "chrome/browser/ui/search_engines/search_engine_tab_helper.h"
[email protected]6a3ec2312010-12-02 19:30:1978#include "chrome/browser/ui/status_bubble.h"
79#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
[email protected]9a800652010-12-02 17:08:4480#include "chrome/browser/ui/tabs/dock_info.h"
[email protected]6a3ec2312010-12-02 19:30:1981#include "chrome/browser/ui/tabs/tab_menu_model.h"
[email protected]265a1492011-02-27 05:58:0782#include "chrome/browser/ui/webui/bug_report_ui.h"
83#include "chrome/browser/ui/webui/filebrowse_ui.h"
[email protected]5c557f372011-02-26 15:09:2084#include "chrome/browser/ui/webui/options/content_settings_handler.h"
[email protected]9a800652010-12-02 17:08:4485#include "chrome/browser/ui/window_sizer.h"
[email protected]b1b73942010-05-26 20:11:5486#include "chrome/browser/upgrade_detector.h"
[email protected]86b54012009-11-19 09:18:5087#include "chrome/browser/web_applications/web_app.h"
[email protected]d938aed92009-01-22 19:49:3388#include "chrome/common/chrome_constants.h"
89#include "chrome/common/chrome_switches.h"
[email protected]9e823662010-10-13 23:36:0090#include "chrome/common/content_restriction.h"
[email protected]5b1a0e22009-05-26 19:00:5891#include "chrome/common/extensions/extension.h"
[email protected]46fd1ea42011-02-16 15:59:3392#include "chrome/common/extensions/extension_constants.h"
[email protected]d938aed92009-01-22 19:49:3393#include "chrome/common/page_transition_types.h"
[email protected]8a53ee042009-01-21 16:41:3394#include "chrome/common/pref_names.h"
[email protected]7664ab32011-02-01 23:35:2595#include "chrome/common/profiling.h"
[email protected]b689fce72009-03-17 22:45:3496#include "chrome/common/url_constants.h"
[email protected]bb461532010-11-26 21:50:2397#include "chrome/common/web_apps.h"
[email protected]b6021d32011-02-26 01:25:5498#include "content/browser/host_zoom_map.h"
[email protected]a01efd22011-03-01 00:38:3299#include "content/browser/renderer_host/render_view_host.h"
100#include "content/browser/site_instance.h"
[email protected]a01efd22011-03-01 00:38:32101#include "content/browser/tab_contents/interstitial_page.h"
102#include "content/browser/tab_contents/navigation_controller.h"
103#include "content/browser/tab_contents/navigation_entry.h"
104#include "content/browser/tab_contents/tab_contents.h"
105#include "content/browser/tab_contents/tab_contents_view.h"
[email protected]7f070d42011-03-09 20:25:32106#include "content/common/notification_service.h"
[email protected]a3e18c42009-03-04 23:36:05107#include "grit/chromium_strings.h"
108#include "grit/generated_resources.h"
109#include "grit/locale_settings.h"
[email protected]8a53ee042009-01-21 16:41:33110#include "net/base/cookie_monster.h"
[email protected]8a53ee042009-01-21 16:41:33111#include "net/base/net_util.h"
112#include "net/base/registry_controlled_domain.h"
[email protected]cb370a0632010-01-30 08:24:12113#include "net/base/static_cookie_policy.h"
[email protected]8a53ee042009-01-21 16:41:33114#include "net/url_request/url_request_context.h"
[email protected]f67678062011-01-07 17:33:39115#include "ui/base/animation/animation.h"
[email protected]c051a1b2011-01-21 23:30:17116#include "ui/base/l10n/l10n_util.h"
[email protected]08397d52011-02-05 01:53:38117#include "ui/gfx/point.h"
[email protected]1436beff2010-12-16 19:47:04118#include "webkit/glue/webkit_glue.h"
[email protected]d938aed92009-01-22 19:49:33119#include "webkit/glue/window_open_disposition.h"
[email protected]8a53ee042009-01-21 16:41:33120
121#if defined(OS_WIN)
[email protected]b99603c2010-12-30 22:13:32122#include "app/win/shell.h"
[email protected]36d5e5592010-11-15 20:45:59123#include "chrome/browser/autofill/autofill_ie_toolbar_import_win.h"
[email protected]37936ee2008-09-14 01:09:50124#include "chrome/browser/download/save_package.h"
[email protected]12f520c2010-01-06 18:11:15125#include "chrome/browser/shell_integration.h"
[email protected]b17d41c2011-02-17 22:09:59126#include "chrome/browser/ssl/ssl_error_info.h"
[email protected]a5d1e1e2010-09-23 19:34:12127#include "chrome/browser/task_manager/task_manager.h"
[email protected]6a3ec2312010-12-02 19:30:19128#include "chrome/browser/ui/view_ids.h"
129#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
[email protected]8a53ee042009-01-21 16:41:33130#endif // OS_WIN
[email protected]e1acf6f2008-10-27 20:43:33131
[email protected]6a4f5af22009-09-23 22:43:00132#if defined(OS_MACOSX)
[email protected]7d791652010-12-01 16:34:49133#include "chrome/browser/ui/cocoa/find_pasteboard.h"
[email protected]6a4f5af22009-09-23 22:43:00134#endif
135
[email protected]b7969202010-05-14 21:29:26136#if defined(OS_CHROMEOS)
[email protected]6a2a61d2010-11-22 03:25:35137#include "chrome/browser/chromeos/boot_times_loader.h"
[email protected]b7969202010-05-14 21:29:26138#endif
139
[email protected]8a53ee042009-01-21 16:41:33140using base::TimeDelta;
initial.commit09911bf2008-07-26 23:55:29141
[email protected]36b6dcb2008-11-12 01:19:57142///////////////////////////////////////////////////////////////////////////////
initial.commit09911bf2008-07-26 23:55:29143
[email protected]505323e22009-01-24 02:47:58144namespace {
145
[email protected]91a79232010-11-10 18:15:08146// The URL to be loaded to display Help.
[email protected]8332c162011-01-26 12:01:54147const char kHelpContentUrl[] =
[email protected]91a79232010-11-10 18:15:08148#if defined(OS_CHROMEOS)
[email protected]8332c162011-01-26 12:01:54149 #if defined(OFFICIAL_BUILD)
150 "chrome-extension://honijodknafkokifofgiaalefdiedpko/main.html";
151 #else
152 "http://www.google.com/support/chromeos/";
153 #endif
[email protected]91a79232010-11-10 18:15:08154#else
[email protected]91a79232010-11-10 18:15:08155 "http://www.google.com/support/chrome/";
156#endif
157
158// The URL to be opened when the Help link on the Autofill dialog is clicked.
159const char kAutofillHelpUrl[] =
160#if defined(OS_CHROMEOS)
161 "http://www.google.com/support/chromeos/bin/answer.py?answer=142893";
162#else
163 "http://www.google.com/support/chrome/bin/answer.py?answer=142893";
164#endif
165
166// The URL to be loaded to display the "Report a broken page" form.
167const char kBrokenPageUrl[] =
168 "http://www.google.com/support/chrome/bin/request.py?contact_type="
169 "broken_website&format=inproduct&p.page_title=$1&p.page_url=$2";
170
171// The URL for the privacy dashboard.
172const char kPrivacyDashboardUrl[] = "https://www.google.com/dashboard";
173
174// How long we wait before updating the browser chrome while loading a page.
175const int kUIUpdateCoalescingTimeMS = 200;
176
177const char kHashMark[] = "#";
178
[email protected]57b839a2010-10-04 22:49:45179#if defined(OS_CHROMEOS)
180// If a popup window is bigger than this fraction of the screen on chrome os,
181// turn it into a tab
182const float kPopupMaxWidthFactor = 0.5;
183const float kPopupMaxHeightFactor = 0.6;
184#endif
185
[email protected]505323e22009-01-24 02:47:58186} // namespace
187
[email protected]e838eaf2010-10-13 18:53:33188extern bool g_log_bug53991;
189
[email protected]36b6dcb2008-11-12 01:19:57190///////////////////////////////////////////////////////////////////////////////
191// Browser, Constructors, Creation, Showing:
initial.commit09911bf2008-07-26 23:55:29192
[email protected]299dabd2008-11-19 02:27:16193Browser::Browser(Type type, Profile* profile)
[email protected]15952e462008-11-14 00:29:05194 : type_(type),
195 profile_(profile),
[email protected]f3e99e32008-07-30 04:48:39196 window_(NULL),
[email protected]ecc523f62010-09-28 22:45:40197 ALLOW_THIS_IN_INITIALIZER_LIST(
198 tab_handler_(TabHandler::CreateTabHandler(this))),
[email protected]1fc025202009-01-20 23:03:14199 command_updater_(this),
initial.commit09911bf2008-07-26 23:55:29200 toolbar_model_(this),
[email protected]15952e462008-11-14 00:29:05201 chrome_updater_factory_(this),
202 is_attempting_to_close_browser_(false),
[email protected]69444cc2009-04-09 20:40:06203 cancel_download_confirmation_state_(NOT_PROMPTED),
[email protected]2e716622009-03-09 21:11:01204 maximized_state_(MAXIMIZED_STATE_DEFAULT),
[email protected]867125a02009-12-10 06:01:48205 method_factory_(this),
206 block_command_execution_(false),
207 last_blocked_command_id_(-1),
[email protected]eabfdae92009-12-11 06:13:51208 last_blocked_command_disposition_(CURRENT_TAB),
[email protected]94ce7252010-12-20 21:46:33209 pending_web_app_action_(NONE) {
[email protected]0cb94102009-05-22 19:51:21210 registrar_.Add(this, NotificationType::SSL_VISIBLE_STATE_CHANGED,
211 NotificationService::AllSources());
[email protected]0c6da502009-08-14 22:32:39212 registrar_.Add(this, NotificationType::EXTENSION_UPDATE_DISABLED,
213 NotificationService::AllSources());
[email protected]ad0c2e1b2010-01-30 00:00:10214 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
215 NotificationService::AllSources());
[email protected]0cb94102009-05-22 19:51:21216 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
217 NotificationService::AllSources());
[email protected]0dfe05c2011-02-23 23:03:36218 registrar_.Add(this, NotificationType::EXTENSION_UNINSTALLED,
219 NotificationService::AllSources());
[email protected]a4ed6282009-12-14 20:51:16220 registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED,
[email protected]371ed7a2009-08-25 15:22:46221 NotificationService::AllSources());
[email protected]e001d412009-06-26 20:53:25222 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
223 NotificationService::AllSources());
[email protected]e587a45f2009-10-30 22:34:41224 registrar_.Add(this, NotificationType::PROFILE_ERROR,
[email protected]0e30ef72009-09-05 00:05:08225 NotificationService::AllSources());
initial.commit09911bf2008-07-26 23:55:29226
[email protected]91e1bd82009-09-03 22:04:40227 // Need to know when to alert the user of theme install delay.
228 registrar_.Add(this, NotificationType::EXTENSION_READY_FOR_INSTALL,
229 NotificationService::AllSources());
230
[email protected]6e6f6cb2011-01-27 13:26:55231 // NOTE: These prefs all need to be explicitly destroyed in the destructor
232 // or you'll get a nasty surprise when you run the incognito tests.
[email protected]9e823662010-10-13 23:36:00233 PrefService* local_state = g_browser_process->local_state();
234 if (local_state)
235 printing_enabled_.Init(prefs::kPrintingEnabled, local_state, this);
[email protected]543432ee2010-10-22 16:32:13236 dev_tools_disabled_.Init(prefs::kDevToolsDisabled,
237 profile_->GetPrefs(), this);
[email protected]6e6f6cb2011-01-27 13:26:55238 incognito_mode_allowed_.Init(prefs::kIncognitoEnabled,
239 profile_->GetPrefs(), this);
[email protected]9e823662010-10-13 23:36:00240
initial.commit09911bf2008-07-26 23:55:29241 InitCommandState();
242 BrowserList::AddBrowser(this);
243
244 encoding_auto_detect_.Init(prefs::kWebKitUsesUniversalDetector,
245 profile_->GetPrefs(), NULL);
[email protected]b9c505b2010-04-30 15:05:10246 use_vertical_tabs_.Init(prefs::kUseVerticalTabs, profile_->GetPrefs(), this);
[email protected]73de26a2010-10-17 03:23:25247 instant_enabled_.Init(prefs::kInstantEnabled, profile_->GetPrefs(), this);
[email protected]b9c505b2010-04-30 15:05:10248 if (!TabMenuModel::AreVerticalTabsEnabled()) {
249 // If vertical tabs aren't enabled, explicitly turn them off. Otherwise we
250 // might show vertical tabs but not show an option to turn them off.
251 use_vertical_tabs_.SetValue(false);
252 }
[email protected]b3344872010-05-03 15:52:29253 UpdateTabStripModelInsertionPolicy();
[email protected]281918912010-05-27 22:05:13254
255 tab_restore_service_ = profile->GetTabRestoreService();
256 if (tab_restore_service_) {
257 tab_restore_service_->AddObserver(this);
258 TabRestoreServiceChanged(tab_restore_service_);
259 }
[email protected]d3b98c82010-07-14 07:45:59260
261 if (profile_->GetProfileSyncService())
262 profile_->GetProfileSyncService()->AddObserver(this);
[email protected]03bb953d2010-09-14 21:38:30263
[email protected]2031cf9d2010-10-12 05:05:37264 CreateInstantIfNecessary();
[email protected]07d490bc2011-03-07 17:05:26265
266 // Make sure TabFinder has been created. This does nothing if TabFinder is
267 // not enabled.
268 TabFinder::GetInstance();
initial.commit09911bf2008-07-26 23:55:29269}
270
271Browser::~Browser() {
[email protected]5044da82010-10-27 01:09:16272 VLOG_IF(1, g_log_bug53991) << "~Browser: " << profile_->IsOffTheRecord()
273 << "; stillActive="
274 << BrowserList::IsOffTheRecordSessionActive();
[email protected]e838eaf2010-10-13 18:53:33275
[email protected]d3b98c82010-07-14 07:45:59276 if (profile_->GetProfileSyncService())
277 profile_->GetProfileSyncService()->RemoveObserver(this);
278
initial.commit09911bf2008-07-26 23:55:29279 BrowserList::RemoveBrowser(this);
280
[email protected]fbc947b2009-06-19 13:28:24281#if defined(OS_WIN) || defined(OS_LINUX)
initial.commit09911bf2008-07-26 23:55:29282 if (!BrowserList::HasBrowserWithProfile(profile_)) {
283 // We're the last browser window with this profile. We need to nuke the
284 // TabRestoreService, which will start the shutdown of the
285 // NavigationControllers and allow for proper shutdown. If we don't do this
286 // chrome won't shutdown cleanly, and may end up crashing when some
287 // thread tries to use the IO thread (or another thread) that is no longer
288 // valid.
[email protected]fbc947b2009-06-19 13:28:24289 // This isn't a valid assumption for Mac OS, as it stays running after
290 // the last browser has closed. The Mac equivalent is in its app
291 // controller.
initial.commit09911bf2008-07-26 23:55:29292 profile_->ResetTabRestoreService();
293 }
[email protected]fbc947b2009-06-19 13:28:24294#endif
initial.commit09911bf2008-07-26 23:55:29295
296 SessionService* session_service = profile_->GetSessionService();
297 if (session_service)
298 session_service->WindowClosed(session_id_);
299
[email protected]d8375fd2008-11-25 22:45:39300 TabRestoreService* tab_restore_service = profile()->GetTabRestoreService();
301 if (tab_restore_service)
302 tab_restore_service->BrowserClosed(this);
303
[email protected]9a8c4022011-01-25 14:25:33304 encoding_auto_detect_.Destroy();
305 printing_enabled_.Destroy();
306 dev_tools_disabled_.Destroy();
[email protected]6e6f6cb2011-01-27 13:26:55307 incognito_mode_allowed_.Destroy();
[email protected]9a8c4022011-01-25 14:25:33308 instant_enabled_.Destroy();
309 use_vertical_tabs_.Destroy();
310
initial.commit09911bf2008-07-26 23:55:29311 if (profile_->IsOffTheRecord() &&
312 !BrowserList::IsOffTheRecordSessionActive()) {
[email protected]860f55492009-03-27 19:50:59313 // An off-the-record profile is no longer needed, this indirectly
314 // frees its cache and cookies.
315 profile_->GetOriginalProfile()->DestroyOffTheRecordProfile();
initial.commit09911bf2008-07-26 23:55:29316 }
317
318 // There may be pending file dialogs, we need to tell them that we've gone
319 // away so they don't try and call back to us.
320 if (select_file_dialog_.get())
321 select_file_dialog_->ListenerDestroyed();
[email protected]281918912010-05-27 22:05:13322
323 TabRestoreServiceDestroyed(tab_restore_service_);
initial.commit09911bf2008-07-26 23:55:29324}
325
[email protected]15952e462008-11-14 00:29:05326// static
327Browser* Browser::Create(Profile* profile) {
[email protected]299dabd2008-11-19 02:27:16328 Browser* browser = new Browser(TYPE_NORMAL, profile);
[email protected]9800de5e2011-03-11 18:19:49329 browser->InitBrowserWindow();
[email protected]15952e462008-11-14 00:29:05330 return browser;
331}
[email protected]6104acf2008-11-11 22:27:34332
[email protected]15952e462008-11-14 00:29:05333// static
[email protected]1b74d2122010-10-06 16:49:16334Browser* Browser::CreateForPopup(Type type,
335 Profile* profile,
336 TabContents* new_contents,
337 const gfx::Rect& initial_bounds) {
338 DCHECK(type & TYPE_POPUP);
339 Browser* browser = new Browser(type, profile);
340 browser->set_override_bounds(initial_bounds);
[email protected]9800de5e2011-03-11 18:19:49341 browser->InitBrowserWindow();
[email protected]3c9e1872010-11-18 16:17:49342 TabContentsWrapper* wrapper = new TabContentsWrapper(new_contents);
343 browser->tabstrip_model()->AppendTabContents(wrapper, true);
[email protected]9ee17e8c2010-08-10 19:17:31344 return browser;
345}
346
347// static
348Browser* Browser::CreateForType(Type type, Profile* profile) {
349 Browser* browser = new Browser(type, profile);
[email protected]9800de5e2011-03-11 18:19:49350 browser->InitBrowserWindow();
[email protected]15952e462008-11-14 00:29:05351 return browser;
352}
353
354// static
[email protected]57ecc4b2010-08-11 03:02:51355Browser* Browser::CreateForApp(const std::string& app_name,
[email protected]94ce7252010-12-20 21:46:33356 const gfx::Size& window_size,
[email protected]f2989012010-02-04 16:08:29357 Profile* profile,
358 bool is_panel) {
[email protected]f075fe0a22010-04-26 04:06:43359 Browser::Type type = TYPE_APP;
360
[email protected]61a57ce2010-09-24 16:33:03361 if (is_panel) {
362 // TYPE_APP_PANEL is the logical choice. However, the panel UI
363 // is not fully implemented. See crbug/55943.
364 type = TYPE_APP_POPUP;
[email protected]5530ac652010-09-25 05:35:49365 }
[email protected]f075fe0a22010-04-26 04:06:43366
367 Browser* browser = new Browser(type, profile);
[email protected]15952e462008-11-14 00:29:05368 browser->app_name_ = app_name;
[email protected]605cfad2010-06-22 20:49:35369
[email protected]94ce7252010-12-20 21:46:33370 if (!window_size.IsEmpty()) {
371 gfx::Rect initial_pos(window_size);
372 browser->set_override_bounds(initial_pos);
[email protected]fbf3da12010-06-25 17:29:58373 }
[email protected]605cfad2010-06-22 20:49:35374
[email protected]9800de5e2011-03-11 18:19:49375 browser->InitBrowserWindow();
[email protected]605cfad2010-06-22 20:49:35376
[email protected]15952e462008-11-14 00:29:05377 return browser;
378}
379
[email protected]8e48e982009-12-25 11:22:46380// static
381Browser* Browser::CreateForDevTools(Profile* profile) {
382 Browser* browser = new Browser(TYPE_DEVTOOLS, profile);
383 browser->app_name_ = DevToolsWindow::kDevToolsApp;
[email protected]9800de5e2011-03-11 18:19:49384 browser->InitBrowserWindow();
[email protected]8e48e982009-12-25 11:22:46385 return browser;
386}
387
[email protected]9800de5e2011-03-11 18:19:49388void Browser::InitBrowserWindow() {
[email protected]15952e462008-11-14 00:29:05389 DCHECK(!window_);
[email protected]9c45b7182009-08-04 16:44:43390
[email protected]9800de5e2011-03-11 18:19:49391 window_ = CreateBrowserWindow();
[email protected]15952e462008-11-14 00:29:05392
[email protected]80cf3562009-11-17 08:17:24393#if defined(OS_WIN)
[email protected]45446a52010-11-04 17:41:00394 {
395 // TODO: This might hit the disk
396 // http://code.google.com/p/chromium/issues/detail?id=61638
397 base::ThreadRestrictions::ScopedAllowIO allow_io;
398
399 // Set the app user model id for this application to that of the application
400 // name. See http://crbug.com/7028.
[email protected]b99603c2010-12-30 22:13:32401 app::win::SetAppIdForWindow(
[email protected]45446a52010-11-04 17:41:00402 type_ & TYPE_APP ?
403 ShellIntegration::GetAppId(UTF8ToWide(app_name_), profile_->GetPath()) :
404 ShellIntegration::GetChromiumAppId(profile_->GetPath()),
405 window()->GetNativeHandle());
406 }
[email protected]80cf3562009-11-17 08:17:24407#endif
408
[email protected]14d8c66e2009-09-22 00:32:52409 NotificationService::current()->Notify(
410 NotificationType::BROWSER_WINDOW_READY,
411 Source<Browser>(this),
412 NotificationService::NoDetails());
413
[email protected]15952e462008-11-14 00:29:05414 // Show the First Run information bubble if we've been told to.
415 PrefService* local_state = g_browser_process->local_state();
[email protected]be3877f2009-01-14 15:51:10416 if (!local_state)
417 return;
[email protected]da6ce5602009-12-07 23:09:32418 if (local_state->FindPreference(prefs::kShouldShowFirstRunBubble) &&
[email protected]15952e462008-11-14 00:29:05419 local_state->GetBoolean(prefs::kShouldShowFirstRunBubble)) {
[email protected]450028dd2010-08-28 00:24:50420 FirstRun::BubbleType bubble_type = FirstRun::LARGE_BUBBLE;
[email protected]adfe1882010-04-13 23:01:07421 if (local_state->
[email protected]da6ce5602009-12-07 23:09:32422 FindPreference(prefs::kShouldUseOEMFirstRunBubble) &&
[email protected]adfe1882010-04-13 23:01:07423 local_state->GetBoolean(prefs::kShouldUseOEMFirstRunBubble)) {
[email protected]450028dd2010-08-28 00:24:50424 bubble_type = FirstRun::OEM_BUBBLE;
[email protected]adfe1882010-04-13 23:01:07425 } else if (local_state->
426 FindPreference(prefs::kShouldUseMinimalFirstRunBubble) &&
427 local_state->GetBoolean(prefs::kShouldUseMinimalFirstRunBubble)) {
[email protected]450028dd2010-08-28 00:24:50428 bubble_type = FirstRun::MINIMAL_BUBBLE;
[email protected]adfe1882010-04-13 23:01:07429 }
[email protected]15952e462008-11-14 00:29:05430 // Reset the preference so we don't show the bubble for subsequent windows.
431 local_state->ClearPref(prefs::kShouldShowFirstRunBubble);
[email protected]adfe1882010-04-13 23:01:07432 window_->GetLocationBar()->ShowFirstRunBubble(bubble_type);
initial.commit09911bf2008-07-26 23:55:29433 }
[email protected]f69c8852010-10-12 02:36:46434 if (local_state->FindPreference(
435 prefs::kAutoFillPersonalDataManagerFirstRun) &&
436 local_state->GetBoolean(prefs::kAutoFillPersonalDataManagerFirstRun)) {
437 // Notify PDM that this is a first run.
438#if defined(OS_WIN)
439 ImportAutofillDataWin(profile_->GetPersonalDataManager());
440#endif // defined(OS_WIN)
441 // Reset the preference so we don't call it again for subsequent windows.
442 local_state->ClearPref(prefs::kAutoFillPersonalDataManagerFirstRun);
443 }
initial.commit09911bf2008-07-26 23:55:29444}
445
[email protected]36b6dcb2008-11-12 01:19:57446///////////////////////////////////////////////////////////////////////////////
[email protected]5c238752009-06-13 10:29:07447// Getters & Setters
448
449const std::vector<std::wstring>& Browser::user_data_dir_profiles() const {
450 return g_browser_process->user_data_dir_profiles();
451}
452
453void Browser::set_user_data_dir_profiles(
454 const std::vector<std::wstring>& profiles) {
455 g_browser_process->user_data_dir_profiles() = profiles;
456}
457
[email protected]b77cb302009-10-29 04:09:17458FindBarController* Browser::GetFindBarController() {
459 if (!find_bar_controller_.get()) {
460 FindBar* find_bar = BrowserWindow::CreateFindBar(this);
461 find_bar_controller_.reset(new FindBarController(find_bar));
462 find_bar->SetFindBarController(find_bar_controller_.get());
[email protected]9c318862011-02-01 22:27:24463 find_bar_controller_->ChangeTabContents(GetSelectedTabContentsWrapper());
[email protected]b77cb302009-10-29 04:09:17464 find_bar_controller_->find_bar()->MoveWindowIfNecessary(gfx::Rect(), true);
465 }
466 return find_bar_controller_.get();
467}
468
[email protected]24db8a072009-10-29 20:35:37469bool Browser::HasFindBarController() const {
470 return find_bar_controller_.get() != NULL;
471}
472
[email protected]5c238752009-06-13 10:29:07473///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:57474// Browser, Creation Helpers:
475
476// static
[email protected]15952e462008-11-14 00:29:05477void Browser::OpenEmptyWindow(Profile* profile) {
478 Browser* browser = Browser::Create(profile);
[email protected]36b6dcb2008-11-12 01:19:57479 browser->AddBlankTab(true);
[email protected]15952e462008-11-14 00:29:05480 browser->window()->Show();
initial.commit09911bf2008-07-26 23:55:29481}
482
[email protected]36b6dcb2008-11-12 01:19:57483// static
[email protected]fbc947b2009-06-19 13:28:24484void Browser::OpenWindowWithRestoredTabs(Profile* profile) {
485 TabRestoreService* service = profile->GetTabRestoreService();
486 if (service)
487 service->RestoreMostRecentEntry(NULL);
488}
489
490// static
[email protected]36b6dcb2008-11-12 01:19:57491void Browser::OpenURLOffTheRecord(Profile* profile, const GURL& url) {
[email protected]cecc93a2010-10-05 15:58:55492 Browser* browser = GetOrCreateTabbedBrowser(
493 profile->GetOffTheRecordProfile());
494 browser->AddSelectedTabWithURL(url, PageTransition::LINK);
[email protected]15952e462008-11-14 00:29:05495 browser->window()->Show();
[email protected]2baf83d2008-07-30 05:58:17496}
497
[email protected]36b6dcb2008-11-12 01:19:57498// static
[email protected]d83a5602010-09-16 00:22:48499TabContents* Browser::OpenApplication(
500 Profile* profile,
[email protected]9adb9692010-10-29 23:14:02501 const Extension* extension,
[email protected]24bf2022010-10-14 16:34:39502 extension_misc::LaunchContainer container,
503 TabContents* existing_tab) {
[email protected]56869382010-05-11 21:45:46504 TabContents* tab = NULL;
[email protected]4033bd92011-03-08 19:27:04505 ExtensionPrefs* prefs = profile->GetExtensionService()->extension_prefs();
506 prefs->SetActiveBit(extension->id(), true);
[email protected]e3acb7c2010-05-11 19:23:37507
[email protected]9b217652010-10-08 22:04:23508 UMA_HISTOGRAM_ENUMERATION("Extensions.AppLaunchContainer", container, 100);
509
[email protected]bbadaa782010-04-28 21:21:53510 switch (container) {
[email protected]d83a5602010-09-16 00:22:48511 case extension_misc::LAUNCH_WINDOW:
512 case extension_misc::LAUNCH_PANEL:
[email protected]bbadaa782010-04-28 21:21:53513 tab = Browser::OpenApplicationWindow(profile, extension, container,
[email protected]0e71e4152010-12-07 04:16:26514 GURL(), NULL);
[email protected]c28071ad2010-03-12 17:28:56515 break;
[email protected]d83a5602010-09-16 00:22:48516 case extension_misc::LAUNCH_TAB: {
[email protected]24bf2022010-10-14 16:34:39517 tab = Browser::OpenApplicationTab(profile, extension, existing_tab);
[email protected]c28071ad2010-03-12 17:28:56518 break;
519 }
520 default:
521 NOTREACHED();
[email protected]bbadaa782010-04-28 21:21:53522 break;
[email protected]c28071ad2010-03-12 17:28:56523 }
[email protected]bbadaa782010-04-28 21:21:53524 return tab;
[email protected]c28071ad2010-03-12 17:28:56525}
526
527// static
[email protected]bbadaa782010-04-28 21:21:53528TabContents* Browser::OpenApplicationWindow(
529 Profile* profile,
[email protected]9adb9692010-10-29 23:14:02530 const Extension* extension,
[email protected]d83a5602010-09-16 00:22:48531 extension_misc::LaunchContainer container,
[email protected]0e71e4152010-12-07 04:16:26532 const GURL& url_input,
533 Browser** app_browser) {
[email protected]f381dfa2010-04-29 04:41:37534 GURL url;
535 if (!url_input.is_empty()) {
536 if (extension)
537 DCHECK(extension->web_extent().ContainsURL(url_input));
538 url = url_input;
539 } else {
[email protected]ae5909e2011-02-23 14:34:18540 DCHECK(extension); // Empty url and no extension. Nothing to open.
[email protected]f381dfa2010-04-29 04:41:37541 url = extension->GetFullLaunchURL();
542 }
543
[email protected]2f1c09d2011-01-14 14:58:14544 std::string app_name;
545 if (extension)
546 app_name =
547 web_app::GenerateApplicationNameFromExtensionId(extension->id());
548 else
549 app_name = web_app::GenerateApplicationNameFromURL(url);
550
[email protected]f87919d72011-02-02 18:46:16551 RegisterAppPrefs(app_name, profile);
[email protected]15952e462008-11-14 00:29:05552
[email protected]d83a5602010-09-16 00:22:48553 bool as_panel = extension && (container == extension_misc::LAUNCH_PANEL);
[email protected]94ce7252010-12-20 21:46:33554
555 gfx::Size window_size;
556 if (extension)
557 window_size.SetSize(extension->launch_width(),
558 extension->launch_height());
559
560 Browser* browser = Browser::CreateForApp(app_name, window_size, profile,
[email protected]cecc93a2010-10-05 15:58:55561 as_panel);
[email protected]0e71e4152010-12-07 04:16:26562 if (app_browser)
563 *app_browser = browser;
564
[email protected]3c9e1872010-11-18 16:17:49565 TabContentsWrapper* wrapper =
[email protected]cecc93a2010-10-05 15:58:55566 browser->AddSelectedTabWithURL(url, PageTransition::START_PAGE);
[email protected]3c9e1872010-11-18 16:17:49567 TabContents* contents = wrapper->tab_contents();
[email protected]cecc93a2010-10-05 15:58:55568 contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
569 contents->render_view_host()->SyncRendererPrefs();
570 browser->window()->Show();
[email protected]bbadaa782010-04-28 21:21:53571
[email protected]68f009f2009-02-26 19:43:35572 // TODO(jcampan): http://crbug.com/8123 we should not need to set the initial
573 // focus explicitly.
[email protected]cecc93a2010-10-05 15:58:55574 contents->view()->SetInitialFocus();
[email protected]0e71e4152010-12-07 04:16:26575 return contents;
576}
[email protected]eabfdae92009-12-11 06:13:51577
[email protected]0e71e4152010-12-07 04:16:26578TabContents* Browser::OpenAppShortcutWindow(Profile* profile,
579 const GURL& url,
580 bool update_shortcut) {
581 Browser* app_browser;
582 TabContents* tab = OpenApplicationWindow(
583 profile,
584 NULL, // this is a URL app. No extension.
585 extension_misc::LAUNCH_WINDOW,
586 url,
587 &app_browser);
588
589 if (!tab)
590 return NULL;
591
592 if (update_shortcut) {
[email protected]f45d2a72010-03-08 23:28:35593 // Set UPDATE_SHORTCUT as the pending web app action. This action is picked
594 // up in LoadingStateChanged to schedule a GetApplicationInfo. And when
595 // the web app info is available, TabContents notifies Browser via
[email protected]867a73e12010-03-19 20:45:46596 // OnDidGetApplicationInfo, which calls
597 // web_app::UpdateShortcutForTabContents when it sees UPDATE_SHORTCUT as
598 // pending web app action.
[email protected]0e71e4152010-12-07 04:16:26599 app_browser->pending_web_app_action_ = UPDATE_SHORTCUT;
[email protected]f45d2a72010-03-08 23:28:35600 }
[email protected]0e71e4152010-12-07 04:16:26601 return tab;
[email protected]c28071ad2010-03-12 17:28:56602}
603
604// static
[email protected]bbadaa782010-04-28 21:21:53605TabContents* Browser::OpenApplicationTab(Profile* profile,
[email protected]9adb9692010-10-29 23:14:02606 const Extension* extension,
[email protected]24bf2022010-10-14 16:34:39607 TabContents* existing_tab) {
[email protected]ea86bfb2011-02-08 18:15:44608 Browser* browser =
609 BrowserList::FindBrowserWithType(profile, Browser::TYPE_NORMAL, false);
[email protected]cecc93a2010-10-05 15:58:55610 TabContents* contents = NULL;
[email protected]ea86bfb2011-02-08 18:15:44611 if (!browser)
[email protected]cecc93a2010-10-05 15:58:55612 return contents;
[email protected]c28071ad2010-03-12 17:28:56613
[email protected]10abd192010-09-30 02:03:49614 // Check the prefs for overridden mode.
[email protected]eaa7dd182010-12-14 11:09:00615 ExtensionService* extensions_service = profile->GetExtensionService();
[email protected]10abd192010-09-30 02:03:49616 DCHECK(extensions_service);
[email protected]b283a7532010-08-12 21:24:59617
[email protected]10abd192010-09-30 02:03:49618 ExtensionPrefs::LaunchType launch_type =
[email protected]a3b734b2010-11-30 03:17:11619 extensions_service->extension_prefs()->GetLaunchType(
[email protected]4e595682011-02-09 17:07:02620 extension->id(), ExtensionPrefs::LAUNCH_DEFAULT);
[email protected]9b217652010-10-08 22:04:23621 UMA_HISTOGRAM_ENUMERATION("Extensions.AppTabLaunchType", launch_type, 100);
[email protected]10abd192010-09-30 02:03:49622 int add_type = TabStripModel::ADD_SELECTED;
623 if (launch_type == ExtensionPrefs::LAUNCH_PINNED)
624 add_type |= TabStripModel::ADD_PINNED;
625
[email protected]37fcf262011-01-26 19:39:15626 // For extensions lacking launch urls, determine a reasonable fallback.
627 GURL extension_url = extension->GetFullLaunchURL();
628 if (!extension_url.is_valid()) {
629 extension_url = extension->options_url();
630 if (!extension_url.is_valid())
631 extension_url = GURL(chrome::kChromeUIExtensionsURL);
632 }
633
[email protected]10abd192010-09-30 02:03:49634 // TODO(erikkay): START_PAGE doesn't seem like the right transition in all
635 // cases.
[email protected]37fcf262011-01-26 19:39:15636 browser::NavigateParams params(browser, extension_url,
[email protected]616381f02010-11-02 15:15:33637 PageTransition::START_PAGE);
638 params.tabstrip_add_types = add_type;
[email protected]24bf2022010-10-14 16:34:39639
640 // Launch the application in the existing TabContents, if it was supplied.
641 if (existing_tab) {
642 TabStripModel* model = browser->tabstrip_model();
[email protected]3c9e1872010-11-18 16:17:49643 int tab_index = model->GetWrapperIndex(existing_tab);
[email protected]24bf2022010-10-14 16:34:39644
645 existing_tab->OpenURL(extension->GetFullLaunchURL(), existing_tab->GetURL(),
646 CURRENT_TAB, PageTransition::LINK);
[email protected]616381f02010-11-02 15:15:33647 if (params.tabstrip_add_types & TabStripModel::ADD_PINNED) {
[email protected]24bf2022010-10-14 16:34:39648 model->SetTabPinned(tab_index, true);
[email protected]3c9e1872010-11-18 16:17:49649 tab_index = model->GetWrapperIndex(existing_tab);
[email protected]7dfec4212010-11-01 22:12:26650 }
[email protected]616381f02010-11-02 15:15:33651 if (params.tabstrip_add_types & TabStripModel::ADD_SELECTED)
[email protected]24bf2022010-10-14 16:34:39652 model->SelectTabContentsAt(tab_index, true);
653
654 contents = existing_tab;
655 } else {
[email protected]616381f02010-11-02 15:15:33656 params.disposition = NEW_FOREGROUND_TAB;
657 browser::Navigate(&params);
[email protected]3c9e1872010-11-18 16:17:49658 contents = params.target_contents->tab_contents();
[email protected]24bf2022010-10-14 16:34:39659 }
660
[email protected]7bd42fc2011-02-09 17:32:42661 // TODO(skerner): If we are already in full screen mode, and the user
662 // set the app to open as a regular or pinned tab, what should happen?
663 // Today we open the tab, but stay in full screen mode. Should we leave
664 // full screen mode in this case?
665 if (launch_type == ExtensionPrefs::LAUNCH_FULLSCREEN &&
666 !browser->window()->IsFullscreen())
667 browser->ToggleFullscreenMode();
[email protected]10abd192010-09-30 02:03:49668
[email protected]cecc93a2010-10-05 15:58:55669 return contents;
[email protected]c28071ad2010-03-12 17:28:56670}
671
672// static
[email protected]90a8bf252010-03-12 00:09:47673void Browser::OpenBookmarkManagerWindow(Profile* profile) {
674 Browser* browser = Browser::Create(profile);
675 browser->ShowBookmarkManagerTab();
676 browser->window()->Show();
677}
678
[email protected]057d959a2010-03-12 02:56:20679#if defined(OS_MACOSX)
[email protected]90a8bf252010-03-12 00:09:47680// static
[email protected]91a5b3e2009-10-30 19:32:22681void Browser::OpenHistoryWindow(Profile* profile) {
682 Browser* browser = Browser::Create(profile);
683 browser->ShowHistoryTab();
684 browser->window()->Show();
685}
686
687// static
688void Browser::OpenDownloadsWindow(Profile* profile) {
689 Browser* browser = Browser::Create(profile);
690 browser->ShowDownloadsTab();
691 browser->window()->Show();
692}
693
694// static
[email protected]1fdff702009-10-22 00:36:18695void Browser::OpenHelpWindow(Profile* profile) {
696 Browser* browser = Browser::Create(profile);
697 browser->OpenHelpTab();
698 browser->window()->Show();
699}
[email protected]4a42d272010-06-18 01:29:42700
[email protected]eca258132010-11-15 23:33:08701// static
[email protected]4a42d272010-06-18 01:29:42702void Browser::OpenOptionsWindow(Profile* profile) {
703 Browser* browser = Browser::Create(profile);
[email protected]fee320542011-03-02 01:30:49704 browser->OpenOptionsDialog();
[email protected]4a42d272010-06-18 01:29:42705 browser->window()->Show();
706}
[email protected]c8de64a2011-01-25 17:10:23707
708// static
709void Browser::OpenClearBrowingDataDialogWindow(Profile* profile) {
710 Browser* browser = Browser::Create(profile);
711 browser->OpenClearBrowsingDataDialog();
712 browser->window()->Show();
713}
714
715// static
716void Browser::OpenImportSettingsDialogWindow(Profile* profile) {
717 Browser* browser = Browser::Create(profile);
718 browser->OpenImportSettingsDialog();
719 browser->window()->Show();
720}
[email protected]b99081b2011-03-10 17:43:47721
722// static
723void Browser::OpenInstantConfirmDialogWindow(Profile* profile) {
724 Browser* browser = Browser::Create(profile);
725 browser->OpenInstantConfirmDialog();
726 browser->window()->Show();
727}
[email protected]1fdff702009-10-22 00:36:18728#endif
729
[email protected]ccb55cf52010-03-06 22:02:04730// static
731void Browser::OpenExtensionsWindow(Profile* profile) {
732 Browser* browser = Browser::Create(profile);
733 browser->ShowExtensionsTab();
734 browser->window()->Show();
735}
736
737
[email protected]36b6dcb2008-11-12 01:19:57738///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:57739// Browser, State Storage and Retrieval for UI:
740
[email protected]57ecc4b2010-08-11 03:02:51741std::string Browser::GetWindowPlacementKey() const {
742 std::string name(prefs::kBrowserWindowPlacement);
[email protected]36b6dcb2008-11-12 01:19:57743 if (!app_name_.empty()) {
[email protected]57ecc4b2010-08-11 03:02:51744 name.append("_");
[email protected]36b6dcb2008-11-12 01:19:57745 name.append(app_name_);
746 }
[email protected]bc9a5152008-11-15 00:32:04747 return name;
748}
[email protected]36b6dcb2008-11-12 01:19:57749
[email protected]bc9a5152008-11-15 00:32:04750bool Browser::ShouldSaveWindowPlacement() const {
[email protected]25ef2b72009-12-09 05:06:51751 // Only save the window placement of popups if they are restored.
752 return (type() & TYPE_POPUP) == 0 || browser_defaults::kRestorePopups;
[email protected]bc9a5152008-11-15 00:32:04753}
[email protected]36b6dcb2008-11-12 01:19:57754
[email protected]bc9a5152008-11-15 00:32:04755void Browser::SaveWindowPlacement(const gfx::Rect& bounds, bool maximized) {
756 // Save to the session storage service, used when reloading a past session.
757 // Note that we don't want to be the ones who cause lazy initialization of
758 // the session service. This function gets called during initial window
759 // showing, and we don't want to bring in the session service this early.
[email protected]36b6dcb2008-11-12 01:19:57760 if (profile()->HasSessionService()) {
761 SessionService* session_service = profile()->GetSessionService();
762 if (session_service)
763 session_service->SetWindowBounds(session_id_, bounds, maximized);
764 }
765}
766
[email protected]15952e462008-11-14 00:29:05767gfx::Rect Browser::GetSavedWindowBounds() const {
[email protected]bb975362009-01-21 01:00:22768 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
[email protected]15952e462008-11-14 00:29:05769 bool record_mode = parsed_command_line.HasSwitch(switches::kRecordMode);
770 bool playback_mode = parsed_command_line.HasSwitch(switches::kPlaybackMode);
771 if (record_mode || playback_mode) {
772 // In playback/record mode we always fix the size of the browser and
773 // move it to (0,0). The reason for this is two reasons: First we want
774 // resize/moves in the playback to still work, and Second we want
775 // playbacks to work (as much as possible) on machines w/ different
776 // screen sizes.
777 return gfx::Rect(0, 0, 800, 600);
778 }
779
780 gfx::Rect restored_bounds = override_bounds_;
781 bool maximized;
[email protected]f87919d72011-02-02 18:46:16782 WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, this,
[email protected]15952e462008-11-14 00:29:05783 &restored_bounds, &maximized);
784 return restored_bounds;
785}
786
787// TODO(beng): obtain maximized state some other way so we don't need to go
788// through all this hassle.
789bool Browser::GetSavedMaximizedState() const {
[email protected]bb975362009-01-21 01:00:22790 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kStartMaximized))
[email protected]15952e462008-11-14 00:29:05791 return true;
792
[email protected]2e716622009-03-09 21:11:01793 if (maximized_state_ == MAXIMIZED_STATE_MAXIMIZED)
794 return true;
795 if (maximized_state_ == MAXIMIZED_STATE_UNMAXIMIZED)
796 return false;
797
798 // An explicit maximized state was not set. Query the window sizer.
[email protected]15952e462008-11-14 00:29:05799 gfx::Rect restored_bounds;
[email protected]2e716622009-03-09 21:11:01800 bool maximized = false;
[email protected]f87919d72011-02-02 18:46:16801 WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, this,
[email protected]15952e462008-11-14 00:29:05802 &restored_bounds, &maximized);
803 return maximized;
[email protected]36b6dcb2008-11-12 01:19:57804}
805
806SkBitmap Browser::GetCurrentPageIcon() const {
[email protected]ce5348a82008-12-18 18:36:23807 TabContents* contents = GetSelectedTabContents();
808 // |contents| can be NULL since GetCurrentPageIcon() is called by the window
809 // during the window's creation (before tabs have been added).
810 return contents ? contents->GetFavIcon() : SkBitmap();
[email protected]36b6dcb2008-11-12 01:19:57811}
812
[email protected]731f8a42009-07-20 22:07:32813string16 Browser::GetWindowTitleForCurrentTab() const {
[email protected]3c9e1872010-11-18 16:17:49814 TabContents* contents = GetSelectedTabContents();
[email protected]dda5dfa32009-07-10 00:33:29815 string16 title;
[email protected]c7c42332008-11-15 01:10:54816
[email protected]731f8a42009-07-20 22:07:32817 // |contents| can be NULL because GetWindowTitleForCurrentTab is called by the
818 // window during the window's creation (before tabs have been added).
[email protected]36b6dcb2008-11-12 01:19:57819 if (contents) {
[email protected]dda5dfa32009-07-10 00:33:29820 title = contents->GetTitle();
[email protected]36b6dcb2008-11-12 01:19:57821 FormatTitleForDisplay(&title);
822 }
823 if (title.empty())
[email protected]0dd3a0ab2011-02-18 08:17:44824 title = TabContentsWrapper::GetDefaultTitle();
[email protected]36b6dcb2008-11-12 01:19:57825
[email protected]16779842009-07-08 23:45:29826#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
[email protected]22a3daa2009-11-09 22:03:33827 // On Mac or ChromeOS, we don't want to suffix the page title with
828 // the application name.
[email protected]d904bc82009-07-07 00:41:04829 return title;
830#elif defined(OS_WIN) || defined(OS_LINUX)
[email protected]edb5e6a2009-04-08 23:46:17831 int string_id = IDS_BROWSER_WINDOW_TITLE_FORMAT;
[email protected]dff529732010-04-01 23:50:55832 // Don't append the app name to window titles on app frames and app popups
833 if (type_ & TYPE_APP)
[email protected]edb5e6a2009-04-08 23:46:17834 string_id = IDS_BROWSER_WINDOW_TITLE_FORMAT_NO_LOGO;
[email protected]dda5dfa32009-07-10 00:33:29835 return l10n_util::GetStringFUTF16(string_id, title);
[email protected]57e68dba2009-05-15 21:30:50836#endif
[email protected]36b6dcb2008-11-12 01:19:57837}
838
839// static
[email protected]dda5dfa32009-07-10 00:33:29840void Browser::FormatTitleForDisplay(string16* title) {
[email protected]36b6dcb2008-11-12 01:19:57841 size_t current_index = 0;
842 size_t match_index;
[email protected]57ecc4b2010-08-11 03:02:51843 while ((match_index = title->find(L'\n', current_index)) != string16::npos) {
[email protected]810a52ef2010-01-08 01:22:15844 title->replace(match_index, 1, string16());
[email protected]36b6dcb2008-11-12 01:19:57845 current_index = match_index;
846 }
847}
848
849///////////////////////////////////////////////////////////////////////////////
850// Browser, OnBeforeUnload handling:
851
[email protected]460a2942010-12-15 19:43:15852bool Browser::TabsNeedBeforeUnloadFired() {
853 if (tabs_needing_before_unload_fired_.empty()) {
854 for (int i = 0; i < tab_count(); ++i) {
855 TabContents* contents = GetTabContentsAt(i);
856 if (contents->NeedToFireBeforeUnload())
857 tabs_needing_before_unload_fired_.insert(contents);
858 }
859 }
860 return !tabs_needing_before_unload_fired_.empty();
861}
862
[email protected]36b6dcb2008-11-12 01:19:57863bool Browser::ShouldCloseWindow() {
[email protected]69444cc2009-04-09 20:40:06864 if (!CanCloseWithInProgressDownloads())
865 return false;
866
867 if (HasCompletedUnloadProcessing())
[email protected]0b4d3382010-07-14 16:13:04868 return IsClosingPermitted();
[email protected]69444cc2009-04-09 20:40:06869
[email protected]36b6dcb2008-11-12 01:19:57870 is_attempting_to_close_browser_ = true;
871
[email protected]460a2942010-12-15 19:43:15872 if (!TabsNeedBeforeUnloadFired())
[email protected]0b4d3382010-07-14 16:13:04873 return IsClosingPermitted();
[email protected]36b6dcb2008-11-12 01:19:57874
875 ProcessPendingTabs();
876 return false;
877}
878
879void Browser::OnWindowClosing() {
880 if (!ShouldCloseWindow())
881 return;
882
[email protected]911f8152010-03-18 16:46:40883 bool exiting = false;
884
[email protected]c984d9f2010-07-20 20:52:20885 // Application should shutdown on last window close if the user is explicitly
886 // trying to quit, or if there is nothing keeping the browser alive (such as
887 // AppController on the Mac, or BackgroundContentsService for background
888 // pages).
889 bool should_quit_if_last_browser =
890 browser_shutdown::IsTryingToQuit() || !BrowserList::WillKeepAlive();
[email protected]7dc8c6b2010-04-09 17:02:50891
892 if (should_quit_if_last_browser && BrowserList::size() == 1) {
[email protected]36b6dcb2008-11-12 01:19:57893 browser_shutdown::OnShutdownStarting(browser_shutdown::WINDOW_CLOSE);
[email protected]911f8152010-03-18 16:46:40894 exiting = true;
895 }
[email protected]36b6dcb2008-11-12 01:19:57896
897 // Don't use HasSessionService here, we want to force creation of the
898 // session service so that user can restore what was open.
899 SessionService* session_service = profile()->GetSessionService();
900 if (session_service)
901 session_service->WindowClosing(session_id());
902
[email protected]d8375fd2008-11-25 22:45:39903 TabRestoreService* tab_restore_service = profile()->GetTabRestoreService();
904 if (tab_restore_service)
905 tab_restore_service->BrowserClosing(this);
906
[email protected]911f8152010-03-18 16:46:40907 // TODO(sky): convert session/tab restore to use notification.
908 NotificationService::current()->Notify(
909 NotificationType::BROWSER_CLOSING,
910 Source<Browser>(this),
911 Details<bool>(&exiting));
912
[email protected]36b6dcb2008-11-12 01:19:57913 CloseAllTabs();
914}
915
[email protected]69444cc2009-04-09 20:40:06916////////////////////////////////////////////////////////////////////////////////
917// In-progress download termination handling:
918
919void Browser::InProgressDownloadResponse(bool cancel_downloads) {
920 if (cancel_downloads) {
921 cancel_download_confirmation_state_ = RESPONSE_RECEIVED;
922 CloseWindow();
923 return;
924 }
925
926 // Sets the confirmation state to NOT_PROMPTED so that if the user tries to
927 // close again we'll show the warning again.
928 cancel_download_confirmation_state_ = NOT_PROMPTED;
929
930 // Show the download page so the user can figure-out what downloads are still
931 // in-progress.
932 ShowDownloadsTab();
933}
934
[email protected]69444cc2009-04-09 20:40:06935////////////////////////////////////////////////////////////////////////////////
[email protected]c848d3d92010-09-16 21:57:45936// Browser, TabStripModel pass-thrus:
937
938int Browser::tab_count() const {
[email protected]ecc523f62010-09-28 22:45:40939 return tab_handler_->GetTabStripModel()->count();
[email protected]c848d3d92010-09-16 21:57:45940}
941
942int Browser::selected_index() const {
[email protected]ecc523f62010-09-28 22:45:40943 return tab_handler_->GetTabStripModel()->selected_index();
[email protected]c848d3d92010-09-16 21:57:45944}
945
946int Browser::GetIndexOfController(
947 const NavigationController* controller) const {
[email protected]ecc523f62010-09-28 22:45:40948 return tab_handler_->GetTabStripModel()->GetIndexOfController(controller);
[email protected]c848d3d92010-09-16 21:57:45949}
950
[email protected]3c9e1872010-11-18 16:17:49951TabContentsWrapper* Browser::GetSelectedTabContentsWrapper() const {
952 return tabstrip_model()->GetSelectedTabContents();
953}
954TabContentsWrapper* Browser::GetTabContentsWrapperAt(int index) const {
955 return tabstrip_model()->GetTabContentsAt(index);
[email protected]c848d3d92010-09-16 21:57:45956}
957
958TabContents* Browser::GetSelectedTabContents() const {
[email protected]3c9e1872010-11-18 16:17:49959 TabContentsWrapper* wrapper = GetSelectedTabContentsWrapper();
960 if (wrapper)
961 return wrapper->tab_contents();
962 return NULL;
963}
964
965TabContents* Browser::GetTabContentsAt(int index) const {
966 TabContentsWrapper* wrapper = tabstrip_model()->GetTabContentsAt(index);
967 if (wrapper)
968 return wrapper->tab_contents();
969 return NULL;
[email protected]c848d3d92010-09-16 21:57:45970}
971
972void Browser::SelectTabContentsAt(int index, bool user_gesture) {
[email protected]ecc523f62010-09-28 22:45:40973 tab_handler_->GetTabStripModel()->SelectTabContentsAt(index, user_gesture);
[email protected]c848d3d92010-09-16 21:57:45974}
975
976void Browser::CloseAllTabs() {
[email protected]ecc523f62010-09-28 22:45:40977 tab_handler_->GetTabStripModel()->CloseAllTabs();
[email protected]c848d3d92010-09-16 21:57:45978}
979
980////////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:57981// Browser, Tab adding/showing functions:
982
[email protected]95bf8a5b2010-12-22 16:04:07983bool Browser::IsTabStripEditable() const {
984 return window()->IsTabStripEditable();
985}
986
[email protected]b3344872010-05-03 15:52:29987int Browser::GetIndexForInsertionDuringRestore(int relative_index) {
[email protected]ecc523f62010-09-28 22:45:40988 return (tab_handler_->GetTabStripModel()->insertion_policy() ==
989 TabStripModel::INSERT_AFTER) ? tab_count() : relative_index;
[email protected]b3344872010-05-03 15:52:29990}
991
[email protected]3c9e1872010-11-18 16:17:49992TabContentsWrapper* Browser::AddSelectedTabWithURL(const GURL& url,
[email protected]cecc93a2010-10-05 15:58:55993 PageTransition::Type transition) {
[email protected]616381f02010-11-02 15:15:33994 browser::NavigateParams params(this, url, transition);
995 params.disposition = NEW_FOREGROUND_TAB;
996 browser::Navigate(&params);
997 return params.target_contents;
[email protected]36b6dcb2008-11-12 01:19:57998}
999
[email protected]3c9e1872010-11-18 16:17:491000TabContents* Browser::AddTab(TabContentsWrapper* tab_contents,
[email protected]d99cdfd2009-10-08 18:58:111001 PageTransition::Type type) {
[email protected]ecc523f62010-09-28 22:45:401002 tab_handler_->GetTabStripModel()->AddTabContents(
[email protected]4a1665442010-06-28 16:09:391003 tab_contents, -1, type, TabStripModel::ADD_SELECTED);
[email protected]3c9e1872010-11-18 16:17:491004 return tab_contents->tab_contents();
[email protected]36b6dcb2008-11-12 01:19:571005}
1006
[email protected]e0c7c262009-04-23 23:09:431007void Browser::AddTabContents(TabContents* new_contents,
1008 WindowOpenDisposition disposition,
1009 const gfx::Rect& initial_pos,
1010 bool user_gesture) {
1011 AddNewContents(NULL, new_contents, disposition, initial_pos, user_gesture);
1012}
1013
1014void Browser::CloseTabContents(TabContents* contents) {
1015 CloseContents(contents);
1016}
1017
1018void Browser::BrowserShowHtmlDialog(HtmlDialogUIDelegate* delegate,
[email protected]322f3ff2009-05-22 16:19:541019 gfx::NativeWindow parent_window) {
[email protected]e0c7c262009-04-23 23:09:431020 ShowHtmlDialog(delegate, parent_window);
1021}
1022
1023void Browser::BrowserRenderWidgetShowing() {
1024 RenderWidgetShowing();
1025}
1026
1027void Browser::ToolbarSizeChanged(bool is_animating) {
1028 ToolbarSizeChanged(NULL, is_animating);
1029}
1030
[email protected]ce3fa3c2009-04-20 19:55:571031TabContents* Browser::AddRestoredTab(
[email protected]36b6dcb2008-11-12 01:19:571032 const std::vector<TabNavigation>& navigations,
1033 int tab_index,
1034 int selected_navigation,
[email protected]98aa0b52010-05-06 17:03:081035 const std::string& extension_app_id,
[email protected]5c0e6482009-07-14 20:20:091036 bool select,
[email protected]5e369672009-11-03 23:48:301037 bool pin,
[email protected]6ee12c42010-09-14 09:36:071038 bool from_last_session,
1039 SessionStorageNamespace* session_storage_namespace) {
[email protected]3c9e1872010-11-18 16:17:491040 TabContentsWrapper* wrapper = TabContentsFactory(profile(), NULL,
1041 MSG_ROUTING_NONE,
1042 GetSelectedTabContents(),
[email protected]ecc523f62010-09-28 22:45:401043 session_storage_namespace);
[email protected]3c9e1872010-11-18 16:17:491044 TabContents* new_tab = wrapper->tab_contents();
[email protected]98aa0b52010-05-06 17:03:081045 new_tab->SetExtensionAppById(extension_app_id);
[email protected]5e369672009-11-03 23:48:301046 new_tab->controller().RestoreFromState(navigations, selected_navigation,
1047 from_last_session);
[email protected]36b6dcb2008-11-12 01:19:571048
[email protected]5c0e6482009-07-14 20:20:091049 bool really_pin =
[email protected]567ef6b2010-02-05 20:31:331050 (pin && tab_index == tabstrip_model()->IndexOfFirstNonMiniTab());
[email protected]ecc523f62010-09-28 22:45:401051 tab_handler_->GetTabStripModel()->InsertTabContentsAt(
[email protected]3c9e1872010-11-18 16:17:491052 tab_index, wrapper,
[email protected]4a1665442010-06-28 16:09:391053 select ? TabStripModel::ADD_SELECTED : TabStripModel::ADD_NONE);
[email protected]5c0e6482009-07-14 20:20:091054 if (really_pin)
[email protected]ecc523f62010-09-28 22:45:401055 tab_handler_->GetTabStripModel()->SetTabPinned(tab_index, true);
[email protected]c93a9dd2010-04-22 20:25:181056 if (select) {
[email protected]77bc6732009-04-20 22:01:031057 window_->Activate();
[email protected]c93a9dd2010-04-22 20:25:181058 } else {
1059 // We set the size of the view here, before WebKit does its initial
1060 // layout. If we don't, the initial layout of background tabs will be
1061 // performed with a view width of 0, which may cause script outputs and
1062 // anchor link location calculations to be incorrect even after a new
1063 // layout with proper view dimensions. TabStripModel::AddTabContents()
1064 // contains similar logic.
1065 new_tab->view()->SizeContents(window_->GetRestoredBounds().size());
1066 new_tab->HideContents();
1067 }
[email protected]36b6dcb2008-11-12 01:19:571068 if (profile_->HasSessionService()) {
1069 SessionService* session_service = profile_->GetSessionService();
1070 if (session_service)
[email protected]5c0e6482009-07-14 20:20:091071 session_service->TabRestored(&new_tab->controller(), really_pin);
[email protected]36b6dcb2008-11-12 01:19:571072 }
[email protected]ce3fa3c2009-04-20 19:55:571073 return new_tab;
[email protected]36b6dcb2008-11-12 01:19:571074}
1075
1076void Browser::ReplaceRestoredTab(
1077 const std::vector<TabNavigation>& navigations,
[email protected]5e369672009-11-03 23:48:301078 int selected_navigation,
[email protected]fca656c2010-02-10 20:30:101079 bool from_last_session,
[email protected]6ee12c42010-09-14 09:36:071080 const std::string& extension_app_id,
1081 SessionStorageNamespace* session_storage_namespace) {
[email protected]3c9e1872010-11-18 16:17:491082 TabContentsWrapper* wrapper = TabContentsFactory(profile(), NULL,
[email protected]ecc523f62010-09-28 22:45:401083 MSG_ROUTING_NONE,
[email protected]3c9e1872010-11-18 16:17:491084 GetSelectedTabContents(),
[email protected]6ee12c42010-09-14 09:36:071085 session_storage_namespace);
[email protected]3c9e1872010-11-18 16:17:491086 TabContents* replacement = wrapper->tab_contents();
[email protected]98aa0b52010-05-06 17:03:081087 replacement->SetExtensionAppById(extension_app_id);
[email protected]5e369672009-11-03 23:48:301088 replacement->controller().RestoreFromState(navigations, selected_navigation,
1089 from_last_session);
[email protected]36b6dcb2008-11-12 01:19:571090
[email protected]ecc523f62010-09-28 22:45:401091 tab_handler_->GetTabStripModel()->ReplaceNavigationControllerAt(
1092 tab_handler_->GetTabStripModel()->selected_index(),
[email protected]3c9e1872010-11-18 16:17:491093 wrapper);
[email protected]36b6dcb2008-11-12 01:19:571094}
1095
[email protected]a8eff102009-04-14 15:23:431096bool Browser::CanRestoreTab() {
[email protected]281918912010-05-27 22:05:131097 return command_updater_.IsCommandEnabled(IDC_RESTORE_TAB);
[email protected]a8eff102009-04-14 15:23:431098}
1099
[email protected]3698f172010-03-17 20:50:291100bool Browser::NavigateToIndexWithDisposition(int index,
1101 WindowOpenDisposition disp) {
1102 NavigationController& controller =
[email protected]cb84d642010-06-10 00:56:281103 GetOrCloneTabForDisposition(disp)->controller();
1104 if (index < 0 || index >= controller.entry_count())
[email protected]3698f172010-03-17 20:50:291105 return false;
[email protected]cb84d642010-06-10 00:56:281106 controller.GoToIndex(index);
1107 return true;
[email protected]3698f172010-03-17 20:50:291108}
1109
[email protected]fee320542011-03-02 01:30:491110browser::NavigateParams Browser::GetSingletonTabNavigateParams(
1111 const GURL& url) {
[email protected]616381f02010-11-02 15:15:331112 browser::NavigateParams params(this, url, PageTransition::AUTO_BOOKMARK);
1113 params.disposition = SINGLETON_TAB;
1114 params.show_window = true;
[email protected]fee320542011-03-02 01:30:491115 return params;
1116}
1117
1118void Browser::ShowSingletonTab(const GURL& url) {
1119 browser::NavigateParams params(GetSingletonTabNavigateParams(url));
[email protected]616381f02010-11-02 15:15:331120 browser::Navigate(&params);
[email protected]36b6dcb2008-11-12 01:19:571121}
[email protected]d938aed92009-01-22 19:49:331122
[email protected]ae2622c2009-07-30 23:47:581123void Browser::UpdateCommandsForFullscreenMode(bool is_fullscreen) {
[email protected]326464d2010-02-16 22:21:101124#if !defined(OS_MACOSX)
[email protected]ae2622c2009-07-30 23:47:581125 const bool show_main_ui = (type() == TYPE_NORMAL) && !is_fullscreen;
[email protected]326464d2010-02-16 22:21:101126#else
1127 const bool show_main_ui = (type() == TYPE_NORMAL);
1128#endif
[email protected]ae2622c2009-07-30 23:47:581129
[email protected]83548a42010-06-18 13:53:371130 bool main_not_fullscreen_or_popup =
1131 show_main_ui && !is_fullscreen && (type() & TYPE_POPUP) == 0;
1132
[email protected]ae2622c2009-07-30 23:47:581133 // Navigation commands
1134 command_updater_.UpdateCommandEnabled(IDC_OPEN_CURRENT_URL, show_main_ui);
1135
1136 // Window management commands
[email protected]ae2622c2009-07-30 23:47:581137 command_updater_.UpdateCommandEnabled(IDC_SHOW_AS_TAB,
1138 (type() & TYPE_POPUP) && !is_fullscreen);
1139
1140 // Focus various bits of UI
1141 command_updater_.UpdateCommandEnabled(IDC_FOCUS_TOOLBAR, show_main_ui);
1142 command_updater_.UpdateCommandEnabled(IDC_FOCUS_LOCATION, show_main_ui);
1143 command_updater_.UpdateCommandEnabled(IDC_FOCUS_SEARCH, show_main_ui);
[email protected]cc824372010-03-31 15:33:011144 command_updater_.UpdateCommandEnabled(
[email protected]83548a42010-06-18 13:53:371145 IDC_FOCUS_MENU_BAR, main_not_fullscreen_or_popup);
1146 command_updater_.UpdateCommandEnabled(
1147 IDC_FOCUS_NEXT_PANE, main_not_fullscreen_or_popup);
1148 command_updater_.UpdateCommandEnabled(
1149 IDC_FOCUS_PREVIOUS_PANE, main_not_fullscreen_or_popup);
1150 command_updater_.UpdateCommandEnabled(
1151 IDC_FOCUS_BOOKMARKS, main_not_fullscreen_or_popup);
1152 command_updater_.UpdateCommandEnabled(
1153 IDC_FOCUS_CHROMEOS_STATUS, main_not_fullscreen_or_popup);
[email protected]ae2622c2009-07-30 23:47:581154
1155 // Show various bits of UI
1156 command_updater_.UpdateCommandEnabled(IDC_DEVELOPER_MENU, show_main_ui);
[email protected]1c41a932010-11-22 23:41:231157 command_updater_.UpdateCommandEnabled(IDC_FEEDBACK, show_main_ui);
[email protected]4a4180a52010-08-23 06:39:481158 command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_BAR,
1159 browser_defaults::bookmarks_enabled && show_main_ui);
[email protected]ae2622c2009-07-30 23:47:581160 command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, show_main_ui);
[email protected]d3b98c82010-07-14 07:45:591161 command_updater_.UpdateCommandEnabled(IDC_SYNC_BOOKMARKS,
1162 show_main_ui && profile_->IsSyncAccessible());
[email protected]da96e54c2010-08-12 00:18:321163
[email protected]ae2622c2009-07-30 23:47:581164 command_updater_.UpdateCommandEnabled(IDC_OPTIONS, show_main_ui);
1165 command_updater_.UpdateCommandEnabled(IDC_EDIT_SEARCH_ENGINES, show_main_ui);
1166 command_updater_.UpdateCommandEnabled(IDC_VIEW_PASSWORDS, show_main_ui);
1167 command_updater_.UpdateCommandEnabled(IDC_ABOUT, show_main_ui);
[email protected]fdb98512009-08-26 01:37:101168 command_updater_.UpdateCommandEnabled(IDC_SHOW_APP_MENU, show_main_ui);
[email protected]c8b59f92010-05-28 21:45:471169 command_updater_.UpdateCommandEnabled(IDC_TOGGLE_VERTICAL_TABS, show_main_ui);
[email protected]7664ab32011-02-01 23:35:251170#if defined (ENABLE_PROFILING) && !defined(NO_TCMALLOC)
1171 command_updater_.UpdateCommandEnabled(IDC_PROFILING_ENABLED, show_main_ui);
1172#endif
[email protected]ae2622c2009-07-30 23:47:581173}
1174
[email protected]36b6dcb2008-11-12 01:19:571175///////////////////////////////////////////////////////////////////////////////
1176// Browser, Assorted browser commands:
1177
[email protected]d497b0782010-03-29 19:19:061178bool Browser::ShouldOpenNewTabForWindowDisposition(
1179 WindowOpenDisposition disposition) {
1180 return (disposition == NEW_FOREGROUND_TAB ||
1181 disposition == NEW_BACKGROUND_TAB);
1182}
1183
[email protected]cb84d642010-06-10 00:56:281184TabContents* Browser::GetOrCloneTabForDisposition(
[email protected]3698f172010-03-17 20:50:291185 WindowOpenDisposition disposition) {
[email protected]3c9e1872010-11-18 16:17:491186 TabContentsWrapper* current_tab = GetSelectedTabContentsWrapper();
[email protected]d497b0782010-03-29 19:19:061187 if (ShouldOpenNewTabForWindowDisposition(disposition)) {
[email protected]cb84d642010-06-10 00:56:281188 current_tab = current_tab->Clone();
[email protected]ecc523f62010-09-28 22:45:401189 tab_handler_->GetTabStripModel()->AddTabContents(
[email protected]4a1665442010-06-28 16:09:391190 current_tab, -1, PageTransition::LINK,
1191 disposition == NEW_FOREGROUND_TAB ? TabStripModel::ADD_SELECTED :
1192 TabStripModel::ADD_NONE);
[email protected]3698f172010-03-17 20:50:291193 }
[email protected]3c9e1872010-11-18 16:17:491194 return current_tab->tab_contents();
[email protected]3698f172010-03-17 20:50:291195}
1196
[email protected]b3344872010-05-03 15:52:291197void Browser::UpdateTabStripModelInsertionPolicy() {
[email protected]ecc523f62010-09-28 22:45:401198 tab_handler_->GetTabStripModel()->SetInsertionPolicy(UseVerticalTabs() ?
[email protected]b3344872010-05-03 15:52:291199 TabStripModel::INSERT_BEFORE : TabStripModel::INSERT_AFTER);
1200}
1201
1202void Browser::UseVerticalTabsChanged() {
1203 UpdateTabStripModelInsertionPolicy();
1204 window()->ToggleTabStripMode();
1205}
1206
[email protected]018cf362010-05-05 22:43:221207bool Browser::SupportsWindowFeatureImpl(WindowFeature feature,
1208 bool check_fullscreen) const {
1209 // On Mac, fullscreen mode has most normal things (in a slide-down panel). On
1210 // other platforms, we hide some controls when in fullscreen mode.
1211 bool hide_ui_for_fullscreen = false;
1212#if !defined(OS_MACOSX)
1213 hide_ui_for_fullscreen = check_fullscreen && window_ &&
1214 window_->IsFullscreen();
1215#endif
1216
[email protected]8b8e7c92010-08-19 18:05:561217 unsigned int features = FEATURE_INFOBAR | FEATURE_SIDEBAR;
[email protected]018cf362010-05-05 22:43:221218
1219#if !defined(OS_CHROMEOS)
1220 // Chrome OS opens a FileBrowse pop up instead of using download shelf.
1221 // So FEATURE_DOWNLOADSHELF is only added for non-chromeos platforms.
1222 features |= FEATURE_DOWNLOADSHELF;
1223#endif // !defined(OS_CHROMEOS)
1224
1225 if (type() == TYPE_NORMAL) {
1226 features |= FEATURE_BOOKMARKBAR;
[email protected]018cf362010-05-05 22:43:221227 }
1228
1229 if (!hide_ui_for_fullscreen) {
[email protected]94ce7252010-12-20 21:46:331230 if (type() != TYPE_NORMAL)
[email protected]018cf362010-05-05 22:43:221231 features |= FEATURE_TITLEBAR;
1232
[email protected]94ce7252010-12-20 21:46:331233 if (type() == TYPE_NORMAL)
[email protected]018cf362010-05-05 22:43:221234 features |= FEATURE_TABSTRIP;
1235
[email protected]94ce7252010-12-20 21:46:331236 if (type() == TYPE_NORMAL)
[email protected]018cf362010-05-05 22:43:221237 features |= FEATURE_TOOLBAR;
1238
[email protected]94ce7252010-12-20 21:46:331239 if ((type() & Browser::TYPE_APP) == 0)
[email protected]018cf362010-05-05 22:43:221240 features |= FEATURE_LOCATIONBAR;
1241 }
1242 return !!(features & feature);
1243}
1244
[email protected]0b4d3382010-07-14 16:13:041245bool Browser::IsClosingPermitted() {
1246 TabCloseableStateWatcher* watcher =
1247 g_browser_process->tab_closeable_state_watcher();
1248 bool can_close = !watcher || watcher->CanCloseBrowser(this);
1249 if (!can_close && is_attempting_to_close_browser_)
1250 CancelWindowClose();
1251 return can_close;
1252}
1253
[email protected]485fba42009-03-24 23:27:291254void Browser::GoBack(WindowOpenDisposition disposition) {
[email protected]896220042010-03-23 18:14:281255 UserMetrics::RecordAction(UserMetricsAction("Back"), profile_);
[email protected]fbd77592008-11-12 20:50:271256
[email protected]3c9e1872010-11-18 16:17:491257 TabContentsWrapper* current_tab = GetSelectedTabContentsWrapper();
[email protected]ce3fa3c2009-04-20 19:55:571258 if (current_tab->controller().CanGoBack()) {
[email protected]cb84d642010-06-10 00:56:281259 TabContents* new_tab = GetOrCloneTabForDisposition(disposition);
[email protected]d497b0782010-03-29 19:19:061260 // If we are on an interstitial page and clone the tab, it won't be copied
1261 // to the new tab, so we don't need to go back.
[email protected]3c9e1872010-11-18 16:17:491262 if (current_tab->tab_contents()->showing_interstitial_page() &&
1263 (new_tab != current_tab->tab_contents()))
[email protected]d497b0782010-03-29 19:19:061264 return;
[email protected]cb84d642010-06-10 00:56:281265 new_tab->controller().GoBack();
[email protected]485fba42009-03-24 23:27:291266 }
[email protected]36b6dcb2008-11-12 01:19:571267}
1268
[email protected]3698f172010-03-17 20:50:291269void Browser::GoForward(WindowOpenDisposition disposition) {
[email protected]896220042010-03-23 18:14:281270 UserMetrics::RecordAction(UserMetricsAction("Forward"), profile_);
[email protected]3c9e1872010-11-18 16:17:491271 if (GetSelectedTabContentsWrapper()->controller().CanGoForward())
[email protected]cb84d642010-06-10 00:56:281272 GetOrCloneTabForDisposition(disposition)->controller().GoForward();
[email protected]36b6dcb2008-11-12 01:19:571273}
1274
[email protected]cb84d642010-06-10 00:56:281275void Browser::Reload(WindowOpenDisposition disposition) {
[email protected]896220042010-03-23 18:14:281276 UserMetrics::RecordAction(UserMetricsAction("Reload"), profile_);
[email protected]cb84d642010-06-10 00:56:281277 ReloadInternal(disposition, false);
[email protected]1ccb3568d2010-02-19 10:51:161278}
[email protected]fbd77592008-11-12 20:50:271279
[email protected]cb84d642010-06-10 00:56:281280void Browser::ReloadIgnoringCache(WindowOpenDisposition disposition) {
[email protected]896220042010-03-23 18:14:281281 UserMetrics::RecordAction(UserMetricsAction("ReloadIgnoringCache"), profile_);
[email protected]cb84d642010-06-10 00:56:281282 ReloadInternal(disposition, true);
[email protected]1ccb3568d2010-02-19 10:51:161283}
1284
[email protected]cb84d642010-06-10 00:56:281285void Browser::ReloadInternal(WindowOpenDisposition disposition,
1286 bool ignore_cache) {
[email protected]36b6dcb2008-11-12 01:19:571287 // If we are showing an interstitial, treat this as an OpenURL.
1288 TabContents* current_tab = GetSelectedTabContents();
[email protected]cb84d642010-06-10 00:56:281289 if (current_tab && current_tab->showing_interstitial_page()) {
1290 NavigationEntry* entry = current_tab->controller().GetActiveEntry();
1291 DCHECK(entry); // Should exist if interstitial is showing.
1292 OpenURL(entry->url(), GURL(), disposition, PageTransition::RELOAD);
1293 return;
[email protected]36b6dcb2008-11-12 01:19:571294 }
[email protected]cb84d642010-06-10 00:56:281295
1296 // As this is caused by a user action, give the focus to the page.
[email protected]3c9e1872010-11-18 16:17:491297 TabContents* tab = GetOrCloneTabForDisposition(disposition);
1298 if (!tab->FocusLocationBarByDefault())
1299 tab->Focus();
[email protected]cb84d642010-06-10 00:56:281300 if (ignore_cache)
[email protected]3c9e1872010-11-18 16:17:491301 tab->controller().ReloadIgnoringCache(true);
[email protected]cb84d642010-06-10 00:56:281302 else
[email protected]3c9e1872010-11-18 16:17:491303 tab->controller().Reload(true);
[email protected]36b6dcb2008-11-12 01:19:571304}
1305
[email protected]485fba42009-03-24 23:27:291306void Browser::Home(WindowOpenDisposition disposition) {
[email protected]896220042010-03-23 18:14:281307 UserMetrics::RecordAction(UserMetricsAction("Home"), profile_);
[email protected]485fba42009-03-24 23:27:291308 OpenURL(GetHomePage(), GURL(), disposition, PageTransition::AUTO_BOOKMARK);
[email protected]36b6dcb2008-11-12 01:19:571309}
1310
[email protected]fbd77592008-11-12 20:50:271311void Browser::OpenCurrentURL() {
[email protected]896220042010-03-23 18:14:281312 UserMetrics::RecordAction(UserMetricsAction("LoadURL"), profile_);
[email protected]7745b822009-01-27 20:15:351313 LocationBar* location_bar = window_->GetLocationBar();
[email protected]9800de5e2011-03-11 18:19:491314 if (!location_bar)
1315 return;
1316
[email protected]9d0306ea2009-09-02 19:38:391317 WindowOpenDisposition open_disposition =
1318 location_bar->GetWindowOpenDisposition();
[email protected]6b723f82010-10-05 20:14:271319 if (OpenInstant(open_disposition))
[email protected]03bb953d2010-09-14 21:38:301320 return;
[email protected]03bb953d2010-09-14 21:38:301321
[email protected]83bf2d142009-11-06 18:19:301322 GURL url(WideToUTF8(location_bar->GetInputString()));
[email protected]07d490bc2011-03-07 17:05:261323
1324 if (open_disposition == CURRENT_TAB && TabFinder::IsEnabled()) {
1325 Browser* existing_browser = NULL;
1326 TabContents* existing_tab = TabFinder::GetInstance()->FindTab(
1327 this, url, &existing_browser);
1328 if (existing_tab) {
1329 existing_browser->ActivateContents(existing_tab);
1330 return;
1331 }
1332 }
1333
[email protected]616381f02010-11-02 15:15:331334 browser::NavigateParams params(this, url, location_bar->GetPageTransition());
1335 params.disposition = open_disposition;
[email protected]514576a2010-07-01 22:51:251336 // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
1337 // inherit the opener. In some cases the tabstrip will determine the group
1338 // should be inherited, in which case the group is inherited instead of the
1339 // opener.
[email protected]616381f02010-11-02 15:15:331340 params.tabstrip_add_types =
1341 TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
1342 browser::Navigate(&params);
[email protected]46fd1ea42011-02-16 15:59:331343
[email protected]6e37fe32011-03-02 09:06:521344 DCHECK(profile_->GetExtensionService());
1345 if (profile_->GetExtensionService()->IsInstalledApp(url)) {
[email protected]46fd1ea42011-02-16 15:59:331346 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram,
1347 extension_misc::APP_LAUNCH_OMNIBOX_LOCATION,
1348 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY);
1349 }
[email protected]fbd77592008-11-12 20:50:271350}
1351
[email protected]84214982008-12-10 18:49:101352void Browser::Stop() {
[email protected]896220042010-03-23 18:14:281353 UserMetrics::RecordAction(UserMetricsAction("Stop"), profile_);
[email protected]3c9e1872010-11-18 16:17:491354 GetSelectedTabContentsWrapper()->tab_contents()->Stop();
[email protected]84214982008-12-10 18:49:101355}
1356
1357void Browser::NewWindow() {
[email protected]047e7272010-06-03 19:53:351358 if (browser_defaults::kAlwaysOpenIncognitoWindow &&
[email protected]6e6f6cb2011-01-27 13:26:551359 CommandLine::ForCurrentProcess()->HasSwitch(switches::kIncognito) &&
1360 incognito_mode_allowed_.GetValue()) {
[email protected]047e7272010-06-03 19:53:351361 NewIncognitoWindow();
1362 return;
1363 }
[email protected]896220042010-03-23 18:14:281364 UserMetrics::RecordAction(UserMetricsAction("NewWindow"), profile_);
[email protected]c9b19942010-03-26 15:58:081365 SessionService* session_service =
1366 profile_->GetOriginalProfile()->GetSessionService();
1367 if (!session_service ||
1368 !session_service->RestoreIfNecessary(std::vector<GURL>())) {
1369 Browser::OpenEmptyWindow(profile_->GetOriginalProfile());
1370 }
[email protected]84214982008-12-10 18:49:101371}
1372
1373void Browser::NewIncognitoWindow() {
[email protected]6e6f6cb2011-01-27 13:26:551374 if (!incognito_mode_allowed_.GetValue()) {
1375 NewWindow();
1376 return;
1377 }
1378
[email protected]896220042010-03-23 18:14:281379 UserMetrics::RecordAction(UserMetricsAction("NewIncognitoWindow"), profile_);
[email protected]84214982008-12-10 18:49:101380 Browser::OpenEmptyWindow(profile_->GetOffTheRecordProfile());
1381}
1382
[email protected]84214982008-12-10 18:49:101383void Browser::CloseWindow() {
[email protected]896220042010-03-23 18:14:281384 UserMetrics::RecordAction(UserMetricsAction("CloseWindow"), profile_);
[email protected]84214982008-12-10 18:49:101385 window_->Close();
1386}
1387
[email protected]fbd77592008-11-12 20:50:271388void Browser::NewTab() {
[email protected]896220042010-03-23 18:14:281389 UserMetrics::RecordAction(UserMetricsAction("NewTab"), profile_);
[email protected]b7969202010-05-14 21:29:261390
[email protected]299dabd2008-11-19 02:27:161391 if (type() == TYPE_NORMAL) {
[email protected]fbd77592008-11-12 20:50:271392 AddBlankTab(true);
[email protected]49bb7ea32011-02-02 17:58:061393 GetSelectedTabContentsWrapper()->view()->RestoreFocus();
[email protected]fbd77592008-11-12 20:50:271394 } else {
[email protected]1a6b30a2009-08-19 03:52:111395 Browser* b = GetOrCreateTabbedBrowser(profile_);
[email protected]fbd77592008-11-12 20:50:271396 b->AddBlankTab(true);
[email protected]15952e462008-11-14 00:29:051397 b->window()->Show();
[email protected]e54f30d2009-01-14 21:17:111398 // The call to AddBlankTab above did not set the focus to the tab as its
1399 // window was not active, so we have to do it explicitly.
1400 // See http://crbug.com/6380.
[email protected]3c9e1872010-11-18 16:17:491401 b->GetSelectedTabContentsWrapper()->view()->RestoreFocus();
[email protected]fbd77592008-11-12 20:50:271402 }
1403}
1404
1405void Browser::CloseTab() {
[email protected]896220042010-03-23 18:14:281406 UserMetrics::RecordAction(UserMetricsAction("CloseTab_Accelerator"),
1407 profile_);
[email protected]0b4d3382010-07-14 16:13:041408 if (CanCloseTab()) {
[email protected]ecc523f62010-09-28 22:45:401409 tab_handler_->GetTabStripModel()->CloseTabContentsAt(
1410 tab_handler_->GetTabStripModel()->selected_index(),
[email protected]0b4d3382010-07-14 16:13:041411 TabStripModel::CLOSE_USER_GESTURE |
1412 TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
1413 }
[email protected]fbd77592008-11-12 20:50:271414}
1415
[email protected]fbd77592008-11-12 20:50:271416void Browser::SelectNextTab() {
[email protected]896220042010-03-23 18:14:281417 UserMetrics::RecordAction(UserMetricsAction("SelectNextTab"), profile_);
[email protected]ecc523f62010-09-28 22:45:401418 tab_handler_->GetTabStripModel()->SelectNextTab();
[email protected]fbd77592008-11-12 20:50:271419}
1420
1421void Browser::SelectPreviousTab() {
[email protected]896220042010-03-23 18:14:281422 UserMetrics::RecordAction(UserMetricsAction("SelectPrevTab"), profile_);
[email protected]ecc523f62010-09-28 22:45:401423 tab_handler_->GetTabStripModel()->SelectPreviousTab();
[email protected]fbd77592008-11-12 20:50:271424}
1425
[email protected]91ac9202010-07-30 18:32:351426void Browser::OpenTabpose() {
1427#if defined(OS_MACOSX)
[email protected]91ac9202010-07-30 18:32:351428 UserMetrics::RecordAction(UserMetricsAction("OpenTabpose"), profile_);
1429 window()->OpenTabpose();
1430#else
1431 NOTREACHED();
1432#endif
1433}
1434
[email protected]9ac7fcb2009-09-14 18:22:521435void Browser::MoveTabNext() {
[email protected]896220042010-03-23 18:14:281436 UserMetrics::RecordAction(UserMetricsAction("MoveTabNext"), profile_);
[email protected]ecc523f62010-09-28 22:45:401437 tab_handler_->GetTabStripModel()->MoveTabNext();
[email protected]9ac7fcb2009-09-14 18:22:521438}
1439
1440void Browser::MoveTabPrevious() {
[email protected]896220042010-03-23 18:14:281441 UserMetrics::RecordAction(UserMetricsAction("MoveTabPrevious"), profile_);
[email protected]ecc523f62010-09-28 22:45:401442 tab_handler_->GetTabStripModel()->MoveTabPrevious();
[email protected]9ac7fcb2009-09-14 18:22:521443}
1444
[email protected]fbd77592008-11-12 20:50:271445void Browser::SelectNumberedTab(int index) {
1446 if (index < tab_count()) {
[email protected]896220042010-03-23 18:14:281447 UserMetrics::RecordAction(UserMetricsAction("SelectNumberedTab"),
1448 profile_);
[email protected]ecc523f62010-09-28 22:45:401449 tab_handler_->GetTabStripModel()->SelectTabContentsAt(index, true);
[email protected]fbd77592008-11-12 20:50:271450 }
1451}
1452
1453void Browser::SelectLastTab() {
[email protected]896220042010-03-23 18:14:281454 UserMetrics::RecordAction(UserMetricsAction("SelectLastTab"), profile_);
[email protected]ecc523f62010-09-28 22:45:401455 tab_handler_->GetTabStripModel()->SelectLastTab();
[email protected]fbd77592008-11-12 20:50:271456}
1457
1458void Browser::DuplicateTab() {
[email protected]896220042010-03-23 18:14:281459 UserMetrics::RecordAction(UserMetricsAction("Duplicate"), profile_);
[email protected]fbd77592008-11-12 20:50:271460 DuplicateContentsAt(selected_index());
1461}
1462
1463void Browser::RestoreTab() {
[email protected]896220042010-03-23 18:14:281464 UserMetrics::RecordAction(UserMetricsAction("RestoreTab"), profile_);
[email protected]fbd77592008-11-12 20:50:271465 TabRestoreService* service = profile_->GetTabRestoreService();
1466 if (!service)
1467 return;
1468
[email protected]d8375fd2008-11-25 22:45:391469 service->RestoreMostRecentEntry(this);
[email protected]fbd77592008-11-12 20:50:271470}
1471
[email protected]0c4c3882009-10-01 21:42:141472void Browser::WriteCurrentURLToClipboard() {
1473 // TODO(ericu): There isn't currently a metric for this. Should there be?
1474 // We don't appear to track the action when it comes from the
1475 // RenderContextViewMenu.
[email protected]0c4c3882009-10-01 21:42:141476
1477 TabContents* contents = GetSelectedTabContents();
1478 if (!contents->ShouldDisplayURL())
1479 return;
1480
[email protected]90f39902009-10-03 04:25:371481 chrome_browser_net::WriteURLToClipboard(
[email protected]0c4c3882009-10-01 21:42:141482 contents->GetURL(),
[email protected]9f284f132010-08-31 06:14:171483 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages),
[email protected]0c4c3882009-10-01 21:42:141484 g_browser_process->clipboard());
1485}
1486
[email protected]fbd77592008-11-12 20:50:271487void Browser::ConvertPopupToTabbedBrowser() {
[email protected]896220042010-03-23 18:14:281488 UserMetrics::RecordAction(UserMetricsAction("ShowAsTab"), profile_);
[email protected]ecc523f62010-09-28 22:45:401489 int tab_strip_index = tab_handler_->GetTabStripModel()->selected_index();
[email protected]3c9e1872010-11-18 16:17:491490 TabContentsWrapper* contents =
[email protected]ecc523f62010-09-28 22:45:401491 tab_handler_->GetTabStripModel()->DetachTabContentsAt(tab_strip_index);
[email protected]15952e462008-11-14 00:29:051492 Browser* browser = Browser::Create(profile_);
1493 browser->tabstrip_model()->AppendTabContents(contents, true);
1494 browser->window()->Show();
[email protected]fbd77592008-11-12 20:50:271495}
1496
[email protected]9282cea2009-02-18 18:49:001497void Browser::ToggleFullscreenMode() {
[email protected]34930432009-11-09 00:12:091498#if !defined(OS_MACOSX)
1499 // In kiosk mode, we always want to be fullscreen. When the browser first
1500 // starts we're not yet fullscreen, so let the initial toggle go through.
1501 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode) &&
1502 window_->IsFullscreen())
1503 return;
1504#endif
1505
[email protected]896220042010-03-23 18:14:281506 UserMetrics::RecordAction(UserMetricsAction("ToggleFullscreen"), profile_);
[email protected]9282cea2009-02-18 18:49:001507 window_->SetFullscreen(!window_->IsFullscreen());
[email protected]ae2622c2009-07-30 23:47:581508 // On Linux, setting fullscreen mode is an async call to the X server, which
1509 // may or may not support fullscreen mode.
1510#if !defined(OS_LINUX)
[email protected]9282cea2009-02-18 18:49:001511 UpdateCommandsForFullscreenMode(window_->IsFullscreen());
[email protected]ae2622c2009-07-30 23:47:581512#endif
[email protected]9282cea2009-02-18 18:49:001513}
1514
[email protected]da17b372010-01-22 23:37:221515#if defined(OS_CHROMEOS)
[email protected]f97d7f632010-06-01 21:08:331516void Browser::Search() {
1517 // If the NTP is showing, close it.
1518 if (StartsWithASCII(GetSelectedTabContents()->GetURL().spec(),
1519 chrome::kChromeUINewTabURL, true)) {
1520 CloseTab();
1521 return;
1522 }
[email protected]64559862010-09-23 19:00:161523
1524 // Exit fullscreen to show omnibox.
[email protected]ebdda9092010-10-22 17:59:101525 if (window_->IsFullscreen()) {
[email protected]64559862010-09-23 19:00:161526 ToggleFullscreenMode();
[email protected]ebdda9092010-10-22 17:59:101527 // ToggleFullscreenMode is asynchronous, so we don't have omnibox
1528 // visible at this point. Wait for next event cycle which toggles
1529 // the visibility of omnibox before creating new tab.
1530 MessageLoop::current()->PostTask(
1531 FROM_HERE, method_factory_.NewRunnableMethod(&Browser::Search));
1532 return;
1533 }
[email protected]64559862010-09-23 19:00:161534
[email protected]f97d7f632010-06-01 21:08:331535 // Otherwise just open it.
1536 NewTab();
1537}
[email protected]d14af522010-12-02 03:54:501538
1539void Browser::ShowKeyboardOverlay() {
1540 window_->ShowKeyboardOverlay(window_->GetNativeHandle());
1541}
[email protected]20d17242009-10-26 20:21:051542#endif
1543
[email protected]fbd77592008-11-12 20:50:271544void Browser::Exit() {
[email protected]896220042010-03-23 18:14:281545 UserMetrics::RecordAction(UserMetricsAction("Exit"), profile_);
[email protected]965e4c42010-09-07 21:23:351546#if defined(OS_CHROMEOS)
[email protected]6a2a61d2010-11-22 03:25:351547 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("LogoutStarted", false);
1548 // Write /tmp/uptime-logout-started as well.
1549 const char kLogoutStarted[] = "logout-started";
1550 chromeos::BootTimesLoader::Get()->RecordCurrentStats(kLogoutStarted);
[email protected]db3abe62011-02-09 15:13:251551
1552 // Login screen should show up in owner's locale.
1553 PrefService* state = g_browser_process->local_state();
1554 if (state) {
1555 std::string owner_locale = state->GetString(prefs::kOwnerLocale);
1556 if (!owner_locale.empty() &&
1557 state->GetString(prefs::kApplicationLocale) != owner_locale &&
1558 !state->IsManagedPreference(prefs::kApplicationLocale)) {
1559 state->SetString(prefs::kApplicationLocale, owner_locale);
1560 state->ScheduleSavePersistentPrefs();
1561 }
1562 }
[email protected]965e4c42010-09-07 21:23:351563#endif
[email protected]460a2942010-12-15 19:43:151564 BrowserList::Exit();
[email protected]fbd77592008-11-12 20:50:271565}
1566
[email protected]36b6dcb2008-11-12 01:19:571567void Browser::BookmarkCurrentPage() {
[email protected]896220042010-03-23 18:14:281568 UserMetrics::RecordAction(UserMetricsAction("Star"), profile_);
[email protected]fbd77592008-11-12 20:50:271569
[email protected]76624fde2009-10-09 18:13:231570 BookmarkModel* model = profile()->GetBookmarkModel();
[email protected]36b6dcb2008-11-12 01:19:571571 if (!model || !model->IsLoaded())
1572 return; // Ignore requests until bookmarks are loaded.
1573
[email protected]76624fde2009-10-09 18:13:231574 GURL url;
[email protected]261cd762010-08-20 05:45:371575 string16 title;
[email protected]ef0d04c2010-12-15 23:34:211576 TabContents* tab = GetSelectedTabContents();
1577 bookmark_utils::GetURLAndTitleToBookmark(tab, &url, &title);
[email protected]c50d0d42009-03-03 17:37:441578 bool was_bookmarked = model->IsBookmarked(url);
[email protected]ef0d04c2010-12-15 23:34:211579 if (!was_bookmarked && profile_->IsOffTheRecord()) {
[email protected]2c910b72011-03-08 21:16:321580 // If we're incognito the favicon may not have been saved. Save it now
[email protected]ef0d04c2010-12-15 23:34:211581 // so that bookmarks have an icon for the page.
1582 tab->SaveFavicon();
1583 }
[email protected]261cd762010-08-20 05:45:371584 model->SetURLStarred(url, title, true);
[email protected]11dbbd22009-11-06 18:55:041585 // Make sure the model actually added a bookmark before showing the star. A
1586 // bookmark isn't created if the url is invalid.
1587 if (window_->IsActive() && model->IsBookmarked(url)) {
[email protected]5f2731c52009-02-28 00:41:271588 // Only show the bubble if the window is active, otherwise we may get into
1589 // weird situations were the bubble is deleted as soon as it is shown.
[email protected]c50d0d42009-03-03 17:37:441590 window_->ShowBookmarkBubble(url, was_bookmarked);
[email protected]5f2731c52009-02-28 00:41:271591 }
[email protected]36b6dcb2008-11-12 01:19:571592}
1593
[email protected]40bdb6d92009-02-25 00:22:271594void Browser::SavePage() {
[email protected]896220042010-03-23 18:14:281595 UserMetrics::RecordAction(UserMetricsAction("SavePage"), profile_);
[email protected]15d04ae2010-10-30 01:04:501596 TabContents* current_tab = GetSelectedTabContents();
1597 if (current_tab && current_tab->contents_mime_type() == "application/pdf")
1598 UserMetrics::RecordAction(UserMetricsAction("PDF.SavePage"), profile_);
[email protected]57c6a652009-05-04 07:58:341599 GetSelectedTabContents()->OnSavePage();
[email protected]40bdb6d92009-02-25 00:22:271600}
1601
[email protected]77d8d622010-12-15 10:30:121602void Browser::ViewSelectedSource() {
1603 ViewSource(GetSelectedTabContentsWrapper());
[email protected]36b6dcb2008-11-12 01:19:571604}
initial.commit09911bf2008-07-26 23:55:291605
[email protected]4801ecc2009-04-05 04:52:581606void Browser::ShowFindBar() {
[email protected]b77cb302009-10-29 04:09:171607 GetFindBarController()->Show();
[email protected]4801ecc2009-04-05 04:52:581608}
1609
[email protected]a3e18c42009-03-04 23:36:051610bool Browser::SupportsWindowFeature(WindowFeature feature) const {
[email protected]018cf362010-05-05 22:43:221611 return SupportsWindowFeatureImpl(feature, true);
1612}
[email protected]f5bf8ccf2010-02-05 18:19:251613
[email protected]018cf362010-05-05 22:43:221614bool Browser::CanSupportWindowFeature(WindowFeature feature) const {
1615 return SupportsWindowFeatureImpl(feature, false);
[email protected]a3e18c42009-03-04 23:36:051616}
1617
[email protected]89d6e6e2009-12-03 23:06:511618void Browser::EmailPageLocation() {
[email protected]896220042010-03-23 18:14:281619 UserMetrics::RecordAction(UserMetricsAction("EmailPageLocation"), profile_);
[email protected]89d6e6e2009-12-03 23:06:511620 GetSelectedTabContents()->EmailPageLocation();
1621}
1622
[email protected]fbd77592008-11-12 20:50:271623void Browser::Print() {
[email protected]896220042010-03-23 18:14:281624 UserMetrics::RecordAction(UserMetricsAction("PrintPreview"), profile_);
[email protected]57c6a652009-05-04 07:58:341625 GetSelectedTabContents()->PrintPreview();
[email protected]fbd77592008-11-12 20:50:271626}
1627
[email protected]fbd77592008-11-12 20:50:271628void Browser::ToggleEncodingAutoDetect() {
[email protected]896220042010-03-23 18:14:281629 UserMetrics::RecordAction(UserMetricsAction("AutoDetectChange"), profile_);
[email protected]fbd77592008-11-12 20:50:271630 encoding_auto_detect_.SetValue(!encoding_auto_detect_.GetValue());
[email protected]a697f4c2009-09-14 22:30:181631 // If "auto detect" is turned on, then any current override encoding
1632 // is cleared. This also implicitly performs a reload.
1633 // OTOH, if "auto detect" is turned off, we don't change the currently
1634 // active encoding.
1635 if (encoding_auto_detect_.GetValue()) {
1636 TabContents* contents = GetSelectedTabContents();
1637 if (contents)
[email protected]b2fe07d12010-02-09 14:38:081638 contents->ResetOverrideEncoding();
[email protected]a697f4c2009-09-14 22:30:181639 }
[email protected]fbd77592008-11-12 20:50:271640}
1641
1642void Browser::OverrideEncoding(int encoding_id) {
[email protected]896220042010-03-23 18:14:281643 UserMetrics::RecordAction(UserMetricsAction("OverrideEncoding"), profile_);
[email protected]41fc0322009-09-04 22:23:401644 const std::string selected_encoding =
[email protected]fbd77592008-11-12 20:50:271645 CharacterEncoding::GetCanonicalEncodingNameByCommandId(encoding_id);
[email protected]57c6a652009-05-04 07:58:341646 TabContents* contents = GetSelectedTabContents();
1647 if (!selected_encoding.empty() && contents)
[email protected]b2fe07d12010-02-09 14:38:081648 contents->SetOverrideEncoding(selected_encoding);
[email protected]fbd77592008-11-12 20:50:271649 // Update the list of recently selected encodings.
[email protected]41fc0322009-09-04 22:23:401650 std::string new_selected_encoding_list;
[email protected]ddd231e2010-06-29 20:35:191651 if (CharacterEncoding::UpdateRecentlySelectedEncoding(
1652 profile_->GetPrefs()->GetString(prefs::kRecentlySelectedEncoding),
[email protected]41fc0322009-09-04 22:23:401653 encoding_id,
1654 &new_selected_encoding_list)) {
[email protected]fbd77592008-11-12 20:50:271655 profile_->GetPrefs()->SetString(prefs::kRecentlySelectedEncoding,
[email protected]ddd231e2010-06-29 20:35:191656 new_selected_encoding_list);
[email protected]fbd77592008-11-12 20:50:271657 }
[email protected]36b6dcb2008-11-12 01:19:571658}
1659
[email protected]84214982008-12-10 18:49:101660void Browser::Cut() {
[email protected]896220042010-03-23 18:14:281661 UserMetrics::RecordAction(UserMetricsAction("Cut"), profile_);
[email protected]20012dd42010-01-25 04:46:231662 window()->Cut();
[email protected]36b6dcb2008-11-12 01:19:571663}
1664
[email protected]84214982008-12-10 18:49:101665void Browser::Copy() {
[email protected]896220042010-03-23 18:14:281666 UserMetrics::RecordAction(UserMetricsAction("Copy"), profile_);
[email protected]20012dd42010-01-25 04:46:231667 window()->Copy();
[email protected]36b6dcb2008-11-12 01:19:571668}
1669
[email protected]84214982008-12-10 18:49:101670void Browser::Paste() {
[email protected]896220042010-03-23 18:14:281671 UserMetrics::RecordAction(UserMetricsAction("Paste"), profile_);
[email protected]20012dd42010-01-25 04:46:231672 window()->Paste();
[email protected]84214982008-12-10 18:49:101673}
1674
1675void Browser::Find() {
[email protected]896220042010-03-23 18:14:281676 UserMetrics::RecordAction(UserMetricsAction("Find"), profile_);
[email protected]4f3dc372009-02-24 00:10:291677 FindInPage(false, false);
[email protected]84214982008-12-10 18:49:101678}
1679
1680void Browser::FindNext() {
[email protected]896220042010-03-23 18:14:281681 UserMetrics::RecordAction(UserMetricsAction("FindNext"), profile_);
[email protected]4f3dc372009-02-24 00:10:291682 FindInPage(true, true);
[email protected]84214982008-12-10 18:49:101683}
1684
1685void Browser::FindPrevious() {
[email protected]896220042010-03-23 18:14:281686 UserMetrics::RecordAction(UserMetricsAction("FindPrevious"), profile_);
[email protected]4f3dc372009-02-24 00:10:291687 FindInPage(true, false);
[email protected]84214982008-12-10 18:49:101688}
1689
[email protected]40bd6582009-12-04 23:49:511690void Browser::Zoom(PageZoom::Function zoom_function) {
[email protected]896220042010-03-23 18:14:281691 static const UserMetricsAction kActions[] = {
1692 UserMetricsAction("ZoomMinus"),
1693 UserMetricsAction("ZoomNormal"),
1694 UserMetricsAction("ZoomPlus")
1695 };
1696
1697 UserMetrics::RecordAction(kActions[zoom_function - PageZoom::ZOOM_OUT],
1698 profile_);
[email protected]3c9e1872010-11-18 16:17:491699 TabContentsWrapper* tab_contents = GetSelectedTabContentsWrapper();
[email protected]40bd6582009-12-04 23:49:511700 tab_contents->render_view_host()->Zoom(zoom_function);
[email protected]84214982008-12-10 18:49:101701}
1702
1703void Browser::FocusToolbar() {
[email protected]896220042010-03-23 18:14:281704 UserMetrics::RecordAction(UserMetricsAction("FocusToolbar"), profile_);
[email protected]84214982008-12-10 18:49:101705 window_->FocusToolbar();
1706}
1707
[email protected]bdb7ff62010-07-20 01:56:521708void Browser::FocusAppMenu() {
1709 UserMetrics::RecordAction(UserMetricsAction("FocusAppMenu"), profile_);
1710 window_->FocusAppMenu();
[email protected]cc824372010-03-31 15:33:011711}
1712
[email protected]84214982008-12-10 18:49:101713void Browser::FocusLocationBar() {
[email protected]896220042010-03-23 18:14:281714 UserMetrics::RecordAction(UserMetricsAction("FocusLocation"), profile_);
[email protected]a26dc362010-04-23 01:48:581715 window_->SetFocusToLocationBar(true);
[email protected]84214982008-12-10 18:49:101716}
1717
[email protected]83548a42010-06-18 13:53:371718void Browser::FocusBookmarksToolbar() {
1719 UserMetrics::RecordAction(UserMetricsAction("FocusBookmarksToolbar"),
1720 profile_);
1721 window_->FocusBookmarksToolbar();
1722}
1723
1724void Browser::FocusChromeOSStatus() {
1725 UserMetrics::RecordAction(UserMetricsAction("FocusChromeOSStatus"), profile_);
1726 window_->FocusChromeOSStatus();
1727}
1728
1729void Browser::FocusNextPane() {
1730 UserMetrics::RecordAction(UserMetricsAction("FocusNextPane"), profile_);
1731 window_->RotatePaneFocus(true);
1732}
1733
1734void Browser::FocusPreviousPane() {
1735 UserMetrics::RecordAction(UserMetricsAction("FocusPreviousPane"), profile_);
1736 window_->RotatePaneFocus(false);
1737}
1738
[email protected]84214982008-12-10 18:49:101739void Browser::FocusSearch() {
1740 // TODO(beng): replace this with FocusLocationBar
[email protected]896220042010-03-23 18:14:281741 UserMetrics::RecordAction(UserMetricsAction("FocusSearch"), profile_);
[email protected]7745b822009-01-27 20:15:351742 window_->GetLocationBar()->FocusSearch();
[email protected]84214982008-12-10 18:49:101743}
1744
1745void Browser::OpenFile() {
[email protected]896220042010-03-23 18:14:281746 UserMetrics::RecordAction(UserMetricsAction("OpenFile"), profile_);
[email protected]f59f1162010-04-23 21:19:291747#if defined(OS_CHROMEOS)
1748 FileBrowseUI::OpenPopup(profile_,
1749 "",
1750 FileBrowseUI::kPopupWidth,
1751 FileBrowseUI::kPopupHeight);
1752#else
[email protected]84214982008-12-10 18:49:101753 if (!select_file_dialog_.get())
1754 select_file_dialog_ = SelectFileDialog::Create(this);
1755
[email protected]35896a32010-06-09 08:42:511756 const FilePath directory = profile_->last_selected_directory();
1757
[email protected]84214982008-12-10 18:49:101758 // TODO(beng): figure out how to juggle this.
[email protected]d56bcd22009-03-16 19:51:561759 gfx::NativeWindow parent_window = window_->GetNativeHandle();
[email protected]84214982008-12-10 18:49:101760 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE,
[email protected]35896a32010-06-09 08:42:511761 string16(), directory,
[email protected]b949f1112009-04-12 20:03:081762 NULL, 0, FILE_PATH_LITERAL(""),
[email protected]d56bcd22009-03-16 19:51:561763 parent_window, NULL);
[email protected]f59f1162010-04-23 21:19:291764#endif
[email protected]84214982008-12-10 18:49:101765}
1766
1767void Browser::OpenCreateShortcutsDialog() {
[email protected]896220042010-03-23 18:14:281768 UserMetrics::RecordAction(UserMetricsAction("CreateShortcut"), profile_);
[email protected]b96aa932009-08-12 21:34:491769#if defined(OS_WIN) || defined(OS_LINUX)
[email protected]3c9e1872010-11-18 16:17:491770 TabContentsWrapper* current_tab = GetSelectedTabContentsWrapper();
1771 DCHECK(current_tab &&
1772 web_app::IsValidUrl(current_tab->tab_contents()->GetURL())) <<
1773 "Menu item should be disabled.";
[email protected]ed5431872009-11-17 08:39:511774
1775 NavigationEntry* entry = current_tab->controller().GetLastCommittedEntry();
1776 if (!entry)
1777 return;
1778
[email protected]eabfdae92009-12-11 06:13:511779 // RVH's GetApplicationInfo should not be called before it returns.
1780 DCHECK(pending_web_app_action_ == NONE);
1781 pending_web_app_action_ = CREATE_SHORTCUT;
1782
[email protected]a2cf65eb2010-01-18 08:20:381783 // Start fetching web app info for CreateApplicationShortcut dialog and show
1784 // the dialog when the data is available in OnDidGetApplicationInfo.
[email protected]ed5431872009-11-17 08:39:511785 current_tab->render_view_host()->GetApplicationInfo(entry->page_id());
[email protected]98f6e022009-06-05 22:49:531786#else
1787 NOTIMPLEMENTED();
1788#endif
[email protected]36b6dcb2008-11-12 01:19:571789}
1790
[email protected]2a8a98122010-07-16 11:58:481791void Browser::ToggleDevToolsWindow(DevToolsToggleAction action) {
1792 std::string uma_string;
1793 switch (action) {
1794 case DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE:
1795 uma_string = "DevTools_ToggleConsole";
1796 break;
1797 case DEVTOOLS_TOGGLE_ACTION_NONE:
1798 case DEVTOOLS_TOGGLE_ACTION_INSPECT:
1799 default:
1800 uma_string = "DevTools_ToggleWindow";
1801 break;
1802 }
1803 UserMetrics::RecordAction(UserMetricsAction(uma_string.c_str()), profile_);
[email protected]3061ccf32009-07-13 14:17:491804 DevToolsManager::GetInstance()->ToggleDevToolsWindow(
[email protected]3c9e1872010-11-18 16:17:491805 GetSelectedTabContentsWrapper()->render_view_host(), action);
[email protected]fbd77592008-11-12 20:50:271806}
1807
[email protected]adb6a84d2011-02-07 16:58:401808void Browser::OpenTaskManager(bool highlight_background_resources) {
[email protected]896220042010-03-23 18:14:281809 UserMetrics::RecordAction(UserMetricsAction("TaskManager"), profile_);
[email protected]adb6a84d2011-02-07 16:58:401810 if (highlight_background_resources)
1811 window_->ShowBackgroundPages();
1812 else
1813 window_->ShowTaskManager();
[email protected]84214982008-12-10 18:49:101814}
1815
[email protected]84214982008-12-10 18:49:101816void Browser::OpenBugReportDialog() {
[email protected]86206622010-05-14 05:45:261817 UserMetrics::RecordAction(UserMetricsAction("ReportBug"), profile_);
[email protected]35d06152011-01-10 22:19:421818 browser::ShowHtmlBugReportView(this);
[email protected]84214982008-12-10 18:49:101819}
[email protected]44b2c8852009-03-18 00:57:491820
[email protected]84214982008-12-10 18:49:101821void Browser::ToggleBookmarkBar() {
[email protected]896220042010-03-23 18:14:281822 UserMetrics::RecordAction(UserMetricsAction("ShowBookmarksBar"), profile_);
[email protected]84214982008-12-10 18:49:101823 window_->ToggleBookmarkBar();
1824}
1825
[email protected]84214982008-12-10 18:49:101826void Browser::OpenBookmarkManager() {
[email protected]896220042010-03-23 18:14:281827 UserMetrics::RecordAction(UserMetricsAction("ShowBookmarkManager"), profile_);
[email protected]47e532b2010-04-23 17:46:401828 ShowBookmarkManagerTab();
[email protected]84214982008-12-10 18:49:101829}
[email protected]8bf80e922009-03-09 20:56:361830
[email protected]fdb98512009-08-26 01:37:101831void Browser::ShowAppMenu() {
[email protected]366069f2011-01-11 09:36:121832 // We record the user metric for this event in WrenchMenu::RunMenu.
[email protected]fdb98512009-08-26 01:37:101833 window_->ShowAppMenu();
1834}
1835
[email protected]6404197b2010-03-03 00:40:401836void Browser::ShowBookmarkManagerTab() {
[email protected]04f40d362010-10-11 17:52:451837 UserMetrics::RecordAction(UserMetricsAction("ShowBookmarks"), profile_);
[email protected]fee320542011-03-02 01:30:491838 ShowSingletonTab(GURL(chrome::kChromeUIBookmarksURL));
[email protected]6404197b2010-03-03 00:40:401839}
1840
[email protected]8bf80e922009-03-09 20:56:361841void Browser::ShowHistoryTab() {
[email protected]896220042010-03-23 18:14:281842 UserMetrics::RecordAction(UserMetricsAction("ShowHistory"), profile_);
[email protected]fee320542011-03-02 01:30:491843 ShowSingletonTab(GURL(chrome::kChromeUIHistoryURL));
[email protected]8bf80e922009-03-09 20:56:361844}
[email protected]84214982008-12-10 18:49:101845
1846void Browser::ShowDownloadsTab() {
[email protected]896220042010-03-23 18:14:281847 UserMetrics::RecordAction(UserMetricsAction("ShowDownloads"), profile_);
[email protected]fee320542011-03-02 01:30:491848 ShowSingletonTab(GURL(chrome::kChromeUIDownloadsURL));
[email protected]84214982008-12-10 18:49:101849}
1850
[email protected]34085a32009-11-06 22:49:481851void Browser::ShowExtensionsTab() {
[email protected]896220042010-03-23 18:14:281852 UserMetrics::RecordAction(UserMetricsAction("ShowExtensions"), profile_);
[email protected]fee320542011-03-02 01:30:491853 ShowSingletonTab(GURL(chrome::kChromeUIExtensionsURL));
[email protected]34085a32009-11-06 22:49:481854}
1855
[email protected]c1bbaa82010-11-08 11:17:051856void Browser::ShowAboutConflictsTab() {
1857 UserMetrics::RecordAction(UserMetricsAction("AboutConflicts"), profile_);
[email protected]fee320542011-03-02 01:30:491858 ShowSingletonTab(GURL(chrome::kChromeUIConflictsURL));
[email protected]c1bbaa82010-11-08 11:17:051859}
1860
[email protected]10e457c2010-04-29 03:35:231861void Browser::ShowBrokenPageTab(TabContents* contents) {
1862 UserMetrics::RecordAction(UserMetricsAction("ReportBug"), profile_);
1863 string16 page_title = contents->GetTitle();
1864 NavigationEntry* entry = contents->controller().GetActiveEntry();
1865 if (!entry)
1866 return;
1867 std::string page_url = entry->url().spec();
1868 std::vector<std::string> subst;
1869 subst.push_back(UTF16ToASCII(page_title));
1870 subst.push_back(page_url);
1871 std::string report_page_url =
1872 ReplaceStringPlaceholders(kBrokenPageUrl, subst, NULL);
[email protected]fee320542011-03-02 01:30:491873 ShowSingletonTab(GURL(report_page_url));
[email protected]10e457c2010-04-29 03:35:231874}
1875
[email protected]12e816bde2010-09-14 19:59:291876void Browser::ShowOptionsTab(const std::string& sub_page) {
[email protected]e50eeee2010-09-22 00:33:301877 GURL url(chrome::kChromeUISettingsURL + sub_page);
[email protected]fee320542011-03-02 01:30:491878 browser::NavigateParams params(GetSingletonTabNavigateParams(url));
1879 params.path_behavior = browser::NavigateParams::IGNORE_AND_NAVIGATE;
1880 browser::Navigate(&params);
[email protected]4a42d272010-06-18 01:29:421881}
1882
[email protected]84214982008-12-10 18:49:101883void Browser::OpenClearBrowsingDataDialog() {
[email protected]896220042010-03-23 18:14:281884 UserMetrics::RecordAction(UserMetricsAction("ClearBrowsingData_ShowDlg"),
1885 profile_);
[email protected]445177652011-03-09 02:04:051886 ShowOptionsTab(chrome::kClearBrowserDataSubPage);
[email protected]84214982008-12-10 18:49:101887}
1888
[email protected]84214982008-12-10 18:49:101889void Browser::OpenOptionsDialog() {
[email protected]024617a2010-08-20 05:08:051890 UserMetrics::RecordAction(UserMetricsAction("ShowOptions"), profile_);
[email protected]445177652011-03-09 02:04:051891 GURL url(chrome::kChromeUISettingsURL);
1892 browser::NavigateParams params(GetSingletonTabNavigateParams(url));
1893 params.path_behavior = browser::NavigateParams::IGNORE_AND_STAY_PUT;
1894 browser::Navigate(&params);
[email protected]fbd77592008-11-12 20:50:271895}
1896
1897void Browser::OpenPasswordManager() {
[email protected]e8ce8bb2011-03-10 03:10:041898 UserMetrics::RecordAction(UserMetricsAction("Options_ShowPasswordManager"),
1899 profile_);
1900 ShowOptionsTab(chrome::kPasswordManagerSubPage);
[email protected]fbd77592008-11-12 20:50:271901}
1902
[email protected]1bdf29e2009-05-11 23:45:251903void Browser::OpenImportSettingsDialog() {
[email protected]896220042010-03-23 18:14:281904 UserMetrics::RecordAction(UserMetricsAction("Import_ShowDlg"), profile_);
[email protected]445177652011-03-09 02:04:051905 ShowOptionsTab(chrome::kImportDataSubPage);
[email protected]1bdf29e2009-05-11 23:45:251906}
[email protected]1bdf29e2009-05-11 23:45:251907
[email protected]b99081b2011-03-10 17:43:471908void Browser::OpenInstantConfirmDialog() {
1909 ShowOptionsTab(chrome::kInstantConfirmPage);
1910}
1911
[email protected]ca38d8e2009-08-20 18:08:161912void Browser::OpenSyncMyBookmarksDialog() {
[email protected]40f047972009-11-25 03:54:401913 sync_ui_util::OpenSyncMyBookmarksDialog(
[email protected]c8de64a2011-01-25 17:10:231914 profile_, this, ProfileSyncService::START_FROM_WRENCH);
[email protected]ca38d8e2009-08-20 18:08:161915}
[email protected]ca38d8e2009-08-20 18:08:161916
[email protected]fbd77592008-11-12 20:50:271917void Browser::OpenAboutChromeDialog() {
[email protected]896220042010-03-23 18:14:281918 UserMetrics::RecordAction(UserMetricsAction("AboutChrome"), profile_);
[email protected]976e69f2010-08-13 18:28:171919#if defined(OS_CHROMEOS)
[email protected]fee320542011-03-02 01:30:491920 ShowSingletonTab(GURL(chrome::kChromeUIAboutURL));
[email protected]976e69f2010-08-13 18:28:171921#else
[email protected]2d46c842008-11-14 19:24:311922 window_->ShowAboutChromeDialog();
[email protected]976e69f2010-08-13 18:28:171923#endif
[email protected]fbd77592008-11-12 20:50:271924}
1925
[email protected]b1b73942010-05-26 20:11:541926void Browser::OpenUpdateChromeDialog() {
1927 UserMetrics::RecordAction(UserMetricsAction("UpdateChrome"), profile_);
1928 window_->ShowUpdateChromeDialog();
1929}
1930
[email protected]fbd77592008-11-12 20:50:271931void Browser::OpenHelpTab() {
[email protected]0a4a0be2010-11-09 10:42:471932 GURL help_url(kHelpContentUrl);
[email protected]0a4a0be2010-11-09 10:42:471933 GURL localized_help_url = google_util::AppendGoogleLocaleParam(help_url);
1934 AddSelectedTabWithURL(localized_help_url, PageTransition::AUTO_BOOKMARK);
[email protected]fbd77592008-11-12 20:50:271935}
1936
[email protected]403c14862009-10-28 00:00:491937void Browser::OpenThemeGalleryTabAndActivate() {
[email protected]616381f02010-11-02 15:15:331938 AddSelectedTabWithURL(GURL(l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_URL)),
1939 PageTransition::LINK);
[email protected]403c14862009-10-28 00:00:491940}
1941
[email protected]31cc1c022010-10-15 20:03:471942void Browser::OpenPrivacyDashboardTabAndActivate() {
[email protected]3e0505452010-11-02 21:45:241943 OpenURL(GURL(kPrivacyDashboardUrl), GURL(),
1944 NEW_FOREGROUND_TAB, PageTransition::LINK);
[email protected]31cc1c022010-10-15 20:03:471945 window_->Activate();
1946}
1947
[email protected]bb8fe2d2010-06-28 20:04:221948void Browser::OpenAutoFillHelpTabAndActivate() {
[email protected]91a79232010-11-10 18:15:081949 GURL help_url = google_util::AppendGoogleLocaleParam(GURL(kAutofillHelpUrl));
1950 AddSelectedTabWithURL(help_url, PageTransition::LINK);
[email protected]bb8fe2d2010-06-28 20:04:221951}
1952
[email protected]024617a2010-08-20 05:08:051953void Browser::OpenSearchEngineOptionsDialog() {
[email protected]445177652011-03-09 02:04:051954 UserMetrics::RecordAction(UserMetricsAction("EditSearchEngines"), profile_);
[email protected]445177652011-03-09 02:04:051955 ShowOptionsTab(chrome::kSearchEnginesSubPage);
[email protected]024617a2010-08-20 05:08:051956}
1957
[email protected]16779842009-07-08 23:45:291958#if defined(OS_CHROMEOS)
[email protected]5dcbc02f2010-01-26 22:32:061959void Browser::OpenSystemOptionsDialog() {
[email protected]896220042010-03-23 18:14:281960 UserMetrics::RecordAction(UserMetricsAction("OpenSystemOptionsDialog"),
1961 profile_);
[email protected]445177652011-03-09 02:04:051962 ShowOptionsTab(chrome::kSystemOptionsSubPage);
[email protected]5dcbc02f2010-01-26 22:32:061963}
1964
1965void Browser::OpenInternetOptionsDialog() {
[email protected]896220042010-03-23 18:14:281966 UserMetrics::RecordAction(UserMetricsAction("OpenInternetOptionsDialog"),
1967 profile_);
[email protected]445177652011-03-09 02:04:051968 ShowOptionsTab(chrome::kInternetOptionsSubPage);
[email protected]024617a2010-08-20 05:08:051969}
1970
1971void Browser::OpenLanguageOptionsDialog() {
1972 UserMetrics::RecordAction(UserMetricsAction("OpenLanguageOptionsDialog"),
1973 profile_);
[email protected]445177652011-03-09 02:04:051974 ShowOptionsTab(chrome::kLanguageOptionsSubPage);
[email protected]be715072009-07-07 15:43:201975}
[email protected]46b92f852010-10-06 13:12:051976
1977void Browser::OpenSystemTabAndActivate() {
1978 OpenURL(GURL(chrome::kChromeUISystemInfoURL), GURL(),
1979 NEW_FOREGROUND_TAB, PageTransition::LINK);
1980 window_->Activate();
1981}
1982
[email protected]38017612010-10-13 18:46:001983void Browser::OpenMobilePlanTabAndActivate() {
1984 OpenURL(GURL(chrome::kChromeUIMobileSetupURL), GURL(),
1985 NEW_FOREGROUND_TAB, PageTransition::LINK);
1986 window_->Activate();
1987}
[email protected]be715072009-07-07 15:43:201988#endif
1989
[email protected]a003d8e2010-10-02 21:03:351990void Browser::OpenPluginsTabAndActivate() {
1991 OpenURL(GURL(chrome::kAboutPluginsURL), GURL(),
1992 NEW_FOREGROUND_TAB, PageTransition::LINK);
1993 window_->Activate();
1994}
1995
[email protected]36b6dcb2008-11-12 01:19:571996///////////////////////////////////////////////////////////////////////////////
1997
1998// static
[email protected]79117172009-08-28 16:11:441999void Browser::SetNewHomePagePrefs(PrefService* prefs) {
[email protected]8fe6e1c2010-05-27 08:21:542000 const PrefService::Preference* home_page_pref =
2001 prefs->FindPreference(prefs::kHomePage);
2002 if (home_page_pref &&
2003 !home_page_pref->IsManaged() &&
[email protected]ddd231e2010-06-29 20:35:192004 !prefs->HasPrefPath(prefs::kHomePage)) {
[email protected]b41eb732009-09-30 16:49:332005 prefs->SetString(prefs::kHomePage,
[email protected]ddd231e2010-06-29 20:35:192006 GoogleURLTracker::kDefaultGoogleHomepage);
2007 }
[email protected]8fe6e1c2010-05-27 08:21:542008 const PrefService::Preference* home_page_is_new_tab_page_pref =
2009 prefs->FindPreference(prefs::kHomePageIsNewTabPage);
2010 if (home_page_is_new_tab_page_pref &&
2011 !home_page_is_new_tab_page_pref->IsManaged() &&
2012 !prefs->HasPrefPath(prefs::kHomePageIsNewTabPage))
[email protected]b41eb732009-09-30 16:49:332013 prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
[email protected]79117172009-08-28 16:11:442014}
2015
2016// static
[email protected]36b6dcb2008-11-12 01:19:572017void Browser::RegisterPrefs(PrefService* prefs) {
[email protected]36b6dcb2008-11-12 01:19:572018 prefs->RegisterIntegerPref(prefs::kOptionsWindowLastTabIndex, 0);
[email protected]8b8e7c92010-08-19 18:05:562019 prefs->RegisterIntegerPref(prefs::kExtensionSidebarWidth, -1);
[email protected]f87919d72011-02-02 18:46:162020 prefs->RegisterIntegerPref(prefs::kMultipleProfilePrefMigration, 0);
[email protected]09d81f82010-12-15 16:46:422021 // Educated guess: Chrome has a bundled Flash version supporting
2022 // clearing LSO data, Chromium hasn't.
2023#if defined(GOOGLE_CHROME_BUILD)
2024 prefs->RegisterBooleanPref(prefs::kClearPluginLSODataEnabled, true);
2025#else
2026 prefs->RegisterBooleanPref(prefs::kClearPluginLSODataEnabled, false);
2027#endif
[email protected]36b6dcb2008-11-12 01:19:572028}
2029
2030// static
2031void Browser::RegisterUserPrefs(PrefService* prefs) {
[email protected]0d220832009-11-06 00:45:182032 prefs->RegisterStringPref(prefs::kHomePage,
[email protected]20ce516d2010-06-18 02:20:042033 chrome::kChromeUINewTabURL);
[email protected]36b6dcb2008-11-12 01:19:572034 prefs->RegisterBooleanPref(prefs::kHomePageIsNewTabPage, true);
[email protected]4ef795df2010-02-03 02:35:082035 prefs->RegisterBooleanPref(prefs::kClearSiteDataOnExit, false);
[email protected]36b6dcb2008-11-12 01:19:572036 prefs->RegisterBooleanPref(prefs::kShowHomeButton, false);
[email protected]93a2c7242009-07-07 18:43:092037#if defined(OS_MACOSX)
2038 // This really belongs in platform code, but there's no good place to
2039 // initialize it between the time when the AppController is created
2040 // (where there's no profile) and the time the controller gets another
2041 // crack at the start of the main event loop. By that time, BrowserInit
2042 // has already created the browser window, and it's too late: we need the
2043 // pref to be already initialized. Doing it here also saves us from having
2044 // to hard-code pref registration in the several unit tests that use
2045 // this preference.
2046 prefs->RegisterBooleanPref(prefs::kShowPageOptionsButtons, false);
[email protected]eee9f552009-11-28 22:05:112047 prefs->RegisterBooleanPref(prefs::kShowUpdatePromotionInfoBar, true);
[email protected]93a2c7242009-07-07 18:43:092048#endif
[email protected]20ce516d2010-06-18 02:20:042049 prefs->RegisterStringPref(prefs::kRecentlySelectedEncoding, "");
[email protected]36b6dcb2008-11-12 01:19:572050 prefs->RegisterBooleanPref(prefs::kDeleteBrowsingHistory, true);
2051 prefs->RegisterBooleanPref(prefs::kDeleteDownloadHistory, true);
2052 prefs->RegisterBooleanPref(prefs::kDeleteCache, true);
2053 prefs->RegisterBooleanPref(prefs::kDeleteCookies, true);
2054 prefs->RegisterBooleanPref(prefs::kDeletePasswords, false);
[email protected]18f92d4f2010-10-19 00:14:582055 prefs->RegisterBooleanPref(prefs::kDeleteFormData, false);
[email protected]36b6dcb2008-11-12 01:19:572056 prefs->RegisterIntegerPref(prefs::kDeleteTimePeriod, 0);
[email protected]48b47ffa2009-05-02 07:18:302057 prefs->RegisterBooleanPref(prefs::kCheckDefaultBrowser, true);
[email protected]c8865482009-07-23 20:40:102058 prefs->RegisterBooleanPref(prefs::kShowOmniboxSearchHint, true);
[email protected]ed5431872009-11-17 08:39:512059 prefs->RegisterBooleanPref(prefs::kWebAppCreateOnDesktop, true);
2060 prefs->RegisterBooleanPref(prefs::kWebAppCreateInAppsMenu, true);
2061 prefs->RegisterBooleanPref(prefs::kWebAppCreateInQuickLaunchBar, true);
[email protected]b9c505b2010-04-30 15:05:102062 prefs->RegisterBooleanPref(prefs::kUseVerticalTabs, false);
[email protected]0908acd92010-02-26 17:42:132063 prefs->RegisterBooleanPref(prefs::kEnableTranslate, true);
[email protected]e96bf0c52010-08-23 23:20:572064 prefs->RegisterBooleanPref(prefs::kRemotingHasSetupCompleted, false);
[email protected]02337592010-09-27 18:38:252065 prefs->RegisterStringPref(prefs::kCloudPrintEmail, std::string());
[email protected]06c17322011-02-02 22:41:552066 prefs->RegisterBooleanPref(prefs::kCloudPrintProxyEnabled, true);
[email protected]543432ee2010-10-22 16:32:132067 prefs->RegisterBooleanPref(prefs::kDevToolsDisabled, false);
[email protected]6e6f6cb2011-01-27 13:26:552068 prefs->RegisterBooleanPref(prefs::kIncognitoEnabled, true);
[email protected]fb534c92011-02-01 01:02:072069 prefs->RegisterDoublePref(prefs::kDefaultZoomLevel, 0.0);
[email protected]f87919d72011-02-02 18:46:162070 prefs->RegisterIntegerPref(prefs::kDevToolsSplitLocation, -1);
2071 prefs->RegisterDictionaryPref(prefs::kBrowserWindowPlacement);
[email protected]0d277d682011-02-08 18:04:422072 prefs->RegisterDictionaryPref(prefs::kPreferencesWindowPlacement);
[email protected]97123dc2010-12-21 02:12:332073 // We need to register the type of this preference in order to query
2074 // it even though it's only typically controlled via policy.
2075 prefs->RegisterBooleanPref(prefs::kDisable3DAPIs, false);
[email protected]36b6dcb2008-11-12 01:19:572076}
2077
2078// static
[email protected]ecc523f62010-09-28 22:45:402079bool Browser::RunUnloadEventsHelper(TabContents* contents) {
2080 // If the TabContents is not connected yet, then there's no unload
2081 // handler we can fire even if the TabContents has an unload listener.
2082 // One case where we hit this is in a tab that has an infinite loop
2083 // before load.
[email protected]5aab5e22010-12-08 22:13:292084 if (contents->NeedToFireBeforeUnload()) {
[email protected]ecc523f62010-09-28 22:45:402085 // If the page has unload listeners, then we tell the renderer to fire
2086 // them. Once they have fired, we'll get a message back saying whether
2087 // to proceed closing the page or not, which sends us back to this method
[email protected]5aab5e22010-12-08 22:13:292088 // with the NeedToFireBeforeUnload bit cleared.
[email protected]ecc523f62010-09-28 22:45:402089 contents->render_view_host()->FirePageBeforeUnload(false);
2090 return true;
2091 }
2092 return false;
2093}
2094
2095// static
[email protected]36b6dcb2008-11-12 01:19:572096Browser* Browser::GetBrowserForController(
2097 const NavigationController* controller, int* index_result) {
2098 BrowserList::const_iterator it;
2099 for (it = BrowserList::begin(); it != BrowserList::end(); ++it) {
[email protected]ecc523f62010-09-28 22:45:402100 int index = (*it)->tab_handler_->GetTabStripModel()->GetIndexOfController(
2101 controller);
[email protected]36b6dcb2008-11-12 01:19:572102 if (index != TabStripModel::kNoTab) {
2103 if (index_result)
2104 *index_result = index;
2105 return *it;
2106 }
2107 }
2108
2109 return NULL;
2110}
2111
[email protected]485fba42009-03-24 23:27:292112void Browser::ExecuteCommandWithDisposition(
2113 int id, WindowOpenDisposition disposition) {
[email protected]1fc025202009-01-20 23:03:142114 // No commands are enabled if there is not yet any selected tab.
2115 // TODO(pkasting): It seems like we should not need this, because either
2116 // most/all commands should not have been enabled yet anyway or the ones that
2117 // are enabled should be global, or safe themselves against having no selected
2118 // tab. However, Ben says he tried removing this before and got lots of
2119 // crashes, e.g. from Windows sending WM_COMMANDs at random times during
2120 // window construction. This probably could use closer examination someday.
[email protected]3c9e1872010-11-18 16:17:492121 if (!GetSelectedTabContentsWrapper())
[email protected]1fc025202009-01-20 23:03:142122 return;
2123
[email protected]59c9f002010-11-19 00:38:052124 DCHECK(command_updater_.IsCommandEnabled(id)) << "Invalid/disabled command "
2125 << id;
[email protected]36b6dcb2008-11-12 01:19:572126
[email protected]867125a02009-12-10 06:01:482127 // If command execution is blocked then just record the command and return.
2128 if (block_command_execution_) {
2129 // We actually only allow no more than one blocked command, otherwise some
2130 // commands maybe lost.
[email protected]5dcbc02f2010-01-26 22:32:062131 DCHECK_EQ(last_blocked_command_id_, -1);
[email protected]867125a02009-12-10 06:01:482132 last_blocked_command_id_ = id;
2133 last_blocked_command_disposition_ = disposition;
2134 return;
2135 }
2136
[email protected]fbd77592008-11-12 20:50:272137 // The order of commands in this switch statement must match the function
2138 // declaration order in browser.h!
[email protected]36b6dcb2008-11-12 01:19:572139 switch (id) {
[email protected]84214982008-12-10 18:49:102140 // Navigation commands
[email protected]cb84d642010-06-10 00:56:282141 case IDC_BACK: GoBack(disposition); break;
2142 case IDC_FORWARD: GoForward(disposition); break;
2143 case IDC_RELOAD: Reload(disposition); break;
2144 case IDC_RELOAD_IGNORING_CACHE: ReloadIgnoringCache(disposition); break;
2145 case IDC_HOME: Home(disposition); break;
2146 case IDC_OPEN_CURRENT_URL: OpenCurrentURL(); break;
[email protected]cb84d642010-06-10 00:56:282147 case IDC_STOP: Stop(); break;
[email protected]36b6dcb2008-11-12 01:19:572148
[email protected]84214982008-12-10 18:49:102149 // Window management commands
[email protected]cb84d642010-06-10 00:56:282150 case IDC_NEW_WINDOW: NewWindow(); break;
2151 case IDC_NEW_INCOGNITO_WINDOW: NewIncognitoWindow(); break;
[email protected]cb84d642010-06-10 00:56:282152 case IDC_CLOSE_WINDOW: CloseWindow(); break;
2153 case IDC_NEW_TAB: NewTab(); break;
2154 case IDC_CLOSE_TAB: CloseTab(); break;
2155 case IDC_SELECT_NEXT_TAB: SelectNextTab(); break;
2156 case IDC_SELECT_PREVIOUS_TAB: SelectPreviousTab(); break;
[email protected]91ac9202010-07-30 18:32:352157 case IDC_TABPOSE: OpenTabpose(); break;
[email protected]cb84d642010-06-10 00:56:282158 case IDC_MOVE_TAB_NEXT: MoveTabNext(); break;
2159 case IDC_MOVE_TAB_PREVIOUS: MoveTabPrevious(); break;
[email protected]36b6dcb2008-11-12 01:19:572160 case IDC_SELECT_TAB_0:
2161 case IDC_SELECT_TAB_1:
2162 case IDC_SELECT_TAB_2:
2163 case IDC_SELECT_TAB_3:
2164 case IDC_SELECT_TAB_4:
2165 case IDC_SELECT_TAB_5:
2166 case IDC_SELECT_TAB_6:
[email protected]cb525c82008-12-08 23:04:542167 case IDC_SELECT_TAB_7: SelectNumberedTab(id - IDC_SELECT_TAB_0);
[email protected]cb84d642010-06-10 00:56:282168 break;
2169 case IDC_SELECT_LAST_TAB: SelectLastTab(); break;
2170 case IDC_DUPLICATE_TAB: DuplicateTab(); break;
2171 case IDC_RESTORE_TAB: RestoreTab(); break;
2172 case IDC_COPY_URL: WriteCurrentURLToClipboard(); break;
2173 case IDC_SHOW_AS_TAB: ConvertPopupToTabbedBrowser(); break;
2174 case IDC_FULLSCREEN: ToggleFullscreenMode(); break;
2175 case IDC_EXIT: Exit(); break;
2176 case IDC_TOGGLE_VERTICAL_TABS: ToggleUseVerticalTabs(); break;
[email protected]da17b372010-01-22 23:37:222177#if defined(OS_CHROMEOS)
[email protected]cb84d642010-06-10 00:56:282178 case IDC_SEARCH: Search(); break;
[email protected]d14af522010-12-02 03:54:502179 case IDC_SHOW_KEYBOARD_OVERLAY: ShowKeyboardOverlay(); break;
[email protected]20d17242009-10-26 20:21:052180#endif
[email protected]36b6dcb2008-11-12 01:19:572181
[email protected]84214982008-12-10 18:49:102182 // Page-related commands
[email protected]cb84d642010-06-10 00:56:282183 case IDC_SAVE_PAGE: SavePage(); break;
2184 case IDC_BOOKMARK_PAGE: BookmarkCurrentPage(); break;
2185 case IDC_BOOKMARK_ALL_TABS: BookmarkAllTabs(); break;
[email protected]77d8d622010-12-15 10:30:122186 case IDC_VIEW_SOURCE: ViewSelectedSource(); break;
[email protected]cb84d642010-06-10 00:56:282187 case IDC_EMAIL_PAGE_LOCATION: EmailPageLocation(); break;
2188 case IDC_PRINT: Print(); break;
2189 case IDC_ENCODING_AUTO_DETECT: ToggleEncodingAutoDetect(); break;
[email protected]36b6dcb2008-11-12 01:19:572190 case IDC_ENCODING_UTF8:
2191 case IDC_ENCODING_UTF16LE:
2192 case IDC_ENCODING_ISO88591:
2193 case IDC_ENCODING_WINDOWS1252:
[email protected]1c5bf632008-12-11 20:30:492194 case IDC_ENCODING_GBK:
[email protected]36b6dcb2008-11-12 01:19:572195 case IDC_ENCODING_GB18030:
2196 case IDC_ENCODING_BIG5HKSCS:
2197 case IDC_ENCODING_BIG5:
2198 case IDC_ENCODING_KOREAN:
2199 case IDC_ENCODING_SHIFTJIS:
2200 case IDC_ENCODING_ISO2022JP:
2201 case IDC_ENCODING_EUCJP:
2202 case IDC_ENCODING_THAI:
2203 case IDC_ENCODING_ISO885915:
2204 case IDC_ENCODING_MACINTOSH:
2205 case IDC_ENCODING_ISO88592:
2206 case IDC_ENCODING_WINDOWS1250:
2207 case IDC_ENCODING_ISO88595:
2208 case IDC_ENCODING_WINDOWS1251:
2209 case IDC_ENCODING_KOI8R:
2210 case IDC_ENCODING_KOI8U:
2211 case IDC_ENCODING_ISO88597:
2212 case IDC_ENCODING_WINDOWS1253:
2213 case IDC_ENCODING_ISO88594:
2214 case IDC_ENCODING_ISO885913:
2215 case IDC_ENCODING_WINDOWS1257:
2216 case IDC_ENCODING_ISO88593:
2217 case IDC_ENCODING_ISO885910:
2218 case IDC_ENCODING_ISO885914:
2219 case IDC_ENCODING_ISO885916:
[email protected]36b6dcb2008-11-12 01:19:572220 case IDC_ENCODING_WINDOWS1254:
2221 case IDC_ENCODING_ISO88596:
2222 case IDC_ENCODING_WINDOWS1256:
2223 case IDC_ENCODING_ISO88598:
[email protected]e13271f2009-03-07 00:26:002224 case IDC_ENCODING_ISO88598I:
[email protected]36b6dcb2008-11-12 01:19:572225 case IDC_ENCODING_WINDOWS1255:
[email protected]cb84d642010-06-10 00:56:282226 case IDC_ENCODING_WINDOWS1258: OverrideEncoding(id); break;
[email protected]36b6dcb2008-11-12 01:19:572227
[email protected]84214982008-12-10 18:49:102228 // Clipboard commands
[email protected]cb84d642010-06-10 00:56:282229 case IDC_CUT: Cut(); break;
2230 case IDC_COPY: Copy(); break;
2231 case IDC_PASTE: Paste(); break;
[email protected]84214982008-12-10 18:49:102232
2233 // Find-in-page
[email protected]cb84d642010-06-10 00:56:282234 case IDC_FIND: Find(); break;
2235 case IDC_FIND_NEXT: FindNext(); break;
2236 case IDC_FIND_PREVIOUS: FindPrevious(); break;
[email protected]84214982008-12-10 18:49:102237
2238 // Zoom
[email protected]cb84d642010-06-10 00:56:282239 case IDC_ZOOM_PLUS: Zoom(PageZoom::ZOOM_IN); break;
2240 case IDC_ZOOM_NORMAL: Zoom(PageZoom::RESET); break;
2241 case IDC_ZOOM_MINUS: Zoom(PageZoom::ZOOM_OUT); break;
[email protected]84214982008-12-10 18:49:102242
2243 // Focus various bits of UI
[email protected]cb84d642010-06-10 00:56:282244 case IDC_FOCUS_TOOLBAR: FocusToolbar(); break;
2245 case IDC_FOCUS_LOCATION: FocusLocationBar(); break;
2246 case IDC_FOCUS_SEARCH: FocusSearch(); break;
[email protected]bdb7ff62010-07-20 01:56:522247 case IDC_FOCUS_MENU_BAR: FocusAppMenu(); break;
[email protected]83548a42010-06-18 13:53:372248 case IDC_FOCUS_BOOKMARKS: FocusBookmarksToolbar(); break;
2249 case IDC_FOCUS_CHROMEOS_STATUS: FocusChromeOSStatus(); break;
2250 case IDC_FOCUS_NEXT_PANE: FocusNextPane(); break;
2251 case IDC_FOCUS_PREVIOUS_PANE: FocusPreviousPane(); break;
[email protected]84214982008-12-10 18:49:102252
2253 // Show various bits of UI
[email protected]cb84d642010-06-10 00:56:282254 case IDC_OPEN_FILE: OpenFile(); break;
2255 case IDC_CREATE_SHORTCUTS: OpenCreateShortcutsDialog(); break;
[email protected]2a8a98122010-07-16 11:58:482256 case IDC_DEV_TOOLS: ToggleDevToolsWindow(
2257 DEVTOOLS_TOGGLE_ACTION_NONE);
2258 break;
2259 case IDC_DEV_TOOLS_CONSOLE: ToggleDevToolsWindow(
2260 DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE);
2261 break;
2262 case IDC_DEV_TOOLS_INSPECT: ToggleDevToolsWindow(
2263 DEVTOOLS_TOGGLE_ACTION_INSPECT);
2264 break;
[email protected]adb6a84d2011-02-07 16:58:402265 case IDC_TASK_MANAGER: OpenTaskManager(false); break;
2266 case IDC_VIEW_BACKGROUND_PAGES: OpenTaskManager(true); break;
[email protected]1c41a932010-11-22 23:41:232267 case IDC_FEEDBACK: OpenBugReportDialog(); break;
[email protected]44b2c8852009-03-18 00:57:492268
[email protected]cb84d642010-06-10 00:56:282269 case IDC_SHOW_BOOKMARK_BAR: ToggleBookmarkBar(); break;
[email protected]7664ab32011-02-01 23:35:252270 case IDC_PROFILING_ENABLED: Profiling::Toggle(); break;
[email protected]44b2c8852009-03-18 00:57:492271
[email protected]cb84d642010-06-10 00:56:282272 case IDC_SHOW_BOOKMARK_MANAGER: OpenBookmarkManager(); break;
2273 case IDC_SHOW_APP_MENU: ShowAppMenu(); break;
[email protected]cb84d642010-06-10 00:56:282274 case IDC_SHOW_HISTORY: ShowHistoryTab(); break;
2275 case IDC_SHOW_DOWNLOADS: ShowDownloadsTab(); break;
2276 case IDC_MANAGE_EXTENSIONS: ShowExtensionsTab(); break;
2277 case IDC_SYNC_BOOKMARKS: OpenSyncMyBookmarksDialog(); break;
2278 case IDC_OPTIONS: OpenOptionsDialog(); break;
[email protected]445177652011-03-09 02:04:052279 case IDC_EDIT_SEARCH_ENGINES: OpenSearchEngineOptionsDialog(); break;
[email protected]cb84d642010-06-10 00:56:282280 case IDC_VIEW_PASSWORDS: OpenPasswordManager(); break;
2281 case IDC_CLEAR_BROWSING_DATA: OpenClearBrowsingDataDialog(); break;
2282 case IDC_IMPORT_SETTINGS: OpenImportSettingsDialog(); break;
[email protected]b21d6912010-08-31 19:22:412283 case IDC_ABOUT: OpenAboutChromeDialog(); break;
2284 case IDC_UPGRADE_DIALOG: OpenUpdateChromeDialog(); break;
[email protected]c1bbaa82010-11-08 11:17:052285 case IDC_VIEW_INCOMPATIBILITIES: ShowAboutConflictsTab(); break;
[email protected]cb84d642010-06-10 00:56:282286 case IDC_HELP_PAGE: OpenHelpTab(); break;
[email protected]16779842009-07-08 23:45:292287#if defined(OS_CHROMEOS)
[email protected]cb84d642010-06-10 00:56:282288 case IDC_SYSTEM_OPTIONS: OpenSystemOptionsDialog(); break;
2289 case IDC_INTERNET_OPTIONS: OpenInternetOptionsDialog(); break;
[email protected]024617a2010-08-20 05:08:052290 case IDC_LANGUAGE_OPTIONS: OpenLanguageOptionsDialog(); break;
[email protected]be715072009-07-07 15:43:202291#endif
[email protected]d938aed92009-01-22 19:49:332292
[email protected]36b6dcb2008-11-12 01:19:572293 default:
[email protected]84214982008-12-10 18:49:102294 LOG(WARNING) << "Received Unimplemented Command: " << id;
[email protected]fbd77592008-11-12 20:50:272295 break;
[email protected]36b6dcb2008-11-12 01:19:572296 }
2297}
2298
[email protected]3ab6796d32010-12-21 23:56:072299bool Browser::ExecuteCommandIfEnabled(int id) {
2300 if (command_updater_.SupportsCommand(id) &&
2301 command_updater_.IsCommandEnabled(id)) {
2302 ExecuteCommand(id);
2303 return true;
2304 }
2305 return false;
2306}
2307
[email protected]06181422011-02-09 17:44:212308bool Browser::IsReservedCommandOrKey(int command_id,
2309 const NativeWebKeyboardEvent& event) {
[email protected]06181422011-02-09 17:44:212310#if defined(OS_CHROMEOS)
2311 // Chrome OS's top row of keys produces F1-10. Make sure that web pages
2312 // aren't able to block Chrome from performing the standard actions for F1-F4
2313 // (F5-7 are grabbed by other X clients and hence don't need this protection,
2314 // and F8-10 are handled separately in Chrome via a GDK event filter, but
2315 // let's future-proof this).
2316 ui::KeyboardCode key_code =
[email protected]6a1ae6cd2011-02-11 20:06:092317 static_cast<ui::KeyboardCode>(event.windowsKeyCode);
[email protected]06181422011-02-09 17:44:212318 if (key_code == ui::VKEY_F1 ||
2319 key_code == ui::VKEY_F2 ||
2320 key_code == ui::VKEY_F3 ||
2321 key_code == ui::VKEY_F4 ||
2322 key_code == ui::VKEY_F5 ||
2323 key_code == ui::VKEY_F6 ||
2324 key_code == ui::VKEY_F7 ||
2325 key_code == ui::VKEY_F8 ||
2326 key_code == ui::VKEY_F9 ||
2327 key_code == ui::VKEY_F10) {
[email protected]6a1ae6cd2011-02-11 20:06:092328 return true;
[email protected]06181422011-02-09 17:44:212329 }
2330#endif
2331
[email protected]6a1ae6cd2011-02-11 20:06:092332 return command_id == IDC_CLOSE_TAB ||
[email protected]867125a02009-12-10 06:01:482333 command_id == IDC_CLOSE_WINDOW ||
2334 command_id == IDC_NEW_INCOGNITO_WINDOW ||
2335 command_id == IDC_NEW_TAB ||
2336 command_id == IDC_NEW_WINDOW ||
2337 command_id == IDC_RESTORE_TAB ||
2338 command_id == IDC_SELECT_NEXT_TAB ||
2339 command_id == IDC_SELECT_PREVIOUS_TAB ||
[email protected]c1d0d812010-07-27 20:21:552340 command_id == IDC_TABPOSE ||
[email protected]f97d7f632010-06-01 21:08:332341 command_id == IDC_EXIT ||
2342 command_id == IDC_SEARCH;
[email protected]867125a02009-12-10 06:01:482343}
2344
2345void Browser::SetBlockCommandExecution(bool block) {
2346 block_command_execution_ = block;
2347 if (block) {
2348 last_blocked_command_id_ = -1;
2349 last_blocked_command_disposition_ = CURRENT_TAB;
2350 }
2351}
2352
2353int Browser::GetLastBlockedCommand(WindowOpenDisposition* disposition) {
2354 if (disposition)
2355 *disposition = last_blocked_command_disposition_;
2356 return last_blocked_command_id_;
2357}
2358
[email protected]3c9e1872010-11-18 16:17:492359void Browser::UpdateUIForNavigationInTab(TabContentsWrapper* contents,
[email protected]19d9f3a2010-10-14 21:49:362360 PageTransition::Type transition,
2361 bool user_initiated) {
2362 tabstrip_model()->TabNavigating(contents, transition);
2363
[email protected]3c9e1872010-11-18 16:17:492364 bool contents_is_selected = contents == GetSelectedTabContentsWrapper();
[email protected]19d9f3a2010-10-14 21:49:362365 if (user_initiated && contents_is_selected && window()->GetLocationBar()) {
2366 // Forcibly reset the location bar if the url is going to change in the
2367 // current tab, since otherwise it won't discard any ongoing user edits,
2368 // since it doesn't realize this is a user-initiated action.
2369 window()->GetLocationBar()->Revert();
2370 }
2371
2372 if (GetStatusBubble())
2373 GetStatusBubble()->Hide();
2374
2375 // Update the location bar. This is synchronous. We specifically don't
2376 // update the load state since the load hasn't started yet and updating it
2377 // will put it out of sync with the actual state like whether we're
2378 // displaying a favicon, which controls the throbber. If we updated it here,
2379 // the throbber will show the default favicon for a split second when
2380 // navigating away from the new tab page.
[email protected]3c9e1872010-11-18 16:17:492381 ScheduleUIUpdate(contents->tab_contents(), TabContents::INVALIDATE_URL);
[email protected]19d9f3a2010-10-14 21:49:362382
2383 if (contents_is_selected)
[email protected]3c9e1872010-11-18 16:17:492384 contents->tab_contents()->Focus();
[email protected]19d9f3a2010-10-14 21:49:362385}
2386
2387GURL Browser::GetHomePage() const {
2388 // --homepage overrides any preferences.
2389 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
2390 if (command_line.HasSwitch(switches::kHomePage)) {
[email protected]a8e4b5a82010-10-27 00:05:472391 // TODO(evanm): clean up usage of DIR_CURRENT.
2392 // http://code.google.com/p/chromium/issues/detail?id=60630
2393 // For now, allow this code to call getcwd().
2394 base::ThreadRestrictions::ScopedAllowIO allow_io;
2395
[email protected]19d9f3a2010-10-14 21:49:362396 FilePath browser_directory;
2397 PathService::Get(base::DIR_CURRENT, &browser_directory);
2398 GURL home_page(URLFixerUpper::FixupRelativeFile(browser_directory,
2399 command_line.GetSwitchValuePath(switches::kHomePage)));
2400 if (home_page.is_valid())
2401 return home_page;
2402 }
2403
2404 if (profile_->GetPrefs()->GetBoolean(prefs::kHomePageIsNewTabPage))
2405 return GURL(chrome::kChromeUINewTabURL);
2406 GURL home_page(URLFixerUpper::FixupURL(
2407 profile_->GetPrefs()->GetString(prefs::kHomePage),
2408 std::string()));
2409 if (!home_page.is_valid())
2410 return GURL(chrome::kChromeUINewTabURL);
2411 return home_page;
2412}
2413
[email protected]36b6dcb2008-11-12 01:19:572414///////////////////////////////////////////////////////////////////////////////
[email protected]ecc523f62010-09-28 22:45:402415// Browser, PageNavigator implementation:
[email protected]19d9f3a2010-10-14 21:49:362416
[email protected]ecc523f62010-09-28 22:45:402417void Browser::OpenURL(const GURL& url, const GURL& referrer,
2418 WindowOpenDisposition disposition,
2419 PageTransition::Type transition) {
2420 OpenURLFromTab(NULL, url, referrer, disposition, transition);
2421}
2422
2423///////////////////////////////////////////////////////////////////////////////
[email protected]485fba42009-03-24 23:27:292424// Browser, CommandUpdater::CommandUpdaterDelegate implementation:
2425
2426void Browser::ExecuteCommand(int id) {
2427 ExecuteCommandWithDisposition(id, CURRENT_TAB);
2428}
2429
2430///////////////////////////////////////////////////////////////////////////////
[email protected]ecc523f62010-09-28 22:45:402431// Browser, TabHandlerDelegate implementation:
2432
2433Profile* Browser::GetProfile() const {
2434 return profile();
2435}
2436
2437Browser* Browser::AsBrowser() {
2438 return this;
2439}
2440
2441///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:572442// Browser, TabStripModelDelegate implementation:
2443
[email protected]3c9e1872010-11-18 16:17:492444TabContentsWrapper* Browser::AddBlankTab(bool foreground) {
[email protected]22735af62009-04-07 21:09:582445 return AddBlankTabAt(-1, foreground);
2446}
2447
[email protected]3c9e1872010-11-18 16:17:492448TabContentsWrapper* Browser::AddBlankTabAt(int index, bool foreground) {
[email protected]3f8eb7f2009-10-02 23:58:052449 // Time new tab page creation time. We keep track of the timing data in
2450 // TabContents, but we want to include the time it takes to create the
2451 // TabContents object too.
2452 base::TimeTicks new_tab_start_time = base::TimeTicks::Now();
[email protected]616381f02010-11-02 15:15:332453 browser::NavigateParams params(this, GURL(chrome::kChromeUINewTabURL),
2454 PageTransition::TYPED);
[email protected]616381f02010-11-02 15:15:332455 params.disposition = foreground ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
2456 params.tabstrip_index = index;
2457 browser::Navigate(&params);
[email protected]3c9e1872010-11-18 16:17:492458 params.target_contents->tab_contents()->set_new_tab_start_time(
2459 new_tab_start_time);
[email protected]616381f02010-11-02 15:15:332460 return params.target_contents;
[email protected]15952e462008-11-14 00:29:052461}
2462
[email protected]3c9e1872010-11-18 16:17:492463Browser* Browser::CreateNewStripWithContents(
2464 TabContentsWrapper* detached_contents,
2465 const gfx::Rect& window_bounds,
2466 const DockInfo& dock_info,
2467 bool maximize) {
[email protected]018cf362010-05-05 22:43:222468 DCHECK(CanSupportWindowFeature(FEATURE_TABSTRIP));
[email protected]adf650f2008-12-09 16:10:062469
[email protected]5e495462008-11-20 23:07:412470 gfx::Rect new_window_bounds = window_bounds;
[email protected]5e495462008-11-20 23:07:412471 if (dock_info.GetNewWindowBounds(&new_window_bounds, &maximize))
2472 dock_info.AdjustOtherWindowBounds();
2473
[email protected]36b6dcb2008-11-12 01:19:572474 // Create an empty new browser window the same size as the old one.
[email protected]299dabd2008-11-19 02:27:162475 Browser* browser = new Browser(TYPE_NORMAL, profile_);
[email protected]5e495462008-11-20 23:07:412476 browser->set_override_bounds(new_window_bounds);
[email protected]2e716622009-03-09 21:11:012477 browser->set_maximized_state(
2478 maximize ? MAXIMIZED_STATE_MAXIMIZED : MAXIMIZED_STATE_UNMAXIMIZED);
[email protected]9800de5e2011-03-11 18:19:492479 browser->InitBrowserWindow();
[email protected]15952e462008-11-14 00:29:052480 browser->tabstrip_model()->AppendTabContents(detached_contents, true);
[email protected]159f7762008-12-19 14:58:272481 // Make sure the loading state is updated correctly, otherwise the throbber
2482 // won't start if the page is loading.
[email protected]3c9e1872010-11-18 16:17:492483 browser->LoadingStateChanged(detached_contents->tab_contents());
[email protected]3d1104f2009-03-26 15:30:282484 return browser;
[email protected]36b6dcb2008-11-12 01:19:572485}
2486
2487int Browser::GetDragActions() const {
[email protected]ecc523f62010-09-28 22:45:402488 return TabStripModelDelegate::TAB_TEAROFF_ACTION | (tab_count() > 1 ?
2489 TabStripModelDelegate::TAB_MOVE_ACTION : 0);
[email protected]36b6dcb2008-11-12 01:19:572490}
2491
[email protected]3c9e1872010-11-18 16:17:492492TabContentsWrapper* Browser::CreateTabContentsForURL(
[email protected]36b6dcb2008-11-12 01:19:572493 const GURL& url, const GURL& referrer, Profile* profile,
2494 PageTransition::Type transition, bool defer_load,
2495 SiteInstance* instance) const {
[email protected]3c9e1872010-11-18 16:17:492496 TabContentsWrapper* contents = TabContentsFactory(profile, instance,
[email protected]ecc523f62010-09-28 22:45:402497 MSG_ROUTING_NONE,
[email protected]3c9e1872010-11-18 16:17:492498 GetSelectedTabContents(), NULL);
[email protected]36b6dcb2008-11-12 01:19:572499 if (!defer_load) {
2500 // Load the initial URL before adding the new tab contents to the tab strip
2501 // so that the tab contents has navigation state.
[email protected]ce3fa3c2009-04-20 19:55:572502 contents->controller().LoadURL(url, referrer, transition);
[email protected]36b6dcb2008-11-12 01:19:572503 }
2504
2505 return contents;
2506}
2507
2508bool Browser::CanDuplicateContentsAt(int index) {
[email protected]ce3fa3c2009-04-20 19:55:572509 NavigationController& nc = GetTabContentsAt(index)->controller();
2510 return nc.tab_contents() && nc.GetLastCommittedEntry();
[email protected]36b6dcb2008-11-12 01:19:572511}
2512
2513void Browser::DuplicateContentsAt(int index) {
[email protected]3c9e1872010-11-18 16:17:492514 TabContentsWrapper* contents = GetTabContentsWrapperAt(index);
[email protected]94ce7252010-12-20 21:46:332515 CHECK(contents);
[email protected]77d8d622010-12-15 10:30:122516 TabContentsWrapper* contents_dupe = contents->Clone();
[email protected]47b309f2010-12-28 17:35:562517 TabContents* new_contents = contents_dupe->tab_contents();
2518
2519 bool pinned = false;
2520 if (CanSupportWindowFeature(FEATURE_TABSTRIP)) {
2521 // If this is a tabbed browser, just create a duplicate tab inside the same
2522 // window next to the tab being duplicated.
2523 int index = tab_handler_->GetTabStripModel()->
2524 GetIndexOfTabContents(contents);
2525 pinned = tab_handler_->GetTabStripModel()->IsTabPinned(index);
2526 int add_types = TabStripModel::ADD_SELECTED |
2527 TabStripModel::ADD_INHERIT_GROUP |
2528 (pinned ? TabStripModel::ADD_PINNED : 0);
2529 tab_handler_->GetTabStripModel()->InsertTabContentsAt(index + 1,
2530 contents_dupe,
2531 add_types);
2532 } else {
2533 Browser* browser = NULL;
2534 if (type_ & TYPE_APP) {
2535 CHECK((type_ & TYPE_POPUP) == 0);
2536 CHECK(type_ != TYPE_APP_PANEL);
2537 browser = Browser::CreateForApp(app_name_, gfx::Size(), profile_,
2538 false);
2539 } else if (type_ == TYPE_POPUP) {
2540 browser = Browser::CreateForType(TYPE_POPUP, profile_);
2541 }
2542
2543 // Preserve the size of the original window. The new window has already
2544 // been given an offset by the OS, so we shouldn't copy the old bounds.
2545 BrowserWindow* new_window = browser->window();
2546 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
2547 window()->GetRestoredBounds().size()));
2548
[email protected]4e595682011-02-09 17:07:022549 // We need to show the browser now. Otherwise ContainerWin assumes the
[email protected]47b309f2010-12-28 17:35:562550 // TabContents is invisible and won't size it.
2551 browser->window()->Show();
2552
2553 // The page transition below is only for the purpose of inserting the tab.
2554 browser->AddTab(contents_dupe, PageTransition::LINK);
2555 }
2556
2557 if (profile_->HasSessionService()) {
2558 SessionService* session_service = profile_->GetSessionService();
2559 if (session_service)
2560 session_service->TabRestored(&new_contents->controller(), pinned);
2561 }
[email protected]36b6dcb2008-11-12 01:19:572562}
2563
[email protected]36b6dcb2008-11-12 01:19:572564void Browser::CloseFrameAfterDragSession() {
[email protected]9aefecc92009-06-10 21:31:322565#if defined(OS_WIN) || defined(OS_LINUX)
[email protected]36b6dcb2008-11-12 01:19:572566 // This is scheduled to run after we return to the message loop because
2567 // otherwise the frame will think the drag session is still active and ignore
2568 // the request.
[email protected]d6a3c772009-01-27 19:41:202569 // TODO(port): figure out what is required here in a cross-platform world
[email protected]0586b0e2010-02-12 21:38:372570 MessageLoop::current()->PostTask(
2571 FROM_HERE, method_factory_.NewRunnableMethod(&Browser::CloseFrame));
[email protected]d6a3c772009-01-27 19:41:202572#endif
initial.commit09911bf2008-07-26 23:55:292573}
2574
[email protected]3c9e1872010-11-18 16:17:492575void Browser::CreateHistoricalTab(TabContentsWrapper* contents) {
[email protected]505323e22009-01-24 02:47:582576 // We don't create historical tabs for incognito windows or windows without
2577 // profiles.
2578 if (!profile() || profile()->IsOffTheRecord() ||
2579 !profile()->GetTabRestoreService()) {
2580 return;
2581 }
2582
[email protected]fb5ff422010-05-03 20:46:102583 // We only create historical tab entries for tabbed browser windows.
[email protected]018cf362010-05-05 22:43:222584 if (CanSupportWindowFeature(FEATURE_TABSTRIP)) {
[email protected]505323e22009-01-24 02:47:582585 profile()->GetTabRestoreService()->CreateHistoricalTab(
[email protected]ce3fa3c2009-04-20 19:55:572586 &contents->controller());
[email protected]505323e22009-01-24 02:47:582587 }
2588}
2589
[email protected]3c9e1872010-11-18 16:17:492590bool Browser::RunUnloadListenerBeforeClosing(TabContentsWrapper* contents) {
2591 return Browser::RunUnloadEventsHelper(contents->tab_contents());
[email protected]505323e22009-01-24 02:47:582592}
2593
[email protected]8e48e982009-12-25 11:22:462594bool Browser::CanReloadContents(TabContents* source) const {
2595 return type() != TYPE_DEVTOOLS;
2596}
2597
[email protected]940ccb22009-04-30 17:11:102598bool Browser::CanCloseContentsAt(int index) {
[email protected]0b4d3382010-07-14 16:13:042599 if (!CanCloseTab())
2600 return false;
[email protected]ecc523f62010-09-28 22:45:402601 if (tab_handler_->GetTabStripModel()->count() > 1)
[email protected]940ccb22009-04-30 17:11:102602 return true;
2603 // We are closing the last tab for this browser. Make sure to check for
2604 // in-progress downloads.
2605 // Note that the next call when it returns false will ask the user for
2606 // confirmation before closing the browser if the user decides so.
2607 return CanCloseWithInProgressDownloads();
2608}
[email protected]d6a3c772009-01-27 19:41:202609
[email protected]a206b442009-10-08 23:20:202610bool Browser::CanBookmarkAllTabs() const {
2611 BookmarkModel* model = profile()->GetBookmarkModel();
[email protected]76624fde2009-10-09 18:13:232612 return (model && model->IsLoaded() && (tab_count() > 1));
[email protected]a206b442009-10-08 23:20:202613}
2614
[email protected]b3ac5c82009-10-08 20:56:542615void Browser::BookmarkAllTabs() {
[email protected]ec12ffe2009-10-16 22:28:442616 BookmarkModel* model = profile()->GetBookmarkModel();
2617 DCHECK(model && model->IsLoaded());
2618
2619 BookmarkEditor::EditDetails details;
2620 details.type = BookmarkEditor::EditDetails::NEW_FOLDER;
2621 bookmark_utils::GetURLsForOpenTabs(this, &(details.urls));
2622 DCHECK(!details.urls.empty());
[email protected]b3ac5c82009-10-08 20:56:542623
[email protected]b3ac5c82009-10-08 20:56:542624 BookmarkEditor::Show(window()->GetNativeHandle(), profile_,
[email protected]ec12ffe2009-10-16 22:28:442625 model->GetParentForNewNodes(), details,
[email protected]97a056462010-04-28 16:46:352626 BookmarkEditor::SHOW_TREE);
[email protected]b3ac5c82009-10-08 20:56:542627}
2628
[email protected]0b4d3382010-07-14 16:13:042629bool Browser::CanCloseTab() const {
2630 TabCloseableStateWatcher* watcher =
2631 g_browser_process->tab_closeable_state_watcher();
2632 return !watcher || watcher->CanCloseTab(this);
2633}
2634
[email protected]b9c505b2010-04-30 15:05:102635void Browser::ToggleUseVerticalTabs() {
2636 use_vertical_tabs_.SetValue(!UseVerticalTabs());
[email protected]b3344872010-05-03 15:52:292637 UseVerticalTabsChanged();
[email protected]b9c505b2010-04-30 15:05:102638}
2639
[email protected]b283a7532010-08-12 21:24:592640bool Browser::LargeIconsPermitted() const {
[email protected]af801acd2010-08-20 20:27:442641 // We don't show the big icons in tabs for TYPE_EXTENSION_APP windows because
2642 // for those windows, we already have a big icon in the top-left outside any
2643 // tab. Having big tab icons too looks kinda redonk.
[email protected]94ce7252010-12-20 21:46:332644 return true;
[email protected]b283a7532010-08-12 21:24:592645}
2646
[email protected]2d46c842008-11-14 19:24:312647///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:572648// Browser, TabStripModelObserver implementation:
2649
[email protected]3c9e1872010-11-18 16:17:492650void Browser::TabInsertedAt(TabContentsWrapper* contents,
[email protected]36b6dcb2008-11-12 01:19:572651 int index,
2652 bool foreground) {
[email protected]9219d262011-02-15 21:05:122653 SetAsDelegate(contents, this);
[email protected]ce3fa3c2009-04-20 19:55:572654 contents->controller().SetWindowID(session_id());
[email protected]36b6dcb2008-11-12 01:19:572655
[email protected]c37e3b62010-01-22 00:15:172656 SyncHistoryWithTabs(index);
[email protected]36b6dcb2008-11-12 01:19:572657
[email protected]159f7762008-12-19 14:58:272658 // Make sure the loading state is updated correctly, otherwise the throbber
2659 // won't start if the page is loading.
[email protected]3c9e1872010-11-18 16:17:492660 LoadingStateChanged(contents->tab_contents());
[email protected]159f7762008-12-19 14:58:272661
[email protected]36b6dcb2008-11-12 01:19:572662 // If the tab crashes in the beforeunload or unload handler, it won't be
2663 // able to ack. But we know we can close it.
[email protected]0cb94102009-05-22 19:51:212664 registrar_.Add(this, NotificationType::TAB_CONTENTS_DISCONNECTED,
[email protected]3c9e1872010-11-18 16:17:492665 Source<TabContentsWrapper>(contents));
[email protected]36b6dcb2008-11-12 01:19:572666}
2667
[email protected]f2cc7382010-10-15 18:03:052668void Browser::TabClosingAt(TabStripModel* tab_strip_model,
[email protected]3c9e1872010-11-18 16:17:492669 TabContentsWrapper* contents,
[email protected]f2cc7382010-10-15 18:03:052670 int index) {
[email protected]bfd04a62009-02-01 18:16:562671 NotificationService::current()->Notify(
2672 NotificationType::TAB_CLOSING,
[email protected]ce3fa3c2009-04-20 19:55:572673 Source<NavigationController>(&contents->controller()),
[email protected]bfd04a62009-02-01 18:16:562674 NotificationService::NoDetails());
[email protected]36b6dcb2008-11-12 01:19:572675
2676 // Sever the TabContents' connection back to us.
[email protected]9219d262011-02-15 21:05:122677 SetAsDelegate(contents, NULL);
[email protected]36b6dcb2008-11-12 01:19:572678}
2679
[email protected]3c9e1872010-11-18 16:17:492680void Browser::TabDetachedAt(TabContentsWrapper* contents, int index) {
[email protected]c37e3b62010-01-22 00:15:172681 TabDetachedAtImpl(contents, index, DETACH_TYPE_DETACH);
[email protected]36b6dcb2008-11-12 01:19:572682}
2683
[email protected]2ab3fa92011-02-27 21:46:512684void Browser::TabDeselected(TabContentsWrapper* contents) {
[email protected]6b723f82010-10-05 20:14:272685 if (instant())
2686 instant()->DestroyPreviewContents();
[email protected]03bb953d2010-09-14 21:38:302687
[email protected]85ff2c42009-05-29 21:22:032688 // Save what the user's currently typing, so it can be restored when we
2689 // switch back to this tab.
[email protected]3c9e1872010-11-18 16:17:492690 window_->GetLocationBar()->SaveStateToContents(contents->tab_contents());
[email protected]85ff2c42009-05-29 21:22:032691}
2692
[email protected]3c9e1872010-11-18 16:17:492693void Browser::TabSelectedAt(TabContentsWrapper* old_contents,
2694 TabContentsWrapper* new_contents,
[email protected]36b6dcb2008-11-12 01:19:572695 int index,
2696 bool user_gesture) {
[email protected]02cd2bf2011-03-02 21:45:562697 if (old_contents == new_contents)
2698 return;
[email protected]36b6dcb2008-11-12 01:19:572699
[email protected]a8f024392011-01-13 21:50:162700 // On some platforms we want to automatically reload tabs that are
2701 // killed when the user selects them.
2702 if (user_gesture && new_contents->tab_contents()->crashed_status() ==
2703 base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
2704 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
[email protected]f8a35772011-02-02 23:17:562705 if (parsed_command_line.HasSwitch(switches::kReloadKilledTabs)) {
[email protected]a8f024392011-01-13 21:50:162706 Reload(CURRENT_TAB);
[email protected]f8a35772011-02-02 23:17:562707 return;
2708 }
[email protected]a8f024392011-01-13 21:50:162709 }
2710
[email protected]36b6dcb2008-11-12 01:19:572711 // If we have any update pending, do it now.
2712 if (!chrome_updater_factory_.empty() && old_contents)
2713 ProcessPendingUIUpdates();
2714
[email protected]36b6dcb2008-11-12 01:19:572715 // Propagate the profile to the location bar.
2716 UpdateToolbar(true);
2717
[email protected]943d8122010-06-11 02:13:452718 // Update reload/stop state.
[email protected]3c9e1872010-11-18 16:17:492719 UpdateReloadStopState(new_contents->tab_contents()->is_loading(), true);
[email protected]36b6dcb2008-11-12 01:19:572720
[email protected]84214982008-12-10 18:49:102721 // Update commands to reflect current state.
2722 UpdateCommandsForTabState();
[email protected]36b6dcb2008-11-12 01:19:572723
2724 // Reset the status bubble.
[email protected]be3877f2009-01-14 15:51:102725 StatusBubble* status_bubble = GetStatusBubble();
2726 if (status_bubble) {
2727 status_bubble->Hide();
[email protected]36b6dcb2008-11-12 01:19:572728
[email protected]be3877f2009-01-14 15:51:102729 // Show the loading state (if any).
[email protected]0dd3a0ab2011-02-18 08:17:442730 status_bubble->SetStatus(GetSelectedTabContentsWrapper()->GetStatusText());
[email protected]be3877f2009-01-14 15:51:102731 }
[email protected]36b6dcb2008-11-12 01:19:572732
[email protected]24db8a072009-10-29 20:35:372733 if (HasFindBarController()) {
[email protected]9c318862011-02-01 22:27:242734 find_bar_controller_->ChangeTabContents(new_contents);
[email protected]b77cb302009-10-29 04:09:172735 find_bar_controller_->find_bar()->MoveWindowIfNecessary(gfx::Rect(), true);
[email protected]4801ecc2009-04-05 04:52:582736 }
2737
[email protected]36b6dcb2008-11-12 01:19:572738 // Update sessions. Don't force creation of sessions. If sessions doesn't
2739 // exist, the change will be picked up by sessions when created.
2740 if (profile_->HasSessionService()) {
2741 SessionService* session_service = profile_->GetSessionService();
[email protected]ecc523f62010-09-28 22:45:402742 if (session_service && !tab_handler_->GetTabStripModel()->closing_all()) {
[email protected]2d46c842008-11-14 19:24:312743 session_service->SetSelectedTabInWindow(
[email protected]ecc523f62010-09-28 22:45:402744 session_id(), tab_handler_->GetTabStripModel()->selected_index());
[email protected]36b6dcb2008-11-12 01:19:572745 }
2746 }
2747}
2748
[email protected]3c9e1872010-11-18 16:17:492749void Browser::TabMoved(TabContentsWrapper* contents,
[email protected]36b6dcb2008-11-12 01:19:572750 int from_index,
[email protected]1a242c32010-02-02 21:20:542751 int to_index) {
[email protected]36b6dcb2008-11-12 01:19:572752 DCHECK(from_index >= 0 && to_index >= 0);
2753 // Notify the history service.
2754 SyncHistoryWithTabs(std::min(from_index, to_index));
2755}
2756
[email protected]da25dd52011-01-11 19:06:302757void Browser::TabReplacedAt(TabStripModel* tab_strip_model,
2758 TabContentsWrapper* old_contents,
[email protected]3c9e1872010-11-18 16:17:492759 TabContentsWrapper* new_contents,
[email protected]8a34e6602010-10-02 17:29:432760 int index) {
[email protected]c37e3b62010-01-22 00:15:172761 TabDetachedAtImpl(old_contents, index, DETACH_TYPE_REPLACE);
2762 TabInsertedAt(new_contents, index,
[email protected]ecc523f62010-09-28 22:45:402763 (index == tab_handler_->GetTabStripModel()->selected_index()));
[email protected]c37e3b62010-01-22 00:15:172764
2765 int entry_count = new_contents->controller().entry_count();
2766 if (entry_count > 0) {
2767 // Send out notification so that observers are updated appropriately.
2768 new_contents->controller().NotifyEntryChanged(
2769 new_contents->controller().GetEntryAtIndex(entry_count - 1),
2770 entry_count - 1);
2771 }
[email protected]47e020a2010-10-15 14:43:372772
2773 SessionService* session_service = profile()->GetSessionService();
2774 if (session_service) {
2775 // The new_contents may end up with a different navigation stack. Force
2776 // the session service to update itself.
2777 session_service->TabRestored(
2778 &new_contents->controller(),
2779 tab_handler_->GetTabStripModel()->IsTabPinned(index));
2780 }
[email protected]2914600d2011-01-31 23:25:142781
2782 DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
2783 if (devtools_manager) // NULL in unit tests.
2784 devtools_manager->TabReplaced(old_contents, new_contents);
[email protected]c37e3b62010-01-22 00:15:172785}
2786
[email protected]3c9e1872010-11-18 16:17:492787void Browser::TabPinnedStateChanged(TabContentsWrapper* contents, int index) {
[email protected]5c0e6482009-07-14 20:20:092788 if (!profile()->HasSessionService())
2789 return;
2790 SessionService* session_service = profile()->GetSessionService();
2791 if (session_service) {
2792 session_service->SetPinnedState(
2793 session_id(),
2794 GetTabContentsAt(index)->controller().session_id(),
[email protected]ecc523f62010-09-28 22:45:402795 tab_handler_->GetTabStripModel()->IsTabPinned(index));
[email protected]5c0e6482009-07-14 20:20:092796 }
2797}
2798
[email protected]36b6dcb2008-11-12 01:19:572799void Browser::TabStripEmpty() {
2800 // Close the frame after we return to the message loop (not immediately,
2801 // otherwise it will destroy this object before the stack has a chance to
2802 // cleanly unwind.)
2803 // Note: This will be called several times if TabStripEmpty is called several
2804 // times. This is because it does not close the window if tabs are
2805 // still present.
2806 // NOTE: If you change to be immediate (no invokeLater) then you'll need to
2807 // update BrowserList::CloseAllBrowsers.
[email protected]0586b0e2010-02-12 21:38:372808 MessageLoop::current()->PostTask(
2809 FROM_HERE, method_factory_.NewRunnableMethod(&Browser::CloseFrame));
[email protected]36b6dcb2008-11-12 01:19:572810}
2811
2812///////////////////////////////////////////////////////////////////////////////
2813// Browser, TabContentsDelegate implementation:
initial.commit09911bf2008-07-26 23:55:292814
2815void Browser::OpenURLFromTab(TabContents* source,
[email protected]1f7d7e92009-06-02 20:55:042816 const GURL& url,
2817 const GURL& referrer,
initial.commit09911bf2008-07-26 23:55:292818 WindowOpenDisposition disposition,
[email protected]e38f40152008-09-12 23:08:302819 PageTransition::Type transition) {
[email protected]616381f02010-11-02 15:15:332820 browser::NavigateParams params(this, url, transition);
[email protected]3c9e1872010-11-18 16:17:492821 params.source_contents =
2822 tabstrip_model()->GetTabContentsAt(
2823 tabstrip_model()->GetWrapperIndex(source));
[email protected]616381f02010-11-02 15:15:332824 params.referrer = referrer;
2825 params.disposition = disposition;
2826 params.tabstrip_add_types = TabStripModel::ADD_NONE;
[email protected]caee0792010-11-19 21:19:362827 params.show_window = true;
[email protected]616381f02010-11-02 15:15:332828 browser::Navigate(&params);
initial.commit09911bf2008-07-26 23:55:292829}
2830
2831void Browser::NavigationStateChanged(const TabContents* source,
2832 unsigned changed_flags) {
initial.commit09911bf2008-07-26 23:55:292833 // Only update the UI when something visible has changed.
[email protected]e83f1682008-09-07 23:57:402834 if (changed_flags)
initial.commit09911bf2008-07-26 23:55:292835 ScheduleUIUpdate(source, changed_flags);
2836
[email protected]84214982008-12-10 18:49:102837 // We don't schedule updates to commands since they will only change once per
2838 // navigation, so we don't have to worry about flickering.
[email protected]e83f1682008-09-07 23:57:402839 if (changed_flags & TabContents::INVALIDATE_URL)
[email protected]84214982008-12-10 18:49:102840 UpdateCommandsForTabState();
initial.commit09911bf2008-07-26 23:55:292841}
2842
initial.commit09911bf2008-07-26 23:55:292843void Browser::AddNewContents(TabContents* source,
2844 TabContents* new_contents,
2845 WindowOpenDisposition disposition,
2846 const gfx::Rect& initial_pos,
2847 bool user_gesture) {
[email protected]616381f02010-11-02 15:15:332848 // No code for this yet
2849 DCHECK(disposition != SAVE_TO_DISK);
2850 // Can't create a new contents for the current tab - invalid case.
2851 DCHECK(disposition != CURRENT_TAB);
initial.commit09911bf2008-07-26 23:55:292852
[email protected]616381f02010-11-02 15:15:332853 // TODO(beng): This belongs behind the platform-specific View interface.
2854 // That's why it's there.
[email protected]57b839a2010-10-04 22:49:452855#if defined(OS_CHROMEOS)
[email protected]616381f02010-11-02 15:15:332856 if (disposition == NEW_POPUP) {
2857 // If the popup is bigger than a given factor of the screen, then
2858 // turn it into a foreground tab (on chrome os only)
2859 // Also check for width or height == 0, which would otherwise indicate
2860 // a tab sized popup window.
2861 GdkScreen* screen = gdk_screen_get_default();
2862 int max_width = gdk_screen_get_width(screen) * kPopupMaxWidthFactor;
2863 int max_height = gdk_screen_get_height(screen) * kPopupMaxHeightFactor;
2864 if (initial_pos.width() > max_width || initial_pos.width() == 0 ||
2865 initial_pos.height() > max_height || initial_pos.height() == 0) {
2866 disposition = NEW_FOREGROUND_TAB;
[email protected]57b839a2010-10-04 22:49:452867 }
[email protected]616381f02010-11-02 15:15:332868 }
[email protected]57b839a2010-10-04 22:49:452869#endif
2870
[email protected]3c9e1872010-11-18 16:17:492871 TabContentsWrapper* wrapper = new TabContentsWrapper(new_contents);
2872 browser::NavigateParams params(this, wrapper);
2873 params.source_contents =
2874 tabstrip_model()->GetTabContentsAt(
2875 tabstrip_model()->GetWrapperIndex(source));
2876 params.disposition = disposition;
2877 params.window_bounds = initial_pos;
[email protected]caee0792010-11-19 21:19:362878 params.show_window = true;
[email protected]3c9e1872010-11-18 16:17:492879 browser::Navigate(&params);
initial.commit09911bf2008-07-26 23:55:292880}
2881
initial.commit09911bf2008-07-26 23:55:292882void Browser::ActivateContents(TabContents* contents) {
[email protected]ecc523f62010-09-28 22:45:402883 tab_handler_->GetTabStripModel()->SelectTabContentsAt(
[email protected]3c9e1872010-11-18 16:17:492884 tab_handler_->GetTabStripModel()->GetWrapperIndex(contents), false);
[email protected]f3e99e32008-07-30 04:48:392885 window_->Activate();
initial.commit09911bf2008-07-26 23:55:292886}
2887
[email protected]ea42e7782010-08-23 23:58:122888void Browser::DeactivateContents(TabContents* contents) {
2889 window_->Deactivate();
2890}
2891
initial.commit09911bf2008-07-26 23:55:292892void Browser::LoadingStateChanged(TabContents* source) {
[email protected]ecc523f62010-09-28 22:45:402893 window_->UpdateLoadingAnimations(
2894 tab_handler_->GetTabStripModel()->TabsAreLoading());
[email protected]f3e99e32008-07-30 04:48:392895 window_->UpdateTitleBar();
initial.commit09911bf2008-07-26 23:55:292896
[email protected]3c9e1872010-11-18 16:17:492897 TabContents* selected_contents = GetSelectedTabContents();
2898 if (source == selected_contents) {
[email protected]943d8122010-06-11 02:13:452899 UpdateReloadStopState(source->is_loading(), false);
[email protected]43d259d2010-09-03 21:37:462900 if (GetStatusBubble()) {
[email protected]0dd3a0ab2011-02-18 08:17:442901 GetStatusBubble()->SetStatus(
2902 GetSelectedTabContentsWrapper()->GetStatusText());
[email protected]43d259d2010-09-03 21:37:462903 }
[email protected]eabfdae92009-12-11 06:13:512904
2905 if (!source->is_loading() &&
2906 pending_web_app_action_ == UPDATE_SHORTCUT) {
[email protected]867dff82010-04-23 21:30:332907 // Schedule a shortcut update when web application info is available if
2908 // last committed entry is not NULL. Last committed entry could be NULL
2909 // when an interstitial page is injected (e.g. bad https certificate,
2910 // malware site etc). When this happens, we abort the shortcut update.
[email protected]eabfdae92009-12-11 06:13:512911 NavigationEntry* entry = source->controller().GetLastCommittedEntry();
2912 if (entry) {
2913 source->render_view_host()->GetApplicationInfo(entry->page_id());
2914 } else {
2915 pending_web_app_action_ = NONE;
[email protected]eabfdae92009-12-11 06:13:512916 }
2917 }
initial.commit09911bf2008-07-26 23:55:292918 }
2919}
2920
2921void Browser::CloseContents(TabContents* source) {
[email protected]04b4a6c2008-08-02 00:44:472922 if (is_attempting_to_close_browser_) {
2923 // If we're trying to close the browser, just clear the state related to
[email protected]adf650f2008-12-09 16:10:062924 // waiting for unload to fire. Don't actually try to close the tab as it
[email protected]04b4a6c2008-08-02 00:44:472925 // will go down the slow shutdown path instead of the fast path of killing
2926 // all the renderer processes.
[email protected]08f0d612011-01-13 23:58:212927 ClearUnloadState(source, true);
[email protected]04b4a6c2008-08-02 00:44:472928 return;
2929 }
2930
[email protected]3c9e1872010-11-18 16:17:492931 int index = tab_handler_->GetTabStripModel()->GetWrapperIndex(source);
initial.commit09911bf2008-07-26 23:55:292932 if (index == TabStripModel::kNoTab) {
2933 NOTREACHED() << "CloseContents called for tab not in our strip";
2934 return;
2935 }
[email protected]ecc523f62010-09-28 22:45:402936 tab_handler_->GetTabStripModel()->CloseTabContentsAt(
[email protected]0cce15f2010-05-21 16:58:392937 index,
2938 TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
initial.commit09911bf2008-07-26 23:55:292939}
2940
[email protected]15e8abe2008-08-20 22:40:402941void Browser::MoveContents(TabContents* source, const gfx::Rect& pos) {
[email protected]d5fbc002009-02-27 22:12:582942 if ((type() & TYPE_POPUP) == 0) {
initial.commit09911bf2008-07-26 23:55:292943 NOTREACHED() << "moving invalid browser type";
2944 return;
2945 }
[email protected]e561e202010-03-24 17:57:122946 window_->SetBounds(pos);
initial.commit09911bf2008-07-26 23:55:292947}
2948
[email protected]b6c874582009-05-08 19:38:312949void Browser::DetachContents(TabContents* source) {
[email protected]3c9e1872010-11-18 16:17:492950 int index = tab_handler_->GetTabStripModel()->GetWrapperIndex(source);
[email protected]b6c874582009-05-08 19:38:312951 if (index >= 0)
[email protected]ecc523f62010-09-28 22:45:402952 tab_handler_->GetTabStripModel()->DetachTabContentsAt(index);
[email protected]b6c874582009-05-08 19:38:312953}
2954
[email protected]be04582b2010-07-26 21:56:562955bool Browser::IsPopup(const TabContents* source) const {
initial.commit09911bf2008-07-26 23:55:292956 // A non-tabbed BROWSER is an unconstrained popup.
[email protected]d6df2e32009-10-31 04:39:452957 return !!(type() & TYPE_POPUP);
initial.commit09911bf2008-07-26 23:55:292958}
2959
[email protected]36b6dcb2008-11-12 01:19:572960void Browser::ToolbarSizeChanged(TabContents* source, bool is_animating) {
2961 if (source == GetSelectedTabContents() || source == NULL) {
2962 // This will refresh the shelf if needed.
2963 window_->SelectedTabToolbarSizeChanged(is_animating);
2964 }
2965}
2966
[email protected]b8595e92009-11-14 01:18:002967void Browser::ContentsMouseEvent(
2968 TabContents* source, const gfx::Point& location, bool motion) {
[email protected]be3877f2009-01-14 15:51:102969 if (!GetStatusBubble())
2970 return;
2971
[email protected]36b6dcb2008-11-12 01:19:572972 if (source == GetSelectedTabContents()) {
[email protected]b8595e92009-11-14 01:18:002973 GetStatusBubble()->MouseMoved(location, !motion);
2974 if (!motion)
[email protected]43d259d2010-09-03 21:37:462975 GetStatusBubble()->SetURL(GURL(), string16());
[email protected]36b6dcb2008-11-12 01:19:572976 }
2977}
2978
2979void Browser::UpdateTargetURL(TabContents* source, const GURL& url) {
[email protected]be3877f2009-01-14 15:51:102980 if (!GetStatusBubble())
2981 return;
2982
[email protected]36b6dcb2008-11-12 01:19:572983 if (source == GetSelectedTabContents()) {
2984 PrefService* prefs = profile_->GetPrefs();
[email protected]ddd231e2010-06-29 20:35:192985 GetStatusBubble()->SetURL(
[email protected]43d259d2010-09-03 21:37:462986 url, UTF8ToUTF16(prefs->GetString(prefs::kAcceptLanguages)));
[email protected]36b6dcb2008-11-12 01:19:572987 }
2988}
2989
[email protected]3a6a3b62009-05-27 21:36:202990void Browser::UpdateDownloadShelfVisibility(bool visible) {
[email protected]9b032bf2009-07-21 17:34:232991 if (GetStatusBubble())
2992 GetStatusBubble()->UpdateDownloadShelfVisibility(visible);
[email protected]3a6a3b62009-05-27 21:36:202993}
2994
[email protected]aa02fff12010-07-21 19:55:252995bool Browser::UseVerticalTabs() const {
2996 return use_vertical_tabs_.GetValue();
2997}
2998
[email protected]36b6dcb2008-11-12 01:19:572999void Browser::ContentsZoomChange(bool zoom_in) {
[email protected]b75b8292010-10-01 07:28:253000 ExecuteCommand(zoom_in ? IDC_ZOOM_PLUS : IDC_ZOOM_MINUS);
[email protected]36b6dcb2008-11-12 01:19:573001}
3002
[email protected]20ad6a92010-04-21 14:07:243003void Browser::OnContentSettingsChange(TabContents* source) {
[email protected]9800de5e2011-03-11 18:19:493004 if (source == GetSelectedTabContents()) {
3005 LocationBar* location_bar = window()->GetLocationBar();
3006 if (location_bar)
3007 location_bar->UpdateContentSettingsIcons();
3008 }
[email protected]8cc8d492010-02-02 10:40:493009}
3010
[email protected]fa1cf0b82010-01-15 21:49:443011void Browser::SetTabContentBlocked(TabContents* contents, bool blocked) {
[email protected]3c9e1872010-11-18 16:17:493012 int index = tabstrip_model()->GetWrapperIndex(contents);
[email protected]fa1cf0b82010-01-15 21:49:443013 if (index == TabStripModel::kNoTab) {
3014 NOTREACHED();
3015 return;
3016 }
3017 tabstrip_model()->SetTabBlocked(index, blocked);
3018}
3019
[email protected]7e383692009-06-12 19:14:543020void Browser::TabContentsFocused(TabContents* tab_content) {
3021 window_->TabContentsFocused(tab_content);
3022}
3023
[email protected]130efb02009-09-18 18:54:353024bool Browser::TakeFocus(bool reverse) {
3025 NotificationService::current()->Notify(
3026 NotificationType::FOCUS_RETURNED_TO_BROWSER,
3027 Source<Browser>(this),
3028 NotificationService::NoDetails());
3029 return false;
3030}
3031
[email protected]36b6dcb2008-11-12 01:19:573032bool Browser::IsApplication() const {
[email protected]d5fbc002009-02-27 22:12:583033 return (type_ & TYPE_APP) != 0;
[email protected]36b6dcb2008-11-12 01:19:573034}
3035
3036void Browser::ConvertContentsToApplication(TabContents* contents) {
[email protected]ce3fa3c2009-04-20 19:55:573037 const GURL& url = contents->controller().GetActiveEntry()->url();
[email protected]57ecc4b2010-08-11 03:02:513038 std::string app_name = web_app::GenerateApplicationNameFromURL(url);
[email protected]f87919d72011-02-02 18:46:163039 RegisterAppPrefs(app_name, contents->profile());
[email protected]36b6dcb2008-11-12 01:19:573040
[email protected]b6c874582009-05-08 19:38:313041 DetachContents(contents);
[email protected]94ce7252010-12-20 21:46:333042 Browser* app_browser = Browser::CreateForApp(
3043 app_name, gfx::Size(), profile_, false);
[email protected]3c9e1872010-11-18 16:17:493044 TabContentsWrapper* wrapper = new TabContentsWrapper(contents);
[email protected]75aef122010-12-06 21:48:323045 app_browser->tabstrip_model()->AppendTabContents(wrapper, true);
3046
3047 contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
3048 contents->render_view_host()->SyncRendererPrefs();
3049 app_browser->window()->Show();
[email protected]36b6dcb2008-11-12 01:19:573050}
3051
[email protected]36b6dcb2008-11-12 01:19:573052bool Browser::ShouldDisplayURLField() {
3053 return !IsApplication();
3054}
3055
3056void Browser::BeforeUnloadFired(TabContents* tab,
3057 bool proceed,
3058 bool* proceed_to_fire_unload) {
3059 if (!is_attempting_to_close_browser_) {
3060 *proceed_to_fire_unload = proceed;
[email protected]0cce15f2010-05-21 16:58:393061 if (!proceed)
3062 tab->set_closed_by_user_gesture(false);
[email protected]36b6dcb2008-11-12 01:19:573063 return;
3064 }
3065
3066 if (!proceed) {
3067 CancelWindowClose();
3068 *proceed_to_fire_unload = false;
[email protected]0cce15f2010-05-21 16:58:393069 tab->set_closed_by_user_gesture(false);
[email protected]36b6dcb2008-11-12 01:19:573070 return;
3071 }
3072
[email protected]06b42f032008-12-03 18:43:053073 if (RemoveFromSet(&tabs_needing_before_unload_fired_, tab)) {
[email protected]2d46c842008-11-14 19:24:313074 // Now that beforeunload has fired, put the tab on the queue to fire
3075 // unload.
[email protected]06b42f032008-12-03 18:43:053076 tabs_needing_unload_fired_.insert(tab);
[email protected]36b6dcb2008-11-12 01:19:573077 ProcessPendingTabs();
[email protected]adf650f2008-12-09 16:10:063078 // We want to handle firing the unload event ourselves since we want to
[email protected]36b6dcb2008-11-12 01:19:573079 // fire all the beforeunload events before attempting to fire the unload
3080 // events should the user cancel closing the browser.
3081 *proceed_to_fire_unload = false;
3082 return;
3083 }
3084
3085 *proceed_to_fire_unload = true;
3086}
3087
[email protected]4acc19a62009-04-03 03:05:113088void Browser::ShowHtmlDialog(HtmlDialogUIDelegate* delegate,
[email protected]322f3ff2009-05-22 16:19:543089 gfx::NativeWindow parent_window) {
[email protected]2d46c842008-11-14 19:24:313090 window_->ShowHTMLDialog(delegate, parent_window);
initial.commit09911bf2008-07-26 23:55:293091}
3092
[email protected]a26dc362010-04-23 01:48:583093void Browser::SetFocusToLocationBar(bool select_all) {
[email protected]1a380622009-02-17 17:33:133094 // Two differences between this and FocusLocationBar():
3095 // (1) This doesn't get recorded in user metrics, since it's called
3096 // internally.
3097 // (2) This checks whether the location bar can be focused, and if not, clears
3098 // the focus. FocusLocationBar() is only reached when the location bar is
3099 // focusable, but this may be reached at other times, e.g. while in
3100 // fullscreen mode, where we need to leave focus in a consistent state.
[email protected]a26dc362010-04-23 01:48:583101 window_->SetFocusToLocationBar(select_all);
[email protected]4bcefee2009-01-29 15:57:573102}
3103
[email protected]7d5925a2009-03-03 02:59:123104void Browser::RenderWidgetShowing() {
3105 window_->DisableInactiveFrame();
3106}
[email protected]a239c3f2009-02-17 22:13:193107
[email protected]0a2aeb82009-05-15 21:52:483108int Browser::GetExtraRenderViewHeight() const {
3109 return window_->GetExtraRenderViewHeight();
3110}
3111
[email protected]5b928b62010-08-03 11:46:513112void Browser::OnStartDownload(DownloadItem* download, TabContents* tab) {
[email protected]d0cc9fb52009-06-23 02:26:163113 if (!window())
3114 return;
3115
[email protected]f5bf8ccf2010-02-05 18:19:253116#if defined(OS_CHROMEOS)
[email protected]52c45d62010-06-17 16:26:563117 // Don't show content browser for extension/theme downloads from gallery.
[email protected]d3071992010-10-08 15:24:073118 if (download->is_extension_install()) {
[email protected]eaa7dd182010-12-14 11:09:003119 ExtensionService* service = profile_->GetExtensionService();
[email protected]d3071992010-10-08 15:24:073120 if (service && service->IsDownloadFromGallery(download->url(),
3121 download->referrer_url())) {
3122 return;
3123 }
3124 }
[email protected]52c45d62010-06-17 16:26:563125
[email protected]f5bf8ccf2010-02-05 18:19:253126 // skip the download shelf and just open the file browser in chromeos
3127 std::string arg = download->full_path().DirName().value();
[email protected]467293292010-04-16 19:41:563128 FileBrowseUI::OpenPopup(profile_,
3129 arg,
3130 FileBrowseUI::kPopupWidth,
3131 FileBrowseUI::kPopupHeight);
[email protected]f5bf8ccf2010-02-05 18:19:253132
3133#else
[email protected]d0cc9fb52009-06-23 02:26:163134 // GetDownloadShelf creates the download shelf if it was not yet created.
3135 window()->GetDownloadShelf()->AddDownload(new DownloadItemModel(download));
3136
[email protected]d0cc9fb52009-06-23 02:26:163137 // Don't show the animation for "Save file" downloads.
[email protected]e00778c2009-12-18 02:17:243138 if (download->total_bytes() <= 0)
3139 return;
[email protected]8e48e982009-12-25 11:22:463140
[email protected]e00778c2009-12-18 02:17:243141 // For non-theme extensions, we don't show the download animation.
[email protected]a60c8ae2009-12-25 06:50:573142 if (download->is_extension_install() &&
[email protected]eaa7dd182010-12-14 11:09:003143 !ExtensionService::IsDownloadFromMiniGallery(download->url()))
[email protected]e00778c2009-12-18 02:17:243144 return;
3145
3146 TabContents* current_tab = GetSelectedTabContents();
3147 // We make this check for the case of minimized windows, unit tests, etc.
3148 if (platform_util::IsVisible(current_tab->GetNativeView()) &&
[email protected]f67678062011-01-07 17:33:393149 ui::Animation::ShouldRenderRichAnimation()) {
[email protected]e00778c2009-12-18 02:17:243150 DownloadStartedAnimation::Show(current_tab);
[email protected]f5bf8ccf2010-02-05 18:19:253151 }
3152#endif
[email protected]5b928b62010-08-03 11:46:513153
3154 // If the download occurs in a new tab, close it
3155 if (tab->controller().IsInitialNavigation() &&
3156 GetConstrainingContents(tab) == tab && tab_count() > 1) {
3157 CloseContents(tab);
3158 }
[email protected]d0cc9fb52009-06-23 02:26:163159}
3160
[email protected]bb678332009-07-21 00:15:503161void Browser::ShowPageInfo(Profile* profile,
[email protected]4d677202009-07-19 07:37:123162 const GURL& url,
3163 const NavigationEntry::SSLStatus& ssl,
3164 bool show_history) {
[email protected]bb678332009-07-21 00:15:503165 window()->ShowPageInfo(profile, url, ssl, show_history);
[email protected]4d677202009-07-19 07:37:123166}
3167
[email protected]1788e772010-12-15 16:40:503168void Browser::ViewSourceForTab(TabContents* source, const GURL& page_url) {
3169 DCHECK(source);
3170 int index = tabstrip_model()->GetWrapperIndex(source);
[email protected]77d8d622010-12-15 10:30:123171 TabContentsWrapper* wrapper = tabstrip_model()->GetTabContentsAt(index);
3172 ViewSource(wrapper);
3173}
3174
[email protected]932b7a12011-03-09 12:50:273175void Browser::ViewSourceForFrame(TabContents* source,
3176 const GURL& frame_url,
3177 const std::string& frame_content_state) {
3178 DCHECK(source);
3179 int index = tabstrip_model()->GetWrapperIndex(source);
3180 TabContentsWrapper* wrapper = tabstrip_model()->GetTabContentsAt(index);
3181 ViewSource(wrapper, frame_url, frame_content_state);
3182}
3183
[email protected]867125a02009-12-10 06:01:483184bool Browser::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
3185 bool* is_keyboard_shortcut) {
3186 return window()->PreHandleKeyboardEvent(event, is_keyboard_shortcut);
3187}
[email protected]97df4b332009-10-02 01:25:413188
[email protected]867125a02009-12-10 06:01:483189void Browser::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
3190 window()->HandleKeyboardEvent(event);
[email protected]97df4b332009-10-02 01:25:413191}
3192
[email protected]14f3408a2009-08-31 20:53:533193void Browser::ShowRepostFormWarningDialog(TabContents *tab_contents) {
3194 window()->ShowRepostFormWarningDialog(tab_contents);
3195}
3196
[email protected]63543142010-02-09 23:22:203197void Browser::ShowContentSettingsWindow(ContentSettingsType content_type) {
[email protected]445177652011-03-09 02:04:053198 // TODO(jhawkins): Remove BrowserWindow::ShowContentSettingsWindow.
3199 ShowOptionsTab(
3200 chrome::kContentSettingsExceptionsSubPage + std::string(kHashMark) +
3201 ContentSettingsHandler::ContentSettingsTypeToGroupName(content_type));
[email protected]63543142010-02-09 23:22:203202}
3203
[email protected]a503c97c2010-07-16 13:05:483204void Browser::ShowCollectedCookiesDialog(TabContents *tab_contents) {
3205 window()->ShowCollectedCookiesDialog(tab_contents);
3206}
3207
[email protected]ec0b6c42010-08-26 03:16:583208bool Browser::ShouldAddNavigationToHistory(
3209 const history::HistoryAddPageArgs& add_page_args,
3210 NavigationType::Type navigation_type) {
[email protected]2e29d922009-10-22 22:13:353211 // Don't update history if running as app.
3212 return !IsApplication();
3213}
3214
[email protected]ed5431872009-11-17 08:39:513215void Browser::OnDidGetApplicationInfo(TabContents* tab_contents,
3216 int32 page_id) {
3217 TabContents* current_tab = GetSelectedTabContents();
3218 if (current_tab != tab_contents)
3219 return;
3220
3221 NavigationEntry* entry = current_tab->controller().GetLastCommittedEntry();
3222 if (!entry || (entry->page_id() != page_id))
3223 return;
3224
[email protected]eabfdae92009-12-11 06:13:513225 switch (pending_web_app_action_) {
3226 case CREATE_SHORTCUT: {
[email protected]a3b734b2010-11-30 03:17:113227 window()->ShowCreateWebAppShortcutsDialog(current_tab);
[email protected]eabfdae92009-12-11 06:13:513228 break;
3229 }
3230 case UPDATE_SHORTCUT: {
3231 web_app::UpdateShortcutForTabContents(current_tab);
3232 break;
3233 }
3234 default:
3235 NOTREACHED();
3236 break;
3237 }
3238
3239 pending_web_app_action_ = NONE;
[email protected]ed5431872009-11-17 08:39:513240}
3241
[email protected]bb461532010-11-26 21:50:233242void Browser::OnInstallApplication(TabContents* source,
3243 const WebApplicationInfo& web_app) {
[email protected]eaa7dd182010-12-14 11:09:003244 ExtensionService* extensions_service = profile()->GetExtensionService();
[email protected]bb461532010-11-26 21:50:233245 if (!extensions_service)
3246 return;
3247
3248 scoped_refptr<CrxInstaller> installer(
3249 new CrxInstaller(extensions_service,
3250 extensions_service->show_extensions_prompts() ?
3251 new ExtensionInstallUI(profile()) : NULL));
3252 installer->InstallWebApp(web_app);
3253}
3254
[email protected]9e823662010-10-13 23:36:003255void Browser::ContentRestrictionsChanged(TabContents* source) {
3256 UpdateCommandsForContentRestrictionState();
3257}
3258
[email protected]0dd3a0ab2011-02-18 08:17:443259void Browser::WorkerCrashed() {
3260 TabContents* tab_contents = GetSelectedTabContents();
3261 if (!tab_contents)
3262 return;
3263 tab_contents->AddInfoBar(new SimpleAlertInfoBarDelegate(tab_contents, NULL,
3264 l10n_util::GetStringUTF16(IDS_WEBWORKER_CRASHED_PROMPT), true));
3265}
3266
[email protected]36b6dcb2008-11-12 01:19:573267///////////////////////////////////////////////////////////////////////////////
[email protected]a0366a52011-02-04 20:04:213268// Browser, TabContentsWrapperDelegate implementation:
3269
3270void Browser::URLStarredChanged(TabContentsWrapper* source, bool starred) {
3271 if (source == GetSelectedTabContentsWrapper())
3272 window_->SetStarredState(starred);
3273}
3274
[email protected]c90c6ca2011-02-16 20:11:383275///////////////////////////////////////////////////////////////////////////////
3276// Browser, SearchEngineTabHelperDelegate implementation:
3277
[email protected]9219d262011-02-15 21:05:123278void Browser::ConfirmSetDefaultSearchProvider(
[email protected]b5a1d11c2011-02-17 03:09:423279 TabContents* tab_contents,
[email protected]9219d262011-02-15 21:05:123280 TemplateURL* template_url,
3281 TemplateURLModel* template_url_model) {
3282 window()->ConfirmSetDefaultSearchProvider(tab_contents, template_url,
3283 template_url_model);
3284}
3285
3286void Browser::ConfirmAddSearchProvider(const TemplateURL* template_url,
3287 Profile* profile) {
3288 window()->ConfirmAddSearchProvider(template_url, profile);
3289}
3290
[email protected]a0366a52011-02-04 20:04:213291///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:573292// Browser, SelectFileDialog::Listener implementation:
3293
[email protected]561abe62009-04-06 18:08:343294void Browser::FileSelected(const FilePath& path, int index, void* params) {
[email protected]35896a32010-06-09 08:42:513295 profile_->set_last_selected_directory(path.DirName());
[email protected]72cbd322009-04-07 10:17:123296 GURL file_url = net::FilePathToFileURL(path);
[email protected]36b6dcb2008-11-12 01:19:573297 if (!file_url.is_empty())
3298 OpenURL(file_url, GURL(), CURRENT_TAB, PageTransition::TYPED);
3299}
3300
3301///////////////////////////////////////////////////////////////////////////////
3302// Browser, NotificationObserver implementation:
3303
initial.commit09911bf2008-07-26 23:55:293304void Browser::Observe(NotificationType type,
3305 const NotificationSource& source,
3306 const NotificationDetails& details) {
[email protected]bfd04a62009-02-01 18:16:563307 switch (type.value) {
[email protected]57c6a652009-05-04 07:58:343308 case NotificationType::TAB_CONTENTS_DISCONNECTED:
[email protected]e83f1682008-09-07 23:57:403309 if (is_attempting_to_close_browser_) {
[email protected]08f0d612011-01-13 23:58:213310 // Pass in false so that we delay processing. We need to delay the
3311 // processing as it may close the tab, which is currently on the call
3312 // stack above us.
3313 ClearUnloadState(Source<TabContents>(source).ptr(), false);
[email protected]e83f1682008-09-07 23:57:403314 }
3315 break;
3316
[email protected]b4a19ea2009-03-17 10:08:243317 case NotificationType::SSL_VISIBLE_STATE_CHANGED:
[email protected]e83f1682008-09-07 23:57:403318 // When the current tab's SSL state changes, we need to update the URL
[email protected]90e8d062008-09-08 02:26:323319 // bar to reflect the new state. Note that it's possible for the selected
3320 // tab contents to be NULL. This is because we listen for all sources
3321 // (NavigationControllers) for convenience, so the notification could
3322 // actually be for a different window while we're doing asynchronous
3323 // closing of this one.
3324 if (GetSelectedTabContents() &&
[email protected]ce3fa3c2009-04-20 19:55:573325 &GetSelectedTabContents()->controller() ==
[email protected]e83f1682008-09-07 23:57:403326 Source<NavigationController>(source).ptr())
[email protected]36b6dcb2008-11-12 01:19:573327 UpdateToolbar(false);
[email protected]e83f1682008-09-07 23:57:403328 break;
3329
[email protected]0c6da502009-08-14 22:32:393330 case NotificationType::EXTENSION_UPDATE_DISABLED: {
[email protected]e6090e42010-03-23 22:44:083331 // Show the UI if the extension was disabled for escalated permissions.
[email protected]24e7a9d2009-11-04 11:11:343332 Profile* profile = Source<Profile>(source).ptr();
[email protected]bc535ee52010-08-31 18:40:323333 if (profile_->IsSameProfile(profile)) {
[email protected]eaa7dd182010-12-14 11:09:003334 ExtensionService* service = profile->GetExtensionService();
[email protected]bc535ee52010-08-31 18:40:323335 DCHECK(service);
[email protected]9adb9692010-10-29 23:14:023336 const Extension* extension = Details<const Extension>(details).ptr();
[email protected]bc535ee52010-08-31 18:40:323337 if (service->extension_prefs()->DidExtensionEscalatePermissions(
3338 extension->id()))
3339 ShowExtensionDisabledUI(service, profile_, extension);
3340 }
[email protected]0c6da502009-08-14 22:32:393341 break;
3342 }
3343
[email protected]a9f39a312010-12-23 22:14:273344 case NotificationType::EXTENSION_UNLOADED: {
[email protected]b723ee82009-11-20 16:42:503345 window()->GetLocationBar()->UpdatePageActions();
[email protected]57f71b92009-09-11 19:31:383346
[email protected]894bb502009-05-21 22:39:573347 // Close any tabs from the unloaded extension.
[email protected]a9f39a312010-12-23 22:14:273348 const Extension* extension =
3349 Details<UnloadedExtensionInfo>(details)->extension;
[email protected]ecc523f62010-09-28 22:45:403350 TabStripModel* model = tab_handler_->GetTabStripModel();
3351 for (int i = model->count() - 1; i >= 0; --i) {
[email protected]3c9e1872010-11-18 16:17:493352 TabContents* tc = model->GetTabContentsAt(i)->tab_contents();
[email protected]894bb502009-05-21 22:39:573353 if (tc->GetURL().SchemeIs(chrome::kExtensionScheme) &&
3354 tc->GetURL().host() == extension->id()) {
3355 CloseTabContents(tc);
[email protected]894bb502009-05-21 22:39:573356 }
3357 }
[email protected]9fd542df2009-09-30 07:32:013358
[email protected]894bb502009-05-21 22:39:573359 break;
3360 }
3361
[email protected]a4ed6282009-12-14 20:51:163362 case NotificationType::EXTENSION_PROCESS_TERMINATED: {
[email protected]57f71b92009-09-11 19:31:383363 window()->GetLocationBar()->InvalidatePageActions();
3364
[email protected]371ed7a2009-08-25 15:22:463365 TabContents* tab_contents = GetSelectedTabContents();
3366 if (!tab_contents)
3367 break;
[email protected]eaa7dd182010-12-14 11:09:003368 ExtensionService* extensions_service =
3369 Source<Profile>(source).ptr()->GetExtensionService();
[email protected]371ed7a2009-08-25 15:22:463370 ExtensionHost* extension_host = Details<ExtensionHost>(details).ptr();
3371 tab_contents->AddInfoBar(new CrashedExtensionInfoBarDelegate(
3372 tab_contents, extensions_service, extension_host->extension()));
3373 break;
3374 }
3375
[email protected]0dfe05c2011-02-23 23:03:363376 case NotificationType::EXTENSION_UNINSTALLED: {
3377 window()->GetLocationBar()->UpdatePageActions();
3378
3379 // If any "This extension has crashed" InfoBarDelegates are around for
3380 // this extension, it means that it has been uninstalled
3381 // so just remove the remaining CrashedExtensionInfoBarDelegate objects.
3382 const UninstalledExtensionInfo* uninstalled_extension =
3383 Details<const UninstalledExtensionInfo>(details).ptr();
3384 RemoveCrashedExtensionInfoBar(uninstalled_extension->extension_id);
3385 break;
3386 }
3387
[email protected]ad0c2e1b2010-01-30 00:00:103388 case NotificationType::EXTENSION_LOADED: {
[email protected]26571792010-05-19 21:04:483389 window()->GetLocationBar()->UpdatePageActions();
3390
[email protected]ad0c2e1b2010-01-30 00:00:103391 // If any "This extension has crashed" InfoBarDelegates are around for
3392 // this extension, it means that it has been reloaded in another window
3393 // so just remove the remaining CrashedExtensionInfoBarDelegate objects.
[email protected]9adb9692010-10-29 23:14:023394 const Extension* extension = Details<const Extension>(details).ptr();
[email protected]0dfe05c2011-02-23 23:03:363395 RemoveCrashedExtensionInfoBar(extension->id());
[email protected]ad0c2e1b2010-01-30 00:00:103396 break;
3397 }
3398
[email protected]e001d412009-06-26 20:53:253399 case NotificationType::BROWSER_THEME_CHANGED:
3400 window()->UserChangedTheme();
3401 break;
3402
[email protected]91e1bd82009-09-03 22:04:403403 case NotificationType::EXTENSION_READY_FOR_INSTALL: {
[email protected]a65bce4e2010-06-09 16:00:153404 // Handle EXTENSION_READY_FOR_INSTALL for last active normal browser.
3405 if (BrowserList::FindBrowserWithType(profile(),
3406 Browser::TYPE_NORMAL,
[email protected]074e4f42010-06-23 16:12:063407 true) != this)
[email protected]91e1bd82009-09-03 22:04:403408 break;
[email protected]ac025282009-12-16 19:16:383409
3410 // We only want to show the loading dialog for themes, but we don't want
3411 // to wait until unpack to find out an extension is a theme, so we test
3412 // the download_url GURL instead. This means that themes in the extensions
3413 // gallery won't get the loading dialog.
3414 GURL download_url = *(Details<GURL>(details).ptr());
[email protected]eaa7dd182010-12-14 11:09:003415 if (ExtensionService::IsDownloadFromMiniGallery(download_url))
[email protected]ac025282009-12-16 19:16:383416 window()->ShowThemeInstallBubble();
[email protected]91e1bd82009-09-03 22:04:403417 break;
3418 }
3419
[email protected]e587a45f2009-10-30 22:34:413420 case NotificationType::PROFILE_ERROR: {
[email protected]0e30ef72009-09-05 00:05:083421 if (BrowserList::GetLastActive() != this)
3422 break;
[email protected]e587a45f2009-10-30 22:34:413423 int* message_id = Details<int>(details).ptr();
3424 window()->ShowProfileErrorDialog(*message_id);
[email protected]0e30ef72009-09-05 00:05:083425 break;
3426 }
[email protected]91e1bd82009-09-03 22:04:403427
[email protected]b9c505b2010-04-30 15:05:103428 case NotificationType::PREF_CHANGED: {
[email protected]2a7e7c152010-10-01 20:12:093429 const std::string& pref_name = *Details<std::string>(details).ptr();
3430 if (pref_name == prefs::kUseVerticalTabs) {
[email protected]b3344872010-05-03 15:52:293431 UseVerticalTabsChanged();
[email protected]2a7e7c152010-10-01 20:12:093432 } else if (pref_name == prefs::kPrintingEnabled) {
[email protected]9e823662010-10-13 23:36:003433 UpdatePrintingState(0);
[email protected]73de26a2010-10-17 03:23:253434 } else if (pref_name == prefs::kInstantEnabled) {
3435 if (!InstantController::IsEnabled(profile())) {
3436 if (instant()) {
3437 instant()->DestroyPreviewContents();
[email protected]5aab5e22010-12-08 22:13:293438 instant_.reset();
3439 instant_unload_handler_.reset();
[email protected]73de26a2010-10-17 03:23:253440 }
3441 } else {
3442 CreateInstantIfNecessary();
3443 }
[email protected]543432ee2010-10-22 16:32:133444 } else if (pref_name == prefs::kDevToolsDisabled) {
3445 UpdateCommandsForDevTools();
3446 if (dev_tools_disabled_.GetValue())
3447 g_browser_process->devtools_manager()->CloseAllClientHosts();
[email protected]8f8300212011-02-03 09:49:373448 } else if (pref_name == prefs::kIncognitoEnabled) {
3449 break; // No further action is required.
[email protected]2a7e7c152010-10-01 20:12:093450 } else {
[email protected]b9c505b2010-04-30 15:05:103451 NOTREACHED();
[email protected]2a7e7c152010-10-01 20:12:093452 }
[email protected]b9c505b2010-04-30 15:05:103453 break;
3454 }
3455
[email protected]e83f1682008-09-07 23:57:403456 default:
3457 NOTREACHED() << "Got a notification we didn't register for.";
initial.commit09911bf2008-07-26 23:55:293458 }
3459}
3460
[email protected]0dfe05c2011-02-23 23:03:363461void Browser::RemoveCrashedExtensionInfoBar(const std::string& extension_id) {
3462 TabStripModel* model = tab_handler_->GetTabStripModel();
3463 for (int m = 0; m < model->count(); ++m) {
3464 TabContents* tab_contents = model->GetTabContentsAt(m)->tab_contents();
3465 for (size_t i = 0; i < tab_contents->infobar_count(); ) {
3466 CrashedExtensionInfoBarDelegate* delegate = tab_contents->
3467 GetInfoBarDelegateAt(i)->AsCrashedExtensionInfoBarDelegate();
3468 if (delegate && delegate->extension_id() == extension_id)
3469 tab_contents->RemoveInfoBar(delegate);
3470 else
3471 ++i;
3472 }
3473 }
3474}
3475
[email protected]d3b98c82010-07-14 07:45:593476///////////////////////////////////////////////////////////////////////////////
3477// Browser, ProfileSyncServiceObserver implementation:
3478
3479void Browser::OnStateChanged() {
3480 DCHECK(profile_->GetProfileSyncService());
3481
3482#if !defined(OS_MACOSX)
3483 const bool show_main_ui = (type() == TYPE_NORMAL) && !window_->IsFullscreen();
3484#else
3485 const bool show_main_ui = (type() == TYPE_NORMAL);
3486#endif
3487
3488 command_updater_.UpdateCommandEnabled(IDC_SYNC_BOOKMARKS,
3489 show_main_ui && profile_->IsSyncAccessible());
3490}
[email protected]88d74942009-01-21 22:04:443491
[email protected]36b6dcb2008-11-12 01:19:573492///////////////////////////////////////////////////////////////////////////////
[email protected]6b723f82010-10-05 20:14:273493// Browser, InstantDelegate implementation:
[email protected]03bb953d2010-09-14 21:38:303494
[email protected]36d5e5592010-11-15 20:45:593495void Browser::PrepareForInstant() {
3496 window_->PrepareForInstant();
3497}
3498
[email protected]3c9e1872010-11-18 16:17:493499void Browser::ShowInstant(TabContentsWrapper* preview_contents) {
3500 DCHECK(instant_->tab_contents() == GetSelectedTabContentsWrapper());
3501 window_->ShowInstant(preview_contents->tab_contents());
[email protected]03bb953d2010-09-14 21:38:303502}
3503
[email protected]6b723f82010-10-05 20:14:273504void Browser::HideInstant() {
[email protected]1946c932010-12-15 00:07:383505 window_->HideInstant(instant_->is_active());
[email protected]03bb953d2010-09-14 21:38:303506}
3507
[email protected]3c9e1872010-11-18 16:17:493508void Browser::CommitInstant(TabContentsWrapper* preview_contents) {
3509 TabContentsWrapper* tab_contents = instant_->tab_contents();
3510 int index =
3511 tab_handler_->GetTabStripModel()->GetIndexOfTabContents(tab_contents);
3512 DCHECK_NE(TabStripModel::kNoTab, index);
[email protected]03bb953d2010-09-14 21:38:303513 preview_contents->controller().CopyStateFromAndPrune(
[email protected]47e020a2010-10-15 14:43:373514 &tab_contents->controller());
[email protected]03bb953d2010-09-14 21:38:303515 // TabStripModel takes ownership of preview_contents.
[email protected]5aab5e22010-12-08 22:13:293516 TabContentsWrapper* old_contents =
3517 tab_handler_->GetTabStripModel()->ReplaceTabContentsAt(
3518 index, preview_contents);
3519 // InstantUnloadHandler takes ownership of old_contents.
3520 instant_unload_handler_->RunUnloadListenersOrDestroy(old_contents, index);
[email protected]46fd1ea42011-02-16 15:59:333521
3522 GURL url = preview_contents->tab_contents()->GetURL();
[email protected]6e37fe32011-03-02 09:06:523523 DCHECK(profile_->GetExtensionService());
3524 if (profile_->GetExtensionService()->IsInstalledApp(url)) {
[email protected]46fd1ea42011-02-16 15:59:333525 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram,
3526 extension_misc::APP_LAUNCH_OMNIBOX_INSTANT,
3527 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY);
3528 }
[email protected]03bb953d2010-09-14 21:38:303529}
3530
3531void Browser::SetSuggestedText(const string16& text) {
3532 window()->GetLocationBar()->SetSuggestedText(text);
3533}
3534
[email protected]6b723f82010-10-05 20:14:273535gfx::Rect Browser::GetInstantBounds() {
3536 return window()->GetInstantBounds();
[email protected]46fe8e92010-09-22 03:32:473537}
3538
[email protected]03bb953d2010-09-14 21:38:303539///////////////////////////////////////////////////////////////////////////////
[email protected]9800de5e2011-03-11 18:19:493540// Browser, protected:
3541
3542BrowserWindow* Browser::CreateBrowserWindow() {
3543 return BrowserWindow::CreateBrowserWindow(this);
3544}
3545
3546
3547///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:573548// Browser, Command and state updating (private):
3549
3550void Browser::InitCommandState() {
3551 // All browser commands whose state isn't set automagically some other way
3552 // (like Back & Forward with initial page load) must have their state
3553 // initialized here, otherwise they will be forever disabled.
3554
[email protected]84214982008-12-10 18:49:103555 // Navigation commands
[email protected]1fc025202009-01-20 23:03:143556 command_updater_.UpdateCommandEnabled(IDC_RELOAD, true);
[email protected]1ccb3568d2010-02-19 10:51:163557 command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE, true);
[email protected]84214982008-12-10 18:49:103558
3559 // Window management commands
[email protected]1fc025202009-01-20 23:03:143560 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW, true);
[email protected]6e6f6cb2011-01-27 13:26:553561 command_updater_.UpdateCommandEnabled(IDC_NEW_INCOGNITO_WINDOW,
3562 incognito_mode_allowed_.GetValue());
[email protected]1fc025202009-01-20 23:03:143563 command_updater_.UpdateCommandEnabled(IDC_CLOSE_WINDOW, true);
3564 command_updater_.UpdateCommandEnabled(IDC_NEW_TAB, true);
3565 command_updater_.UpdateCommandEnabled(IDC_CLOSE_TAB, true);
3566 command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB, true);
[email protected]281918912010-05-27 22:05:133567 command_updater_.UpdateCommandEnabled(IDC_RESTORE_TAB, false);
[email protected]1fc025202009-01-20 23:03:143568 command_updater_.UpdateCommandEnabled(IDC_EXIT, true);
[email protected]c8b59f92010-05-28 21:45:473569 command_updater_.UpdateCommandEnabled(IDC_TOGGLE_VERTICAL_TABS, true);
[email protected]84214982008-12-10 18:49:103570
3571 // Page-related commands
[email protected]89d6e6e2009-12-03 23:06:513572 command_updater_.UpdateCommandEnabled(IDC_EMAIL_PAGE_LOCATION, true);
[email protected]1fc025202009-01-20 23:03:143573 command_updater_.UpdateCommandEnabled(IDC_ENCODING_AUTO_DETECT, true);
3574 command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF8, true);
3575 command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF16LE, true);
3576 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88591, true);
3577 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1252, true);
3578 command_updater_.UpdateCommandEnabled(IDC_ENCODING_GBK, true);
3579 command_updater_.UpdateCommandEnabled(IDC_ENCODING_GB18030, true);
3580 command_updater_.UpdateCommandEnabled(IDC_ENCODING_BIG5HKSCS, true);
3581 command_updater_.UpdateCommandEnabled(IDC_ENCODING_BIG5, true);
3582 command_updater_.UpdateCommandEnabled(IDC_ENCODING_THAI, true);
3583 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOREAN, true);
3584 command_updater_.UpdateCommandEnabled(IDC_ENCODING_SHIFTJIS, true);
3585 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO2022JP, true);
3586 command_updater_.UpdateCommandEnabled(IDC_ENCODING_EUCJP, true);
3587 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885915, true);
3588 command_updater_.UpdateCommandEnabled(IDC_ENCODING_MACINTOSH, true);
3589 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88592, true);
3590 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1250, true);
3591 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88595, true);
3592 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1251, true);
3593 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8R, true);
3594 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8U, true);
3595 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88597, true);
3596 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1253, true);
3597 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88594, true);
3598 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885913, true);
3599 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1257, true);
3600 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88593, true);
3601 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885910, true);
3602 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885914, true);
3603 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885916, true);
3604 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1254, true);
3605 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88596, true);
3606 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1256, true);
3607 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598, true);
[email protected]e13271f2009-03-07 00:26:003608 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598I, true);
[email protected]1fc025202009-01-20 23:03:143609 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1255, true);
3610 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1258, true);
[email protected]84214982008-12-10 18:49:103611
[email protected]63b02932009-06-05 09:40:513612 // Zoom
3613 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MENU, true);
3614 command_updater_.UpdateCommandEnabled(IDC_ZOOM_PLUS, true);
3615 command_updater_.UpdateCommandEnabled(IDC_ZOOM_NORMAL, true);
3616 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MINUS, true);
3617
[email protected]84214982008-12-10 18:49:103618 // Show various bits of UI
[email protected]1fc025202009-01-20 23:03:143619 command_updater_.UpdateCommandEnabled(IDC_OPEN_FILE, true);
3620 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS, false);
[email protected]543432ee2010-10-22 16:32:133621 UpdateCommandsForDevTools();
[email protected]1fc025202009-01-20 23:03:143622 command_updater_.UpdateCommandEnabled(IDC_TASK_MANAGER, true);
[email protected]1fc025202009-01-20 23:03:143623 command_updater_.UpdateCommandEnabled(IDC_SHOW_HISTORY, true);
[email protected]4a4180a52010-08-23 06:39:483624 command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER,
3625 browser_defaults::bookmarks_enabled);
[email protected]1fc025202009-01-20 23:03:143626 command_updater_.UpdateCommandEnabled(IDC_SHOW_DOWNLOADS, true);
3627 command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE, true);
[email protected]4aee5652009-11-19 18:59:213628 command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, true);
[email protected]9cd51a02009-10-23 22:30:293629
[email protected]96e34672010-02-09 21:40:293630#if defined(OS_CHROMEOS)
[email protected]f97d7f632010-06-01 21:08:333631 command_updater_.UpdateCommandEnabled(IDC_SEARCH, true);
[email protected]d14af522010-12-02 03:54:503632 command_updater_.UpdateCommandEnabled(IDC_SHOW_KEYBOARD_OVERLAY, true);
[email protected]c8b59f92010-05-28 21:45:473633 command_updater_.UpdateCommandEnabled(IDC_SYSTEM_OPTIONS, true);
3634 command_updater_.UpdateCommandEnabled(IDC_INTERNET_OPTIONS, true);
[email protected]96e34672010-02-09 21:40:293635#endif
[email protected]c8b59f92010-05-28 21:45:473636
[email protected]eaa7dd182010-12-14 11:09:003637 ExtensionService* extensions_service = profile()->GetExtensionService();
[email protected]9cd51a02009-10-23 22:30:293638 bool enable_extensions =
3639 extensions_service && extensions_service->extensions_enabled();
3640 command_updater_.UpdateCommandEnabled(IDC_MANAGE_EXTENSIONS,
3641 enable_extensions);
3642
[email protected]64ff7942008-12-17 18:11:233643 // Initialize other commands based on the window type.
[email protected]11f4857282009-11-13 19:56:173644 bool normal_window = type() == TYPE_NORMAL;
[email protected]fc33e9992010-04-08 19:40:133645 bool non_devtools_window = type() != TYPE_DEVTOOLS;
[email protected]64ff7942008-12-17 18:11:233646
[email protected]11f4857282009-11-13 19:56:173647 // Navigation commands
3648 command_updater_.UpdateCommandEnabled(IDC_HOME, normal_window);
[email protected]64ff7942008-12-17 18:11:233649
[email protected]11f4857282009-11-13 19:56:173650 // Window management commands
[email protected]cf299bc2010-08-12 20:27:093651 command_updater_.UpdateCommandEnabled(IDC_FULLSCREEN,
3652 type() != TYPE_APP_PANEL);
[email protected]11f4857282009-11-13 19:56:173653 command_updater_.UpdateCommandEnabled(IDC_SELECT_NEXT_TAB, normal_window);
3654 command_updater_.UpdateCommandEnabled(IDC_SELECT_PREVIOUS_TAB,
3655 normal_window);
3656 command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_NEXT, normal_window);
3657 command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_PREVIOUS, normal_window);
3658 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_0, normal_window);
3659 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_1, normal_window);
3660 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_2, normal_window);
3661 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_3, normal_window);
3662 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_4, normal_window);
3663 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_5, normal_window);
3664 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_6, normal_window);
3665 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_7, normal_window);
3666 command_updater_.UpdateCommandEnabled(IDC_SELECT_LAST_TAB, normal_window);
[email protected]c1d0d812010-07-27 20:21:553667#if defined(OS_MACOSX)
3668 command_updater_.UpdateCommandEnabled(IDC_TABPOSE, normal_window);
3669#endif
[email protected]e662ade2009-06-08 18:20:143670
[email protected]11f4857282009-11-13 19:56:173671 // Page-related commands
[email protected]4a4180a52010-08-23 06:39:483672 command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_PAGE,
3673 browser_defaults::bookmarks_enabled && normal_window);
[email protected]76624fde2009-10-09 18:13:233674
[email protected]fc33e9992010-04-08 19:40:133675 // Clipboard commands
3676 command_updater_.UpdateCommandEnabled(IDC_COPY_URL, non_devtools_window);
3677
3678 // Find-in-page
3679 command_updater_.UpdateCommandEnabled(IDC_FIND, non_devtools_window);
3680 command_updater_.UpdateCommandEnabled(IDC_FIND_NEXT, non_devtools_window);
3681 command_updater_.UpdateCommandEnabled(IDC_FIND_PREVIOUS, non_devtools_window);
3682
[email protected]cf28ec52010-04-09 22:56:343683 // AutoFill
3684 command_updater_.UpdateCommandEnabled(IDC_AUTOFILL_DEFAULT,
3685 non_devtools_window);
3686
[email protected]11f4857282009-11-13 19:56:173687 // Show various bits of UI
[email protected]fc33e9992010-04-08 19:40:133688 command_updater_.UpdateCommandEnabled(IDC_CLEAR_BROWSING_DATA, normal_window);
[email protected]9282cea2009-02-18 18:49:003689
[email protected]c1bbaa82010-11-08 11:17:053690 // The upgrade entry and the view incompatibility entry should always be
3691 // enabled. Whether they are visible is a separate matter determined on menu
3692 // show.
[email protected]b21d6912010-08-31 19:22:413693 command_updater_.UpdateCommandEnabled(IDC_UPGRADE_DIALOG, true);
[email protected]c1bbaa82010-11-08 11:17:053694 command_updater_.UpdateCommandEnabled(IDC_VIEW_INCOMPATIBILITIES, true);
[email protected]b21d6912010-08-31 19:22:413695
[email protected]b569c112010-11-22 20:53:443696 // View Background Pages entry is always enabled, but is hidden if there are
3697 // no background pages.
3698 command_updater_.UpdateCommandEnabled(IDC_VIEW_BACKGROUND_PAGES, true);
3699
[email protected]9282cea2009-02-18 18:49:003700 // Initialize other commands whose state changes based on fullscreen mode.
3701 UpdateCommandsForFullscreenMode(false);
[email protected]9e823662010-10-13 23:36:003702
3703 UpdateCommandsForContentRestrictionState();
[email protected]36b6dcb2008-11-12 01:19:573704}
3705
[email protected]84214982008-12-10 18:49:103706void Browser::UpdateCommandsForTabState() {
[email protected]c7c42332008-11-15 01:10:543707 TabContents* current_tab = GetSelectedTabContents();
[email protected]a0366a52011-02-04 20:04:213708 TabContentsWrapper* current_tab_wrapper = GetSelectedTabContentsWrapper();
3709 if (!current_tab || !current_tab_wrapper) // May be NULL during tab restore.
[email protected]d8375fd2008-11-25 22:45:393710 return;
[email protected]d8375fd2008-11-25 22:45:393711
[email protected]84214982008-12-10 18:49:103712 // Navigation commands
[email protected]ce3fa3c2009-04-20 19:55:573713 NavigationController& nc = current_tab->controller();
3714 command_updater_.UpdateCommandEnabled(IDC_BACK, nc.CanGoBack());
3715 command_updater_.UpdateCommandEnabled(IDC_FORWARD, nc.CanGoForward());
[email protected]fc33e9992010-04-08 19:40:133716 command_updater_.UpdateCommandEnabled(IDC_RELOAD,
3717 CanReloadContents(current_tab));
3718 command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE,
3719 CanReloadContents(current_tab));
initial.commit09911bf2008-07-26 23:55:293720
[email protected]84214982008-12-10 18:49:103721 // Window management commands
[email protected]fc33e9992010-04-08 19:40:133722 bool non_app_window = !(type() & TYPE_APP);
[email protected]1fc025202009-01-20 23:03:143723 command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB,
[email protected]fc33e9992010-04-08 19:40:133724 non_app_window && CanDuplicateContentsAt(selected_index()));
[email protected]ad0acc62009-12-15 14:28:313725 command_updater_.UpdateCommandEnabled(IDC_SELECT_NEXT_TAB,
[email protected]fc33e9992010-04-08 19:40:133726 non_app_window && tab_count() > 1);
[email protected]ad0acc62009-12-15 14:28:313727 command_updater_.UpdateCommandEnabled(IDC_SELECT_PREVIOUS_TAB,
[email protected]fc33e9992010-04-08 19:40:133728 non_app_window && tab_count() > 1);
[email protected]84214982008-12-10 18:49:103729
[email protected]57c6a652009-05-04 07:58:343730 // Page-related commands
[email protected]a0366a52011-02-04 20:04:213731 window_->SetStarredState(current_tab_wrapper->is_starred());
[email protected]a206b442009-10-08 23:20:203732 command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_ALL_TABS,
[email protected]4a4180a52010-08-23 06:39:483733 browser_defaults::bookmarks_enabled && CanBookmarkAllTabs());
[email protected]57c6a652009-05-04 07:58:343734 command_updater_.UpdateCommandEnabled(IDC_VIEW_SOURCE,
[email protected]31682282010-01-15 18:05:163735 current_tab->controller().CanViewSource());
[email protected]151666e2010-10-21 17:05:253736 command_updater_.UpdateCommandEnabled(IDC_EMAIL_PAGE_LOCATION,
3737 current_tab->ShouldDisplayURL() && current_tab->GetURL().is_valid());
3738
3739 // Changing the encoding is not possible on Chrome-internal webpages.
[email protected]4d07cdc2009-08-22 16:09:393740 // Instead of using GetURL here, we use url() (which is the "real" url of the
3741 // page) from the NavigationEntry because its reflects their origin rather
3742 // than the display one (returned by GetURL) which may be different (like
3743 // having "view-source:" on the front).
[email protected]fc33e9992010-04-08 19:40:133744 NavigationEntry* active_entry = nc.GetActiveEntry();
[email protected]c0f82ec52010-07-27 14:22:143745 bool is_chrome_internal = (active_entry ?
3746 active_entry->url().SchemeIs(chrome::kChromeUIScheme) : false);
3747 command_updater_.UpdateCommandEnabled(IDC_ENCODING_MENU,
3748 !is_chrome_internal && SavePackage::IsSavableContents(
3749 current_tab->contents_mime_type()));
3750
[email protected]57c6a652009-05-04 07:58:343751 // Show various bits of UI
[email protected]c065fa072010-01-20 23:12:253752 // TODO(pinkerton): Disable app-mode in the model until we implement it
3753 // on the Mac. Be sure to remove both ifdefs. http://crbug.com/13148
3754#if !defined(OS_MACOSX)
[email protected]57c6a652009-05-04 07:58:343755 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS,
[email protected]12ea22a2009-11-19 07:17:233756 web_app::IsValidUrl(current_tab->GetURL()));
[email protected]c065fa072010-01-20 23:12:253757#endif
[email protected]9e823662010-10-13 23:36:003758
3759 UpdateCommandsForContentRestrictionState();
3760}
3761
3762void Browser::UpdateCommandsForContentRestrictionState() {
3763 int restrictions = 0;
3764 TabContents* current_tab = GetSelectedTabContents();
[email protected]151666e2010-10-21 17:05:253765 if (current_tab) {
[email protected]9e823662010-10-13 23:36:003766 restrictions = current_tab->content_restrictions();
[email protected]151666e2010-10-21 17:05:253767 NavigationEntry* active_entry = current_tab->controller().GetActiveEntry();
3768 // See comment in UpdateCommandsForTabState about why we call url().
3769 if (!SavePackage::IsSavableURL(active_entry ? active_entry->url() : GURL()))
3770 restrictions |= CONTENT_RESTRICTION_SAVE;
3771 }
[email protected]9e823662010-10-13 23:36:003772
3773 command_updater_.UpdateCommandEnabled(
3774 IDC_COPY, !(restrictions & CONTENT_RESTRICTION_COPY));
3775 command_updater_.UpdateCommandEnabled(
3776 IDC_CUT, !(restrictions & CONTENT_RESTRICTION_CUT));
3777 command_updater_.UpdateCommandEnabled(
3778 IDC_PASTE, !(restrictions & CONTENT_RESTRICTION_PASTE));
[email protected]151666e2010-10-21 17:05:253779 command_updater_.UpdateCommandEnabled(
3780 IDC_SAVE_PAGE, !(restrictions & CONTENT_RESTRICTION_SAVE));
[email protected]9e823662010-10-13 23:36:003781 UpdatePrintingState(restrictions);
3782}
3783
3784void Browser::UpdatePrintingState(int content_restrictions) {
3785 bool enabled = true;
3786 if (content_restrictions & CONTENT_RESTRICTION_PRINT) {
3787 enabled = false;
3788 } else if (g_browser_process->local_state()) {
3789 enabled = printing_enabled_.GetValue();
3790 }
3791 command_updater_.UpdateCommandEnabled(IDC_PRINT, enabled);
initial.commit09911bf2008-07-26 23:55:293792}
3793
[email protected]943d8122010-06-11 02:13:453794void Browser::UpdateReloadStopState(bool is_loading, bool force) {
3795 window_->UpdateReloadStopState(is_loading, force);
[email protected]1fc025202009-01-20 23:03:143796 command_updater_.UpdateCommandEnabled(IDC_STOP, is_loading);
[email protected]64ff7942008-12-17 18:11:233797}
3798
[email protected]543432ee2010-10-22 16:32:133799void Browser::UpdateCommandsForDevTools() {
3800 bool dev_tools_enabled = !dev_tools_disabled_.GetValue();
3801 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS,
3802 dev_tools_enabled);
3803 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_CONSOLE,
3804 dev_tools_enabled);
3805 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_INSPECT,
3806 dev_tools_enabled);
3807}
3808
[email protected]36b6dcb2008-11-12 01:19:573809///////////////////////////////////////////////////////////////////////////////
3810// Browser, UI update coalescing and handling (private):
3811
3812void Browser::UpdateToolbar(bool should_restore_state) {
[email protected]3c9e1872010-11-18 16:17:493813 window_->UpdateToolbar(GetSelectedTabContentsWrapper(), should_restore_state);
initial.commit09911bf2008-07-26 23:55:293814}
3815
[email protected]36b6dcb2008-11-12 01:19:573816void Browser::ScheduleUIUpdate(const TabContents* source,
3817 unsigned changed_flags) {
[email protected]a5231662009-09-26 00:56:003818 if (!source)
3819 return;
3820
[email protected]2b4355c2009-04-04 17:55:463821 // Do some synchronous updates.
[email protected]36b6dcb2008-11-12 01:19:573822 if (changed_flags & TabContents::INVALIDATE_URL &&
3823 source == GetSelectedTabContents()) {
3824 // Only update the URL for the current tab. Note that we do not update
3825 // the navigation commands since those would have already been updated
3826 // synchronously by NavigationStateChanged.
3827 UpdateToolbar(false);
[email protected]8030f012009-09-25 18:09:373828 changed_flags &= ~TabContents::INVALIDATE_URL;
[email protected]36b6dcb2008-11-12 01:19:573829 }
[email protected]a5231662009-09-26 00:56:003830 if (changed_flags & TabContents::INVALIDATE_LOAD) {
[email protected]6ebdc9b2010-09-27 16:55:573831 // Update the loading state synchronously. This is so the throbber will
3832 // immediately start/stop, which gives a more snappy feel. We want to do
[email protected]a5231662009-09-26 00:56:003833 // this for any tab so they start & stop quickly.
[email protected]ecc523f62010-09-28 22:45:403834 tab_handler_->GetTabStripModel()->UpdateTabContentsStateAt(
3835 tab_handler_->GetTabStripModel()->GetIndexOfController(
3836 &source->controller()),
[email protected]6ebdc9b2010-09-27 16:55:573837 TabStripModelObserver::LOADING_ONLY);
3838 // The status bubble needs to be updated during INVALIDATE_LOAD too, but
3839 // we do that asynchronously by not stripping INVALIDATE_LOAD from
3840 // changed_flags.
[email protected]8030f012009-09-25 18:09:373841 }
3842
[email protected]f1cd5e82009-10-23 17:19:033843 if (changed_flags & TabContents::INVALIDATE_TITLE && !source->is_loading()) {
3844 // To correctly calculate whether the title changed while not loading
3845 // we need to process the update synchronously. This state only matters for
3846 // the TabStripModel, so we notify the TabStripModel now and notify others
3847 // asynchronously.
[email protected]ecc523f62010-09-28 22:45:403848 tab_handler_->GetTabStripModel()->UpdateTabContentsStateAt(
3849 tab_handler_->GetTabStripModel()->GetIndexOfController(
3850 &source->controller()),
[email protected]f1cd5e82009-10-23 17:19:033851 TabStripModelObserver::TITLE_NOT_LOADING);
3852 }
3853
[email protected]6d7a6042010-08-12 20:12:423854 if (changed_flags & TabContents::INVALIDATE_BOOKMARK_BAR) {
[email protected]8030f012009-09-25 18:09:373855 window()->ShelfVisibilityChanged();
[email protected]6d7a6042010-08-12 20:12:423856 changed_flags &= ~TabContents::INVALIDATE_BOOKMARK_BAR;
[email protected]2b4355c2009-04-04 17:55:463857 }
3858
3859 // If the only updates were synchronously handled above, we're done.
[email protected]8030f012009-09-25 18:09:373860 if (changed_flags == 0)
[email protected]2b4355c2009-04-04 17:55:463861 return;
[email protected]36b6dcb2008-11-12 01:19:573862
3863 // Save the dirty bits.
[email protected]85354982009-09-25 19:58:403864 scheduled_updates_[source] |= changed_flags;
[email protected]36b6dcb2008-11-12 01:19:573865
3866 if (chrome_updater_factory_.empty()) {
3867 // No task currently scheduled, start another.
[email protected]0586b0e2010-02-12 21:38:373868 MessageLoop::current()->PostDelayedTask(
3869 FROM_HERE,
[email protected]36b6dcb2008-11-12 01:19:573870 chrome_updater_factory_.NewRunnableMethod(
3871 &Browser::ProcessPendingUIUpdates),
[email protected]6ebdc9b2010-09-27 16:55:573872 kUIUpdateCoalescingTimeMS);
[email protected]36b6dcb2008-11-12 01:19:573873 }
3874}
3875
3876void Browser::ProcessPendingUIUpdates() {
3877#ifndef NDEBUG
3878 // Validate that all tabs we have pending updates for exist. This is scary
3879 // because the pending list must be kept in sync with any detached or
[email protected]a5231662009-09-26 00:56:003880 // deleted tabs.
[email protected]85354982009-09-25 19:58:403881 for (UpdateMap::const_iterator i = scheduled_updates_.begin();
3882 i != scheduled_updates_.end(); ++i) {
[email protected]36b6dcb2008-11-12 01:19:573883 bool found = false;
3884 for (int tab = 0; tab < tab_count(); tab++) {
[email protected]a5231662009-09-26 00:56:003885 if (GetTabContentsAt(tab) == i->first) {
[email protected]36b6dcb2008-11-12 01:19:573886 found = true;
3887 break;
3888 }
3889 }
3890 DCHECK(found);
3891 }
3892#endif
3893
3894 chrome_updater_factory_.RevokeAll();
3895
[email protected]85354982009-09-25 19:58:403896 for (UpdateMap::const_iterator i = scheduled_updates_.begin();
3897 i != scheduled_updates_.end(); ++i) {
[email protected]36b6dcb2008-11-12 01:19:573898 // Do not dereference |contents|, it may be out-of-date!
[email protected]85354982009-09-25 19:58:403899 const TabContents* contents = i->first;
3900 unsigned flags = i->second;
[email protected]36b6dcb2008-11-12 01:19:573901
[email protected]a5231662009-09-26 00:56:003902 if (contents == GetSelectedTabContents()) {
3903 // Updates that only matter when the tab is selected go here.
[email protected]f7f3a5f2009-05-01 22:02:343904
[email protected]9800de5e2011-03-11 18:19:493905 if (flags & TabContents::INVALIDATE_PAGE_ACTIONS) {
3906 LocationBar* location_bar = window()->GetLocationBar();
3907 if (location_bar)
3908 location_bar->UpdatePageActions();
3909 }
[email protected]6ebdc9b2010-09-27 16:55:573910 // Updating the URL happens synchronously in ScheduleUIUpdate.
[email protected]0dd3a0ab2011-02-18 08:17:443911 if (flags & TabContents::INVALIDATE_LOAD && GetStatusBubble()) {
3912 GetStatusBubble()->SetStatus(
3913 GetSelectedTabContentsWrapper()->GetStatusText());
3914 }
[email protected]a5231662009-09-26 00:56:003915
[email protected]f1cd5e82009-10-23 17:19:033916 if (flags & (TabContents::INVALIDATE_TAB |
3917 TabContents::INVALIDATE_TITLE)) {
[email protected]c065fa072010-01-20 23:12:253918// TODO(pinkerton): Disable app-mode in the model until we implement it
3919// on the Mac. Be sure to remove both ifdefs. http://crbug.com/13148
3920#if !defined(OS_MACOSX)
[email protected]a5231662009-09-26 00:56:003921 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS,
[email protected]12ea22a2009-11-19 07:17:233922 web_app::IsValidUrl(contents->GetURL()));
[email protected]c065fa072010-01-20 23:12:253923#endif
[email protected]a5231662009-09-26 00:56:003924 window_->UpdateTitleBar();
3925 }
[email protected]4d34e2e2009-05-26 22:55:283926 }
[email protected]36b6dcb2008-11-12 01:19:573927
[email protected]a5231662009-09-26 00:56:003928 // Updates that don't depend upon the selected state go here.
[email protected]f1cd5e82009-10-23 17:19:033929 if (flags & (TabContents::INVALIDATE_TAB | TabContents::INVALIDATE_TITLE)) {
[email protected]ecc523f62010-09-28 22:45:403930 tab_handler_->GetTabStripModel()->UpdateTabContentsStateAt(
[email protected]3c9e1872010-11-18 16:17:493931 tab_handler_->GetTabStripModel()->GetWrapperIndex(contents),
[email protected]f1cd5e82009-10-23 17:19:033932 TabStripModelObserver::ALL);
[email protected]36b6dcb2008-11-12 01:19:573933 }
3934
3935 // We don't need to process INVALIDATE_STATE, since that's not visible.
3936 }
3937
3938 scheduled_updates_.clear();
3939}
3940
3941void Browser::RemoveScheduledUpdatesFor(TabContents* contents) {
3942 if (!contents)
3943 return;
3944
[email protected]85354982009-09-25 19:58:403945 UpdateMap::iterator i = scheduled_updates_.find(contents);
3946 if (i != scheduled_updates_.end())
3947 scheduled_updates_.erase(i);
initial.commit09911bf2008-07-26 23:55:293948}
3949
[email protected]d938aed92009-01-22 19:49:333950
[email protected]36b6dcb2008-11-12 01:19:573951///////////////////////////////////////////////////////////////////////////////
3952// Browser, Getters for UI (private):
initial.commit09911bf2008-07-26 23:55:293953
[email protected]36b6dcb2008-11-12 01:19:573954StatusBubble* Browser::GetStatusBubble() {
[email protected]34930432009-11-09 00:12:093955#if !defined(OS_MACOSX)
3956 // In kiosk mode, we want to always hide the status bubble.
3957 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
3958 return NULL;
3959#endif
[email protected]9b032bf2009-07-21 17:34:233960 return window_ ? window_->GetStatusBubble() : NULL;
initial.commit09911bf2008-07-26 23:55:293961}
3962
[email protected]36b6dcb2008-11-12 01:19:573963///////////////////////////////////////////////////////////////////////////////
3964// Browser, Session restore functions (private):
initial.commit09911bf2008-07-26 23:55:293965
3966void Browser::SyncHistoryWithTabs(int index) {
3967 if (!profile()->HasSessionService())
3968 return;
3969 SessionService* session_service = profile()->GetSessionService();
3970 if (session_service) {
3971 for (int i = index; i < tab_count(); ++i) {
3972 TabContents* contents = GetTabContentsAt(i);
3973 if (contents) {
3974 session_service->SetTabIndexInWindow(
[email protected]ce3fa3c2009-04-20 19:55:573975 session_id(), contents->controller().session_id(), i);
[email protected]ecc523f62010-09-28 22:45:403976 session_service->SetPinnedState(
3977 session_id(),
3978 contents->controller().session_id(),
3979 tab_handler_->GetTabStripModel()->IsTabPinned(i));
initial.commit09911bf2008-07-26 23:55:293980 }
3981 }
3982 }
3983}
3984
[email protected]36b6dcb2008-11-12 01:19:573985///////////////////////////////////////////////////////////////////////////////
3986// Browser, OnBeforeUnload handling (private):
initial.commit09911bf2008-07-26 23:55:293987
[email protected]04b4a6c2008-08-02 00:44:473988void Browser::ProcessPendingTabs() {
[email protected]08f0d612011-01-13 23:58:213989 if (!is_attempting_to_close_browser_) {
3990 // Because we might invoke this after a delay it's possible for the value of
3991 // is_attempting_to_close_browser_ to have changed since we scheduled the
3992 // task.
3993 return;
3994 }
initial.commit09911bf2008-07-26 23:55:293995
[email protected]04b4a6c2008-08-02 00:44:473996 if (HasCompletedUnloadProcessing()) {
3997 // We've finished all the unload events and can proceed to close the
3998 // browser.
3999 OnWindowClosing();
initial.commit09911bf2008-07-26 23:55:294000 return;
4001 }
4002
[email protected]04b4a6c2008-08-02 00:44:474003 // Process beforeunload tabs first. When that queue is empty, process
4004 // unload tabs.
[email protected]04b4a6c2008-08-02 00:44:474005 if (!tabs_needing_before_unload_fired_.empty()) {
[email protected]06b42f032008-12-03 18:43:054006 TabContents* tab = *(tabs_needing_before_unload_fired_.begin());
[email protected]22484622009-06-10 21:17:244007 // Null check render_view_host here as this gets called on a PostTask and
4008 // the tab's render_view_host may have been nulled out.
4009 if (tab->render_view_host()) {
[email protected]ae23c272009-07-27 20:15:404010 tab->render_view_host()->FirePageBeforeUnload(false);
[email protected]22484622009-06-10 21:17:244011 } else {
[email protected]08f0d612011-01-13 23:58:214012 ClearUnloadState(tab, true);
[email protected]22484622009-06-10 21:17:244013 }
[email protected]04b4a6c2008-08-02 00:44:474014 } else if (!tabs_needing_unload_fired_.empty()) {
initial.commit09911bf2008-07-26 23:55:294015 // We've finished firing all beforeunload events and can proceed with unload
4016 // events.
4017 // TODO(ojan): We should add a call to browser_shutdown::OnShutdownStarting
4018 // somewhere around here so that we have accurate measurements of shutdown
4019 // time.
[email protected]04b4a6c2008-08-02 00:44:474020 // TODO(ojan): We can probably fire all the unload events in parallel and
4021 // get a perf benefit from that in the cases where the tab hangs in it's
4022 // unload handler or takes a long time to page in.
[email protected]06b42f032008-12-03 18:43:054023 TabContents* tab = *(tabs_needing_unload_fired_.begin());
[email protected]22484622009-06-10 21:17:244024 // Null check render_view_host here as this gets called on a PostTask and
4025 // the tab's render_view_host may have been nulled out.
4026 if (tab->render_view_host()) {
[email protected]eb6b87a2009-07-24 15:57:394027 tab->render_view_host()->ClosePage(false, -1, -1);
[email protected]22484622009-06-10 21:17:244028 } else {
[email protected]08f0d612011-01-13 23:58:214029 ClearUnloadState(tab, true);
[email protected]22484622009-06-10 21:17:244030 }
initial.commit09911bf2008-07-26 23:55:294031 } else {
[email protected]04b4a6c2008-08-02 00:44:474032 NOTREACHED();
initial.commit09911bf2008-07-26 23:55:294033 }
4034}
4035
[email protected]d043c2cc2009-03-25 18:30:454036bool Browser::HasCompletedUnloadProcessing() const {
[email protected]04b4a6c2008-08-02 00:44:474037 return is_attempting_to_close_browser_ &&
4038 tabs_needing_before_unload_fired_.empty() &&
4039 tabs_needing_unload_fired_.empty();
4040}
4041
4042void Browser::CancelWindowClose() {
[email protected]0b4d3382010-07-14 16:13:044043 // Closing of window can be canceled from:
4044 // - canceling beforeunload
4045 // - disallowing closing from IsClosingPermitted.
[email protected]04b4a6c2008-08-02 00:44:474046 DCHECK(is_attempting_to_close_browser_);
[email protected]8f673f3a2008-08-05 22:34:284047 tabs_needing_before_unload_fired_.clear();
4048 tabs_needing_unload_fired_.clear();
[email protected]04b4a6c2008-08-02 00:44:474049 is_attempting_to_close_browser_ = false;
[email protected]0b4d3382010-07-14 16:13:044050
4051 // Inform TabCloseableStateWatcher that closing of window has been canceled.
4052 TabCloseableStateWatcher* watcher =
4053 g_browser_process->tab_closeable_state_watcher();
4054 if (watcher)
4055 watcher->OnWindowCloseCanceled(this);
[email protected]04b4a6c2008-08-02 00:44:474056}
4057
[email protected]06b42f032008-12-03 18:43:054058bool Browser::RemoveFromSet(UnloadListenerSet* set, TabContents* tab) {
[email protected]04b4a6c2008-08-02 00:44:474059 DCHECK(is_attempting_to_close_browser_);
4060
[email protected]06b42f032008-12-03 18:43:054061 UnloadListenerSet::iterator iter = std::find(set->begin(), set->end(), tab);
4062 if (iter != set->end()) {
4063 set->erase(iter);
4064 return true;
[email protected]04b4a6c2008-08-02 00:44:474065 }
4066 return false;
4067}
initial.commit09911bf2008-07-26 23:55:294068
[email protected]08f0d612011-01-13 23:58:214069void Browser::ClearUnloadState(TabContents* tab, bool process_now) {
[email protected]0b4d3382010-07-14 16:13:044070 // Closing of browser could be canceled (via IsClosingPermitted) between the
4071 // time when request was initiated and when this method is called, so check
4072 // for is_attempting_to_close_browser_ flag before proceeding.
4073 if (is_attempting_to_close_browser_) {
4074 RemoveFromSet(&tabs_needing_before_unload_fired_, tab);
4075 RemoveFromSet(&tabs_needing_unload_fired_, tab);
[email protected]08f0d612011-01-13 23:58:214076 if (process_now) {
4077 ProcessPendingTabs();
4078 } else {
4079 MessageLoop::current()->PostTask(
4080 FROM_HERE,
4081 method_factory_.NewRunnableMethod(&Browser::ProcessPendingTabs));
4082 }
[email protected]0b4d3382010-07-14 16:13:044083 }
initial.commit09911bf2008-07-26 23:55:294084}
4085
[email protected]36b6dcb2008-11-12 01:19:574086///////////////////////////////////////////////////////////////////////////////
[email protected]69444cc2009-04-09 20:40:064087// Browser, In-progress download termination handling (private):
4088
[email protected]460a2942010-12-15 19:43:154089void Browser::CheckDownloadsInProgress(bool* normal_downloads_are_present,
4090 bool* incognito_downloads_are_present) {
4091 *normal_downloads_are_present = false;
4092 *incognito_downloads_are_present = false;
4093
4094 // If there are no download in-progress, our job is done.
4095 DownloadManager* download_manager = NULL;
4096 // But first we need to check for the existance of the download manager, as
4097 // GetDownloadManager() will unnecessarily try to create one if it does not
4098 // exist.
4099 if (profile()->HasCreatedDownloadManager())
4100 download_manager = profile()->GetDownloadManager();
4101 if (profile()->IsOffTheRecord()) {
4102 // Browser is incognito and so download_manager if present is for incognito
4103 // downloads.
4104 *incognito_downloads_are_present =
4105 (download_manager && download_manager->in_progress_count() != 0);
4106 // Check original profile.
4107 if (profile()->GetOriginalProfile()->HasCreatedDownloadManager())
4108 download_manager = profile()->GetOriginalProfile()->GetDownloadManager();
4109 }
4110
4111 *normal_downloads_are_present =
4112 (download_manager && download_manager->in_progress_count() != 0);
4113}
4114
[email protected]69444cc2009-04-09 20:40:064115bool Browser::CanCloseWithInProgressDownloads() {
4116 if (cancel_download_confirmation_state_ != NOT_PROMPTED) {
[email protected]7a22201c2009-10-16 16:50:374117 if (cancel_download_confirmation_state_ == WAITING_FOR_RESPONSE) {
4118 // We need to hear from the user before we can close.
4119 return false;
4120 }
4121 // RESPONSE_RECEIVED case, the user decided to go along with the closing.
[email protected]69444cc2009-04-09 20:40:064122 return true;
4123 }
[email protected]446295a2010-04-19 23:43:004124 // Indicated that normal (non-incognito) downloads are pending.
4125 bool normal_downloads_are_present = false;
4126 bool incognito_downloads_are_present = false;
[email protected]460a2942010-12-15 19:43:154127 CheckDownloadsInProgress(&normal_downloads_are_present,
4128 &incognito_downloads_are_present);
[email protected]446295a2010-04-19 23:43:004129 if (!normal_downloads_are_present && !incognito_downloads_are_present)
4130 return true;
4131
4132 if (is_attempting_to_close_browser_)
4133 return true;
4134
4135 if ((!normal_downloads_are_present && !profile()->IsOffTheRecord()) ||
4136 (!incognito_downloads_are_present && profile()->IsOffTheRecord()))
[email protected]69444cc2009-04-09 20:40:064137 return true;
4138
4139 // Let's figure out if we are the last window for our profile.
4140 // Note that we cannot just use BrowserList::GetBrowserCount as browser
4141 // windows closing is delayed and the returned count might include windows
4142 // that are being closed.
[email protected]446295a2010-04-19 23:43:004143 // The browser allowed to be closed only if:
4144 // 1. It is a regular browser and there are no regular downloads present or
4145 // this is not the last regular browser window.
4146 // 2. It is an incognito browser and there are no incognito downloads present
4147 // or this is not the last incognito browser window.
[email protected]69444cc2009-04-09 20:40:064148 int count = 0;
4149 for (BrowserList::const_iterator iter = BrowserList::begin();
4150 iter != BrowserList::end(); ++iter) {
4151 // Don't count this browser window or any other in the process of closing.
[email protected]460a2942010-12-15 19:43:154152 // Only consider normal browser windows, not popups.
4153 Browser* const browser = *iter;
4154 if (browser == this
4155 || browser->is_attempting_to_close_browser_
4156 || browser->type() != Browser::TYPE_NORMAL)
[email protected]69444cc2009-04-09 20:40:064157 continue;
4158
[email protected]446295a2010-04-19 23:43:004159 // Verify that this is not the last non-incognito or incognito browser,
4160 // depending on the pending downloads.
4161 if (normal_downloads_are_present && !profile()->IsOffTheRecord() &&
[email protected]460a2942010-12-15 19:43:154162 browser->profile()->IsOffTheRecord())
[email protected]446295a2010-04-19 23:43:004163 continue;
4164 if (incognito_downloads_are_present && profile()->IsOffTheRecord() &&
[email protected]460a2942010-12-15 19:43:154165 !browser->profile()->IsOffTheRecord())
[email protected]446295a2010-04-19 23:43:004166 continue;
4167
[email protected]69444cc2009-04-09 20:40:064168 // We test the original profile, because an incognito browser window keeps
4169 // the original profile alive (and its DownloadManager).
4170 // We also need to test explicitly the profile directly so that 2 incognito
4171 // profiles count as a match.
4172 if ((*iter)->profile() == profile() ||
4173 (*iter)->profile()->GetOriginalProfile() == profile())
4174 count++;
4175 }
4176 if (count > 0)
4177 return true;
4178
4179 cancel_download_confirmation_state_ = WAITING_FOR_RESPONSE;
4180 window_->ConfirmBrowserCloseWithPendingDownloads();
4181
4182 // Return false so the browser does not close. We'll close if the user
4183 // confirms in the dialog.
4184 return false;
4185}
4186
4187///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:574188// Browser, Assorted utility functions (private):
initial.commit09911bf2008-07-26 23:55:294189
[email protected]1a6b30a2009-08-19 03:52:114190// static
[email protected]de4e7632010-09-01 06:24:044191Browser* Browser::GetTabbedBrowser(Profile* profile, bool match_incognito) {
4192 return BrowserList::FindBrowserWithType(profile, TYPE_NORMAL,
4193 match_incognito);
4194}
4195
4196// static
[email protected]1a6b30a2009-08-19 03:52:114197Browser* Browser::GetOrCreateTabbedBrowser(Profile* profile) {
[email protected]de4e7632010-09-01 06:24:044198 Browser* browser = GetTabbedBrowser(profile, false);
[email protected]15952e462008-11-14 00:29:054199 if (!browser)
[email protected]1a6b30a2009-08-19 03:52:114200 browser = Browser::Create(profile);
initial.commit09911bf2008-07-26 23:55:294201 return browser;
4202}
4203
[email protected]9219d262011-02-15 21:05:124204void Browser::SetAsDelegate(TabContentsWrapper* tab, Browser* delegate) {
4205 tab->tab_contents()->set_delegate(delegate);
4206 tab->set_delegate(delegate);
4207 tab->search_engine_tab_helper()->set_delegate(delegate);
4208}
4209
[email protected]4f3dc372009-02-24 00:10:294210void Browser::FindInPage(bool find_next, bool forward_direction) {
[email protected]4801ecc2009-04-05 04:52:584211 ShowFindBar();
[email protected]4f3dc372009-02-24 00:10:294212 if (find_next) {
[email protected]6a4f5af22009-09-23 22:43:004213 string16 find_text;
4214#if defined(OS_MACOSX)
4215 // We always want to search for the contents of the find pasteboard on OS X.
4216 find_text = GetFindPboardText();
4217#endif
[email protected]9c318862011-02-01 22:27:244218 GetSelectedTabContentsWrapper()->
[email protected]c90c6ca2011-02-16 20:11:384219 find_tab_helper()->StartFinding(find_text,
4220 forward_direction,
4221 false); // Not case sensitive.
[email protected]4f3dc372009-02-24 00:10:294222 }
[email protected]fbd77592008-11-12 20:50:274223}
[email protected]cb17f7f2009-02-06 18:14:484224
[email protected]36b6dcb2008-11-12 01:19:574225void Browser::CloseFrame() {
4226 window_->Close();
initial.commit09911bf2008-07-26 23:55:294227}
4228
[email protected]3c9e1872010-11-18 16:17:494229void Browser::TabDetachedAtImpl(TabContentsWrapper* contents, int index,
[email protected]c37e3b62010-01-22 00:15:174230 DetachType type) {
4231 if (type == DETACH_TYPE_DETACH) {
[email protected]56580852010-11-17 16:09:154232 // Save the current location bar state, but only if the tab being detached
4233 // is the selected tab. Because saving state can conditionally revert the
4234 // location bar, saving the current tab's location bar state to a
4235 // non-selected tab can corrupt both tabs.
[email protected]9800de5e2011-03-11 18:19:494236 if (contents == GetSelectedTabContentsWrapper()) {
4237 LocationBar* location_bar = window()->GetLocationBar();
4238 if (location_bar)
4239 location_bar->SaveStateToContents(contents->tab_contents());
4240 }
[email protected]c37e3b62010-01-22 00:15:174241
[email protected]ecc523f62010-09-28 22:45:404242 if (!tab_handler_->GetTabStripModel()->closing_all())
[email protected]c37e3b62010-01-22 00:15:174243 SyncHistoryWithTabs(0);
4244 }
4245
[email protected]9219d262011-02-15 21:05:124246 SetAsDelegate(contents, NULL);
[email protected]3c9e1872010-11-18 16:17:494247 RemoveScheduledUpdatesFor(contents->tab_contents());
[email protected]c37e3b62010-01-22 00:15:174248
[email protected]ecc523f62010-09-28 22:45:404249 if (find_bar_controller_.get() &&
4250 index == tab_handler_->GetTabStripModel()->selected_index()) {
[email protected]c37e3b62010-01-22 00:15:174251 find_bar_controller_->ChangeTabContents(NULL);
[email protected]ecc523f62010-09-28 22:45:404252 }
[email protected]c37e3b62010-01-22 00:15:174253
[email protected]08f0d612011-01-13 23:58:214254 if (is_attempting_to_close_browser_) {
4255 // If this is the last tab with unload handlers, then ProcessPendingTabs
4256 // would call back into the TabStripModel (which is invoking this method on
4257 // us). Avoid that by passing in false so that the call to
4258 // ProcessPendingTabs is delayed.
4259 ClearUnloadState(contents->tab_contents(), false);
4260 }
4261
[email protected]c37e3b62010-01-22 00:15:174262 registrar_.Remove(this, NotificationType::TAB_CONTENTS_DISCONNECTED,
[email protected]3c9e1872010-11-18 16:17:494263 Source<TabContentsWrapper>(contents));
[email protected]c37e3b62010-01-22 00:15:174264}
4265
initial.commit09911bf2008-07-26 23:55:294266// static
[email protected]f87919d72011-02-02 18:46:164267void Browser::RegisterAppPrefs(const std::string& app_name, Profile* profile) {
initial.commit09911bf2008-07-26 23:55:294268 // A set of apps that we've already started.
[email protected]57ecc4b2010-08-11 03:02:514269 static std::set<std::string>* g_app_names = NULL;
initial.commit09911bf2008-07-26 23:55:294270
4271 if (!g_app_names)
[email protected]57ecc4b2010-08-11 03:02:514272 g_app_names = new std::set<std::string>;
initial.commit09911bf2008-07-26 23:55:294273
4274 // Only register once for each app name.
4275 if (g_app_names->find(app_name) != g_app_names->end())
4276 return;
4277 g_app_names->insert(app_name);
4278
4279 // We need to register the window position pref.
[email protected]57ecc4b2010-08-11 03:02:514280 std::string window_pref(prefs::kBrowserWindowPlacement);
4281 window_pref.append("_");
initial.commit09911bf2008-07-26 23:55:294282 window_pref.append(app_name);
[email protected]f87919d72011-02-02 18:46:164283 profile->GetPrefs()->RegisterDictionaryPref(window_pref.c_str());
initial.commit09911bf2008-07-26 23:55:294284}
[email protected]5c238752009-06-13 10:29:074285
[email protected]281918912010-05-27 22:05:134286void Browser::TabRestoreServiceChanged(TabRestoreService* service) {
4287 command_updater_.UpdateCommandEnabled(IDC_RESTORE_TAB,
4288 !service->entries().empty());
4289}
4290
4291void Browser::TabRestoreServiceDestroyed(TabRestoreService* service) {
4292 if (!tab_restore_service_)
4293 return;
4294
4295 DCHECK_EQ(tab_restore_service_, service);
4296 tab_restore_service_->RemoveObserver(this);
4297 tab_restore_service_ = NULL;
4298}
[email protected]97b6c4f2010-09-27 19:31:264299
[email protected]3c9e1872010-11-18 16:17:494300// Centralized method for creating a TabContents, configuring and installing
4301// all its supporting objects and observers.
4302TabContentsWrapper* Browser::TabContentsFactory(
4303 Profile* profile,
4304 SiteInstance* site_instance,
4305 int routing_id,
4306 const TabContents* base_tab_contents,
4307 SessionStorageNamespace* session_storage_namespace) {
4308 TabContents* new_contents = new TabContents(profile, site_instance,
4309 routing_id, base_tab_contents,
4310 session_storage_namespace);
4311 TabContentsWrapper* wrapper = new TabContentsWrapper(new_contents);
4312 return wrapper;
4313}
4314
[email protected]6b723f82010-10-05 20:14:274315bool Browser::OpenInstant(WindowOpenDisposition disposition) {
[email protected]35242602011-01-06 16:38:534316 if (!instant() || !instant()->is_active() || !instant()->IsCurrent() ||
4317 disposition == NEW_BACKGROUND_TAB) {
4318 // NEW_BACKGROUND_TAB results in leaving the omnibox open, so we don't
4319 // attempt to use the instant preview.
[email protected]97b6c4f2010-09-27 19:31:264320 return false;
[email protected]35242602011-01-06 16:38:534321 }
[email protected]97b6c4f2010-09-27 19:31:264322
4323 if (disposition == CURRENT_TAB) {
[email protected]6b723f82010-10-05 20:14:274324 instant()->CommitCurrentPreview(INSTANT_COMMIT_PRESSED_ENTER);
[email protected]97b6c4f2010-09-27 19:31:264325 return true;
4326 }
[email protected]35242602011-01-06 16:38:534327 if (disposition == NEW_FOREGROUND_TAB) {
[email protected]3c9e1872010-11-18 16:17:494328 TabContentsWrapper* preview_contents = instant()->ReleasePreviewContents(
[email protected]6b723f82010-10-05 20:14:274329 INSTANT_COMMIT_PRESSED_ENTER);
[email protected]a0df03c122011-01-05 00:22:554330 // HideInstant is invoked after release so that InstantController is not
4331 // active when HideInstant asks it for its state.
4332 HideInstant();
[email protected]97b6c4f2010-09-27 19:31:264333 preview_contents->controller().PruneAllButActive();
[email protected]ecc523f62010-09-28 22:45:404334 tab_handler_->GetTabStripModel()->AddTabContents(
[email protected]97b6c4f2010-09-27 19:31:264335 preview_contents,
4336 -1,
[email protected]6b723f82010-10-05 20:14:274337 instant()->last_transition_type(),
[email protected]3c2db4f2011-03-11 00:07:184338 TabStripModel::ADD_SELECTED);
[email protected]3c9e1872010-11-18 16:17:494339 instant()->CompleteRelease(preview_contents->tab_contents());
[email protected]97b6c4f2010-09-27 19:31:264340 return true;
4341 }
4342 // The omnibox currently doesn't use other dispositions, so we don't attempt
4343 // to handle them. If you hit this NOTREACHED file a bug and I'll (sky) add
4344 // support for the new disposition.
4345 NOTREACHED();
4346 return false;
4347}
[email protected]2031cf9d2010-10-12 05:05:374348
4349void Browser::CreateInstantIfNecessary() {
[email protected]73de26a2010-10-17 03:23:254350 if (type() == TYPE_NORMAL && InstantController::IsEnabled(profile()) &&
[email protected]2031cf9d2010-10-12 05:05:374351 !profile()->IsOffTheRecord()) {
[email protected]fdf773c52010-11-01 20:58:194352 instant_.reset(new InstantController(profile_, this));
[email protected]5aab5e22010-12-08 22:13:294353 instant_unload_handler_.reset(new InstantUnloadHandler(this));
[email protected]2031cf9d2010-10-12 05:05:374354 }
4355}
[email protected]77d8d622010-12-15 10:30:124356
4357void Browser::ViewSource(TabContentsWrapper* contents) {
[email protected]932b7a12011-03-09 12:50:274358 DCHECK(contents);
4359
4360 NavigationEntry* active_entry = contents->controller().GetActiveEntry();
4361 if (!active_entry)
4362 return;
4363
4364 ViewSource(contents, active_entry->url(), active_entry->content_state());
4365}
4366
4367void Browser::ViewSource(TabContentsWrapper* contents,
4368 const GURL& url,
4369 const std::string& content_state) {
[email protected]77d8d622010-12-15 10:30:124370 UserMetrics::RecordAction(UserMetricsAction("ViewSource"), profile_);
4371 DCHECK(contents);
4372
4373 TabContentsWrapper* view_source_contents = contents->Clone();
4374 view_source_contents->controller().PruneAllButActive();
4375 NavigationEntry* active_entry =
4376 view_source_contents->controller().GetActiveEntry();
[email protected]1788e772010-12-15 16:40:504377 if (!active_entry)
4378 return;
4379
[email protected]932b7a12011-03-09 12:50:274380 GURL view_source_url = GURL(chrome::kViewSourceScheme + std::string(":") +
4381 url.spec());
4382 active_entry->set_virtual_url(view_source_url);
[email protected]1436beff2010-12-16 19:47:044383
[email protected]932b7a12011-03-09 12:50:274384 // Do not restore scroller position.
4385 active_entry->set_content_state(
4386 webkit_glue::RemoveScrollOffsetFromHistoryState(content_state));
4387
[email protected]cd3d50d2010-12-18 21:03:294388 // Do not restore title, derive it from the url.
4389 active_entry->set_title(string16());
[email protected]77d8d622010-12-15 10:30:124390
[email protected]47b309f2010-12-28 17:35:564391 // Now show view-source entry.
[email protected]77d8d622010-12-15 10:30:124392 if (CanSupportWindowFeature(FEATURE_TABSTRIP)) {
4393 // If this is a tabbed browser, just create a duplicate tab inside the same
4394 // window next to the tab being duplicated.
4395 int index = tab_handler_->GetTabStripModel()->
4396 GetIndexOfTabContents(contents);
[email protected]77d8d622010-12-15 10:30:124397 int add_types = TabStripModel::ADD_SELECTED |
[email protected]47b309f2010-12-28 17:35:564398 TabStripModel::ADD_INHERIT_GROUP;
[email protected]77d8d622010-12-15 10:30:124399 tab_handler_->GetTabStripModel()->InsertTabContentsAt(index + 1,
[email protected]47b309f2010-12-28 17:35:564400 view_source_contents,
[email protected]77d8d622010-12-15 10:30:124401 add_types);
4402 } else {
[email protected]47b309f2010-12-28 17:35:564403 Browser* browser = Browser::CreateForType(TYPE_NORMAL, profile_);
[email protected]77d8d622010-12-15 10:30:124404
4405 // Preserve the size of the original window. The new window has already
4406 // been given an offset by the OS, so we shouldn't copy the old bounds.
4407 BrowserWindow* new_window = browser->window();
4408 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
4409 window()->GetRestoredBounds().size()));
4410
4411 // We need to show the browser now. Otherwise ContainerWin assumes the
4412 // TabContents is invisible and won't size it.
4413 browser->window()->Show();
4414
4415 // The page transition below is only for the purpose of inserting the tab.
[email protected]47b309f2010-12-28 17:35:564416 browser->AddTab(view_source_contents, PageTransition::LINK);
[email protected]77d8d622010-12-15 10:30:124417 }
4418
4419 if (profile_->HasSessionService()) {
4420 SessionService* session_service = profile_->GetSessionService();
4421 if (session_service)
[email protected]47b309f2010-12-28 17:35:564422 session_service->TabRestored(&view_source_contents->controller(), false);
[email protected]77d8d622010-12-15 10:30:124423 }
4424}