Commit 853f94dc authored by khmel@google.com's avatar khmel@google.com Committed by Commit Bot

arc: Prevent launching apps while supervision transition is in progress.

This also shows notification when this attempt happens.

TBR=xiyuan@chromium.org

TEST=Manually and unit_tests extended
BUG=841939

Change-Id: I6cdb770374d60c4e56539b1fa1d460b011e6bf21
Reviewed-on: https://chromium-review.googlesource.com/1134509
Commit-Queue: Yury Khmel <khmel@google.com>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#574725}
parent 1a23b6b0
...@@ -110,17 +110,27 @@ MessageCenterController::MessageCenterController() { ...@@ -110,17 +110,27 @@ MessageCenterController::MessageCenterController() {
std::make_unique<PopupNotificationBlocker>(MessageCenter::Get()); std::make_unique<PopupNotificationBlocker>(MessageCenter::Get());
} }
message_center::RegisterVectorIcons( message_center::RegisterVectorIcons({&kNotificationCaptivePortalIcon,
{&kNotificationCaptivePortalIcon, &kNotificationCellularAlertIcon, &kNotificationCellularAlertIcon,
&kNotificationDownloadIcon, &kNotificationEndOfSupportIcon, &kNotificationDownloadIcon,
&kNotificationGoogleIcon, &kNotificationImageIcon, &kNotificationEndOfSupportIcon,
&kNotificationInstalledIcon, &kNotificationMultiDeviceSetupIcon, &kNotificationFamilyLinkIcon,
&kNotificationMobileDataIcon, &kNotificationMobileDataOffIcon, &kNotificationGoogleIcon,
&kNotificationPlayPrismIcon, &kNotificationPrintingDoneIcon, &kNotificationImageIcon,
&kNotificationPrintingIcon, &kNotificationPrintingWarningIcon, &kNotificationInstalledIcon,
&kNotificationSettingsIcon, &kNotificationStorageFullIcon, &kNotificationMultiDeviceSetupIcon,
&kNotificationSupervisedUserIcon, &kNotificationVpnIcon, &kNotificationMobileDataIcon,
&kNotificationWarningIcon, &kNotificationWifiOffIcon}); &kNotificationMobileDataOffIcon,
&kNotificationPlayPrismIcon,
&kNotificationPrintingDoneIcon,
&kNotificationPrintingIcon,
&kNotificationPrintingWarningIcon,
&kNotificationSettingsIcon,
&kNotificationStorageFullIcon,
&kNotificationSupervisedUserIcon,
&kNotificationVpnIcon,
&kNotificationWarningIcon,
&kNotificationWifiOffIcon});
// Set the system notification source display name ("Chrome OS" or "Chromium // Set the system notification source display name ("Chrome OS" or "Chromium
// OS"). // OS").
......
...@@ -13,6 +13,7 @@ aggregate_vector_icons("ash_public_vector_icons") { ...@@ -13,6 +13,7 @@ aggregate_vector_icons("ash_public_vector_icons") {
"notification_cellular_alert.icon", "notification_cellular_alert.icon",
"notification_download.icon", "notification_download.icon",
"notification_end_of_support.icon", "notification_end_of_support.icon",
"notification_family_link.icon",
"notification_google.icon", "notification_google.icon",
"notification_image.icon", "notification_image.icon",
"notification_installed.icon", "notification_installed.icon",
......
// Copyright 2018 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.
CANVAS_DIMENSIONS, 96,
MOVE_TO, 49.54f, 9.6f,
LINE_TO, 22.24f, 38.4f,
LINE_TO, 45.85f, 74.37f,
LINE_TO, 43.94f, 77.25f,
CUBIC_TO, 43.73f, 77.58f, 43.5f, 77.83f, 43.26f, 78.12f,
CUBIC_TO, 42.1f, 79.31f, 40.6f, 79.99f, 38.96f, 79.99f,
CUBIC_TO, 37.32f, 79.99f, 35.82f, 79.34f, 34.66f, 78.12f,
CUBIC_TO, 33.5f, 76.89f, 32.88f, 75.31f, 32.88f, 73.58f,
CUBIC_TO, 32.88f, 70.16f, 31.62f, 66.96f, 29.33f, 64.54f,
CUBIC_TO, 27.05f, 62.13f, 24.01f, 60.8f, 20.77f, 60.8f,
LINE_TO, 19.2f, 60.8f,
LINE_TO, 19.2f, 67.21f,
LINE_TO, 20.77f, 67.21f,
CUBIC_TO, 22.41f, 67.21f, 23.91f, 67.86f, 25.07f, 69.08f,
CUBIC_TO, 26.23f, 70.31f, 26.84f, 71.89f, 26.84f, 73.62f,
CUBIC_TO, 26.84f, 77.04f, 28.11f, 80.24f, 30.39f, 82.66f,
CUBIC_TO, 32.68f, 85.07f, 35.72f, 86.4f, 38.96f, 86.4f,
CUBIC_TO, 42.2f, 86.4f, 45.24f, 85.07f, 47.52f, 82.66f,
CUBIC_TO, 48.03f, 82.12f, 48.48f, 81.54f, 48.89f, 80.96f,
LINE_TO, 55, 71.64f,
LINE_TO, 76.8f, 38.4f,
LINE_TO, 49.54f, 9.6f,
CLOSE
...@@ -4699,6 +4699,18 @@ ...@@ -4699,6 +4699,18 @@
<message name="IDS_HATS_DONE_BUTTON_LABEL" desc="Label used for the done button at the end of survey"> <message name="IDS_HATS_DONE_BUTTON_LABEL" desc="Label used for the done button at the end of survey">
Done Done
</message> </message>
<message name="IDS_ARC_CHILD_TRANSITION_TO_REGULAR_TITLE" desc="Title of the toast shown when the user tries to activate ARC app and transition to regular user is not completed.">
Application launch blocked
</message>
<message name="IDS_ARC_CHILD_TRANSITION_TO_REGULAR_MESSAGE" desc="Message of the toast shown when the user tries to activate ARC app and transition to regular user is not completed.">
You cannot use Android apps while transition to regular user is in progress.
</message>
<message name="IDS_ARC_CHILD_TRANSITION_FROM_REGULAR_TITLE" desc="Title of the toast shown when the user tries to activate ARC app and transition from regular user is not completed.">
Application launch blocked
</message>
<message name="IDS_ARC_CHILD_TRANSITION_FROM_REGULAR_MESSAGE" desc="Message of the toast shown when the user tries to activate ARC app and transition from regular user is not completed.">
You cannot use Android apps while transition to child user is in progress.
</message>
<message name="IDS_ARC_DATA_REMOVAL_CONFIRMATION_HEADING" desc="Heading text in the content area of the confirmation for data removal in case ARC comes to wrong state."> <message name="IDS_ARC_DATA_REMOVAL_CONFIRMATION_HEADING" desc="Heading text in the content area of the confirmation for data removal in case ARC comes to wrong state.">
To use apps from Google Play, your local app data needs to be reset. To use apps from Google Play, your local app data needs to be reset.
</message> </message>
......
...@@ -427,6 +427,8 @@ source_set("chromeos") { ...@@ -427,6 +427,8 @@ source_set("chromeos") {
"arc/notification/arc_boot_error_notification.h", "arc/notification/arc_boot_error_notification.h",
"arc/notification/arc_provision_notification_service.cc", "arc/notification/arc_provision_notification_service.cc",
"arc/notification/arc_provision_notification_service.h", "arc/notification/arc_provision_notification_service.h",
"arc/notification/arc_supervision_transition_notification.cc",
"arc/notification/arc_supervision_transition_notification.h",
"arc/oemcrypto/arc_oemcrypto_bridge.cc", "arc/oemcrypto/arc_oemcrypto_bridge.cc",
"arc/oemcrypto/arc_oemcrypto_bridge.h", "arc/oemcrypto/arc_oemcrypto_bridge.h",
"arc/optin/arc_optin_preference_handler.cc", "arc/optin/arc_optin_preference_handler.cc",
...@@ -1918,6 +1920,7 @@ source_set("unit_tests") { ...@@ -1918,6 +1920,7 @@ source_set("unit_tests") {
"arc/intent_helper/open_with_menu_unittest.cc", "arc/intent_helper/open_with_menu_unittest.cc",
"arc/kiosk/arc_kiosk_bridge_unittest.cc", "arc/kiosk/arc_kiosk_bridge_unittest.cc",
"arc/notification/arc_provision_notification_service_unittest.cc", "arc/notification/arc_provision_notification_service_unittest.cc",
"arc/notification/arc_supervision_transition_notification_unittest.cc",
"arc/optin/arc_terms_of_service_default_negotiator_unittest.cc", "arc/optin/arc_terms_of_service_default_negotiator_unittest.cc",
"arc/policy/arc_policy_bridge_unittest.cc", "arc/policy/arc_policy_bridge_unittest.cc",
"arc/process/arc_process_unittest.cc", "arc/process/arc_process_unittest.cc",
......
// Copyright 2018 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/notification/arc_supervision_transition_notification.h"
#include "ash/public/cpp/vector_icons/vector_icons.h"
#include "base/bind.h"
#include "base/macros.h"
#include "chrome/browser/chromeos/arc/arc_session_manager.h"
#include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/notifications/notification_display_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/theme_resources.h"
#include "components/account_id/account_id.h"
#include "components/arc/arc_prefs.h"
#include "components/prefs/pref_change_registrar.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/message_center/public/cpp/notification_delegate.h"
#include "url/gurl.h"
namespace arc {
namespace {
// Id of the notifier.
constexpr char kNotifierId[] = "arc_supervision_transition";
// Observes following ARC++ events that dismisses notification.
// * ARC++ opted out.
// * supervision transition completed.
// If one of these events happens notification is automatically dismissed.
class NotificationDelegate : public message_center::NotificationDelegate,
public ArcSessionManager::Observer {
public:
explicit NotificationDelegate(Profile* profile) : profile_(profile) {
ArcSessionManager::Get()->AddObserver(this);
pref_change_registrar_.Init(profile_->GetPrefs());
pref_change_registrar_.Add(
prefs::kArcSupervisionTransition,
base::BindRepeating(&NotificationDelegate::OnTransitionChanged,
base::Unretained(this)));
}
// ArcSessionManager::Observer:
void OnArcPlayStoreEnabledChanged(bool enabled) override {
// ARC++ Play Store can be only opted out in case notifcation is shown.
DCHECK(!enabled);
Dismiss();
}
private:
~NotificationDelegate() override {
ArcSessionManager::Get()->RemoveObserver(this);
}
// Dismisses currently active notification.
void Dismiss() {
NotificationDisplayService::GetForProfile(profile_)->Close(
NotificationHandler::Type::TRANSIENT,
kSupervisionTransitionNotificationId);
}
// Called in case transition state is changed.
void OnTransitionChanged() {
DCHECK_EQ(ArcSupervisionTransition::NO_TRANSITION,
GetSupervisionTransition(profile_));
Dismiss();
}
// Not owned.
Profile* const profile_;
// Registrar used to monitor ARC enabled state.
PrefChangeRegistrar pref_change_registrar_;
DISALLOW_COPY_AND_ASSIGN(NotificationDelegate);
};
} // namespace
const char kSupervisionTransitionNotificationId[] =
"arc_supervision_transition/notification";
void ShowSupervisionTransitionNotification(Profile* profile) {
const ArcSupervisionTransition transition = GetSupervisionTransition(profile);
int message_id = 0;
int title_id = 0;
switch (transition) {
case ArcSupervisionTransition::CHILD_TO_REGULAR:
title_id = IDS_ARC_CHILD_TRANSITION_TO_REGULAR_TITLE;
message_id = IDS_ARC_CHILD_TRANSITION_TO_REGULAR_MESSAGE;
break;
case ArcSupervisionTransition::REGULAR_TO_CHILD:
title_id = IDS_ARC_CHILD_TRANSITION_FROM_REGULAR_TITLE;
message_id = IDS_ARC_CHILD_TRANSITION_FROM_REGULAR_MESSAGE;
break;
default:
NOTREACHED() << "Notification requested with no transition in progress";
return;
}
message_center::NotifierId notifier_id(
message_center::NotifierId::SYSTEM_COMPONENT, kNotifierId);
notifier_id.profile_id =
multi_user_util::GetAccountIdFromProfile(profile).GetUserEmail();
std::unique_ptr<message_center::Notification> notification =
message_center::Notification::CreateSystemNotification(
message_center::NOTIFICATION_TYPE_SIMPLE,
kSupervisionTransitionNotificationId,
l10n_util::GetStringUTF16(title_id),
l10n_util::GetStringUTF16(message_id), gfx::Image(),
l10n_util::GetStringUTF16(IDS_ARC_NOTIFICATION_DISPLAY_SOURCE),
GURL(), notifier_id, message_center::RichNotificationData(),
new NotificationDelegate(profile), ash::kNotificationFamilyLinkIcon,
message_center::SystemNotificationWarningLevel::NORMAL);
NotificationDisplayService::GetForProfile(profile)->Display(
NotificationHandler::Type::TRANSIENT, *notification);
}
} // namespace arc
// Copyright 2018 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.
#ifndef CHROME_BROWSER_CHROMEOS_ARC_NOTIFICATION_ARC_SUPERVISION_TRANSITION_NOTIFICATION_H_
#define CHROME_BROWSER_CHROMEOS_ARC_NOTIFICATION_ARC_SUPERVISION_TRANSITION_NOTIFICATION_H_
class Profile;
namespace arc {
// To share with unit tests.
extern const char kSupervisionTransitionNotificationId[];
// Shows supervision transition notification that notifies that ARC++ is not
// reachable while supervision transition is in progress. This is informative
// notification only. This notification is automatically dismissed when ARC++ is
// opted out or supervision transition is completed.
void ShowSupervisionTransitionNotification(Profile* profile);
} // namespace arc
#endif // CHROME_BROWSER_CHROMEOS_ARC_NOTIFICATION_ARC_SUPERVISION_TRANSITION_NOTIFICATION_H_
// Copyright 2018 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 <memory>
#include "base/macros.h"
#include "base/run_loop.h"
#include "chrome/browser/chromeos/arc/notification/arc_supervision_transition_notification.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
#include "chrome/browser/ui/app_list/arc/arc_app_test.h"
#include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
#include "chrome/test/base/testing_profile.h"
#include "components/arc/arc_prefs.h"
#include "components/arc/arc_supervision_transition.h"
#include "components/arc/test/fake_app_instance.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace arc {
class ArcSupervisionTransitionNotificationTest
: public testing::Test,
public testing::WithParamInterface<ArcSupervisionTransition> {
public:
ArcSupervisionTransitionNotificationTest() = default;
~ArcSupervisionTransitionNotificationTest() override = default;
void SetUp() override {
profile_ = std::make_unique<TestingProfile>();
display_service_ =
std::make_unique<NotificationDisplayServiceTester>(profile());
arc_app_test_.SetUp(profile());
}
void TearDown() override {
arc_app_test_.TearDown();
display_service_.reset();
profile_.reset();
}
Profile* profile() { return profile_.get(); }
NotificationDisplayServiceTester* display_service() {
return display_service_.get();
}
ArcAppTest* arc_app_test() { return &arc_app_test_; }
private:
std::unique_ptr<TestingProfile> profile_;
std::unique_ptr<NotificationDisplayServiceTester> display_service_;
ArcAppTest arc_app_test_;
content::TestBrowserThreadBundle thread_bundle_;
DISALLOW_COPY_AND_ASSIGN(ArcSupervisionTransitionNotificationTest);
};
INSTANTIATE_TEST_CASE_P(
,
ArcSupervisionTransitionNotificationTest,
::testing::Values(ArcSupervisionTransition::NO_TRANSITION,
ArcSupervisionTransition::CHILD_TO_REGULAR,
ArcSupervisionTransition::REGULAR_TO_CHILD));
TEST_P(ArcSupervisionTransitionNotificationTest, BaseFlow) {
ASSERT_TRUE(arc_app_test()->fake_apps().size());
arc_app_test()->app_instance()->RefreshAppList();
arc_app_test()->app_instance()->SendRefreshAppList(
arc_app_test()->fake_apps());
const std::string app_id =
ArcAppTest::GetAppId(arc_app_test()->fake_apps()[0]);
profile()->GetPrefs()->SetInteger(prefs::kArcSupervisionTransition,
static_cast<int>(GetParam()));
// Attempt to launch ARC++ app triggers notification.
LaunchApp(profile(), app_id, 0 /* event_flags */);
std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
arc_app_test()->arc_app_list_prefs()->GetApp(app_id);
ASSERT_TRUE(app_info);
// In case no supervision transition in progress notification is not
// triggered.
if (GetParam() == ArcSupervisionTransition::NO_TRANSITION) {
EXPECT_FALSE(display_service()->GetNotification(
kSupervisionTransitionNotificationId));
// Last launch is set, indicating that launch attempt was not blocked.
EXPECT_FALSE(app_info->last_launch_time.is_null());
return;
}
EXPECT_TRUE(
display_service()->GetNotification(kSupervisionTransitionNotificationId));
// Last launch is not set, indicating that launch attempt was blocked.
EXPECT_TRUE(app_info->last_launch_time.is_null());
// Finishing transition automatically dismisses notification.
profile()->GetPrefs()->SetInteger(
prefs::kArcSupervisionTransition,
static_cast<int>(ArcSupervisionTransition::NO_TRANSITION));
EXPECT_FALSE(
display_service()->GetNotification(kSupervisionTransitionNotificationId));
// Re-activate notification and check opt out. On opt-out notification is also
// automatially dismissed.
profile()->GetPrefs()->SetInteger(prefs::kArcSupervisionTransition,
static_cast<int>(GetParam()));
ShowSupervisionTransitionNotification(profile());
EXPECT_TRUE(
display_service()->GetNotification(kSupervisionTransitionNotificationId));
profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, false);
EXPECT_FALSE(
display_service()->GetNotification(kSupervisionTransitionNotificationId));
}
} // namespace arc
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "chrome/browser/chromeos/arc/arc_session_manager.h" #include "chrome/browser/chromeos/arc/arc_session_manager.h"
#include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h" #include "chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h"
#include "chrome/browser/chromeos/arc/notification/arc_supervision_transition_notification.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
#include "chrome/browser/ui/ash/launcher/arc_app_shelf_id.h" #include "chrome/browser/ui/ash/launcher/arc_app_shelf_id.h"
...@@ -232,10 +233,23 @@ bool LaunchAppWithIntent(content::BrowserContext* context, ...@@ -232,10 +233,23 @@ bool LaunchAppWithIntent(content::BrowserContext* context,
// as a placeholder to show the guide notification for proper configuration. // as a placeholder to show the guide notification for proper configuration.
// Handle such a case here and shows the desired notification. // Handle such a case here and shows the desired notification.
if (IsArcBlockedDueToIncompatibleFileSystem(profile)) { if (IsArcBlockedDueToIncompatibleFileSystem(profile)) {
VLOG(1) << "Attempt to launch " << app_id
<< " while ARC++ is blocked due to incompatible file system.";
arc::ShowArcMigrationGuideNotification(profile); arc::ShowArcMigrationGuideNotification(profile);
return false; return false;
} }
// In case supervision transition is in progress ARC++ is not available.
const ArcSupervisionTransition supervision_transition =
GetSupervisionTransition(profile);
if (supervision_transition != ArcSupervisionTransition::NO_TRANSITION) {
VLOG(1) << "Attempt to launch " << app_id
<< " while supervision transition " << supervision_transition
<< " is in progress.";
arc::ShowSupervisionTransitionNotification(profile);
return false;
}
ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context); ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context);
std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(app_id); std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(app_id);
if (app_info && !app_info->ready) { if (app_info && !app_info->ready) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment