1 // Copyright 2016 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/startup/startup_tab_provider.h"
6 
7 #include "base/metrics/histogram_macros.h"
8 #include "build/branding_buildflags.h"
9 #include "chrome/browser/first_run/first_run.h"
10 #include "chrome/browser/profile_resetter/triggered_profile_resetter.h"
11 #include "chrome/browser/profile_resetter/triggered_profile_resetter_factory.h"
12 #include "chrome/browser/signin/identity_manager_factory.h"
13 #include "chrome/browser/signin/signin_util.h"
14 #include "chrome/browser/sync/profile_sync_service_factory.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_list.h"
17 #include "chrome/browser/ui/chrome_pages.h"
18 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/common/pref_names.h"
21 #include "chrome/common/url_constants.h"
22 #include "components/prefs/pref_service.h"
23 #include "components/signin/public/identity_manager/identity_manager.h"
24 #include "components/signin/public/identity_manager/primary_account_mutator.h"
25 #include "net/base/url_util.h"
26 
27 #if defined(OS_WIN)
28 #include "base/win/windows_version.h"
29 #include "chrome/browser/browser_process.h"
30 #include "chrome/browser/shell_integration.h"
31 #endif  // defined(OS_WIN)
32 
33 namespace {
34 
35 // Attempts to find an existing, non-empty tabbed browser for this profile.
ProfileHasOtherTabbedBrowser(Profile * profile)36 bool ProfileHasOtherTabbedBrowser(Profile* profile) {
37   BrowserList* browser_list = BrowserList::GetInstance();
38   auto other_tabbed_browser = std::find_if(
39       browser_list->begin(), browser_list->end(), [profile](Browser* browser) {
40         return browser->profile() == profile && browser->is_type_normal() &&
41                !browser->tab_strip_model()->empty();
42       });
43   return other_tabbed_browser != browser_list->end();
44 }
45 
46 }  // namespace
47 
GetOnboardingTabs(Profile * profile) const48 StartupTabs StartupTabProviderImpl::GetOnboardingTabs(Profile* profile) const {
49 // Chrome OS has its own welcome flow provided by OOBE.
50 #if defined(OS_CHROMEOS)
51   return StartupTabs();
52 #else
53   if (!profile)
54     return StartupTabs();
55 
56   StandardOnboardingTabsParams standard_params;
57   standard_params.is_first_run = first_run::IsChromeFirstRun();
58   PrefService* prefs = profile->GetPrefs();
59   standard_params.has_seen_welcome_page =
60       prefs && prefs->GetBoolean(prefs::kHasSeenWelcomePage);
61   standard_params.is_signin_allowed =
62       ProfileSyncServiceFactory::IsSyncAllowed(profile);
63   if (auto* identity_manager = IdentityManagerFactory::GetForProfile(profile)) {
64     standard_params.is_signed_in = identity_manager->HasPrimaryAccount();
65   }
66   standard_params.is_supervised_user = profile->IsSupervised();
67   standard_params.is_force_signin_enabled = signin_util::IsForceSigninEnabled();
68 
69   return GetStandardOnboardingTabsForState(standard_params);
70 #endif  // defined(OS_CHROMEOS)
71 }
72 
GetWelcomeBackTabs(Profile * profile,StartupBrowserCreator * browser_creator,bool process_startup) const73 StartupTabs StartupTabProviderImpl::GetWelcomeBackTabs(
74     Profile* profile,
75     StartupBrowserCreator* browser_creator,
76     bool process_startup) const {
77   StartupTabs tabs;
78   if (!process_startup || !browser_creator)
79     return tabs;
80   if (browser_creator->welcome_back_page() &&
81       CanShowWelcome(ProfileSyncServiceFactory::IsSyncAllowed(profile),
82                      profile->IsSupervised(),
83                      signin_util::IsForceSigninEnabled())) {
84     tabs.emplace_back(GetWelcomePageUrl(false), false);
85   }
86   return tabs;
87 }
88 
GetDistributionFirstRunTabs(StartupBrowserCreator * browser_creator) const89 StartupTabs StartupTabProviderImpl::GetDistributionFirstRunTabs(
90     StartupBrowserCreator* browser_creator) const {
91   if (!browser_creator)
92     return StartupTabs();
93   StartupTabs tabs = GetInitialPrefsTabsForState(
94       first_run::IsChromeFirstRun(), browser_creator->first_run_tabs_);
95   browser_creator->first_run_tabs_.clear();
96   return tabs;
97 }
98 
GetResetTriggerTabs(Profile * profile) const99 StartupTabs StartupTabProviderImpl::GetResetTriggerTabs(
100     Profile* profile) const {
101   auto* triggered_profile_resetter =
102       TriggeredProfileResetterFactory::GetForBrowserContext(profile);
103   bool has_reset_trigger = triggered_profile_resetter &&
104                            triggered_profile_resetter->HasResetTrigger();
105   return GetResetTriggerTabsForState(has_reset_trigger);
106 }
107 
GetPinnedTabs(const base::CommandLine & command_line,Profile * profile) const108 StartupTabs StartupTabProviderImpl::GetPinnedTabs(
109     const base::CommandLine& command_line,
110     Profile* profile) const {
111   return GetPinnedTabsForState(
112       StartupBrowserCreator::GetSessionStartupPref(command_line, profile),
113       PinnedTabCodec::ReadPinnedTabs(profile),
114       ProfileHasOtherTabbedBrowser(profile));
115 }
116 
GetPreferencesTabs(const base::CommandLine & command_line,Profile * profile) const117 StartupTabs StartupTabProviderImpl::GetPreferencesTabs(
118     const base::CommandLine& command_line,
119     Profile* profile) const {
120   return GetPreferencesTabsForState(
121       StartupBrowserCreator::GetSessionStartupPref(command_line, profile),
122       ProfileHasOtherTabbedBrowser(profile));
123 }
124 
GetNewTabPageTabs(const base::CommandLine & command_line,Profile * profile) const125 StartupTabs StartupTabProviderImpl::GetNewTabPageTabs(
126     const base::CommandLine& command_line,
127     Profile* profile) const {
128   return GetNewTabPageTabsForState(
129       StartupBrowserCreator::GetSessionStartupPref(command_line, profile));
130 }
131 
GetPostCrashTabs(bool has_incompatible_applications) const132 StartupTabs StartupTabProviderImpl::GetPostCrashTabs(
133     bool has_incompatible_applications) const {
134   return GetPostCrashTabsForState(has_incompatible_applications);
135 }
136 
GetExtensionCheckupTabs(bool serve_extensions_page) const137 StartupTabs StartupTabProviderImpl::GetExtensionCheckupTabs(
138     bool serve_extensions_page) const {
139   return GetExtensionCheckupTabsForState(serve_extensions_page);
140 }
141 
142 // static
CanShowWelcome(bool is_signin_allowed,bool is_supervised_user,bool is_force_signin_enabled)143 bool StartupTabProviderImpl::CanShowWelcome(bool is_signin_allowed,
144                                             bool is_supervised_user,
145                                             bool is_force_signin_enabled) {
146   return is_signin_allowed && !is_supervised_user && !is_force_signin_enabled;
147 }
148 
149 // static
ShouldShowWelcomeForOnboarding(bool has_seen_welcome_page,bool is_signed_in)150 bool StartupTabProviderImpl::ShouldShowWelcomeForOnboarding(
151     bool has_seen_welcome_page,
152     bool is_signed_in) {
153   return !has_seen_welcome_page && !is_signed_in;
154 }
155 
156 // static
GetStandardOnboardingTabsForState(const StandardOnboardingTabsParams & params)157 StartupTabs StartupTabProviderImpl::GetStandardOnboardingTabsForState(
158     const StandardOnboardingTabsParams& params) {
159   StartupTabs tabs;
160   if (CanShowWelcome(params.is_signin_allowed, params.is_supervised_user,
161                      params.is_force_signin_enabled) &&
162       ShouldShowWelcomeForOnboarding(params.has_seen_welcome_page,
163                                      params.is_signed_in)) {
164     tabs.emplace_back(GetWelcomePageUrl(!params.is_first_run), false);
165   }
166   return tabs;
167 }
168 
169 // static
GetInitialPrefsTabsForState(bool is_first_run,const std::vector<GURL> & first_run_tabs)170 StartupTabs StartupTabProviderImpl::GetInitialPrefsTabsForState(
171     bool is_first_run,
172     const std::vector<GURL>& first_run_tabs) {
173   // Constants: Magic words used by initial preferences files in place of a URL
174   // host to indicate that internal pages should appear on first run.
175   static constexpr char kNewTabUrlHost[] = "new_tab_page";
176   static constexpr char kWelcomePageUrlHost[] = "welcome_page";
177 
178   StartupTabs tabs;
179   if (is_first_run) {
180     tabs.reserve(first_run_tabs.size());
181     for (GURL url : first_run_tabs) {
182       if (url.host_piece() == kNewTabUrlHost)
183         url = GURL(chrome::kChromeUINewTabURL);
184       else if (url.host_piece() == kWelcomePageUrlHost)
185         url = GetWelcomePageUrl(false);
186       tabs.emplace_back(url, false);
187     }
188   }
189   return tabs;
190 }
191 
192 // static
GetResetTriggerTabsForState(bool profile_has_trigger)193 StartupTabs StartupTabProviderImpl::GetResetTriggerTabsForState(
194     bool profile_has_trigger) {
195   StartupTabs tabs;
196   if (profile_has_trigger)
197     tabs.emplace_back(GetTriggeredResetSettingsUrl(), false);
198   return tabs;
199 }
200 
201 // static
GetPinnedTabsForState(const SessionStartupPref & pref,const StartupTabs & pinned_tabs,bool profile_has_other_tabbed_browser)202 StartupTabs StartupTabProviderImpl::GetPinnedTabsForState(
203     const SessionStartupPref& pref,
204     const StartupTabs& pinned_tabs,
205     bool profile_has_other_tabbed_browser) {
206   if (pref.type == SessionStartupPref::Type::LAST ||
207       profile_has_other_tabbed_browser)
208     return StartupTabs();
209   return pinned_tabs;
210 }
211 
212 // static
GetPreferencesTabsForState(const SessionStartupPref & pref,bool profile_has_other_tabbed_browser)213 StartupTabs StartupTabProviderImpl::GetPreferencesTabsForState(
214     const SessionStartupPref& pref,
215     bool profile_has_other_tabbed_browser) {
216   StartupTabs tabs;
217   if (pref.type == SessionStartupPref::Type::URLS && !pref.urls.empty() &&
218       !profile_has_other_tabbed_browser) {
219     for (const auto& url : pref.urls)
220       tabs.push_back(StartupTab(url, false));
221   }
222   return tabs;
223 }
224 
225 // static
GetNewTabPageTabsForState(const SessionStartupPref & pref)226 StartupTabs StartupTabProviderImpl::GetNewTabPageTabsForState(
227     const SessionStartupPref& pref) {
228   StartupTabs tabs;
229   if (pref.type != SessionStartupPref::Type::LAST)
230     tabs.emplace_back(GURL(chrome::kChromeUINewTabURL), false);
231   return tabs;
232 }
233 
234 // static
GetPostCrashTabsForState(bool has_incompatible_applications)235 StartupTabs StartupTabProviderImpl::GetPostCrashTabsForState(
236     bool has_incompatible_applications) {
237   StartupTabs tabs;
238   if (has_incompatible_applications)
239     AddIncompatibleApplicationsUrl(&tabs);
240   return tabs;
241 }
242 
243 // static
GetExtensionCheckupTabsForState(bool serve_extensions_page)244 StartupTabs StartupTabProviderImpl::GetExtensionCheckupTabsForState(
245     bool serve_extensions_page) {
246   StartupTabs tabs;
247   if (serve_extensions_page) {
248     tabs.emplace_back(
249         net::AppendQueryParameter(GURL(chrome::kChromeUIExtensionsURL),
250                                   "checkup", "shown"),
251         false);
252   }
253   return tabs;
254 }
255 
256 // static
GetWelcomePageUrl(bool use_later_run_variant)257 GURL StartupTabProviderImpl::GetWelcomePageUrl(bool use_later_run_variant) {
258   GURL url(chrome::kChromeUIWelcomeURL);
259   return use_later_run_variant
260              ? net::AppendQueryParameter(url, "variant", "everywhere")
261              : url;
262 }
263 
264 // static
AddIncompatibleApplicationsUrl(StartupTabs * tabs)265 void StartupTabProviderImpl::AddIncompatibleApplicationsUrl(StartupTabs* tabs) {
266 #if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
267   UMA_HISTOGRAM_BOOLEAN("IncompatibleApplicationsPage.AddedPostCrash", true);
268   GURL url(chrome::kChromeUISettingsURL);
269   tabs->emplace_back(url.Resolve("incompatibleApplications"), false);
270 #endif  // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
271 }
272 
273 // static
GetTriggeredResetSettingsUrl()274 GURL StartupTabProviderImpl::GetTriggeredResetSettingsUrl() {
275   return GURL(
276       chrome::GetSettingsUrl(chrome::kTriggeredResetProfileSettingsSubPage));
277 }
278