| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/command_line.h" |
| #include "base/macros.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/chrome_notification_types.h" |
| #include "chrome/browser/chromeos/arc/arc_util.h" |
| #include "chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h" |
| #include "chrome/browser/chromeos/first_run/first_run_controller.h" |
| #include "chrome/browser/chromeos/login/ui/login_display_host.h" |
| #include "chrome/browser/chromeos/login/wizard_controller.h" |
| #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/prefs/pref_service_syncable_util.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/signin/signin_manager_factory.h" |
| #include "chrome/browser/ui/extensions/app_launch_params.h" |
| #include "chrome/browser/ui/extensions/application_launch.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/extensions/extension_constants.h" |
| #include "chrome/common/pref_names.h" |
| #include "chromeos/chromeos_switches.h" |
| #include "components/arc/arc_service_manager.h" |
| #include "components/pref_registry/pref_registry_syncable.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/signin/core/browser/account_info.h" |
| #include "components/signin/core/browser/account_tracker_service.h" |
| #include "components/signin/core/browser/signin_manager.h" |
| #include "components/sync_preferences/pref_service_syncable.h" |
| #include "components/user_manager/user_manager.h" |
| #include "content/public/browser/notification_observer.h" |
| #include "content/public/browser/notification_registrar.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/common/content_switches.h" |
| #include "extensions/browser/extension_system.h" |
| #include "extensions/common/constants.h" |
| #include "ui/gfx/geometry/rect.h" |
| |
| namespace chromeos { |
| namespace first_run { |
| |
| namespace { |
| |
| void LaunchDialogForProfile(Profile* profile) { |
| ExtensionService* service = |
| extensions::ExtensionSystem::Get(profile)->extension_service(); |
| if (!service) |
| return; |
| |
| const extensions::Extension* extension = |
| service->GetExtensionById(extension_misc::kFirstRunDialogId, false); |
| if (!extension) |
| return; |
| |
| OpenApplication(AppLaunchParams( |
| profile, extension, extensions::LAUNCH_CONTAINER_WINDOW, |
| WindowOpenDisposition::NEW_WINDOW, extensions::SOURCE_CHROME_INTERNAL)); |
| profile->GetPrefs()->SetBoolean(prefs::kFirstRunTutorialShown, true); |
| } |
| |
| void TryLaunchFirstRunDialog(Profile* profile) { |
| base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| |
| if (command_line->HasSwitch(switches::kOobeSkipPostLogin)) |
| return; |
| |
| if (command_line->HasSwitch(switches::kForceFirstRunUI)) { |
| LaunchDialogForProfile(profile); |
| return; |
| } |
| |
| if (command_line->HasSwitch(::switches::kTestType)) |
| return; |
| |
| if (!user_manager::UserManager::Get()->IsCurrentUserNew()) |
| return; |
| |
| if (profile->GetPrefs()->GetBoolean(prefs::kFirstRunTutorialShown)) |
| return; |
| |
| bool is_pref_synced = |
| PrefServiceSyncableFromProfile(profile)->IsPrioritySyncing(); |
| bool is_user_ephemeral = user_manager::UserManager::Get() |
| ->IsCurrentUserNonCryptohomeDataEphemeral(); |
| if (!is_pref_synced && is_user_ephemeral) |
| return; |
| |
| LaunchDialogForProfile(profile); |
| } |
| |
| // Object of this class waits for session start. Then it launches or not |
| // launches first-run dialog depending on user prefs and flags. Than object |
| // deletes itself. |
| class DialogLauncher : public content::NotificationObserver { |
| public: |
| explicit DialogLauncher(Profile* profile) |
| : profile_(profile) { |
| DCHECK(profile); |
| registrar_.Add(this, |
| chrome::NOTIFICATION_SESSION_STARTED, |
| content::NotificationService::AllSources()); |
| } |
| |
| ~DialogLauncher() override {} |
| |
| void Observe(int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) override { |
| DCHECK(type == chrome::NOTIFICATION_SESSION_STARTED); |
| DCHECK(content::Details<const user_manager::User>(details).ptr() == |
| ProfileHelper::Get()->GetUserByProfile(profile_)); |
| |
| // Whether the account is supported for voice interaction. |
| bool account_supported = false; |
| SigninManagerBase* signin_manager = |
| SigninManagerFactory::GetForProfile(profile_); |
| if (signin_manager) { |
| std::string hosted_domain = |
| signin_manager->GetAuthenticatedAccountInfo().hosted_domain; |
| if (hosted_domain == AccountTrackerService::kNoHostedDomainFound || |
| hosted_domain == "google.com") |
| account_supported = true; |
| } |
| |
| // If voice interaction value prop needs to be shown, the tutorial will be |
| // shown after the voice interaction OOBE flow. |
| if (account_supported && arc::IsArcPlayStoreEnabledForProfile(profile_) && |
| !profile_->GetPrefs()->GetBoolean( |
| prefs::kArcVoiceInteractionValuePropAccepted)) { |
| auto* service = |
| arc::ArcVoiceInteractionFrameworkService::GetForBrowserContext( |
| profile_); |
| if (service) |
| service->StartSessionFromUserInteraction(gfx::Rect()); |
| } else { |
| TryLaunchFirstRunDialog(profile_); |
| } |
| |
| delete this; |
| } |
| |
| private: |
| Profile* profile_; |
| content::NotificationRegistrar registrar_; |
| |
| DISALLOW_COPY_AND_ASSIGN(DialogLauncher); |
| }; |
| |
| } // namespace |
| |
| void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { |
| registry->RegisterBooleanPref( |
| prefs::kFirstRunTutorialShown, |
| false, |
| user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); |
| } |
| |
| void MaybeLaunchDialogAfterSessionStart() { |
| new DialogLauncher(ProfileHelper::Get()->GetProfileByUserUnsafe( |
| user_manager::UserManager::Get()->GetActiveUser())); |
| } |
| |
| void MaybeLaunchDialogImmediately() { |
| TryLaunchFirstRunDialog(ProfileHelper::Get()->GetProfileByUser( |
| user_manager::UserManager::Get()->GetActiveUser())); |
| } |
| |
| void LaunchTutorial() { |
| UMA_HISTOGRAM_BOOLEAN("CrosFirstRun.TutorialLaunched", true); |
| FirstRunController::Start(); |
| } |
| |
| } // namespace first_run |
| } // namespace chromeos |