| Index: content/renderer/media/media_devices_event_dispatcher_unittest.cc
 | 
| diff --git a/content/renderer/media/media_devices_event_dispatcher_unittest.cc b/content/renderer/media/media_devices_event_dispatcher_unittest.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..733f512d2c05a7be71bedc93522b4c7c66f4dc41
 | 
| --- /dev/null
 | 
| +++ b/content/renderer/media/media_devices_event_dispatcher_unittest.cc
 | 
| @@ -0,0 +1,193 @@
 | 
| +// 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 "content/renderer/media/media_devices_event_dispatcher.h"
 | 
| +
 | 
| +#include <stddef.h>
 | 
| +
 | 
| +#include <memory>
 | 
| +#include <string>
 | 
| +
 | 
| +#include "base/memory/ref_counted.h"
 | 
| +#include "base/message_loop/message_loop.h"
 | 
| +#include "base/run_loop.h"
 | 
| +#include "base/strings/string_number_conversions.h"
 | 
| +#include "mojo/public/cpp/bindings/binding.h"
 | 
| +#include "testing/gmock/include/gmock/gmock.h"
 | 
| +#include "testing/gtest/include/gtest/gtest.h"
 | 
| +#include "url/gurl.h"
 | 
| +#include "url/origin.h"
 | 
| +
 | 
| +using testing::_;
 | 
| +
 | 
