• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 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/prefs/pref_service.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/bookmarks/bookmark_model.h"
12 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
13 #include "chrome/browser/bookmarks/bookmark_utils.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/browsing_data/browsing_data_helper.h"
16 #include "chrome/browser/browsing_data/browsing_data_remover.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/chrome_page_zoom.h"
19 #include "chrome/browser/devtools/devtools_window.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/extensions/tab_helper.h"
22 #include "chrome/browser/favicon/favicon_tab_helper.h"
23 #include "chrome/browser/google/google_util.h"
24 #include "chrome/browser/lifetime/application_lifetime.h"
25 #include "chrome/browser/platform_util.h"
26 #include "chrome/browser/prefs/incognito_mode_prefs.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/rlz/rlz.h"
29 #include "chrome/browser/search/search.h"
30 #include "chrome/browser/sessions/session_service_factory.h"
31 #include "chrome/browser/sessions/tab_restore_service.h"
32 #include "chrome/browser/sessions/tab_restore_service_delegate.h"
33 #include "chrome/browser/sessions/tab_restore_service_factory.h"
34 #include "chrome/browser/translate/translate_tab_helper.h"
35 #include "chrome/browser/ui/bookmarks/bookmark_prompt_controller.h"
36 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
37 #include "chrome/browser/ui/browser.h"
38 #include "chrome/browser/ui/browser_command_controller.h"
39 #include "chrome/browser/ui/browser_dialogs.h"
40 #include "chrome/browser/ui/browser_instant_controller.h"
41 #include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
42 #include "chrome/browser/ui/browser_tabstrip.h"
43 #include "chrome/browser/ui/browser_window.h"
44 #include "chrome/browser/ui/chrome_pages.h"
45 #include "chrome/browser/ui/find_bar/find_bar.h"
46 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
47 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
48 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
49 #include "chrome/browser/ui/omnibox/location_bar.h"
50 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
51 #include "chrome/browser/ui/search/search_tab_helper.h"
52 #include "chrome/browser/ui/status_bubble.h"
53 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
54 #include "chrome/browser/ui/tabs/tab_strip_model.h"
55 #include "chrome/browser/ui/translate/translate_bubble_model.h"
56 #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
57 #include "chrome/browser/upgrade_detector.h"
58 #include "chrome/browser/web_applications/web_app.h"
59 #include "chrome/common/chrome_switches.h"
60 #include "chrome/common/chrome_version_info.h"
61 #include "chrome/common/content_restriction.h"
62 #include "chrome/common/pref_names.h"
63 #include "components/web_modal/web_contents_modal_dialog_manager.h"
64 #include "content/public/browser/devtools_agent_host.h"
65 #include "content/public/browser/navigation_controller.h"
66 #include "content/public/browser/navigation_entry.h"
67 #include "content/public/browser/notification_service.h"
68 #include "content/public/browser/page_navigator.h"
69 #include "content/public/browser/render_view_host.h"
70 #include "content/public/browser/user_metrics.h"
71 #include "content/public/browser/web_contents.h"
72 #include "content/public/browser/web_contents_view.h"
73 #include "content/public/common/renderer_preferences.h"
74 #include "content/public/common/url_constants.h"
75 #include "content/public/common/url_utils.h"
76 #include "net/base/escape.h"
77 #include "webkit/common/user_agent/user_agent_util.h"
78 
79 #if defined(OS_WIN)
80 #include "chrome/browser/ui/metro_pin_tab_helper_win.h"
81 #include "win8/util/win8_util.h"
82 #endif
83 
84 #if defined(ENABLE_PRINTING)
85 #if defined(ENABLE_FULL_PRINTING)
86 #include "chrome/browser/printing/print_preview_dialog_controller.h"
87 #include "chrome/browser/printing/print_view_manager.h"
88 #else
89 #include "chrome/browser/printing/print_view_manager_basic.h"
90 #endif  // defined(ENABLE_FULL_PRINTING)
91 #endif  // defined(ENABLE_PRINTING)
92 
93 namespace {
94 const char kOsOverrideForTabletSite[] = "Linux; Android 4.0.3";
95 }
96 
97 using content::NavigationController;
98 using content::NavigationEntry;
99 using content::OpenURLParams;
100 using content::Referrer;
101 using content::SSLStatus;
102 using content::UserMetricsAction;
103 using content::WebContents;
104 using web_modal::WebContentsModalDialogManager;
105 
106 namespace chrome {
107 namespace {
108 
BookmarkCurrentPageInternal(Browser * browser,bool from_star)109 void BookmarkCurrentPageInternal(Browser* browser, bool from_star) {
110   content::RecordAction(UserMetricsAction("Star"));
111 
112   BookmarkModel* model =
113       BookmarkModelFactory::GetForProfile(browser->profile());
114   if (!model || !model->loaded())
115     return;  // Ignore requests until bookmarks are loaded.
116 
117   GURL url;
118   base::string16 title;
119   WebContents* web_contents =
120       browser->tab_strip_model()->GetActiveWebContents();
121   GetURLAndTitleToBookmark(web_contents, &url, &title);
122   bool was_bookmarked = model->IsBookmarked(url);
123   if (!was_bookmarked && web_contents->GetBrowserContext()->IsOffTheRecord()) {
124     // If we're incognito the favicon may not have been saved. Save it now
125     // so that bookmarks have an icon for the page.
126     FaviconTabHelper::FromWebContents(web_contents)->SaveFavicon();
127   }
128   bookmark_utils::AddIfNotBookmarked(model, url, title);
129   if (from_star && !was_bookmarked)
130     BookmarkPromptController::AddedBookmark(browser, url);
131   // Make sure the model actually added a bookmark before showing the star. A
132   // bookmark isn't created if the url is invalid.
133   if (browser->window()->IsActive() && model->IsBookmarked(url)) {
134     // Only show the bubble if the window is active, otherwise we may get into
135     // weird situations where the bubble is deleted as soon as it is shown.
136     browser->window()->ShowBookmarkBubble(url, was_bookmarked);
137   }
138 }
139 
GetOrCloneTabForDisposition(Browser * browser,WindowOpenDisposition disposition)140 WebContents* GetOrCloneTabForDisposition(Browser* browser,
141                                          WindowOpenDisposition disposition) {
142   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
143   switch (disposition) {
144     case NEW_FOREGROUND_TAB:
145     case NEW_BACKGROUND_TAB: {
146       current_tab = current_tab->Clone();
147       browser->tab_strip_model()->AddWebContents(
148           current_tab, -1, content::PAGE_TRANSITION_LINK,
149           disposition == NEW_FOREGROUND_TAB ? TabStripModel::ADD_ACTIVE :
150                                               TabStripModel::ADD_NONE);
151       break;
152     }
153     case NEW_WINDOW: {
154       current_tab = current_tab->Clone();
155       Browser* b = new Browser(Browser::CreateParams(
156           browser->profile(), browser->host_desktop_type()));
157       b->tab_strip_model()->AddWebContents(
158           current_tab, -1, content::PAGE_TRANSITION_LINK,
159           TabStripModel::ADD_ACTIVE);
160       b->window()->Show();
161       break;
162     }
163     default:
164       break;
165   }
166   return current_tab;
167 }
168 
ReloadInternal(Browser * browser,WindowOpenDisposition disposition,bool ignore_cache)169 void ReloadInternal(Browser* browser,
170                     WindowOpenDisposition disposition,
171                     bool ignore_cache) {
172   // As this is caused by a user action, give the focus to the page.
173   //
174   // Also notify RenderViewHostDelegate of the user gesture; this is
175   // normally done in Browser::Navigate, but a reload bypasses Navigate.
176   WebContents* web_contents = GetOrCloneTabForDisposition(browser, disposition);
177   web_contents->UserGestureDone();
178   if (!web_contents->FocusLocationBarByDefault())
179     web_contents->GetView()->Focus();
180   if (ignore_cache)
181     web_contents->GetController().ReloadIgnoringCache(true);
182   else
183     web_contents->GetController().Reload(true);
184 }
185 
IsShowingWebContentsModalDialog(const Browser * browser)186 bool IsShowingWebContentsModalDialog(const Browser* browser) {
187   WebContents* web_contents =
188       browser->tab_strip_model()->GetActiveWebContents();
189   if (!web_contents)
190     return false;
191 
192   WebContentsModalDialogManager* web_contents_modal_dialog_manager =
193       WebContentsModalDialogManager::FromWebContents(web_contents);
194   return web_contents_modal_dialog_manager->IsDialogActive();
195 }
196 
PrintPreviewShowing(const Browser * browser)197 bool PrintPreviewShowing(const Browser* browser) {
198 #if defined(ENABLE_FULL_PRINTING)
199   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
200   printing::PrintPreviewDialogController* controller =
201       printing::PrintPreviewDialogController::GetInstance();
202   return controller && (controller->GetPrintPreviewForContents(contents) ||
203                         controller->is_creating_print_preview_dialog());
204 #else
205   return false;
206 #endif
207 }
208 
209 }  // namespace
210 
IsCommandEnabled(Browser * browser,int command)211 bool IsCommandEnabled(Browser* browser, int command) {
212   return browser->command_controller()->command_updater()->IsCommandEnabled(
213       command);
214 }
215 
SupportsCommand(Browser * browser,int command)216 bool SupportsCommand(Browser* browser, int command) {
217   return browser->command_controller()->command_updater()->SupportsCommand(
218       command);
219 }
220 
ExecuteCommand(Browser * browser,int command)221 bool ExecuteCommand(Browser* browser, int command) {
222   return browser->command_controller()->command_updater()->ExecuteCommand(
223       command);
224 }
225 
ExecuteCommandWithDisposition(Browser * browser,int command,WindowOpenDisposition disposition)226 bool ExecuteCommandWithDisposition(Browser* browser,
227                                    int command,
228                                    WindowOpenDisposition disposition) {
229   return browser->command_controller()->command_updater()->
230       ExecuteCommandWithDisposition(command, disposition);
231 }
232 
UpdateCommandEnabled(Browser * browser,int command,bool enabled)233 void UpdateCommandEnabled(Browser* browser, int command, bool enabled) {
234   browser->command_controller()->command_updater()->UpdateCommandEnabled(
235       command, enabled);
236 }
237 
AddCommandObserver(Browser * browser,int command,CommandObserver * observer)238 void AddCommandObserver(Browser* browser,
239                         int command,
240                         CommandObserver* observer) {
241   browser->command_controller()->command_updater()->AddCommandObserver(
242       command, observer);
243 }
244 
RemoveCommandObserver(Browser * browser,int command,CommandObserver * observer)245 void RemoveCommandObserver(Browser* browser,
246                            int command,
247                            CommandObserver* observer) {
248   browser->command_controller()->command_updater()->RemoveCommandObserver(
249       command, observer);
250 }
251 
GetContentRestrictions(const Browser * browser)252 int GetContentRestrictions(const Browser* browser) {
253   int content_restrictions = 0;
254   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
255   if (current_tab) {
256     CoreTabHelper* core_tab_helper =
257         CoreTabHelper::FromWebContents(current_tab);
258     content_restrictions = core_tab_helper->content_restrictions();
259     NavigationEntry* active_entry =
260         current_tab->GetController().GetActiveEntry();
261     // See comment in UpdateCommandsForTabState about why we call url().
262     if (!content::IsSavableURL(
263             active_entry ? active_entry->GetURL() : GURL()) ||
264         current_tab->ShowingInterstitialPage())
265       content_restrictions |= CONTENT_RESTRICTION_SAVE;
266     if (current_tab->ShowingInterstitialPage())
267       content_restrictions |= CONTENT_RESTRICTION_PRINT;
268   }
269   return content_restrictions;
270 }
271 
NewEmptyWindow(Profile * profile,HostDesktopType desktop_type)272 void NewEmptyWindow(Profile* profile, HostDesktopType desktop_type) {
273   bool incognito = profile->IsOffTheRecord();
274   PrefService* prefs = profile->GetPrefs();
275   if (incognito) {
276     if (IncognitoModePrefs::GetAvailability(prefs) ==
277           IncognitoModePrefs::DISABLED) {
278       incognito = false;
279     }
280   } else {
281     if (browser_defaults::kAlwaysOpenIncognitoWindow &&
282         IncognitoModePrefs::ShouldLaunchIncognito(
283             *CommandLine::ForCurrentProcess(), prefs)) {
284       incognito = true;
285     }
286   }
287 
288   if (incognito) {
289     content::RecordAction(UserMetricsAction("NewIncognitoWindow"));
290     OpenEmptyWindow(profile->GetOffTheRecordProfile(), desktop_type);
291   } else {
292     content::RecordAction(UserMetricsAction("NewWindow"));
293     SessionService* session_service =
294         SessionServiceFactory::GetForProfileForSessionRestore(
295             profile->GetOriginalProfile());
296     if (!session_service ||
297         !session_service->RestoreIfNecessary(std::vector<GURL>())) {
298       OpenEmptyWindow(profile->GetOriginalProfile(), desktop_type);
299     }
300   }
301 }
302 
OpenEmptyWindow(Profile * profile,HostDesktopType desktop_type)303 Browser* OpenEmptyWindow(Profile* profile, HostDesktopType desktop_type) {
304   Browser* browser = new Browser(
305       Browser::CreateParams(Browser::TYPE_TABBED, profile, desktop_type));
306   AddTabAt(browser, GURL(), -1, true);
307   browser->window()->Show();
308   return browser;
309 }
310 
OpenWindowWithRestoredTabs(Profile * profile,HostDesktopType host_desktop_type)311 void OpenWindowWithRestoredTabs(Profile* profile,
312                                 HostDesktopType host_desktop_type) {
313   TabRestoreService* service = TabRestoreServiceFactory::GetForProfile(profile);
314   if (service)
315     service->RestoreMostRecentEntry(NULL, host_desktop_type);
316 }
317 
OpenURLOffTheRecord(Profile * profile,const GURL & url,chrome::HostDesktopType desktop_type)318 void OpenURLOffTheRecord(Profile* profile,
319                          const GURL& url,
320                          chrome::HostDesktopType desktop_type) {
321   ScopedTabbedBrowserDisplayer displayer(profile->GetOffTheRecordProfile(),
322                                          desktop_type);
323   AddSelectedTabWithURL(displayer.browser(), url,
324       content::PAGE_TRANSITION_LINK);
325 }
326 
CanGoBack(const Browser * browser)327 bool CanGoBack(const Browser* browser) {
328   return browser->tab_strip_model()->GetActiveWebContents()->
329       GetController().CanGoBack();
330 }
331 
GoBack(Browser * browser,WindowOpenDisposition disposition)332 void GoBack(Browser* browser, WindowOpenDisposition disposition) {
333   content::RecordAction(UserMetricsAction("Back"));
334 
335   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
336   if (CanGoBack(browser)) {
337     WebContents* new_tab = GetOrCloneTabForDisposition(browser, disposition);
338     // If we are on an interstitial page and clone the tab, it won't be copied
339     // to the new tab, so we don't need to go back.
340     if (current_tab->ShowingInterstitialPage() && new_tab != current_tab)
341       return;
342     new_tab->GetController().GoBack();
343   }
344 }
345 
CanGoForward(const Browser * browser)346 bool CanGoForward(const Browser* browser) {
347   return browser->tab_strip_model()->GetActiveWebContents()->
348       GetController().CanGoForward();
349 }
350 
GoForward(Browser * browser,WindowOpenDisposition disposition)351 void GoForward(Browser* browser, WindowOpenDisposition disposition) {
352   content::RecordAction(UserMetricsAction("Forward"));
353   if (CanGoForward(browser)) {
354     GetOrCloneTabForDisposition(browser, disposition)->
355         GetController().GoForward();
356   }
357 }
358 
NavigateToIndexWithDisposition(Browser * browser,int index,WindowOpenDisposition disp)359 bool NavigateToIndexWithDisposition(Browser* browser,
360                                     int index,
361                                     WindowOpenDisposition disp) {
362   NavigationController& controller =
363       GetOrCloneTabForDisposition(browser, disp)->GetController();
364   if (index < 0 || index >= controller.GetEntryCount())
365     return false;
366   controller.GoToIndex(index);
367   return true;
368 }
369 
Reload(Browser * browser,WindowOpenDisposition disposition)370 void Reload(Browser* browser, WindowOpenDisposition disposition) {
371   content::RecordAction(UserMetricsAction("Reload"));
372   ReloadInternal(browser, disposition, false);
373 }
374 
ReloadIgnoringCache(Browser * browser,WindowOpenDisposition disposition)375 void ReloadIgnoringCache(Browser* browser, WindowOpenDisposition disposition) {
376   content::RecordAction(UserMetricsAction("ReloadIgnoringCache"));
377   ReloadInternal(browser, disposition, true);
378 }
379 
CanReload(const Browser * browser)380 bool CanReload(const Browser* browser) {
381   return !browser->is_devtools();
382 }
383 
Home(Browser * browser,WindowOpenDisposition disposition)384 void Home(Browser* browser, WindowOpenDisposition disposition) {
385   content::RecordAction(UserMetricsAction("Home"));
386 
387   std::string extra_headers;
388 #if defined(ENABLE_RLZ)
389   // If the home page is a Google home page, add the RLZ header to the request.
390   PrefService* pref_service = browser->profile()->GetPrefs();
391   if (pref_service) {
392     if (google_util::IsGoogleHomePageUrl(
393         GURL(pref_service->GetString(prefs::kHomePage)))) {
394       extra_headers = RLZTracker::GetAccessPointHttpHeader(
395           RLZTracker::CHROME_HOME_PAGE);
396     }
397   }
398 #endif
399 
400   OpenURLParams params(
401       browser->profile()->GetHomePage(), Referrer(), disposition,
402       content::PageTransitionFromInt(
403           content::PAGE_TRANSITION_AUTO_BOOKMARK |
404           content::PAGE_TRANSITION_HOME_PAGE),
405       false);
406   params.extra_headers = extra_headers;
407   browser->OpenURL(params);
408 }
409 
OpenCurrentURL(Browser * browser)410 void OpenCurrentURL(Browser* browser) {
411   content::RecordAction(UserMetricsAction("LoadURL"));
412   LocationBar* location_bar = browser->window()->GetLocationBar();
413   if (!location_bar)
414     return;
415 
416   GURL url(location_bar->GetDestinationURL());
417 
418   content::PageTransition page_transition = location_bar->GetPageTransition();
419   content::PageTransition page_transition_without_qualifier(
420       PageTransitionStripQualifier(page_transition));
421   WindowOpenDisposition open_disposition =
422       location_bar->GetWindowOpenDisposition();
423   // A PAGE_TRANSITION_TYPED means the user has typed a URL. We do not want to
424   // open URLs with instant_controller since in some cases it disregards it
425   // and performs a search instead. For example, when using CTRL-Enter, the
426   // location_bar is aware of the URL but instant is not.
427   // Instant should also not handle PAGE_TRANSITION_RELOAD because its knowledge
428   // of the omnibox text may be stale if the user focuses in the omnibox and
429   // presses enter without typing anything.
430   if (page_transition_without_qualifier != content::PAGE_TRANSITION_TYPED &&
431       page_transition_without_qualifier != content::PAGE_TRANSITION_RELOAD &&
432       browser->instant_controller() &&
433       browser->instant_controller()->OpenInstant(open_disposition, url))
434     return;
435 
436   NavigateParams params(browser, url, page_transition);
437   params.disposition = open_disposition;
438   // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
439   // inherit the opener. In some cases the tabstrip will determine the group
440   // should be inherited, in which case the group is inherited instead of the
441   // opener.
442   params.tabstrip_add_types =
443       TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
444   Navigate(&params);
445 
446   DCHECK(browser->profile()->GetExtensionService());
447   const extensions::Extension* extension =
448       browser->profile()->GetExtensionService()->GetInstalledApp(url);
449   if (extension) {
450     CoreAppLauncherHandler::RecordAppLaunchType(
451         extension_misc::APP_LAUNCH_OMNIBOX_LOCATION,
452         extension->GetType());
453   }
454 }
455 
Stop(Browser * browser)456 void Stop(Browser* browser) {
457   content::RecordAction(UserMetricsAction("Stop"));
458   browser->tab_strip_model()->GetActiveWebContents()->Stop();
459 }
460 
461 #if !defined(OS_WIN)
NewWindow(Browser * browser)462 void NewWindow(Browser* browser) {
463   NewEmptyWindow(browser->profile()->GetOriginalProfile(),
464                  browser->host_desktop_type());
465 }
466 
NewIncognitoWindow(Browser * browser)467 void NewIncognitoWindow(Browser* browser) {
468   NewEmptyWindow(browser->profile()->GetOffTheRecordProfile(),
469                  browser->host_desktop_type());
470 }
471 #endif  // OS_WIN
472 
CloseWindow(Browser * browser)473 void CloseWindow(Browser* browser) {
474   content::RecordAction(UserMetricsAction("CloseWindow"));
475   browser->window()->Close();
476 }
477 
NewTab(Browser * browser)478 void NewTab(Browser* browser) {
479   content::RecordAction(UserMetricsAction("NewTab"));
480   // TODO(asvitkine): This is invoked programmatically from several places.
481   // Audit the code and change it so that the histogram only gets collected for
482   // user-initiated commands.
483   UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
484                             TabStripModel::NEW_TAB_ENUM_COUNT);
485 
486   if (browser->is_type_tabbed()) {
487     AddTabAt(browser, GURL(), -1, true);
488     browser->tab_strip_model()->GetActiveWebContents()->GetView()->
489         RestoreFocus();
490   } else {
491     ScopedTabbedBrowserDisplayer displayer(browser->profile(),
492                                            browser->host_desktop_type());
493     Browser* b = displayer.browser();
494     AddTabAt(b, GURL(), -1, true);
495     b->window()->Show();
496     // The call to AddBlankTabAt above did not set the focus to the tab as its
497     // window was not active, so we have to do it explicitly.
498     // See http://crbug.com/6380.
499     b->tab_strip_model()->GetActiveWebContents()->GetView()->RestoreFocus();
500   }
501 }
502 
CloseTab(Browser * browser)503 void CloseTab(Browser* browser) {
504   content::RecordAction(UserMetricsAction("CloseTab_Accelerator"));
505   browser->tab_strip_model()->CloseSelectedTabs();
506 }
507 
RestoreTab(Browser * browser)508 void RestoreTab(Browser* browser) {
509   content::RecordAction(UserMetricsAction("RestoreTab"));
510   TabRestoreService* service =
511       TabRestoreServiceFactory::GetForProfile(browser->profile());
512   if (service)
513     service->RestoreMostRecentEntry(browser->tab_restore_service_delegate(),
514                                     browser->host_desktop_type());
515 }
516 
GetRestoreTabType(const Browser * browser)517 TabStripModelDelegate::RestoreTabType GetRestoreTabType(
518     const Browser* browser) {
519   TabRestoreService* service =
520       TabRestoreServiceFactory::GetForProfile(browser->profile());
521   if (!service || service->entries().empty())
522     return TabStripModelDelegate::RESTORE_NONE;
523   if (service->entries().front()->type == TabRestoreService::WINDOW)
524     return TabStripModelDelegate::RESTORE_WINDOW;
525   return TabStripModelDelegate::RESTORE_TAB;
526 }
527 
SelectNextTab(Browser * browser)528 void SelectNextTab(Browser* browser) {
529   content::RecordAction(UserMetricsAction("SelectNextTab"));
530   browser->tab_strip_model()->SelectNextTab();
531 }
532 
SelectPreviousTab(Browser * browser)533 void SelectPreviousTab(Browser* browser) {
534   content::RecordAction(UserMetricsAction("SelectPrevTab"));
535   browser->tab_strip_model()->SelectPreviousTab();
536 }
537 
OpenTabpose(Browser * browser)538 void OpenTabpose(Browser* browser) {
539 #if defined(OS_MACOSX)
540   if (!CommandLine::ForCurrentProcess()->HasSwitch(
541         switches::kEnableExposeForTabs)) {
542     return;
543   }
544 
545   content::RecordAction(UserMetricsAction("OpenTabpose"));
546   browser->window()->OpenTabpose();
547 #else
548   NOTREACHED();
549 #endif
550 }
551 
MoveTabNext(Browser * browser)552 void MoveTabNext(Browser* browser) {
553   content::RecordAction(UserMetricsAction("MoveTabNext"));
554   browser->tab_strip_model()->MoveTabNext();
555 }
556 
MoveTabPrevious(Browser * browser)557 void MoveTabPrevious(Browser* browser) {
558   content::RecordAction(UserMetricsAction("MoveTabPrevious"));
559   browser->tab_strip_model()->MoveTabPrevious();
560 }
561 
SelectNumberedTab(Browser * browser,int index)562 void SelectNumberedTab(Browser* browser, int index) {
563   if (index < browser->tab_strip_model()->count()) {
564     content::RecordAction(UserMetricsAction("SelectNumberedTab"));
565     browser->tab_strip_model()->ActivateTabAt(index, true);
566   }
567 }
568 
SelectLastTab(Browser * browser)569 void SelectLastTab(Browser* browser) {
570   content::RecordAction(UserMetricsAction("SelectLastTab"));
571   browser->tab_strip_model()->SelectLastTab();
572 }
573 
DuplicateTab(Browser * browser)574 void DuplicateTab(Browser* browser) {
575   content::RecordAction(UserMetricsAction("Duplicate"));
576   DuplicateTabAt(browser, browser->tab_strip_model()->active_index());
577 }
578 
CanDuplicateTab(const Browser * browser)579 bool CanDuplicateTab(const Browser* browser) {
580   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
581   return contents && contents->GetController().GetLastCommittedEntry();
582 }
583 
DuplicateTabAt(Browser * browser,int index)584 WebContents* DuplicateTabAt(Browser* browser, int index) {
585   WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(index);
586   CHECK(contents);
587   WebContents* contents_dupe = contents->Clone();
588 
589   bool pinned = false;
590   if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
591     // If this is a tabbed browser, just create a duplicate tab inside the same
592     // window next to the tab being duplicated.
593     int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
594     pinned = browser->tab_strip_model()->IsTabPinned(index);
595     int add_types = TabStripModel::ADD_ACTIVE |
596         TabStripModel::ADD_INHERIT_GROUP |
597         (pinned ? TabStripModel::ADD_PINNED : 0);
598     browser->tab_strip_model()->InsertWebContentsAt(
599         index + 1, contents_dupe, add_types);
600   } else {
601     Browser* new_browser = NULL;
602     if (browser->is_app() &&
603         !browser->is_type_popup()) {
604       new_browser = new Browser(
605           Browser::CreateParams::CreateForApp(browser->type(),
606                                               browser->app_name(),
607                                               gfx::Rect(),
608                                               browser->profile(),
609                                               browser->host_desktop_type()));
610     } else {
611       new_browser = new Browser(
612           Browser::CreateParams(browser->type(), browser->profile(),
613                                 browser->host_desktop_type()));
614     }
615     // Preserve the size of the original window. The new window has already
616     // been given an offset by the OS, so we shouldn't copy the old bounds.
617     BrowserWindow* new_window = new_browser->window();
618     new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
619                           browser->window()->GetRestoredBounds().size()));
620 
621     // We need to show the browser now.  Otherwise ContainerWin assumes the
622     // WebContents is invisible and won't size it.
623     new_browser->window()->Show();
624 
625     // The page transition below is only for the purpose of inserting the tab.
626     new_browser->tab_strip_model()->AddWebContents(
627         contents_dupe, -1,
628         content::PAGE_TRANSITION_LINK,
629         TabStripModel::ADD_ACTIVE);
630   }
631 
632   SessionService* session_service =
633       SessionServiceFactory::GetForProfileIfExisting(browser->profile());
634   if (session_service)
635     session_service->TabRestored(contents_dupe, pinned);
636   return contents_dupe;
637 }
638 
CanDuplicateTabAt(Browser * browser,int index)639 bool CanDuplicateTabAt(Browser* browser, int index) {
640   content::NavigationController& nc =
641       browser->tab_strip_model()->GetWebContentsAt(index)->GetController();
642   return nc.GetWebContents() && nc.GetLastCommittedEntry();
643 }
644 
ConvertPopupToTabbedBrowser(Browser * browser)645 void ConvertPopupToTabbedBrowser(Browser* browser) {
646   content::RecordAction(UserMetricsAction("ShowAsTab"));
647   TabStripModel* tab_strip = browser->tab_strip_model();
648   WebContents* contents =
649       tab_strip->DetachWebContentsAt(tab_strip->active_index());
650   Browser* b = new Browser(Browser::CreateParams(browser->profile(),
651                                                  browser->host_desktop_type()));
652   b->tab_strip_model()->AppendWebContents(contents, true);
653   b->window()->Show();
654 }
655 
Exit()656 void Exit() {
657   content::RecordAction(UserMetricsAction("Exit"));
658   chrome::AttemptUserExit();
659 }
660 
BookmarkCurrentPage(Browser * browser)661 void BookmarkCurrentPage(Browser* browser) {
662   BookmarkCurrentPageInternal(browser, false);
663 }
664 
BookmarkCurrentPageFromStar(Browser * browser)665 void BookmarkCurrentPageFromStar(Browser* browser) {
666   BookmarkCurrentPageInternal(browser, true);
667 }
668 
CanBookmarkCurrentPage(const Browser * browser)669 bool CanBookmarkCurrentPage(const Browser* browser) {
670   BookmarkModel* model =
671       BookmarkModelFactory::GetForProfile(browser->profile());
672   return browser_defaults::bookmarks_enabled &&
673       browser->profile()->GetPrefs()->GetBoolean(
674           prefs::kEditBookmarksEnabled) &&
675       model && model->loaded() && browser->is_type_tabbed();
676 }
677 
BookmarkAllTabs(Browser * browser)678 void BookmarkAllTabs(Browser* browser) {
679   chrome::ShowBookmarkAllTabsDialog(browser);
680 }
681 
CanBookmarkAllTabs(const Browser * browser)682 bool CanBookmarkAllTabs(const Browser* browser) {
683   return browser->tab_strip_model()->count() > 1 &&
684              CanBookmarkCurrentPage(browser);
685 }
686 
Translate(Browser * browser)687 void Translate(Browser* browser) {
688   if (!browser->window()->IsActive())
689     return;
690 
691   WebContents* web_contents =
692       browser->tab_strip_model()->GetActiveWebContents();
693   TranslateTabHelper* translate_tab_helper =
694       TranslateTabHelper::FromWebContents(web_contents);
695 
696   TranslateBubbleModel::ViewState view_state =
697       TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE;
698   if (translate_tab_helper) {
699     if (translate_tab_helper->language_state().translation_pending())
700       view_state = TranslateBubbleModel::VIEW_STATE_TRANSLATING;
701     else if (translate_tab_helper->language_state().IsPageTranslated())
702       view_state = TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE;
703   }
704   browser->window()->ShowTranslateBubble(web_contents, view_state,
705                                          TranslateErrors::NONE);
706 }
707 
TogglePagePinnedToStartScreen(Browser * browser)708 void TogglePagePinnedToStartScreen(Browser* browser) {
709 #if defined(OS_WIN)
710   MetroPinTabHelper::FromWebContents(
711       browser->tab_strip_model()->GetActiveWebContents())->
712           TogglePinnedToStartScreen();
713 #endif
714 }
715 
SavePage(Browser * browser)716 void SavePage(Browser* browser) {
717   content::RecordAction(UserMetricsAction("SavePage"));
718   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
719   if (current_tab && current_tab->GetContentsMimeType() == "application/pdf")
720     content::RecordAction(UserMetricsAction("PDF.SavePage"));
721   current_tab->OnSavePage();
722 }
723 
CanSavePage(const Browser * browser)724 bool CanSavePage(const Browser* browser) {
725   // LocalState can be NULL in tests.
726   if (g_browser_process->local_state() &&
727       !g_browser_process->local_state()->GetBoolean(
728       prefs::kAllowFileSelectionDialogs)) {
729     return false;
730   }
731   return !browser->is_devtools() &&
732       !(GetContentRestrictions(browser) & CONTENT_RESTRICTION_SAVE);
733 }
734 
ShowFindBar(Browser * browser)735 void ShowFindBar(Browser* browser) {
736   browser->GetFindBarController()->Show();
737 }
738 
ShowWebsiteSettings(Browser * browser,content::WebContents * web_contents,const GURL & url,const SSLStatus & ssl)739 void ShowWebsiteSettings(Browser* browser,
740                          content::WebContents* web_contents,
741                          const GURL& url,
742                          const SSLStatus& ssl) {
743   browser->window()->ShowWebsiteSettings(
744       Profile::FromBrowserContext(web_contents->GetBrowserContext()),
745       web_contents, url, ssl);
746 }
747 
748 
Print(Browser * browser)749 void Print(Browser* browser) {
750 #if defined(ENABLE_PRINTING)
751   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
752 #if defined(ENABLE_FULL_PRINTING)
753   printing::PrintViewManager* print_view_manager =
754       printing::PrintViewManager::FromWebContents(contents);
755   if (browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled))
756     print_view_manager->PrintNow();
757   else
758     print_view_manager->PrintPreviewNow(false);
759 #else
760   printing::PrintViewManagerBasic* print_view_manager =
761       printing::PrintViewManagerBasic::FromWebContents(contents);
762   print_view_manager->PrintNow();
763 #endif  // defined(ENABLE_FULL_PRINTING)
764 #endif  // defined(ENABLE_PRINTING)
765 }
766 
CanPrint(const Browser * browser)767 bool CanPrint(const Browser* browser) {
768   // Do not print when printing is disabled via pref or policy.
769   // Do not print when a constrained window is showing. It's confusing.
770   return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
771       !(IsShowingWebContentsModalDialog(browser) ||
772       GetContentRestrictions(browser) & CONTENT_RESTRICTION_PRINT);
773 }
774 
AdvancedPrint(Browser * browser)775 void AdvancedPrint(Browser* browser) {
776 #if defined(ENABLE_FULL_PRINTING)
777   printing::PrintViewManager* print_view_manager =
778       printing::PrintViewManager::FromWebContents(
779           browser->tab_strip_model()->GetActiveWebContents());
780   print_view_manager->AdvancedPrintNow();
781 #endif
782 }
783 
CanAdvancedPrint(const Browser * browser)784 bool CanAdvancedPrint(const Browser* browser) {
785   // If printing is not disabled via pref or policy, it is always possible to
786   // advanced print when the print preview is visible.  The exception to this
787   // is under Win8 ash, since showing the advanced print dialog will open it
788   // modally on the Desktop and hang the browser.  We can remove this check
789   // once we integrate with the system print charm.
790 #if defined(OS_WIN)
791   if (chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH)
792     return false;
793 #endif
794 
795   return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
796       (PrintPreviewShowing(browser) || CanPrint(browser));
797 }
798 
PrintToDestination(Browser * browser)799 void PrintToDestination(Browser* browser) {
800 #if defined(ENABLE_FULL_PRINTING)
801   printing::PrintViewManager* print_view_manager =
802       printing::PrintViewManager::FromWebContents(
803           browser->tab_strip_model()->GetActiveWebContents());
804   print_view_manager->PrintToDestination();
805 #endif
806 }
807 
EmailPageLocation(Browser * browser)808 void EmailPageLocation(Browser* browser) {
809   content::RecordAction(UserMetricsAction("EmailPageLocation"));
810   WebContents* wc = browser->tab_strip_model()->GetActiveWebContents();
811   DCHECK(wc);
812 
813   std::string title = net::EscapeQueryParamValue(
814       UTF16ToUTF8(wc->GetTitle()), false);
815   std::string page_url = net::EscapeQueryParamValue(wc->GetURL().spec(), false);
816   std::string mailto = std::string("mailto:?subject=Fwd:%20") +
817       title + "&body=%0A%0A" + page_url;
818   platform_util::OpenExternal(browser->profile(), GURL(mailto));
819 }
820 
CanEmailPageLocation(const Browser * browser)821 bool CanEmailPageLocation(const Browser* browser) {
822   return browser->toolbar_model()->ShouldDisplayURL() &&
823       browser->tab_strip_model()->GetActiveWebContents()->GetURL().is_valid();
824 }
825 
Cut(Browser * browser)826 void Cut(Browser* browser) {
827   content::RecordAction(UserMetricsAction("Cut"));
828   browser->window()->Cut();
829 }
830 
Copy(Browser * browser)831 void Copy(Browser* browser) {
832   content::RecordAction(UserMetricsAction("Copy"));
833   browser->window()->Copy();
834 }
835 
Paste(Browser * browser)836 void Paste(Browser* browser) {
837   content::RecordAction(UserMetricsAction("Paste"));
838   browser->window()->Paste();
839 }
840 
Find(Browser * browser)841 void Find(Browser* browser) {
842   content::RecordAction(UserMetricsAction("Find"));
843   FindInPage(browser, false, false);
844 }
845 
FindNext(Browser * browser)846 void FindNext(Browser* browser) {
847   content::RecordAction(UserMetricsAction("FindNext"));
848   FindInPage(browser, true, true);
849 }
850 
FindPrevious(Browser * browser)851 void FindPrevious(Browser* browser) {
852   content::RecordAction(UserMetricsAction("FindPrevious"));
853   FindInPage(browser, true, false);
854 }
855 
FindInPage(Browser * browser,bool find_next,bool forward_direction)856 void FindInPage(Browser* browser, bool find_next, bool forward_direction) {
857   ShowFindBar(browser);
858   if (find_next) {
859     base::string16 find_text;
860     FindTabHelper* find_helper = FindTabHelper::FromWebContents(
861         browser->tab_strip_model()->GetActiveWebContents());
862 #if defined(OS_MACOSX)
863     // We always want to search for the current contents of the find bar on
864     // OS X. For regular profile it's always the current find pboard. For
865     // Incognito window it's the newest value of the find pboard content and
866     // user-typed text.
867     FindBar* find_bar = browser->GetFindBarController()->find_bar();
868     find_text = find_bar->GetFindText();
869 #endif
870     find_helper->StartFinding(find_text, forward_direction, false);
871   }
872 }
873 
Zoom(Browser * browser,content::PageZoom zoom)874 void Zoom(Browser* browser, content::PageZoom zoom) {
875   if (browser->is_devtools())
876     return;
877 
878   chrome_page_zoom::Zoom(browser->tab_strip_model()->GetActiveWebContents(),
879                          zoom);
880 }
881 
FocusToolbar(Browser * browser)882 void FocusToolbar(Browser* browser) {
883   content::RecordAction(UserMetricsAction("FocusToolbar"));
884   browser->window()->FocusToolbar();
885 }
886 
FocusLocationBar(Browser * browser)887 void FocusLocationBar(Browser* browser) {
888   content::RecordAction(UserMetricsAction("FocusLocation"));
889   browser->window()->SetFocusToLocationBar(true);
890 }
891 
FocusSearch(Browser * browser)892 void FocusSearch(Browser* browser) {
893   // TODO(beng): replace this with FocusLocationBar
894   content::RecordAction(UserMetricsAction("FocusSearch"));
895   browser->window()->GetLocationBar()->FocusSearch();
896 }
897 
FocusAppMenu(Browser * browser)898 void FocusAppMenu(Browser* browser) {
899   content::RecordAction(UserMetricsAction("FocusAppMenu"));
900   browser->window()->FocusAppMenu();
901 }
902 
FocusBookmarksToolbar(Browser * browser)903 void FocusBookmarksToolbar(Browser* browser) {
904   content::RecordAction(UserMetricsAction("FocusBookmarksToolbar"));
905   browser->window()->FocusBookmarksToolbar();
906 }
907 
FocusInfobars(Browser * browser)908 void FocusInfobars(Browser* browser) {
909   content::RecordAction(UserMetricsAction("FocusInfobars"));
910   browser->window()->FocusInfobars();
911 }
912 
FocusNextPane(Browser * browser)913 void FocusNextPane(Browser* browser) {
914   content::RecordAction(UserMetricsAction("FocusNextPane"));
915   browser->window()->RotatePaneFocus(true);
916 }
917 
FocusPreviousPane(Browser * browser)918 void FocusPreviousPane(Browser* browser) {
919   content::RecordAction(UserMetricsAction("FocusPreviousPane"));
920   browser->window()->RotatePaneFocus(false);
921 }
922 
ToggleDevToolsWindow(Browser * browser,DevToolsToggleAction action)923 void ToggleDevToolsWindow(Browser* browser, DevToolsToggleAction action) {
924   if (action.type() == DevToolsToggleAction::kShowConsole)
925     content::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
926   else
927     content::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
928   DevToolsWindow::ToggleDevToolsWindow(browser, action);
929 }
930 
CanOpenTaskManager()931 bool CanOpenTaskManager() {
932 #if defined(OS_WIN)
933   // In metro we can't display the task manager, as it is a native window.
934   return !win8::IsSingleWindowMetroMode();
935 #else
936   return true;
937 #endif
938 }
939 
OpenTaskManager(Browser * browser)940 void OpenTaskManager(Browser* browser) {
941   content::RecordAction(UserMetricsAction("TaskManager"));
942   chrome::ShowTaskManager(browser);
943 }
944 
OpenFeedbackDialog(Browser * browser)945 void OpenFeedbackDialog(Browser* browser) {
946   content::RecordAction(UserMetricsAction("Feedback"));
947   chrome::ShowFeedbackPage(browser, std::string(), std::string());
948 }
949 
ToggleBookmarkBar(Browser * browser)950 void ToggleBookmarkBar(Browser* browser) {
951   content::RecordAction(UserMetricsAction("ShowBookmarksBar"));
952   ToggleBookmarkBarWhenVisible(browser->profile());
953 }
954 
ShowAppMenu(Browser * browser)955 void ShowAppMenu(Browser* browser) {
956   // We record the user metric for this event in WrenchMenu::RunMenu.
957   browser->window()->ShowAppMenu();
958 }
959 
ShowAvatarMenu(Browser * browser)960 void ShowAvatarMenu(Browser* browser) {
961   browser->window()->ShowAvatarBubbleFromAvatarButton();
962 }
963 
OpenUpdateChromeDialog(Browser * browser)964 void OpenUpdateChromeDialog(Browser* browser) {
965   if (UpgradeDetector::GetInstance()->is_outdated_install()) {
966     content::NotificationService::current()->Notify(
967         chrome::NOTIFICATION_OUTDATED_INSTALL,
968         content::NotificationService::AllSources(),
969         content::NotificationService::NoDetails());
970   } else {
971     content::RecordAction(UserMetricsAction("UpdateChrome"));
972     browser->window()->ShowUpdateChromeDialog();
973   }
974 }
975 
ToggleSpeechInput(Browser * browser)976 void ToggleSpeechInput(Browser* browser) {
977   WebContents* web_contents =
978       browser->tab_strip_model()->GetActiveWebContents();
979   web_contents->GetRenderViewHost()->ToggleSpeechInput();
980 
981   SearchTabHelper* search_tab_helper =
982       SearchTabHelper::FromWebContents(web_contents);
983   // |search_tab_helper| can be null in unit tests.
984   if (search_tab_helper)
985     search_tab_helper->ToggleVoiceSearch();
986 }
987 
CanRequestTabletSite(WebContents * current_tab)988 bool CanRequestTabletSite(WebContents* current_tab) {
989   if (!current_tab)
990     return false;
991   return current_tab->GetController().GetActiveEntry() != NULL;
992 }
993 
IsRequestingTabletSite(Browser * browser)994 bool IsRequestingTabletSite(Browser* browser) {
995   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
996   if (!current_tab)
997     return false;
998   content::NavigationEntry* entry =
999       current_tab->GetController().GetActiveEntry();
1000   if (!entry)
1001     return false;
1002   return entry->GetIsOverridingUserAgent();
1003 }
1004 
ToggleRequestTabletSite(Browser * browser)1005 void ToggleRequestTabletSite(Browser* browser) {
1006   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
1007   if (!current_tab)
1008     return;
1009   NavigationController& controller = current_tab->GetController();
1010   NavigationEntry* entry = controller.GetActiveEntry();
1011   if (!entry)
1012     return;
1013   if (entry->GetIsOverridingUserAgent()) {
1014     entry->SetIsOverridingUserAgent(false);
1015   } else {
1016     entry->SetIsOverridingUserAgent(true);
1017     chrome::VersionInfo version_info;
1018     std::string product;
1019     if (version_info.is_valid())
1020       product = version_info.ProductNameAndVersionForUserAgent();
1021     current_tab->SetUserAgentOverride(
1022         webkit_glue::BuildUserAgentFromOSAndProduct(
1023             kOsOverrideForTabletSite, product));
1024   }
1025   controller.ReloadOriginalRequestURL(true);
1026 }
1027 
ToggleFullscreenMode(Browser * browser)1028 void ToggleFullscreenMode(Browser* browser) {
1029   browser->fullscreen_controller()->ToggleFullscreenMode();
1030 }
1031 
ClearCache(Browser * browser)1032 void ClearCache(Browser* browser) {
1033   BrowsingDataRemover* remover =
1034       BrowsingDataRemover::CreateForUnboundedRange(browser->profile());
1035   remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
1036                   BrowsingDataHelper::UNPROTECTED_WEB);
1037   // BrowsingDataRemover takes care of deleting itself when done.
1038 }
1039 
IsDebuggerAttachedToCurrentTab(Browser * browser)1040 bool IsDebuggerAttachedToCurrentTab(Browser* browser) {
1041   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
1042   return contents ?
1043       content::DevToolsAgentHost::IsDebuggerAttached(contents) : false;
1044 }
1045 
ViewSource(Browser * browser,WebContents * contents)1046 void ViewSource(Browser* browser, WebContents* contents) {
1047   DCHECK(contents);
1048 
1049   // Use the last committed entry, since the pending entry hasn't loaded yet and
1050   // won't be copied into the cloned tab.
1051   NavigationEntry* entry = contents->GetController().GetLastCommittedEntry();
1052   if (!entry)
1053     return;
1054 
1055   ViewSource(browser, contents, entry->GetURL(), entry->GetPageState());
1056 }
1057 
ViewSource(Browser * browser,WebContents * contents,const GURL & url,const content::PageState & page_state)1058 void ViewSource(Browser* browser,
1059                 WebContents* contents,
1060                 const GURL& url,
1061                 const content::PageState& page_state) {
1062   content::RecordAction(UserMetricsAction("ViewSource"));
1063   DCHECK(contents);
1064 
1065   // Note that Clone does not copy the pending or transient entries, so the
1066   // active entry in view_source_contents will be the last committed entry.
1067   WebContents* view_source_contents = contents->Clone();
1068   DCHECK(view_source_contents->GetController().CanPruneAllButLastCommitted());
1069   view_source_contents->GetController().PruneAllButLastCommitted();
1070   NavigationEntry* active_entry =
1071       view_source_contents->GetController().GetActiveEntry();
1072   if (!active_entry)
1073     return;
1074 
1075   GURL view_source_url =
1076       GURL(content::kViewSourceScheme + std::string(":") + url.spec());
1077   active_entry->SetVirtualURL(view_source_url);
1078 
1079   // Do not restore scroller position.
1080   active_entry->SetPageState(page_state.RemoveScrollOffset());
1081 
1082   // Do not restore title, derive it from the url.
1083   active_entry->SetTitle(string16());
1084 
1085   // Now show view-source entry.
1086   if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
1087     // If this is a tabbed browser, just create a duplicate tab inside the same
1088     // window next to the tab being duplicated.
1089     int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
1090     int add_types = TabStripModel::ADD_ACTIVE |
1091         TabStripModel::ADD_INHERIT_GROUP;
1092     browser->tab_strip_model()->InsertWebContentsAt(
1093         index + 1,
1094         view_source_contents,
1095         add_types);
1096   } else {
1097     Browser* b = new Browser(
1098         Browser::CreateParams(Browser::TYPE_TABBED, browser->profile(),
1099                               browser->host_desktop_type()));
1100 
1101     // Preserve the size of the original window. The new window has already
1102     // been given an offset by the OS, so we shouldn't copy the old bounds.
1103     BrowserWindow* new_window = b->window();
1104     new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
1105                           browser->window()->GetRestoredBounds().size()));
1106 
1107     // We need to show the browser now. Otherwise ContainerWin assumes the
1108     // WebContents is invisible and won't size it.
1109     b->window()->Show();
1110 
1111     // The page transition below is only for the purpose of inserting the tab.
1112     b->tab_strip_model()->AddWebContents(view_source_contents, -1,
1113                                          content::PAGE_TRANSITION_LINK,
1114                                          TabStripModel::ADD_ACTIVE);
1115   }
1116 
1117   SessionService* session_service =
1118       SessionServiceFactory::GetForProfileIfExisting(browser->profile());
1119   if (session_service)
1120     session_service->TabRestored(view_source_contents, false);
1121 }
1122 
ViewSelectedSource(Browser * browser)1123 void ViewSelectedSource(Browser* browser) {
1124   ViewSource(browser, browser->tab_strip_model()->GetActiveWebContents());
1125 }
1126 
CanViewSource(const Browser * browser)1127 bool CanViewSource(const Browser* browser) {
1128   return browser->tab_strip_model()->GetActiveWebContents()->
1129       GetController().CanViewSource();
1130 }
1131 
CreateApplicationShortcuts(Browser * browser)1132 void CreateApplicationShortcuts(Browser* browser) {
1133   content::RecordAction(UserMetricsAction("CreateShortcut"));
1134   extensions::TabHelper::FromWebContents(
1135       browser->tab_strip_model()->GetActiveWebContents())->
1136           CreateApplicationShortcuts();
1137 }
1138 
CreateHostedAppFromCurrentWebContents(Browser * browser)1139 void CreateHostedAppFromCurrentWebContents(Browser* browser) {
1140   content::RecordAction(UserMetricsAction("CreateHostedApp"));
1141   extensions::TabHelper::FromWebContents(
1142       browser->tab_strip_model()->GetActiveWebContents())->
1143           CreateHostedAppFromWebContents();
1144 }
1145 
CanCreateApplicationShortcuts(const Browser * browser)1146 bool CanCreateApplicationShortcuts(const Browser* browser) {
1147   return extensions::TabHelper::FromWebContents(
1148       browser->tab_strip_model()->GetActiveWebContents())->
1149           CanCreateApplicationShortcuts();
1150 }
1151 
ConvertTabToAppWindow(Browser * browser,content::WebContents * contents)1152 void ConvertTabToAppWindow(Browser* browser,
1153                            content::WebContents* contents) {
1154   const GURL& url = contents->GetController().GetActiveEntry()->GetURL();
1155   std::string app_name = web_app::GenerateApplicationNameFromURL(url);
1156 
1157   int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
1158   if (index >= 0)
1159     browser->tab_strip_model()->DetachWebContentsAt(index);
1160 
1161   Browser* app_browser = new Browser(
1162       Browser::CreateParams::CreateForApp(
1163           Browser::TYPE_POPUP, app_name, gfx::Rect(), browser->profile(),
1164           browser->host_desktop_type()));
1165   app_browser->tab_strip_model()->AppendWebContents(contents, true);
1166 
1167   contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
1168   contents->GetRenderViewHost()->SyncRendererPrefs();
1169   app_browser->window()->Show();
1170 }
1171 
1172 }  // namespace chrome
1173