Commit d059788b authored by Sergey Poromov's avatar Sergey Poromov Committed by Commit Bot

arc: Wait for kiosk app policy compliance

ARC Kiosk service should wait till DPC reports that the kiosk app
is not policy non-compliant anymore, otherwise not all kiosk app
policies are applied, e.g. permission policies.

BUG=b/109639337
TEST=Manual

Change-Id: I08471986c462dcf8b01eb8d5512faa1b36640a66
Reviewed-on: https://chromium-review.googlesource.com/1124452
Commit-Queue: Sergey Poromov <poromov@chromium.org>
Reviewed-by: default avatarPavol Marko <pmarko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#575248}
parent 6b5064ba
......@@ -13,14 +13,18 @@
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
#include "components/arc/arc_prefs.h"
#include "components/prefs/pref_service.h"
#include "ui/base/layout.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
namespace chromeos {
namespace {
constexpr int kNonComplianceReasonAppNotInstalled = 5;
} // namespace
// Timeout maintenance session after 30 minutes.
constexpr base::TimeDelta kArcKioskMaintenanceSessionTimeout =
base::TimeDelta::FromMinutes(30);
......@@ -43,6 +47,7 @@ void ArcKioskAppService::Shutdown() {
ArcAppListPrefs::Get(profile_)->RemoveObserver(this);
arc::ArcSessionManager::Get()->RemoveObserver(this);
app_manager_->RemoveObserver(this);
arc::ArcPolicyBridge::GetForBrowserContext(profile_)->RemoveObserver(this);
}
void ArcKioskAppService::OnAppRegistered(
......@@ -135,19 +140,39 @@ void ArcKioskAppService::OnArcSessionStopped(arc::ArcStopReason reason) {
ResetAppLauncher();
}
void ArcKioskAppService::OnComplianceReportReceived(
const base::Value* compliance_report) {
VLOG(2) << "Compliance report received";
compliance_report_received_ = true;
pending_policy_app_installs_.clear();
const base::Value* const details = compliance_report->FindKeyOfType(
"nonComplianceDetails", base::Value::Type::LIST);
if (!details) {
PreconditionsChanged();
return;
}
for (const auto& detail : details->GetList()) {
const base::Value* const reason =
detail.FindKeyOfType("nonComplianceReason", base::Value::Type::INTEGER);
if (!reason || reason->GetInt() != kNonComplianceReasonAppNotInstalled)
continue;
const base::Value* const app_name =
detail.FindKeyOfType("packageName", base::Value::Type::STRING);
if (!app_name || app_name->GetString().empty())
continue;
pending_policy_app_installs_.insert(app_name->GetString());
}
PreconditionsChanged();
}
ArcKioskAppService::ArcKioskAppService(Profile* profile) : profile_(profile) {
ArcAppListPrefs::Get(profile_)->AddObserver(this);
arc::ArcSessionManager::Get()->AddObserver(this);
app_manager_ = ArcKioskAppManager::Get();
DCHECK(app_manager_);
app_manager_->AddObserver(this);
pref_change_registrar_.reset(new PrefChangeRegistrar());
pref_change_registrar_->Init(profile_->GetPrefs());
// Kiosk app can be started only when policy compliance is reported.
pref_change_registrar_->Add(
arc::prefs::kArcPolicyComplianceReported,
base::Bind(&ArcKioskAppService::PreconditionsChanged,
base::Unretained(this)));
arc::ArcPolicyBridge::GetForBrowserContext(profile_)->AddObserver(this);
PreconditionsChanged();
}
......@@ -181,15 +206,16 @@ void ArcKioskAppService::PreconditionsChanged() {
VLOG(2) << "Maintenance session is "
<< (maintenance_session_running_ ? "running" : "not running");
VLOG(2) << "Policy compliance is "
<< (profile_->GetPrefs()->GetBoolean(
arc::prefs::kArcPolicyComplianceReported)
? "reported"
: "not yet reported");
<< (compliance_report_received_ ? "reported" : "not yet reported");
VLOG(2) << "Kiosk app with id: " << app_id_ << " is "
<< (app_launcher_ ? "already launched" : "not yet launched");
VLOG(2) << "Kiosk app is policy "
<< (pending_policy_app_installs_.count(app_info_->package_name)
? "non-compliant"
: "compliant");
if (app_info_ && app_info_->ready && !maintenance_session_running_ &&
profile_->GetPrefs()->GetBoolean(
arc::prefs::kArcPolicyComplianceReported)) {
compliance_report_received_ &&
pending_policy_app_installs_.count(app_info_->package_name) == 0) {
if (!app_launcher_) {
VLOG(2) << "Starting kiosk app";
app_launcher_ = std::make_unique<ArcKioskAppLauncher>(
......
......@@ -5,16 +5,17 @@
#ifndef CHROME_BROWSER_CHROMEOS_APP_MODE_ARC_ARC_KIOSK_APP_SERVICE_H_
#define CHROME_BROWSER_CHROMEOS_APP_MODE_ARC_ARC_KIOSK_APP_SERVICE_H_
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/timer/timer.h"
#include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_launcher.h"
#include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_manager.h"
#include "chrome/browser/chromeos/arc/arc_session_manager.h"
#include "chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.h"
#include "chrome/browser/chromeos/arc/policy/arc_policy_bridge.h"
#include "chrome/browser/ui/app_list/arc/arc_app_icon.h"
#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
class Profile;
......@@ -37,7 +38,8 @@ class ArcKioskAppService
public arc::ArcKioskBridge::Delegate,
public ArcKioskAppLauncher::Delegate,
public ArcAppIcon::Observer,
public arc::ArcSessionManager::Observer {
public arc::ArcSessionManager::Observer,
public arc::ArcPolicyBridge::Observer {
public:
class Delegate {
public:
......@@ -88,6 +90,10 @@ class ArcKioskAppService
void OnArcSessionRestarting() override;
void OnArcSessionStopped(arc::ArcStopReason reason) override;
// ArcPolicyBridge::Observer overrides
void OnComplianceReportReceived(
const base::Value* compliance_report) override;
private:
explicit ArcKioskAppService(Profile* profile);
~ArcKioskAppService() override;
......@@ -108,7 +114,14 @@ class ArcKioskAppService
std::unique_ptr<ArcAppListPrefs::AppInfo> app_info_;
std::unique_ptr<ArcAppIcon> app_icon_;
int32_t task_id_ = -1;
std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
// This contains the list of apps that must be installed for the device to be
// policy-compliant according to the policy report. Even if an app has already
// finished installing, it could still remain in this list for some time.
// ArcKioskAppService may only start apps which are not in this list anymore,
// because it's only assured that kiosk policies have been applied (e.g.
// permission policies) when the app is not in this list anymore.
base::flat_set<std::string> pending_policy_app_installs_;
bool compliance_report_received_ = false;
// Keeps track whether the app is already launched
std::unique_ptr<ArcKioskAppLauncher> app_launcher_;
// Not owning the delegate, delegate removes itself in destructor
......
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