Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h" | 5 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 183 | 183 |
| 184 void UrlsToTabs(const std::vector<GURL>& urls, StartupTabs* tabs) { | 184 void UrlsToTabs(const std::vector<GURL>& urls, StartupTabs* tabs) { |
| 185 for (size_t i = 0; i < urls.size(); ++i) { | 185 for (size_t i = 0; i < urls.size(); ++i) { |
| 186 StartupTab tab; | 186 StartupTab tab; |
| 187 tab.is_pinned = false; | 187 tab.is_pinned = false; |
| 188 tab.url = urls[i]; | 188 tab.url = urls[i]; |
| 189 tabs->push_back(tab); | 189 tabs->push_back(tab); |
| 190 } | 190 } |
| 191 } | 191 } |
| 192 | 192 |
| 193 std::vector<GURL> TabsToUrls(const StartupTabs& tabs) { | |
| 194 std::vector<GURL> urls(tabs.size()); | |
|
grt (UTC plus 2)
2016/10/28 18:49:16
micro-optimization: you could default construct th
| |
| 195 std::transform(tabs.begin(), tabs.end(), urls.begin(), | |
| 196 [](StartupTab tab) { return tab.url; }); | |
|
grt (UTC plus 2)
2016/10/28 18:49:15
const StartupTab& tab
| |
| 197 return urls; | |
| 198 } | |
| 199 | |
| 193 // Return true if the command line option --app-id is used. Set | 200 // Return true if the command line option --app-id is used. Set |
| 194 // |out_extension| to the app to open, and |out_launch_container| | 201 // |out_extension| to the app to open, and |out_launch_container| |
| 195 // to the type of window into which the app should be open. | 202 // to the type of window into which the app should be open. |
| 196 bool GetAppLaunchContainer( | 203 bool GetAppLaunchContainer( |
| 197 Profile* profile, | 204 Profile* profile, |
| 198 const std::string& app_id, | 205 const std::string& app_id, |
| 199 const Extension** out_extension, | 206 const Extension** out_extension, |
| 200 extensions::LaunchContainer* out_launch_container) { | 207 extensions::LaunchContainer* out_launch_container) { |
| 201 | 208 |
| 202 const Extension* extension = extensions::ExtensionRegistry::Get( | 209 const Extension* extension = extensions::ExtensionRegistry::Get( |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 261 extension_id, extensions::ExtensionRegistry::EVERYTHING); | 268 extension_id, extensions::ExtensionRegistry::EVERYTHING); |
| 262 return extension && extension->is_platform_app() ? extension : NULL; | 269 return extension && extension->is_platform_app() ? extension : NULL; |
| 263 } | 270 } |
| 264 | 271 |
| 265 // Appends the contents of |from| to the end of |to|. | 272 // Appends the contents of |from| to the end of |to|. |
| 266 void AppendTabs(const StartupTabs& from, StartupTabs* to) { | 273 void AppendTabs(const StartupTabs& from, StartupTabs* to) { |
| 267 if (!from.empty()) | 274 if (!from.empty()) |
| 268 to->insert(to->end(), from.begin(), from.end()); | 275 to->insert(to->end(), from.begin(), from.end()); |
| 269 } | 276 } |
| 270 | 277 |
| 278 // Determines whether the Consolidated startup flow should be used, based on | |
| 279 // OS, OS version, and the kUseConsolidatedStartupFlow Feature. | |
| 280 bool UseConsolidatedFlow() { | |
| 281 #if defined(OS_WIN) | |
| 282 if (base::win::GetVersion() >= base::win::VERSION_WIN10) | |
| 283 return false; | |
| 284 #endif // defined(OS_WIN) | |
| 285 return base::FeatureList::IsEnabled(features::kUseConsolidatedStartupFlow); | |
| 286 } | |
| 287 | |
| 271 } // namespace | 288 } // namespace |
| 272 | 289 |
| 273 namespace internals { | 290 namespace internals { |
| 274 | 291 |
| 275 GURL GetTriggeredResetSettingsURL() { | 292 GURL GetTriggeredResetSettingsURL() { |
| 276 return GURL( | 293 return GURL( |
| 277 chrome::GetSettingsUrl(chrome::kTriggeredResetProfileSettingsSubPage)); | 294 chrome::GetSettingsUrl(chrome::kTriggeredResetProfileSettingsSubPage)); |
| 278 } | 295 } |
| 279 | 296 |
| 280 GURL GetWelcomePageURL() { | 297 GURL GetWelcomePageURL() { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 347 // URLs in that case. The user should see the window as an app, | 364 // URLs in that case. The user should see the window as an app, |
| 348 // not as chrome. | 365 // not as chrome. |
| 349 // Special case is when app switches are passed but we do want to restore | 366 // Special case is when app switches are passed but we do want to restore |
| 350 // session. In that case open app window + focus it after session is restored. | 367 // session. In that case open app window + focus it after session is restored. |
| 351 if (OpenApplicationWindow(profile)) { | 368 if (OpenApplicationWindow(profile)) { |
| 352 RecordLaunchModeHistogram(LM_AS_WEBAPP); | 369 RecordLaunchModeHistogram(LM_AS_WEBAPP); |
| 353 } else { | 370 } else { |
| 354 RecordLaunchModeHistogram(urls_to_open.empty() ? | 371 RecordLaunchModeHistogram(urls_to_open.empty() ? |
| 355 LM_TO_BE_DECIDED : LM_WITH_URLS); | 372 LM_TO_BE_DECIDED : LM_WITH_URLS); |
| 356 | 373 |
| 357 if (base::FeatureList::IsEnabled(features::kUseConsolidatedStartupFlow)) | 374 if (UseConsolidatedFlow()) |
| 358 ProcessLaunchUrlsUsingConsolidatedFlow(process_startup, urls_to_open); | 375 ProcessLaunchUrlsUsingConsolidatedFlow(process_startup, urls_to_open); |
| 359 else | 376 else |
| 360 ProcessLaunchURLs(process_startup, urls_to_open); | 377 ProcessLaunchURLs(process_startup, urls_to_open); |
| 361 | 378 |
| 362 if (command_line_.HasSwitch(switches::kInstallChromeApp)) { | 379 if (command_line_.HasSwitch(switches::kInstallChromeApp)) { |
| 363 install_chrome_app::InstallChromeApp( | 380 install_chrome_app::InstallChromeApp( |
| 364 command_line_.GetSwitchValueASCII(switches::kInstallChromeApp)); | 381 command_line_.GetSwitchValueASCII(switches::kInstallChromeApp)); |
| 365 } | 382 } |
| 366 | 383 |
| 367 // If this is an app launch, but we didn't open an app window, it may | 384 // If this is an app launch, but we didn't open an app window, it may |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 589 void StartupBrowserCreatorImpl::ProcessLaunchUrlsUsingConsolidatedFlow( | 606 void StartupBrowserCreatorImpl::ProcessLaunchUrlsUsingConsolidatedFlow( |
| 590 bool process_startup, | 607 bool process_startup, |
| 591 const std::vector<GURL>& cmd_line_urls) { | 608 const std::vector<GURL>& cmd_line_urls) { |
| 592 // Don't open any browser windows if starting up in "background mode". | 609 // Don't open any browser windows if starting up in "background mode". |
| 593 if (process_startup && command_line_.HasSwitch(switches::kNoStartupWindow)) | 610 if (process_startup && command_line_.HasSwitch(switches::kNoStartupWindow)) |
| 594 return; | 611 return; |
| 595 | 612 |
| 596 StartupTabs cmd_line_tabs; | 613 StartupTabs cmd_line_tabs; |
| 597 UrlsToTabs(cmd_line_urls, &cmd_line_tabs); | 614 UrlsToTabs(cmd_line_urls, &cmd_line_tabs); |
| 598 | 615 |
| 599 bool is_incognito = IncognitoModePrefs::ShouldLaunchIncognito( | 616 bool is_incognito_or_guest = |
| 600 command_line_, profile_->GetPrefs()); | 617 profile_->GetProfileType() != Profile::ProfileType::REGULAR_PROFILE; |
| 601 bool is_post_crash_launch = HasPendingUncleanExit(profile_); | 618 bool is_post_crash_launch = HasPendingUncleanExit(profile_); |
| 602 StartupTabs tabs = | 619 StartupTabs tabs = |
| 603 DetermineStartupTabs(StartupTabProviderImpl(), cmd_line_tabs, | 620 DetermineStartupTabs(StartupTabProviderImpl(), cmd_line_tabs, |
| 604 is_incognito, is_post_crash_launch); | 621 is_incognito_or_guest, is_post_crash_launch); |
| 605 | 622 |
| 606 // TODO(tmartino): If this is not process startup, attempt to restore | 623 // If an async restore is necessary and is successfully kicked off, the |
| 607 // asynchronously and return here. This logic is self-contained in | 624 // remainder of the process is self-contained, so return. |
| 608 // SessionService and therefore can't be combined with the other Browser | 625 if (MaybeAsyncRestore(tabs, process_startup, is_post_crash_launch)) |
| 609 // creation logic. | 626 return; |
| 610 | 627 |
| 611 // TODO(tmartino): Function which determines what behavior of session | 628 BrowserOpenBehavior behavior = DetermineBrowserOpenBehavior( |
| 612 // restore, if any, is necessary, and passes the result to a new function | 629 StartupBrowserCreator::GetSessionStartupPref(command_line_, profile_), |
| 613 // which opens tabs in a restored or newly-created Browser accordingly. | 630 process_startup, is_post_crash_launch, |
| 614 // Incorporates code from ProcessStartupUrls. | 631 command_line_.HasSwitch(switches::kRestoreLastSession), |
| 632 command_line_.HasSwitch(switches::kOpenInNewWindow), | |
| 633 !cmd_line_tabs.empty()); | |
| 615 | 634 |
| 616 Browser* browser = OpenTabsInBrowser(nullptr, process_startup, tabs); | 635 uint32_t restore_options = 0; |
| 636 if (behavior == BrowserOpenBehavior::SYNCHRONOUS_RESTORE) { | |
| 637 #if defined(OS_MACOSX) | |
| 638 bool was_mac_login_or_resume = base::mac::WasLaunchedAsLoginOrResumeItem(); | |
| 639 #else | |
| 640 bool was_mac_login_or_resume = false; | |
| 641 #endif | |
| 642 restore_options = DetermineSynchronousRestoreOptions( | |
| 643 browser_defaults::kAlwaysCreateTabbedBrowserOnSessionRestore, | |
| 644 base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 645 switches::kCreateBrowserOnStartupForTests), | |
| 646 was_mac_login_or_resume); | |
| 647 } | |
| 648 | |
| 649 Browser* browser = RestoreOrCreateBrowser( | |
| 650 tabs, behavior, restore_options, process_startup, is_post_crash_launch); | |
| 617 | 651 |
| 618 // Finally, add info bars. | 652 // Finally, add info bars. |
| 619 AddInfoBarsIfNecessary( | 653 AddInfoBarsIfNecessary( |
| 620 browser, process_startup ? chrome::startup::IS_PROCESS_STARTUP | 654 browser, process_startup ? chrome::startup::IS_PROCESS_STARTUP |
| 621 : chrome::startup::IS_NOT_PROCESS_STARTUP); | 655 : chrome::startup::IS_NOT_PROCESS_STARTUP); |
| 622 } | 656 } |
| 623 | 657 |
| 624 StartupTabs StartupBrowserCreatorImpl::DetermineStartupTabs( | 658 StartupTabs StartupBrowserCreatorImpl::DetermineStartupTabs( |
| 625 const StartupTabProvider& provider, | 659 const StartupTabProvider& provider, |
| 626 const StartupTabs& cmd_line_tabs, | 660 const StartupTabs& cmd_line_tabs, |
| 627 bool is_incognito, | 661 bool is_incognito_or_guest, |
| 628 bool is_post_crash_launch) { | 662 bool is_post_crash_launch) { |
| 629 // Only the New Tab Page or command line URLs may be shown in incognito mode. | 663 // Only the New Tab Page or command line URLs may be shown in incognito mode. |
| 630 // A similar policy exists for crash recovery launches, to prevent getting the | 664 // A similar policy exists for crash recovery launches, to prevent getting the |
| 631 // user stuck in a crash loop. | 665 // user stuck in a crash loop. |
| 632 if (is_incognito || is_post_crash_launch) { | 666 if (is_incognito_or_guest || is_post_crash_launch) { |
| 633 if (cmd_line_tabs.empty()) | 667 if (cmd_line_tabs.empty()) |
| 634 return StartupTabs({StartupTab(GURL(chrome::kChromeUINewTabURL), false)}); | 668 return StartupTabs({StartupTab(GURL(chrome::kChromeUINewTabURL), false)}); |
| 635 return cmd_line_tabs; | 669 return cmd_line_tabs; |
| 636 } | 670 } |
| 637 | 671 |
| 638 // A trigger on a profile may indicate that we should show a tab which | 672 // A trigger on a profile may indicate that we should show a tab which |
| 639 // offers to reset the user's settings. When this appears, it is first, and | 673 // offers to reset the user's settings. When this appears, it is first, and |
| 640 // may be shown alongside command-line tabs. | 674 // may be shown alongside command-line tabs. |
| 641 StartupTabs tabs = provider.GetResetTriggerTabs(profile_); | 675 StartupTabs tabs = provider.GetResetTriggerTabs(profile_); |
| 642 | 676 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 658 // including OS and whether or not this is First Run. | 692 // including OS and whether or not this is First Run. |
| 659 StartupTabs onboarding_tabs = provider.GetOnboardingTabs(); | 693 StartupTabs onboarding_tabs = provider.GetOnboardingTabs(); |
| 660 AppendTabs(onboarding_tabs, &tabs); | 694 AppendTabs(onboarding_tabs, &tabs); |
| 661 | 695 |
| 662 // If the user has set the preference indicating URLs to show on opening, | 696 // If the user has set the preference indicating URLs to show on opening, |
| 663 // read and add those. | 697 // read and add those. |
| 664 StartupTabs prefs_tabs = provider.GetPreferencesTabs(command_line_, profile_); | 698 StartupTabs prefs_tabs = provider.GetPreferencesTabs(command_line_, profile_); |
| 665 AppendTabs(prefs_tabs, &tabs); | 699 AppendTabs(prefs_tabs, &tabs); |
| 666 | 700 |
| 667 // Potentially add the New Tab Page. Onboarding content is designed to | 701 // Potentially add the New Tab Page. Onboarding content is designed to |
| 668 // replace (and eventually funnel the user to) the NTP. Likewise, URLs read | 702 // replace (and eventually funnel the user to) the NTP. Likewise, URLs |
| 669 // from preferences are explicitly meant to override showing the NTP. | 703 // from preferences are explicitly meant to override showing the NTP. |
| 670 if (onboarding_tabs.empty() && prefs_tabs.empty()) | 704 if (onboarding_tabs.empty() && prefs_tabs.empty()) |
| 671 tabs.emplace_back(GURL(chrome::kChromeUINewTabURL), false); | 705 AppendTabs(provider.GetNewTabPageTabs(command_line_, profile_), &tabs); |
| 672 | 706 |
| 673 // Add any tabs which the user has previously pinned. | 707 // Maybe add any tabs which the user has previously pinned. |
| 674 AppendTabs(provider.GetPinnedTabs(profile_), &tabs); | 708 AppendTabs(provider.GetPinnedTabs(command_line_, profile_), &tabs); |
| 675 | 709 |
| 676 return tabs; | 710 return tabs; |
| 677 } | 711 } |
| 678 | 712 |
| 713 bool StartupBrowserCreatorImpl::MaybeAsyncRestore(const StartupTabs& tabs, | |
| 714 bool process_startup, | |
| 715 bool is_post_crash_launch) { | |
| 716 // Restore is performed synchronously on startup, and is never performed when | |
| 717 // launching after crashing. | |
| 718 if (process_startup || is_post_crash_launch) | |
| 719 return false; | |
| 720 | |
| 721 SessionService* service = | |
| 722 SessionServiceFactory::GetForProfileForSessionRestore(profile_); | |
| 723 | |
| 724 // Service will be null in incognito and guest mode. | |
| 725 return (service && service->RestoreIfNecessary(TabsToUrls(tabs))); | |
| 726 } | |
| 727 | |
| 728 Browser* StartupBrowserCreatorImpl::RestoreOrCreateBrowser( | |
| 729 const StartupTabs& tabs, | |
| 730 BrowserOpenBehavior behavior, | |
| 731 uint32_t restore_options, | |
| 732 bool process_startup, | |
| 733 bool is_post_crash_launch) { | |
| 734 Browser* browser = nullptr; | |
| 735 | |
| 736 if (behavior == BrowserOpenBehavior::SYNCHRONOUS_RESTORE) { | |
| 737 browser = SessionRestore::RestoreSession(profile_, nullptr, restore_options, | |
| 738 TabsToUrls(tabs)); | |
| 739 if (browser) | |
| 740 return browser; | |
| 741 } else if (behavior == BrowserOpenBehavior::USE_EXISTING) { | |
| 742 browser = chrome::FindTabbedBrowser(profile_, process_startup); | |
| 743 } | |
| 744 | |
| 745 StartupBrowserCreator::in_synchronous_profile_launch_ = true; | |
| 746 | |
| 747 // OpenTabsInBrowser requires at least one tab be passed. As a fallback to | |
| 748 // prevent a crash, use the NTP if |tabs| is empty. | |
| 749 browser = OpenTabsInBrowser( | |
| 750 browser, process_startup, | |
| 751 (tabs.empty() | |
| 752 ? StartupTabs({StartupTab(GURL(chrome::kChromeUINewTabURL), false)}) | |
| 753 : tabs)); | |
| 754 | |
| 755 StartupBrowserCreator::in_synchronous_profile_launch_ = false; | |
| 756 | |
| 757 // Now that a restore is no longer possible, it is safe to clear DOM storage, | |
| 758 // unless this is a crash recovery. | |
| 759 if (!is_post_crash_launch) { | |
| 760 content::BrowserContext::GetDefaultStoragePartition(profile_) | |
| 761 ->GetDOMStorageContext() | |
| 762 ->StartScavengingUnusedSessionStorage(); | |
| 763 } | |
| 764 | |
| 765 return browser; | |
| 766 } | |
| 767 | |
| 768 // static | |
| 769 StartupBrowserCreatorImpl::BrowserOpenBehavior | |
| 770 StartupBrowserCreatorImpl::DetermineBrowserOpenBehavior( | |
| 771 const SessionStartupPref& pref, | |
| 772 bool process_startup, | |
| 773 bool is_post_crash_launch, | |
| 774 bool has_restore_switch, | |
| 775 bool has_new_window_switch, | |
| 776 bool has_cmd_line_tabs) { | |
| 777 if (!process_startup) { | |
| 778 // For existing processes, restore would have happened before invoking this | |
| 779 // function. If Chrome was launched with passed URLs, assume these should | |
| 780 // be appended to an existing window if possible, unless overridden by | |
| 781 // switch. | |
| 782 return (has_cmd_line_tabs && !has_new_window_switch) | |
| 783 ? BrowserOpenBehavior::USE_EXISTING | |
| 784 : BrowserOpenBehavior::NEW; | |
| 785 } | |
| 786 | |
| 787 if (pref.type == SessionStartupPref::LAST) { | |
| 788 // Don't perform a session restore on a post-crash launch, as this could | |
| 789 // cause a crash loop. These checks can be overridden by a switch. | |
| 790 // TODO(crbug.com/647851): Group this check with the logic in | |
| 791 // GetSessionStartupPref. | |
| 792 if (!is_post_crash_launch || has_restore_switch) | |
| 793 return BrowserOpenBehavior::SYNCHRONOUS_RESTORE; | |
| 794 } | |
| 795 | |
| 796 return BrowserOpenBehavior::NEW; | |
| 797 } | |
| 798 | |
| 799 // static | |
| 800 uint32_t StartupBrowserCreatorImpl::DetermineSynchronousRestoreOptions( | |
| 801 bool has_create_browser_default, | |
| 802 bool has_create_browser_switch, | |
| 803 bool was_mac_login_or_resume) { | |
| 804 uint32_t options = SessionRestore::SYNCHRONOUS; | |
| 805 | |
| 806 // On Mac, when restoring a session with no windows, suppress the creation | |
| 807 // of a new window in the case where the system is launching Chrome via a | |
| 808 // login item or the resume feature in OS 10.7+. | |
| 809 if (!was_mac_login_or_resume && | |
| 810 (has_create_browser_default || has_create_browser_switch)) { | |
| 811 options |= SessionRestore::ALWAYS_CREATE_TABBED_BROWSER; | |
| 812 } | |
| 813 | |
| 814 return options; | |
| 815 } | |
| 816 | |
| 679 void StartupBrowserCreatorImpl::AddUniqueURLs(const std::vector<GURL>& urls, | 817 void StartupBrowserCreatorImpl::AddUniqueURLs(const std::vector<GURL>& urls, |
| 680 StartupTabs* tabs) { | 818 StartupTabs* tabs) { |
| 681 size_t num_existing_tabs = tabs->size(); | 819 size_t num_existing_tabs = tabs->size(); |
| 682 for (size_t i = 0; i < urls.size(); ++i) { | 820 for (size_t i = 0; i < urls.size(); ++i) { |
| 683 bool in_tabs = false; | 821 bool in_tabs = false; |
| 684 for (size_t j = 0; j < num_existing_tabs; ++j) { | 822 for (size_t j = 0; j < num_existing_tabs; ++j) { |
| 685 if (urls[i] == (*tabs)[j].url) { | 823 if (urls[i] == (*tabs)[j].url) { |
| 686 in_tabs = true; | 824 in_tabs = true; |
| 687 break; | 825 break; |
| 688 } | 826 } |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1082 #if defined(OS_WIN) | 1220 #if defined(OS_WIN) |
| 1083 TriggeredProfileResetter* triggered_profile_resetter = | 1221 TriggeredProfileResetter* triggered_profile_resetter = |
| 1084 TriggeredProfileResetterFactory::GetForBrowserContext(profile_); | 1222 TriggeredProfileResetterFactory::GetForBrowserContext(profile_); |
| 1085 // TriggeredProfileResetter instance will be nullptr for incognito profiles. | 1223 // TriggeredProfileResetter instance will be nullptr for incognito profiles. |
| 1086 if (triggered_profile_resetter) { | 1224 if (triggered_profile_resetter) { |
| 1087 has_reset_trigger = triggered_profile_resetter->HasResetTrigger(); | 1225 has_reset_trigger = triggered_profile_resetter->HasResetTrigger(); |
| 1088 } | 1226 } |
| 1089 #endif // defined(OS_WIN) | 1227 #endif // defined(OS_WIN) |
| 1090 return has_reset_trigger; | 1228 return has_reset_trigger; |
| 1091 } | 1229 } |
| OLD | NEW |