| // Copyright 2017 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 "chrome/browser/chromeos/arc/arc_play_store_enabled_preference_handler.h" |
| |
| #include <string> |
| |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/logging.h" |
| #include "chrome/browser/chromeos/arc/arc_optin_uma.h" |
| #include "chrome/browser/chromeos/arc/arc_session_manager.h" |
| #include "chrome/browser/chromeos/arc/arc_util.h" |
| #include "chrome/browser/consent_auditor/consent_auditor_factory.h" |
| #include "chrome/browser/prefs/pref_service_syncable_util.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/signin/identity_manager_factory.h" |
| #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" |
| #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "chromeos/constants/chromeos_switches.h" |
| #include "components/arc/arc_prefs.h" |
| #include "components/arc/arc_util.h" |
| #include "components/consent_auditor/consent_auditor.h" |
| #include "components/sync_preferences/pref_service_syncable.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "services/identity/public/cpp/identity_manager.h" |
| |
| using sync_pb::UserConsentTypes; |
| |
| namespace arc { |
| |
| ArcPlayStoreEnabledPreferenceHandler::ArcPlayStoreEnabledPreferenceHandler( |
| Profile* profile, |
| ArcSessionManager* arc_session_manager) |
| : profile_(profile), |
| arc_session_manager_(arc_session_manager), |
| weak_ptr_factory_(this) { |
| DCHECK(profile_); |
| DCHECK(arc_session_manager_); |
| } |
| |
| ArcPlayStoreEnabledPreferenceHandler::~ArcPlayStoreEnabledPreferenceHandler() { |
| pref_change_registrar_.RemoveAll(); |
| } |
| |
| void ArcPlayStoreEnabledPreferenceHandler::Start() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| |
| // Start observing Google Play Store enabled preference. |
| pref_change_registrar_.Init(profile_->GetPrefs()); |
| pref_change_registrar_.Add( |
| prefs::kArcEnabled, |
| base::Bind(&ArcPlayStoreEnabledPreferenceHandler::OnPreferenceChanged, |
| weak_ptr_factory_.GetWeakPtr())); |
| |
| const bool is_play_store_enabled = IsArcPlayStoreEnabledForProfile(profile_); |
| VLOG(1) << "Start observing Google Play Store enabled preference. " |
| << "Initial value: " << is_play_store_enabled; |
| |
| // Force data clean if needed. |
| if (IsArcDataCleanupOnStartRequested()) { |
| VLOG(1) << "Request to cleanup data on start."; |
| arc_session_manager_->RequestArcDataRemoval(); |
| } |
| |
| // If the OOBE is shown, don't kill the mini-container. We'll do it if and |
| // when the user declines the TOS. We need to check |is_play_store_enabled| to |
| // handle the case where |kArcEnabled| is managed but some of the preferences |
| // still need to be set by the user. |
| // TODO(cmtm): This feature isn't covered by unittests. Add a unittest for it. |
| if (!IsArcOobeOptInActive() || is_play_store_enabled) |
| UpdateArcSessionManager(); |
| if (is_play_store_enabled) |
| return; |
| |
| // Google Play Store is initially disabled, here. |
| |
| if (IsArcPlayStoreEnabledPreferenceManagedForProfile(profile_)) { |
| // All users that can disable Google Play Store by themselves will have |
| // the |kARcDataRemoveRequested| pref set, so we don't need to eagerly |
| // remove the data for that case. |
| // For managed users, the preference can change when the Profile object is |
| // not alive, so we still need to check it here in case it was disabled to |
| // ensure that the data is deleted in case it was disabled between |
| // launches. |
| VLOG(1) << "Google Play Store is initially disabled for managed " |
| << "profile. Removing data."; |
| arc_session_manager_->RequestArcDataRemoval(); |
| } |
| } |
| |
| void ArcPlayStoreEnabledPreferenceHandler::OnPreferenceChanged() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| const bool is_play_store_enabled = IsArcPlayStoreEnabledForProfile(profile_); |
| if (!IsArcPlayStoreEnabledPreferenceManagedForProfile(profile_)) { |
| // Update UMA only for non-Managed cases. Note, that multiple OptIn/OptOut |
| // may happen during a session. In this case each event would be reported. |
| // For example, if a user opts-in ARC on OOBE, and later opts-out via |
| // settings page, OOBE_OPTED_IN and SESSION_OPTED_OUT will be recorded. |
| if (IsArcOobeOptInActive()) { |
| OptInActionType type; |
| if (IsArcOobeOptInConfigurationBased()) { |
| type = is_play_store_enabled |
| ? OptInActionType::OOBE_OPTED_IN_CONFIGURATION |
| : OptInActionType::OOBE_OPTED_OUT; |
| } else { |
| type = is_play_store_enabled ? OptInActionType::OOBE_OPTED_IN |
| : OptInActionType::OOBE_OPTED_OUT; |
| } |
| UpdateOptInActionUMA(type); |
| } else { |
| UpdateOptInActionUMA(is_play_store_enabled |
| ? OptInActionType::SESSION_OPTED_IN |
| : OptInActionType::SESSION_OPTED_OUT); |
| } |
| |
| if (!is_play_store_enabled) { |
| // Remove the pinned Play Store icon launcher in Shelf. |
| // This is only for non-Managed cases. In managed cases, it is expected |
| // to be "disabled" rather than "removed", so keep it here. |
| auto* chrome_launcher_controller = ChromeLauncherController::instance(); |
| if (chrome_launcher_controller) |
| chrome_launcher_controller->UnpinAppWithID(kPlayStoreAppId); |
| |
| // Tell Consent Auditor that the Play Store consent was revoked. |
| identity::IdentityManager* identity_manager = |
| IdentityManagerFactory::GetForProfile(profile_); |
| // TODO(crbug.com/850297): Fix unrelated tests that are not properly |
| // setting up the state of identity_manager and enable the DCHECK instead |
| // of the conditional below. |
| // DCHECK(identity_manager->HasPrimaryAccount()); |
| if (identity_manager->HasPrimaryAccount()) { |
| const std::string account_id = identity_manager->GetPrimaryAccountId(); |
| |
| UserConsentTypes::ArcPlayTermsOfServiceConsent play_consent; |
| play_consent.set_status(UserConsentTypes::NOT_GIVEN); |
| play_consent.set_confirmation_grd_id( |
| IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_REMOVE); |
| play_consent.add_description_grd_ids( |
| IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE); |
| play_consent.set_consent_flow( |
| UserConsentTypes::ArcPlayTermsOfServiceConsent::SETTING_CHANGE); |
| ConsentAuditorFactory::GetForProfile(profile_)->RecordArcPlayConsent( |
| account_id, play_consent); |
| } |
| } |
| } |
| |
| UpdateArcSessionManager(); |
| |
| // Due to life time management, OnArcPlayStoreEnabledChanged() is notified |
| // via ArcSessionManager, so that external services can subscribe at almost |
| // any time. |
| arc_session_manager_->NotifyArcPlayStoreEnabledChanged(is_play_store_enabled); |
| } |
| |
| void ArcPlayStoreEnabledPreferenceHandler::UpdateArcSessionManager() { |
| auto* support_host = arc_session_manager_->support_host(); |
| if (support_host && IsArcPlayStoreEnabledForProfile(profile_)) { |
| support_host->SetArcManaged( |
| IsArcPlayStoreEnabledPreferenceManagedForProfile(profile_)); |
| } |
| |
| if (ShouldArcAlwaysStart() || IsArcPlayStoreEnabledForProfile(profile_)) |
| arc_session_manager_->RequestEnable(); |
| else |
| arc_session_manager_->RequestDisable(); |
| } |
| |
| } // namespace arc |