blob: 14c1957a533061531b962ea5297480f81542a552 [file] [log] [blame]
[email protected]a37d4b02012-06-25 21:56:101// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/browser_commands.h"
6
7#include "base/command_line.h"
8#include "base/metrics/histogram.h"
9#include "base/utf_string_conversions.h"
[email protected]5d98294912012-06-27 22:57:4010#include "chrome/browser/bookmarks/bookmark_editor.h"
[email protected]a37d4b02012-06-25 21:56:1011#include "chrome/browser/bookmarks/bookmark_model.h"
12#include "chrome/browser/bookmarks/bookmark_utils.h"
13#include "chrome/browser/browser_process.h"
[email protected]b0cb5e82012-07-19 19:22:4714#include "chrome/browser/browsing_data/browsing_data_helper.h"
15#include "chrome/browser/browsing_data/browsing_data_remover.h"
[email protected]a37d4b02012-06-25 21:56:1016#include "chrome/browser/chrome_page_zoom.h"
17#include "chrome/browser/debugger/devtools_window.h"
[email protected]5d98294912012-06-27 22:57:4018#include "chrome/browser/download/download_util.h"
[email protected]a37d4b02012-06-25 21:56:1019#include "chrome/browser/extensions/extension_service.h"
[email protected]a6394ae2012-07-16 20:58:4320#include "chrome/browser/extensions/tab_helper.h"
[email protected]a37d4b02012-06-25 21:56:1021#include "chrome/browser/favicon/favicon_tab_helper.h"
22#include "chrome/browser/lifetime/application_lifetime.h"
23#include "chrome/browser/platform_util.h"
24#include "chrome/browser/prefs/incognito_mode_prefs.h"
25#include "chrome/browser/prefs/pref_service.h"
[email protected]5d98294912012-06-27 22:57:4026#include "chrome/browser/printing/print_preview_tab_controller.h"
[email protected]a37d4b02012-06-25 21:56:1027#include "chrome/browser/printing/print_view_manager.h"
28#include "chrome/browser/profiles/profile.h"
29#include "chrome/browser/sessions/session_service_factory.h"
[email protected]a37d4b02012-06-25 21:56:1030#include "chrome/browser/sessions/tab_restore_service.h"
[email protected]5d98294912012-06-27 22:57:4031#include "chrome/browser/sessions/tab_restore_service_delegate.h"
[email protected]78e2edc2012-07-01 23:32:2832#include "chrome/browser/sessions/tab_restore_service_factory.h"
[email protected]a37d4b02012-06-25 21:56:1033#include "chrome/browser/ui/browser.h"
[email protected]5d98294912012-06-27 22:57:4034#include "chrome/browser/ui/browser_command_controller.h"
[email protected]a37d4b02012-06-25 21:56:1035#include "chrome/browser/ui/browser_finder.h"
[email protected]7acfaf92012-07-11 15:51:5936#include "chrome/browser/ui/browser_instant_controller.h"
[email protected]5d98294912012-06-27 22:57:4037#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
[email protected]52877dbc62012-06-29 22:22:0338#include "chrome/browser/ui/browser_tabstrip.h"
[email protected]a37d4b02012-06-25 21:56:1039#include "chrome/browser/ui/browser_window.h"
[email protected]5d98294912012-06-27 22:57:4040#include "chrome/browser/ui/constrained_window_tab_helper.h"
[email protected]a37d4b02012-06-25 21:56:1041#include "chrome/browser/ui/find_bar/find_bar_controller.h"
42#include "chrome/browser/ui/find_bar/find_tab_helper.h"
[email protected]3f32b9b2012-07-09 16:59:2843#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
[email protected]ffe6de62012-07-19 00:02:3544#include "chrome/browser/ui/metro_pin_tab_helper.h"
[email protected]a37d4b02012-06-25 21:56:1045#include "chrome/browser/ui/omnibox/location_bar.h"
[email protected]43aafff2012-06-29 21:20:4946#include "chrome/browser/ui/search/search.h"
47#include "chrome/browser/ui/search/search_model.h"
[email protected]a37d4b02012-06-25 21:56:1048#include "chrome/browser/ui/status_bubble.h"
49#include "chrome/browser/ui/tab_contents/tab_contents.h"
50#include "chrome/browser/ui/tabs/tab_strip_model.h"
51#include "chrome/browser/ui/webui/feedback_ui.h"
52#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
[email protected]5d98294912012-06-27 22:57:4053#include "chrome/browser/web_applications/web_app.h"
[email protected]a37d4b02012-06-25 21:56:1054#include "chrome/common/chrome_switches.h"
[email protected]a37d4b02012-06-25 21:56:1055#include "chrome/common/pref_names.h"
[email protected]d3446bda2012-07-12 14:24:3956#include "content/public/browser/devtools_agent_host_registry.h"
[email protected]a37d4b02012-06-25 21:56:1057#include "content/public/browser/navigation_controller.h"
58#include "content/public/browser/navigation_entry.h"
59#include "content/public/browser/page_navigator.h"
60#include "content/public/browser/render_view_host.h"
61#include "content/public/browser/user_metrics.h"
62#include "content/public/browser/web_contents.h"
63#include "content/public/browser/web_contents_view.h"
[email protected]78e2edc2012-07-01 23:32:2864#include "content/public/common/content_restriction.h"
65#include "content/public/common/renderer_preferences.h"
[email protected]2cd4fde2012-06-26 03:10:2666#include "content/public/common/url_constants.h"
[email protected]a37d4b02012-06-25 21:56:1067#include "net/base/escape.h"
[email protected]2cd4fde2012-06-26 03:10:2668#include "webkit/glue/webkit_glue.h"
[email protected]a37d4b02012-06-25 21:56:1069
70#if defined(OS_MACOSX)
71#include "ui/base/cocoa/find_pasteboard.h"
72#endif
73
74#if defined(OS_WIN)
75#include "base/win/metro.h"
76#endif
77
78using content::NavigationController;
79using content::NavigationEntry;
80using content::OpenURLParams;
81using content::Referrer;
82using content::SSLStatus;
83using content::UserMetricsAction;
84using content::WebContents;
85
86namespace chrome {
87namespace {
88
89WebContents* GetOrCloneTabForDisposition(Browser* browser,
90 WindowOpenDisposition disposition) {
[email protected]855370052012-07-10 19:30:3291 TabContents* current_tab = GetActiveTabContents(browser);
[email protected]a37d4b02012-06-25 21:56:1092 switch (disposition) {
93 case NEW_FOREGROUND_TAB:
94 case NEW_BACKGROUND_TAB: {
95 current_tab = current_tab->Clone();
96 browser->tab_strip_model()->AddTabContents(
97 current_tab, -1, content::PAGE_TRANSITION_LINK,
98 disposition == NEW_FOREGROUND_TAB ? TabStripModel::ADD_ACTIVE :
99 TabStripModel::ADD_NONE);
100 break;
101 }
102 case NEW_WINDOW: {
103 current_tab = current_tab->Clone();
104 Browser* b = Browser::Create(browser->profile());
105 b->tab_strip_model()->AddTabContents(
106 current_tab, -1, content::PAGE_TRANSITION_LINK,
107 TabStripModel::ADD_ACTIVE);
108 b->window()->Show();
109 break;
110 }
111 default:
112 break;
113 }
114 return current_tab->web_contents();
115}
116
117void ReloadInternal(Browser* browser,
118 WindowOpenDisposition disposition,
119 bool ignore_cache) {
120 // If we are showing an interstitial, treat this as an OpenURL.
[email protected]855370052012-07-10 19:30:32121 WebContents* current_tab = GetActiveWebContents(browser);
[email protected]a37d4b02012-06-25 21:56:10122 if (current_tab && current_tab->ShowingInterstitialPage()) {
123 NavigationEntry* entry = current_tab->GetController().GetActiveEntry();
124 DCHECK(entry); // Should exist if interstitial is showing.
125 browser->OpenURL(OpenURLParams(
126 entry->GetURL(), Referrer(), disposition,
127 content::PAGE_TRANSITION_RELOAD, false));
128 return;
129 }
130
131 // As this is caused by a user action, give the focus to the page.
132 //
133 // Also notify RenderViewHostDelegate of the user gesture; this is
134 // normally done in Browser::Navigate, but a reload bypasses Navigate.
135 WebContents* web_contents = GetOrCloneTabForDisposition(browser, disposition);
136 web_contents->UserGestureDone();
137 if (!web_contents->FocusLocationBarByDefault())
138 web_contents->Focus();
139 if (ignore_cache)
140 web_contents->GetController().ReloadIgnoringCache(true);
141 else
142 web_contents->GetController().Reload(true);
143}
144
[email protected]5d98294912012-06-27 22:57:40145bool HasConstrainedWindow(const Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03146 TabContents* tab_contents = GetActiveTabContents(browser);
[email protected]5d98294912012-06-27 22:57:40147 return tab_contents && tab_contents->constrained_window_tab_helper()->
148 constrained_window_count();
149}
150
151bool PrintPreviewShowing(const Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03152 TabContents* contents = GetActiveTabContents(browser);
[email protected]5d98294912012-06-27 22:57:40153 printing::PrintPreviewTabController* controller =
154 printing::PrintPreviewTabController::GetInstance();
155 return controller && (controller->GetPrintPreviewForTab(contents) ||
156 controller->is_creating_print_preview_tab());
157}
158
[email protected]db9747252012-07-02 19:28:00159bool IsNTPModeForInstantExtendedAPI(const Browser* browser) {
160 return browser->search_model() &&
[email protected]855370052012-07-10 19:30:32161 search::IsInstantExtendedAPIEnabled(browser->profile()) &&
162 browser->search_model()->mode().is_ntp();
[email protected]db9747252012-07-02 19:28:00163}
164
[email protected]a37d4b02012-06-25 21:56:10165} // namespace
166
[email protected]5d98294912012-06-27 22:57:40167bool IsCommandEnabled(Browser* browser, int command) {
168 return browser->command_controller()->command_updater()->IsCommandEnabled(
169 command);
170}
171
172bool SupportsCommand(Browser* browser, int command) {
173 return browser->command_controller()->command_updater()->SupportsCommand(
174 command);
175}
176
177bool ExecuteCommand(Browser* browser, int command) {
178 return browser->command_controller()->command_updater()->ExecuteCommand(
179 command);
180}
181
182bool ExecuteCommandWithDisposition(Browser* browser,
183 int command,
184 WindowOpenDisposition disposition) {
185 return browser->command_controller()->command_updater()->
186 ExecuteCommandWithDisposition(command, disposition);
187}
188
189void UpdateCommandEnabled(Browser* browser, int command, bool enabled) {
190 browser->command_controller()->command_updater()->UpdateCommandEnabled(
191 command, enabled);
192}
193
194void AddCommandObserver(Browser* browser,
195 int command,
196 CommandObserver* observer) {
197 browser->command_controller()->command_updater()->AddCommandObserver(
198 command, observer);
199}
200
201void RemoveCommandObserver(Browser* browser,
202 int command,
203 CommandObserver* observer) {
204 browser->command_controller()->command_updater()->RemoveCommandObserver(
205 command, observer);
206}
207
208int GetContentRestrictions(const Browser* browser) {
209 int content_restrictions = 0;
[email protected]52877dbc62012-06-29 22:22:03210 WebContents* current_tab = GetActiveWebContents(browser);
[email protected]5d98294912012-06-27 22:57:40211 if (current_tab) {
212 content_restrictions = current_tab->GetContentRestrictions();
213 NavigationEntry* active_entry =
214 current_tab->GetController().GetActiveEntry();
215 // See comment in UpdateCommandsForTabState about why we call url().
216 if (!download_util::IsSavableURL(
217 active_entry ? active_entry->GetURL() : GURL()) ||
218 current_tab->ShowingInterstitialPage())
219 content_restrictions |= content::CONTENT_RESTRICTION_SAVE;
220 if (current_tab->ShowingInterstitialPage())
221 content_restrictions |= content::CONTENT_RESTRICTION_PRINT;
222 }
223 return content_restrictions;
224}
225
[email protected]a37d4b02012-06-25 21:56:10226void NewEmptyWindow(Profile* profile) {
227 bool incognito = profile->IsOffTheRecord();
228 PrefService* prefs = profile->GetPrefs();
229 if (incognito) {
230 if (IncognitoModePrefs::GetAvailability(prefs) ==
231 IncognitoModePrefs::DISABLED) {
232 incognito = false;
233 }
234 } else {
235 if (browser_defaults::kAlwaysOpenIncognitoWindow &&
236 IncognitoModePrefs::ShouldLaunchIncognito(
237 *CommandLine::ForCurrentProcess(), prefs)) {
238 incognito = true;
239 }
240 }
241
242 if (incognito) {
243 content::RecordAction(UserMetricsAction("NewIncognitoWindow"));
244 OpenEmptyWindow(profile->GetOffTheRecordProfile());
245 } else {
246 content::RecordAction(UserMetricsAction("NewWindow"));
247 SessionService* session_service =
248 SessionServiceFactory::GetForProfile(profile->GetOriginalProfile());
249 if (!session_service ||
250 !session_service->RestoreIfNecessary(std::vector<GURL>())) {
251 OpenEmptyWindow(profile->GetOriginalProfile());
252 }
253 }
254}
255
256Browser* OpenEmptyWindow(Profile* profile) {
257 Browser* browser = Browser::Create(profile);
[email protected]855370052012-07-10 19:30:32258 AddBlankTab(browser, true);
[email protected]a37d4b02012-06-25 21:56:10259 browser->window()->Show();
260 return browser;
261}
262
263void OpenWindowWithRestoredTabs(Profile* profile) {
264 TabRestoreService* service = TabRestoreServiceFactory::GetForProfile(profile);
265 if (service)
266 service->RestoreMostRecentEntry(NULL);
267}
268
269void OpenURLOffTheRecord(Profile* profile, const GURL& url) {
270 Browser* browser = browser::FindOrCreateTabbedBrowser(
271 profile->GetOffTheRecordProfile());
[email protected]52877dbc62012-06-29 22:22:03272 AddSelectedTabWithURL(browser, url, content::PAGE_TRANSITION_LINK);
[email protected]a37d4b02012-06-25 21:56:10273 browser->window()->Show();
274}
275
[email protected]5d98294912012-06-27 22:57:40276bool CanGoBack(const Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03277 return GetActiveWebContents(browser)->GetController().CanGoBack();
[email protected]a37d4b02012-06-25 21:56:10278}
279
280void GoBack(Browser* browser, WindowOpenDisposition disposition) {
281 content::RecordAction(UserMetricsAction("Back"));
282
[email protected]52877dbc62012-06-29 22:22:03283 TabContents* current_tab = GetActiveTabContents(browser);
[email protected]a37d4b02012-06-25 21:56:10284 if (CanGoBack(browser)) {
285 WebContents* new_tab = GetOrCloneTabForDisposition(browser, disposition);
286 // If we are on an interstitial page and clone the tab, it won't be copied
287 // to the new tab, so we don't need to go back.
288 if (current_tab->web_contents()->ShowingInterstitialPage() &&
289 (new_tab != current_tab->web_contents()))
290 return;
291 new_tab->GetController().GoBack();
292 }
293}
294
[email protected]5d98294912012-06-27 22:57:40295bool CanGoForward(const Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03296 return GetActiveWebContents(browser)->GetController().CanGoForward();
[email protected]a37d4b02012-06-25 21:56:10297}
298
299void GoForward(Browser* browser, WindowOpenDisposition disposition) {
300 content::RecordAction(UserMetricsAction("Forward"));
301 if (CanGoForward(browser)) {
302 GetOrCloneTabForDisposition(browser, disposition)->
303 GetController().GoForward();
304 }
305}
306
307bool NavigateToIndexWithDisposition(Browser* browser,
308 int index,
309 WindowOpenDisposition disp) {
310 NavigationController& controller =
311 GetOrCloneTabForDisposition(browser, disp)->GetController();
312 if (index < 0 || index >= controller.GetEntryCount())
313 return false;
314 controller.GoToIndex(index);
315 return true;
316}
317
318void Reload(Browser* browser, WindowOpenDisposition disposition) {
319 content::RecordAction(UserMetricsAction("Reload"));
320 ReloadInternal(browser, disposition, false);
321}
322
323void ReloadIgnoringCache(Browser* browser, WindowOpenDisposition disposition) {
324 content::RecordAction(UserMetricsAction("ReloadIgnoringCache"));
325 ReloadInternal(browser, disposition, true);
326}
327
[email protected]5d98294912012-06-27 22:57:40328bool CanReload(const Browser* browser) {
[email protected]db9747252012-07-02 19:28:00329 return !browser->is_devtools() && !IsNTPModeForInstantExtendedAPI(browser);
[email protected]5d98294912012-06-27 22:57:40330}
331
[email protected]a37d4b02012-06-25 21:56:10332void Home(Browser* browser, WindowOpenDisposition disposition) {
333 content::RecordAction(UserMetricsAction("Home"));
334 browser->OpenURL(OpenURLParams(
335 browser->profile()->GetHomePage(), Referrer(), disposition,
336 content::PageTransitionFromInt(
337 content::PAGE_TRANSITION_AUTO_BOOKMARK |
338 content::PAGE_TRANSITION_HOME_PAGE),
339 false));
340}
341
342void OpenCurrentURL(Browser* browser) {
343 content::RecordAction(UserMetricsAction("LoadURL"));
344 LocationBar* location_bar = browser->window()->GetLocationBar();
345 if (!location_bar)
346 return;
347
348 WindowOpenDisposition open_disposition =
349 location_bar->GetWindowOpenDisposition();
[email protected]7acfaf92012-07-11 15:51:59350 if (browser->instant_controller()->OpenInstant(open_disposition))
[email protected]a37d4b02012-06-25 21:56:10351 return;
352
353 GURL url(location_bar->GetInputString());
354
[email protected]855370052012-07-10 19:30:32355 NavigateParams params(browser, url, location_bar->GetPageTransition());
[email protected]a37d4b02012-06-25 21:56:10356 params.disposition = open_disposition;
357 // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
358 // inherit the opener. In some cases the tabstrip will determine the group
359 // should be inherited, in which case the group is inherited instead of the
360 // opener.
361 params.tabstrip_add_types =
362 TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
[email protected]855370052012-07-10 19:30:32363 Navigate(&params);
[email protected]a37d4b02012-06-25 21:56:10364
365 DCHECK(browser->profile()->GetExtensionService());
366 if (browser->profile()->GetExtensionService()->IsInstalledApp(url)) {
367 AppLauncherHandler::RecordAppLaunchType(
368 extension_misc::APP_LAUNCH_OMNIBOX_LOCATION);
369 }
370}
371
372void Stop(Browser* browser) {
373 content::RecordAction(UserMetricsAction("Stop"));
[email protected]52877dbc62012-06-29 22:22:03374 GetActiveWebContents(browser)->Stop();
[email protected]a37d4b02012-06-25 21:56:10375}
376
377#if !defined(OS_WIN)
378void NewWindow(Browser* browser) {
379 NewEmptyWindow(browser->profile()->GetOriginalProfile());
380}
381
382void NewIncognitoWindow(Browser* browser) {
383 NewEmptyWindow(browser->profile()->GetOffTheRecordProfile());
384}
385#endif // OS_WIN
386
387void CloseWindow(Browser* browser) {
388 content::RecordAction(UserMetricsAction("CloseWindow"));
389 browser->window()->Close();
390}
391
392void NewTab(Browser* browser) {
393 content::RecordAction(UserMetricsAction("NewTab"));
394 // TODO(asvitkine): This is invoked programmatically from several places.
395 // Audit the code and change it so that the histogram only gets collected for
396 // user-initiated commands.
397 UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
398 TabStripModel::NEW_TAB_ENUM_COUNT);
399
400 if (browser->is_type_tabbed()) {
[email protected]855370052012-07-10 19:30:32401 AddBlankTab(browser, true);
[email protected]52877dbc62012-06-29 22:22:03402 GetActiveWebContents(browser)->GetView()->RestoreFocus();
[email protected]a37d4b02012-06-25 21:56:10403 } else {
404 Browser* b = browser::FindOrCreateTabbedBrowser(browser->profile());
[email protected]855370052012-07-10 19:30:32405 AddBlankTab(b, true);
[email protected]a37d4b02012-06-25 21:56:10406 b->window()->Show();
407 // The call to AddBlankTab above did not set the focus to the tab as its
408 // window was not active, so we have to do it explicitly.
409 // See http://crbug.com/6380.
[email protected]855370052012-07-10 19:30:32410 GetActiveWebContents(b)->GetView()->RestoreFocus();
[email protected]a37d4b02012-06-25 21:56:10411 }
412}
413
414void CloseTab(Browser* browser) {
415 content::RecordAction(UserMetricsAction("CloseTab_Accelerator"));
416 browser->tab_strip_model()->CloseSelectedTabs();
417}
418
[email protected]5d98294912012-06-27 22:57:40419void RestoreTab(Browser* browser) {
420 content::RecordAction(UserMetricsAction("RestoreTab"));
421 TabRestoreService* service =
422 TabRestoreServiceFactory::GetForProfile(browser->profile());
423 if (service)
424 service->RestoreMostRecentEntry(browser->tab_restore_service_delegate());
425}
426
427bool CanRestoreTab(const Browser* browser) {
428 TabRestoreService* service =
429 TabRestoreServiceFactory::GetForProfile(browser->profile());
430 return service && !service->entries().empty();
431}
432
[email protected]a37d4b02012-06-25 21:56:10433void SelectNextTab(Browser* browser) {
434 content::RecordAction(UserMetricsAction("SelectNextTab"));
435 browser->tab_strip_model()->SelectNextTab();
436}
437
438void SelectPreviousTab(Browser* browser) {
439 content::RecordAction(UserMetricsAction("SelectPrevTab"));
440 browser->tab_strip_model()->SelectPreviousTab();
441}
442
443void OpenTabpose(Browser* browser) {
444#if defined(OS_MACOSX)
445 if (!CommandLine::ForCurrentProcess()->HasSwitch(
446 switches::kEnableExposeForTabs)) {
447 return;
448 }
449
450 content::RecordAction(UserMetricsAction("OpenTabpose"));
451 browser->window()->OpenTabpose();
452#else
453 NOTREACHED();
454#endif
455}
456
457void MoveTabNext(Browser* browser) {
458 content::RecordAction(UserMetricsAction("MoveTabNext"));
459 browser->tab_strip_model()->MoveTabNext();
460}
461
462void MoveTabPrevious(Browser* browser) {
463 content::RecordAction(UserMetricsAction("MoveTabPrevious"));
464 browser->tab_strip_model()->MoveTabPrevious();
465}
466
467void SelectNumberedTab(Browser* browser, int index) {
468 if (index < browser->tab_count()) {
469 content::RecordAction(UserMetricsAction("SelectNumberedTab"));
[email protected]52877dbc62012-06-29 22:22:03470 ActivateTabAt(browser, index, true);
[email protected]a37d4b02012-06-25 21:56:10471 }
472}
473
474void SelectLastTab(Browser* browser) {
475 content::RecordAction(UserMetricsAction("SelectLastTab"));
476 browser->tab_strip_model()->SelectLastTab();
477}
478
479void DuplicateTab(Browser* browser) {
480 content::RecordAction(UserMetricsAction("Duplicate"));
[email protected]855370052012-07-10 19:30:32481 DuplicateTabAt(browser, browser->active_index());
[email protected]a37d4b02012-06-25 21:56:10482}
483
[email protected]5d98294912012-06-27 22:57:40484bool CanDuplicateTab(const Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03485 WebContents* contents = GetActiveWebContents(browser);
[email protected]5d98294912012-06-27 22:57:40486 return contents && contents->GetController().GetLastCommittedEntry();
487}
488
[email protected]855370052012-07-10 19:30:32489void DuplicateTabAt(Browser* browser, int index) {
490 TabContents* contents = GetTabContentsAt(browser, index);
491 CHECK(contents);
492 TabContents* contents_dupe = contents->Clone();
493
494 bool pinned = false;
495 if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
496 // If this is a tabbed browser, just create a duplicate tab inside the same
497 // window next to the tab being duplicated.
498 int index = browser->tab_strip_model()->GetIndexOfTabContents(contents);
499 pinned = browser->tab_strip_model()->IsTabPinned(index);
500 int add_types = TabStripModel::ADD_ACTIVE |
501 TabStripModel::ADD_INHERIT_GROUP |
502 (pinned ? TabStripModel::ADD_PINNED : 0);
503 browser->tab_strip_model()->InsertTabContentsAt(
504 index + 1, contents_dupe, add_types);
505 } else {
506 Browser* browser = NULL;
507 if (browser->is_app()) {
508 CHECK(!browser->is_type_popup());
509 CHECK(!browser->is_type_panel());
510 browser = Browser::CreateWithParams(
511 Browser::CreateParams::CreateForApp(Browser::TYPE_POPUP,
512 browser->app_name(),
513 gfx::Rect(),
514 browser->profile()));
515 } else if (browser->is_type_popup()) {
516 browser = Browser::CreateWithParams(
517 Browser::CreateParams(Browser::TYPE_POPUP, browser->profile()));
518 }
519
520 // Preserve the size of the original window. The new window has already
521 // been given an offset by the OS, so we shouldn't copy the old bounds.
522 BrowserWindow* new_window = browser->window();
523 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
524 browser->window()->GetRestoredBounds().size()));
525
526 // We need to show the browser now. Otherwise ContainerWin assumes the
527 // WebContents is invisible and won't size it.
528 browser->window()->Show();
529
530 // The page transition below is only for the purpose of inserting the tab.
531 AddTab(browser, contents_dupe, content::PAGE_TRANSITION_LINK);
532 }
533
534 SessionService* session_service =
535 SessionServiceFactory::GetForProfileIfExisting(browser->profile());
536 if (session_service)
537 session_service->TabRestored(contents_dupe, pinned);
538}
539
540bool CanDuplicateTabAt(Browser* browser, int index) {
541 content::NavigationController& nc =
542 GetWebContentsAt(browser, index)->GetController();
543 return nc.GetWebContents() && nc.GetLastCommittedEntry();
544}
545
[email protected]a37d4b02012-06-25 21:56:10546void ConvertPopupToTabbedBrowser(Browser* browser) {
547 content::RecordAction(UserMetricsAction("ShowAsTab"));
548 TabContents* contents =
549 browser->tab_strip_model()->DetachTabContentsAt(browser->active_index());
550 Browser* b = Browser::Create(browser->profile());
551 b->tab_strip_model()->AppendTabContents(contents, true);
552 b->window()->Show();
553}
554
555void Exit() {
556 content::RecordAction(UserMetricsAction("Exit"));
557 browser::AttemptUserExit();
558}
559
560void BookmarkCurrentPage(Browser* browser) {
561 content::RecordAction(UserMetricsAction("Star"));
562
563 BookmarkModel* model = browser->profile()->GetBookmarkModel();
564 if (!model || !model->IsLoaded())
565 return; // Ignore requests until bookmarks are loaded.
566
567 GURL url;
568 string16 title;
[email protected]52877dbc62012-06-29 22:22:03569 TabContents* tab = GetActiveTabContents(browser);
[email protected]a37d4b02012-06-25 21:56:10570 bookmark_utils::GetURLAndTitleToBookmark(tab->web_contents(), &url, &title);
571 bool was_bookmarked = model->IsBookmarked(url);
572 if (!was_bookmarked && browser->profile()->IsOffTheRecord()) {
573 // If we're incognito the favicon may not have been saved. Save it now
574 // so that bookmarks have an icon for the page.
575 tab->favicon_tab_helper()->SaveFavicon();
576 }
577 bookmark_utils::AddIfNotBookmarked(model, url, title);
578 // Make sure the model actually added a bookmark before showing the star. A
579 // bookmark isn't created if the url is invalid.
580 if (browser->window()->IsActive() && model->IsBookmarked(url)) {
581 // Only show the bubble if the window is active, otherwise we may get into
582 // weird situations where the bubble is deleted as soon as it is shown.
583 browser->window()->ShowBookmarkBubble(url, was_bookmarked);
584 }
585}
586
[email protected]5d98294912012-06-27 22:57:40587bool CanBookmarkCurrentPage(const Browser* browser) {
588 BookmarkModel* model = browser->profile()->GetBookmarkModel();
589 return browser_defaults::bookmarks_enabled &&
590 browser->profile()->GetPrefs()->GetBoolean(
591 prefs::kEditBookmarksEnabled) &&
592 model && model->IsLoaded() && browser->is_type_tabbed();
593}
594
595void BookmarkAllTabs(Browser* browser) {
596 BookmarkEditor::ShowBookmarkAllTabsDialog(browser);
597}
598
599bool CanBookmarkAllTabs(const Browser* browser) {
600 return browser->tab_count() > 1 && CanBookmarkCurrentPage(browser);
601}
602
[email protected]ffe6de62012-07-19 00:02:35603void TogglePagePinnedToStartScreen(Browser* browser) {
604 GetActiveTabContents(browser)->metro_pin_tab_helper()->
605 TogglePinnedToStartScreen();
[email protected]a37d4b02012-06-25 21:56:10606}
[email protected]a37d4b02012-06-25 21:56:10607
608void SavePage(Browser* browser) {
609 content::RecordAction(UserMetricsAction("SavePage"));
[email protected]52877dbc62012-06-29 22:22:03610 WebContents* current_tab = GetActiveWebContents(browser);
[email protected]a37d4b02012-06-25 21:56:10611 if (current_tab && current_tab->GetContentsMimeType() == "application/pdf")
612 content::RecordAction(UserMetricsAction("PDF.SavePage"));
613 current_tab->OnSavePage();
614}
615
[email protected]5d98294912012-06-27 22:57:40616bool CanSavePage(const Browser* browser) {
617 // LocalState can be NULL in tests.
618 if (g_browser_process->local_state() &&
619 !g_browser_process->local_state()->GetBoolean(
620 prefs::kAllowFileSelectionDialogs)) {
621 return false;
622 }
623 return !browser->is_devtools() &&
624 !(GetContentRestrictions(browser) & content::CONTENT_RESTRICTION_SAVE);
625}
626
[email protected]a37d4b02012-06-25 21:56:10627void ShowFindBar(Browser* browser) {
628 browser->GetFindBarController()->Show();
629}
630
631void ShowPageInfo(Browser* browser,
632 content::WebContents* web_contents,
633 const GURL& url,
634 const SSLStatus& ssl,
635 bool show_history) {
636 Profile* profile = Profile::FromBrowserContext(
637 web_contents->GetBrowserContext());
638 TabContents* tab_contents = TabContents::FromWebContents(web_contents);
639
640 if (CommandLine::ForCurrentProcess()->HasSwitch(
641 switches::kEnableWebsiteSettings)) {
642 browser->window()->ShowWebsiteSettings(
643 profile, tab_contents, url, ssl, show_history);
644 } else {
645 browser->window()->ShowPageInfo(web_contents, url, ssl, show_history);
646 }
647}
648
649void ShowChromeToMobileBubble(Browser* browser) {
650 // Only show the bubble if the window is active, otherwise we may get into
651 // weird situations where the bubble is deleted as soon as it is shown.
652 if (browser->window()->IsActive())
653 browser->window()->ShowChromeToMobileBubble();
654}
655
656void Print(Browser* browser) {
657 if (g_browser_process->local_state()->GetBoolean(
658 prefs::kPrintPreviewDisabled)) {
[email protected]52877dbc62012-06-29 22:22:03659 GetActiveTabContents(browser)->print_view_manager()->PrintNow();
[email protected]a37d4b02012-06-25 21:56:10660 } else {
[email protected]52877dbc62012-06-29 22:22:03661 GetActiveTabContents(browser)->print_view_manager()->
662 PrintPreviewNow();
[email protected]a37d4b02012-06-25 21:56:10663 }
664}
665
[email protected]5d98294912012-06-27 22:57:40666bool CanPrint(const Browser* browser) {
667 // LocalState can be NULL in tests.
668 if (g_browser_process->local_state() &&
669 !g_browser_process->local_state()->GetBoolean(prefs::kPrintingEnabled)) {
670 return false;
671 }
672
673 // Do not print when a constrained window is showing. It's confusing.
[email protected]db9747252012-07-02 19:28:00674 // Do not print if instant extended API is enabled and mode is NTP.
[email protected]5d98294912012-06-27 22:57:40675 return !(HasConstrainedWindow(browser) ||
[email protected]db9747252012-07-02 19:28:00676 GetContentRestrictions(browser) & content::CONTENT_RESTRICTION_PRINT ||
677 IsNTPModeForInstantExtendedAPI(browser));
[email protected]5d98294912012-06-27 22:57:40678}
679
[email protected]a37d4b02012-06-25 21:56:10680void AdvancedPrint(Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03681 GetActiveTabContents(browser)->print_view_manager()->
682 AdvancedPrintNow();
[email protected]a37d4b02012-06-25 21:56:10683}
684
[email protected]5d98294912012-06-27 22:57:40685bool CanAdvancedPrint(const Browser* browser) {
686 // LocalState can be NULL in tests.
687 if (g_browser_process->local_state() &&
688 !g_browser_process->local_state()->GetBoolean(prefs::kPrintingEnabled)) {
689 return false;
690 }
691
692 // It is always possible to advanced print when print preview is visible.
693 return PrintPreviewShowing(browser) || CanPrint(browser);
694}
695
[email protected]d53e4032012-06-29 18:58:34696void PrintToDestination(Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03697 GetActiveTabContents(browser)->print_view_manager()->PrintToDestination();
[email protected]d53e4032012-06-29 18:58:34698}
699
[email protected]a37d4b02012-06-25 21:56:10700void EmailPageLocation(Browser* browser) {
701 content::RecordAction(UserMetricsAction("EmailPageLocation"));
[email protected]52877dbc62012-06-29 22:22:03702 WebContents* wc = GetActiveWebContents(browser);
[email protected]a37d4b02012-06-25 21:56:10703 DCHECK(wc);
704
705 std::string title = net::EscapeQueryParamValue(
706 UTF16ToUTF8(wc->GetTitle()), false);
707 std::string page_url = net::EscapeQueryParamValue(wc->GetURL().spec(), false);
708 std::string mailto = std::string("mailto:?subject=Fwd:%20") +
709 title + "&body=%0A%0A" + page_url;
710 platform_util::OpenExternal(GURL(mailto));
711}
712
[email protected]5d98294912012-06-27 22:57:40713bool CanEmailPageLocation(const Browser* browser) {
714 return browser->toolbar_model()->ShouldDisplayURL() &&
[email protected]52877dbc62012-06-29 22:22:03715 GetActiveWebContents(browser)->GetURL().is_valid();
[email protected]5d98294912012-06-27 22:57:40716}
717
[email protected]a37d4b02012-06-25 21:56:10718void Cut(Browser* browser) {
719 content::RecordAction(UserMetricsAction("Cut"));
720 browser->window()->Cut();
721}
722
723void Copy(Browser* browser) {
724 content::RecordAction(UserMetricsAction("Copy"));
725 browser->window()->Copy();
726}
727
728void Paste(Browser* browser) {
729 content::RecordAction(UserMetricsAction("Paste"));
730 browser->window()->Paste();
731}
732
733void Find(Browser* browser) {
734 content::RecordAction(UserMetricsAction("Find"));
735 FindInPage(browser, false, false);
736}
737
738void FindNext(Browser* browser) {
739 content::RecordAction(UserMetricsAction("FindNext"));
740 FindInPage(browser, true, true);
741}
742
743void FindPrevious(Browser* browser) {
744 content::RecordAction(UserMetricsAction("FindPrevious"));
745 FindInPage(browser, true, false);
746}
747
748void FindInPage(Browser* browser, bool find_next, bool forward_direction) {
749 ShowFindBar(browser);
750 if (find_next) {
751 string16 find_text;
752#if defined(OS_MACOSX)
753 // We always want to search for the contents of the find pasteboard on OS X.
754 find_text = GetFindPboardText();
755#endif
[email protected]52877dbc62012-06-29 22:22:03756 GetActiveTabContents(browser)->
[email protected]a37d4b02012-06-25 21:56:10757 find_tab_helper()->StartFinding(find_text,
758 forward_direction,
759 false); // Not case sensitive.
760 }
761}
762
763void Zoom(Browser* browser, content::PageZoom zoom) {
764 if (browser->is_devtools())
765 return;
766
[email protected]8233cbc2012-07-13 16:14:52767 chrome_page_zoom::Zoom(GetActiveWebContents(browser), zoom);
[email protected]a37d4b02012-06-25 21:56:10768}
769
770void FocusToolbar(Browser* browser) {
771 content::RecordAction(UserMetricsAction("FocusToolbar"));
772 browser->window()->FocusToolbar();
773}
774
775void FocusLocationBar(Browser* browser) {
776 content::RecordAction(UserMetricsAction("FocusLocation"));
777 browser->window()->SetFocusToLocationBar(true);
778}
779
780void FocusSearch(Browser* browser) {
781 // TODO(beng): replace this with FocusLocationBar
782 content::RecordAction(UserMetricsAction("FocusSearch"));
783 browser->window()->GetLocationBar()->FocusSearch();
784}
785
786void FocusAppMenu(Browser* browser) {
787 content::RecordAction(UserMetricsAction("FocusAppMenu"));
788 browser->window()->FocusAppMenu();
789}
790
791void FocusBookmarksToolbar(Browser* browser) {
792 content::RecordAction(UserMetricsAction("FocusBookmarksToolbar"));
793 browser->window()->FocusBookmarksToolbar();
794}
795
796void FocusNextPane(Browser* browser) {
797 content::RecordAction(UserMetricsAction("FocusNextPane"));
798 browser->window()->RotatePaneFocus(true);
799}
800
801void FocusPreviousPane(Browser* browser) {
802 content::RecordAction(UserMetricsAction("FocusPreviousPane"));
803 browser->window()->RotatePaneFocus(false);
804}
805
806void ToggleDevToolsWindow(Browser* browser, DevToolsToggleAction action) {
807 if (action == DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE)
808 content::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
809 else
810 content::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
811
812 DevToolsWindow::ToggleDevToolsWindow(
[email protected]52877dbc62012-06-29 22:22:03813 GetActiveWebContents(browser)->GetRenderViewHost(),
[email protected]a37d4b02012-06-25 21:56:10814 action);
815}
816
817bool CanOpenTaskManager() {
818#if defined(OS_WIN)
819 // In metro we can't display the task manager, as it is a native window.
820 return !base::win::IsMetroProcess();
821#else
822 return true;
823#endif
824}
825
826void OpenTaskManager(Browser* browser, bool highlight_background_resources) {
827 content::RecordAction(UserMetricsAction("TaskManager"));
828 if (highlight_background_resources)
829 browser->window()->ShowBackgroundPages();
830 else
831 browser->window()->ShowTaskManager();
832}
833
834void OpenFeedbackDialog(Browser* browser) {
835 content::RecordAction(UserMetricsAction("Feedback"));
836 browser::ShowWebFeedbackView(browser, std::string(), std::string());
837}
838
839void ToggleBookmarkBar(Browser* browser) {
840 content::RecordAction(UserMetricsAction("ShowBookmarksBar"));
841 browser->window()->ToggleBookmarkBar();
842}
843
844void ShowAppMenu(Browser* browser) {
845 // We record the user metric for this event in WrenchMenu::RunMenu.
846 browser->window()->ShowAppMenu();
847}
848
849void ShowAvatarMenu(Browser* browser) {
850 browser->window()->ShowAvatarBubbleFromAvatarButton();
851}
852
853void OpenUpdateChromeDialog(Browser* browser) {
854 content::RecordAction(UserMetricsAction("UpdateChrome"));
855 browser->window()->ShowUpdateChromeDialog();
856}
857
858void ToggleSpeechInput(Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03859 GetActiveWebContents(browser)->GetRenderViewHost()->ToggleSpeechInput();
[email protected]a37d4b02012-06-25 21:56:10860}
861
[email protected]3f32b9b2012-07-09 16:59:28862void ToggleFullscreenMode(Browser* browser) {
863 browser->fullscreen_controller()->ToggleFullscreenMode();
864}
865
[email protected]d3446bda2012-07-12 14:24:39866void ClearCache(Browser* browser) {
867 BrowsingDataRemover* remover = new BrowsingDataRemover(browser->profile(),
868 BrowsingDataRemover::EVERYTHING,
869 base::Time());
870 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
871 BrowsingDataHelper::UNPROTECTED_WEB);
872 // BrowsingDataRemover takes care of deleting itself when done.
873}
874
875bool IsDebuggerAttachedToCurrentTab(Browser* browser) {
876 WebContents* contents = chrome::GetActiveWebContents(browser);
877 return contents ?
878 content::DevToolsAgentHostRegistry::IsDebuggerAttached(contents) : false;
879}
880
[email protected]2cd4fde2012-06-26 03:10:26881void ViewSource(Browser* browser, TabContents* contents) {
882 DCHECK(contents);
883
884 NavigationEntry* active_entry =
885 contents->web_contents()->GetController().GetActiveEntry();
886 if (!active_entry)
887 return;
888
889 ViewSource(browser, contents, active_entry->GetURL(),
890 active_entry->GetContentState());
891}
892
893void ViewSource(Browser* browser,
894 TabContents* contents,
895 const GURL& url,
896 const std::string& content_state) {
897 content::RecordAction(UserMetricsAction("ViewSource"));
898 DCHECK(contents);
899
900 TabContents* view_source_contents = contents->Clone();
901 view_source_contents->web_contents()->GetController().PruneAllButActive();
902 NavigationEntry* active_entry =
903 view_source_contents->web_contents()->GetController().GetActiveEntry();
904 if (!active_entry)
905 return;
906
[email protected]52877dbc62012-06-29 22:22:03907 GURL view_source_url = GURL(kViewSourceScheme + std::string(":") +
[email protected]2cd4fde2012-06-26 03:10:26908 url.spec());
909 active_entry->SetVirtualURL(view_source_url);
910
911 // Do not restore scroller position.
912 active_entry->SetContentState(
913 webkit_glue::RemoveScrollOffsetFromHistoryState(content_state));
914
915 // Do not restore title, derive it from the url.
916 active_entry->SetTitle(string16());
917
918 // Now show view-source entry.
919 if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
920 // If this is a tabbed browser, just create a duplicate tab inside the same
921 // window next to the tab being duplicated.
922 int index = browser->tab_strip_model()->GetIndexOfTabContents(contents);
923 int add_types = TabStripModel::ADD_ACTIVE |
924 TabStripModel::ADD_INHERIT_GROUP;
925 browser->tab_strip_model()->InsertTabContentsAt(index + 1,
926 view_source_contents,
927 add_types);
928 } else {
929 Browser* b = Browser::CreateWithParams(
930 Browser::CreateParams(Browser::TYPE_TABBED, browser->profile()));
931
932 // Preserve the size of the original window. The new window has already
933 // been given an offset by the OS, so we shouldn't copy the old bounds.
934 BrowserWindow* new_window = b->window();
935 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
936 browser->window()->GetRestoredBounds().size()));
937
938 // We need to show the browser now. Otherwise ContainerWin assumes the
939 // WebContents is invisible and won't size it.
940 b->window()->Show();
941
942 // The page transition below is only for the purpose of inserting the tab.
[email protected]855370052012-07-10 19:30:32943 AddTab(b, view_source_contents, content::PAGE_TRANSITION_LINK);
[email protected]2cd4fde2012-06-26 03:10:26944 }
945
946 SessionService* session_service =
947 SessionServiceFactory::GetForProfileIfExisting(browser->profile());
948 if (session_service)
949 session_service->TabRestored(view_source_contents, false);
950}
951
952void ViewSelectedSource(Browser* browser) {
[email protected]855370052012-07-10 19:30:32953 ViewSource(browser, GetActiveTabContents(browser));
[email protected]2cd4fde2012-06-26 03:10:26954}
955
[email protected]5d98294912012-06-27 22:57:40956bool CanViewSource(const Browser* browser) {
[email protected]855370052012-07-10 19:30:32957 return GetActiveWebContents(browser)->GetController().CanViewSource();
[email protected]5d98294912012-06-27 22:57:40958}
959
[email protected]619f86182012-07-03 21:30:18960void CreateApplicationShortcuts(Browser* browser) {
961 content::RecordAction(UserMetricsAction("CreateShortcut"));
[email protected]855370052012-07-10 19:30:32962 GetActiveTabContents(browser)->extension_tab_helper()->
[email protected]619f86182012-07-03 21:30:18963 CreateApplicationShortcuts();
964}
965
[email protected]5d98294912012-06-27 22:57:40966bool CanCreateApplicationShortcuts(const Browser* browser) {
[email protected]855370052012-07-10 19:30:32967 return GetActiveTabContents(browser)->extension_tab_helper()->
[email protected]619f86182012-07-03 21:30:18968 CanCreateApplicationShortcuts();
[email protected]5d98294912012-06-27 22:57:40969}
970
[email protected]40df6f52012-06-28 17:08:52971void ConvertTabToAppWindow(Browser* browser,
972 content::WebContents* contents) {
973 const GURL& url = contents->GetController().GetActiveEntry()->GetURL();
974 std::string app_name = web_app::GenerateApplicationNameFromURL(url);
975
976 int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
977 if (index >= 0)
978 browser->tab_strip_model()->DetachTabContentsAt(index);
979
980 Browser* app_browser = Browser::CreateWithParams(
981 Browser::CreateParams::CreateForApp(
982 Browser::TYPE_POPUP, app_name, gfx::Rect(), browser->profile()));
983 TabContents* tab_contents = TabContents::FromWebContents(contents);
984 if (!tab_contents)
985 tab_contents = new TabContents(contents);
986 app_browser->tab_strip_model()->AppendTabContents(tab_contents, true);
987
988 contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
989 contents->GetRenderViewHost()->SyncRendererPrefs();
990 app_browser->window()->Show();
991}
992
[email protected]a37d4b02012-06-25 21:56:10993} // namespace chrome