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