| +namespace content {
 | 
| +namespace {
 | 
| +
 | 
| +class MockMediaDevicesEventSubscriber {
 | 
| + public:
 | 
| +  MOCK_METHOD2(EventDispatched,
 | 
| +               void(MediaDeviceType, const MediaDeviceInfoArray&));
 | 
| +};
 | 
| +
 | 
| +class MockMediaDevicesDispatcherHost
 | 
| +    : public ::mojom::MediaDevicesDispatcherHost {
 | 
| + public:
 | 
| +  MockMediaDevicesDispatcherHost() : binding_(this) {}
 | 
| +
 | 
| +  MOCK_METHOD5(EnumerateDevices,
 | 
| +               void(bool request_audio_input,
 | 
| +                    bool request_video_input,
 | 
| +                    bool request_audio_output,
 | 
| +                    const url::Origin& security_origin,
 | 
| +                    const EnumerateDevicesCallback& callback));
 | 
| +  MOCK_METHOD3(SubscribeDeviceChangeNotifications,
 | 
| +               void(MediaDeviceType type,
 | 
| +                    uint32_t subscription_id,
 | 
| +                    const url::Origin& security_origin));
 | 
| +  MOCK_METHOD2(UnsubscribeDeviceChangeNotifications,
 | 
| +               void(MediaDeviceType type, uint32_t subscription_id));
 | 
| +
 | 
| +  ::mojom::MediaDevicesDispatcherHostPtr CreateInterfacePtrAndBind() {
 | 
| +    return binding_.CreateInterfacePtrAndBind();
 | 
| +  }
 | 
| +
 | 
| + private:
 | 
| +  mojo::Binding<::mojom::MediaDevicesDispatcherHost> binding_;
 | 
| +};
 | 
| +
 | 
| +class MediaDevicesEventDispatcherTest : public ::testing::Test {
 | 
| + public:
 | 
| +  MediaDevicesEventDispatcherTest() {}
 | 
| +
 | 
| +  void SetUp() override {
 | 
| +    event_dispatcher_ = MediaDevicesEventDispatcher::GetForRenderFrame(nullptr);
 | 
| +    ::mojom::MediaDevicesDispatcherHostPtr ptr =
 | 
| +        media_devices_dispatcher_.CreateInterfacePtrAndBind();
 | 
| +    event_dispatcher_->SetMediaDevicesDispatcherForTesting(std::move(ptr));
 | 
| +  }
 | 
| +
 | 
| +  void TearDown() override { event_dispatcher_->OnDestruct(); }
 | 
| +
 | 
| + protected:
 | 
| +  base::MessageLoop message_loop_;
 | 
| +  base::WeakPtr<MediaDevicesEventDispatcher> event_dispatcher_;
 | 
| +  MockMediaDevicesDispatcherHost media_devices_dispatcher_;
 | 
| +};
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +TEST_F(MediaDevicesEventDispatcherTest, SubscribeUnsubscribeSingleType) {
 | 
| +  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
 | 
| +    MediaDeviceType type = static_cast<MediaDeviceType>(i);
 | 
| +    MediaDeviceInfoArray device_infos;
 | 
| +    MockMediaDevicesEventSubscriber subscriber1, subscriber2;
 | 
| +    url::Origin security_origin(GURL("http://localhost"));
 | 
| +    EXPECT_CALL(media_devices_dispatcher_,
 | 
| +                SubscribeDeviceChangeNotifications(type, _, security_origin))
 | 
| +        .Times(2);
 | 
| +    auto subscription_id1 =
 | 
| +        event_dispatcher_->SubscribeDeviceChangeNotifications(
 | 
| +            type, security_origin,
 | 
| +            base::Bind(&MockMediaDevicesEventSubscriber::EventDispatched,
 | 
| +                       base::Unretained(&subscriber1)));
 | 
| +    auto subscription_id2 =
 | 
| +        event_dispatcher_->SubscribeDeviceChangeNotifications(
 | 
| +            type, security_origin,
 | 
| +            base::Bind(&MockMediaDevicesEventSubscriber::EventDispatched,
 | 
| +                       base::Unretained(&subscriber2)));
 | 
| +
 | 
| +    // Simulate a device change.
 | 
| +    EXPECT_CALL(subscriber1, EventDispatched(type, _));
 | 
| +    EXPECT_CALL(subscriber2, EventDispatched(type, _));
 | 
| +    event_dispatcher_->DispatchDevicesChangedEvent(type, device_infos);
 | 
| +    base::RunLoop().RunUntilIdle();
 | 
| +
 | 
| +    // Unsubscribe one of the subscribers.
 | 
| +    EXPECT_CALL(media_devices_dispatcher_,
 | 
| +                UnsubscribeDeviceChangeNotifications(type, subscription_id1));
 | 
| +    event_dispatcher_->UnsubscribeDeviceChangeNotifications(type,
 | 
| +                                                            subscription_id1);
 | 
| +
 | 
| +    // Simulate another device change.
 | 
| +    EXPECT_CALL(subscriber1, EventDispatched(_, _)).Times(0);
 | 
| +    EXPECT_CALL(subscriber2, EventDispatched(type, _));
 | 
| +    event_dispatcher_->DispatchDevicesChangedEvent(type, device_infos);
 | 
| +    base::RunLoop().RunUntilIdle();
 | 
| +
 | 
| +    // Unsubscribe the other subscriber.
 | 
| +    EXPECT_CALL(media_devices_dispatcher_,
 | 
| +                UnsubscribeDeviceChangeNotifications(type, subscription_id2));
 | 
| +    event_dispatcher_->UnsubscribeDeviceChangeNotifications(type,
 | 
| +                                                            subscription_id2);
 | 
| +    base::RunLoop().RunUntilIdle();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +TEST_F(MediaDevicesEventDispatcherTest, SubscribeUnsubscribeAllTypes) {
 | 
| +  MediaDeviceInfoArray device_infos;
 | 
| +  MockMediaDevicesEventSubscriber subscriber1, subscriber2;
 | 
| +  url::Origin security_origin(GURL("http://localhost"));
 | 
| +  EXPECT_CALL(media_devices_dispatcher_,
 | 
| +              SubscribeDeviceChangeNotifications(MEDIA_DEVICE_TYPE_AUDIO_INPUT,
 | 
| +                                                 _, security_origin))
 | 
| +      .Times(2);
 | 
| +  EXPECT_CALL(media_devices_dispatcher_,
 | 
| +              SubscribeDeviceChangeNotifications(MEDIA_DEVICE_TYPE_VIDEO_INPUT,
 | 
| +                                                 _, security_origin))
 | 
| +      .Times(2);
 | 
| +  EXPECT_CALL(media_devices_dispatcher_,
 | 
| +              SubscribeDeviceChangeNotifications(MEDIA_DEVICE_TYPE_AUDIO_OUTPUT,
 | 
| +                                                 _, security_origin))
 | 
| +      .Times(2);
 | 
| +  auto subscription_list_1 =
 | 
| +      event_dispatcher_->SubscribeDeviceChangeNotifications(
 | 
| +          security_origin,
 | 
| +          base::Bind(&MockMediaDevicesEventSubscriber::EventDispatched,
 | 
| +                     base::Unretained(&subscriber1)));
 | 
| +  auto subscription_list_2 =
 | 
| +      event_dispatcher_->SubscribeDeviceChangeNotifications(
 | 
| +          security_origin,
 | 
| +          base::Bind(&MockMediaDevicesEventSubscriber::EventDispatched,
 | 
| +                     base::Unretained(&subscriber2)));
 | 
| +
 | 
| +  // Simulate a device changes for all types.
 | 
| +  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
 | 
| +    MediaDeviceType type = static_cast<MediaDeviceType>(i);
 | 
| +    EXPECT_CALL(subscriber1, EventDispatched(type, _));
 | 
| +    EXPECT_CALL(subscriber2, EventDispatched(type, _));
 | 
| +    event_dispatcher_->DispatchDevicesChangedEvent(type, device_infos);
 | 
| +    base::RunLoop().RunUntilIdle();
 | 
| +  }
 | 
| +
 | 
| +  // Unsubscribe one of the subscribers.
 | 
| +  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
 | 
| +    MediaDeviceType type = static_cast<MediaDeviceType>(i);
 | 
| +    EXPECT_CALL(
 | 
| +        media_devices_dispatcher_,
 | 
| +        UnsubscribeDeviceChangeNotifications(type, subscription_list_1[type]));
 | 
| +  }
 | 
| +  event_dispatcher_->UnsubscribeDeviceChangeNotifications(subscription_list_1);
 | 
| +  base::RunLoop().RunUntilIdle();
 | 
| +
 | 
| +  // Simulate more device changes.
 | 
| +  EXPECT_CALL(subscriber1, EventDispatched(_, _)).Times(0);
 | 
| +  EXPECT_CALL(subscriber2, EventDispatched(_, _)).Times(NUM_MEDIA_DEVICE_TYPES);
 | 
| +  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
 | 
| +    MediaDeviceType type = static_cast<MediaDeviceType>(i);
 | 
| +    event_dispatcher_->DispatchDevicesChangedEvent(type, device_infos);
 | 
| +    base::RunLoop().RunUntilIdle();
 | 
| +  }
 | 
| +
 | 
| +  // Unsubscribe the other subscriber.
 | 
| +  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
 | 
| +    MediaDeviceType type = static_cast<MediaDeviceType>(i);
 | 
| +    EXPECT_CALL(
 | 
| +        media_devices_dispatcher_,
 | 
| +        UnsubscribeDeviceChangeNotifications(type, subscription_list_2[type]));
 | 
| +  }
 | 
| +  event_dispatcher_->UnsubscribeDeviceChangeNotifications(subscription_list_2);
 | 
| +  base::RunLoop().RunUntilIdle();
 | 
| +}
 | 
| +
 | 
| +}  // namespace content
 | 
| 
 |