1 // Copyright 2013 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/chromeos/first_run/first_run.h"
6
7 #include "ash/public/cpp/tablet_mode.h"
8 #include "base/command_line.h"
9 #include "base/macros.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/metrics/histogram_macros.h"
12 #include "chrome/browser/apps/app_service/app_service_proxy.h"
13 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/chromeos/arc/arc_util.h"
16 #include "chrome/browser/chromeos/first_run/first_run_controller.h"
17 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
18 #include "chrome/browser/chromeos/login/wizard_controller.h"
19 #include "chrome/browser/chromeos/profiles/profile_helper.h"
20 #include "chrome/browser/chromeos/web_applications/default_web_app_ids.h"
21 #include "chrome/browser/policy/profile_policy_connector.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/profiles/profile_observer.h"
24 #include "chrome/browser/signin/identity_manager_factory.h"
25 #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
26 #include "chrome/browser/web_applications/web_app_provider.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/extensions/extension_constants.h"
29 #include "chrome/common/pref_names.h"
30 #include "chromeos/constants/chromeos_features.h"
31 #include "chromeos/constants/chromeos_switches.h"
32 #include "chromeos/login/login_state/login_state.h"
33 #include "components/arc/arc_prefs.h"
34 #include "components/arc/arc_service_manager.h"
35 #include "components/pref_registry/pref_registry_syncable.h"
36 #include "components/prefs/pref_service.h"
37 #include "components/session_manager/core/session_manager.h"
38 #include "components/session_manager/core/session_manager_observer.h"
39 #include "components/signin/public/identity_manager/account_info.h"
40 #include "components/signin/public/identity_manager/identity_manager.h"
41 #include "components/sync_preferences/pref_service_syncable.h"
42 #include "components/user_manager/user_manager.h"
43 #include "content/public/common/content_switches.h"
44 #include "extensions/browser/extension_registry.h"
45 #include "extensions/common/constants.h"
46 #include "ui/display/types/display_constants.h"
47 #include "ui/events/event_constants.h"
48 #include "ui/gfx/geometry/rect.h"
49
50 namespace chromeos {
51 namespace first_run {
52
53 namespace {
54
LaunchApp(Profile * profile,std::string app_id)55 void LaunchApp(Profile* profile, std::string app_id) {
56 apps::AppServiceProxy* proxy =
57 apps::AppServiceProxyFactory::GetForProfile(profile);
58
59 proxy->Launch(app_id, ui::EventFlags::EF_NONE,
60 apps::mojom::LaunchSource::kFromChromeInternal,
61 display::kInvalidDisplayId);
62 profile->GetPrefs()->SetBoolean(prefs::kFirstRunTutorialShown, true);
63 }
64
65 // Returns true if this user type is probably a human who wants to configure
66 // their device through the help app. Other user types are robots, guests or
67 // public accounts.
IsRegularUserOrSupervisedChild(user_manager::UserManager * user_manager)68 bool IsRegularUserOrSupervisedChild(user_manager::UserManager* user_manager) {
69 switch (user_manager->GetActiveUser()->GetType()) {
70 case user_manager::USER_TYPE_REGULAR:
71 case user_manager::USER_TYPE_SUPERVISED:
72 case user_manager::USER_TYPE_CHILD:
73 return true;
74 default:
75 return false;
76 }
77 }
78
79 // Getting started module is shown to unmanaged regular, supervised and child
80 // accounts.
ShouldShowGetStarted(Profile * profile,user_manager::UserManager * user_manager)81 bool ShouldShowGetStarted(Profile* profile,
82 user_manager::UserManager* user_manager) {
83 // If we are disabling the first run experience, we don't show the getting
84 // started module.
85 if (!base::FeatureList::IsEnabled(chromeos::features::kHelpAppFirstRun))
86 return false;
87
88 // Child users return true for IsManaged. These are not EDU accounts though,
89 // should still see the getting started module.
90 if (profile->IsChild())
91 return true;
92 switch (user_manager->GetActiveUser()->GetType()) {
93 case user_manager::USER_TYPE_REGULAR:
94 case user_manager::USER_TYPE_SUPERVISED:
95 return !profile->GetProfilePolicyConnector()->IsManaged();
96 default:
97 return false;
98 }
99 }
100
101 // Object of this class waits for system web apps to load. Then it launches the
102 // help app. The object deletes itself if the app is launched or the profile is
103 // destroyed.
104 class AppLauncher : public ProfileObserver,
105 public base::SupportsWeakPtr<AppLauncher> {
106 public:
107 // App launcher owns itself and will be deleted when the app is launched or
108 // the profile is destroyed.
LaunchHelpAfterSWALoad(Profile * profile)109 static void LaunchHelpAfterSWALoad(Profile* profile) {
110 new AppLauncher(profile);
111 }
112 // ProfileObserver:
OnProfileWillBeDestroyed(Profile * profile)113 void OnProfileWillBeDestroyed(Profile* profile) override { delete this; }
114
115 private:
AppLauncher(Profile * profile)116 explicit AppLauncher(Profile* profile) : profile_(profile) {
117 profile->AddObserver(this);
118 web_app::WebAppProvider::Get(profile)
119 ->system_web_app_manager()
120 .on_apps_synchronized()
121 .Post(FROM_HERE,
122 base::BindOnce(&AppLauncher::LaunchHelpApp, AsWeakPtr()));
123 }
124
~AppLauncher()125 ~AppLauncher() override { this->profile_->RemoveObserver(this); }
126 AppLauncher(const AppLauncher&) = delete;
127 AppLauncher& operator=(const AppLauncher&) = delete;
128
LaunchHelpApp()129 void LaunchHelpApp() {
130 LaunchApp(this->profile_, default_web_apps::kHelpAppId);
131 delete this;
132 }
133 Profile* profile_;
134 base::WeakPtrFactory<AppLauncher> weak_factory_{this};
135 };
136
137 } // namespace
138
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)139 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
140 // This preference used to be syncable, change it to non-syncable so new
141 // users will always see the welcome app on a new device.
142 // See crbug.com/752361
143 registry->RegisterBooleanPref(prefs::kFirstRunTutorialShown, false);
144 registry->RegisterBooleanPref(prefs::kHelpAppShouldShowGetStarted, false);
145 registry->RegisterBooleanPref(prefs::kHelpAppShouldShowParentalControl,
146 false);
147 registry->RegisterBooleanPref(prefs::kHelpAppTabletModeDuringOobe, false);
148 }
149
ShouldLaunchHelpApp(Profile * profile)150 bool ShouldLaunchHelpApp(Profile* profile) {
151 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
152 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
153 // Even if we don't launch the help app now, define the preferences for what
154 // should be shown in the app when it is launched.
155 profile->GetPrefs()->SetBoolean(prefs::kHelpAppShouldShowGetStarted,
156 ShouldShowGetStarted(profile, user_manager));
157 profile->GetPrefs()->SetBoolean(prefs::kHelpAppTabletModeDuringOobe,
158 ash::TabletMode::Get()->InTabletMode());
159
160 if (WizardController::default_controller())
161 WizardController::default_controller()->PrepareFirstRunPrefs();
162
163 if (!IsRegularUserOrSupervisedChild(user_manager))
164 return false;
165
166 if (chromeos::switches::ShouldSkipOobePostLogin())
167 return false;
168
169 if (command_line->HasSwitch(switches::kForceFirstRunUI)) {
170 return true;
171 }
172
173 if (!base::FeatureList::IsEnabled(chromeos::features::kHelpAppFirstRun))
174 return false;
175
176 // ash::TabletMode does not exist in some tests.
177 if (ash::TabletMode::Get() && ash::TabletMode::Get()->InTabletMode())
178 return false;
179
180 if (command_line->HasSwitch(::switches::kTestType))
181 return false;
182
183 if (!user_manager->IsCurrentUserNew())
184 return false;
185
186 if (profile->GetPrefs()->GetBoolean(prefs::kFirstRunTutorialShown))
187 return false;
188
189 if (user_manager->IsCurrentUserNonCryptohomeDataEphemeral())
190 return false;
191
192 // Child accounts show up as managed, so check this first.
193 if (profile->IsChild())
194 return true;
195
196 if (profile->GetProfilePolicyConnector()->IsManaged())
197 return false;
198
199 return true;
200 }
201
LaunchHelpApp(Profile * profile)202 void LaunchHelpApp(Profile* profile) {
203 AppLauncher::LaunchHelpAfterSWALoad(profile);
204 }
205
LaunchTutorial()206 void LaunchTutorial() {
207 UMA_HISTOGRAM_BOOLEAN("CrosFirstRun.TutorialLaunched", true);
208 FirstRunController::Start();
209 }
210
211 } // namespace first_run
212 } // namespace chromeos
213