Index: blimp/client/core/contents/blimp_contents_impl_unittest.cc |
diff --git a/blimp/client/core/contents/blimp_contents_impl_unittest.cc b/blimp/client/core/contents/blimp_contents_impl_unittest.cc |
index 98fa2066246edf05c0c085cd0116196bd5a7edec..ed9fd36488a8ffa84e3a9b8b5ae93108307ca8c3 100644 |
--- a/blimp/client/core/contents/blimp_contents_impl_unittest.cc |
+++ b/blimp/client/core/contents/blimp_contents_impl_unittest.cc |
@@ -5,11 +5,19 @@ |
#include "blimp/client/core/contents/blimp_contents_impl.h" |
#include "base/message_loop/message_loop.h" |
-#include "blimp/client/core/contents/blimp_contents_impl.h" |
+#include "blimp/client/core/compositor/compositor_deps_provider.h" |
#include "blimp/client/core/contents/fake_navigation_feature.h" |
+#include "blimp/client/core/render_widget/blimp_render_widget.h" |
+#include "blimp/client/core/render_widget/render_widget_feature.h" |
#include "blimp/client/public/contents/blimp_contents_observer.h" |
+#include "cc/proto/compositor_message.pb.h" |
#include "testing/gmock/include/gmock/gmock.h" |
#include "testing/gtest/include/gtest/gtest.h" |
+#include "third_party/WebKit/public/web/WebInputEvent.h" |
+ |
+using testing::_; |
+using testing::InSequence; |
+using testing::Sequence; |
namespace blimp { |
namespace client { |
@@ -31,36 +39,192 @@ class MockBlimpContentsObserver : public BlimpContentsObserver { |
DISALLOW_COPY_AND_ASSIGN(MockBlimpContentsObserver); |
}; |
-TEST(BlimpContentsImplTest, LoadURLAndNotifyObservers) { |
- base::MessageLoop loop; |
- BlimpContentsImpl blimp_contents(kDummyTabId); |
+class MockRenderWidgetFeature : public RenderWidgetFeature { |
+ public: |
+ MOCK_METHOD3(SendCompositorMessage, |
+ void(const int, const int, const cc::proto::CompositorMessage&)); |
+ MOCK_METHOD3(SendInputEvent, |
+ void(const int, const int, const blink::WebInputEvent&)); |
+ MOCK_METHOD2(SetDelegate, void(int, RenderWidgetFeatureDelegate*)); |
+ MOCK_METHOD1(RemoveDelegate, void(const int)); |
+}; |
+ |
+class MockRenderWidget : public BlimpRenderWidget { |
+ public: |
+ MockRenderWidget(int32_t render_widget_id, |
+ BlimpRenderWidgetDelegate* delegate) |
+ : BlimpRenderWidget(render_widget_id, delegate) {} |
+ |
+ MOCK_METHOD1(SetVisible, void(bool)); |
+ MOCK_METHOD1(SetAcceleratedWidget, void(gfx::AcceleratedWidget)); |
+ |
+ void OnCompositorMessageReceived( |
+ std::unique_ptr<cc::proto::CompositorMessage> message) override { |
+ MockableOnCompositorMessageReceived(*message); |
+ } |
+ MOCK_METHOD1(MockableOnCompositorMessageReceived, |
+ void(const cc::proto::CompositorMessage&)); |
+}; |
+ |
+class BlimpContentsImplForTesting : public BlimpContentsImpl { |
+ public: |
+ BlimpContentsImplForTesting(int id, |
+ RenderWidgetFeature* render_widget_feature) |
+ : BlimpContentsImpl(id, render_widget_feature) {} |
+ |
+ protected: |
+ std::unique_ptr<BlimpRenderWidget> CreateBlimpRenderWidget( |
+ int32_t render_widget_id, |
+ BlimpRenderWidgetDelegate* delegate) override { |
+ return base::MakeUnique<MockRenderWidget>(render_widget_id, delegate); |
+ } |
+}; |
+ |
+class BlimpContentsImplTest : public testing::Test { |
+ public: |
+ BlimpContentsImplTest() : widget1_(nullptr), widget2_(nullptr) {} |
+ |
+ void SetUpBlimpContents(bool use_internal_display) { |
+ CompositorDepsProvider::Initialize(use_internal_display); |
+ image_serialization_processor_ = |
+ base::MakeUnique<BlobImageSerializationProcessor>(); |
+ blimp_contents_ = base::MakeUnique<BlimpContentsImplForTesting>( |
+ kDummyTabId, &render_widget_feature_); |
+ } |
+ |
+ void SetUpWidgets() { |
+ blimp_contents_->OnRenderWidgetCreated(1); |
+ blimp_contents_->OnRenderWidgetCreated(2); |
+ |
+ widget1_ = |
+ static_cast<MockRenderWidget*>(blimp_contents_->GetWidgetForId(1)); |
+ widget2_ = |
+ static_cast<MockRenderWidget*>(blimp_contents_->GetWidgetForId(2)); |
+ |
+ EXPECT_NE(nullptr, widget1_); |
+ EXPECT_NE(nullptr, widget2_); |
+ } |
+ |
+ void TearDown() override { |
+ blimp_contents_.reset(); |
+ CompositorDepsProvider::Terminate(); |
+ image_serialization_processor_.reset(); |
+ widget1_ = nullptr; |
+ widget2_ = nullptr; |
+ } |
+ |
+ base::MessageLoop loop_; |
+ std::unique_ptr<BlimpContentsImpl> blimp_contents_; |
+ std::unique_ptr<BlobImageSerializationProcessor> |
+ image_serialization_processor_; |
+ MockRenderWidgetFeature render_widget_feature_; |
+ |
+ MockRenderWidget* widget1_; |
+ MockRenderWidget* widget2_; |
+}; |
+ |
+TEST_F(BlimpContentsImplTest, LoadURLAndNotifyObservers) { |
+ SetUpBlimpContents(true); |
BlimpNavigationControllerImpl& navigation_controller = |
- blimp_contents.GetNavigationController(); |
+ blimp_contents_->GetNavigationController(); |
FakeNavigationFeature feature; |
feature.SetDelegate(1, &navigation_controller); |
navigation_controller.SetNavigationFeatureForTesting(&feature); |
- testing::StrictMock<MockBlimpContentsObserver> observer1(&blimp_contents); |
- testing::StrictMock<MockBlimpContentsObserver> observer2(&blimp_contents); |
+ testing::StrictMock<MockBlimpContentsObserver> observer1( |
+ blimp_contents_.get()); |
+ testing::StrictMock<MockBlimpContentsObserver> observer2( |
+ blimp_contents_.get()); |
EXPECT_CALL(observer1, OnNavigationStateChanged()); |
EXPECT_CALL(observer2, OnNavigationStateChanged()).Times(2); |
navigation_controller.LoadURL(GURL(kExampleURL)); |
- loop.RunUntilIdle(); |
+ loop_.RunUntilIdle(); |
EXPECT_EQ(kExampleURL, navigation_controller.GetURL().spec()); |
// Observer should no longer receive callbacks. |
- blimp_contents.RemoveObserver(&observer1); |
+ blimp_contents_->RemoveObserver(&observer1); |
navigation_controller.LoadURL(GURL(kOtherExampleURL)); |
- loop.RunUntilIdle(); |
+ loop_.RunUntilIdle(); |
EXPECT_EQ(kOtherExampleURL, navigation_controller.GetURL().spec()); |
} |
+TEST_F(BlimpContentsImplTest, ForwardsMessagesToCorrectWidget) { |
+ SetUpBlimpContents(true); |
+ SetUpWidgets(); |
+ |
+ // Ensure that the compositor messages for a render widget are forwarded to |
+ // the correct blimp render widget. |
+ EXPECT_CALL(*widget1_, MockableOnCompositorMessageReceived(_)).Times(2); |
+ EXPECT_CALL(*widget2_, MockableOnCompositorMessageReceived(_)).Times(1); |
+ EXPECT_CALL(*widget1_, SetVisible(false)).Times(1); |
+ EXPECT_CALL(*widget1_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)) |
+ .Times(1); |
+ |
+ blimp_contents_->OnCompositorMessageReceived( |
+ widget1_->GetId(), base::WrapUnique(new cc::proto::CompositorMessage)); |
+ blimp_contents_->OnRenderWidgetInitialized(widget1_->GetId()); |
+ EXPECT_EQ(widget1_, blimp_contents_->GetActiveWidget()); |
+ |
+ blimp_contents_->OnCompositorMessageReceived( |
+ widget1_->GetId(), base::WrapUnique(new cc::proto::CompositorMessage)); |
+ blimp_contents_->OnCompositorMessageReceived( |
+ widget2_->GetId(), base::WrapUnique(new cc::proto::CompositorMessage)); |
+ |
+ int32_t deleted_id = widget1_->GetId(); |
+ blimp_contents_->OnRenderWidgetDeleted(deleted_id); |
+ EXPECT_EQ(nullptr, blimp_contents_->GetWidgetForId(deleted_id)); |
+} |
+ |
+TEST_F(BlimpContentsImplTest, ForwardsViewEventsToCorrectWidget) { |
+ InSequence sequence; |
+ SetUpBlimpContents(true); |
+ SetUpWidgets(); |
+ |
+ // Called when the first widget is intialized. |
+ EXPECT_CALL(*widget1_, SetVisible(true)); |
+ EXPECT_CALL(*widget1_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)); |
+ |
+ // Called when the second widget is initialized. |
+ EXPECT_CALL(*widget1_, SetVisible(false)); |
+ EXPECT_CALL(*widget1_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)); |
+ EXPECT_CALL(*widget2_, SetVisible(true)); |
+ EXPECT_CALL(*widget2_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)); |
+ |
+ // Called when the visibility is toggled after the second widget is |
+ // initialized. |
+ EXPECT_CALL(*widget2_, SetVisible(false)); |
+ |
+ // Make the BlimpContents visible while we don't have any render widget |
+ // initialized. |
+ blimp_contents_->SetVisible(true); |
+ blimp_contents_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); |
+ |
+ // Initialize the first render widget. This should propagate the visibility |
+ // and the accelerated widget to the corresponding widget. |
+ blimp_contents_->OnRenderWidgetInitialized(widget1_->GetId()); |
+ |
+ // Now initialize the second render widget. This should swap the widget |
+ // and make the first one invisible and release the accelerated widget. |
+ blimp_contents_->OnRenderWidgetInitialized(widget2_->GetId()); |
+ |
+ // Now make the BlimpContents invisible. This should make the current render |
+ // widget invisible. |
+ blimp_contents_->SetVisible(false); |
+ |
+ // Destroy all the widgets. We should not be receiving any calls for the view |
+ // events forwarded after this. |
+ blimp_contents_->OnRenderWidgetDeleted(widget1_->GetId()); |
+ blimp_contents_->OnRenderWidgetDeleted(widget2_->GetId()); |
+ |
+ blimp_contents_->SetVisible(true); |
+} |
+ |
} // namespace |
} // namespace client |
} // namespace blimp |