blob: b7fa6e6e5ec1b708dee36d76681019270760baf3 [file] [log] [blame]
// 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 "components/arc/arc_util.h"
#include <string>
#include "ash/public/cpp/app_types.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
#include "components/user_manager/user_manager.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
namespace arc {
namespace {
// This is for finch. See also crbug.com/633704 for details.
// TODO(hidehiko): More comments of the intention how this works, when
// we unify the commandline flags.
const base::Feature kEnableArcFeature{"EnableARC",
base::FEATURE_DISABLED_BY_DEFAULT};
// Possible values for --arc-availability flag.
constexpr char kAvailabilityNone[] = "none";
constexpr char kAvailabilityInstalled[] = "installed";
constexpr char kAvailabilityOfficiallySupported[] = "officially-supported";
constexpr char kAlwaysStart[] = "always-start";
constexpr char kAlwaysStartWithNoPlayStore[] =
"always-start-with-no-play-store";
void SetArcCpuRestrictionCallback(
login_manager::ContainerCpuRestrictionState state,
bool success) {
if (success)
return;
const char* message =
(state == login_manager::CONTAINER_CPU_RESTRICTION_BACKGROUND)
? "unprioritize"
: "prioritize";
LOG(ERROR) << "Failed to " << message << " ARC";
}
} // namespace
bool IsArcAvailable() {
const auto* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(chromeos::switches::kArcAvailability)) {
const std::string value =
command_line->GetSwitchValueASCII(chromeos::switches::kArcAvailability);
DCHECK(value == kAvailabilityNone || value == kAvailabilityInstalled ||
value == kAvailabilityOfficiallySupported)
<< "Unknown flag value: " << value;
return value == kAvailabilityOfficiallySupported ||
(value == kAvailabilityInstalled &&
base::FeatureList::IsEnabled(kEnableArcFeature));
}
// For transition, fallback to old flags.
// TODO(hidehiko): Remove this and clean up whole this function, when
// session_manager supports a new flag.
return command_line->HasSwitch(chromeos::switches::kEnableArc) ||
(command_line->HasSwitch(chromeos::switches::kArcAvailable) &&
base::FeatureList::IsEnabled(kEnableArcFeature));
}
bool IsPlayStoreAvailable() {
const auto* command_line = base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(chromeos::switches::kArcStartMode))
return true;
const std::string value =
command_line->GetSwitchValueASCII(chromeos::switches::kArcStartMode);
return value != kAlwaysStartWithNoPlayStore;
}
bool ShouldArcAlwaysStart() {
const auto* command_line = base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(chromeos::switches::kArcStartMode))
return false;
const std::string value =
command_line->GetSwitchValueASCII(chromeos::switches::kArcStartMode);
return value == kAlwaysStartWithNoPlayStore || value == kAlwaysStart;
}
void SetArcAlwaysStartForTesting(bool play_store_available) {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
chromeos::switches::kArcStartMode,
play_store_available ? kAlwaysStart : kAlwaysStartWithNoPlayStore);
}
bool IsArcKioskAvailable() {
const auto* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(chromeos::switches::kArcAvailability)) {
std::string value =
command_line->GetSwitchValueASCII(chromeos::switches::kArcAvailability);
if (value == kAvailabilityInstalled)
return true;
return IsArcAvailable();
}
// TODO(hidehiko): Remove this when session_manager supports the new flag.
if (command_line->HasSwitch(chromeos::switches::kArcAvailable))
return true;
// If not special kiosk device case, use general ARC check.
return IsArcAvailable();
}
void SetArcAvailableCommandLineForTesting(base::CommandLine* command_line) {
command_line->AppendSwitchASCII(chromeos::switches::kArcAvailability,
kAvailabilityOfficiallySupported);
}
bool IsArcKioskMode() {
return user_manager::UserManager::IsInitialized() &&
user_manager::UserManager::Get()->IsLoggedInAsArcKioskApp();
}
bool IsArcAllowedForUser(const user_manager::User* user) {
if (!user) {
VLOG(1) << "No ARC for nullptr user.";
return false;
}
// ARC is only supported for the following cases:
// - Users have Gaia accounts;
// - Active directory users;
// - ARC kiosk session;
// USER_TYPE_ARC_KIOSK_APP check is compatible with IsArcKioskMode()
// above because ARC kiosk user is always the primary/active user of a
// user session.
if (!user->HasGaiaAccount() && !user->IsActiveDirectoryUser() &&
user->GetType() != user_manager::USER_TYPE_ARC_KIOSK_APP) {
VLOG(1) << "Users without GAIA or AD accounts, or not ARC kiosk apps are "
"not supported in ARC.";
return false;
}
// Do not allow for ephemeral data user. cf) b/26402681
if (user_manager::UserManager::Get()->IsUserCryptohomeDataEphemeral(
user->GetAccountId())) {
VLOG(1) << "Users with ephemeral data are not supported in ARC.";
return false;
}
return true;
}
bool IsArcOptInVerificationDisabled() {
const auto* command_line = base::CommandLine::ForCurrentProcess();
return command_line->HasSwitch(
chromeos::switches::kDisableArcOptInVerification);
}
bool IsArcAppWindow(aura::Window* window) {
if (!window)
return false;
return window->GetProperty(aura::client::kAppType) ==
static_cast<int>(ash::AppType::ARC_APP);
}
void SetArcCpuRestriction(bool do_restrict) {
chromeos::SessionManagerClient* session_manager_client =
chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
if (!session_manager_client) {
LOG(WARNING) << "SessionManagerClient is not available";
return;
}
const login_manager::ContainerCpuRestrictionState state =
do_restrict ? login_manager::CONTAINER_CPU_RESTRICTION_BACKGROUND
: login_manager::CONTAINER_CPU_RESTRICTION_FOREGROUND;
session_manager_client->SetArcCpuRestriction(
state, base::Bind(SetArcCpuRestrictionCallback, state));
}
} // namespace arc