blob: bab9d2e28fffd9f8cd10b0f1943d5664217cd924 [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]a37d4b02012-06-25 21:56:1010#include "chrome/browser/bookmarks/bookmark_model.h"
[email protected]4f7490ef2012-07-31 08:49:0311#include "chrome/browser/bookmarks/bookmark_model_factory.h"
[email protected]a37d4b02012-06-25 21:56:1012#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"
[email protected]72ea827d2012-09-28 01:30:5522#include "chrome/browser/google/google_util.h"
[email protected]a37d4b02012-06-25 21:56:1023#include "chrome/browser/lifetime/application_lifetime.h"
24#include "chrome/browser/platform_util.h"
25#include "chrome/browser/prefs/incognito_mode_prefs.h"
26#include "chrome/browser/prefs/pref_service.h"
[email protected]5d98294912012-06-27 22:57:4027#include "chrome/browser/printing/print_preview_tab_controller.h"
[email protected]a37d4b02012-06-25 21:56:1028#include "chrome/browser/printing/print_view_manager.h"
29#include "chrome/browser/profiles/profile.h"
[email protected]72ea827d2012-09-28 01:30:5530#include "chrome/browser/rlz/rlz.h"
[email protected]a37d4b02012-06-25 21:56:1031#include "chrome/browser/sessions/session_service_factory.h"
[email protected]a37d4b02012-06-25 21:56:1032#include "chrome/browser/sessions/tab_restore_service.h"
[email protected]5d98294912012-06-27 22:57:4033#include "chrome/browser/sessions/tab_restore_service_delegate.h"
[email protected]78e2edc2012-07-01 23:32:2834#include "chrome/browser/sessions/tab_restore_service_factory.h"
[email protected]345d7d32012-10-03 23:10:1835#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
[email protected]a37d4b02012-06-25 21:56:1036#include "chrome/browser/ui/browser.h"
[email protected]5d98294912012-06-27 22:57:4037#include "chrome/browser/ui/browser_command_controller.h"
[email protected]a37d4b02012-06-25 21:56:1038#include "chrome/browser/ui/browser_finder.h"
[email protected]7acfaf92012-07-11 15:51:5939#include "chrome/browser/ui/browser_instant_controller.h"
[email protected]5d98294912012-06-27 22:57:4040#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
[email protected]52877dbc62012-06-29 22:22:0341#include "chrome/browser/ui/browser_tabstrip.h"
[email protected]a37d4b02012-06-25 21:56:1042#include "chrome/browser/ui/browser_window.h"
[email protected]7a19ea22012-08-02 14:39:3943#include "chrome/browser/ui/chrome_pages.h"
[email protected]5d98294912012-06-27 22:57:4044#include "chrome/browser/ui/constrained_window_tab_helper.h"
[email protected]a37d4b02012-06-25 21:56:1045#include "chrome/browser/ui/find_bar/find_bar_controller.h"
46#include "chrome/browser/ui/find_bar/find_tab_helper.h"
[email protected]3f32b9b2012-07-09 16:59:2847#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
[email protected]ffe6de62012-07-19 00:02:3548#include "chrome/browser/ui/metro_pin_tab_helper.h"
[email protected]a37d4b02012-06-25 21:56:1049#include "chrome/browser/ui/omnibox/location_bar.h"
[email protected]43aafff2012-06-29 21:20:4950#include "chrome/browser/ui/search/search.h"
51#include "chrome/browser/ui/search/search_model.h"
[email protected]a37d4b02012-06-25 21:56:1052#include "chrome/browser/ui/status_bubble.h"
53#include "chrome/browser/ui/tab_contents/tab_contents.h"
54#include "chrome/browser/ui/tabs/tab_strip_model.h"
[email protected]a37d4b02012-06-25 21:56:1055#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
[email protected]5d98294912012-06-27 22:57:4056#include "chrome/browser/web_applications/web_app.h"
[email protected]a37d4b02012-06-25 21:56:1057#include "chrome/common/chrome_switches.h"
[email protected]a37d4b02012-06-25 21:56:1058#include "chrome/common/pref_names.h"
[email protected]d3446bda2012-07-12 14:24:3959#include "content/public/browser/devtools_agent_host_registry.h"
[email protected]a37d4b02012-06-25 21:56:1060#include "content/public/browser/navigation_controller.h"
61#include "content/public/browser/navigation_entry.h"
62#include "content/public/browser/page_navigator.h"
63#include "content/public/browser/render_view_host.h"
64#include "content/public/browser/user_metrics.h"
65#include "content/public/browser/web_contents.h"
66#include "content/public/browser/web_contents_view.h"
[email protected]6c2d6eb2012-09-01 00:06:3167#include "content/public/browser/web_intents_dispatcher.h"
[email protected]9b7ab882012-09-10 23:46:3668#include "content/public/common/content_client.h"
[email protected]78e2edc2012-07-01 23:32:2869#include "content/public/common/content_restriction.h"
70#include "content/public/common/renderer_preferences.h"
[email protected]2cd4fde2012-06-26 03:10:2671#include "content/public/common/url_constants.h"
[email protected]a37d4b02012-06-25 21:56:1072#include "net/base/escape.h"
[email protected]6c2d6eb2012-09-01 00:06:3173#include "webkit/glue/web_intent_data.h"
[email protected]2cd4fde2012-06-26 03:10:2674#include "webkit/glue/webkit_glue.h"
[email protected]9b7ab882012-09-10 23:46:3675#include "webkit/user_agent/user_agent_util.h"
[email protected]a37d4b02012-06-25 21:56:1076
77#if defined(OS_MACOSX)
78#include "ui/base/cocoa/find_pasteboard.h"
79#endif
80
81#if defined(OS_WIN)
82#include "base/win/metro.h"
83#endif
84
[email protected]9b7ab882012-09-10 23:46:3685namespace {
86const char kOsOverrideForTabletSite[] = "Linux; Android 4.0.3";
87}
88
[email protected]a37d4b02012-06-25 21:56:1089using content::NavigationController;
90using content::NavigationEntry;
91using content::OpenURLParams;
92using content::Referrer;
93using content::SSLStatus;
94using content::UserMetricsAction;
95using content::WebContents;
96
[email protected]f250fd52012-08-27 20:09:3797// TODO(avi): Kill this when TabContents goes away.
98class BrowserCommandsTabContentsCreator {
99 public:
100 static TabContents* CreateTabContents(content::WebContents* contents) {
101 return TabContents::Factory::CreateTabContents(contents);
102 }
103 static TabContents* CloneTabContents(TabContents* contents) {
104 return TabContents::Factory::CloneTabContents(contents);
105 }
106};
107
[email protected]a37d4b02012-06-25 21:56:10108namespace chrome {
109namespace {
110
111WebContents* GetOrCloneTabForDisposition(Browser* browser,
112 WindowOpenDisposition disposition) {
[email protected]855370052012-07-10 19:30:32113 TabContents* current_tab = GetActiveTabContents(browser);
[email protected]a37d4b02012-06-25 21:56:10114 switch (disposition) {
115 case NEW_FOREGROUND_TAB:
116 case NEW_BACKGROUND_TAB: {
[email protected]f250fd52012-08-27 20:09:37117 current_tab =
118 BrowserCommandsTabContentsCreator::CloneTabContents(current_tab);
[email protected]a37d4b02012-06-25 21:56:10119 browser->tab_strip_model()->AddTabContents(
120 current_tab, -1, content::PAGE_TRANSITION_LINK,
121 disposition == NEW_FOREGROUND_TAB ? TabStripModel::ADD_ACTIVE :
122 TabStripModel::ADD_NONE);
123 break;
124 }
125 case NEW_WINDOW: {
[email protected]f250fd52012-08-27 20:09:37126 current_tab =
127 BrowserCommandsTabContentsCreator::CloneTabContents(current_tab);
[email protected]a4fe67012012-07-25 20:14:29128 Browser* b = new Browser(Browser::CreateParams(browser->profile()));
[email protected]a37d4b02012-06-25 21:56:10129 b->tab_strip_model()->AddTabContents(
130 current_tab, -1, content::PAGE_TRANSITION_LINK,
131 TabStripModel::ADD_ACTIVE);
132 b->window()->Show();
133 break;
134 }
135 default:
136 break;
137 }
138 return current_tab->web_contents();
139}
140
141void ReloadInternal(Browser* browser,
142 WindowOpenDisposition disposition,
143 bool ignore_cache) {
[email protected]a37d4b02012-06-25 21:56:10144 // As this is caused by a user action, give the focus to the page.
145 //
146 // Also notify RenderViewHostDelegate of the user gesture; this is
147 // normally done in Browser::Navigate, but a reload bypasses Navigate.
148 WebContents* web_contents = GetOrCloneTabForDisposition(browser, disposition);
149 web_contents->UserGestureDone();
150 if (!web_contents->FocusLocationBarByDefault())
151 web_contents->Focus();
152 if (ignore_cache)
153 web_contents->GetController().ReloadIgnoringCache(true);
154 else
155 web_contents->GetController().Reload(true);
156}
157
[email protected]5d98294912012-06-27 22:57:40158bool HasConstrainedWindow(const Browser* browser) {
[email protected]c6464ad2012-10-03 00:27:28159 WebContents* web_contents = GetActiveWebContents(browser);
160 if (!web_contents)
161 return false;
162
163 ConstrainedWindowTabHelper* constrained_window_tab_helper =
164 ConstrainedWindowTabHelper::FromWebContents(web_contents);
165 return constrained_window_tab_helper->constrained_window_count() > 0;
[email protected]5d98294912012-06-27 22:57:40166}
167
168bool PrintPreviewShowing(const Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03169 TabContents* contents = GetActiveTabContents(browser);
[email protected]5d98294912012-06-27 22:57:40170 printing::PrintPreviewTabController* controller =
171 printing::PrintPreviewTabController::GetInstance();
172 return controller && (controller->GetPrintPreviewForTab(contents) ||
173 controller->is_creating_print_preview_tab());
174}
175
[email protected]db9747252012-07-02 19:28:00176bool IsNTPModeForInstantExtendedAPI(const Browser* browser) {
177 return browser->search_model() &&
[email protected]855370052012-07-10 19:30:32178 search::IsInstantExtendedAPIEnabled(browser->profile()) &&
179 browser->search_model()->mode().is_ntp();
[email protected]db9747252012-07-02 19:28:00180}
181
[email protected]a37d4b02012-06-25 21:56:10182} // namespace
183
[email protected]5d98294912012-06-27 22:57:40184bool IsCommandEnabled(Browser* browser, int command) {
185 return browser->command_controller()->command_updater()->IsCommandEnabled(
186 command);
187}
188
189bool SupportsCommand(Browser* browser, int command) {
190 return browser->command_controller()->command_updater()->SupportsCommand(
191 command);
192}
193
194bool ExecuteCommand(Browser* browser, int command) {
195 return browser->command_controller()->command_updater()->ExecuteCommand(
196 command);
197}
198
199bool ExecuteCommandWithDisposition(Browser* browser,
200 int command,
201 WindowOpenDisposition disposition) {
202 return browser->command_controller()->command_updater()->
203 ExecuteCommandWithDisposition(command, disposition);
204}
205
206void UpdateCommandEnabled(Browser* browser, int command, bool enabled) {
207 browser->command_controller()->command_updater()->UpdateCommandEnabled(
208 command, enabled);
209}
210
211void AddCommandObserver(Browser* browser,
212 int command,
213 CommandObserver* observer) {
214 browser->command_controller()->command_updater()->AddCommandObserver(
215 command, observer);
216}
217
218void RemoveCommandObserver(Browser* browser,
219 int command,
220 CommandObserver* observer) {
221 browser->command_controller()->command_updater()->RemoveCommandObserver(
222 command, observer);
223}
224
225int GetContentRestrictions(const Browser* browser) {
226 int content_restrictions = 0;
[email protected]52877dbc62012-06-29 22:22:03227 WebContents* current_tab = GetActiveWebContents(browser);
[email protected]5d98294912012-06-27 22:57:40228 if (current_tab) {
229 content_restrictions = current_tab->GetContentRestrictions();
230 NavigationEntry* active_entry =
231 current_tab->GetController().GetActiveEntry();
232 // See comment in UpdateCommandsForTabState about why we call url().
233 if (!download_util::IsSavableURL(
234 active_entry ? active_entry->GetURL() : GURL()) ||
235 current_tab->ShowingInterstitialPage())
236 content_restrictions |= content::CONTENT_RESTRICTION_SAVE;
237 if (current_tab->ShowingInterstitialPage())
238 content_restrictions |= content::CONTENT_RESTRICTION_PRINT;
239 }
240 return content_restrictions;
241}
242
[email protected]a37d4b02012-06-25 21:56:10243void NewEmptyWindow(Profile* profile) {
244 bool incognito = profile->IsOffTheRecord();
245 PrefService* prefs = profile->GetPrefs();
246 if (incognito) {
247 if (IncognitoModePrefs::GetAvailability(prefs) ==
248 IncognitoModePrefs::DISABLED) {
249 incognito = false;
250 }
251 } else {
252 if (browser_defaults::kAlwaysOpenIncognitoWindow &&
253 IncognitoModePrefs::ShouldLaunchIncognito(
254 *CommandLine::ForCurrentProcess(), prefs)) {
255 incognito = true;
256 }
257 }
258
259 if (incognito) {
260 content::RecordAction(UserMetricsAction("NewIncognitoWindow"));
261 OpenEmptyWindow(profile->GetOffTheRecordProfile());
262 } else {
263 content::RecordAction(UserMetricsAction("NewWindow"));
264 SessionService* session_service =
265 SessionServiceFactory::GetForProfile(profile->GetOriginalProfile());
266 if (!session_service ||
267 !session_service->RestoreIfNecessary(std::vector<GURL>())) {
268 OpenEmptyWindow(profile->GetOriginalProfile());
269 }
270 }
271}
272
273Browser* OpenEmptyWindow(Profile* profile) {
[email protected]a4fe67012012-07-25 20:14:29274 Browser* browser = new Browser(Browser::CreateParams(profile));
[email protected]855370052012-07-10 19:30:32275 AddBlankTab(browser, true);
[email protected]a37d4b02012-06-25 21:56:10276 browser->window()->Show();
277 return browser;
278}
279
280void OpenWindowWithRestoredTabs(Profile* profile) {
281 TabRestoreService* service = TabRestoreServiceFactory::GetForProfile(profile);
282 if (service)
283 service->RestoreMostRecentEntry(NULL);
284}
285
[email protected]3b14b7f22012-10-04 01:29:09286void OpenURLOffTheRecord(Profile* profile,
287 const GURL& url,
288 chrome::HostDesktopType desktop_type) {
[email protected]a37d4b02012-06-25 21:56:10289 Browser* browser = browser::FindOrCreateTabbedBrowser(
[email protected]3b14b7f22012-10-04 01:29:09290 profile->GetOffTheRecordProfile(), desktop_type);
[email protected]52877dbc62012-06-29 22:22:03291 AddSelectedTabWithURL(browser, url, content::PAGE_TRANSITION_LINK);
[email protected]a37d4b02012-06-25 21:56:10292 browser->window()->Show();
293}
294
[email protected]5d98294912012-06-27 22:57:40295bool CanGoBack(const Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03296 return GetActiveWebContents(browser)->GetController().CanGoBack();
[email protected]a37d4b02012-06-25 21:56:10297}
298
299void GoBack(Browser* browser, WindowOpenDisposition disposition) {
300 content::RecordAction(UserMetricsAction("Back"));
301
[email protected]52877dbc62012-06-29 22:22:03302 TabContents* current_tab = GetActiveTabContents(browser);
[email protected]a37d4b02012-06-25 21:56:10303 if (CanGoBack(browser)) {
304 WebContents* new_tab = GetOrCloneTabForDisposition(browser, disposition);
305 // If we are on an interstitial page and clone the tab, it won't be copied
306 // to the new tab, so we don't need to go back.
307 if (current_tab->web_contents()->ShowingInterstitialPage() &&
308 (new_tab != current_tab->web_contents()))
309 return;
310 new_tab->GetController().GoBack();
311 }
312}
313
[email protected]5d98294912012-06-27 22:57:40314bool CanGoForward(const Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03315 return GetActiveWebContents(browser)->GetController().CanGoForward();
[email protected]a37d4b02012-06-25 21:56:10316}
317
318void GoForward(Browser* browser, WindowOpenDisposition disposition) {
319 content::RecordAction(UserMetricsAction("Forward"));
320 if (CanGoForward(browser)) {
321 GetOrCloneTabForDisposition(browser, disposition)->
322 GetController().GoForward();
323 }
324}
325
326bool NavigateToIndexWithDisposition(Browser* browser,
327 int index,
328 WindowOpenDisposition disp) {
329 NavigationController& controller =
330 GetOrCloneTabForDisposition(browser, disp)->GetController();
331 if (index < 0 || index >= controller.GetEntryCount())
332 return false;
333 controller.GoToIndex(index);
334 return true;
335}
336
337void Reload(Browser* browser, WindowOpenDisposition disposition) {
338 content::RecordAction(UserMetricsAction("Reload"));
339 ReloadInternal(browser, disposition, false);
340}
341
342void ReloadIgnoringCache(Browser* browser, WindowOpenDisposition disposition) {
343 content::RecordAction(UserMetricsAction("ReloadIgnoringCache"));
344 ReloadInternal(browser, disposition, true);
345}
346
[email protected]5d98294912012-06-27 22:57:40347bool CanReload(const Browser* browser) {
[email protected]db9747252012-07-02 19:28:00348 return !browser->is_devtools() && !IsNTPModeForInstantExtendedAPI(browser);
[email protected]5d98294912012-06-27 22:57:40349}
350
[email protected]a37d4b02012-06-25 21:56:10351void Home(Browser* browser, WindowOpenDisposition disposition) {
352 content::RecordAction(UserMetricsAction("Home"));
[email protected]72ea827d2012-09-28 01:30:55353
354 std::string extra_headers;
355#if defined(ENABLE_RLZ)
356 // If the home page is a Google home page, add the RLZ header to the request.
357 PrefService* pref_service = browser->profile()->GetPrefs();
358 if (pref_service) {
359 std::string home_page = pref_service->GetString(prefs::kHomePage);
360 if (google_util::IsGoogleHomePageUrl(home_page)) {
361 extra_headers = RLZTracker::GetAccessPointHttpHeader(
362 rlz_lib::CHROME_HOME_PAGE);
363 }
364 }
365#endif
366
367 OpenURLParams params(
[email protected]a37d4b02012-06-25 21:56:10368 browser->profile()->GetHomePage(), Referrer(), disposition,
369 content::PageTransitionFromInt(
370 content::PAGE_TRANSITION_AUTO_BOOKMARK |
371 content::PAGE_TRANSITION_HOME_PAGE),
[email protected]72ea827d2012-09-28 01:30:55372 false);
373 params.extra_headers = extra_headers;
374 browser->OpenURL(params);
[email protected]a37d4b02012-06-25 21:56:10375}
376
377void OpenCurrentURL(Browser* browser) {
378 content::RecordAction(UserMetricsAction("LoadURL"));
379 LocationBar* location_bar = browser->window()->GetLocationBar();
380 if (!location_bar)
381 return;
382
383 WindowOpenDisposition open_disposition =
384 location_bar->GetWindowOpenDisposition();
[email protected]7acfaf92012-07-11 15:51:59385 if (browser->instant_controller()->OpenInstant(open_disposition))
[email protected]a37d4b02012-06-25 21:56:10386 return;
387
388 GURL url(location_bar->GetInputString());
389
[email protected]855370052012-07-10 19:30:32390 NavigateParams params(browser, url, location_bar->GetPageTransition());
[email protected]a37d4b02012-06-25 21:56:10391 params.disposition = open_disposition;
392 // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
393 // inherit the opener. In some cases the tabstrip will determine the group
394 // should be inherited, in which case the group is inherited instead of the
395 // opener.
396 params.tabstrip_add_types =
397 TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
[email protected]855370052012-07-10 19:30:32398 Navigate(&params);
[email protected]a37d4b02012-06-25 21:56:10399
400 DCHECK(browser->profile()->GetExtensionService());
401 if (browser->profile()->GetExtensionService()->IsInstalledApp(url)) {
402 AppLauncherHandler::RecordAppLaunchType(
403 extension_misc::APP_LAUNCH_OMNIBOX_LOCATION);
404 }
405}
406
407void Stop(Browser* browser) {
408 content::RecordAction(UserMetricsAction("Stop"));
[email protected]52877dbc62012-06-29 22:22:03409 GetActiveWebContents(browser)->Stop();
[email protected]a37d4b02012-06-25 21:56:10410}
411
412#if !defined(OS_WIN)
413void NewWindow(Browser* browser) {
414 NewEmptyWindow(browser->profile()->GetOriginalProfile());
415}
416
417void NewIncognitoWindow(Browser* browser) {
418 NewEmptyWindow(browser->profile()->GetOffTheRecordProfile());
419}
420#endif // OS_WIN
421
422void CloseWindow(Browser* browser) {
423 content::RecordAction(UserMetricsAction("CloseWindow"));
424 browser->window()->Close();
425}
426
427void NewTab(Browser* browser) {
428 content::RecordAction(UserMetricsAction("NewTab"));
429 // TODO(asvitkine): This is invoked programmatically from several places.
430 // Audit the code and change it so that the histogram only gets collected for
431 // user-initiated commands.
432 UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
433 TabStripModel::NEW_TAB_ENUM_COUNT);
434
435 if (browser->is_type_tabbed()) {
[email protected]855370052012-07-10 19:30:32436 AddBlankTab(browser, true);
[email protected]52877dbc62012-06-29 22:22:03437 GetActiveWebContents(browser)->GetView()->RestoreFocus();
[email protected]a37d4b02012-06-25 21:56:10438 } else {
[email protected]3b14b7f22012-10-04 01:29:09439 Browser* b =
440 browser::FindOrCreateTabbedBrowser(browser->profile(),
441 browser->host_desktop_type());
[email protected]855370052012-07-10 19:30:32442 AddBlankTab(b, true);
[email protected]a37d4b02012-06-25 21:56:10443 b->window()->Show();
444 // The call to AddBlankTab above did not set the focus to the tab as its
445 // window was not active, so we have to do it explicitly.
446 // See http://crbug.com/6380.
[email protected]855370052012-07-10 19:30:32447 GetActiveWebContents(b)->GetView()->RestoreFocus();
[email protected]a37d4b02012-06-25 21:56:10448 }
449}
450
451void CloseTab(Browser* browser) {
452 content::RecordAction(UserMetricsAction("CloseTab_Accelerator"));
453 browser->tab_strip_model()->CloseSelectedTabs();
454}
455
[email protected]5d98294912012-06-27 22:57:40456void RestoreTab(Browser* browser) {
457 content::RecordAction(UserMetricsAction("RestoreTab"));
458 TabRestoreService* service =
459 TabRestoreServiceFactory::GetForProfile(browser->profile());
460 if (service)
461 service->RestoreMostRecentEntry(browser->tab_restore_service_delegate());
462}
463
464bool CanRestoreTab(const Browser* browser) {
465 TabRestoreService* service =
466 TabRestoreServiceFactory::GetForProfile(browser->profile());
467 return service && !service->entries().empty();
468}
469
[email protected]a37d4b02012-06-25 21:56:10470void SelectNextTab(Browser* browser) {
471 content::RecordAction(UserMetricsAction("SelectNextTab"));
472 browser->tab_strip_model()->SelectNextTab();
473}
474
475void SelectPreviousTab(Browser* browser) {
476 content::RecordAction(UserMetricsAction("SelectPrevTab"));
477 browser->tab_strip_model()->SelectPreviousTab();
478}
479
480void OpenTabpose(Browser* browser) {
481#if defined(OS_MACOSX)
482 if (!CommandLine::ForCurrentProcess()->HasSwitch(
483 switches::kEnableExposeForTabs)) {
484 return;
485 }
486
487 content::RecordAction(UserMetricsAction("OpenTabpose"));
488 browser->window()->OpenTabpose();
489#else
490 NOTREACHED();
491#endif
492}
493
494void MoveTabNext(Browser* browser) {
495 content::RecordAction(UserMetricsAction("MoveTabNext"));
496 browser->tab_strip_model()->MoveTabNext();
497}
498
499void MoveTabPrevious(Browser* browser) {
500 content::RecordAction(UserMetricsAction("MoveTabPrevious"));
501 browser->tab_strip_model()->MoveTabPrevious();
502}
503
504void SelectNumberedTab(Browser* browser, int index) {
505 if (index < browser->tab_count()) {
506 content::RecordAction(UserMetricsAction("SelectNumberedTab"));
[email protected]52877dbc62012-06-29 22:22:03507 ActivateTabAt(browser, index, true);
[email protected]a37d4b02012-06-25 21:56:10508 }
509}
510
511void SelectLastTab(Browser* browser) {
512 content::RecordAction(UserMetricsAction("SelectLastTab"));
513 browser->tab_strip_model()->SelectLastTab();
514}
515
516void DuplicateTab(Browser* browser) {
517 content::RecordAction(UserMetricsAction("Duplicate"));
[email protected]855370052012-07-10 19:30:32518 DuplicateTabAt(browser, browser->active_index());
[email protected]a37d4b02012-06-25 21:56:10519}
520
[email protected]5d98294912012-06-27 22:57:40521bool CanDuplicateTab(const Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03522 WebContents* contents = GetActiveWebContents(browser);
[email protected]5d98294912012-06-27 22:57:40523 return contents && contents->GetController().GetLastCommittedEntry();
524}
525
[email protected]37bb5822012-09-10 15:09:57526TabContents* DuplicateTabAt(Browser* browser, int index) {
[email protected]855370052012-07-10 19:30:32527 TabContents* contents = GetTabContentsAt(browser, index);
528 CHECK(contents);
[email protected]f250fd52012-08-27 20:09:37529 TabContents* contents_dupe =
530 BrowserCommandsTabContentsCreator::CloneTabContents(contents);
[email protected]855370052012-07-10 19:30:32531
532 bool pinned = false;
533 if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
534 // If this is a tabbed browser, just create a duplicate tab inside the same
535 // window next to the tab being duplicated.
536 int index = browser->tab_strip_model()->GetIndexOfTabContents(contents);
537 pinned = browser->tab_strip_model()->IsTabPinned(index);
538 int add_types = TabStripModel::ADD_ACTIVE |
539 TabStripModel::ADD_INHERIT_GROUP |
540 (pinned ? TabStripModel::ADD_PINNED : 0);
541 browser->tab_strip_model()->InsertTabContentsAt(
542 index + 1, contents_dupe, add_types);
543 } else {
544 Browser* browser = NULL;
545 if (browser->is_app()) {
546 CHECK(!browser->is_type_popup());
547 CHECK(!browser->is_type_panel());
[email protected]a4fe67012012-07-25 20:14:29548 browser = new Browser(
[email protected]855370052012-07-10 19:30:32549 Browser::CreateParams::CreateForApp(Browser::TYPE_POPUP,
550 browser->app_name(),
551 gfx::Rect(),
552 browser->profile()));
553 } else if (browser->is_type_popup()) {
[email protected]a4fe67012012-07-25 20:14:29554 browser = new Browser(
[email protected]855370052012-07-10 19:30:32555 Browser::CreateParams(Browser::TYPE_POPUP, browser->profile()));
556 }
557
558 // Preserve the size of the original window. The new window has already
559 // been given an offset by the OS, so we shouldn't copy the old bounds.
560 BrowserWindow* new_window = browser->window();
561 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
562 browser->window()->GetRestoredBounds().size()));
563
564 // We need to show the browser now. Otherwise ContainerWin assumes the
565 // WebContents is invisible and won't size it.
566 browser->window()->Show();
567
568 // The page transition below is only for the purpose of inserting the tab.
569 AddTab(browser, contents_dupe, content::PAGE_TRANSITION_LINK);
570 }
571
572 SessionService* session_service =
573 SessionServiceFactory::GetForProfileIfExisting(browser->profile());
574 if (session_service)
575 session_service->TabRestored(contents_dupe, pinned);
[email protected]37bb5822012-09-10 15:09:57576 return contents_dupe;
[email protected]855370052012-07-10 19:30:32577}
578
579bool CanDuplicateTabAt(Browser* browser, int index) {
580 content::NavigationController& nc =
581 GetWebContentsAt(browser, index)->GetController();
582 return nc.GetWebContents() && nc.GetLastCommittedEntry();
583}
584
[email protected]a37d4b02012-06-25 21:56:10585void ConvertPopupToTabbedBrowser(Browser* browser) {
586 content::RecordAction(UserMetricsAction("ShowAsTab"));
587 TabContents* contents =
588 browser->tab_strip_model()->DetachTabContentsAt(browser->active_index());
[email protected]a4fe67012012-07-25 20:14:29589 Browser* b = new Browser(Browser::CreateParams(browser->profile()));
[email protected]a37d4b02012-06-25 21:56:10590 b->tab_strip_model()->AppendTabContents(contents, true);
591 b->window()->Show();
592}
593
594void Exit() {
595 content::RecordAction(UserMetricsAction("Exit"));
596 browser::AttemptUserExit();
597}
598
599void BookmarkCurrentPage(Browser* browser) {
600 content::RecordAction(UserMetricsAction("Star"));
601
[email protected]4f7490ef2012-07-31 08:49:03602 BookmarkModel* model =
603 BookmarkModelFactory::GetForProfile(browser->profile());
[email protected]a37d4b02012-06-25 21:56:10604 if (!model || !model->IsLoaded())
605 return; // Ignore requests until bookmarks are loaded.
606
607 GURL url;
608 string16 title;
[email protected]502b5612012-10-02 01:33:10609 WebContents* web_contents = GetActiveWebContents(browser);
610 bookmark_utils::GetURLAndTitleToBookmark(web_contents, &url, &title);
[email protected]a37d4b02012-06-25 21:56:10611 bool was_bookmarked = model->IsBookmarked(url);
[email protected]502b5612012-10-02 01:33:10612 if (!was_bookmarked && web_contents->GetBrowserContext()->IsOffTheRecord()) {
[email protected]a37d4b02012-06-25 21:56:10613 // If we're incognito the favicon may not have been saved. Save it now
614 // so that bookmarks have an icon for the page.
[email protected]502b5612012-10-02 01:33:10615 FaviconTabHelper::FromWebContents(web_contents)->SaveFavicon();
[email protected]a37d4b02012-06-25 21:56:10616 }
617 bookmark_utils::AddIfNotBookmarked(model, url, title);
618 // Make sure the model actually added a bookmark before showing the star. A
619 // bookmark isn't created if the url is invalid.
620 if (browser->window()->IsActive() && model->IsBookmarked(url)) {
621 // Only show the bubble if the window is active, otherwise we may get into
622 // weird situations where the bubble is deleted as soon as it is shown.
623 browser->window()->ShowBookmarkBubble(url, was_bookmarked);
624 }
625}
626
[email protected]5d98294912012-06-27 22:57:40627bool CanBookmarkCurrentPage(const Browser* browser) {
[email protected]4f7490ef2012-07-31 08:49:03628 BookmarkModel* model =
629 BookmarkModelFactory::GetForProfile(browser->profile());
[email protected]5d98294912012-06-27 22:57:40630 return browser_defaults::bookmarks_enabled &&
631 browser->profile()->GetPrefs()->GetBoolean(
632 prefs::kEditBookmarksEnabled) &&
633 model && model->IsLoaded() && browser->is_type_tabbed();
634}
635
636void BookmarkAllTabs(Browser* browser) {
[email protected]345d7d32012-10-03 23:10:18637 chrome::ShowBookmarkAllTabsDialog(browser);
[email protected]5d98294912012-06-27 22:57:40638}
639
640bool CanBookmarkAllTabs(const Browser* browser) {
641 return browser->tab_count() > 1 && CanBookmarkCurrentPage(browser);
642}
643
[email protected]ffe6de62012-07-19 00:02:35644void TogglePagePinnedToStartScreen(Browser* browser) {
[email protected]5ab8d622012-09-07 18:00:48645 MetroPinTabHelper::FromWebContents(GetActiveWebContents(browser))->
[email protected]ffe6de62012-07-19 00:02:35646 TogglePinnedToStartScreen();
[email protected]a37d4b02012-06-25 21:56:10647}
[email protected]a37d4b02012-06-25 21:56:10648
649void SavePage(Browser* browser) {
650 content::RecordAction(UserMetricsAction("SavePage"));
[email protected]52877dbc62012-06-29 22:22:03651 WebContents* current_tab = GetActiveWebContents(browser);
[email protected]a37d4b02012-06-25 21:56:10652 if (current_tab && current_tab->GetContentsMimeType() == "application/pdf")
653 content::RecordAction(UserMetricsAction("PDF.SavePage"));
654 current_tab->OnSavePage();
655}
656
[email protected]5d98294912012-06-27 22:57:40657bool CanSavePage(const Browser* browser) {
658 // LocalState can be NULL in tests.
659 if (g_browser_process->local_state() &&
660 !g_browser_process->local_state()->GetBoolean(
661 prefs::kAllowFileSelectionDialogs)) {
662 return false;
663 }
664 return !browser->is_devtools() &&
665 !(GetContentRestrictions(browser) & content::CONTENT_RESTRICTION_SAVE);
666}
667
[email protected]a37d4b02012-06-25 21:56:10668void ShowFindBar(Browser* browser) {
669 browser->GetFindBarController()->Show();
670}
671
672void ShowPageInfo(Browser* browser,
673 content::WebContents* web_contents,
674 const GURL& url,
675 const SSLStatus& ssl,
676 bool show_history) {
677 Profile* profile = Profile::FromBrowserContext(
678 web_contents->GetBrowserContext());
679 TabContents* tab_contents = TabContents::FromWebContents(web_contents);
680
681 if (CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]9a8e9352012-08-24 00:45:17682 switches::kDisableWebsiteSettings)) {
683 browser->window()->ShowPageInfo(web_contents, url, ssl, show_history);
684 } else {
[email protected]a37d4b02012-06-25 21:56:10685 browser->window()->ShowWebsiteSettings(
686 profile, tab_contents, url, ssl, show_history);
[email protected]a37d4b02012-06-25 21:56:10687 }
688}
689
690void ShowChromeToMobileBubble(Browser* browser) {
691 // Only show the bubble if the window is active, otherwise we may get into
692 // weird situations where the bubble is deleted as soon as it is shown.
693 if (browser->window()->IsActive())
694 browser->window()->ShowChromeToMobileBubble();
695}
696
[email protected]6c2d6eb2012-09-01 00:06:31697void ShareCurrentPage(Browser* browser) {
698 const GURL& current_url = chrome::GetActiveWebContents(browser)->GetURL();
699 webkit_glue::WebIntentData intent_data(
700 ASCIIToUTF16("http://webintents.org/share"),
701 ASCIIToUTF16("text/uri-list"),
702 UTF8ToUTF16(current_url.spec()));
703 scoped_ptr<content::WebIntentsDispatcher> dispatcher(
704 content::WebIntentsDispatcher::Create(intent_data));
705 static_cast<content::WebContentsDelegate*>(browser)->
706 WebIntentDispatch(NULL, dispatcher.release());
707}
708
[email protected]a37d4b02012-06-25 21:56:10709void Print(Browser* browser) {
[email protected]e3a7e6f2012-09-18 22:44:31710 printing::PrintViewManager* print_view_manager =
711 printing::PrintViewManager::FromWebContents(
712 GetActiveWebContents(browser));
[email protected]0045b0f42012-07-26 11:52:08713 if (browser->profile()->GetPrefs()->GetBoolean(
[email protected]e3a7e6f2012-09-18 22:44:31714 prefs::kPrintPreviewDisabled))
715 print_view_manager->PrintNow();
716 else
717 print_view_manager->PrintPreviewNow();
[email protected]a37d4b02012-06-25 21:56:10718}
719
[email protected]5d98294912012-06-27 22:57:40720bool CanPrint(const Browser* browser) {
[email protected]0045b0f42012-07-26 11:52:08721 // Do not print when printing is disabled via pref or policy.
[email protected]5d98294912012-06-27 22:57:40722 // Do not print when a constrained window is showing. It's confusing.
[email protected]db9747252012-07-02 19:28:00723 // Do not print if instant extended API is enabled and mode is NTP.
[email protected]0045b0f42012-07-26 11:52:08724 return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
725 !(HasConstrainedWindow(browser) ||
[email protected]db9747252012-07-02 19:28:00726 GetContentRestrictions(browser) & content::CONTENT_RESTRICTION_PRINT ||
727 IsNTPModeForInstantExtendedAPI(browser));
[email protected]5d98294912012-06-27 22:57:40728}
729
[email protected]a37d4b02012-06-25 21:56:10730void AdvancedPrint(Browser* browser) {
[email protected]e3a7e6f2012-09-18 22:44:31731 printing::PrintViewManager* print_view_manager =
732 printing::PrintViewManager::FromWebContents(
733 GetActiveWebContents(browser));
734 print_view_manager->AdvancedPrintNow();
[email protected]a37d4b02012-06-25 21:56:10735}
736
[email protected]5d98294912012-06-27 22:57:40737bool CanAdvancedPrint(const Browser* browser) {
[email protected]0045b0f42012-07-26 11:52:08738 // If printing is not disabled via pref or policy, it is always possible to
739 // advanced print when the print preview is visible.
740 return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
741 (PrintPreviewShowing(browser) || CanPrint(browser));
[email protected]5d98294912012-06-27 22:57:40742}
743
[email protected]d53e4032012-06-29 18:58:34744void PrintToDestination(Browser* browser) {
[email protected]e3a7e6f2012-09-18 22:44:31745 printing::PrintViewManager* print_view_manager =
746 printing::PrintViewManager::FromWebContents(
747 GetActiveWebContents(browser));
748 print_view_manager->PrintToDestination();
[email protected]d53e4032012-06-29 18:58:34749}
750
[email protected]a37d4b02012-06-25 21:56:10751void EmailPageLocation(Browser* browser) {
752 content::RecordAction(UserMetricsAction("EmailPageLocation"));
[email protected]52877dbc62012-06-29 22:22:03753 WebContents* wc = GetActiveWebContents(browser);
[email protected]a37d4b02012-06-25 21:56:10754 DCHECK(wc);
755
756 std::string title = net::EscapeQueryParamValue(
757 UTF16ToUTF8(wc->GetTitle()), false);
758 std::string page_url = net::EscapeQueryParamValue(wc->GetURL().spec(), false);
759 std::string mailto = std::string("mailto:?subject=Fwd:%20") +
760 title + "&body=%0A%0A" + page_url;
761 platform_util::OpenExternal(GURL(mailto));
762}
763
[email protected]5d98294912012-06-27 22:57:40764bool CanEmailPageLocation(const Browser* browser) {
765 return browser->toolbar_model()->ShouldDisplayURL() &&
[email protected]52877dbc62012-06-29 22:22:03766 GetActiveWebContents(browser)->GetURL().is_valid();
[email protected]5d98294912012-06-27 22:57:40767}
768
[email protected]a37d4b02012-06-25 21:56:10769void Cut(Browser* browser) {
770 content::RecordAction(UserMetricsAction("Cut"));
771 browser->window()->Cut();
772}
773
774void Copy(Browser* browser) {
775 content::RecordAction(UserMetricsAction("Copy"));
776 browser->window()->Copy();
777}
778
779void Paste(Browser* browser) {
780 content::RecordAction(UserMetricsAction("Paste"));
781 browser->window()->Paste();
782}
783
784void Find(Browser* browser) {
785 content::RecordAction(UserMetricsAction("Find"));
786 FindInPage(browser, false, false);
787}
788
789void FindNext(Browser* browser) {
790 content::RecordAction(UserMetricsAction("FindNext"));
791 FindInPage(browser, true, true);
792}
793
794void FindPrevious(Browser* browser) {
795 content::RecordAction(UserMetricsAction("FindPrevious"));
796 FindInPage(browser, true, false);
797}
798
799void FindInPage(Browser* browser, bool find_next, bool forward_direction) {
800 ShowFindBar(browser);
801 if (find_next) {
802 string16 find_text;
803#if defined(OS_MACOSX)
804 // We always want to search for the contents of the find pasteboard on OS X.
805 find_text = GetFindPboardText();
806#endif
[email protected]bc852c932012-09-29 21:38:34807 FindTabHelper::FromWebContents(GetActiveWebContents(browser))->
808 StartFinding(find_text,
809 forward_direction,
810 false); // Not case sensitive.
[email protected]a37d4b02012-06-25 21:56:10811 }
812}
813
814void Zoom(Browser* browser, content::PageZoom zoom) {
815 if (browser->is_devtools())
816 return;
817
[email protected]8233cbc2012-07-13 16:14:52818 chrome_page_zoom::Zoom(GetActiveWebContents(browser), zoom);
[email protected]a37d4b02012-06-25 21:56:10819}
820
821void FocusToolbar(Browser* browser) {
822 content::RecordAction(UserMetricsAction("FocusToolbar"));
823 browser->window()->FocusToolbar();
824}
825
826void FocusLocationBar(Browser* browser) {
827 content::RecordAction(UserMetricsAction("FocusLocation"));
828 browser->window()->SetFocusToLocationBar(true);
829}
830
831void FocusSearch(Browser* browser) {
832 // TODO(beng): replace this with FocusLocationBar
833 content::RecordAction(UserMetricsAction("FocusSearch"));
834 browser->window()->GetLocationBar()->FocusSearch();
835}
836
837void FocusAppMenu(Browser* browser) {
838 content::RecordAction(UserMetricsAction("FocusAppMenu"));
839 browser->window()->FocusAppMenu();
840}
841
842void FocusBookmarksToolbar(Browser* browser) {
843 content::RecordAction(UserMetricsAction("FocusBookmarksToolbar"));
844 browser->window()->FocusBookmarksToolbar();
845}
846
847void FocusNextPane(Browser* browser) {
848 content::RecordAction(UserMetricsAction("FocusNextPane"));
849 browser->window()->RotatePaneFocus(true);
850}
851
852void FocusPreviousPane(Browser* browser) {
853 content::RecordAction(UserMetricsAction("FocusPreviousPane"));
854 browser->window()->RotatePaneFocus(false);
855}
856
857void ToggleDevToolsWindow(Browser* browser, DevToolsToggleAction action) {
858 if (action == DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE)
859 content::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
860 else
861 content::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
[email protected]d16657c2012-09-03 14:25:10862 DevToolsWindow::ToggleDevToolsWindow(browser, action);
[email protected]a37d4b02012-06-25 21:56:10863}
864
865bool CanOpenTaskManager() {
866#if defined(OS_WIN)
867 // In metro we can't display the task manager, as it is a native window.
868 return !base::win::IsMetroProcess();
869#else
870 return true;
871#endif
872}
873
874void OpenTaskManager(Browser* browser, bool highlight_background_resources) {
875 content::RecordAction(UserMetricsAction("TaskManager"));
876 if (highlight_background_resources)
877 browser->window()->ShowBackgroundPages();
878 else
879 browser->window()->ShowTaskManager();
880}
881
882void OpenFeedbackDialog(Browser* browser) {
883 content::RecordAction(UserMetricsAction("Feedback"));
[email protected]7a19ea22012-08-02 14:39:39884 chrome::ShowFeedbackPage(browser, std::string(), std::string());
[email protected]a37d4b02012-06-25 21:56:10885}
886
887void ToggleBookmarkBar(Browser* browser) {
888 content::RecordAction(UserMetricsAction("ShowBookmarksBar"));
889 browser->window()->ToggleBookmarkBar();
890}
891
892void ShowAppMenu(Browser* browser) {
893 // We record the user metric for this event in WrenchMenu::RunMenu.
894 browser->window()->ShowAppMenu();
895}
896
897void ShowAvatarMenu(Browser* browser) {
898 browser->window()->ShowAvatarBubbleFromAvatarButton();
899}
900
901void OpenUpdateChromeDialog(Browser* browser) {
902 content::RecordAction(UserMetricsAction("UpdateChrome"));
903 browser->window()->ShowUpdateChromeDialog();
904}
905
906void ToggleSpeechInput(Browser* browser) {
[email protected]52877dbc62012-06-29 22:22:03907 GetActiveWebContents(browser)->GetRenderViewHost()->ToggleSpeechInput();
[email protected]a37d4b02012-06-25 21:56:10908}
909
[email protected]9b7ab882012-09-10 23:46:36910bool CanRequestTabletSite(WebContents* current_tab) {
911 if (!current_tab)
912 return false;
913 return current_tab->GetController().GetActiveEntry() != NULL;
914}
915
916bool IsRequestingTabletSite(Browser* browser) {
917 WebContents* current_tab = chrome::GetActiveWebContents(browser);
918 if (!current_tab)
919 return false;
920 content::NavigationEntry* entry =
921 current_tab->GetController().GetActiveEntry();
922 if (!entry)
923 return false;
924 return entry->GetIsOverridingUserAgent();
925}
926
927void ToggleRequestTabletSite(Browser* browser) {
928 WebContents* current_tab = GetActiveWebContents(browser);
929 if (!current_tab)
930 return;
931 NavigationController& controller = current_tab->GetController();
932 NavigationEntry* entry = controller.GetActiveEntry();
933 if (!entry)
934 return;
935 if (entry->GetIsOverridingUserAgent()) {
936 entry->SetIsOverridingUserAgent(false);
937 } else {
938 entry->SetIsOverridingUserAgent(true);
939 current_tab->SetUserAgentOverride(
940 webkit_glue::BuildUserAgentFromOSAndProduct(
941 kOsOverrideForTabletSite,
942 content::GetContentClient()->GetProduct()));
943 }
944 controller.ReloadOriginalRequestURL(true);
945}
946
[email protected]3f32b9b2012-07-09 16:59:28947void ToggleFullscreenMode(Browser* browser) {
948 browser->fullscreen_controller()->ToggleFullscreenMode();
949}
950
[email protected]d3446bda2012-07-12 14:24:39951void ClearCache(Browser* browser) {
[email protected]38b892b42012-09-04 13:25:47952 BrowsingDataRemover* remover =
953 BrowsingDataRemover::CreateForUnboundedRange(browser->profile());
[email protected]d3446bda2012-07-12 14:24:39954 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
955 BrowsingDataHelper::UNPROTECTED_WEB);
956 // BrowsingDataRemover takes care of deleting itself when done.
957}
958
959bool IsDebuggerAttachedToCurrentTab(Browser* browser) {
960 WebContents* contents = chrome::GetActiveWebContents(browser);
961 return contents ?
962 content::DevToolsAgentHostRegistry::IsDebuggerAttached(contents) : false;
963}
964
[email protected]2cd4fde2012-06-26 03:10:26965void ViewSource(Browser* browser, TabContents* contents) {
966 DCHECK(contents);
967
[email protected]8fcc7bf2012-08-14 18:14:50968 // Use the last committed entry, since the pending entry hasn't loaded yet and
969 // won't be copied into the cloned tab.
970 NavigationEntry* entry =
971 contents->web_contents()->GetController().GetLastCommittedEntry();
972 if (!entry)
[email protected]2cd4fde2012-06-26 03:10:26973 return;
974
[email protected]8fcc7bf2012-08-14 18:14:50975 ViewSource(browser, contents, entry->GetURL(), entry->GetContentState());
[email protected]2cd4fde2012-06-26 03:10:26976}
977
978void ViewSource(Browser* browser,
979 TabContents* contents,
980 const GURL& url,
981 const std::string& content_state) {
982 content::RecordAction(UserMetricsAction("ViewSource"));
983 DCHECK(contents);
984
[email protected]8fcc7bf2012-08-14 18:14:50985 // Note that Clone does not copy the pending or transient entries, so the
986 // active entry in view_source_contents will be the last committed entry.
[email protected]f250fd52012-08-27 20:09:37987 TabContents* view_source_contents =
988 BrowserCommandsTabContentsCreator::CloneTabContents(contents);
[email protected]2cd4fde2012-06-26 03:10:26989 view_source_contents->web_contents()->GetController().PruneAllButActive();
990 NavigationEntry* active_entry =
991 view_source_contents->web_contents()->GetController().GetActiveEntry();
992 if (!active_entry)
993 return;
994
[email protected]52877dbc62012-06-29 22:22:03995 GURL view_source_url = GURL(kViewSourceScheme + std::string(":") +
[email protected]2cd4fde2012-06-26 03:10:26996 url.spec());
997 active_entry->SetVirtualURL(view_source_url);
998
999 // Do not restore scroller position.
1000 active_entry->SetContentState(
1001 webkit_glue::RemoveScrollOffsetFromHistoryState(content_state));
1002
1003 // Do not restore title, derive it from the url.
1004 active_entry->SetTitle(string16());
1005
1006 // Now show view-source entry.
1007 if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
1008 // If this is a tabbed browser, just create a duplicate tab inside the same
1009 // window next to the tab being duplicated.
1010 int index = browser->tab_strip_model()->GetIndexOfTabContents(contents);
1011 int add_types = TabStripModel::ADD_ACTIVE |
1012 TabStripModel::ADD_INHERIT_GROUP;
1013 browser->tab_strip_model()->InsertTabContentsAt(index + 1,
1014 view_source_contents,
1015 add_types);
1016 } else {
[email protected]a4fe67012012-07-25 20:14:291017 Browser* b = new Browser(
[email protected]2cd4fde2012-06-26 03:10:261018 Browser::CreateParams(Browser::TYPE_TABBED, browser->profile()));
1019
1020 // Preserve the size of the original window. The new window has already
1021 // been given an offset by the OS, so we shouldn't copy the old bounds.
1022 BrowserWindow* new_window = b->window();
1023 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
1024 browser->window()->GetRestoredBounds().size()));
1025
1026 // We need to show the browser now. Otherwise ContainerWin assumes the
1027 // WebContents is invisible and won't size it.
1028 b->window()->Show();
1029
1030 // The page transition below is only for the purpose of inserting the tab.
[email protected]855370052012-07-10 19:30:321031 AddTab(b, view_source_contents, content::PAGE_TRANSITION_LINK);
[email protected]2cd4fde2012-06-26 03:10:261032 }
1033
1034 SessionService* session_service =
1035 SessionServiceFactory::GetForProfileIfExisting(browser->profile());
1036 if (session_service)
1037 session_service->TabRestored(view_source_contents, false);
1038}
1039
1040void ViewSelectedSource(Browser* browser) {
[email protected]855370052012-07-10 19:30:321041 ViewSource(browser, GetActiveTabContents(browser));
[email protected]2cd4fde2012-06-26 03:10:261042}
1043
[email protected]5d98294912012-06-27 22:57:401044bool CanViewSource(const Browser* browser) {
[email protected]855370052012-07-10 19:30:321045 return GetActiveWebContents(browser)->GetController().CanViewSource();
[email protected]5d98294912012-06-27 22:57:401046}
1047
[email protected]619f86182012-07-03 21:30:181048void CreateApplicationShortcuts(Browser* browser) {
1049 content::RecordAction(UserMetricsAction("CreateShortcut"));
[email protected]7381d9f2012-09-12 20:26:221050 extensions::TabHelper::FromWebContents(GetActiveWebContents(browser))->
[email protected]619f86182012-07-03 21:30:181051 CreateApplicationShortcuts();
1052}
1053
[email protected]5d98294912012-06-27 22:57:401054bool CanCreateApplicationShortcuts(const Browser* browser) {
[email protected]7381d9f2012-09-12 20:26:221055 return extensions::TabHelper::FromWebContents(GetActiveWebContents(browser))->
[email protected]619f86182012-07-03 21:30:181056 CanCreateApplicationShortcuts();
[email protected]5d98294912012-06-27 22:57:401057}
1058
[email protected]40df6f52012-06-28 17:08:521059void ConvertTabToAppWindow(Browser* browser,
1060 content::WebContents* contents) {
1061 const GURL& url = contents->GetController().GetActiveEntry()->GetURL();
1062 std::string app_name = web_app::GenerateApplicationNameFromURL(url);
1063
1064 int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
1065 if (index >= 0)
1066 browser->tab_strip_model()->DetachTabContentsAt(index);
1067
[email protected]a4fe67012012-07-25 20:14:291068 Browser* app_browser = new Browser(
[email protected]40df6f52012-06-28 17:08:521069 Browser::CreateParams::CreateForApp(
1070 Browser::TYPE_POPUP, app_name, gfx::Rect(), browser->profile()));
1071 TabContents* tab_contents = TabContents::FromWebContents(contents);
[email protected]f250fd52012-08-27 20:09:371072 if (!tab_contents) {
1073 tab_contents =
1074 BrowserCommandsTabContentsCreator::CreateTabContents(contents);
1075 }
[email protected]40df6f52012-06-28 17:08:521076 app_browser->tab_strip_model()->AppendTabContents(tab_contents, true);
1077
1078 contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
1079 contents->GetRenderViewHost()->SyncRendererPrefs();
1080 app_browser->window()->Show();
1081}
1082
[email protected]a37d4b02012-06-25 21:56:101083} // namespace chrome