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