OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "blimp/client/core/contents/blimp_contents_impl.h" | 5 #include "blimp/client/core/contents/blimp_contents_impl.h" |
6 | 6 |
7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
8 #include "blimp/client/core/contents/blimp_contents_impl.h" | 8 #include "blimp/client/core/compositor/compositor_deps_provider.h" |
9 #include "blimp/client/core/contents/fake_navigation_feature.h" | 9 #include "blimp/client/core/contents/fake_navigation_feature.h" |
| 10 #include "blimp/client/core/render_widget/blimp_render_widget.h" |
| 11 #include "blimp/client/core/render_widget/render_widget_feature.h" |
10 #include "blimp/client/public/contents/blimp_contents_observer.h" | 12 #include "blimp/client/public/contents/blimp_contents_observer.h" |
| 13 #include "cc/proto/compositor_message.pb.h" |
11 #include "testing/gmock/include/gmock/gmock.h" | 14 #include "testing/gmock/include/gmock/gmock.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 #include "third_party/WebKit/public/web/WebInputEvent.h" |
| 17 |
| 18 using testing::_; |
| 19 using testing::InSequence; |
| 20 using testing::Sequence; |
13 | 21 |
14 namespace blimp { | 22 namespace blimp { |
15 namespace client { | 23 namespace client { |
16 namespace { | 24 namespace { |
17 | 25 |
18 const char kExampleURL[] = "https://www.example.com/"; | 26 const char kExampleURL[] = "https://www.example.com/"; |
19 const char kOtherExampleURL[] = "https://www.otherexample.com/"; | 27 const char kOtherExampleURL[] = "https://www.otherexample.com/"; |
20 const int kDummyTabId = 0; | 28 const int kDummyTabId = 0; |
21 | 29 |
22 class MockBlimpContentsObserver : public BlimpContentsObserver { | 30 class MockBlimpContentsObserver : public BlimpContentsObserver { |
23 public: | 31 public: |
24 explicit MockBlimpContentsObserver(BlimpContents* blimp_contents) | 32 explicit MockBlimpContentsObserver(BlimpContents* blimp_contents) |
25 : BlimpContentsObserver(blimp_contents) {} | 33 : BlimpContentsObserver(blimp_contents) {} |
26 ~MockBlimpContentsObserver() override = default; | 34 ~MockBlimpContentsObserver() override = default; |
27 | 35 |
28 MOCK_METHOD0(OnNavigationStateChanged, void()); | 36 MOCK_METHOD0(OnNavigationStateChanged, void()); |
29 | 37 |
30 private: | 38 private: |
31 DISALLOW_COPY_AND_ASSIGN(MockBlimpContentsObserver); | 39 DISALLOW_COPY_AND_ASSIGN(MockBlimpContentsObserver); |
32 }; | 40 }; |
33 | 41 |
34 TEST(BlimpContentsImplTest, LoadURLAndNotifyObservers) { | 42 class MockRenderWidgetFeature : public RenderWidgetFeature { |
35 base::MessageLoop loop; | 43 public: |
36 BlimpContentsImpl blimp_contents(kDummyTabId); | 44 MOCK_METHOD3(SendCompositorMessage, |
| 45 void(const int, const int, const cc::proto::CompositorMessage&)); |
| 46 MOCK_METHOD3(SendInputEvent, |
| 47 void(const int, const int, const blink::WebInputEvent&)); |
| 48 MOCK_METHOD2(SetDelegate, void(int, RenderWidgetFeatureDelegate*)); |
| 49 MOCK_METHOD1(RemoveDelegate, void(const int)); |
| 50 }; |
| 51 |
| 52 class MockRenderWidget : public BlimpRenderWidget { |
| 53 public: |
| 54 MockRenderWidget(int32_t render_widget_id, |
| 55 BlimpRenderWidgetDelegate* delegate) |
| 56 : BlimpRenderWidget(render_widget_id, delegate) {} |
| 57 |
| 58 MOCK_METHOD1(SetVisible, void(bool)); |
| 59 MOCK_METHOD1(SetAcceleratedWidget, void(gfx::AcceleratedWidget)); |
| 60 |
| 61 void OnCompositorMessageReceived( |
| 62 std::unique_ptr<cc::proto::CompositorMessage> message) override { |
| 63 MockableOnCompositorMessageReceived(*message); |
| 64 } |
| 65 MOCK_METHOD1(MockableOnCompositorMessageReceived, |
| 66 void(const cc::proto::CompositorMessage&)); |
| 67 }; |
| 68 |
| 69 class BlimpContentsImplForTesting : public BlimpContentsImpl { |
| 70 public: |
| 71 BlimpContentsImplForTesting(int id, |
| 72 RenderWidgetFeature* render_widget_feature) |
| 73 : BlimpContentsImpl(id, render_widget_feature) {} |
| 74 |
| 75 protected: |
| 76 std::unique_ptr<BlimpRenderWidget> CreateBlimpRenderWidget( |
| 77 int32_t render_widget_id, |
| 78 BlimpRenderWidgetDelegate* delegate) override { |
| 79 return base::MakeUnique<MockRenderWidget>(render_widget_id, delegate); |
| 80 } |
| 81 }; |
| 82 |
| 83 class BlimpContentsImplTest : public testing::Test { |
| 84 public: |
| 85 BlimpContentsImplTest() : widget1_(nullptr), widget2_(nullptr) {} |
| 86 |
| 87 void SetUpBlimpContents(bool use_internal_display) { |
| 88 CompositorDepsProvider::Initialize(use_internal_display); |
| 89 image_serialization_processor_ = |
| 90 base::MakeUnique<BlobImageSerializationProcessor>(); |
| 91 blimp_contents_ = base::MakeUnique<BlimpContentsImplForTesting>( |
| 92 kDummyTabId, &render_widget_feature_); |
| 93 } |
| 94 |
| 95 void SetUpWidgets() { |
| 96 blimp_contents_->OnRenderWidgetCreated(1); |
| 97 blimp_contents_->OnRenderWidgetCreated(2); |
| 98 |
| 99 widget1_ = |
| 100 static_cast<MockRenderWidget*>(blimp_contents_->GetWidgetForId(1)); |
| 101 widget2_ = |
| 102 static_cast<MockRenderWidget*>(blimp_contents_->GetWidgetForId(2)); |
| 103 |
| 104 EXPECT_NE(nullptr, widget1_); |
| 105 EXPECT_NE(nullptr, widget2_); |
| 106 } |
| 107 |
| 108 void TearDown() override { |
| 109 blimp_contents_.reset(); |
| 110 CompositorDepsProvider::Terminate(); |
| 111 image_serialization_processor_.reset(); |
| 112 widget1_ = nullptr; |
| 113 widget2_ = nullptr; |
| 114 } |
| 115 |
| 116 base::MessageLoop loop_; |
| 117 std::unique_ptr<BlimpContentsImpl> blimp_contents_; |
| 118 std::unique_ptr<BlobImageSerializationProcessor> |
| 119 image_serialization_processor_; |
| 120 MockRenderWidgetFeature render_widget_feature_; |
| 121 |
| 122 MockRenderWidget* widget1_; |
| 123 MockRenderWidget* widget2_; |
| 124 }; |
| 125 |
| 126 TEST_F(BlimpContentsImplTest, LoadURLAndNotifyObservers) { |
| 127 SetUpBlimpContents(true); |
37 | 128 |
38 BlimpNavigationControllerImpl& navigation_controller = | 129 BlimpNavigationControllerImpl& navigation_controller = |
39 blimp_contents.GetNavigationController(); | 130 blimp_contents_->GetNavigationController(); |
40 FakeNavigationFeature feature; | 131 FakeNavigationFeature feature; |
41 feature.SetDelegate(1, &navigation_controller); | 132 feature.SetDelegate(1, &navigation_controller); |
42 navigation_controller.SetNavigationFeatureForTesting(&feature); | 133 navigation_controller.SetNavigationFeatureForTesting(&feature); |
43 | 134 |
44 testing::StrictMock<MockBlimpContentsObserver> observer1(&blimp_contents); | 135 testing::StrictMock<MockBlimpContentsObserver> observer1( |
45 testing::StrictMock<MockBlimpContentsObserver> observer2(&blimp_contents); | 136 blimp_contents_.get()); |
| 137 testing::StrictMock<MockBlimpContentsObserver> observer2( |
| 138 blimp_contents_.get()); |
46 | 139 |
47 EXPECT_CALL(observer1, OnNavigationStateChanged()); | 140 EXPECT_CALL(observer1, OnNavigationStateChanged()); |
48 EXPECT_CALL(observer2, OnNavigationStateChanged()).Times(2); | 141 EXPECT_CALL(observer2, OnNavigationStateChanged()).Times(2); |
49 | 142 |
50 navigation_controller.LoadURL(GURL(kExampleURL)); | 143 navigation_controller.LoadURL(GURL(kExampleURL)); |
51 loop.RunUntilIdle(); | 144 loop_.RunUntilIdle(); |
52 | 145 |
53 EXPECT_EQ(kExampleURL, navigation_controller.GetURL().spec()); | 146 EXPECT_EQ(kExampleURL, navigation_controller.GetURL().spec()); |
54 | 147 |
55 // Observer should no longer receive callbacks. | 148 // Observer should no longer receive callbacks. |
56 blimp_contents.RemoveObserver(&observer1); | 149 blimp_contents_->RemoveObserver(&observer1); |
57 | 150 |
58 navigation_controller.LoadURL(GURL(kOtherExampleURL)); | 151 navigation_controller.LoadURL(GURL(kOtherExampleURL)); |
59 loop.RunUntilIdle(); | 152 loop_.RunUntilIdle(); |
60 | 153 |
61 EXPECT_EQ(kOtherExampleURL, navigation_controller.GetURL().spec()); | 154 EXPECT_EQ(kOtherExampleURL, navigation_controller.GetURL().spec()); |
62 } | 155 } |
63 | 156 |
| 157 TEST_F(BlimpContentsImplTest, ForwardsMessagesToCorrectWidget) { |
| 158 SetUpBlimpContents(true); |
| 159 SetUpWidgets(); |
| 160 |
| 161 // Ensure that the compositor messages for a render widget are forwarded to |
| 162 // the correct blimp render widget. |
| 163 EXPECT_CALL(*widget1_, MockableOnCompositorMessageReceived(_)).Times(2); |
| 164 EXPECT_CALL(*widget2_, MockableOnCompositorMessageReceived(_)).Times(1); |
| 165 EXPECT_CALL(*widget1_, SetVisible(false)).Times(1); |
| 166 EXPECT_CALL(*widget1_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)) |
| 167 .Times(1); |
| 168 |
| 169 blimp_contents_->OnCompositorMessageReceived( |
| 170 widget1_->GetId(), base::WrapUnique(new cc::proto::CompositorMessage)); |
| 171 blimp_contents_->OnRenderWidgetInitialized(widget1_->GetId()); |
| 172 EXPECT_EQ(widget1_, blimp_contents_->GetActiveWidget()); |
| 173 |
| 174 blimp_contents_->OnCompositorMessageReceived( |
| 175 widget1_->GetId(), base::WrapUnique(new cc::proto::CompositorMessage)); |
| 176 blimp_contents_->OnCompositorMessageReceived( |
| 177 widget2_->GetId(), base::WrapUnique(new cc::proto::CompositorMessage)); |
| 178 |
| 179 int32_t deleted_id = widget1_->GetId(); |
| 180 blimp_contents_->OnRenderWidgetDeleted(deleted_id); |
| 181 EXPECT_EQ(nullptr, blimp_contents_->GetWidgetForId(deleted_id)); |
| 182 } |
| 183 |
| 184 TEST_F(BlimpContentsImplTest, ForwardsViewEventsToCorrectWidget) { |
| 185 InSequence sequence; |
| 186 SetUpBlimpContents(true); |
| 187 SetUpWidgets(); |
| 188 |
| 189 // Called when the first widget is intialized. |
| 190 EXPECT_CALL(*widget1_, SetVisible(true)); |
| 191 EXPECT_CALL(*widget1_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)); |
| 192 |
| 193 // Called when the second widget is initialized. |
| 194 EXPECT_CALL(*widget1_, SetVisible(false)); |
| 195 EXPECT_CALL(*widget1_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)); |
| 196 EXPECT_CALL(*widget2_, SetVisible(true)); |
| 197 EXPECT_CALL(*widget2_, SetAcceleratedWidget(gfx::kNullAcceleratedWidget)); |
| 198 |
| 199 // Called when the visibility is toggled after the second widget is |
| 200 // initialized. |
| 201 EXPECT_CALL(*widget2_, SetVisible(false)); |
| 202 |
| 203 // Make the BlimpContents visible while we don't have any render widget |
| 204 // initialized. |
| 205 blimp_contents_->SetVisible(true); |
| 206 blimp_contents_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); |
| 207 |
| 208 // Initialize the first render widget. This should propagate the visibility |
| 209 // and the accelerated widget to the corresponding widget. |
| 210 blimp_contents_->OnRenderWidgetInitialized(widget1_->GetId()); |
| 211 |
| 212 // Now initialize the second render widget. This should swap the widget |
| 213 // and make the first one invisible and release the accelerated widget. |
| 214 blimp_contents_->OnRenderWidgetInitialized(widget2_->GetId()); |
| 215 |
| 216 // Now make the BlimpContents invisible. This should make the current render |
| 217 // widget invisible. |
| 218 blimp_contents_->SetVisible(false); |
| 219 |
| 220 // Destroy all the widgets. We should not be receiving any calls for the view |
| 221 // events forwarded after this. |
| 222 blimp_contents_->OnRenderWidgetDeleted(widget1_->GetId()); |
| 223 blimp_contents_->OnRenderWidgetDeleted(widget2_->GetId()); |
| 224 |
| 225 blimp_contents_->SetVisible(true); |
| 226 } |
| 227 |
64 } // namespace | 228 } // namespace |
65 } // namespace client | 229 } // namespace client |
66 } // namespace blimp | 230 } // namespace blimp |
OLD | NEW |