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