blob: 43a232c144328242bd6454bce16875c954cc98c0 [file] [log] [blame]
[email protected]4801ecc2009-04-05 04:52:581// Copyright (c) 2006-2009 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]c61db1d2009-02-06 03:39:185#include "chrome/browser/browser.h"
6
[email protected]6289beb2009-06-06 10:04:157#include "app/animation.h"
[email protected]a92b8642009-05-05 23:38:568#include "app/l10n_util.h"
[email protected]8a53ee042009-01-21 16:41:339#include "base/command_line.h"
10#include "base/idle_timer.h"
[email protected]22cdd932009-08-18 02:16:2111#include "base/keyboard_codes.h"
[email protected]8a53ee042009-01-21 16:41:3312#include "base/logging.h"
13#include "base/string_util.h"
[email protected]b689fce72009-03-17 22:45:3414#include "base/thread.h"
[email protected]88d74942009-01-21 22:04:4415#include "chrome/app/chrome_dll_resource.h"
[email protected]a9afddb2009-02-12 17:49:4216#include "chrome/browser/bookmarks/bookmark_model.h"
[email protected]8a53ee042009-01-21 16:41:3317#include "chrome/browser/browser_list.h"
[email protected]5c238752009-06-13 10:29:0718#include "chrome/browser/browser_process.h"
[email protected]c61db1d2009-02-06 03:39:1819#include "chrome/browser/browser_shutdown.h"
[email protected]c98fe6f2009-02-25 20:33:2320#include "chrome/browser/browser_window.h"
[email protected]40d59ce52009-03-06 23:20:1421#include "chrome/browser/character_encoding.h"
[email protected]40ecc902009-03-16 13:42:4722#include "chrome/browser/debugger/devtools_manager.h"
[email protected]59560e0b2009-06-04 03:30:2223#include "chrome/browser/download/download_item_model.h"
[email protected]69444cc2009-04-09 20:40:0624#include "chrome/browser/download/download_manager.h"
[email protected]59560e0b2009-06-04 03:30:2225#include "chrome/browser/download/download_shelf.h"
26#include "chrome/browser/download/download_started_animation.h"
[email protected]371ed7a2009-08-25 15:22:4627#include "chrome/browser/extensions/crashed_extension_infobar.h"
[email protected]0c6da502009-08-14 22:32:3928#include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
[email protected]4801ecc2009-04-05 04:52:5829#include "chrome/browser/find_bar.h"
30#include "chrome/browser/find_bar_controller.h"
[email protected]7745b822009-01-27 20:15:3531#include "chrome/browser/location_bar.h"
[email protected]d938aed92009-01-22 19:49:3332#include "chrome/browser/metrics/user_metrics.h"
[email protected]a239c3f2009-02-17 22:13:1933#include "chrome/browser/net/url_fixer_upper.h"
[email protected]0e3e3e32009-05-14 01:00:5334#include "chrome/browser/options_window.h"
[email protected]f7011fcb2009-01-28 21:54:3235#include "chrome/browser/profile.h"
[email protected]14e60c8d2009-06-29 03:56:5136#include "chrome/browser/renderer_host/site_instance.h"
[email protected]85e921fb82009-02-11 23:19:4437#include "chrome/browser/sessions/session_service.h"
[email protected]c61db1d2009-02-06 03:39:1838#include "chrome/browser/sessions/session_types.h"
[email protected]bd580a252009-02-12 01:16:3039#include "chrome/browser/sessions/tab_restore_service.h"
[email protected]abf6c7a2009-03-03 16:24:1040#include "chrome/browser/status_bubble.h"
[email protected]a165a052009-02-18 21:43:0041#include "chrome/browser/tab_contents/interstitial_page.h"
[email protected]c61db1d2009-02-06 03:39:1842#include "chrome/browser/tab_contents/navigation_controller.h"
43#include "chrome/browser/tab_contents/navigation_entry.h"
[email protected]57c6a652009-05-04 07:58:3444#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]81af9392009-04-21 02:37:4545#include "chrome/browser/tab_contents/tab_contents_view.h"
[email protected]4d34e2e2009-05-26 22:55:2846#include "chrome/browser/window_sizer.h"
[email protected]d938aed92009-01-22 19:49:3347#include "chrome/common/chrome_constants.h"
48#include "chrome/common/chrome_switches.h"
[email protected]5b1a0e22009-05-26 19:00:5849#include "chrome/common/extensions/extension.h"
[email protected]bfd04a62009-02-01 18:16:5650#include "chrome/common/notification_service.h"
[email protected]d938aed92009-01-22 19:49:3351#include "chrome/common/page_transition_types.h"
[email protected]59560e0b2009-06-04 03:30:2252#include "chrome/common/platform_util.h"
[email protected]8a53ee042009-01-21 16:41:3353#include "chrome/common/pref_names.h"
54#include "chrome/common/pref_service.h"
[email protected]b689fce72009-03-17 22:45:3455#include "chrome/common/url_constants.h"
[email protected]026e34a2009-02-06 00:06:1256#ifdef CHROME_PERSONALIZATION
[email protected]ca38d8e2009-08-20 18:08:1657#include "chrome/browser/sync/profile_sync_service.h"
[email protected]026e34a2009-02-06 00:06:1258#endif
[email protected]a3e18c42009-03-04 23:36:0559#include "grit/chromium_strings.h"
60#include "grit/generated_resources.h"
61#include "grit/locale_settings.h"
[email protected]8a53ee042009-01-21 16:41:3362#include "net/base/cookie_monster.h"
63#include "net/base/cookie_policy.h"
[email protected]2bfd94d2009-04-29 20:32:0364#include "net/base/mime_util.h"
[email protected]8a53ee042009-01-21 16:41:3365#include "net/base/net_util.h"
66#include "net/base/registry_controlled_domain.h"
67#include "net/url_request/url_request_context.h"
[email protected]d938aed92009-01-22 19:49:3368#include "webkit/glue/window_open_disposition.h"
[email protected]8a53ee042009-01-21 16:41:3369
70#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2971#include <windows.h>
72#include <shellapi.h>
73
[email protected]4a0765a2009-05-08 23:12:2574#include "app/win_util.h"
[email protected]36b6dcb2008-11-12 01:19:5775#include "chrome/browser/automation/ui_controls.h"
initial.commit09911bf2008-07-26 23:55:2976#include "chrome/browser/browser_process.h"
initial.commit09911bf2008-07-26 23:55:2977#include "chrome/browser/browser_url_handler.h"
78#include "chrome/browser/cert_store.h"
[email protected]37936ee2008-09-14 01:09:5079#include "chrome/browser/download/save_package.h"
[email protected]3b073b22009-01-16 03:29:0380#include "chrome/browser/ssl/ssl_error_info.h"
[email protected]36b6dcb2008-11-12 01:19:5781#include "chrome/browser/task_manager.h"
[email protected]f2530062008-12-03 23:52:0382#include "chrome/browser/user_data_manager.h"
initial.commit09911bf2008-07-26 23:55:2983#include "chrome/browser/view_ids.h"
initial.commit09911bf2008-07-26 23:55:2984#include "chrome/browser/views/location_bar_view.h"
[email protected]6dffde322009-02-18 03:47:4885#include "chrome/common/child_process_host.h"
[email protected]8a53ee042009-01-21 16:41:3386#endif // OS_WIN
[email protected]e1acf6f2008-10-27 20:43:3387
[email protected]33e5f442009-05-28 03:30:2788#if !defined(OS_MACOSX)
[email protected]7d3feb912009-05-15 20:37:4289#include "chrome/browser/dock_info.h"
90#endif
91
[email protected]8a53ee042009-01-21 16:41:3392using base::TimeDelta;
initial.commit09911bf2008-07-26 23:55:2993
94// How long we wait before updating the browser chrome while loading a page.
95static const int kUIUpdateCoalescingTimeMS = 200;
96
97// Idle time before helping prune memory consumption.
98static const int kBrowserReleaseMemoryInterval = 30; // In seconds.
99
[email protected]36b6dcb2008-11-12 01:19:57100///////////////////////////////////////////////////////////////////////////////
initial.commit09911bf2008-07-26 23:55:29101
[email protected]a436d922009-02-13 23:16:42102// A task to reduce the working set of the child processes that live on the IO
103// thread (i.e. plugins, workers).
104class ReduceChildProcessesWorkingSetTask : public Task {
initial.commit09911bf2008-07-26 23:55:29105 public:
106 virtual void Run() {
[email protected]8a53ee042009-01-21 16:41:33107#if defined(OS_WIN)
[email protected]6dffde322009-02-18 03:47:48108 for (ChildProcessHost::Iterator iter; !iter.Done(); ++iter)
109 iter->ReduceWorkingSet();
[email protected]8a53ee042009-01-21 16:41:33110#endif
initial.commit09911bf2008-07-26 23:55:29111 }
112};
113
114// A browser task to run when the user is not using the browser.
115// In our case, we're trying to be nice to the operating system and release
116// memory not in use.
[email protected]aeab57ea2008-08-28 20:50:12117class BrowserIdleTimer : public base::IdleTimer {
initial.commit09911bf2008-07-26 23:55:29118 public:
[email protected]aeab57ea2008-08-28 20:50:12119 BrowserIdleTimer()
120 : base::IdleTimer(TimeDelta::FromSeconds(kBrowserReleaseMemoryInterval),
121 false) {
initial.commit09911bf2008-07-26 23:55:29122 }
123
124 virtual void OnIdle() {
[email protected]8a53ee042009-01-21 16:41:33125#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29126 // We're idle. Release browser and renderer unused pages.
127
128 // Handle the Browser.
[email protected]176aa482008-11-14 03:25:15129 base::Process process(GetCurrentProcess());
initial.commit09911bf2008-07-26 23:55:29130 process.ReduceWorkingSet();
131
132 // Handle the Renderer(s).
[email protected]9de09f82009-08-17 20:13:53133 RenderProcessHost::iterator renderer_iter(
134 RenderProcessHost::AllHostsIterator());
135 while (!renderer_iter.IsAtEnd()) {
136 base::Process process = renderer_iter.GetCurrentValue()->process();
137 process.ReduceWorkingSet();
138 renderer_iter.Advance();
initial.commit09911bf2008-07-26 23:55:29139 }
140
[email protected]a436d922009-02-13 23:16:42141 // Handle the child processe. We need to iterate through them on the IO
142 // thread because that thread manages the child process collection.
initial.commit09911bf2008-07-26 23:55:29143 g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
[email protected]a436d922009-02-13 23:16:42144 new ReduceChildProcessesWorkingSetTask());
[email protected]8a53ee042009-01-21 16:41:33145#endif
initial.commit09911bf2008-07-26 23:55:29146 }
147};
148
[email protected]36b6dcb2008-11-12 01:19:57149///////////////////////////////////////////////////////////////////////////////
initial.commit09911bf2008-07-26 23:55:29150
151struct Browser::UIUpdate {
152 UIUpdate(const TabContents* src, unsigned flags)
153 : source(src),
154 changed_flags(flags) {
155 }
156
157 // The source of the update.
158 const TabContents* source;
159
160 // What changed in the UI.
161 unsigned changed_flags;
162};
163
[email protected]505323e22009-01-24 02:47:58164namespace {
165
166// Returns true if the specified TabContents has unload listeners registered.
167bool TabHasUnloadListener(TabContents* contents) {
[email protected]57c6a652009-05-04 07:58:34168 return contents->notify_disconnection() &&
169 !contents->showing_interstitial_page() &&
170 !contents->render_view_host()->SuddenTerminationAllowed();
[email protected]505323e22009-01-24 02:47:58171}
172
173} // namespace
174
[email protected]36b6dcb2008-11-12 01:19:57175///////////////////////////////////////////////////////////////////////////////
176// Browser, Constructors, Creation, Showing:
initial.commit09911bf2008-07-26 23:55:29177
[email protected]299dabd2008-11-19 02:27:16178Browser::Browser(Type type, Profile* profile)
[email protected]15952e462008-11-14 00:29:05179 : type_(type),
180 profile_(profile),
[email protected]f3e99e32008-07-30 04:48:39181 window_(NULL),
initial.commit09911bf2008-07-26 23:55:29182 tabstrip_model_(this, profile),
[email protected]1fc025202009-01-20 23:03:14183 command_updater_(this),
initial.commit09911bf2008-07-26 23:55:29184 toolbar_model_(this),
[email protected]15952e462008-11-14 00:29:05185 chrome_updater_factory_(this),
186 is_attempting_to_close_browser_(false),
[email protected]69444cc2009-04-09 20:40:06187 cancel_download_confirmation_state_(NOT_PROMPTED),
[email protected]2e716622009-03-09 21:11:01188 maximized_state_(MAXIMIZED_STATE_DEFAULT),
[email protected]15952e462008-11-14 00:29:05189 method_factory_(this),
[email protected]ebdcf9742009-01-23 05:25:28190 idle_task_(new BrowserIdleTimer) {
initial.commit09911bf2008-07-26 23:55:29191 tabstrip_model_.AddObserver(this);
192
[email protected]0cb94102009-05-22 19:51:21193 registrar_.Add(this, NotificationType::SSL_VISIBLE_STATE_CHANGED,
194 NotificationService::AllSources());
[email protected]0c6da502009-08-14 22:32:39195 registrar_.Add(this, NotificationType::EXTENSION_UPDATE_DISABLED,
196 NotificationService::AllSources());
[email protected]0cb94102009-05-22 19:51:21197 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
198 NotificationService::AllSources());
[email protected]371ed7a2009-08-25 15:22:46199 registrar_.Add(this, NotificationType::EXTENSION_PROCESS_CRASHED,
200 NotificationService::AllSources());
[email protected]e001d412009-06-26 20:53:25201 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
202 NotificationService::AllSources());
initial.commit09911bf2008-07-26 23:55:29203
initial.commit09911bf2008-07-26 23:55:29204 InitCommandState();
205 BrowserList::AddBrowser(this);
206
207 encoding_auto_detect_.Init(prefs::kWebKitUsesUniversalDetector,
208 profile_->GetPrefs(), NULL);
209
210 // Trim browser memory on idle for low & medium memory models.
211 if (g_browser_process->memory_model() < BrowserProcess::HIGH_MEMORY_MODEL)
212 idle_task_->Start();
initial.commit09911bf2008-07-26 23:55:29213}
214
215Browser::~Browser() {
216 // The tab strip should be empty at this point.
217 DCHECK(tabstrip_model_.empty());
218 tabstrip_model_.RemoveObserver(this);
219
220 BrowserList::RemoveBrowser(this);
221
[email protected]fbc947b2009-06-19 13:28:24222#if defined(OS_WIN) || defined(OS_LINUX)
initial.commit09911bf2008-07-26 23:55:29223 if (!BrowserList::HasBrowserWithProfile(profile_)) {
224 // We're the last browser window with this profile. We need to nuke the
225 // TabRestoreService, which will start the shutdown of the
226 // NavigationControllers and allow for proper shutdown. If we don't do this
227 // chrome won't shutdown cleanly, and may end up crashing when some
228 // thread tries to use the IO thread (or another thread) that is no longer
229 // valid.
[email protected]fbc947b2009-06-19 13:28:24230 // This isn't a valid assumption for Mac OS, as it stays running after
231 // the last browser has closed. The Mac equivalent is in its app
232 // controller.
initial.commit09911bf2008-07-26 23:55:29233 profile_->ResetTabRestoreService();
234 }
[email protected]fbc947b2009-06-19 13:28:24235#endif
initial.commit09911bf2008-07-26 23:55:29236
237 SessionService* session_service = profile_->GetSessionService();
238 if (session_service)
239 session_service->WindowClosed(session_id_);
240
[email protected]d8375fd2008-11-25 22:45:39241 TabRestoreService* tab_restore_service = profile()->GetTabRestoreService();
242 if (tab_restore_service)
243 tab_restore_service->BrowserClosed(this);
244
initial.commit09911bf2008-07-26 23:55:29245 if (profile_->IsOffTheRecord() &&
246 !BrowserList::IsOffTheRecordSessionActive()) {
[email protected]860f55492009-03-27 19:50:59247 // An off-the-record profile is no longer needed, this indirectly
248 // frees its cache and cookies.
249 profile_->GetOriginalProfile()->DestroyOffTheRecordProfile();
initial.commit09911bf2008-07-26 23:55:29250 }
251
252 // There may be pending file dialogs, we need to tell them that we've gone
253 // away so they don't try and call back to us.
254 if (select_file_dialog_.get())
255 select_file_dialog_->ListenerDestroyed();
256}
257
[email protected]15952e462008-11-14 00:29:05258// static
259Browser* Browser::Create(Profile* profile) {
[email protected]299dabd2008-11-19 02:27:16260 Browser* browser = new Browser(TYPE_NORMAL, profile);
[email protected]15952e462008-11-14 00:29:05261 browser->CreateBrowserWindow();
262 return browser;
263}
[email protected]6104acf2008-11-11 22:27:34264
[email protected]15952e462008-11-14 00:29:05265// static
266Browser* Browser::CreateForPopup(Profile* profile) {
[email protected]299dabd2008-11-19 02:27:16267 Browser* browser = new Browser(TYPE_POPUP, profile);
[email protected]15952e462008-11-14 00:29:05268 browser->CreateBrowserWindow();
269 return browser;
270}
271
272// static
273Browser* Browser::CreateForApp(const std::wstring& app_name,
[email protected]d5fbc002009-02-27 22:12:58274 Profile* profile, bool is_popup) {
275 Browser* browser = new Browser(is_popup? TYPE_APP_POPUP : TYPE_APP, profile);
[email protected]15952e462008-11-14 00:29:05276 browser->app_name_ = app_name;
277 browser->CreateBrowserWindow();
278 return browser;
279}
280
281void Browser::CreateBrowserWindow() {
282 DCHECK(!window_);
[email protected]9c45b7182009-08-04 16:44:43283
284 if (SupportsWindowFeature(FEATURE_EXTENSIONSHELF))
285 extension_shelf_model_.reset(new ExtensionShelfModel(this));
286
[email protected]15952e462008-11-14 00:29:05287 window_ = BrowserWindow::CreateBrowserWindow(this);
288
289 // Show the First Run information bubble if we've been told to.
290 PrefService* local_state = g_browser_process->local_state();
[email protected]be3877f2009-01-14 15:51:10291 if (!local_state)
292 return;
[email protected]15952e462008-11-14 00:29:05293 if (local_state->IsPrefRegistered(prefs::kShouldShowFirstRunBubble) &&
294 local_state->GetBoolean(prefs::kShouldShowFirstRunBubble)) {
[email protected]b1390d02009-05-19 23:50:37295 bool show_OEM_bubble = (local_state->
296 IsPrefRegistered(prefs::kShouldUseOEMFirstRunBubble) &&
297 local_state->GetBoolean(prefs::kShouldUseOEMFirstRunBubble));
[email protected]15952e462008-11-14 00:29:05298 // Reset the preference so we don't show the bubble for subsequent windows.
299 local_state->ClearPref(prefs::kShouldShowFirstRunBubble);
[email protected]b1390d02009-05-19 23:50:37300 window_->GetLocationBar()->ShowFirstRunBubble(show_OEM_bubble);
initial.commit09911bf2008-07-26 23:55:29301 }
[email protected]4801ecc2009-04-05 04:52:58302
[email protected]d87301172009-05-31 04:28:18303#if !(defined(OS_LINUX) && defined(TOOLKIT_VIEWS))
[email protected]4801ecc2009-04-05 04:52:58304 FindBar* find_bar = BrowserWindow::CreateFindBar(this);
305 find_bar_controller_.reset(new FindBarController(find_bar));
306 find_bar->SetFindBarController(find_bar_controller_.get());
[email protected]21230ca2009-05-30 08:27:29307#endif
initial.commit09911bf2008-07-26 23:55:29308}
309
[email protected]36b6dcb2008-11-12 01:19:57310///////////////////////////////////////////////////////////////////////////////
[email protected]5c238752009-06-13 10:29:07311// Getters & Setters
312
313const std::vector<std::wstring>& Browser::user_data_dir_profiles() const {
314 return g_browser_process->user_data_dir_profiles();
315}
316
317void Browser::set_user_data_dir_profiles(
318 const std::vector<std::wstring>& profiles) {
319 g_browser_process->user_data_dir_profiles() = profiles;
320}
321
322///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:57323// Browser, Creation Helpers:
324
325// static
[email protected]15952e462008-11-14 00:29:05326void Browser::OpenEmptyWindow(Profile* profile) {
327 Browser* browser = Browser::Create(profile);
[email protected]36b6dcb2008-11-12 01:19:57328 browser->AddBlankTab(true);
[email protected]15952e462008-11-14 00:29:05329 browser->window()->Show();
initial.commit09911bf2008-07-26 23:55:29330}
331
[email protected]36b6dcb2008-11-12 01:19:57332// static
[email protected]fbc947b2009-06-19 13:28:24333void Browser::OpenWindowWithRestoredTabs(Profile* profile) {
334 TabRestoreService* service = profile->GetTabRestoreService();
335 if (service)
336 service->RestoreMostRecentEntry(NULL);
337}
338
339// static
[email protected]36b6dcb2008-11-12 01:19:57340void Browser::OpenURLOffTheRecord(Profile* profile, const GURL& url) {
341 Profile* off_the_record_profile = profile->GetOffTheRecordProfile();
342 Browser* browser = BrowserList::FindBrowserWithType(
[email protected]15952e462008-11-14 00:29:05343 off_the_record_profile,
[email protected]299dabd2008-11-19 02:27:16344 TYPE_NORMAL);
[email protected]15952e462008-11-14 00:29:05345 if (!browser)
346 browser = Browser::Create(off_the_record_profile);
[email protected]36b6dcb2008-11-12 01:19:57347 // TODO(eroman): should we have referrer here?
[email protected]5a4940be2009-05-06 06:44:39348 browser->AddTabWithURL(url, GURL(), PageTransition::LINK, true, -1, false,
349 NULL);
[email protected]15952e462008-11-14 00:29:05350 browser->window()->Show();
[email protected]2baf83d2008-07-30 05:58:17351}
352
[email protected]36b6dcb2008-11-12 01:19:57353// static
[email protected]0303f31c2009-02-02 06:42:05354void Browser::OpenApplicationWindow(Profile* profile, const GURL& url) {
355 std::wstring app_name = ComputeApplicationNameFromURL(url);
[email protected]36b6dcb2008-11-12 01:19:57356 RegisterAppPrefs(app_name);
[email protected]15952e462008-11-14 00:29:05357
[email protected]d5fbc002009-02-27 22:12:58358 Browser* browser = Browser::CreateForApp(app_name, profile, false);
[email protected]22735af62009-04-07 21:09:58359 browser->AddTabWithURL(url, GURL(), PageTransition::START_PAGE, true, -1,
[email protected]5a4940be2009-05-06 06:44:39360 false, NULL);
[email protected]840b1512009-07-21 16:53:46361
[email protected]3df2aaf2009-07-25 00:24:57362#if defined(OS_WIN)
363 // Set the app user model id for this application to that of the application
364 // name. See http://crbug.com/7028.
365 win_util::SetAppIdForWindow(app_name, browser->window()->GetNativeHandle());
366#endif
367
[email protected]840b1512009-07-21 16:53:46368 TabContents* tab_contents = browser->GetSelectedTabContents();
369 tab_contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
370 tab_contents->render_view_host()->SyncRendererPrefs();
[email protected]15952e462008-11-14 00:29:05371 browser->window()->Show();
[email protected]68f009f2009-02-26 19:43:35372 // TODO(jcampan): http://crbug.com/8123 we should not need to set the initial
373 // focus explicitly.
[email protected]840b1512009-07-21 16:53:46374 tab_contents->view()->SetInitialFocus();
[email protected]d6a3c772009-01-27 19:41:20375}
initial.commit09911bf2008-07-26 23:55:29376
[email protected]36b6dcb2008-11-12 01:19:57377///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:57378// Browser, State Storage and Retrieval for UI:
379
[email protected]bc9a5152008-11-15 00:32:04380std::wstring Browser::GetWindowPlacementKey() const {
[email protected]36b6dcb2008-11-12 01:19:57381 std::wstring name(prefs::kBrowserWindowPlacement);
382 if (!app_name_.empty()) {
383 name.append(L"_");
384 name.append(app_name_);
385 }
[email protected]bc9a5152008-11-15 00:32:04386 return name;
387}
[email protected]36b6dcb2008-11-12 01:19:57388
[email protected]bc9a5152008-11-15 00:32:04389bool Browser::ShouldSaveWindowPlacement() const {
390 // We don't save window position for popups.
[email protected]d5fbc002009-02-27 22:12:58391 return (type() & TYPE_POPUP) == 0;
[email protected]bc9a5152008-11-15 00:32:04392}
[email protected]36b6dcb2008-11-12 01:19:57393
[email protected]bc9a5152008-11-15 00:32:04394void Browser::SaveWindowPlacement(const gfx::Rect& bounds, bool maximized) {
395 // Save to the session storage service, used when reloading a past session.
396 // Note that we don't want to be the ones who cause lazy initialization of
397 // the session service. This function gets called during initial window
398 // showing, and we don't want to bring in the session service this early.
[email protected]36b6dcb2008-11-12 01:19:57399 if (profile()->HasSessionService()) {
400 SessionService* session_service = profile()->GetSessionService();
401 if (session_service)
402 session_service->SetWindowBounds(session_id_, bounds, maximized);
403 }
404}
405
[email protected]15952e462008-11-14 00:29:05406gfx::Rect Browser::GetSavedWindowBounds() const {
[email protected]bb975362009-01-21 01:00:22407 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
[email protected]15952e462008-11-14 00:29:05408 bool record_mode = parsed_command_line.HasSwitch(switches::kRecordMode);
409 bool playback_mode = parsed_command_line.HasSwitch(switches::kPlaybackMode);
410 if (record_mode || playback_mode) {
411 // In playback/record mode we always fix the size of the browser and
412 // move it to (0,0). The reason for this is two reasons: First we want
413 // resize/moves in the playback to still work, and Second we want
414 // playbacks to work (as much as possible) on machines w/ different
415 // screen sizes.
416 return gfx::Rect(0, 0, 800, 600);
417 }
418
419 gfx::Rect restored_bounds = override_bounds_;
420 bool maximized;
[email protected]6dfed102009-04-28 03:09:53421 WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, NULL,
[email protected]15952e462008-11-14 00:29:05422 &restored_bounds, &maximized);
423 return restored_bounds;
424}
425
426// TODO(beng): obtain maximized state some other way so we don't need to go
427// through all this hassle.
428bool Browser::GetSavedMaximizedState() const {
[email protected]bb975362009-01-21 01:00:22429 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kStartMaximized))
[email protected]15952e462008-11-14 00:29:05430 return true;
431
[email protected]2e716622009-03-09 21:11:01432 if (maximized_state_ == MAXIMIZED_STATE_MAXIMIZED)
433 return true;
434 if (maximized_state_ == MAXIMIZED_STATE_UNMAXIMIZED)
435 return false;
436
437 // An explicit maximized state was not set. Query the window sizer.
[email protected]15952e462008-11-14 00:29:05438 gfx::Rect restored_bounds;
[email protected]2e716622009-03-09 21:11:01439 bool maximized = false;
[email protected]6dfed102009-04-28 03:09:53440 WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, NULL,
[email protected]15952e462008-11-14 00:29:05441 &restored_bounds, &maximized);
442 return maximized;
[email protected]36b6dcb2008-11-12 01:19:57443}
444
445SkBitmap Browser::GetCurrentPageIcon() const {
[email protected]ce5348a82008-12-18 18:36:23446 TabContents* contents = GetSelectedTabContents();
447 // |contents| can be NULL since GetCurrentPageIcon() is called by the window
448 // during the window's creation (before tabs have been added).
449 return contents ? contents->GetFavIcon() : SkBitmap();
[email protected]36b6dcb2008-11-12 01:19:57450}
451
[email protected]731f8a42009-07-20 22:07:32452string16 Browser::GetWindowTitleForCurrentTab() const {
[email protected]36b6dcb2008-11-12 01:19:57453 TabContents* contents = tabstrip_model_.GetSelectedTabContents();
[email protected]dda5dfa32009-07-10 00:33:29454 string16 title;
[email protected]c7c42332008-11-15 01:10:54455
[email protected]731f8a42009-07-20 22:07:32456 // |contents| can be NULL because GetWindowTitleForCurrentTab is called by the
457 // window during the window's creation (before tabs have been added).
[email protected]36b6dcb2008-11-12 01:19:57458 if (contents) {
[email protected]dda5dfa32009-07-10 00:33:29459 title = contents->GetTitle();
[email protected]36b6dcb2008-11-12 01:19:57460 FormatTitleForDisplay(&title);
461 }
462 if (title.empty())
[email protected]dda5dfa32009-07-10 00:33:29463 title = l10n_util::GetStringUTF16(IDS_TAB_UNTITLED_TITLE);
[email protected]36b6dcb2008-11-12 01:19:57464
[email protected]16779842009-07-08 23:45:29465#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
[email protected]d904bc82009-07-07 00:41:04466 // On Mac, we don't want to suffix the page title with the application name.
467 return title;
468#elif defined(OS_WIN) || defined(OS_LINUX)
[email protected]edb5e6a2009-04-08 23:46:17469 int string_id = IDS_BROWSER_WINDOW_TITLE_FORMAT;
470 // Don't append the app name to window titles when we're not displaying a
471 // distributor logo for the frame.
472 if (!ShouldShowDistributorLogo())
473 string_id = IDS_BROWSER_WINDOW_TITLE_FORMAT_NO_LOGO;
[email protected]dda5dfa32009-07-10 00:33:29474 return l10n_util::GetStringFUTF16(string_id, title);
[email protected]57e68dba2009-05-15 21:30:50475#endif
[email protected]36b6dcb2008-11-12 01:19:57476}
477
478// static
[email protected]dda5dfa32009-07-10 00:33:29479void Browser::FormatTitleForDisplay(string16* title) {
[email protected]36b6dcb2008-11-12 01:19:57480 size_t current_index = 0;
481 size_t match_index;
482 while ((match_index = title->find(L'\n', current_index)) !=
483 std::wstring::npos) {
[email protected]dda5dfa32009-07-10 00:33:29484 title->replace(match_index, 1, EmptyString16());
[email protected]36b6dcb2008-11-12 01:19:57485 current_index = match_index;
486 }
487}
488
[email protected]edb5e6a2009-04-08 23:46:17489bool Browser::ShouldShowDistributorLogo() const {
490 // Don't show the distributor logo on app frames and app popups.
491 return !(type_ & TYPE_APP);
492}
[email protected]c61db1d2009-02-06 03:39:18493
[email protected]36b6dcb2008-11-12 01:19:57494///////////////////////////////////////////////////////////////////////////////
495// Browser, OnBeforeUnload handling:
496
497bool Browser::ShouldCloseWindow() {
[email protected]69444cc2009-04-09 20:40:06498 if (!CanCloseWithInProgressDownloads())
499 return false;
500
501 if (HasCompletedUnloadProcessing())
[email protected]36b6dcb2008-11-12 01:19:57502 return true;
[email protected]69444cc2009-04-09 20:40:06503
[email protected]36b6dcb2008-11-12 01:19:57504 is_attempting_to_close_browser_ = true;
505
506 for (int i = 0; i < tab_count(); ++i) {
[email protected]505323e22009-01-24 02:47:58507 TabContents* contents = GetTabContentsAt(i);
508 if (TabHasUnloadListener(contents))
509 tabs_needing_before_unload_fired_.insert(contents);
[email protected]36b6dcb2008-11-12 01:19:57510 }
511
512 if (tabs_needing_before_unload_fired_.empty())
513 return true;
514
515 ProcessPendingTabs();
516 return false;
517}
518
519void Browser::OnWindowClosing() {
520 if (!ShouldCloseWindow())
521 return;
522
[email protected]a239c3f2009-02-17 22:13:19523#if defined(OS_WIN) || defined(OS_LINUX)
524 // We don't want to do this on Mac since closing all windows isn't a sign
525 // that the app is shutting down.
[email protected]36b6dcb2008-11-12 01:19:57526 if (BrowserList::size() == 1)
527 browser_shutdown::OnShutdownStarting(browser_shutdown::WINDOW_CLOSE);
[email protected]a239c3f2009-02-17 22:13:19528#endif
[email protected]36b6dcb2008-11-12 01:19:57529
530 // Don't use HasSessionService here, we want to force creation of the
531 // session service so that user can restore what was open.
532 SessionService* session_service = profile()->GetSessionService();
533 if (session_service)
534 session_service->WindowClosing(session_id());
535
[email protected]d8375fd2008-11-25 22:45:39536 TabRestoreService* tab_restore_service = profile()->GetTabRestoreService();
537 if (tab_restore_service)
538 tab_restore_service->BrowserClosing(this);
539
[email protected]36b6dcb2008-11-12 01:19:57540 CloseAllTabs();
541}
542
[email protected]69444cc2009-04-09 20:40:06543////////////////////////////////////////////////////////////////////////////////
544// In-progress download termination handling:
545
546void Browser::InProgressDownloadResponse(bool cancel_downloads) {
547 if (cancel_downloads) {
548 cancel_download_confirmation_state_ = RESPONSE_RECEIVED;
549 CloseWindow();
550 return;
551 }
552
553 // Sets the confirmation state to NOT_PROMPTED so that if the user tries to
554 // close again we'll show the warning again.
555 cancel_download_confirmation_state_ = NOT_PROMPTED;
556
557 // Show the download page so the user can figure-out what downloads are still
558 // in-progress.
559 ShowDownloadsTab();
560}
561
562
563////////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:57564// Browser, Tab adding/showing functions:
565
566TabContents* Browser::AddTabWithURL(
567 const GURL& url, const GURL& referrer, PageTransition::Type transition,
[email protected]5a4940be2009-05-06 06:44:39568 bool foreground, int index, bool force_index,
569 SiteInstance* instance) {
[email protected]22735af62009-04-07 21:09:58570 TabContents* contents = NULL;
571 if (type_ == TYPE_NORMAL || tabstrip_model()->empty()) {
572 GURL url_to_load = url;
573 if (url_to_load.is_empty())
574 url_to_load = GetHomePage();
575 contents = CreateTabContentsForURL(url_to_load, referrer, profile_,
576 transition, false, instance);
[email protected]5a4940be2009-05-06 06:44:39577 tabstrip_model_.AddTabContents(contents, index, force_index,
578 transition, foreground);
[email protected]22735af62009-04-07 21:09:58579 // By default, content believes it is not hidden. When adding contents
580 // in the background, tell it that it's hidden.
581 if (!foreground)
582 contents->WasHidden();
583 } else {
584 // We're in an app window or a popup window. Find an existing browser to
585 // open this URL in, creating one if none exists.
[email protected]1a6b30a2009-08-19 03:52:11586 Browser* b = GetOrCreateTabbedBrowser(profile_);
[email protected]22735af62009-04-07 21:09:58587 contents = b->AddTabWithURL(url, referrer, transition, foreground, index,
[email protected]5a4940be2009-05-06 06:44:39588 force_index, instance);
[email protected]22735af62009-04-07 21:09:58589 b->window()->Show();
[email protected]36b6dcb2008-11-12 01:19:57590 }
[email protected]36b6dcb2008-11-12 01:19:57591 return contents;
592}
593
[email protected]ce3fa3c2009-04-20 19:55:57594// TODO(brettw) this should be just AddTab and it should take a TabContents.
[email protected]36b6dcb2008-11-12 01:19:57595TabContents* Browser::AddTabWithNavigationController(
596 NavigationController* ctrl, PageTransition::Type type) {
[email protected]7f0005a2009-04-15 03:25:11597 TabContents* tc = ctrl->tab_contents();
[email protected]5a4940be2009-05-06 06:44:39598 tabstrip_model_.AddTabContents(tc, -1, false, type, true);
[email protected]36b6dcb2008-11-12 01:19:57599 return tc;
600}
601
[email protected]e0c7c262009-04-23 23:09:43602void Browser::AddTabContents(TabContents* new_contents,
603 WindowOpenDisposition disposition,
604 const gfx::Rect& initial_pos,
605 bool user_gesture) {
606 AddNewContents(NULL, new_contents, disposition, initial_pos, user_gesture);
607}
608
609void Browser::CloseTabContents(TabContents* contents) {
610 CloseContents(contents);
611}
612
613void Browser::BrowserShowHtmlDialog(HtmlDialogUIDelegate* delegate,
[email protected]322f3ff2009-05-22 16:19:54614 gfx::NativeWindow parent_window) {
[email protected]e0c7c262009-04-23 23:09:43615 ShowHtmlDialog(delegate, parent_window);
616}
617
618void Browser::BrowserRenderWidgetShowing() {
619 RenderWidgetShowing();
620}
621
622void Browser::ToolbarSizeChanged(bool is_animating) {
623 ToolbarSizeChanged(NULL, is_animating);
624}
625
[email protected]ce3fa3c2009-04-20 19:55:57626TabContents* Browser::AddRestoredTab(
[email protected]36b6dcb2008-11-12 01:19:57627 const std::vector<TabNavigation>& navigations,
628 int tab_index,
629 int selected_navigation,
[email protected]5c0e6482009-07-14 20:20:09630 bool select,
631 bool pin) {
[email protected]57c6a652009-05-04 07:58:34632 TabContents* new_tab = new TabContents(profile(), NULL,
[email protected]ce3fa3c2009-04-20 19:55:57633 MSG_ROUTING_NONE, NULL);
634 new_tab->controller().RestoreFromState(navigations, selected_navigation);
[email protected]36b6dcb2008-11-12 01:19:57635
[email protected]5c0e6482009-07-14 20:20:09636 bool really_pin =
637 (pin && tab_index == tabstrip_model()->IndexOfFirstNonPinnedTab());
[email protected]ce3fa3c2009-04-20 19:55:57638 tabstrip_model_.InsertTabContentsAt(tab_index, new_tab, select, false);
[email protected]5c0e6482009-07-14 20:20:09639 if (really_pin)
640 tabstrip_model_.SetTabPinned(tab_index, true);
[email protected]77bc6732009-04-20 22:01:03641 if (select)
642 window_->Activate();
[email protected]36b6dcb2008-11-12 01:19:57643 if (profile_->HasSessionService()) {
644 SessionService* session_service = profile_->GetSessionService();
645 if (session_service)
[email protected]5c0e6482009-07-14 20:20:09646 session_service->TabRestored(&new_tab->controller(), really_pin);
[email protected]36b6dcb2008-11-12 01:19:57647 }
[email protected]ce3fa3c2009-04-20 19:55:57648 return new_tab;
[email protected]36b6dcb2008-11-12 01:19:57649}
650
651void Browser::ReplaceRestoredTab(
652 const std::vector<TabNavigation>& navigations,
653 int selected_navigation) {
[email protected]57c6a652009-05-04 07:58:34654 TabContents* replacement = new TabContents(profile(), NULL,
[email protected]ce3fa3c2009-04-20 19:55:57655 MSG_ROUTING_NONE, NULL);
656 replacement->controller().RestoreFromState(navigations, selected_navigation);
[email protected]36b6dcb2008-11-12 01:19:57657
658 tabstrip_model_.ReplaceNavigationControllerAt(
659 tabstrip_model_.selected_index(),
[email protected]ce3fa3c2009-04-20 19:55:57660 &replacement->controller());
[email protected]36b6dcb2008-11-12 01:19:57661}
662
[email protected]a8eff102009-04-14 15:23:43663bool Browser::CanRestoreTab() {
664 TabRestoreService* service = profile_->GetTabRestoreService();
665 return service && !service->entries().empty();
666}
667
[email protected]7a5f33d2009-03-03 04:35:36668void Browser::ShowSingleDOMUITab(const GURL& url) {
[email protected]b689fce72009-03-17 22:45:34669 // See if we already have a tab with the given URL and select it if so.
670 for (int i = 0; i < tabstrip_model_.count(); i++) {
671 TabContents* tc = tabstrip_model_.GetTabContentsAt(i);
672 if (tc->GetURL() == url) {
[email protected]36b6dcb2008-11-12 01:19:57673 tabstrip_model_.SelectTabContentsAt(i, false);
674 return;
675 }
676 }
[email protected]b689fce72009-03-17 22:45:34677
678 // Otherwise, just create a new tab.
[email protected]5a4940be2009-05-06 06:44:39679 AddTabWithURL(url, GURL(), PageTransition::AUTO_BOOKMARK, true, -1,
680 false, NULL);
[email protected]36b6dcb2008-11-12 01:19:57681}
[email protected]d938aed92009-01-22 19:49:33682
[email protected]ae2622c2009-07-30 23:47:58683void Browser::UpdateCommandsForFullscreenMode(bool is_fullscreen) {
684 const bool show_main_ui = (type() == TYPE_NORMAL) && !is_fullscreen;
685
686 // Navigation commands
687 command_updater_.UpdateCommandEnabled(IDC_OPEN_CURRENT_URL, show_main_ui);
688
689 // Window management commands
690 command_updater_.UpdateCommandEnabled(IDC_PROFILE_MENU, show_main_ui);
691 command_updater_.UpdateCommandEnabled(IDC_SHOW_AS_TAB,
692 (type() & TYPE_POPUP) && !is_fullscreen);
693
694 // Focus various bits of UI
695 command_updater_.UpdateCommandEnabled(IDC_FOCUS_TOOLBAR, show_main_ui);
696 command_updater_.UpdateCommandEnabled(IDC_FOCUS_LOCATION, show_main_ui);
697 command_updater_.UpdateCommandEnabled(IDC_FOCUS_SEARCH, show_main_ui);
698
699 // Show various bits of UI
700 command_updater_.UpdateCommandEnabled(IDC_DEVELOPER_MENU, show_main_ui);
701 command_updater_.UpdateCommandEnabled(IDC_NEW_PROFILE, show_main_ui);
702 command_updater_.UpdateCommandEnabled(IDC_REPORT_BUG, show_main_ui);
703 command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_BAR, show_main_ui);
704 command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, show_main_ui);
[email protected]ca38d8e2009-08-20 18:08:16705 command_updater_.UpdateCommandEnabled(IDC_SYNC_BOOKMARKS, show_main_ui);
[email protected]ae2622c2009-07-30 23:47:58706 command_updater_.UpdateCommandEnabled(IDC_OPTIONS, show_main_ui);
707 command_updater_.UpdateCommandEnabled(IDC_EDIT_SEARCH_ENGINES, show_main_ui);
708 command_updater_.UpdateCommandEnabled(IDC_VIEW_PASSWORDS, show_main_ui);
709 command_updater_.UpdateCommandEnabled(IDC_ABOUT, show_main_ui);
710}
711
[email protected]36b6dcb2008-11-12 01:19:57712///////////////////////////////////////////////////////////////////////////////
713// Browser, Assorted browser commands:
714
[email protected]485fba42009-03-24 23:27:29715void Browser::GoBack(WindowOpenDisposition disposition) {
[email protected]fbd77592008-11-12 20:50:27716 UserMetrics::RecordAction(L"Back", profile_);
717
[email protected]36b6dcb2008-11-12 01:19:57718 // If we are showing an interstitial, just hide it.
719 TabContents* current_tab = GetSelectedTabContents();
[email protected]57c6a652009-05-04 07:58:34720 if (current_tab->interstitial_page()) {
[email protected]a3a1d142008-12-19 00:42:30721 // The GoBack() case is a special case when an interstitial is shown because
722 // the "previous" page is still available, just hidden by the interstitial.
723 // We treat the back as a "Don't proceed", this hides the interstitial and
724 // reveals the previous page.
[email protected]57c6a652009-05-04 07:58:34725 current_tab->interstitial_page()->DontProceed();
[email protected]c7c42332008-11-15 01:10:54726 return;
[email protected]36b6dcb2008-11-12 01:19:57727 }
[email protected]485fba42009-03-24 23:27:29728
[email protected]ce3fa3c2009-04-20 19:55:57729 if (current_tab->controller().CanGoBack()) {
730 NavigationController* controller = NULL;
731 if (disposition == NEW_FOREGROUND_TAB ||
732 disposition == NEW_BACKGROUND_TAB) {
[email protected]90ba8dd2009-04-25 19:43:52733 TabContents* cloned = GetSelectedTabContents()->Clone();
[email protected]5a4940be2009-05-06 06:44:39734 tabstrip_model_.AddTabContents(cloned, -1, false,
[email protected]90ba8dd2009-04-25 19:43:52735 PageTransition::LINK,
736 disposition == NEW_FOREGROUND_TAB);
737 controller = &cloned->controller();
[email protected]485fba42009-03-24 23:27:29738 } else {
739 // Default disposition is CURRENT_TAB.
[email protected]ce3fa3c2009-04-20 19:55:57740 controller = &current_tab->controller();
[email protected]485fba42009-03-24 23:27:29741 }
742 controller->GoBack();
743 }
[email protected]36b6dcb2008-11-12 01:19:57744}
745
[email protected]485fba42009-03-24 23:27:29746void Browser::GoForward(WindowOpenDisposition disp) {
[email protected]ce3fa3c2009-04-20 19:55:57747 // TODO(brettw) this is mostly duplicated from GoBack, these should have a
748 // common backend or something.
[email protected]fbd77592008-11-12 20:50:27749 UserMetrics::RecordAction(L"Forward", profile_);
[email protected]ce3fa3c2009-04-20 19:55:57750 if (GetSelectedTabContents()->controller().CanGoForward()) {
[email protected]485fba42009-03-24 23:27:29751 NavigationController* controller = 0;
752 if (disp == NEW_FOREGROUND_TAB || disp == NEW_BACKGROUND_TAB) {
[email protected]90ba8dd2009-04-25 19:43:52753 TabContents* cloned = GetSelectedTabContents()->Clone();
[email protected]5a4940be2009-05-06 06:44:39754 tabstrip_model_.AddTabContents(cloned, -1, false,
[email protected]90ba8dd2009-04-25 19:43:52755 PageTransition::LINK,
756 disp == NEW_FOREGROUND_TAB);
757 controller = &cloned->controller();
[email protected]485fba42009-03-24 23:27:29758 } else {
759 // Default disposition is CURRENT_TAB.
[email protected]ce3fa3c2009-04-20 19:55:57760 controller = &GetSelectedTabContents()->controller();
[email protected]485fba42009-03-24 23:27:29761 }
762 controller->GoForward();
763 }
[email protected]36b6dcb2008-11-12 01:19:57764}
765
766void Browser::Reload() {
[email protected]fbd77592008-11-12 20:50:27767 UserMetrics::RecordAction(L"Reload", profile_);
768
[email protected]36b6dcb2008-11-12 01:19:57769 // If we are showing an interstitial, treat this as an OpenURL.
770 TabContents* current_tab = GetSelectedTabContents();
771 if (current_tab) {
[email protected]57c6a652009-05-04 07:58:34772 if (current_tab->showing_interstitial_page()) {
[email protected]ce3fa3c2009-04-20 19:55:57773 NavigationEntry* entry = current_tab->controller().GetActiveEntry();
[email protected]36b6dcb2008-11-12 01:19:57774 DCHECK(entry); // Should exist if interstitial is showing.
775 OpenURL(entry->url(), GURL(), CURRENT_TAB, PageTransition::RELOAD);
776 return;
777 }
[email protected]36b6dcb2008-11-12 01:19:57778
[email protected]20142ba2009-05-04 16:58:47779 // As this is caused by a user action, give the focus to the page.
[email protected]9d8a4642009-07-29 17:25:30780 if (!current_tab->FocusLocationBarByDefault())
781 current_tab->Focus();
[email protected]ce3fa3c2009-04-20 19:55:57782 current_tab->controller().Reload(true);
[email protected]36b6dcb2008-11-12 01:19:57783 }
784}
785
[email protected]485fba42009-03-24 23:27:29786void Browser::Home(WindowOpenDisposition disposition) {
[email protected]fbd77592008-11-12 20:50:27787 UserMetrics::RecordAction(L"Home", profile_);
[email protected]485fba42009-03-24 23:27:29788 OpenURL(GetHomePage(), GURL(), disposition, PageTransition::AUTO_BOOKMARK);
[email protected]36b6dcb2008-11-12 01:19:57789}
790
[email protected]fbd77592008-11-12 20:50:27791void Browser::OpenCurrentURL() {
792 UserMetrics::RecordAction(L"LoadURL", profile_);
[email protected]7745b822009-01-27 20:15:35793 LocationBar* location_bar = window_->GetLocationBar();
[email protected]1f7d7e92009-06-02 20:55:04794 OpenURLAtIndex(NULL, GURL(WideToUTF8(location_bar->GetInputString())), GURL(),
795 location_bar->GetWindowOpenDisposition(),
796 location_bar->GetPageTransition(), -1, true);
[email protected]fbd77592008-11-12 20:50:27797}
798
[email protected]485fba42009-03-24 23:27:29799void Browser::Go(WindowOpenDisposition disposition) {
[email protected]84214982008-12-10 18:49:10800 UserMetrics::RecordAction(L"Go", profile_);
[email protected]485fba42009-03-24 23:27:29801 window_->GetLocationBar()->AcceptInputWithDisposition(disposition);
[email protected]84214982008-12-10 18:49:10802}
803
804void Browser::Stop() {
805 UserMetrics::RecordAction(L"Stop", profile_);
[email protected]0daf94732008-12-17 01:08:33806 GetSelectedTabContents()->Stop();
[email protected]84214982008-12-10 18:49:10807}
808
809void Browser::NewWindow() {
810 UserMetrics::RecordAction(L"NewWindow", profile_);
811 Browser::OpenEmptyWindow(profile_->GetOriginalProfile());
812}
813
814void Browser::NewIncognitoWindow() {
815 UserMetrics::RecordAction(L"NewIncognitoWindow", profile_);
816 Browser::OpenEmptyWindow(profile_->GetOffTheRecordProfile());
817}
818
819void Browser::NewProfileWindowByIndex(int index) {
[email protected]d938aed92009-01-22 19:49:33820#if defined(OS_WIN)
[email protected]ac926362009-02-26 01:33:18821 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
822 if (!command_line.HasSwitch(switches::kEnableUserDataDirProfiles))
823 return;
[email protected]84214982008-12-10 18:49:10824 UserMetrics::RecordAction(L"NewProfileWindowByIndex", profile_);
825 UserDataManager::Get()->LaunchChromeForProfile(index);
[email protected]d938aed92009-01-22 19:49:33826#endif
[email protected]84214982008-12-10 18:49:10827}
828
829void Browser::CloseWindow() {
830 UserMetrics::RecordAction(L"CloseWindow", profile_);
831 window_->Close();
832}
833
[email protected]fbd77592008-11-12 20:50:27834void Browser::NewTab() {
835 UserMetrics::RecordAction(L"NewTab", profile_);
[email protected]299dabd2008-11-19 02:27:16836 if (type() == TYPE_NORMAL) {
[email protected]fbd77592008-11-12 20:50:27837 AddBlankTab(true);
838 } else {
[email protected]1a6b30a2009-08-19 03:52:11839 Browser* b = GetOrCreateTabbedBrowser(profile_);
[email protected]fbd77592008-11-12 20:50:27840 b->AddBlankTab(true);
[email protected]15952e462008-11-14 00:29:05841 b->window()->Show();
[email protected]e54f30d2009-01-14 21:17:11842 // The call to AddBlankTab above did not set the focus to the tab as its
843 // window was not active, so we have to do it explicitly.
844 // See http://crbug.com/6380.
[email protected]57c6a652009-05-04 07:58:34845 b->GetSelectedTabContents()->view()->RestoreFocus();
[email protected]fbd77592008-11-12 20:50:27846 }
847}
848
849void Browser::CloseTab() {
850 UserMetrics::RecordAction(L"CloseTab_Accelerator", profile_);
851 tabstrip_model_.CloseTabContentsAt(tabstrip_model_.selected_index());
852}
853
[email protected]fbd77592008-11-12 20:50:27854void Browser::SelectNextTab() {
855 UserMetrics::RecordAction(L"SelectNextTab", profile_);
856 tabstrip_model_.SelectNextTab();
857}
858
859void Browser::SelectPreviousTab() {
860 UserMetrics::RecordAction(L"SelectPrevTab", profile_);
861 tabstrip_model_.SelectPreviousTab();
862}
863
864void Browser::SelectNumberedTab(int index) {
865 if (index < tab_count()) {
866 UserMetrics::RecordAction(L"SelectNumberedTab", profile_);
867 tabstrip_model_.SelectTabContentsAt(index, true);
868 }
869}
870
871void Browser::SelectLastTab() {
872 UserMetrics::RecordAction(L"SelectLastTab", profile_);
873 tabstrip_model_.SelectLastTab();
874}
875
876void Browser::DuplicateTab() {
877 UserMetrics::RecordAction(L"Duplicate", profile_);
878 DuplicateContentsAt(selected_index());
879}
880
881void Browser::RestoreTab() {
882 UserMetrics::RecordAction(L"RestoreTab", profile_);
883 TabRestoreService* service = profile_->GetTabRestoreService();
884 if (!service)
885 return;
886
[email protected]d8375fd2008-11-25 22:45:39887 service->RestoreMostRecentEntry(this);
[email protected]fbd77592008-11-12 20:50:27888}
889
890void Browser::ConvertPopupToTabbedBrowser() {
891 UserMetrics::RecordAction(L"ShowAsTab", profile_);
[email protected]fbd77592008-11-12 20:50:27892 int tab_strip_index = tabstrip_model_.selected_index();
893 TabContents* contents = tabstrip_model_.DetachTabContentsAt(tab_strip_index);
[email protected]15952e462008-11-14 00:29:05894 Browser* browser = Browser::Create(profile_);
895 browser->tabstrip_model()->AppendTabContents(contents, true);
896 browser->window()->Show();
[email protected]fbd77592008-11-12 20:50:27897}
898
[email protected]9282cea2009-02-18 18:49:00899void Browser::ToggleFullscreenMode() {
900 UserMetrics::RecordAction(L"ToggleFullscreen", profile_);
901 window_->SetFullscreen(!window_->IsFullscreen());
[email protected]ae2622c2009-07-30 23:47:58902 // On Linux, setting fullscreen mode is an async call to the X server, which
903 // may or may not support fullscreen mode.
904#if !defined(OS_LINUX)
[email protected]9282cea2009-02-18 18:49:00905 UpdateCommandsForFullscreenMode(window_->IsFullscreen());
[email protected]ae2622c2009-07-30 23:47:58906#endif
[email protected]9282cea2009-02-18 18:49:00907}
908
[email protected]fbd77592008-11-12 20:50:27909void Browser::Exit() {
910 UserMetrics::RecordAction(L"Exit", profile_);
911 BrowserList::CloseAllBrowsers(true);
912}
913
[email protected]36b6dcb2008-11-12 01:19:57914void Browser::BookmarkCurrentPage() {
[email protected]fbd77592008-11-12 20:50:27915 UserMetrics::RecordAction(L"Star", profile_);
916
[email protected]b7ca4e62009-01-23 20:37:29917 TabContents* contents = GetSelectedTabContents();
[email protected]85408b7c2009-06-03 19:11:54918 if (!contents->ShouldDisplayURL())
919 return;
920 const GURL& url = contents->GetURL();
921 if (url.is_empty() || !url.is_valid())
922 return;
923 std::wstring title = UTF16ToWideHack(contents->GetTitle());
924
[email protected]b7ca4e62009-01-23 20:37:29925 BookmarkModel* model = contents->profile()->GetBookmarkModel();
[email protected]36b6dcb2008-11-12 01:19:57926 if (!model || !model->IsLoaded())
927 return; // Ignore requests until bookmarks are loaded.
928
[email protected]c50d0d42009-03-03 17:37:44929 bool was_bookmarked = model->IsBookmarked(url);
[email protected]85408b7c2009-06-03 19:11:54930 model->SetURLStarred(url, title, true);
[email protected]5f2731c52009-02-28 00:41:27931 if (window_->IsActive()) {
932 // Only show the bubble if the window is active, otherwise we may get into
933 // weird situations were the bubble is deleted as soon as it is shown.
[email protected]c50d0d42009-03-03 17:37:44934 window_->ShowBookmarkBubble(url, was_bookmarked);
[email protected]5f2731c52009-02-28 00:41:27935 }
[email protected]36b6dcb2008-11-12 01:19:57936}
937
[email protected]40bdb6d92009-02-25 00:22:27938void Browser::SavePage() {
939 UserMetrics::RecordAction(L"SavePage", profile_);
[email protected]57c6a652009-05-04 07:58:34940 GetSelectedTabContents()->OnSavePage();
[email protected]40bdb6d92009-02-25 00:22:27941}
942
[email protected]fbd77592008-11-12 20:50:27943void Browser::ViewSource() {
944 UserMetrics::RecordAction(L"ViewSource", profile_);
[email protected]36b6dcb2008-11-12 01:19:57945
[email protected]36b6dcb2008-11-12 01:19:57946 TabContents* current_tab = GetSelectedTabContents();
[email protected]ce3fa3c2009-04-20 19:55:57947 NavigationEntry* entry = current_tab->controller().GetLastCommittedEntry();
[email protected]fbd77592008-11-12 20:50:27948 if (entry) {
949 GURL url("view-source:" + entry->url().spec());
[email protected]749eea042009-01-05 22:35:54950 OpenURL(url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
[email protected]36b6dcb2008-11-12 01:19:57951 }
952}
initial.commit09911bf2008-07-26 23:55:29953
[email protected]4801ecc2009-04-05 04:52:58954void Browser::ShowFindBar() {
955 find_bar_controller_->Show();
956}
957
[email protected]a3e18c42009-03-04 23:36:05958bool Browser::SupportsWindowFeature(WindowFeature feature) const {
959 unsigned int features = FEATURE_INFOBAR | FEATURE_DOWNLOADSHELF;
[email protected]653c9ea2009-05-06 16:58:56960 if (type() == TYPE_NORMAL) {
961 features |= FEATURE_BOOKMARKBAR;
962 features |= FEATURE_EXTENSIONSHELF;
963 }
[email protected]a3e18c42009-03-04 23:36:05964 if (!window_ || !window_->IsFullscreen()) {
965 if (type() == TYPE_NORMAL)
966 features |= FEATURE_TABSTRIP | FEATURE_TOOLBAR;
967 else
968 features |= FEATURE_TITLEBAR;
969 if ((type() & Browser::TYPE_APP) == 0)
970 features |= FEATURE_LOCATIONBAR;
971 }
972 return !!(features & feature);
973}
974
[email protected]c61db1d2009-02-06 03:39:18975#if defined(OS_WIN)
[email protected]fbd77592008-11-12 20:50:27976void Browser::ClosePopups() {
977 UserMetrics::RecordAction(L"CloseAllSuppressedPopups", profile_);
978 GetSelectedTabContents()->CloseAllSuppressedPopups();
979}
[email protected]6862ac6c2009-08-05 20:26:41980#endif
initial.commit09911bf2008-07-26 23:55:29981
[email protected]fbd77592008-11-12 20:50:27982void Browser::Print() {
983 UserMetrics::RecordAction(L"PrintPreview", profile_);
[email protected]6862ac6c2009-08-05 20:26:41984#if defined(OS_WIN) || defined(OS_LINUX)
[email protected]57c6a652009-05-04 07:58:34985 GetSelectedTabContents()->PrintPreview();
[email protected]6862ac6c2009-08-05 20:26:41986#else
987 NOTIMPLEMENTED();
988#endif
[email protected]fbd77592008-11-12 20:50:27989}
990
[email protected]fbd77592008-11-12 20:50:27991void Browser::ToggleEncodingAutoDetect() {
992 UserMetrics::RecordAction(L"AutoDetectChange", profile_);
993 encoding_auto_detect_.SetValue(!encoding_auto_detect_.GetValue());
994 // Reload the page so we can try to auto-detect the charset.
995 Reload();
996}
997
998void Browser::OverrideEncoding(int encoding_id) {
999 UserMetrics::RecordAction(L"OverrideEncoding", profile_);
1000 const std::wstring selected_encoding =
1001 CharacterEncoding::GetCanonicalEncodingNameByCommandId(encoding_id);
[email protected]57c6a652009-05-04 07:58:341002 TabContents* contents = GetSelectedTabContents();
1003 if (!selected_encoding.empty() && contents)
1004 contents->override_encoding(selected_encoding);
[email protected]fbd77592008-11-12 20:50:271005 // Update the list of recently selected encodings.
1006 std::wstring new_selected_encoding_list;
1007 if (CharacterEncoding::UpdateRecentlySelectdEncoding(
1008 profile_->GetPrefs()->GetString(prefs::kRecentlySelectedEncoding),
1009 encoding_id,
1010 &new_selected_encoding_list)) {
1011 profile_->GetPrefs()->SetString(prefs::kRecentlySelectedEncoding,
1012 new_selected_encoding_list);
1013 }
[email protected]36b6dcb2008-11-12 01:19:571014}
1015
[email protected]40d59ce52009-03-06 23:20:141016#if defined(OS_WIN)
[email protected]84214982008-12-10 18:49:101017// TODO(devint): http://b/issue?id=1117225 Cut, Copy, and Paste are always
1018// enabled in the page menu regardless of whether the command will do
1019// anything. When someone selects the menu item, we just act as if they hit
1020// the keyboard shortcut for the command by sending the associated key press
1021// to windows. The real fix to this bug is to disable the commands when they
1022// won't do anything. We'll need something like an overall clipboard command
1023// manager to do that.
1024
1025void Browser::Cut() {
1026 UserMetrics::RecordAction(L"Cut", profile_);
[email protected]22cdd932009-08-18 02:16:211027 ui_controls::SendKeyPress(window()->GetNativeHandle(), base::VKEY_X, true,
1028 false, false);
[email protected]36b6dcb2008-11-12 01:19:571029}
1030
[email protected]84214982008-12-10 18:49:101031void Browser::Copy() {
1032 UserMetrics::RecordAction(L"Copy", profile_);
[email protected]22cdd932009-08-18 02:16:211033 ui_controls::SendKeyPress(window()->GetNativeHandle(), base::VKEY_C, true,
1034 false, false);
[email protected]36b6dcb2008-11-12 01:19:571035}
1036
[email protected]84214982008-12-10 18:49:101037void Browser::Paste() {
1038 UserMetrics::RecordAction(L"Paste", profile_);
[email protected]22cdd932009-08-18 02:16:211039 ui_controls::SendKeyPress(window()->GetNativeHandle(), base::VKEY_V, true,
1040 false, false);
[email protected]84214982008-12-10 18:49:101041}
[email protected]31b1bc3a2009-03-10 19:26:191042#endif // #if defined(OS_WIN)
[email protected]84214982008-12-10 18:49:101043
1044void Browser::Find() {
1045 UserMetrics::RecordAction(L"Find", profile_);
[email protected]4f3dc372009-02-24 00:10:291046 FindInPage(false, false);
[email protected]84214982008-12-10 18:49:101047}
1048
1049void Browser::FindNext() {
1050 UserMetrics::RecordAction(L"FindNext", profile_);
[email protected]4f3dc372009-02-24 00:10:291051 FindInPage(true, true);
[email protected]84214982008-12-10 18:49:101052}
1053
1054void Browser::FindPrevious() {
1055 UserMetrics::RecordAction(L"FindPrevious", profile_);
[email protected]4f3dc372009-02-24 00:10:291056 FindInPage(true, false);
[email protected]84214982008-12-10 18:49:101057}
1058
1059void Browser::ZoomIn() {
1060 UserMetrics::RecordAction(L"ZoomPlus", profile_);
[email protected]57c6a652009-05-04 07:58:341061 GetSelectedTabContents()->render_view_host()->Zoom(PageZoom::LARGER);
[email protected]84214982008-12-10 18:49:101062}
1063
1064void Browser::ZoomReset() {
1065 UserMetrics::RecordAction(L"ZoomNormal", profile_);
[email protected]57c6a652009-05-04 07:58:341066 GetSelectedTabContents()->render_view_host()->Zoom(PageZoom::STANDARD);
[email protected]84214982008-12-10 18:49:101067}
1068
1069void Browser::ZoomOut() {
1070 UserMetrics::RecordAction(L"ZoomMinus", profile_);
[email protected]57c6a652009-05-04 07:58:341071 GetSelectedTabContents()->render_view_host()->Zoom(PageZoom::SMALLER);
[email protected]84214982008-12-10 18:49:101072}
1073
1074void Browser::FocusToolbar() {
1075 UserMetrics::RecordAction(L"FocusToolbar", profile_);
1076 window_->FocusToolbar();
1077}
1078
1079void Browser::FocusLocationBar() {
1080 UserMetrics::RecordAction(L"FocusLocation", profile_);
[email protected]d56bcd22009-03-16 19:51:561081 window_->SetFocusToLocationBar();
[email protected]84214982008-12-10 18:49:101082}
1083
1084void Browser::FocusSearch() {
1085 // TODO(beng): replace this with FocusLocationBar
1086 UserMetrics::RecordAction(L"FocusSearch", profile_);
[email protected]7745b822009-01-27 20:15:351087 window_->GetLocationBar()->FocusSearch();
[email protected]84214982008-12-10 18:49:101088}
1089
1090void Browser::OpenFile() {
1091 UserMetrics::RecordAction(L"OpenFile", profile_);
1092 if (!select_file_dialog_.get())
1093 select_file_dialog_ = SelectFileDialog::Create(this);
1094
1095 // TODO(beng): figure out how to juggle this.
[email protected]d56bcd22009-03-16 19:51:561096 gfx::NativeWindow parent_window = window_->GetNativeHandle();
[email protected]84214982008-12-10 18:49:101097 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE,
[email protected]561abe62009-04-06 18:08:341098 string16(), FilePath(),
[email protected]b949f1112009-04-12 20:03:081099 NULL, 0, FILE_PATH_LITERAL(""),
[email protected]d56bcd22009-03-16 19:51:561100 parent_window, NULL);
[email protected]84214982008-12-10 18:49:101101}
1102
1103void Browser::OpenCreateShortcutsDialog() {
1104 UserMetrics::RecordAction(L"CreateShortcut", profile_);
[email protected]b96aa932009-08-12 21:34:491105#if defined(OS_WIN) || defined(OS_LINUX)
[email protected]57c6a652009-05-04 07:58:341106 GetSelectedTabContents()->CreateShortcut();
[email protected]98f6e022009-06-05 22:49:531107#else
1108 NOTIMPLEMENTED();
1109#endif
[email protected]36b6dcb2008-11-12 01:19:571110}
1111
[email protected]c630f162009-07-22 09:41:331112void Browser::ToggleDevToolsWindow() {
[email protected]fbd77592008-11-12 20:50:271113 UserMetrics::RecordAction(L"ShowJSConsole", profile_);
[email protected]3061ccf32009-07-13 14:17:491114 DevToolsManager::GetInstance()->ToggleDevToolsWindow(
[email protected]d9f9b792009-06-24 13:17:121115 GetSelectedTabContents()->render_view_host());
[email protected]fbd77592008-11-12 20:50:271116}
1117
[email protected]84214982008-12-10 18:49:101118void Browser::OpenTaskManager() {
1119 UserMetrics::RecordAction(L"TaskManager", profile_);
[email protected]8f90afd72009-06-22 22:44:381120 window_->ShowTaskManager();
[email protected]84214982008-12-10 18:49:101121}
1122
1123void Browser::OpenSelectProfileDialog() {
[email protected]12a6f0362009-03-09 19:37:361124 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1125 if (!command_line.HasSwitch(switches::kEnableUserDataDirProfiles))
1126 return;
[email protected]84214982008-12-10 18:49:101127 UserMetrics::RecordAction(L"SelectProfile", profile_);
[email protected]505323e22009-01-24 02:47:581128 window_->ShowSelectProfileDialog();
[email protected]84214982008-12-10 18:49:101129}
1130
1131void Browser::OpenNewProfileDialog() {
[email protected]ac926362009-02-26 01:33:181132 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1133 if (!command_line.HasSwitch(switches::kEnableUserDataDirProfiles))
1134 return;
[email protected]84214982008-12-10 18:49:101135 UserMetrics::RecordAction(L"CreateProfile", profile_);
[email protected]505323e22009-01-24 02:47:581136 window_->ShowNewProfileDialog();
[email protected]84214982008-12-10 18:49:101137}
1138
1139void Browser::OpenBugReportDialog() {
1140 UserMetrics::RecordAction(L"ReportBug", profile_);
1141 window_->ShowReportBugDialog();
1142}
[email protected]44b2c8852009-03-18 00:57:491143
[email protected]84214982008-12-10 18:49:101144void Browser::ToggleBookmarkBar() {
1145 UserMetrics::RecordAction(L"ShowBookmarksBar", profile_);
1146 window_->ToggleBookmarkBar();
1147}
1148
[email protected]84214982008-12-10 18:49:101149void Browser::OpenBookmarkManager() {
1150 UserMetrics::RecordAction(L"ShowBookmarkManager", profile_);
1151 window_->ShowBookmarkManager();
1152}
[email protected]8bf80e922009-03-09 20:56:361153
1154void Browser::ShowHistoryTab() {
1155 UserMetrics::RecordAction(L"ShowHistory", profile_);
[email protected]b689fce72009-03-17 22:45:341156 ShowSingleDOMUITab(GURL(chrome::kChromeUIHistoryURL));
[email protected]8bf80e922009-03-09 20:56:361157}
[email protected]84214982008-12-10 18:49:101158
1159void Browser::ShowDownloadsTab() {
1160 UserMetrics::RecordAction(L"ShowDownloads", profile_);
[email protected]b689fce72009-03-17 22:45:341161 ShowSingleDOMUITab(GURL(chrome::kChromeUIDownloadsURL));
[email protected]84214982008-12-10 18:49:101162}
1163
1164void Browser::OpenClearBrowsingDataDialog() {
1165 UserMetrics::RecordAction(L"ClearBrowsingData_ShowDlg", profile_);
1166 window_->ShowClearBrowsingDataDialog();
1167}
1168
[email protected]84214982008-12-10 18:49:101169void Browser::OpenOptionsDialog() {
1170 UserMetrics::RecordAction(L"ShowOptions", profile_);
1171 ShowOptionsWindow(OPTIONS_PAGE_DEFAULT, OPTIONS_GROUP_NONE, profile_);
1172}
1173
1174void Browser::OpenKeywordEditor() {
1175 UserMetrics::RecordAction(L"EditSearchEngines", profile_);
1176 window_->ShowSearchEnginesDialog();
[email protected]fbd77592008-11-12 20:50:271177}
1178
1179void Browser::OpenPasswordManager() {
[email protected]2d46c842008-11-14 19:24:311180 window_->ShowPasswordManager();
[email protected]fbd77592008-11-12 20:50:271181}
1182
[email protected]1bdf29e2009-05-11 23:45:251183void Browser::OpenImportSettingsDialog() {
1184 UserMetrics::RecordAction(L"Import_ShowDlg", profile_);
1185 window_->ShowImportDialog();
1186}
[email protected]1bdf29e2009-05-11 23:45:251187
[email protected]ca38d8e2009-08-20 18:08:161188#ifdef CHROME_PERSONALIZATION
1189void Browser::OpenSyncMyBookmarksDialog() {
1190 ProfileSyncService* service = profile_->GetProfileSyncService();
1191 // TODO(timsteele): Incognito has no sync service for the time being,
1192 // so protect against this case.
1193 if (!service)
1194 return;
1195 if (service->HasSyncSetupCompleted()) {
1196 ShowOptionsWindow(OPTIONS_PAGE_CONTENT, OPTIONS_GROUP_NONE, profile_);
1197 } else {
1198 service->EnableForUser();
1199 ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_WRENCH);
1200 }
1201}
1202#endif
1203
[email protected]fbd77592008-11-12 20:50:271204void Browser::OpenAboutChromeDialog() {
1205 UserMetrics::RecordAction(L"AboutChrome", profile_);
[email protected]2d46c842008-11-14 19:24:311206 window_->ShowAboutChromeDialog();
[email protected]fbd77592008-11-12 20:50:271207}
1208
[email protected]fbd77592008-11-12 20:50:271209void Browser::OpenHelpTab() {
[email protected]40d59ce52009-03-06 23:20:141210 GURL help_url(WideToASCII(l10n_util::GetString(IDS_HELP_CONTENT_URL)));
[email protected]22735af62009-04-07 21:09:581211 AddTabWithURL(help_url, GURL(), PageTransition::AUTO_BOOKMARK, true, -1,
[email protected]5a4940be2009-05-06 06:44:391212 false, NULL);
[email protected]fbd77592008-11-12 20:50:271213}
1214
[email protected]16779842009-07-08 23:45:291215#if defined(OS_CHROMEOS)
[email protected]be715072009-07-07 15:43:201216void Browser::ShowControlPanel() {
1217 GURL url("http://localhost:8080");
1218 AddTabWithURL(url, GURL(), PageTransition::AUTO_BOOKMARK, true, -1,
1219 false, NULL);
1220}
1221#endif
1222
[email protected]36b6dcb2008-11-12 01:19:571223///////////////////////////////////////////////////////////////////////////////
1224
1225// static
1226void Browser::RegisterPrefs(PrefService* prefs) {
1227 prefs->RegisterDictionaryPref(prefs::kBrowserWindowPlacement);
1228 prefs->RegisterIntegerPref(prefs::kOptionsWindowLastTabIndex, 0);
[email protected]749380bb2009-07-20 08:57:551229 prefs->RegisterIntegerPref(prefs::kDevToolsSplitLocation, -1);
[email protected]36b6dcb2008-11-12 01:19:571230}
1231
1232// static
1233void Browser::RegisterUserPrefs(PrefService* prefs) {
1234 prefs->RegisterStringPref(prefs::kHomePage, L"chrome-internal:");
1235 prefs->RegisterBooleanPref(prefs::kHomePageIsNewTabPage, true);
1236 prefs->RegisterIntegerPref(prefs::kCookieBehavior,
1237 net::CookiePolicy::ALLOW_ALL_COOKIES);
1238 prefs->RegisterBooleanPref(prefs::kShowHomeButton, false);
[email protected]93a2c7242009-07-07 18:43:091239#if defined(OS_MACOSX)
1240 // This really belongs in platform code, but there's no good place to
1241 // initialize it between the time when the AppController is created
1242 // (where there's no profile) and the time the controller gets another
1243 // crack at the start of the main event loop. By that time, BrowserInit
1244 // has already created the browser window, and it's too late: we need the
1245 // pref to be already initialized. Doing it here also saves us from having
1246 // to hard-code pref registration in the several unit tests that use
1247 // this preference.
1248 prefs->RegisterBooleanPref(prefs::kShowPageOptionsButtons, false);
1249#endif
[email protected]36b6dcb2008-11-12 01:19:571250 prefs->RegisterStringPref(prefs::kRecentlySelectedEncoding, L"");
[email protected]36b6dcb2008-11-12 01:19:571251 prefs->RegisterBooleanPref(prefs::kDeleteBrowsingHistory, true);
1252 prefs->RegisterBooleanPref(prefs::kDeleteDownloadHistory, true);
1253 prefs->RegisterBooleanPref(prefs::kDeleteCache, true);
1254 prefs->RegisterBooleanPref(prefs::kDeleteCookies, true);
1255 prefs->RegisterBooleanPref(prefs::kDeletePasswords, false);
1256 prefs->RegisterBooleanPref(prefs::kDeleteFormData, true);
1257 prefs->RegisterIntegerPref(prefs::kDeleteTimePeriod, 0);
[email protected]48b47ffa2009-05-02 07:18:301258 prefs->RegisterBooleanPref(prefs::kCheckDefaultBrowser, true);
[email protected]c8865482009-07-23 20:40:101259 prefs->RegisterBooleanPref(prefs::kShowOmniboxSearchHint, true);
[email protected]36b6dcb2008-11-12 01:19:571260}
1261
1262// static
1263Browser* Browser::GetBrowserForController(
1264 const NavigationController* controller, int* index_result) {
1265 BrowserList::const_iterator it;
1266 for (it = BrowserList::begin(); it != BrowserList::end(); ++it) {
[email protected]902cdf772009-05-06 15:08:121267 int index = (*it)->tabstrip_model_.GetIndexOfController(controller);
[email protected]36b6dcb2008-11-12 01:19:571268 if (index != TabStripModel::kNoTab) {
1269 if (index_result)
1270 *index_result = index;
1271 return *it;
1272 }
1273 }
1274
1275 return NULL;
1276}
1277
[email protected]485fba42009-03-24 23:27:291278void Browser::ExecuteCommandWithDisposition(
1279 int id, WindowOpenDisposition disposition) {
[email protected]1fc025202009-01-20 23:03:141280 // No commands are enabled if there is not yet any selected tab.
1281 // TODO(pkasting): It seems like we should not need this, because either
1282 // most/all commands should not have been enabled yet anyway or the ones that
1283 // are enabled should be global, or safe themselves against having no selected
1284 // tab. However, Ben says he tried removing this before and got lots of
1285 // crashes, e.g. from Windows sending WM_COMMANDs at random times during
1286 // window construction. This probably could use closer examination someday.
1287 if (!GetSelectedTabContents())
1288 return;
1289
1290 DCHECK(command_updater_.IsCommandEnabled(id)) << "Invalid/disabled command";
[email protected]36b6dcb2008-11-12 01:19:571291
[email protected]fbd77592008-11-12 20:50:271292 // The order of commands in this switch statement must match the function
1293 // declaration order in browser.h!
[email protected]36b6dcb2008-11-12 01:19:571294 switch (id) {
[email protected]84214982008-12-10 18:49:101295 // Navigation commands
[email protected]485fba42009-03-24 23:27:291296 case IDC_BACK: GoBack(disposition); break;
1297 case IDC_FORWARD: GoForward(disposition); break;
[email protected]cb525c82008-12-08 23:04:541298 case IDC_RELOAD: Reload(); break;
[email protected]485fba42009-03-24 23:27:291299 case IDC_HOME: Home(disposition); break;
[email protected]cb525c82008-12-08 23:04:541300 case IDC_OPEN_CURRENT_URL: OpenCurrentURL(); break;
[email protected]485fba42009-03-24 23:27:291301 case IDC_GO: Go(disposition); break;
[email protected]84214982008-12-10 18:49:101302 case IDC_STOP: Stop(); break;
[email protected]36b6dcb2008-11-12 01:19:571303
[email protected]84214982008-12-10 18:49:101304 // Window management commands
[email protected]cb525c82008-12-08 23:04:541305 case IDC_NEW_WINDOW: NewWindow(); break;
1306 case IDC_NEW_INCOGNITO_WINDOW: NewIncognitoWindow(); break;
[email protected]84214982008-12-10 18:49:101307 case IDC_NEW_WINDOW_PROFILE_0:
1308 case IDC_NEW_WINDOW_PROFILE_1:
1309 case IDC_NEW_WINDOW_PROFILE_2:
1310 case IDC_NEW_WINDOW_PROFILE_3:
1311 case IDC_NEW_WINDOW_PROFILE_4:
1312 case IDC_NEW_WINDOW_PROFILE_5:
1313 case IDC_NEW_WINDOW_PROFILE_6:
1314 case IDC_NEW_WINDOW_PROFILE_7:
[email protected]f21c613a2009-02-12 14:46:171315 case IDC_NEW_WINDOW_PROFILE_8:
[email protected]84214982008-12-10 18:49:101316 NewProfileWindowByIndex(id - IDC_NEW_WINDOW_PROFILE_0); break;
[email protected]cb525c82008-12-08 23:04:541317 case IDC_CLOSE_WINDOW: CloseWindow(); break;
[email protected]84214982008-12-10 18:49:101318 case IDC_NEW_TAB: NewTab(); break;
1319 case IDC_CLOSE_TAB: CloseTab(); break;
[email protected]cb525c82008-12-08 23:04:541320 case IDC_SELECT_NEXT_TAB: SelectNextTab(); break;
1321 case IDC_SELECT_PREVIOUS_TAB: SelectPreviousTab(); break;
[email protected]36b6dcb2008-11-12 01:19:571322 case IDC_SELECT_TAB_0:
1323 case IDC_SELECT_TAB_1:
1324 case IDC_SELECT_TAB_2:
1325 case IDC_SELECT_TAB_3:
1326 case IDC_SELECT_TAB_4:
1327 case IDC_SELECT_TAB_5:
1328 case IDC_SELECT_TAB_6:
[email protected]cb525c82008-12-08 23:04:541329 case IDC_SELECT_TAB_7: SelectNumberedTab(id - IDC_SELECT_TAB_0);
1330 break;
1331 case IDC_SELECT_LAST_TAB: SelectLastTab(); break;
1332 case IDC_DUPLICATE_TAB: DuplicateTab(); break;
1333 case IDC_RESTORE_TAB: RestoreTab(); break;
1334 case IDC_SHOW_AS_TAB: ConvertPopupToTabbedBrowser(); break;
[email protected]9282cea2009-02-18 18:49:001335 case IDC_FULLSCREEN: ToggleFullscreenMode(); break;
[email protected]cb525c82008-12-08 23:04:541336 case IDC_EXIT: Exit(); break;
[email protected]36b6dcb2008-11-12 01:19:571337
[email protected]84214982008-12-10 18:49:101338 // Page-related commands
[email protected]40bdb6d92009-02-25 00:22:271339 case IDC_SAVE_PAGE: SavePage(); break;
[email protected]cb525c82008-12-08 23:04:541340 case IDC_STAR: BookmarkCurrentPage(); break;
1341 case IDC_VIEW_SOURCE: ViewSource(); break;
[email protected]c61db1d2009-02-06 03:39:181342#if defined(OS_WIN)
[email protected]cb525c82008-12-08 23:04:541343 case IDC_CLOSE_POPUPS: ClosePopups(); break;
[email protected]40d59ce52009-03-06 23:20:141344#endif
[email protected]6862ac6c2009-08-05 20:26:411345 case IDC_PRINT: Print(); break;
[email protected]cb525c82008-12-08 23:04:541346 case IDC_ENCODING_AUTO_DETECT: ToggleEncodingAutoDetect(); break;
[email protected]36b6dcb2008-11-12 01:19:571347 case IDC_ENCODING_UTF8:
1348 case IDC_ENCODING_UTF16LE:
1349 case IDC_ENCODING_ISO88591:
1350 case IDC_ENCODING_WINDOWS1252:
[email protected]1c5bf632008-12-11 20:30:491351 case IDC_ENCODING_GBK:
[email protected]36b6dcb2008-11-12 01:19:571352 case IDC_ENCODING_GB18030:
1353 case IDC_ENCODING_BIG5HKSCS:
1354 case IDC_ENCODING_BIG5:
1355 case IDC_ENCODING_KOREAN:
1356 case IDC_ENCODING_SHIFTJIS:
1357 case IDC_ENCODING_ISO2022JP:
1358 case IDC_ENCODING_EUCJP:
1359 case IDC_ENCODING_THAI:
1360 case IDC_ENCODING_ISO885915:
1361 case IDC_ENCODING_MACINTOSH:
1362 case IDC_ENCODING_ISO88592:
1363 case IDC_ENCODING_WINDOWS1250:
1364 case IDC_ENCODING_ISO88595:
1365 case IDC_ENCODING_WINDOWS1251:
1366 case IDC_ENCODING_KOI8R:
1367 case IDC_ENCODING_KOI8U:
1368 case IDC_ENCODING_ISO88597:
1369 case IDC_ENCODING_WINDOWS1253:
1370 case IDC_ENCODING_ISO88594:
1371 case IDC_ENCODING_ISO885913:
1372 case IDC_ENCODING_WINDOWS1257:
1373 case IDC_ENCODING_ISO88593:
1374 case IDC_ENCODING_ISO885910:
1375 case IDC_ENCODING_ISO885914:
1376 case IDC_ENCODING_ISO885916:
[email protected]36b6dcb2008-11-12 01:19:571377 case IDC_ENCODING_WINDOWS1254:
1378 case IDC_ENCODING_ISO88596:
1379 case IDC_ENCODING_WINDOWS1256:
1380 case IDC_ENCODING_ISO88598:
[email protected]e13271f2009-03-07 00:26:001381 case IDC_ENCODING_ISO88598I:
[email protected]36b6dcb2008-11-12 01:19:571382 case IDC_ENCODING_WINDOWS1255:
[email protected]cb525c82008-12-08 23:04:541383 case IDC_ENCODING_WINDOWS1258: OverrideEncoding(id); break;
[email protected]36b6dcb2008-11-12 01:19:571384
[email protected]40d59ce52009-03-06 23:20:141385#if defined(OS_WIN)
[email protected]84214982008-12-10 18:49:101386 // Clipboard commands
1387 case IDC_CUT: Cut(); break;
1388 case IDC_COPY: Copy(); break;
[email protected]84214982008-12-10 18:49:101389 case IDC_PASTE: Paste(); break;
[email protected]31b1bc3a2009-03-10 19:26:191390#endif
[email protected]84214982008-12-10 18:49:101391
1392 // Find-in-page
1393 case IDC_FIND: Find(); break;
1394 case IDC_FIND_NEXT: FindNext(); break;
1395 case IDC_FIND_PREVIOUS: FindPrevious(); break;
1396
1397 // Zoom
1398 case IDC_ZOOM_PLUS: ZoomIn(); break;
1399 case IDC_ZOOM_NORMAL: ZoomReset(); break;
1400 case IDC_ZOOM_MINUS: ZoomOut(); break;
1401
1402 // Focus various bits of UI
1403 case IDC_FOCUS_TOOLBAR: FocusToolbar(); break;
1404 case IDC_FOCUS_LOCATION: FocusLocationBar(); break;
1405 case IDC_FOCUS_SEARCH: FocusSearch(); break;
1406
1407 // Show various bits of UI
1408 case IDC_OPEN_FILE: OpenFile(); break;
1409 case IDC_CREATE_SHORTCUTS: OpenCreateShortcutsDialog(); break;
[email protected]c630f162009-07-22 09:41:331410 case IDC_DEV_TOOLS: ToggleDevToolsWindow(); break;
[email protected]cb525c82008-12-08 23:04:541411 case IDC_TASK_MANAGER: OpenTaskManager(); break;
[email protected]cb525c82008-12-08 23:04:541412 case IDC_SELECT_PROFILE: OpenSelectProfileDialog(); break;
1413 case IDC_NEW_PROFILE: OpenNewProfileDialog(); break;
[email protected]84214982008-12-10 18:49:101414 case IDC_REPORT_BUG: OpenBugReportDialog(); break;
[email protected]44b2c8852009-03-18 00:57:491415
[email protected]84214982008-12-10 18:49:101416 case IDC_SHOW_BOOKMARK_BAR: ToggleBookmarkBar(); break;
[email protected]44b2c8852009-03-18 00:57:491417
[email protected]84214982008-12-10 18:49:101418 case IDC_SHOW_BOOKMARK_MANAGER: OpenBookmarkManager(); break;
[email protected]8bf80e922009-03-09 20:56:361419 case IDC_SHOW_HISTORY: ShowHistoryTab(); break;
[email protected]84214982008-12-10 18:49:101420 case IDC_SHOW_DOWNLOADS: ShowDownloadsTab(); break;
[email protected]026e34a2009-02-06 00:06:121421#ifdef CHROME_PERSONALIZATION
[email protected]ca38d8e2009-08-20 18:08:161422 case IDC_SYNC_BOOKMARKS: OpenSyncMyBookmarksDialog(); break;
[email protected]0e3e3e32009-05-14 01:00:531423#endif
[email protected]84214982008-12-10 18:49:101424 case IDC_OPTIONS: OpenOptionsDialog(); break;
1425 case IDC_EDIT_SEARCH_ENGINES: OpenKeywordEditor(); break;
1426 case IDC_VIEW_PASSWORDS: OpenPasswordManager(); break;
[email protected]25364e12009-05-22 01:37:191427 case IDC_CLEAR_BROWSING_DATA: OpenClearBrowsingDataDialog(); break;
[email protected]1bdf29e2009-05-11 23:45:251428 case IDC_IMPORT_SETTINGS: OpenImportSettingsDialog(); break;
[email protected]4dbac172009-04-24 20:23:491429 case IDC_ABOUT: OpenAboutChromeDialog(); break;
[email protected]40d59ce52009-03-06 23:20:141430 case IDC_HELP_PAGE: OpenHelpTab(); break;
[email protected]16779842009-07-08 23:45:291431#if defined(OS_CHROMEOS)
[email protected]be715072009-07-07 15:43:201432 case IDC_CONTROL_PANEL: ShowControlPanel(); break;
1433#endif
[email protected]d938aed92009-01-22 19:49:331434
[email protected]36b6dcb2008-11-12 01:19:571435 default:
[email protected]84214982008-12-10 18:49:101436 LOG(WARNING) << "Received Unimplemented Command: " << id;
[email protected]fbd77592008-11-12 20:50:271437 break;
[email protected]36b6dcb2008-11-12 01:19:571438 }
1439}
1440
1441///////////////////////////////////////////////////////////////////////////////
[email protected]485fba42009-03-24 23:27:291442// Browser, CommandUpdater::CommandUpdaterDelegate implementation:
1443
1444void Browser::ExecuteCommand(int id) {
1445 ExecuteCommandWithDisposition(id, CURRENT_TAB);
1446}
1447
1448///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:571449// Browser, TabStripModelDelegate implementation:
1450
[email protected]22735af62009-04-07 21:09:581451TabContents* Browser::AddBlankTab(bool foreground) {
1452 return AddBlankTabAt(-1, foreground);
1453}
1454
1455TabContents* Browser::AddBlankTabAt(int index, bool foreground) {
1456 return AddTabWithURL(GURL(chrome::kChromeUINewTabURL), GURL(),
[email protected]5a4940be2009-05-06 06:44:391457 PageTransition::TYPED, foreground, index, false, NULL);
[email protected]15952e462008-11-14 00:29:051458}
1459
[email protected]3d1104f2009-03-26 15:30:281460Browser* Browser::CreateNewStripWithContents(TabContents* detached_contents,
1461 const gfx::Rect& window_bounds,
1462 const DockInfo& dock_info) {
[email protected]299dabd2008-11-19 02:27:161463 DCHECK(type_ == TYPE_NORMAL);
[email protected]adf650f2008-12-09 16:10:061464
[email protected]5e495462008-11-20 23:07:411465 gfx::Rect new_window_bounds = window_bounds;
1466 bool maximize = false;
1467 if (dock_info.GetNewWindowBounds(&new_window_bounds, &maximize))
1468 dock_info.AdjustOtherWindowBounds();
1469
[email protected]36b6dcb2008-11-12 01:19:571470 // Create an empty new browser window the same size as the old one.
[email protected]299dabd2008-11-19 02:27:161471 Browser* browser = new Browser(TYPE_NORMAL, profile_);
[email protected]5e495462008-11-20 23:07:411472 browser->set_override_bounds(new_window_bounds);
[email protected]2e716622009-03-09 21:11:011473 browser->set_maximized_state(
1474 maximize ? MAXIMIZED_STATE_MAXIMIZED : MAXIMIZED_STATE_UNMAXIMIZED);
[email protected]15952e462008-11-14 00:29:051475 browser->CreateBrowserWindow();
1476 browser->tabstrip_model()->AppendTabContents(detached_contents, true);
[email protected]159f7762008-12-19 14:58:271477 // Make sure the loading state is updated correctly, otherwise the throbber
1478 // won't start if the page is loading.
1479 browser->LoadingStateChanged(detached_contents);
[email protected]3d1104f2009-03-26 15:30:281480 return browser;
[email protected]36b6dcb2008-11-12 01:19:571481}
1482
[email protected]7c0560f2009-07-07 18:44:311483void Browser::ContinueDraggingDetachedTab(TabContents* contents,
1484 const gfx::Rect& window_bounds,
1485 const gfx::Rect& tab_bounds) {
1486 Browser* browser = new Browser(TYPE_NORMAL, profile_);
1487 browser->set_override_bounds(window_bounds);
1488 browser->CreateBrowserWindow();
1489 browser->tabstrip_model()->AppendTabContents(contents, true);
1490 browser->LoadingStateChanged(contents);
1491 browser->window()->Show();
1492 browser->window()->ContinueDraggingDetachedTab(tab_bounds);
1493}
1494
[email protected]36b6dcb2008-11-12 01:19:571495int Browser::GetDragActions() const {
[email protected]d54f6a002009-03-18 17:17:251496 return TAB_TEAROFF_ACTION | (tab_count() > 1 ? TAB_MOVE_ACTION : 0);
[email protected]36b6dcb2008-11-12 01:19:571497}
1498
1499TabContents* Browser::CreateTabContentsForURL(
1500 const GURL& url, const GURL& referrer, Profile* profile,
1501 PageTransition::Type transition, bool defer_load,
1502 SiteInstance* instance) const {
[email protected]57c6a652009-05-04 07:58:341503 TabContents* contents = new TabContents(profile, instance,
[email protected]9423d9412009-04-14 22:13:551504 MSG_ROUTING_NONE, NULL);
[email protected]36b6dcb2008-11-12 01:19:571505
[email protected]36b6dcb2008-11-12 01:19:571506 if (!defer_load) {
1507 // Load the initial URL before adding the new tab contents to the tab strip
1508 // so that the tab contents has navigation state.
[email protected]ce3fa3c2009-04-20 19:55:571509 contents->controller().LoadURL(url, referrer, transition);
[email protected]36b6dcb2008-11-12 01:19:571510 }
1511
1512 return contents;
1513}
1514
1515bool Browser::CanDuplicateContentsAt(int index) {
[email protected]ce3fa3c2009-04-20 19:55:571516 NavigationController& nc = GetTabContentsAt(index)->controller();
1517 return nc.tab_contents() && nc.GetLastCommittedEntry();
[email protected]36b6dcb2008-11-12 01:19:571518}
1519
1520void Browser::DuplicateContentsAt(int index) {
1521 TabContents* contents = GetTabContentsAt(index);
1522 TabContents* new_contents = NULL;
1523 DCHECK(contents);
[email protected]5c0e6482009-07-14 20:20:091524 bool pinned = false;
[email protected]36b6dcb2008-11-12 01:19:571525
[email protected]299dabd2008-11-19 02:27:161526 if (type_ == TYPE_NORMAL) {
[email protected]36b6dcb2008-11-12 01:19:571527 // If this is a tabbed browser, just create a duplicate tab inside the same
1528 // window next to the tab being duplicated.
[email protected]ce3fa3c2009-04-20 19:55:571529 new_contents = contents->Clone();
[email protected]5c0e6482009-07-14 20:20:091530 // Make sure we force the index, otherwise the duplicate tab may appear at
1531 // the wrong location.
1532 tabstrip_model_.AddTabContents(new_contents, index + 1, true,
[email protected]36b6dcb2008-11-12 01:19:571533 PageTransition::LINK, true);
[email protected]5c0e6482009-07-14 20:20:091534 if (tabstrip_model_.IsTabPinned(index)) {
1535 pinned = true;
1536 tabstrip_model_.SetTabPinned(index + 1, true);
1537 }
[email protected]36b6dcb2008-11-12 01:19:571538 } else {
[email protected]15952e462008-11-14 00:29:051539 Browser* browser = NULL;
[email protected]d5fbc002009-02-27 22:12:581540 if (type_ & TYPE_APP) {
1541 browser = Browser::CreateForApp(app_name_, profile_, type_ & TYPE_POPUP);
[email protected]299dabd2008-11-19 02:27:161542 } else if (type_ == TYPE_POPUP) {
[email protected]15952e462008-11-14 00:29:051543 browser = Browser::CreateForPopup(profile_);
1544 }
[email protected]36b6dcb2008-11-12 01:19:571545
[email protected]b1fed962008-12-18 00:54:081546 // Preserve the size of the original window. The new window has already
1547 // been given an offset by the OS, so we shouldn't copy the old bounds.
1548 BrowserWindow* new_window = browser->window();
[email protected]dae12ee62009-07-29 20:02:051549 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
1550 window()->GetRestoredBounds().size()));
[email protected]b1fed962008-12-18 00:54:081551
[email protected]36b6dcb2008-11-12 01:19:571552 // We need to show the browser now. Otherwise ContainerWin assumes the
1553 // TabContents is invisible and won't size it.
[email protected]15952e462008-11-14 00:29:051554 browser->window()->Show();
[email protected]36b6dcb2008-11-12 01:19:571555
1556 // The page transition below is only for the purpose of inserting the tab.
[email protected]15952e462008-11-14 00:29:051557 new_contents = browser->AddTabWithNavigationController(
[email protected]ce3fa3c2009-04-20 19:55:571558 &contents->Clone()->controller(),
[email protected]36b6dcb2008-11-12 01:19:571559 PageTransition::LINK);
[email protected]36b6dcb2008-11-12 01:19:571560 }
1561
1562 if (profile_->HasSessionService()) {
1563 SessionService* session_service = profile_->GetSessionService();
1564 if (session_service)
[email protected]5c0e6482009-07-14 20:20:091565 session_service->TabRestored(&new_contents->controller(), pinned);
[email protected]36b6dcb2008-11-12 01:19:571566 }
1567}
1568
[email protected]36b6dcb2008-11-12 01:19:571569void Browser::CloseFrameAfterDragSession() {
[email protected]9aefecc92009-06-10 21:31:321570#if defined(OS_WIN) || defined(OS_LINUX)
[email protected]36b6dcb2008-11-12 01:19:571571 // This is scheduled to run after we return to the message loop because
1572 // otherwise the frame will think the drag session is still active and ignore
1573 // the request.
[email protected]d6a3c772009-01-27 19:41:201574 // TODO(port): figure out what is required here in a cross-platform world
[email protected]36b6dcb2008-11-12 01:19:571575 MessageLoop::current()->PostTask(FROM_HERE,
1576 method_factory_.NewRunnableMethod(&Browser::CloseFrame));
[email protected]d6a3c772009-01-27 19:41:201577#endif
initial.commit09911bf2008-07-26 23:55:291578}
1579
[email protected]505323e22009-01-24 02:47:581580void Browser::CreateHistoricalTab(TabContents* contents) {
1581 // We don't create historical tabs for incognito windows or windows without
1582 // profiles.
1583 if (!profile() || profile()->IsOffTheRecord() ||
1584 !profile()->GetTabRestoreService()) {
1585 return;
1586 }
1587
1588 // We only create historical tab entries for normal tabbed browser windows.
1589 if (type() == TYPE_NORMAL) {
1590 profile()->GetTabRestoreService()->CreateHistoricalTab(
[email protected]ce3fa3c2009-04-20 19:55:571591 &contents->controller());
[email protected]505323e22009-01-24 02:47:581592 }
1593}
1594
1595bool Browser::RunUnloadListenerBeforeClosing(TabContents* contents) {
[email protected]57c6a652009-05-04 07:58:341596 // If the TabContents is not connected yet, then there's no unload
1597 // handler we can fire even if the TabContents has an unload listener.
1598 // One case where we hit this is in a tab that has an infinite loop
1599 // before load.
1600 if (TabHasUnloadListener(contents)) {
1601 // If the page has unload listeners, then we tell the renderer to fire
1602 // them. Once they have fired, we'll get a message back saying whether
1603 // to proceed closing the page or not, which sends us back to this method
1604 // with the HasUnloadListener bit cleared.
[email protected]ae23c272009-07-27 20:15:401605 contents->render_view_host()->FirePageBeforeUnload(false);
[email protected]57c6a652009-05-04 07:58:341606 return true;
[email protected]505323e22009-01-24 02:47:581607 }
1608 return false;
1609}
1610
[email protected]940ccb22009-04-30 17:11:101611bool Browser::CanCloseContentsAt(int index) {
1612 if (tabstrip_model_.count() > 1)
1613 return true;
1614 // We are closing the last tab for this browser. Make sure to check for
1615 // in-progress downloads.
1616 // Note that the next call when it returns false will ask the user for
1617 // confirmation before closing the browser if the user decides so.
1618 return CanCloseWithInProgressDownloads();
1619}
[email protected]d6a3c772009-01-27 19:41:201620
[email protected]2d46c842008-11-14 19:24:311621///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:571622// Browser, TabStripModelObserver implementation:
1623
1624void Browser::TabInsertedAt(TabContents* contents,
1625 int index,
1626 bool foreground) {
1627 contents->set_delegate(this);
[email protected]ce3fa3c2009-04-20 19:55:571628 contents->controller().SetWindowID(session_id());
[email protected]36b6dcb2008-11-12 01:19:571629
1630 SyncHistoryWithTabs(tabstrip_model_.GetIndexOfTabContents(contents));
1631
[email protected]159f7762008-12-19 14:58:271632 // Make sure the loading state is updated correctly, otherwise the throbber
1633 // won't start if the page is loading.
1634 LoadingStateChanged(contents);
1635
[email protected]36b6dcb2008-11-12 01:19:571636 // If the tab crashes in the beforeunload or unload handler, it won't be
1637 // able to ack. But we know we can close it.
[email protected]0cb94102009-05-22 19:51:211638 registrar_.Add(this, NotificationType::TAB_CONTENTS_DISCONNECTED,
1639 Source<TabContents>(contents));
[email protected]36b6dcb2008-11-12 01:19:571640}
1641
1642void Browser::TabClosingAt(TabContents* contents, int index) {
[email protected]bfd04a62009-02-01 18:16:561643 NotificationService::current()->Notify(
1644 NotificationType::TAB_CLOSING,
[email protected]ce3fa3c2009-04-20 19:55:571645 Source<NavigationController>(&contents->controller()),
[email protected]bfd04a62009-02-01 18:16:561646 NotificationService::NoDetails());
[email protected]36b6dcb2008-11-12 01:19:571647
1648 // Sever the TabContents' connection back to us.
1649 contents->set_delegate(NULL);
1650}
1651
1652void Browser::TabDetachedAt(TabContents* contents, int index) {
[email protected]aacfcc72009-05-27 19:39:541653 // Save what the user's currently typing.
1654 window_->GetLocationBar()->SaveStateToContents(contents);
1655
[email protected]36b6dcb2008-11-12 01:19:571656 contents->set_delegate(NULL);
1657 if (!tabstrip_model_.closing_all())
1658 SyncHistoryWithTabs(0);
1659
1660 RemoveScheduledUpdatesFor(contents);
1661
[email protected]4801ecc2009-04-05 04:52:581662 if (find_bar_controller_.get() && index == tabstrip_model_.selected_index())
[email protected]57c6a652009-05-04 07:58:341663 find_bar_controller_->ChangeTabContents(NULL);
[email protected]4801ecc2009-04-05 04:52:581664
[email protected]0cb94102009-05-22 19:51:211665 registrar_.Remove(this, NotificationType::TAB_CONTENTS_DISCONNECTED,
1666 Source<TabContents>(contents));
[email protected]36b6dcb2008-11-12 01:19:571667}
1668
[email protected]85ff2c42009-05-29 21:22:031669void Browser::TabDeselectedAt(TabContents* contents, int index) {
1670 // Save what the user's currently typing, so it can be restored when we
1671 // switch back to this tab.
1672 window_->GetLocationBar()->SaveStateToContents(contents);
1673}
1674
[email protected]36b6dcb2008-11-12 01:19:571675void Browser::TabSelectedAt(TabContents* old_contents,
1676 TabContents* new_contents,
1677 int index,
1678 bool user_gesture) {
1679 DCHECK(old_contents != new_contents);
1680
1681 // If we have any update pending, do it now.
1682 if (!chrome_updater_factory_.empty() && old_contents)
1683 ProcessPendingUIUpdates();
1684
[email protected]36b6dcb2008-11-12 01:19:571685 // Propagate the profile to the location bar.
1686 UpdateToolbar(true);
1687
[email protected]64ff7942008-12-17 18:11:231688 // Update stop/go state.
[email protected]c3989812009-04-15 18:08:491689 UpdateStopGoState(new_contents->is_loading(), true);
[email protected]36b6dcb2008-11-12 01:19:571690
[email protected]84214982008-12-10 18:49:101691 // Update commands to reflect current state.
1692 UpdateCommandsForTabState();
[email protected]36b6dcb2008-11-12 01:19:571693
1694 // Reset the status bubble.
[email protected]be3877f2009-01-14 15:51:101695 StatusBubble* status_bubble = GetStatusBubble();
1696 if (status_bubble) {
1697 status_bubble->Hide();
[email protected]36b6dcb2008-11-12 01:19:571698
[email protected]be3877f2009-01-14 15:51:101699 // Show the loading state (if any).
1700 status_bubble->SetStatus(GetSelectedTabContents()->GetStatusText());
1701 }
[email protected]36b6dcb2008-11-12 01:19:571702
[email protected]4801ecc2009-04-05 04:52:581703 if (find_bar_controller_.get()) {
[email protected]57c6a652009-05-04 07:58:341704 find_bar_controller_->ChangeTabContents(new_contents);
[email protected]4801ecc2009-04-05 04:52:581705 find_bar_controller_->find_bar()->MoveWindowIfNecessary(gfx::Rect(),
1706 true);
1707 }
1708
[email protected]36b6dcb2008-11-12 01:19:571709 // Update sessions. Don't force creation of sessions. If sessions doesn't
1710 // exist, the change will be picked up by sessions when created.
1711 if (profile_->HasSessionService()) {
1712 SessionService* session_service = profile_->GetSessionService();
1713 if (session_service && !tabstrip_model_.closing_all()) {
[email protected]2d46c842008-11-14 19:24:311714 session_service->SetSelectedTabInWindow(
1715 session_id(), tabstrip_model_.selected_index());
[email protected]36b6dcb2008-11-12 01:19:571716 }
1717 }
1718}
1719
1720void Browser::TabMoved(TabContents* contents,
1721 int from_index,
[email protected]c8db09162009-07-13 23:48:481722 int to_index,
1723 bool pinned_state_changed) {
[email protected]36b6dcb2008-11-12 01:19:571724 DCHECK(from_index >= 0 && to_index >= 0);
1725 // Notify the history service.
1726 SyncHistoryWithTabs(std::min(from_index, to_index));
1727}
1728
[email protected]5c0e6482009-07-14 20:20:091729void Browser::TabPinnedStateChanged(TabContents* contents, int index) {
1730 if (!profile()->HasSessionService())
1731 return;
1732 SessionService* session_service = profile()->GetSessionService();
1733 if (session_service) {
1734 session_service->SetPinnedState(
1735 session_id(),
1736 GetTabContentsAt(index)->controller().session_id(),
1737 tabstrip_model_.IsTabPinned(index));
1738 }
1739}
1740
[email protected]36b6dcb2008-11-12 01:19:571741void Browser::TabStripEmpty() {
1742 // Close the frame after we return to the message loop (not immediately,
1743 // otherwise it will destroy this object before the stack has a chance to
1744 // cleanly unwind.)
1745 // Note: This will be called several times if TabStripEmpty is called several
1746 // times. This is because it does not close the window if tabs are
1747 // still present.
1748 // NOTE: If you change to be immediate (no invokeLater) then you'll need to
1749 // update BrowserList::CloseAllBrowsers.
1750 MessageLoop::current()->PostTask(FROM_HERE,
1751 method_factory_.NewRunnableMethod(&Browser::CloseFrame));
1752}
1753
1754///////////////////////////////////////////////////////////////////////////////
[email protected]e0c7c262009-04-23 23:09:431755// Browser, PageNavigator implementation:
1756void Browser::OpenURL(const GURL& url, const GURL& referrer,
1757 WindowOpenDisposition disposition,
1758 PageTransition::Type transition) {
1759 OpenURLFromTab(NULL, url, referrer, disposition, transition);
1760}
1761
1762///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:571763// Browser, TabContentsDelegate implementation:
initial.commit09911bf2008-07-26 23:55:291764
1765void Browser::OpenURLFromTab(TabContents* source,
[email protected]1f7d7e92009-06-02 20:55:041766 const GURL& url,
1767 const GURL& referrer,
initial.commit09911bf2008-07-26 23:55:291768 WindowOpenDisposition disposition,
[email protected]e38f40152008-09-12 23:08:301769 PageTransition::Type transition) {
[email protected]1f7d7e92009-06-02 20:55:041770 OpenURLAtIndex(source, url, referrer, disposition, transition, -1, false);
initial.commit09911bf2008-07-26 23:55:291771}
1772
1773void Browser::NavigationStateChanged(const TabContents* source,
1774 unsigned changed_flags) {
initial.commit09911bf2008-07-26 23:55:291775 // Only update the UI when something visible has changed.
[email protected]e83f1682008-09-07 23:57:401776 if (changed_flags)
initial.commit09911bf2008-07-26 23:55:291777 ScheduleUIUpdate(source, changed_flags);
1778
[email protected]84214982008-12-10 18:49:101779 // We don't schedule updates to commands since they will only change once per
1780 // navigation, so we don't have to worry about flickering.
[email protected]e83f1682008-09-07 23:57:401781 if (changed_flags & TabContents::INVALIDATE_URL)
[email protected]84214982008-12-10 18:49:101782 UpdateCommandsForTabState();
initial.commit09911bf2008-07-26 23:55:291783}
1784
initial.commit09911bf2008-07-26 23:55:291785void Browser::AddNewContents(TabContents* source,
1786 TabContents* new_contents,
1787 WindowOpenDisposition disposition,
1788 const gfx::Rect& initial_pos,
1789 bool user_gesture) {
1790 DCHECK(disposition != SAVE_TO_DISK); // No code for this yet
[email protected]b680ad22009-04-15 23:19:421791 DCHECK(disposition != CURRENT_TAB); // Can't create a new contents for the
1792 // current tab.
initial.commit09911bf2008-07-26 23:55:291793
1794 // If this is an application we can only have one tab so we need to process
[email protected]ebdcf9742009-01-23 05:25:281795 // this in tabbed browser window.
1796 if (tabstrip_model_.count() > 0 &&
initial.commit09911bf2008-07-26 23:55:291797 disposition != NEW_WINDOW && disposition != NEW_POPUP &&
[email protected]299dabd2008-11-19 02:27:161798 type_ != TYPE_NORMAL) {
[email protected]1a6b30a2009-08-19 03:52:111799 Browser* b = GetOrCreateTabbedBrowser(profile_);
initial.commit09911bf2008-07-26 23:55:291800 DCHECK(b);
1801 PageTransition::Type transition = PageTransition::LINK;
1802 // If we were called from an "installed webapp" we want to emulate the code
1803 // that is run from browser_init.cc for links from external applications.
1804 // This means we need to open the tab with the START PAGE transition.
1805 // AddNewContents doesn't support this but the TabStripModel's
1806 // AddTabContents method does.
[email protected]d5fbc002009-02-27 22:12:581807 if (type_ & TYPE_APP)
initial.commit09911bf2008-07-26 23:55:291808 transition = PageTransition::START_PAGE;
[email protected]4d34e2e2009-05-26 22:55:281809 b->tabstrip_model()->AddTabContents(new_contents, -1, false, transition,
1810 true);
[email protected]ebdcf9742009-01-23 05:25:281811 b->window()->Show();
initial.commit09911bf2008-07-26 23:55:291812 return;
1813 }
1814
1815 if (disposition == NEW_POPUP) {
1816 BuildPopupWindow(source, new_contents, initial_pos);
1817 } else if (disposition == NEW_WINDOW) {
[email protected]15952e462008-11-14 00:29:051818 Browser* browser = Browser::Create(profile_);
1819 browser->AddNewContents(source, new_contents, NEW_FOREGROUND_TAB,
1820 initial_pos, user_gesture);
1821 browser->window()->Show();
initial.commit09911bf2008-07-26 23:55:291822 } else if (disposition != SUPPRESS_OPEN) {
[email protected]4d34e2e2009-05-26 22:55:281823 tabstrip_model_.AddTabContents(new_contents, -1, false,
1824 PageTransition::LINK,
initial.commit09911bf2008-07-26 23:55:291825 disposition == NEW_FOREGROUND_TAB);
1826 }
1827}
1828
initial.commit09911bf2008-07-26 23:55:291829void Browser::ActivateContents(TabContents* contents) {
1830 tabstrip_model_.SelectTabContentsAt(
1831 tabstrip_model_.GetIndexOfTabContents(contents), false);
[email protected]f3e99e32008-07-30 04:48:391832 window_->Activate();
initial.commit09911bf2008-07-26 23:55:291833}
1834
initial.commit09911bf2008-07-26 23:55:291835void Browser::LoadingStateChanged(TabContents* source) {
[email protected]afb73882008-11-14 22:40:441836 window_->UpdateLoadingAnimations(tabstrip_model_.TabsAreLoading());
[email protected]f3e99e32008-07-30 04:48:391837 window_->UpdateTitleBar();
initial.commit09911bf2008-07-26 23:55:291838
initial.commit09911bf2008-07-26 23:55:291839 if (source == GetSelectedTabContents()) {
[email protected]c3989812009-04-15 18:08:491840 UpdateStopGoState(source->is_loading(), false);
[email protected]be3877f2009-01-14 15:51:101841 if (GetStatusBubble())
1842 GetStatusBubble()->SetStatus(GetSelectedTabContents()->GetStatusText());
initial.commit09911bf2008-07-26 23:55:291843 }
1844}
1845
1846void Browser::CloseContents(TabContents* source) {
[email protected]04b4a6c2008-08-02 00:44:471847 if (is_attempting_to_close_browser_) {
1848 // If we're trying to close the browser, just clear the state related to
[email protected]adf650f2008-12-09 16:10:061849 // waiting for unload to fire. Don't actually try to close the tab as it
[email protected]04b4a6c2008-08-02 00:44:471850 // will go down the slow shutdown path instead of the fast path of killing
1851 // all the renderer processes.
[email protected]8a2ce5a2008-08-11 23:43:081852 ClearUnloadState(source);
[email protected]04b4a6c2008-08-02 00:44:471853 return;
1854 }
1855
initial.commit09911bf2008-07-26 23:55:291856 int index = tabstrip_model_.GetIndexOfTabContents(source);
1857 if (index == TabStripModel::kNoTab) {
1858 NOTREACHED() << "CloseContents called for tab not in our strip";
1859 return;
1860 }
1861 tabstrip_model_.CloseTabContentsAt(index);
1862}
1863
[email protected]15e8abe2008-08-20 22:40:401864void Browser::MoveContents(TabContents* source, const gfx::Rect& pos) {
[email protected]d5fbc002009-02-27 22:12:581865 if ((type() & TYPE_POPUP) == 0) {
initial.commit09911bf2008-07-26 23:55:291866 NOTREACHED() << "moving invalid browser type";
1867 return;
1868 }
[email protected]2d46c842008-11-14 19:24:311869 window_->SetBounds(pos);
initial.commit09911bf2008-07-26 23:55:291870}
1871
[email protected]b6c874582009-05-08 19:38:311872void Browser::DetachContents(TabContents* source) {
1873 int index = tabstrip_model_.GetIndexOfTabContents(source);
1874 if (index >= 0)
1875 tabstrip_model_.DetachTabContentsAt(index);
1876}
1877
initial.commit09911bf2008-07-26 23:55:291878bool Browser::IsPopup(TabContents* source) {
1879 // A non-tabbed BROWSER is an unconstrained popup.
[email protected]d5fbc002009-02-27 22:12:581880 return (type() & TYPE_POPUP);
initial.commit09911bf2008-07-26 23:55:291881}
1882
[email protected]36b6dcb2008-11-12 01:19:571883void Browser::ToolbarSizeChanged(TabContents* source, bool is_animating) {
1884 if (source == GetSelectedTabContents() || source == NULL) {
1885 // This will refresh the shelf if needed.
1886 window_->SelectedTabToolbarSizeChanged(is_animating);
1887 }
1888}
1889
1890void Browser::URLStarredChanged(TabContents* source, bool starred) {
1891 if (source == GetSelectedTabContents())
[email protected]b7ca4e62009-01-23 20:37:291892 window_->SetStarredState(starred);
[email protected]36b6dcb2008-11-12 01:19:571893}
1894
[email protected]b6406032009-03-19 15:10:151895void Browser::ContentsMouseEvent(TabContents* source, bool motion) {
[email protected]be3877f2009-01-14 15:51:101896 if (!GetStatusBubble())
1897 return;
1898
[email protected]36b6dcb2008-11-12 01:19:571899 if (source == GetSelectedTabContents()) {
[email protected]b6406032009-03-19 15:10:151900 if (motion) {
[email protected]36b6dcb2008-11-12 01:19:571901 GetStatusBubble()->MouseMoved();
[email protected]b6406032009-03-19 15:10:151902 } else {
[email protected]36b6dcb2008-11-12 01:19:571903 GetStatusBubble()->SetURL(GURL(), std::wstring());
1904 }
1905 }
1906}
1907
1908void Browser::UpdateTargetURL(TabContents* source, const GURL& url) {
[email protected]be3877f2009-01-14 15:51:101909 if (!GetStatusBubble())
1910 return;
1911
[email protected]36b6dcb2008-11-12 01:19:571912 if (source == GetSelectedTabContents()) {
1913 PrefService* prefs = profile_->GetPrefs();
1914 GetStatusBubble()->SetURL(url, prefs->GetString(prefs::kAcceptLanguages));
1915 }
1916}
1917
[email protected]3a6a3b62009-05-27 21:36:201918void Browser::UpdateDownloadShelfVisibility(bool visible) {
[email protected]9b032bf2009-07-21 17:34:231919 if (GetStatusBubble())
1920 GetStatusBubble()->UpdateDownloadShelfVisibility(visible);
[email protected]3a6a3b62009-05-27 21:36:201921}
1922
[email protected]36b6dcb2008-11-12 01:19:571923void Browser::ContentsZoomChange(bool zoom_in) {
[email protected]1fc025202009-01-20 23:03:141924 ExecuteCommand(zoom_in ? IDC_ZOOM_PLUS : IDC_ZOOM_MINUS);
[email protected]36b6dcb2008-11-12 01:19:571925}
1926
[email protected]7e383692009-06-12 19:14:541927void Browser::TabContentsFocused(TabContents* tab_content) {
1928 window_->TabContentsFocused(tab_content);
1929}
1930
[email protected]36b6dcb2008-11-12 01:19:571931bool Browser::IsApplication() const {
[email protected]d5fbc002009-02-27 22:12:581932 return (type_ & TYPE_APP) != 0;
[email protected]36b6dcb2008-11-12 01:19:571933}
1934
1935void Browser::ConvertContentsToApplication(TabContents* contents) {
[email protected]ce3fa3c2009-04-20 19:55:571936 const GURL& url = contents->controller().GetActiveEntry()->url();
[email protected]0303f31c2009-02-02 06:42:051937 std::wstring app_name = ComputeApplicationNameFromURL(url);
[email protected]36b6dcb2008-11-12 01:19:571938 RegisterAppPrefs(app_name);
1939
[email protected]b6c874582009-05-08 19:38:311940 DetachContents(contents);
[email protected]d5fbc002009-02-27 22:12:581941 Browser* browser = Browser::CreateForApp(app_name, profile_, false);
[email protected]15952e462008-11-14 00:29:051942 browser->tabstrip_model()->AppendTabContents(contents, true);
[email protected]840b1512009-07-21 16:53:461943 TabContents* tab_contents = browser->GetSelectedTabContents();
1944 tab_contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
1945 tab_contents->render_view_host()->SyncRendererPrefs();
[email protected]15952e462008-11-14 00:29:051946 browser->window()->Show();
[email protected]36b6dcb2008-11-12 01:19:571947}
1948
[email protected]36b6dcb2008-11-12 01:19:571949bool Browser::ShouldDisplayURLField() {
1950 return !IsApplication();
1951}
1952
1953void Browser::BeforeUnloadFired(TabContents* tab,
1954 bool proceed,
1955 bool* proceed_to_fire_unload) {
1956 if (!is_attempting_to_close_browser_) {
1957 *proceed_to_fire_unload = proceed;
1958 return;
1959 }
1960
1961 if (!proceed) {
1962 CancelWindowClose();
1963 *proceed_to_fire_unload = false;
1964 return;
1965 }
1966
[email protected]06b42f032008-12-03 18:43:051967 if (RemoveFromSet(&tabs_needing_before_unload_fired_, tab)) {
[email protected]2d46c842008-11-14 19:24:311968 // Now that beforeunload has fired, put the tab on the queue to fire
1969 // unload.
[email protected]06b42f032008-12-03 18:43:051970 tabs_needing_unload_fired_.insert(tab);
[email protected]36b6dcb2008-11-12 01:19:571971 ProcessPendingTabs();
[email protected]adf650f2008-12-09 16:10:061972 // We want to handle firing the unload event ourselves since we want to
[email protected]36b6dcb2008-11-12 01:19:571973 // fire all the beforeunload events before attempting to fire the unload
1974 // events should the user cancel closing the browser.
1975 *proceed_to_fire_unload = false;
1976 return;
1977 }
1978
1979 *proceed_to_fire_unload = true;
1980}
1981
[email protected]f21c613a2009-02-12 14:46:171982gfx::Rect Browser::GetRootWindowResizerRect() const {
1983 return window_->GetRootWindowResizerRect();
1984}
1985
[email protected]4acc19a62009-04-03 03:05:111986void Browser::ShowHtmlDialog(HtmlDialogUIDelegate* delegate,
[email protected]322f3ff2009-05-22 16:19:541987 gfx::NativeWindow parent_window) {
[email protected]2d46c842008-11-14 19:24:311988 window_->ShowHTMLDialog(delegate, parent_window);
initial.commit09911bf2008-07-26 23:55:291989}
1990
[email protected]4bcefee2009-01-29 15:57:571991void Browser::SetFocusToLocationBar() {
[email protected]1a380622009-02-17 17:33:131992 // Two differences between this and FocusLocationBar():
1993 // (1) This doesn't get recorded in user metrics, since it's called
1994 // internally.
1995 // (2) This checks whether the location bar can be focused, and if not, clears
1996 // the focus. FocusLocationBar() is only reached when the location bar is
1997 // focusable, but this may be reached at other times, e.g. while in
1998 // fullscreen mode, where we need to leave focus in a consistent state.
1999 window_->SetFocusToLocationBar();
[email protected]4bcefee2009-01-29 15:57:572000}
2001
[email protected]7d5925a2009-03-03 02:59:122002void Browser::RenderWidgetShowing() {
2003 window_->DisableInactiveFrame();
2004}
[email protected]a239c3f2009-02-17 22:13:192005
[email protected]0a2aeb82009-05-15 21:52:482006int Browser::GetExtraRenderViewHeight() const {
2007 return window_->GetExtraRenderViewHeight();
2008}
2009
[email protected]d0cc9fb52009-06-23 02:26:162010void Browser::OnStartDownload(DownloadItem* download) {
2011 if (!window())
2012 return;
2013
2014 // GetDownloadShelf creates the download shelf if it was not yet created.
2015 window()->GetDownloadShelf()->AddDownload(new DownloadItemModel(download));
2016
[email protected]d0cc9fb52009-06-23 02:26:162017 // Don't show the animation for "Save file" downloads.
2018 if (download->total_bytes() > 0) {
2019 TabContents* current_tab = GetSelectedTabContents();
2020 // We make this check for the case of minimized windows, unit tests, etc.
2021 if (platform_util::IsVisible(current_tab->GetNativeView()) &&
2022 Animation::ShouldRenderRichAnimation())
2023 DownloadStartedAnimation::Show(current_tab);
2024 }
[email protected]d0cc9fb52009-06-23 02:26:162025}
2026
2027void Browser::ConfirmAddSearchProvider(const TemplateURL* template_url,
2028 Profile* profile) {
2029 window()->ConfirmAddSearchProvider(template_url, profile);
2030}
2031
[email protected]bb678332009-07-21 00:15:502032void Browser::ShowPageInfo(Profile* profile,
[email protected]4d677202009-07-19 07:37:122033 const GURL& url,
2034 const NavigationEntry::SSLStatus& ssl,
2035 bool show_history) {
[email protected]bb678332009-07-21 00:15:502036 window()->ShowPageInfo(profile, url, ssl, show_history);
[email protected]4d677202009-07-19 07:37:122037}
2038
[email protected]36b6dcb2008-11-12 01:19:572039///////////////////////////////////////////////////////////////////////////////
2040// Browser, SelectFileDialog::Listener implementation:
2041
[email protected]561abe62009-04-06 18:08:342042void Browser::FileSelected(const FilePath& path, int index, void* params) {
[email protected]72cbd322009-04-07 10:17:122043 GURL file_url = net::FilePathToFileURL(path);
[email protected]36b6dcb2008-11-12 01:19:572044 if (!file_url.is_empty())
2045 OpenURL(file_url, GURL(), CURRENT_TAB, PageTransition::TYPED);
2046}
2047
[email protected]a239c3f2009-02-17 22:13:192048
[email protected]36b6dcb2008-11-12 01:19:572049///////////////////////////////////////////////////////////////////////////////
2050// Browser, NotificationObserver implementation:
2051
initial.commit09911bf2008-07-26 23:55:292052void Browser::Observe(NotificationType type,
2053 const NotificationSource& source,
2054 const NotificationDetails& details) {
[email protected]bfd04a62009-02-01 18:16:562055 switch (type.value) {
[email protected]57c6a652009-05-04 07:58:342056 case NotificationType::TAB_CONTENTS_DISCONNECTED:
[email protected]e83f1682008-09-07 23:57:402057 if (is_attempting_to_close_browser_) {
2058 // Need to do this asynchronously as it will close the tab, which is
2059 // currently on the call stack above us.
2060 MessageLoop::current()->PostTask(FROM_HERE,
2061 method_factory_.NewRunnableMethod(&Browser::ClearUnloadState,
2062 Source<TabContents>(source).ptr()));
2063 }
2064 break;
2065
[email protected]b4a19ea2009-03-17 10:08:242066 case NotificationType::SSL_VISIBLE_STATE_CHANGED:
[email protected]e83f1682008-09-07 23:57:402067 // When the current tab's SSL state changes, we need to update the URL
[email protected]90e8d062008-09-08 02:26:322068 // bar to reflect the new state. Note that it's possible for the selected
2069 // tab contents to be NULL. This is because we listen for all sources
2070 // (NavigationControllers) for convenience, so the notification could
2071 // actually be for a different window while we're doing asynchronous
2072 // closing of this one.
2073 if (GetSelectedTabContents() &&
[email protected]ce3fa3c2009-04-20 19:55:572074 &GetSelectedTabContents()->controller() ==
[email protected]e83f1682008-09-07 23:57:402075 Source<NavigationController>(source).ptr())
[email protected]36b6dcb2008-11-12 01:19:572076 UpdateToolbar(false);
[email protected]e83f1682008-09-07 23:57:402077 break;
2078
[email protected]0c6da502009-08-14 22:32:392079 case NotificationType::EXTENSION_UPDATE_DISABLED: {
2080 // Show the UI.
2081 ExtensionsService* service = Source<ExtensionsService>(source).ptr();
2082 Extension* extension = Details<Extension>(details).ptr();
2083 ShowExtensionDisabledUI(service, profile_, extension);
2084 break;
2085 }
2086
[email protected]894bb502009-05-21 22:39:572087 case NotificationType::EXTENSION_UNLOADED: {
2088 // Close any tabs from the unloaded extension.
2089 Extension* extension = Details<Extension>(details).ptr();
2090 for (int i = 0; i < tabstrip_model_.count(); i++) {
2091 TabContents* tc = tabstrip_model_.GetTabContentsAt(i);
2092 if (tc->GetURL().SchemeIs(chrome::kExtensionScheme) &&
2093 tc->GetURL().host() == extension->id()) {
2094 CloseTabContents(tc);
2095 return;
2096 }
2097 }
2098 break;
2099 }
2100
[email protected]371ed7a2009-08-25 15:22:462101 case NotificationType::EXTENSION_PROCESS_CRASHED: {
2102 TabContents* tab_contents = GetSelectedTabContents();
2103 if (!tab_contents)
2104 break;
2105 ExtensionsService* extensions_service =
2106 Source<ExtensionsService>(source).ptr();
2107 ExtensionHost* extension_host = Details<ExtensionHost>(details).ptr();
2108 tab_contents->AddInfoBar(new CrashedExtensionInfoBarDelegate(
2109 tab_contents, extensions_service, extension_host->extension()));
2110 break;
2111 }
2112
[email protected]e001d412009-06-26 20:53:252113 case NotificationType::BROWSER_THEME_CHANGED:
2114 window()->UserChangedTheme();
2115 break;
2116
[email protected]e83f1682008-09-07 23:57:402117 default:
2118 NOTREACHED() << "Got a notification we didn't register for.";
initial.commit09911bf2008-07-26 23:55:292119 }
2120}
2121
[email protected]88d74942009-01-21 22:04:442122
[email protected]36b6dcb2008-11-12 01:19:572123///////////////////////////////////////////////////////////////////////////////
2124// Browser, Command and state updating (private):
2125
2126void Browser::InitCommandState() {
2127 // All browser commands whose state isn't set automagically some other way
2128 // (like Back & Forward with initial page load) must have their state
2129 // initialized here, otherwise they will be forever disabled.
2130
[email protected]84214982008-12-10 18:49:102131 // Navigation commands
[email protected]1fc025202009-01-20 23:03:142132 command_updater_.UpdateCommandEnabled(IDC_RELOAD, true);
[email protected]84214982008-12-10 18:49:102133
2134 // Window management commands
[email protected]1fc025202009-01-20 23:03:142135 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW, true);
2136 command_updater_.UpdateCommandEnabled(IDC_NEW_INCOGNITO_WINDOW, true);
[email protected]84214982008-12-10 18:49:102137 // TODO(pkasting): Perhaps the code that populates this submenu should do
2138 // this?
[email protected]1fc025202009-01-20 23:03:142139 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW_PROFILE_0, true);
2140 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW_PROFILE_1, true);
2141 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW_PROFILE_2, true);
2142 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW_PROFILE_3, true);
2143 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW_PROFILE_4, true);
2144 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW_PROFILE_5, true);
2145 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW_PROFILE_6, true);
2146 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW_PROFILE_7, true);
2147 command_updater_.UpdateCommandEnabled(IDC_NEW_WINDOW_PROFILE_8, true);
2148 command_updater_.UpdateCommandEnabled(IDC_CLOSE_WINDOW, true);
2149 command_updater_.UpdateCommandEnabled(IDC_NEW_TAB, true);
2150 command_updater_.UpdateCommandEnabled(IDC_CLOSE_TAB, true);
2151 command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB, true);
[email protected]9282cea2009-02-18 18:49:002152 command_updater_.UpdateCommandEnabled(IDC_FULLSCREEN, true);
[email protected]1fc025202009-01-20 23:03:142153 command_updater_.UpdateCommandEnabled(IDC_EXIT, true);
[email protected]84214982008-12-10 18:49:102154
2155 // Page-related commands
[email protected]1fc025202009-01-20 23:03:142156 command_updater_.UpdateCommandEnabled(IDC_CLOSE_POPUPS, true);
[email protected]e662ade2009-06-08 18:20:142157 command_updater_.UpdateCommandEnabled(IDC_PRINT, true);
[email protected]1fc025202009-01-20 23:03:142158 command_updater_.UpdateCommandEnabled(IDC_ENCODING_AUTO_DETECT, true);
2159 command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF8, true);
2160 command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF16LE, true);
2161 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88591, true);
2162 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1252, true);
2163 command_updater_.UpdateCommandEnabled(IDC_ENCODING_GBK, true);
2164 command_updater_.UpdateCommandEnabled(IDC_ENCODING_GB18030, true);
2165 command_updater_.UpdateCommandEnabled(IDC_ENCODING_BIG5HKSCS, true);
2166 command_updater_.UpdateCommandEnabled(IDC_ENCODING_BIG5, true);
2167 command_updater_.UpdateCommandEnabled(IDC_ENCODING_THAI, true);
2168 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOREAN, true);
2169 command_updater_.UpdateCommandEnabled(IDC_ENCODING_SHIFTJIS, true);
2170 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO2022JP, true);
2171 command_updater_.UpdateCommandEnabled(IDC_ENCODING_EUCJP, true);
2172 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885915, true);
2173 command_updater_.UpdateCommandEnabled(IDC_ENCODING_MACINTOSH, true);
2174 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88592, true);
2175 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1250, true);
2176 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88595, true);
2177 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1251, true);
2178 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8R, true);
2179 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8U, true);
2180 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88597, true);
2181 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1253, true);
2182 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88594, true);
2183 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885913, true);
2184 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1257, true);
2185 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88593, true);
2186 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885910, true);
2187 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885914, true);
2188 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885916, true);
2189 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1254, true);
2190 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88596, true);
2191 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1256, true);
2192 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598, true);
[email protected]e13271f2009-03-07 00:26:002193 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598I, true);
[email protected]1fc025202009-01-20 23:03:142194 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1255, true);
2195 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1258, true);
[email protected]84214982008-12-10 18:49:102196
2197 // Clipboard commands
[email protected]1fc025202009-01-20 23:03:142198 command_updater_.UpdateCommandEnabled(IDC_CUT, true);
2199 command_updater_.UpdateCommandEnabled(IDC_COPY, true);
[email protected]1fc025202009-01-20 23:03:142200 command_updater_.UpdateCommandEnabled(IDC_PASTE, true);
[email protected]84214982008-12-10 18:49:102201
[email protected]63b02932009-06-05 09:40:512202 // Find-in-page
2203 command_updater_.UpdateCommandEnabled(IDC_FIND, true);
2204 command_updater_.UpdateCommandEnabled(IDC_FIND_NEXT, true);
2205 command_updater_.UpdateCommandEnabled(IDC_FIND_PREVIOUS, true);
2206
2207 // Zoom
2208 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MENU, true);
2209 command_updater_.UpdateCommandEnabled(IDC_ZOOM_PLUS, true);
2210 command_updater_.UpdateCommandEnabled(IDC_ZOOM_NORMAL, true);
2211 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MINUS, true);
2212
[email protected]84214982008-12-10 18:49:102213 // Show various bits of UI
[email protected]1fc025202009-01-20 23:03:142214 command_updater_.UpdateCommandEnabled(IDC_OPEN_FILE, true);
2215 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS, false);
[email protected]c630f162009-07-22 09:41:332216 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS, true);
[email protected]1fc025202009-01-20 23:03:142217 command_updater_.UpdateCommandEnabled(IDC_TASK_MANAGER, true);
2218 command_updater_.UpdateCommandEnabled(IDC_SELECT_PROFILE, true);
2219 command_updater_.UpdateCommandEnabled(IDC_SHOW_HISTORY, true);
2220 command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER, true);
2221 command_updater_.UpdateCommandEnabled(IDC_SHOW_DOWNLOADS, true);
2222 command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE, true);
[email protected]16779842009-07-08 23:45:292223#if defined(OS_CHROMEOS)
[email protected]be715072009-07-07 15:43:202224 command_updater_.UpdateCommandEnabled(IDC_CONTROL_PANEL, true);
2225#endif
[email protected]64ff7942008-12-17 18:11:232226
2227 // Initialize other commands based on the window type.
2228 {
2229 bool normal_window = type() == TYPE_NORMAL;
2230
2231 // Navigation commands
[email protected]1fc025202009-01-20 23:03:142232 command_updater_.UpdateCommandEnabled(IDC_HOME, normal_window);
[email protected]64ff7942008-12-17 18:11:232233
2234 // Window management commands
[email protected]1fc025202009-01-20 23:03:142235 command_updater_.UpdateCommandEnabled(IDC_SELECT_NEXT_TAB, normal_window);
2236 command_updater_.UpdateCommandEnabled(IDC_SELECT_PREVIOUS_TAB,
2237 normal_window);
2238 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_0, normal_window);
2239 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_1, normal_window);
2240 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_2, normal_window);
2241 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_3, normal_window);
2242 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_4, normal_window);
2243 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_5, normal_window);
2244 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_6, normal_window);
2245 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_7, normal_window);
2246 command_updater_.UpdateCommandEnabled(IDC_SELECT_LAST_TAB, normal_window);
2247 command_updater_.UpdateCommandEnabled(IDC_RESTORE_TAB,
[email protected]64ff7942008-12-17 18:11:232248 normal_window && !profile_->IsOffTheRecord());
[email protected]e662ade2009-06-08 18:20:142249
2250 // Page-related commands
[email protected]63b02932009-06-05 09:40:512251 command_updater_.UpdateCommandEnabled(IDC_STAR, normal_window);
[email protected]e662ade2009-06-08 18:20:142252
2253 // Clipboard commands
[email protected]63b02932009-06-05 09:40:512254 command_updater_.UpdateCommandEnabled(IDC_COPY_URL, normal_window);
[email protected]d5c99b172009-02-25 17:09:212255
2256 // Show various bits of UI
[email protected]7fd4cc32009-04-15 23:17:372257 command_updater_.UpdateCommandEnabled(IDC_CLEAR_BROWSING_DATA,
2258 normal_window);
[email protected]64ff7942008-12-17 18:11:232259 }
[email protected]9282cea2009-02-18 18:49:002260
2261 // Initialize other commands whose state changes based on fullscreen mode.
2262 UpdateCommandsForFullscreenMode(false);
[email protected]36b6dcb2008-11-12 01:19:572263}
2264
[email protected]84214982008-12-10 18:49:102265void Browser::UpdateCommandsForTabState() {
[email protected]c7c42332008-11-15 01:10:542266 TabContents* current_tab = GetSelectedTabContents();
[email protected]64ff7942008-12-17 18:11:232267 if (!current_tab) // May be NULL during tab restore.
[email protected]d8375fd2008-11-25 22:45:392268 return;
[email protected]d8375fd2008-11-25 22:45:392269
[email protected]84214982008-12-10 18:49:102270 // Navigation commands
[email protected]ce3fa3c2009-04-20 19:55:572271 NavigationController& nc = current_tab->controller();
2272 command_updater_.UpdateCommandEnabled(IDC_BACK, nc.CanGoBack());
2273 command_updater_.UpdateCommandEnabled(IDC_FORWARD, nc.CanGoForward());
initial.commit09911bf2008-07-26 23:55:292274
[email protected]84214982008-12-10 18:49:102275 // Window management commands
[email protected]1fc025202009-01-20 23:03:142276 command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB,
[email protected]63b02932009-06-05 09:40:512277 !(type() & TYPE_APP) && CanDuplicateContentsAt(selected_index()));
[email protected]84214982008-12-10 18:49:102278
[email protected]57c6a652009-05-04 07:58:342279 // Current navigation entry, may be NULL.
2280 NavigationEntry* active_entry = current_tab->controller().GetActiveEntry();
[email protected]2bfd94d2009-04-29 20:32:032281 bool is_source_viewable =
[email protected]2bfd94d2009-04-29 20:32:032282 net::IsSupportedNonImageMimeType(
[email protected]57c6a652009-05-04 07:58:342283 current_tab->contents_mime_type().c_str());
[email protected]84214982008-12-10 18:49:102284
[email protected]57c6a652009-05-04 07:58:342285 // Page-related commands
[email protected]57c6a652009-05-04 07:58:342286 window_->SetStarredState(current_tab->is_starred());
2287 // View-source should not be enabled if already in view-source mode or
2288 // the source is not viewable.
2289 command_updater_.UpdateCommandEnabled(IDC_VIEW_SOURCE,
2290 active_entry && !active_entry->IsViewSourceMode() &&
2291 is_source_viewable);
[email protected]4d07cdc2009-08-22 16:09:392292
2293 // Instead of using GetURL here, we use url() (which is the "real" url of the
2294 // page) from the NavigationEntry because its reflects their origin rather
2295 // than the display one (returned by GetURL) which may be different (like
2296 // having "view-source:" on the front).
2297 GURL savable_url = (active_entry) ? active_entry->url() : GURL::EmptyGURL();
2298
[email protected]57c6a652009-05-04 07:58:342299 command_updater_.UpdateCommandEnabled(IDC_SAVE_PAGE,
[email protected]4d07cdc2009-08-22 16:09:392300 SavePackage::IsSavableURL(savable_url));
[email protected]57c6a652009-05-04 07:58:342301 command_updater_.UpdateCommandEnabled(IDC_ENCODING_MENU,
2302 SavePackage::IsSavableContents(current_tab->contents_mime_type()) &&
[email protected]4d07cdc2009-08-22 16:09:392303 SavePackage::IsSavableURL(savable_url));
[email protected]6de74452009-02-25 18:04:592304
[email protected]57c6a652009-05-04 07:58:342305 // Show various bits of UI
[email protected]57c6a652009-05-04 07:58:342306 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS,
2307 !current_tab->GetFavIcon().isNull());
initial.commit09911bf2008-07-26 23:55:292308}
2309
[email protected]c3989812009-04-15 18:08:492310void Browser::UpdateStopGoState(bool is_loading, bool force) {
2311 window_->UpdateStopGoState(is_loading, force);
[email protected]1fc025202009-01-20 23:03:142312 command_updater_.UpdateCommandEnabled(IDC_GO, !is_loading);
2313 command_updater_.UpdateCommandEnabled(IDC_STOP, is_loading);
[email protected]64ff7942008-12-17 18:11:232314}
2315
[email protected]d938aed92009-01-22 19:49:332316
[email protected]36b6dcb2008-11-12 01:19:572317///////////////////////////////////////////////////////////////////////////////
2318// Browser, UI update coalescing and handling (private):
2319
2320void Browser::UpdateToolbar(bool should_restore_state) {
2321 window_->UpdateToolbar(GetSelectedTabContents(), should_restore_state);
initial.commit09911bf2008-07-26 23:55:292322}
2323
[email protected]36b6dcb2008-11-12 01:19:572324void Browser::ScheduleUIUpdate(const TabContents* source,
2325 unsigned changed_flags) {
[email protected]2b4355c2009-04-04 17:55:462326 // Do some synchronous updates.
[email protected]36b6dcb2008-11-12 01:19:572327 if (changed_flags & TabContents::INVALIDATE_URL &&
2328 source == GetSelectedTabContents()) {
2329 // Only update the URL for the current tab. Note that we do not update
2330 // the navigation commands since those would have already been updated
2331 // synchronously by NavigationStateChanged.
2332 UpdateToolbar(false);
[email protected]36b6dcb2008-11-12 01:19:572333 }
[email protected]2b4355c2009-04-04 17:55:462334 if (changed_flags & TabContents::INVALIDATE_LOAD && source) {
2335 // Update the loading state synchronously. This is so the throbber will
2336 // immediately start/stop, which gives a more snappy feel. We want to do
2337 // this for any tab so they start & stop quickly, but the source can be
2338 // NULL, so we have to check for that.
2339 tabstrip_model_.UpdateTabContentsStateAt(
[email protected]902cdf772009-05-06 15:08:122340 tabstrip_model_.GetIndexOfController(&source->controller()), true);
[email protected]2b4355c2009-04-04 17:55:462341 }
2342
2343 // If the only updates were synchronously handled above, we're done.
2344 if (changed_flags ==
2345 (TabContents::INVALIDATE_URL | TabContents::INVALIDATE_LOAD))
2346 return;
[email protected]36b6dcb2008-11-12 01:19:572347
2348 // Save the dirty bits.
2349 scheduled_updates_.push_back(UIUpdate(source, changed_flags));
2350
2351 if (chrome_updater_factory_.empty()) {
2352 // No task currently scheduled, start another.
2353 MessageLoop::current()->PostDelayedTask(FROM_HERE,
2354 chrome_updater_factory_.NewRunnableMethod(
2355 &Browser::ProcessPendingUIUpdates),
2356 kUIUpdateCoalescingTimeMS);
2357 }
2358}
2359
2360void Browser::ProcessPendingUIUpdates() {
2361#ifndef NDEBUG
2362 // Validate that all tabs we have pending updates for exist. This is scary
2363 // because the pending list must be kept in sync with any detached or
2364 // deleted tabs. This code does not dereference any TabContents pointers.
2365 for (size_t i = 0; i < scheduled_updates_.size(); i++) {
2366 bool found = false;
2367 for (int tab = 0; tab < tab_count(); tab++) {
[email protected]ce3fa3c2009-04-20 19:55:572368 if (&GetTabContentsAt(tab)->controller() ==
2369 &scheduled_updates_[i].source->controller()) {
[email protected]36b6dcb2008-11-12 01:19:572370 found = true;
2371 break;
2372 }
2373 }
2374 DCHECK(found);
2375 }
2376#endif
2377
2378 chrome_updater_factory_.RevokeAll();
2379
[email protected]2d46c842008-11-14 19:24:312380 // We could have many updates for the same thing in the queue. This map
2381 // tracks the bits of the stuff we've already updated for each TabContents so
2382 // we don't update again.
[email protected]36b6dcb2008-11-12 01:19:572383 typedef std::map<const TabContents*, unsigned> UpdateTracker;
2384 UpdateTracker updated_stuff;
2385
2386 for (size_t i = 0; i < scheduled_updates_.size(); i++) {
2387 // Do not dereference |contents|, it may be out-of-date!
2388 const TabContents* contents = scheduled_updates_[i].source;
2389 unsigned flags = scheduled_updates_[i].changed_flags;
2390
2391 // Remove any bits we have already updated, and save the new bits.
2392 UpdateTracker::iterator updated = updated_stuff.find(contents);
2393 if (updated != updated_stuff.end()) {
2394 // Turn off bits already set.
2395 flags &= ~updated->second;
2396 if (!flags)
2397 continue;
2398
2399 updated->second |= flags;
2400 } else {
2401 updated_stuff[contents] = flags;
2402 }
2403
[email protected]f7f3a5f2009-05-01 22:02:342404 if (flags & TabContents::INVALIDATE_PAGE_ACTIONS)
2405 window()->GetLocationBar()->UpdatePageActions();
2406
[email protected]36b6dcb2008-11-12 01:19:572407 // Updating the URL happens synchronously in ScheduleUIUpdate.
[email protected]ba8c48212009-05-12 21:20:402408 TabContents* selected_tab = GetSelectedTabContents();
[email protected]4d34e2e2009-05-26 22:55:282409 if (selected_tab &&
2410 flags & TabContents::INVALIDATE_LOAD && GetStatusBubble()) {
[email protected]ba8c48212009-05-12 21:20:402411 GetStatusBubble()->SetStatus(selected_tab->GetStatusText());
[email protected]4d34e2e2009-05-26 22:55:282412 }
[email protected]36b6dcb2008-11-12 01:19:572413
[email protected]c9cd2222009-05-06 05:16:502414 if (flags & TabContents::INVALIDATE_TAB) {
[email protected]36b6dcb2008-11-12 01:19:572415 tabstrip_model_.UpdateTabContentsStateAt(
[email protected]902cdf772009-05-06 15:08:122416 tabstrip_model_.GetIndexOfController(&contents->controller()), false);
[email protected]36b6dcb2008-11-12 01:19:572417 window_->UpdateTitleBar();
2418
[email protected]ba8c48212009-05-12 21:20:402419 if (selected_tab && contents == selected_tab) {
[email protected]1fc025202009-01-20 23:03:142420 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS,
[email protected]ba8c48212009-05-12 21:20:402421 !selected_tab->GetFavIcon().isNull());
[email protected]36b6dcb2008-11-12 01:19:572422 }
2423 }
2424
2425 // We don't need to process INVALIDATE_STATE, since that's not visible.
2426 }
2427
2428 scheduled_updates_.clear();
2429}
2430
2431void Browser::RemoveScheduledUpdatesFor(TabContents* contents) {
2432 if (!contents)
2433 return;
2434
2435 // Remove any pending UI updates for the detached tab.
2436 UpdateVector::iterator cur_update = scheduled_updates_.begin();
2437 while (cur_update != scheduled_updates_.end()) {
2438 if (cur_update->source == contents) {
2439 cur_update = scheduled_updates_.erase(cur_update);
2440 } else {
2441 ++cur_update;
initial.commit09911bf2008-07-26 23:55:292442 }
2443 }
2444}
2445
[email protected]d938aed92009-01-22 19:49:332446
[email protected]36b6dcb2008-11-12 01:19:572447///////////////////////////////////////////////////////////////////////////////
2448// Browser, Getters for UI (private):
initial.commit09911bf2008-07-26 23:55:292449
[email protected]36b6dcb2008-11-12 01:19:572450StatusBubble* Browser::GetStatusBubble() {
[email protected]9b032bf2009-07-21 17:34:232451 return window_ ? window_->GetStatusBubble() : NULL;
initial.commit09911bf2008-07-26 23:55:292452}
2453
[email protected]36b6dcb2008-11-12 01:19:572454///////////////////////////////////////////////////////////////////////////////
2455// Browser, Session restore functions (private):
initial.commit09911bf2008-07-26 23:55:292456
2457void Browser::SyncHistoryWithTabs(int index) {
2458 if (!profile()->HasSessionService())
2459 return;
2460 SessionService* session_service = profile()->GetSessionService();
2461 if (session_service) {
2462 for (int i = index; i < tab_count(); ++i) {
2463 TabContents* contents = GetTabContentsAt(i);
2464 if (contents) {
2465 session_service->SetTabIndexInWindow(
[email protected]ce3fa3c2009-04-20 19:55:572466 session_id(), contents->controller().session_id(), i);
[email protected]5c0e6482009-07-14 20:20:092467 session_service->SetPinnedState(session_id(),
2468 contents->controller().session_id(),
2469 tabstrip_model_.IsTabPinned(i));
initial.commit09911bf2008-07-26 23:55:292470 }
2471 }
2472 }
2473}
2474
[email protected]ce3fa3c2009-04-20 19:55:572475TabContents* Browser::BuildRestoredTab(
[email protected]36b6dcb2008-11-12 01:19:572476 const std::vector<TabNavigation>& navigations,
2477 int selected_navigation) {
2478 if (!navigations.empty()) {
2479 DCHECK(selected_navigation >= 0 &&
2480 selected_navigation < static_cast<int>(navigations.size()));
[email protected]36b6dcb2008-11-12 01:19:572481 // Create a NavigationController. This constructor creates the appropriate
2482 // set of TabContents.
[email protected]57c6a652009-05-04 07:58:342483 TabContents* new_tab = new TabContents(profile_, NULL,
[email protected]ce3fa3c2009-04-20 19:55:572484 MSG_ROUTING_NONE, NULL);
2485 new_tab->controller().RestoreFromState(navigations, selected_navigation);
2486 return new_tab;
[email protected]36b6dcb2008-11-12 01:19:572487 } else {
2488 // No navigations. Create a tab with about:blank.
[email protected]ce3fa3c2009-04-20 19:55:572489 return CreateTabContentsForURL(GURL("about:blank"), GURL(), profile_,
2490 PageTransition::START_PAGE, false, NULL);
initial.commit09911bf2008-07-26 23:55:292491 }
2492}
2493
[email protected]36b6dcb2008-11-12 01:19:572494///////////////////////////////////////////////////////////////////////////////
2495// Browser, OnBeforeUnload handling (private):
initial.commit09911bf2008-07-26 23:55:292496
[email protected]04b4a6c2008-08-02 00:44:472497void Browser::ProcessPendingTabs() {
2498 DCHECK(is_attempting_to_close_browser_);
initial.commit09911bf2008-07-26 23:55:292499
[email protected]04b4a6c2008-08-02 00:44:472500 if (HasCompletedUnloadProcessing()) {
2501 // We've finished all the unload events and can proceed to close the
2502 // browser.
2503 OnWindowClosing();
initial.commit09911bf2008-07-26 23:55:292504 return;
2505 }
2506
[email protected]04b4a6c2008-08-02 00:44:472507 // Process beforeunload tabs first. When that queue is empty, process
2508 // unload tabs.
[email protected]04b4a6c2008-08-02 00:44:472509 if (!tabs_needing_before_unload_fired_.empty()) {
[email protected]06b42f032008-12-03 18:43:052510 TabContents* tab = *(tabs_needing_before_unload_fired_.begin());
[email protected]22484622009-06-10 21:17:242511 // Null check render_view_host here as this gets called on a PostTask and
2512 // the tab's render_view_host may have been nulled out.
2513 if (tab->render_view_host()) {
[email protected]ae23c272009-07-27 20:15:402514 tab->render_view_host()->FirePageBeforeUnload(false);
[email protected]22484622009-06-10 21:17:242515 } else {
2516 ClearUnloadState(tab);
2517 }
[email protected]04b4a6c2008-08-02 00:44:472518 } else if (!tabs_needing_unload_fired_.empty()) {
initial.commit09911bf2008-07-26 23:55:292519 // We've finished firing all beforeunload events and can proceed with unload
2520 // events.
2521 // TODO(ojan): We should add a call to browser_shutdown::OnShutdownStarting
2522 // somewhere around here so that we have accurate measurements of shutdown
2523 // time.
[email protected]04b4a6c2008-08-02 00:44:472524 // TODO(ojan): We can probably fire all the unload events in parallel and
2525 // get a perf benefit from that in the cases where the tab hangs in it's
2526 // unload handler or takes a long time to page in.
[email protected]06b42f032008-12-03 18:43:052527 TabContents* tab = *(tabs_needing_unload_fired_.begin());
[email protected]22484622009-06-10 21:17:242528 // Null check render_view_host here as this gets called on a PostTask and
2529 // the tab's render_view_host may have been nulled out.
2530 if (tab->render_view_host()) {
[email protected]eb6b87a2009-07-24 15:57:392531 tab->render_view_host()->ClosePage(false, -1, -1);
[email protected]22484622009-06-10 21:17:242532 } else {
2533 ClearUnloadState(tab);
2534 }
initial.commit09911bf2008-07-26 23:55:292535 } else {
[email protected]04b4a6c2008-08-02 00:44:472536 NOTREACHED();
initial.commit09911bf2008-07-26 23:55:292537 }
2538}
2539
[email protected]d043c2cc2009-03-25 18:30:452540bool Browser::HasCompletedUnloadProcessing() const {
[email protected]04b4a6c2008-08-02 00:44:472541 return is_attempting_to_close_browser_ &&
2542 tabs_needing_before_unload_fired_.empty() &&
2543 tabs_needing_unload_fired_.empty();
2544}
2545
2546void Browser::CancelWindowClose() {
2547 DCHECK(is_attempting_to_close_browser_);
2548 // Only cancelling beforeunload should be able to cancel the window's close.
2549 // So there had better be a tab that we think needs beforeunload fired.
2550 DCHECK(!tabs_needing_before_unload_fired_.empty());
2551
[email protected]8f673f3a2008-08-05 22:34:282552 tabs_needing_before_unload_fired_.clear();
2553 tabs_needing_unload_fired_.clear();
[email protected]04b4a6c2008-08-02 00:44:472554 is_attempting_to_close_browser_ = false;
2555}
2556
[email protected]06b42f032008-12-03 18:43:052557bool Browser::RemoveFromSet(UnloadListenerSet* set, TabContents* tab) {
[email protected]04b4a6c2008-08-02 00:44:472558 DCHECK(is_attempting_to_close_browser_);
2559
[email protected]06b42f032008-12-03 18:43:052560 UnloadListenerSet::iterator iter = std::find(set->begin(), set->end(), tab);
2561 if (iter != set->end()) {
2562 set->erase(iter);
2563 return true;
[email protected]04b4a6c2008-08-02 00:44:472564 }
2565 return false;
2566}
initial.commit09911bf2008-07-26 23:55:292567
[email protected]36b6dcb2008-11-12 01:19:572568void Browser::ClearUnloadState(TabContents* tab) {
2569 DCHECK(is_attempting_to_close_browser_);
[email protected]06b42f032008-12-03 18:43:052570 RemoveFromSet(&tabs_needing_before_unload_fired_, tab);
2571 RemoveFromSet(&tabs_needing_unload_fired_, tab);
[email protected]36b6dcb2008-11-12 01:19:572572 ProcessPendingTabs();
initial.commit09911bf2008-07-26 23:55:292573}
2574
[email protected]f7454892009-01-29 19:24:212575
[email protected]36b6dcb2008-11-12 01:19:572576///////////////////////////////////////////////////////////////////////////////
[email protected]69444cc2009-04-09 20:40:062577// Browser, In-progress download termination handling (private):
2578
2579bool Browser::CanCloseWithInProgressDownloads() {
2580 if (cancel_download_confirmation_state_ != NOT_PROMPTED) {
2581 // This should probably not happen.
2582 DCHECK(cancel_download_confirmation_state_ != WAITING_FOR_RESPONSE);
2583 return true;
2584 }
2585
2586 // If there are no download in-progress, our job is done.
2587 DownloadManager* download_manager = profile_->GetDownloadManager();
2588 if (!download_manager || download_manager->in_progress_count() == 0)
2589 return true;
2590
2591 // Let's figure out if we are the last window for our profile.
2592 // Note that we cannot just use BrowserList::GetBrowserCount as browser
2593 // windows closing is delayed and the returned count might include windows
2594 // that are being closed.
2595 int count = 0;
2596 for (BrowserList::const_iterator iter = BrowserList::begin();
2597 iter != BrowserList::end(); ++iter) {
2598 // Don't count this browser window or any other in the process of closing.
2599 if (*iter == this || (*iter)->is_attempting_to_close_browser_)
2600 continue;
2601
2602 // We test the original profile, because an incognito browser window keeps
2603 // the original profile alive (and its DownloadManager).
2604 // We also need to test explicitly the profile directly so that 2 incognito
2605 // profiles count as a match.
2606 if ((*iter)->profile() == profile() ||
2607 (*iter)->profile()->GetOriginalProfile() == profile())
2608 count++;
2609 }
2610 if (count > 0)
2611 return true;
2612
2613 cancel_download_confirmation_state_ = WAITING_FOR_RESPONSE;
2614 window_->ConfirmBrowserCloseWithPendingDownloads();
2615
2616 // Return false so the browser does not close. We'll close if the user
2617 // confirms in the dialog.
2618 return false;
2619}
2620
2621///////////////////////////////////////////////////////////////////////////////
[email protected]36b6dcb2008-11-12 01:19:572622// Browser, Assorted utility functions (private):
initial.commit09911bf2008-07-26 23:55:292623
[email protected]1a6b30a2009-08-19 03:52:112624// static
2625Browser* Browser::GetOrCreateTabbedBrowser(Profile* profile) {
initial.commit09911bf2008-07-26 23:55:292626 Browser* browser = BrowserList::FindBrowserWithType(
[email protected]1a6b30a2009-08-19 03:52:112627 profile, TYPE_NORMAL);
[email protected]15952e462008-11-14 00:29:052628 if (!browser)
[email protected]1a6b30a2009-08-19 03:52:112629 browser = Browser::Create(profile);
initial.commit09911bf2008-07-26 23:55:292630 return browser;
2631}
2632
[email protected]1f7d7e92009-06-02 20:55:042633void Browser::OpenURLAtIndex(TabContents* source,
2634 const GURL& url,
2635 const GURL& referrer,
2636 WindowOpenDisposition disposition,
2637 PageTransition::Type transition,
2638 int index,
2639 bool force_index) {
2640 // TODO(beng): Move all this code into a separate helper that has unit tests.
2641
2642 // No code for these yet
2643 DCHECK((disposition != NEW_POPUP) && (disposition != SAVE_TO_DISK));
2644
2645 TabContents* current_tab = source ? source : GetSelectedTabContents();
2646 bool source_tab_was_frontmost = (current_tab == GetSelectedTabContents());
2647 TabContents* new_contents = NULL;
2648
2649 // If the URL is part of the same web site, then load it in the same
2650 // SiteInstance (and thus the same process). This is an optimization to
2651 // reduce process overhead; it is not necessary for compatibility. (That is,
2652 // the new tab will not have script connections to the previous tab, so it
2653 // does not need to be part of the same SiteInstance or BrowsingInstance.)
2654 // Default to loading in a new SiteInstance and BrowsingInstance.
2655 // TODO(creis): should this apply to applications?
2656 SiteInstance* instance = NULL;
2657 // Don't use this logic when "--process-per-tab" is specified.
2658 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab)) {
2659 if (current_tab) {
2660 const GURL& current_url = current_tab->GetURL();
2661 if (SiteInstance::IsSameWebSite(current_url, url))
2662 instance = current_tab->GetSiteInstance();
2663 }
2664 }
2665
2666 // If this is not a normal window (such as a popup or an application), we can
2667 // only have one tab so a new tab always goes into a tabbed browser window.
2668 if (disposition != NEW_WINDOW && type_ != TYPE_NORMAL) {
2669 // If the disposition is OFF_THE_RECORD we don't want to create a new
2670 // browser that will itself create another OTR browser. This will result in
2671 // a browser leak (and crash below because no tab is created or selected).
2672 if (disposition == OFF_THE_RECORD) {
2673 OpenURLOffTheRecord(profile_, url);
2674 return;
2675 }
2676
[email protected]1a6b30a2009-08-19 03:52:112677 Browser* b = GetOrCreateTabbedBrowser(profile_);
[email protected]1f7d7e92009-06-02 20:55:042678 DCHECK(b);
2679
2680 // If we have just created a new browser window, make sure we select the
2681 // tab.
2682 if (b->tab_count() == 0 && disposition == NEW_BACKGROUND_TAB)
2683 disposition = NEW_FOREGROUND_TAB;
2684
2685 b->OpenURL(url, referrer, disposition, transition);
2686 b->window()->Show();
2687 return;
2688 }
2689
2690 if (profile_->IsOffTheRecord() && disposition == OFF_THE_RECORD)
2691 disposition = NEW_FOREGROUND_TAB;
2692
2693 if (disposition == SINGLETON_TAB) {
2694 ShowSingleDOMUITab(url);
2695 return;
2696 } else if (disposition == NEW_WINDOW) {
2697 Browser* browser = Browser::Create(profile_);
2698 new_contents = browser->AddTabWithURL(url, referrer, transition, true,
2699 index, force_index, instance);
2700 browser->window()->Show();
2701 } else if ((disposition == CURRENT_TAB) && current_tab) {
2702 tabstrip_model_.TabNavigating(current_tab, transition);
2703
2704 current_tab->controller().LoadURL(url, referrer, transition);
2705 new_contents = current_tab;
2706 if (GetStatusBubble())
2707 GetStatusBubble()->Hide();
2708
[email protected]b4a8b242009-08-16 15:20:442709 // Update the location bar. This is synchronous. We specifically don't
2710 // update the load state since the load hasn't started yet and updating it
2711 // will put it out of sync with the actual state like whether we're
2712 // displaying a favicon, which controls the throbber. If we updated it here,
2713 // the throbber will show the default favicon for a split second when
2714 // navigating away from the new tab page.
[email protected]1f7d7e92009-06-02 20:55:042715 ScheduleUIUpdate(current_tab, TabContents::INVALIDATE_URL);
2716 } else if (disposition == OFF_THE_RECORD) {
2717 OpenURLOffTheRecord(profile_, url);
2718 return;
2719 } else if (disposition != SUPPRESS_OPEN) {
2720 new_contents = AddTabWithURL(url, referrer, transition,
2721 disposition != NEW_BACKGROUND_TAB, index, force_index, instance);
2722 }
2723
[email protected]b4a8b242009-08-16 15:20:442724 if (disposition != NEW_BACKGROUND_TAB && source_tab_was_frontmost &&
2725 new_contents) {
[email protected]1f7d7e92009-06-02 20:55:042726 // Give the focus to the newly navigated tab, if the source tab was
2727 // front-most.
2728 new_contents->Focus();
2729 }
2730}
2731
initial.commit09911bf2008-07-26 23:55:292732void Browser::BuildPopupWindow(TabContents* source,
2733 TabContents* new_contents,
2734 const gfx::Rect& initial_pos) {
[email protected]9f5b80a2009-04-08 01:26:072735 BuildPopupWindowHelper(source, new_contents, initial_pos,
2736 (type_ & TYPE_APP) ? TYPE_APP_POPUP : TYPE_POPUP,
2737 profile_, false);
2738}
2739
2740void Browser::BuildPopupWindowHelper(TabContents* source,
2741 TabContents* new_contents,
2742 const gfx::Rect& initial_pos,
2743 Browser::Type browser_type,
2744 Profile* profile,
2745 bool start_restored) {
2746 Browser* browser = new Browser(browser_type, profile);
[email protected]15952e462008-11-14 00:29:052747 browser->set_override_bounds(initial_pos);
[email protected]9f5b80a2009-04-08 01:26:072748
2749 if (start_restored)
2750 browser->set_maximized_state(MAXIMIZED_STATE_UNMAXIMIZED);
2751
[email protected]15952e462008-11-14 00:29:052752 browser->CreateBrowserWindow();
[email protected]6b2ee922009-04-30 20:40:532753 browser->tabstrip_model()->AppendTabContents(new_contents, true);
[email protected]2f69fb52008-12-12 18:50:392754 browser->window()->Show();
initial.commit09911bf2008-07-26 23:55:292755}
2756
[email protected]d043c2cc2009-03-25 18:30:452757GURL Browser::GetHomePage() const {
[email protected]15952e462008-11-14 00:29:052758 if (profile_->GetPrefs()->GetBoolean(prefs::kHomePageIsNewTabPage))
[email protected]b689fce72009-03-17 22:45:342759 return GURL(chrome::kChromeUINewTabURL);
[email protected]15952e462008-11-14 00:29:052760 GURL home_page = GURL(URLFixerUpper::FixupURL(
[email protected]a239c3f2009-02-17 22:13:192761 WideToUTF8(profile_->GetPrefs()->GetString(prefs::kHomePage)),
2762 std::string()));
[email protected]15952e462008-11-14 00:29:052763 if (!home_page.is_valid())
[email protected]b689fce72009-03-17 22:45:342764 return GURL(chrome::kChromeUINewTabURL);
[email protected]15952e462008-11-14 00:29:052765 return home_page;
[email protected]36b6dcb2008-11-12 01:19:572766}
initial.commit09911bf2008-07-26 23:55:292767
[email protected]4f3dc372009-02-24 00:10:292768void Browser::FindInPage(bool find_next, bool forward_direction) {
[email protected]4801ecc2009-04-05 04:52:582769 ShowFindBar();
[email protected]4f3dc372009-02-24 00:10:292770 if (find_next) {
[email protected]57c6a652009-05-04 07:58:342771 GetSelectedTabContents()->StartFinding(string16(),
[email protected]e491f1c2009-05-22 20:28:122772 forward_direction,
2773 false); // Not case sensitive.
[email protected]4f3dc372009-02-24 00:10:292774 }
[email protected]fbd77592008-11-12 20:50:272775}
[email protected]cb17f7f2009-02-06 18:14:482776
[email protected]36b6dcb2008-11-12 01:19:572777void Browser::CloseFrame() {
2778 window_->Close();
initial.commit09911bf2008-07-26 23:55:292779}
2780
2781// static
2782std::wstring Browser::ComputeApplicationNameFromURL(const GURL& url) {
2783 std::string t;
2784 t.append(url.host());
2785 t.append("_");
2786 t.append(url.path());
2787 return UTF8ToWide(t);
2788}
2789
2790// static
initial.commit09911bf2008-07-26 23:55:292791void Browser::RegisterAppPrefs(const std::wstring& app_name) {
2792 // A set of apps that we've already started.
2793 static std::set<std::wstring>* g_app_names = NULL;
2794
2795 if (!g_app_names)
2796 g_app_names = new std::set<std::wstring>;
2797
2798 // Only register once for each app name.
2799 if (g_app_names->find(app_name) != g_app_names->end())
2800 return;
2801 g_app_names->insert(app_name);
2802
2803 // We need to register the window position pref.
2804 std::wstring window_pref(prefs::kBrowserWindowPlacement);
2805 window_pref.append(L"_");
2806 window_pref.append(app_name);
2807 PrefService* prefs = g_browser_process->local_state();
2808 DCHECK(prefs);
2809
2810 prefs->RegisterDictionaryPref(window_pref.c_str());
2811}
[email protected]5c238752009-06-13 10:29:072812
2813///////////////////////////////////////////////////////////////////////////////
2814// BrowserToolbarModel (private):
2815
2816NavigationController* Browser::BrowserToolbarModel::GetNavigationController() {
2817 // This |current_tab| can be NULL during the initialization of the
2818 // toolbar during window creation (i.e. before any tabs have been added
2819 // to the window).
2820 TabContents* current_tab = browser_->GetSelectedTabContents();
2821 return current_tab ? &current_tab->controller() : NULL;
2822}