blob: 1907ca7370918bffd8590011e5d4cd84030891f1 [file] [log] [blame]
// Copyright 2019 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 <utility>
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h"
#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
#include "chrome/browser/chromeos/crostini/crostini_test_helper.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/usb/cros_usb_detector.h"
#include "chrome/browser/notifications/notification_display_service.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/notifications/system_notification_helper.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_cicerone_client.h"
#include "chromeos/dbus/fake_concierge_client.h"
#include "device/usb/public/cpp/fake_usb_device_info.h"
#include "device/usb/public/cpp/fake_usb_device_manager.h"
#include "device/usb/public/mojom/device.mojom.h"
#include "device/usb/public/mojom/device_manager.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/message_center/public/cpp/notification.h"
#include "url/gurl.h"
namespace {
const char* kProfileName = "test@example.com";
// USB device product name.
const char* kProductName_1 = "Google Product A";
const char* kProductName_2 = "Google Product B";
const char* kProductName_3 = "Google Product C";
const char* kUnknownProductName = "USB device";
const char* kManufacturerName = "Google";
const int kUsbConfigWithInterfaces = 1;
struct InterfaceCodes {
InterfaceCodes(uint8_t device_class,
uint8_t subclass_code,
uint8_t protocol_code)
: device_class(device_class),
subclass_code(subclass_code),
protocol_code(protocol_code) {}
uint8_t device_class;
uint8_t subclass_code;
uint8_t protocol_code;
};
scoped_refptr<device::FakeUsbDeviceInfo> CreateTestDeviceFromCodes(
uint8_t device_class,
const std::vector<InterfaceCodes>& interface_codes) {
auto config = device::mojom::UsbConfigurationInfo::New();
config->configuration_value = kUsbConfigWithInterfaces;
// The usb_utils do not filter by device class, only by configurations, and
// the FakeUsbDeviceInfo does not set up configurations for a fake device's
// class code. This helper sets up a configuration to match a devices class
// code so that USB devices can be filtered out.
for (size_t i = 0; i < interface_codes.size(); ++i) {
auto alternate = device::mojom::UsbAlternateInterfaceInfo::New();
alternate->alternate_setting = 0;
alternate->class_code = interface_codes[i].device_class;
alternate->subclass_code = interface_codes[i].subclass_code;
alternate->protocol_code = interface_codes[i].protocol_code;
auto interface = device::mojom::UsbInterfaceInfo::New();
interface->interface_number = i;
interface->alternates.push_back(std::move(alternate));
config->interfaces.push_back(std::move(interface));
}
std::vector<device::mojom::UsbConfigurationInfoPtr> configs;
configs.push_back(std::move(config));
scoped_refptr<device::FakeUsbDeviceInfo> device =
new device::FakeUsbDeviceInfo(/*vendor_id*/ 0, /*product_id*/ 1,
device_class, std::move(configs));
device->SetActiveConfig(kUsbConfigWithInterfaces);
return device;
}
scoped_refptr<device::FakeUsbDeviceInfo> CreateTestDeviceOfClass(
uint8_t device_class) {
return CreateTestDeviceFromCodes(device_class,
{InterfaceCodes(device_class, 0xff, 0xff)});
}
} // namespace
class CrosUsbDetectorTest : public BrowserWithTestWindowTest {
public:
CrosUsbDetectorTest() {
chromeos::DBusThreadManager::Initialize();
fake_cicerone_client_ = static_cast<chromeos::FakeCiceroneClient*>(
chromeos::DBusThreadManager::Get()->GetCiceroneClient());
fake_concierge_client_ = static_cast<chromeos::FakeConciergeClient*>(
chromeos::DBusThreadManager::Get()->GetConciergeClient());
cros_usb_detector_ = std::make_unique<chromeos::CrosUsbDetector>();
}
~CrosUsbDetectorTest() override { chromeos::DBusThreadManager::Shutdown(); }
TestingProfile* CreateProfile() override {
return profile_manager()->CreateTestingProfile(kProfileName);
}
void AttachUsbDeviceToVmSuccessCallback(base::OnceClosure closure,
crostini::CrostiniResult result) {
EXPECT_TRUE(fake_concierge_client_->attach_usb_device_called());
std::move(closure).Run();
}
void DetachUsbDeviceToVmSuccessCallback(base::OnceClosure closure,
crostini::CrostiniResult result) {
EXPECT_TRUE(fake_concierge_client_->detach_usb_device_called());
std::move(closure).Run();
}
void SetUp() override {
BrowserWithTestWindowTest::SetUp();
crostini_test_helper_.reset(new crostini::CrostiniTestHelper(profile()));
scoped_feature_list_.InitWithFeatures(
{chromeos::features::kCrostiniUsbSupport,
chromeos::features::kCrostiniUsbAllowUnsupported},
{});
profile_manager()->SetLoggedIn(true);
chromeos::ProfileHelper::Get()->SetActiveUserIdForTesting(kProfileName);
TestingBrowserProcess::GetGlobal()->SetSystemNotificationHelper(
std::make_unique<SystemNotificationHelper>());
display_service_ = std::make_unique<NotificationDisplayServiceTester>(
nullptr /* profile */);
// Set a fake USB device manager before ConnectToDeviceManager().
device::mojom::UsbDeviceManagerPtr device_manager_ptr;
device_manager_.AddBinding(mojo::MakeRequest(&device_manager_ptr));
chromeos::CrosUsbDetector::Get()->SetDeviceManagerForTesting(
std::move(device_manager_ptr));
}
void TearDown() override {
crostini_test_helper_.reset();
BrowserWithTestWindowTest::TearDown();
}
void ConnectToDeviceManager() {
chromeos::CrosUsbDetector::Get()->ConnectToDeviceManager();
}
protected:
base::string16 connection_message(const char* product_name) {
return base::ASCIIToUTF16(base::StringPrintf(
"Open Settings to connect %s to Linux", product_name));
}
base::string16 expected_title() {
return base::ASCIIToUTF16("USB device detected");
}
device::FakeUsbDeviceManager device_manager_;
std::unique_ptr<NotificationDisplayServiceTester> display_service_;
// Owned by chromeos::DBusThreadManager
chromeos::FakeCiceroneClient* fake_cicerone_client_;
chromeos::FakeConciergeClient* fake_concierge_client_;
std::unique_ptr<chromeos::CrosUsbDetector> cros_usb_detector_;
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<crostini::CrostiniTestHelper> crostini_test_helper_;
private:
DISALLOW_COPY_AND_ASSIGN(CrosUsbDetectorTest);
};
TEST_F(CrosUsbDetectorTest, UsbDeviceAddedAndRemoved) {
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
auto device = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
0, 1, kManufacturerName, kProductName_1, "002");
device_manager_.AddDevice(device);
base::RunLoop().RunUntilIdle();
std::string notification_id =
chromeos::CrosUsbDetector::MakeNotificationId(device->guid());
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(notification_id);
ASSERT_TRUE(notification);
EXPECT_EQ(expected_title(), notification->title());
EXPECT_EQ(connection_message(kProductName_1), notification->message());
EXPECT_TRUE(notification->delegate());
device_manager_.RemoveDevice(device);
base::RunLoop().RunUntilIdle();
// Device is removed, so notification should be removed too.
EXPECT_FALSE(display_service_->GetNotification(notification_id));
}
TEST_F(CrosUsbDetectorTest, UsbDeviceClassBlockedAdded) {
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
scoped_refptr<device::FakeUsbDeviceInfo> device =
CreateTestDeviceOfClass(/* USB_CLASS_HID */ 0x03);
device_manager_.AddDevice(device);
base::RunLoop().RunUntilIdle();
std::string notification_id =
chromeos::CrosUsbDetector::MakeNotificationId(device->guid());
ASSERT_FALSE(display_service_->GetNotification(notification_id));
// TODO(jopra): Check that the device is not available for sharing.
}
TEST_F(CrosUsbDetectorTest, UsbDeviceClassAdbAdded) {
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
const int kAdbClass = 0xff;
const int kAdbSubclass = 0x42;
const int kAdbProtocol = 0x1;
// Adb interface as well as a forbidden interface
scoped_refptr<device::FakeUsbDeviceInfo> device = CreateTestDeviceFromCodes(
/* USB_CLASS_HID */ 0x03,
{InterfaceCodes(kAdbClass, kAdbSubclass, kAdbProtocol),
InterfaceCodes(0x03, 0xff, 0xff)});
device_manager_.AddDevice(device);
base::RunLoop().RunUntilIdle();
std::string notification_id =
chromeos::CrosUsbDetector::MakeNotificationId(device->guid());
ASSERT_TRUE(display_service_->GetNotification(notification_id));
}
TEST_F(CrosUsbDetectorTest, UsbDeviceClassWithoutNotificationAdded) {
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
scoped_refptr<device::FakeUsbDeviceInfo> device =
CreateTestDeviceOfClass(/* USB_CLASS_AUDIO */ 0x01);
device_manager_.AddDevice(device);
base::RunLoop().RunUntilIdle();
std::string notification_id =
chromeos::CrosUsbDetector::MakeNotificationId(device->guid());
ASSERT_FALSE(display_service_->GetNotification(notification_id));
// TODO(jopra): Check that the device is available for sharing.
}
TEST_F(CrosUsbDetectorTest, UsbDeviceWithoutProductNameAddedAndRemoved) {
std::string product_name = "";
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
auto device = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
0, 1, kManufacturerName, product_name, "002");
device_manager_.AddDevice(device);
base::RunLoop().RunUntilIdle();
std::string notification_id =
chromeos::CrosUsbDetector::MakeNotificationId(device->guid());
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(notification_id);
ASSERT_TRUE(notification);
EXPECT_EQ(expected_title(), notification->title());
EXPECT_EQ(connection_message("USB device from Google"),
notification->message());
EXPECT_TRUE(notification->delegate());
device_manager_.RemoveDevice(device);
base::RunLoop().RunUntilIdle();
// Device is removed, so notification should be removed too.
EXPECT_FALSE(display_service_->GetNotification(notification_id));
}
TEST_F(CrosUsbDetectorTest,
UsbDeviceWithoutProductNameOrManufacturerNameAddedAndRemoved) {
std::string product_name = "";
std::string manufacturer_name = "";
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
auto device = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
0, 1, manufacturer_name, product_name, "002");
device_manager_.AddDevice(device);
base::RunLoop().RunUntilIdle();
std::string notification_id =
chromeos::CrosUsbDetector::MakeNotificationId(device->guid());
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(notification_id);
ASSERT_TRUE(notification);
EXPECT_EQ(expected_title(), notification->title());
EXPECT_EQ(connection_message(kUnknownProductName), notification->message());
EXPECT_TRUE(notification->delegate());
device_manager_.RemoveDevice(device);
base::RunLoop().RunUntilIdle();
// Device is removed, so notification should be removed too.
EXPECT_FALSE(display_service_->GetNotification(notification_id));
}
TEST_F(CrosUsbDetectorTest, UsbDeviceWasThereBeforeAndThenRemoved) {
// USB device was added before cros_usb_detector was created.
auto device = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
0, 1, kManufacturerName, kProductName_1, "002");
device_manager_.AddDevice(device);
base::RunLoop().RunUntilIdle();
std::string notification_id =
chromeos::CrosUsbDetector::MakeNotificationId(device->guid());
EXPECT_FALSE(display_service_->GetNotification(notification_id));
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
device_manager_.RemoveDevice(device);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id));
}
TEST_F(
CrosUsbDetectorTest,
ThreeUsbDevicesWereThereBeforeAndThenRemovedBeforeUsbDetectorWasCreated) {
auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
0, 1, kManufacturerName, kProductName_1, "002");
std::string notification_id_1 =
chromeos::CrosUsbDetector::MakeNotificationId(device_1->guid());
auto device_2 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
3, 4, kManufacturerName, kProductName_2, "005");
std::string notification_id_2 =
chromeos::CrosUsbDetector::MakeNotificationId(device_2->guid());
auto device_3 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
6, 7, kManufacturerName, kProductName_3, "008");
std::string notification_id_3 =
chromeos::CrosUsbDetector::MakeNotificationId(device_3->guid());
// Three usb devices were added and removed before cros_usb_detector was
// created.
device_manager_.AddDevice(device_1);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
device_manager_.AddDevice(device_2);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
device_manager_.AddDevice(device_3);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
device_manager_.RemoveDevice(device_1);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
device_manager_.RemoveDevice(device_2);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
device_manager_.RemoveDevice(device_3);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
}
TEST_F(CrosUsbDetectorTest,
ThreeUsbDevicesWereThereBeforeAndThenRemovedAfterUsbDetectorWasCreated) {
auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
0, 1, kManufacturerName, kProductName_1, "002");
std::string notification_id_1 =
chromeos::CrosUsbDetector::MakeNotificationId(device_1->guid());
auto device_2 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
3, 4, kManufacturerName, kProductName_2, "005");
std::string notification_id_2 =
chromeos::CrosUsbDetector::MakeNotificationId(device_2->guid());
auto device_3 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
6, 7, kManufacturerName, kProductName_3, "008");
std::string notification_id_3 =
chromeos::CrosUsbDetector::MakeNotificationId(device_3->guid());
// Three usb devices were added before cros_usb_detector was created.
device_manager_.AddDevice(device_1);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
device_manager_.AddDevice(device_2);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
device_manager_.AddDevice(device_3);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
device_manager_.RemoveDevice(device_1);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
device_manager_.RemoveDevice(device_2);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
device_manager_.RemoveDevice(device_3);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
}
TEST_F(CrosUsbDetectorTest,
TwoUsbDevicesWereThereBeforeAndThenRemovedAndNewUsbDeviceAdded) {
auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
0, 1, kManufacturerName, kProductName_1, "002");
std::string notification_id_1 =
chromeos::CrosUsbDetector::MakeNotificationId(device_1->guid());
auto device_2 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
3, 4, kManufacturerName, kProductName_2, "005");
std::string notification_id_2 =
chromeos::CrosUsbDetector::MakeNotificationId(device_2->guid());
// Two usb devices were added before cros_usb_detector was created.
device_manager_.AddDevice(device_1);
device_manager_.AddDevice(device_2);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
device_manager_.RemoveDevice(device_1);
device_manager_.RemoveDevice(device_2);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
device_manager_.AddDevice(device_2);
base::RunLoop().RunUntilIdle();
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(notification_id_2);
ASSERT_TRUE(notification);
EXPECT_EQ(expected_title(), notification->title());
EXPECT_EQ(connection_message(kProductName_2), notification->message());
EXPECT_TRUE(notification->delegate());
device_manager_.RemoveDevice(device_2);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
}
TEST_F(CrosUsbDetectorTest, ThreeUsbDevicesAddedAndRemoved) {
auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
0, 1, kManufacturerName, kProductName_1, "002");
std::string notification_id_1 =
chromeos::CrosUsbDetector::MakeNotificationId(device_1->guid());
auto device_2 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
3, 4, kManufacturerName, kProductName_2, "005");
std::string notification_id_2 =
chromeos::CrosUsbDetector::MakeNotificationId(device_2->guid());
auto device_3 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
6, 7, kManufacturerName, kProductName_3, "008");
std::string notification_id_3 =
chromeos::CrosUsbDetector::MakeNotificationId(device_3->guid());
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
device_manager_.AddDevice(device_1);
base::RunLoop().RunUntilIdle();
base::Optional<message_center::Notification> notification_1 =
display_service_->GetNotification(notification_id_1);
ASSERT_TRUE(notification_1);
EXPECT_EQ(expected_title(), notification_1->title());
EXPECT_EQ(connection_message(kProductName_1), notification_1->message());
EXPECT_TRUE(notification_1->delegate());
device_manager_.RemoveDevice(device_1);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
device_manager_.AddDevice(device_2);
base::RunLoop().RunUntilIdle();
base::Optional<message_center::Notification> notification_2 =
display_service_->GetNotification(notification_id_2);
ASSERT_TRUE(notification_2);
EXPECT_EQ(expected_title(), notification_2->title());
EXPECT_EQ(connection_message(kProductName_2), notification_2->message());
EXPECT_TRUE(notification_2->delegate());
device_manager_.RemoveDevice(device_2);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
device_manager_.AddDevice(device_3);
base::RunLoop().RunUntilIdle();
base::Optional<message_center::Notification> notification_3 =
display_service_->GetNotification(notification_id_3);
ASSERT_TRUE(notification_3);
EXPECT_EQ(expected_title(), notification_3->title());
EXPECT_EQ(connection_message(kProductName_3), notification_3->message());
EXPECT_TRUE(notification_3->delegate());
device_manager_.RemoveDevice(device_3);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
}
TEST_F(CrosUsbDetectorTest, ThreeUsbDeviceAddedAndRemovedDifferentOrder) {
auto device_1 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
0, 1, kManufacturerName, kProductName_1, "002");
std::string notification_id_1 =
chromeos::CrosUsbDetector::MakeNotificationId(device_1->guid());
auto device_2 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
3, 4, kManufacturerName, kProductName_2, "005");
std::string notification_id_2 =
chromeos::CrosUsbDetector::MakeNotificationId(device_2->guid());
auto device_3 = base::MakeRefCounted<device::FakeUsbDeviceInfo>(
6, 7, kManufacturerName, kProductName_3, "008");
std::string notification_id_3 =
chromeos::CrosUsbDetector::MakeNotificationId(device_3->guid());
ConnectToDeviceManager();
base::RunLoop().RunUntilIdle();
device_manager_.AddDevice(device_1);
base::RunLoop().RunUntilIdle();
base::Optional<message_center::Notification> notification_1 =
display_service_->GetNotification(notification_id_1);
ASSERT_TRUE(notification_1);
EXPECT_EQ(expected_title(), notification_1->title());
EXPECT_EQ(connection_message(kProductName_1), notification_1->message());
EXPECT_TRUE(notification_1->delegate());
device_manager_.AddDevice(device_2);
base::RunLoop().RunUntilIdle();
base::Optional<message_center::Notification> notification_2 =
display_service_->GetNotification(notification_id_2);
ASSERT_TRUE(notification_2);
EXPECT_EQ(expected_title(), notification_2->title());
EXPECT_EQ(connection_message(kProductName_2), notification_2->message());
EXPECT_TRUE(notification_2->delegate());
device_manager_.RemoveDevice(device_2);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_2));
device_manager_.AddDevice(device_3);
base::RunLoop().RunUntilIdle();
base::Optional<message_center::Notification> notification_3 =
display_service_->GetNotification(notification_id_3);
ASSERT_TRUE(notification_3);
EXPECT_EQ(expected_title(), notification_3->title());
EXPECT_EQ(connection_message(kProductName_3), notification_3->message());
EXPECT_TRUE(notification_3->delegate());
device_manager_.RemoveDevice(device_1);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_1));
device_manager_.RemoveDevice(device_3);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(display_service_->GetNotification(notification_id_3));
}