blob: 35cb0f6f2d7ccc216ed373c0c13de2f9a19b8aab [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 IsWebstoreSearchEnabled() {
const auto* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(chromeos::switches::kArcAvailability)) {
const std::string value =
command_line->GetSwitchValueASCII(chromeos::switches::kArcAvailability);
return value == kAvailabilityNone;
}
return true;
}
bool IsPlayStoreAvailable() {
if (IsRobotAccountMode())
return false;
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 IsRobotAccountMode() {
return user_manager::UserManager::IsInitialized() &&
(user_manager::UserManager::Get()->IsLoggedInAsArcKioskApp() ||
user_manager::UserManager::Get()->IsLoggedInAsPublicAccount());
}
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;
// - Public Session users;
// 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. The same for USER_TYPE_PUBLIC_ACCOUNT.
if (!user->HasGaiaAccount() && !user->IsActiveDirectoryUser() &&
user->GetType() != user_manager::USER_TYPE_ARC_KIOSK_APP &&
user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
VLOG(1) << "Users without GAIA or AD accounts, or not ARC kiosk apps are "
"not supported in ARC.";
return false;
}
if (user->GetType() == user_manager::USER_TYPE_CHILD) {
VLOG(1) << "ARC usage by Child users is prohibited";
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::BindOnce(SetArcCpuRestrictionCallback, state));
}
} // namespace arc