blob: 1a21fed2ce8422053175dd2057b0ccd171596677 [file] [log] [blame]
// Copyright 2016 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 <string>
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/arc/arc_service_launcher.h"
#include "chrome/browser/chromeos/arc/arc_session_manager.h"
#include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/chromeos/arc/test/arc_data_removed_waiter.h"
#include "chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/extensions/api/tabs/tabs_api.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_profile.h"
#include "components/account_id/account_id.h"
#include "components/arc/arc_prefs.h"
#include "components/arc/arc_service_manager.h"
#include "components/arc/arc_util.h"
#include "components/arc/session/arc_session_runner.h"
#include "components/arc/test/fake_arc_session.h"
#include "components/policy/core/common/cloud/device_management_service.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
#include "components/policy/core/common/policy_switches.h"
#include "components/prefs/pref_member.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/scoped_user_manager.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/url_request/url_request_test_job.h"
#include "services/identity/public/cpp/identity_test_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace {
// Set managed auth token for Android managed accounts.
constexpr char kManagedAuthToken[] = "managed-auth-token";
// Set unmanaged auth token for other Android unmanaged accounts.
constexpr char kUnmanagedAuthToken[] = "unmanaged-auth-token";
constexpr char kWellKnownConsumerName[] = "test@gmail.com";
constexpr char kFakeUserName[] = "test@example.com";
constexpr char kFakeGaiaId[] = "1234567890";
} // namespace
namespace arc {
// Waits for the "arc.enabled" preference value from true to false.
class ArcPlayStoreDisabledWaiter : public ArcSessionManager::Observer {
public:
ArcPlayStoreDisabledWaiter() { ArcSessionManager::Get()->AddObserver(this); }
~ArcPlayStoreDisabledWaiter() override {
ArcSessionManager::Get()->RemoveObserver(this);
}
void Wait() {
base::RunLoop run_loop;
base::AutoReset<base::RunLoop*> reset(&run_loop_, &run_loop);
run_loop.Run();
}
private:
// ArcSessionManager::Observer override:
void OnArcPlayStoreEnabledChanged(bool enabled) override {
if (!enabled) {
DCHECK(run_loop_);
run_loop_->Quit();
}
}
base::RunLoop* run_loop_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ArcPlayStoreDisabledWaiter);
};
class ArcSessionManagerTest : public chromeos::MixinBasedInProcessBrowserTest {
protected:
ArcSessionManagerTest() {}
// MixinBasedInProcessBrowserTest:
~ArcSessionManagerTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
chromeos::MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line);
arc::SetArcAvailableCommandLineForTesting(command_line);
}
void SetUpOnMainThread() override {
chromeos::MixinBasedInProcessBrowserTest::SetUpOnMainThread();
user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
std::make_unique<chromeos::FakeChromeUserManager>());
// Init ArcSessionManager for testing.
ArcServiceLauncher::Get()->ResetForTesting();
ArcSessionManager::SetUiEnabledForTesting(false);
ArcSessionManager::EnableCheckAndroidManagementForTesting(true);
ArcSessionManager::Get()->SetArcSessionRunnerForTesting(
std::make_unique<ArcSessionRunner>(
base::BindRepeating(FakeArcSession::Create)));
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
chromeos::ProfileHelper::SetAlwaysReturnPrimaryUserForTesting(true);
const AccountId account_id(
AccountId::FromUserEmailGaiaId(kFakeUserName, kFakeGaiaId));
GetFakeUserManager()->AddUser(account_id);
GetFakeUserManager()->LoginUser(account_id);
// Create test profile.
TestingProfile::Builder profile_builder;
profile_builder.SetPath(temp_dir_.GetPath().AppendASCII("TestArcProfile"));
profile_builder.SetProfileName(kFakeUserName);
profile_ = IdentityTestEnvironmentProfileAdaptor::
CreateProfileForIdentityTestEnvironment(profile_builder);
identity_test_environment_adaptor_ =
std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile_.get());
// Seed account info properly.
identity_test_env()->MakePrimaryAccountAvailable(kFakeUserName);
profile()->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true);
profile()->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true);
// Set up ARC for test profile.
// Currently, ArcSessionManager is singleton and set up with the original
// Profile instance. This re-initializes the ArcServiceLauncher by
// overwriting Profile with profile().
// TODO(hidehiko): This way several ArcService instances created with
// the original Profile instance on Browser creatuion are kept in the
// ArcServiceManager. For proper overwriting, those should be removed.
ArcServiceLauncher::Get()->OnPrimaryUserProfilePrepared(profile());
}
void TearDownOnMainThread() override {
// Explicitly removing the user is required; otherwise ProfileHelper keeps
// a dangling pointer to the User.
// TODO(nya): Consider removing all users from ProfileHelper in the
// destructor of FakeChromeUserManager.
const AccountId account_id(
AccountId::FromUserEmailGaiaId(kFakeUserName, kFakeGaiaId));
GetFakeUserManager()->RemoveUserFromList(account_id);
// Since ArcServiceLauncher is (re-)set up with profile() in
// SetUpOnMainThread() it is necessary to Shutdown() before the profile()
// is destroyed. ArcServiceLauncher::Shutdown() will be called again on
// fixture destruction (because it is initialized with the original Profile
// instance in fixture, once), but it should be no op.
// TODO(hidehiko): Think about a way to test the code cleanly.
ArcServiceLauncher::Get()->Shutdown();
identity_test_environment_adaptor_.reset();
profile_.reset();
base::RunLoop().RunUntilIdle();
user_manager_enabler_.reset();
chromeos::ProfileHelper::SetAlwaysReturnPrimaryUserForTesting(false);
chromeos::MixinBasedInProcessBrowserTest::TearDownOnMainThread();
}
chromeos::FakeChromeUserManager* GetFakeUserManager() const {
return static_cast<chromeos::FakeChromeUserManager*>(
user_manager::UserManager::Get());
}
void EnableArc() {
PrefService* const prefs = profile()->GetPrefs();
prefs->SetBoolean(prefs::kArcEnabled, true);
base::RunLoop().RunUntilIdle();
}
void set_profile_name(const std::string& username) {
profile_->set_profile_name(username);
}
Profile* profile() { return profile_.get(); }
identity::IdentityTestEnvironment* identity_test_env() {
return identity_test_environment_adaptor_->identity_test_env();
}
private:
chromeos::LocalPolicyTestServerMixin local_policy_mixin_{&mixin_host_};
std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
identity_test_environment_adaptor_;
base::ScopedTempDir temp_dir_;
std::unique_ptr<TestingProfile> profile_;
DISALLOW_COPY_AND_ASSIGN(ArcSessionManagerTest);
};
IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, ConsumerAccount) {
EnableArc();
identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
kUnmanagedAuthToken, base::Time::Max());
ASSERT_EQ(ArcSessionManager::State::ACTIVE,
ArcSessionManager::Get()->state());
}
IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, WellKnownConsumerAccount) {
set_profile_name(kWellKnownConsumerName);
EnableArc();
ASSERT_EQ(ArcSessionManager::State::ACTIVE,
ArcSessionManager::Get()->state());
}
IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, ManagedChromeAccount) {
policy::ProfilePolicyConnector* const connector =
policy::ProfilePolicyConnectorFactory::GetForBrowserContext(profile());
connector->OverrideIsManagedForTesting(true);
EnableArc();
ASSERT_EQ(ArcSessionManager::State::ACTIVE,
ArcSessionManager::Get()->state());
}
IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, ManagedAndroidAccount) {
EnableArc();
identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
kManagedAuthToken, base::Time::Max());
ArcPlayStoreDisabledWaiter().Wait();
EXPECT_FALSE(IsArcPlayStoreEnabledForProfile(profile()));
}
// Make sure that ARC is disabled upon entering locked fullscreen mode.
IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, ArcDisabledInLockedFullscreen) {
EnableArc();
ASSERT_EQ(ArcSessionManager::State::ACTIVE,
ArcSessionManager::Get()->state());
const int window_id = extensions::ExtensionTabUtil::GetWindowId(browser());
const char kStateLockedFullscreen[] =
"[%u, {\"state\": \"locked-fullscreen\"}]";
auto function = base::MakeRefCounted<extensions::WindowsUpdateFunction>();
scoped_refptr<const extensions::Extension> extension(
extensions::ExtensionBuilder("Test")
.SetID("pmgljoohajacndjcjlajcopidgnhphcl")
.AddPermission("lockWindowFullscreenPrivate")
.Build());
function->set_extension(extension.get());
extension_function_test_utils::RunFunctionAndReturnSingleResult(
function.get(), base::StringPrintf(kStateLockedFullscreen, window_id),
browser());
ASSERT_EQ(ArcSessionManager::State::STOPPED,
ArcSessionManager::Get()->state());
}
} // namespace arc