| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "blimp/engine/feature/engine_render_widget_feature.h" | |
| 6 | |
| 7 #include <memory> | |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "base/memory/ptr_util.h" | |
| 11 #include "base/numerics/safe_conversions.h" | |
| 12 #include "base/strings/utf_string_conversions.h" | |
| 13 #include "blimp/common/create_blimp_message.h" | |
| 14 #include "blimp/common/proto/blimp_message.pb.h" | |
| 15 #include "blimp/common/proto/compositor.pb.h" | |
| 16 #include "blimp/common/proto/render_widget.pb.h" | |
| 17 #include "blimp/net/input_message_generator.h" | |
| 18 #include "blimp/net/test_common.h" | |
| 19 #include "content/public/browser/render_widget_host.h" | |
| 20 #include "content/public/common/form_field_data.h" | |
| 21 #include "net/base/net_errors.h" | |
| 22 #include "net/base/test_completion_callback.h" | |
| 23 #include "testing/gmock/include/gmock/gmock.h" | |
| 24 #include "testing/gtest/include/gtest/gtest.h" | |
| 25 #include "third_party/WebKit/public/platform/WebInputEvent.h" | |
| 26 #include "ui/base/ime/dummy_text_input_client.h" | |
| 27 | |
| 28 using testing::_; | |
| 29 using testing::InSequence; | |
| 30 using testing::Sequence; | |
| 31 | |
| 32 namespace blimp { | |
| 33 namespace engine { | |
| 34 | |
| 35 namespace { | |
| 36 | |
| 37 class MockHostRenderWidgetMessageDelegate | |
| 38 : public EngineRenderWidgetFeature::RenderWidgetMessageDelegate { | |
| 39 public: | |
| 40 // EngineRenderWidgetFeature implementation. | |
| 41 void OnWebGestureEvent( | |
| 42 content::RenderWidgetHost* render_widget_host, | |
| 43 std::unique_ptr<blink::WebGestureEvent> event) override { | |
| 44 MockableOnWebGestureEvent(render_widget_host); | |
| 45 } | |
| 46 | |
| 47 void OnCompositorMessageReceived( | |
| 48 content::RenderWidgetHost* render_widget_host, | |
| 49 const std::vector<uint8_t>& message) override { | |
| 50 MockableOnCompositorMessageReceived(render_widget_host, message); | |
| 51 } | |
| 52 | |
| 53 MOCK_METHOD1(MockableOnWebGestureEvent, | |
| 54 void(content::RenderWidgetHost* render_widget_host)); | |
| 55 MOCK_METHOD2(MockableOnCompositorMessageReceived, | |
| 56 void(content::RenderWidgetHost* render_widget_host, | |
| 57 const std::vector<uint8_t>& message)); | |
| 58 }; | |
| 59 | |
| 60 class MockRenderWidgetHost | |
| 61 : public content::RenderWidgetHost { | |
| 62 public: | |
| 63 MockRenderWidgetHost() {} | |
| 64 ~MockRenderWidgetHost() override {} | |
| 65 void UpdateTextDirection(blink::WebTextDirection direction) override {} | |
| 66 void NotifyTextDirection() override {} | |
| 67 void Focus() override {} | |
| 68 void Blur() override {} | |
| 69 void SetActive(bool active) override {} | |
| 70 void CopyFromBackingStore(const gfx::Rect& src_rect, | |
| 71 const gfx::Size& accelerated_dst_size, | |
| 72 const content::ReadbackRequestCallback& callback, | |
| 73 const SkColorType color_type) override {} | |
| 74 bool CanCopyFromBackingStore() override { return false; } | |
| 75 void LockBackingStore() override {} | |
| 76 void UnlockBackingStore() override {} | |
| 77 void ForwardMouseEvent( | |
| 78 const blink::WebMouseEvent& mouse_event) override {} | |
| 79 void ForwardWheelEvent( | |
| 80 const blink::WebMouseWheelEvent& wheel_event) override {} | |
| 81 void ForwardKeyboardEvent( | |
| 82 const content::NativeWebKeyboardEvent& key_event) override {} | |
| 83 void ForwardGestureEvent( | |
| 84 const blink::WebGestureEvent& gesture_event) override {} | |
| 85 content::RenderProcessHost* GetProcess() const override { return nullptr; } | |
| 86 int GetRoutingID() const override { return 0; } | |
| 87 content::RenderWidgetHostView* GetView() const override { return nullptr; } | |
| 88 bool IsLoading() const override { return false; } | |
| 89 void RestartHangMonitorTimeoutIfNecessary() override {} | |
| 90 void DisableHangMonitorForTesting() override {} | |
| 91 void SetIgnoreInputEvents(bool ignore_input_events) override {} | |
| 92 void WasResized() override {} | |
| 93 void AddKeyPressEventCallback( | |
| 94 const KeyPressEventCallback& callback) override {} | |
| 95 void RemoveKeyPressEventCallback( | |
| 96 const KeyPressEventCallback& callback) override {} | |
| 97 void AddMouseEventCallback(const MouseEventCallback& callback) override {} | |
| 98 void RemoveMouseEventCallback(const MouseEventCallback& callback) override {} | |
| 99 void AddInputEventObserver(InputEventObserver* observer) override {} | |
| 100 void RemoveInputEventObserver(InputEventObserver* observer) override {} | |
| 101 void GetScreenInfo(content::ScreenInfo* result) override {} | |
| 102 void HandleCompositorProto(const std::vector<uint8_t>& proto) override {} | |
| 103 | |
| 104 bool Send(IPC::Message* msg) override { return false; } | |
| 105 }; | |
| 106 | |
| 107 class MockTextInputClient : public ui::DummyTextInputClient { | |
| 108 public: | |
| 109 MockTextInputClient() : DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT) {} | |
| 110 | |
| 111 bool GetTextFromRange(const gfx::Range& range, | |
| 112 base::string16* text) const override { | |
| 113 *text = base::string16(base::ASCIIToUTF16("green apple")); | |
| 114 return false; | |
| 115 } | |
| 116 }; | |
| 117 | |
| 118 MATCHER_P(CompMsgEquals, contents, "") { | |
| 119 if (contents.size() != arg.size()) | |
| 120 return false; | |
| 121 | |
| 122 return memcmp(contents.data(), arg.data(), contents.size()) == 0; | |
| 123 } | |
| 124 | |
| 125 MATCHER_P3(BlimpCompMsgEquals, tab_id, rw_id, contents, "") { | |
| 126 if (contents.size() != arg.compositor().payload().size()) | |
| 127 return false; | |
| 128 | |
| 129 if (memcmp(contents.data(), | |
| 130 arg.compositor().payload().data(), | |
| 131 contents.size()) != 0) { | |
| 132 return false; | |
| 133 } | |
| 134 | |
| 135 return arg.compositor().render_widget_id() == rw_id && | |
| 136 arg.target_tab_id() == tab_id; | |
| 137 } | |
| 138 | |
| 139 MATCHER_P3(BlimpRWMsgEquals, tab_id, rw_id, message_type, "") { | |
| 140 return arg.render_widget().render_widget_id() == rw_id && | |
| 141 arg.target_tab_id() == tab_id && | |
| 142 arg.render_widget().type() == message_type; | |
| 143 } | |
| 144 | |
| 145 MATCHER_P2(BlimpImeMsgEquals, tab_id, message_type, "") { | |
| 146 return arg.target_tab_id() == tab_id && arg.ime().type() == message_type; | |
| 147 } | |
| 148 | |
| 149 MATCHER_P5(BlimpImeMsgEquals, | |
| 150 tab_id, | |
| 151 rwid, | |
| 152 message_type, | |
| 153 text, | |
| 154 text_input_type, | |
| 155 "") { | |
| 156 return arg.target_tab_id() == tab_id && | |
| 157 arg.ime().render_widget_id() == rwid && | |
| 158 arg.ime().type() == message_type && | |
| 159 arg.ime().ime_text().compare(text) == 0 && | |
| 160 arg.ime().text_input_type() == text_input_type; | |
| 161 } | |
| 162 | |
| 163 void SendInputMessage(BlimpMessageProcessor* processor, | |
| 164 int tab_id, | |
| 165 int rw_id) { | |
| 166 blink::WebGestureEvent input_event(blink::WebGestureEvent::Type::GestureTap, | |
| 167 blink::WebInputEvent::NoModifiers, | |
| 168 blink::WebInputEvent::TimeStampForTesting); | |
| 169 | |
| 170 InputMessageGenerator generator; | |
| 171 std::unique_ptr<BlimpMessage> message = | |
| 172 generator.GenerateMessage(input_event); | |
| 173 message->set_target_tab_id(tab_id); | |
| 174 message->mutable_input()->set_render_widget_id(rw_id); | |
| 175 | |
| 176 net::TestCompletionCallback cb; | |
| 177 processor->ProcessMessage(std::move(message), cb.callback()); | |
| 178 EXPECT_EQ(net::OK, cb.WaitForResult()); | |
| 179 } | |
| 180 | |
| 181 void SendCompositorMessage(BlimpMessageProcessor* processor, | |
| 182 int tab_id, | |
| 183 int rw_id, | |
| 184 const std::vector<uint8_t>& payload) { | |
| 185 CompositorMessage* details; | |
| 186 std::unique_ptr<BlimpMessage> message = CreateBlimpMessage(&details, tab_id); | |
| 187 details->set_render_widget_id(rw_id); | |
| 188 details->set_payload(payload.data(), base::checked_cast<int>(payload.size())); | |
| 189 net::TestCompletionCallback cb; | |
| 190 processor->ProcessMessage(std::move(message), cb.callback()); | |
| 191 EXPECT_EQ(net::OK, cb.WaitForResult()); | |
| 192 } | |
| 193 | |
| 194 } // namespace | |
| 195 | |
| 196 class EngineRenderWidgetFeatureTest : public testing::Test { | |
| 197 public: | |
| 198 EngineRenderWidgetFeatureTest() : feature_(&settings_) {} | |
| 199 | |
| 200 void SetUp() override { | |
| 201 render_widget_message_sender_ = new MockBlimpMessageProcessor; | |
| 202 feature_.set_render_widget_message_sender( | |
| 203 base::WrapUnique(render_widget_message_sender_)); | |
| 204 compositor_message_sender_ = new MockBlimpMessageProcessor; | |
| 205 feature_.set_compositor_message_sender( | |
| 206 base::WrapUnique(compositor_message_sender_)); | |
| 207 ime_message_sender_ = new MockBlimpMessageProcessor; | |
| 208 feature_.set_ime_message_sender(base::WrapUnique(ime_message_sender_)); | |
| 209 feature_.SetDelegate(1, &delegate1_); | |
| 210 feature_.SetDelegate(2, &delegate2_); | |
| 211 } | |
| 212 | |
| 213 protected: | |
| 214 MockBlimpMessageProcessor* render_widget_message_sender_; | |
| 215 MockBlimpMessageProcessor* compositor_message_sender_; | |
| 216 MockBlimpMessageProcessor* ime_message_sender_; | |
| 217 MockRenderWidgetHost render_widget_host1_; | |
| 218 MockRenderWidgetHost render_widget_host2_; | |
| 219 MockHostRenderWidgetMessageDelegate delegate1_; | |
| 220 MockHostRenderWidgetMessageDelegate delegate2_; | |
| 221 MockTextInputClient text_input_client_; | |
| 222 SettingsManager settings_; | |
| 223 EngineRenderWidgetFeature feature_; | |
| 224 }; | |
| 225 | |
| 226 TEST_F(EngineRenderWidgetFeatureTest, DelegateCallsOK) { | |
| 227 std::vector<uint8_t> payload = { 'd', 'a', 'v', 'i', 'd' }; | |
| 228 | |
| 229 EXPECT_CALL(*render_widget_message_sender_, MockableProcessMessage( | |
| 230 BlimpRWMsgEquals(1, 1, RenderWidgetMessage::CREATED), _)) | |
| 231 .Times(1); | |
| 232 EXPECT_CALL(*render_widget_message_sender_, MockableProcessMessage( | |
| 233 BlimpRWMsgEquals(1, 1, RenderWidgetMessage::INITIALIZE), _)) | |
| 234 .Times(1); | |
| 235 EXPECT_CALL(*render_widget_message_sender_, MockableProcessMessage( | |
| 236 BlimpRWMsgEquals(2, 2, RenderWidgetMessage::CREATED), _)) | |
| 237 .Times(1); | |
| 238 | |
| 239 EXPECT_CALL(delegate1_, | |
| 240 MockableOnCompositorMessageReceived(&render_widget_host1_, | |
| 241 CompMsgEquals(payload))) | |
| 242 .Times(1); | |
| 243 EXPECT_CALL(delegate1_, MockableOnWebGestureEvent(&render_widget_host1_)) | |
| 244 .Times(1); | |
| 245 EXPECT_CALL(delegate2_, | |
| 246 MockableOnCompositorMessageReceived(&render_widget_host2_, | |
| 247 CompMsgEquals(payload))) | |
| 248 .Times(1); | |
| 249 | |
| 250 feature_.OnRenderWidgetCreated(1, &render_widget_host1_); | |
| 251 feature_.OnRenderWidgetInitialized(1, &render_widget_host1_); | |
| 252 feature_.OnRenderWidgetCreated(2, &render_widget_host2_); | |
| 253 SendCompositorMessage(&feature_, 1, 1, payload); | |
| 254 SendInputMessage(&feature_, 1, 1); | |
| 255 SendCompositorMessage(&feature_, 2, 2, payload); | |
| 256 } | |
| 257 | |
| 258 TEST_F(EngineRenderWidgetFeatureTest, ImeRequestSentCorrectly) { | |
| 259 EXPECT_CALL( | |
| 260 *ime_message_sender_, | |
| 261 MockableProcessMessage(BlimpImeMsgEquals(2, 1, ImeMessage::SHOW_IME, | |
| 262 std::string("green apple"), 1), | |
| 263 _)); | |
| 264 | |
| 265 EXPECT_CALL( | |
| 266 *ime_message_sender_, | |
| 267 MockableProcessMessage(BlimpImeMsgEquals(2, ImeMessage::HIDE_IME), _)); | |
| 268 | |
| 269 content::FormFieldData field; | |
| 270 field.text = "green apple"; | |
| 271 field.placeholder = "fruit name"; | |
| 272 field.text_input_type = ui::TEXT_INPUT_TYPE_TEXT; | |
| 273 | |
| 274 feature_.OnRenderWidgetCreated(2, &render_widget_host1_); | |
| 275 feature_.SendShowImeRequest(2, &render_widget_host1_, field); | |
| 276 feature_.SendHideImeRequest(2, &render_widget_host1_); | |
| 277 } | |
| 278 | |
| 279 TEST_F(EngineRenderWidgetFeatureTest, DropsStaleMessages) { | |
| 280 InSequence sequence; | |
| 281 std::vector<uint8_t> payload = { 'f', 'u', 'n' }; | |
| 282 std::vector<uint8_t> new_payload = {'n', 'o', ' ', 'f', 'u', 'n'}; | |
| 283 | |
| 284 EXPECT_CALL(*render_widget_message_sender_, | |
| 285 MockableProcessMessage( | |
| 286 BlimpRWMsgEquals(1, 1, RenderWidgetMessage::CREATED), _)); | |
| 287 EXPECT_CALL(delegate1_, | |
| 288 MockableOnCompositorMessageReceived(&render_widget_host1_, | |
| 289 CompMsgEquals(payload))); | |
| 290 EXPECT_CALL(*render_widget_message_sender_, | |
| 291 MockableProcessMessage( | |
| 292 BlimpRWMsgEquals(1, 1, RenderWidgetMessage::DELETED), _)); | |
| 293 EXPECT_CALL(*render_widget_message_sender_, | |
| 294 MockableProcessMessage( | |
| 295 BlimpRWMsgEquals(1, 2, RenderWidgetMessage::CREATED), _)); | |
| 296 | |
| 297 EXPECT_CALL(delegate1_, | |
| 298 MockableOnCompositorMessageReceived(&render_widget_host2_, | |
| 299 CompMsgEquals(new_payload))); | |
| 300 EXPECT_CALL(delegate1_, MockableOnWebGestureEvent(&render_widget_host2_)); | |
| 301 | |
| 302 feature_.OnRenderWidgetCreated(1, &render_widget_host1_); | |
| 303 SendCompositorMessage(&feature_, 1, 1, payload); | |
| 304 feature_.OnRenderWidgetDeleted(1, &render_widget_host1_); | |
| 305 feature_.OnRenderWidgetCreated(1, &render_widget_host2_); | |
| 306 | |
| 307 // These next three calls should be dropped. | |
| 308 SendCompositorMessage(&feature_, 1, 1, payload); | |
| 309 SendCompositorMessage(&feature_, 1, 1, payload); | |
| 310 SendInputMessage(&feature_, 1, 1); | |
| 311 | |
| 312 SendCompositorMessage(&feature_, 1, 2, new_payload); | |
| 313 SendInputMessage(&feature_, 1, 2); | |
| 314 } | |
| 315 | |
| 316 TEST_F(EngineRenderWidgetFeatureTest, RepliesHaveCorrectRenderWidgetId) { | |
| 317 Sequence delegate1_sequence; | |
| 318 Sequence delegate2_sequence; | |
| 319 std::vector<uint8_t> payload = { 'a', 'b', 'c', 'd' }; | |
| 320 | |
| 321 EXPECT_CALL(*render_widget_message_sender_, | |
| 322 MockableProcessMessage( | |
| 323 BlimpRWMsgEquals(1, 1, RenderWidgetMessage::CREATED), _)) | |
| 324 .InSequence(delegate1_sequence); | |
| 325 EXPECT_CALL(*render_widget_message_sender_, | |
| 326 MockableProcessMessage( | |
| 327 BlimpRWMsgEquals(1, 1, RenderWidgetMessage::INITIALIZE), _)) | |
| 328 .InSequence(delegate1_sequence); | |
| 329 EXPECT_CALL(*compositor_message_sender_, | |
| 330 MockableProcessMessage(BlimpCompMsgEquals(1, 1, payload), _)) | |
| 331 .InSequence(delegate1_sequence); | |
| 332 | |
| 333 EXPECT_CALL(*render_widget_message_sender_, | |
| 334 MockableProcessMessage( | |
| 335 BlimpRWMsgEquals(2, 2, RenderWidgetMessage::CREATED), _)) | |
| 336 .InSequence(delegate2_sequence); | |
| 337 EXPECT_CALL(*render_widget_message_sender_, | |
| 338 MockableProcessMessage( | |
| 339 BlimpRWMsgEquals(2, 2, RenderWidgetMessage::DELETED), _)) | |
| 340 .InSequence(delegate2_sequence); | |
| 341 | |
| 342 feature_.OnRenderWidgetCreated(1, &render_widget_host1_); | |
| 343 feature_.OnRenderWidgetCreated(2, &render_widget_host2_); | |
| 344 feature_.OnRenderWidgetInitialized(1, &render_widget_host1_); | |
| 345 feature_.OnRenderWidgetDeleted(2, &render_widget_host2_); | |
| 346 feature_.SendCompositorMessage(1, &render_widget_host1_, payload); | |
| 347 } | |
| 348 | |
| 349 } // namespace engine | |
| 350 } // namespace blimp | |
| OLD | NEW |