blob: 3e56d1d63f37a60dd2ba094417c6181e6a7a0358 [file] [log] [blame]
// 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/ui/app_list/arc/arc_usb_host_permission_manager.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.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_factory.h"
#include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/arc/arc_util.h"
#include "components/arc/mojom/app.mojom.h"
#include "components/arc/test/connection_holder_util.h"
#include "components/arc/test/fake_app_instance.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/test/test_utils.h"
namespace arc {
namespace {
// Test package strings.
constexpr char kAppName[] = "test.app.name";
constexpr char kAppActivity[] = "test.app.activity";
constexpr char kPackageName[] = "test.app.package.name";
constexpr char kTestProfileName[] = "user@gmail.com";
} // namespace
class ArcUsbHostPermissionTest : public InProcessBrowserTest {
public:
ArcUsbHostPermissionTest() = default;
~ArcUsbHostPermissionTest() override = default;
void SetUpCommandLine(base::CommandLine* command_line) override {
arc::SetArcAvailableCommandLineForTesting(command_line);
}
void SetUpInProcessBrowserTestFixture() override {
ArcSessionManager::SetUiEnabledForTesting(false);
}
void SetUpOnMainThread() override {
profile_ = browser()->profile();
arc::SetArcPlayStoreEnabledForProfile(profile_, true);
arc_app_list_pref_ = ArcAppListPrefs::Get(profile_);
DCHECK(arc_app_list_pref_);
base::RunLoop run_loop;
arc_app_list_pref_->SetDefaultAppsReadyCallback(run_loop.QuitClosure());
run_loop.Run();
app_instance_ = std::make_unique<arc::FakeAppInstance>(arc_app_list_pref_);
arc_app_list_pref_->app_connection_holder()->SetInstance(
app_instance_.get());
WaitForInstanceReady(arc_app_list_pref_->app_connection_holder());
arc_usb_permission_manager_ =
ArcUsbHostPermissionManager::GetForBrowserContext(profile_);
DCHECK(arc_usb_permission_manager_);
}
void TearDownOnMainThread() override {
arc_app_list_pref_->app_connection_holder()->CloseInstance(
app_instance_.get());
app_instance_.reset();
ArcSessionManager::Get()->Shutdown();
}
protected:
void AddArcApp(const std::string& app_name,
const std::string& package_name,
const std::string& activity) {
arc::mojom::AppInfo app_info;
app_info.name = app_name;
app_info.package_name = package_name;
app_info.activity = activity;
app_instance_->SendPackageAppListRefreshed(package_name, {app_info});
}
void AddArcPackage(const std::string& package_name) {
app_instance_->SendPackageAdded(arc::mojom::ArcPackageInfo::New(
package_name, 0 /* package_version */, 0 /* last_backup_android_id */,
0 /* last_backup_time */, false /* sync */));
}
void RemovePackage(const std::string& package_name) {
app_instance_->UninstallPackage(package_name);
}
void DeviceRemoved(const std::string& guid) {
arc_usb_permission_manager_->DeviceRemoved(guid);
}
void RestorePermissionFromChromePrefs() {
arc_usb_permission_manager_->RestorePermissionFromChromePrefs();
}
void UpdateArcUsbScanDeviceListPermission(const std::string& package_name,
bool allowed) {
arc_usb_permission_manager_->UpdateArcUsbScanDeviceListPermission(
package_name, allowed);
}
void UpdateArcUsbAccessPermission(
const std::string& package_name,
const ArcUsbHostPermissionManager::UsbDeviceEntry& usb_device_entry,
bool allowed) {
arc_usb_permission_manager_->UpdateArcUsbAccessPermission(
package_name, usb_device_entry, allowed);
}
void GrantTemporayUsbAccessPermission(
const std::string& package_name,
const ArcUsbHostPermissionManager::UsbDeviceEntry& usb_device_entry) {
arc_usb_permission_manager_->GrantUsbAccessPermission(
package_name, usb_device_entry.guid, usb_device_entry.vendor_id,
usb_device_entry.product_id);
}
std::unordered_set<std::string> GetEventPackageList(
const ArcUsbHostPermissionManager::UsbDeviceEntry& usb_device_entry)
const {
return arc_usb_permission_manager_->GetEventPackageList(
usb_device_entry.guid, usb_device_entry.serial_number,
usb_device_entry.vendor_id, usb_device_entry.product_id);
}
bool HasUsbScanDeviceListPermission(const std::string& package_name) const {
return arc_usb_permission_manager_->HasUsbScanDeviceListPermission(
package_name);
}
bool HasUsbAccessPermission(const std::string& package_name,
const ArcUsbHostPermissionManager::UsbDeviceEntry&
usb_device_entry) const {
return arc_usb_permission_manager_->HasUsbAccessPermission(
package_name, usb_device_entry);
}
void ClearPermissions() {
arc_usb_permission_manager_->ClearPermissionForTesting();
}
ArcUsbHostPermissionManager* arc_usb_permission_manager() {
return arc_usb_permission_manager_;
}
private:
ArcAppListPrefs* arc_app_list_pref_;
ArcUsbHostPermissionManager* arc_usb_permission_manager_;
std::unique_ptr<FakeAppInstance> app_instance_;
Profile* profile_;
DISALLOW_COPY_AND_ASSIGN(ArcUsbHostPermissionTest);
};
class ArcUsbHostKioskPermissionTest : public ArcUsbHostPermissionTest {
public:
ArcUsbHostKioskPermissionTest() = default;
~ArcUsbHostKioskPermissionTest() override = default;
void SetUpOnMainThread() override {
user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
std::make_unique<chromeos::FakeChromeUserManager>());
const AccountId account_id(AccountId::FromUserEmail(kTestProfileName));
GetFakeUserManager()->AddArcKioskAppUser(account_id);
GetFakeUserManager()->LoginUser(account_id);
ArcUsbHostPermissionTest::SetUpOnMainThread();
}
void TearDownOnMainThread() override {
ArcUsbHostPermissionTest::TearDownOnMainThread();
const AccountId account_id(AccountId::FromUserEmail(kTestProfileName));
GetFakeUserManager()->RemoveUserFromList(account_id);
user_manager_enabler_.reset();
}
void set_response(bool accepted) {
if (accepted)
accepted_response_count_++;
}
int accepted_response_count() const { return accepted_response_count_; }
private:
chromeos::FakeChromeUserManager* GetFakeUserManager() const {
return static_cast<chromeos::FakeChromeUserManager*>(
user_manager::UserManager::Get());
}
int accepted_response_count_ = 0;
std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
DISALLOW_COPY_AND_ASSIGN(ArcUsbHostKioskPermissionTest);
};
IN_PROC_BROWSER_TEST_F(ArcUsbHostPermissionTest, UsbTemporayPermissionTest) {
AddArcApp(kAppName, kPackageName, kAppActivity);
AddArcPackage(kPackageName);
// Persistent device0.
const std::string guid0 = "TestGuidXXXXXX0";
const base::string16 device_name0 = base::UTF8ToUTF16("TestDevice0");
const base::string16 serial_number0 = base::UTF8ToUTF16("TestSerialNumber0");
const uint16_t vendor_id0 = 123;
const uint16_t product_id0 = 456;
ArcUsbHostPermissionManager::UsbDeviceEntry testDevice0(
guid0, device_name0, serial_number0, vendor_id0, product_id0);
GrantTemporayUsbAccessPermission(kPackageName, testDevice0);
EXPECT_TRUE(HasUsbAccessPermission(kPackageName, testDevice0));
EXPECT_EQ(1u, GetEventPackageList(testDevice0).size());
DeviceRemoved(guid0);
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice0));
EXPECT_EQ(0u, GetEventPackageList(testDevice0).size());
}
IN_PROC_BROWSER_TEST_F(ArcUsbHostPermissionTest, UsbChromePrefsTest) {
AddArcApp(kAppName, kPackageName, kAppActivity);
AddArcPackage(kPackageName);
// Persistent device0.
const std::string guid0 = "TestGuidXXXXXX0";
const base::string16 device_name0 = base::UTF8ToUTF16("TestDevice0");
const base::string16 serial_number0 = base::UTF8ToUTF16("TestSerialNumber0");
const uint16_t vendor_id0 = 123;
const uint16_t product_id0 = 456;
// Persistent device1.
const std::string guid1 = "TestGuidXXXXXX1";
const base::string16 device_name1 = base::UTF8ToUTF16("TestDevice1");
const base::string16 serial_number1 = base::UTF8ToUTF16("TestSerialNumber1");
const uint16_t vendor_id1 = 234;
const uint16_t product_id1 = 567;
// Non persistent device2.
const std::string guid2 = "TestGuidXXXXXX2";
const base::string16 device_name2 = base::UTF8ToUTF16("TestDevice2");
const uint16_t vendor_id2 = 345;
const uint16_t product_id2 = 678;
ArcUsbHostPermissionManager::UsbDeviceEntry testDevice0(
guid0, device_name0, serial_number0, vendor_id0, product_id0);
ArcUsbHostPermissionManager::UsbDeviceEntry testDevice1(
guid1, device_name1, serial_number1, vendor_id1, product_id1);
ArcUsbHostPermissionManager::UsbDeviceEntry testDevice2(
guid2, device_name2, base::string16() /*serial_number*/, vendor_id2,
product_id2);
EXPECT_FALSE(HasUsbScanDeviceListPermission(kPackageName));
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice0));
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice1));
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice2));
UpdateArcUsbScanDeviceListPermission(kPackageName, true /*allowed*/);
UpdateArcUsbAccessPermission(kPackageName, testDevice0, true /*allowed*/);
UpdateArcUsbAccessPermission(kPackageName, testDevice1, true /*allowed*/);
UpdateArcUsbAccessPermission(kPackageName, testDevice2, true /*allowed*/);
EXPECT_TRUE(HasUsbScanDeviceListPermission(kPackageName));
EXPECT_TRUE(HasUsbAccessPermission(kPackageName, testDevice0));
EXPECT_TRUE(HasUsbAccessPermission(kPackageName, testDevice1));
EXPECT_TRUE(HasUsbAccessPermission(kPackageName, testDevice2));
// Remove all devices. Permission for persistent device should remain.
DeviceRemoved(guid0);
DeviceRemoved(guid1);
DeviceRemoved(guid2);
EXPECT_TRUE(HasUsbScanDeviceListPermission(kPackageName));
EXPECT_TRUE(HasUsbAccessPermission(kPackageName, testDevice0));
EXPECT_TRUE(HasUsbAccessPermission(kPackageName, testDevice1));
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice2));
ClearPermissions();
EXPECT_FALSE(HasUsbScanDeviceListPermission(kPackageName));
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice0));
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice1));
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice2));
// Resotre permission from Chrome prefs. Permission for persistent devices
// should be restored.
RestorePermissionFromChromePrefs();
EXPECT_TRUE(HasUsbScanDeviceListPermission(kPackageName));
EXPECT_TRUE(HasUsbAccessPermission(kPackageName, testDevice0));
EXPECT_TRUE(HasUsbAccessPermission(kPackageName, testDevice1));
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice2));
// Remove the package. All permission are gone.
ClearPermissions();
RemovePackage(kPackageName);
RestorePermissionFromChromePrefs();
EXPECT_FALSE(HasUsbScanDeviceListPermission(kPackageName));
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice0));
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice1));
EXPECT_FALSE(HasUsbAccessPermission(kPackageName, testDevice2));
}
// If Enterprise wants to control USB permission for kiosk app, this
// test expectation should also be updated.
IN_PROC_BROWSER_TEST_F(ArcUsbHostKioskPermissionTest, UsbKioskPermission) {
DCHECK(IsArcKioskMode());
AddArcApp(kAppName, kPackageName, kAppActivity);
AddArcPackage(kPackageName);
// Persistent device0.
const std::string guid = "TestGuidXXXXXX0";
const base::string16 serial_number = base::UTF8ToUTF16("TestSerialNumber0");
const uint16_t vendor_id = 123;
const uint16_t product_id = 456;
int request_count = 0;
EXPECT_EQ(request_count, accepted_response_count());
arc_usb_permission_manager()->RequestUsbScanDeviceListPermission(
kPackageName, base::BindOnce(&ArcUsbHostKioskPermissionTest::set_response,
base::Unretained(this)));
EXPECT_EQ(++request_count, accepted_response_count());
arc_usb_permission_manager()->RequestUsbAccessPermission(
kPackageName, guid, serial_number, base::string16(), base::string16(),
vendor_id, product_id,
base::BindOnce(&ArcUsbHostKioskPermissionTest::set_response,
base::Unretained(this)));
EXPECT_EQ(++request_count, accepted_response_count());
}
} // namespace arc