OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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 "content/browser/renderer_host/input/touch_selection_controller_client_
aura.h" | 5 #include "content/browser/renderer_host/input/touch_selection_controller_client_
aura.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
11 #include "base/run_loop.h" | 11 #include "base/run_loop.h" |
| 12 #include "base/test/test_timeouts.h" |
| 13 #include "content/browser/frame_host/render_widget_host_view_child_frame.h" |
12 #include "content/browser/renderer_host/render_widget_host_view_aura.h" | 14 #include "content/browser/renderer_host/render_widget_host_view_aura.h" |
13 #include "content/browser/renderer_host/render_widget_host_view_event_handler.h" | 15 #include "content/browser/renderer_host/render_widget_host_view_event_handler.h" |
14 #include "content/browser/web_contents/web_contents_impl.h" | 16 #include "content/browser/web_contents/web_contents_impl.h" |
15 #include "content/public/test/browser_test_utils.h" | 17 #include "content/public/test/browser_test_utils.h" |
16 #include "content/public/test/content_browser_test.h" | 18 #include "content/public/test/content_browser_test.h" |
17 #include "content/public/test/content_browser_test_utils.h" | 19 #include "content/public/test/content_browser_test_utils.h" |
| 20 #include "content/public/test/test_navigation_observer.h" |
| 21 #include "content/public/test/test_utils.h" |
18 #include "content/shell/browser/shell.h" | 22 #include "content/shell/browser/shell.h" |
| 23 #include "content/test/content_browser_test_utils_internal.h" |
| 24 #include "net/dns/mock_host_resolver.h" |
| 25 #include "net/test/embedded_test_server/embedded_test_server.h" |
19 #include "ui/aura/window.h" | 26 #include "ui/aura/window.h" |
20 #include "ui/aura/window_tree_host.h" | 27 #include "ui/aura/window_tree_host.h" |
21 #include "ui/display/display_switches.h" | 28 #include "ui/display/display_switches.h" |
22 #include "ui/events/event_utils.h" | 29 #include "ui/events/event_utils.h" |
23 #include "ui/events/test/event_generator.h" | 30 #include "ui/events/test/event_generator.h" |
24 #include "ui/touch_selection/touch_selection_controller_test_api.h" | 31 #include "ui/touch_selection/touch_selection_controller_test_api.h" |
25 | 32 |
26 namespace content { | 33 namespace content { |
27 namespace { | 34 namespace { |
28 | 35 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 | 170 |
164 void InitSelectionController() { | 171 void InitSelectionController() { |
165 RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura(); | 172 RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura(); |
166 selection_controller_client_ = | 173 selection_controller_client_ = |
167 new TestTouchSelectionControllerClientAura(rwhva); | 174 new TestTouchSelectionControllerClientAura(rwhva); |
168 rwhva->SetSelectionControllerClientForTest( | 175 rwhva->SetSelectionControllerClientForTest( |
169 base::WrapUnique(selection_controller_client_)); | 176 base::WrapUnique(selection_controller_client_)); |
170 rwhva->event_handler()->disable_input_event_router_for_testing(); | 177 rwhva->event_handler()->disable_input_event_router_for_testing(); |
171 } | 178 } |
172 | 179 |
173 private: | 180 protected: |
174 void SetUpOnMainThread() override { | 181 void SetUpOnMainThread() override { |
175 ContentBrowserTest::SetUpOnMainThread(); | 182 ContentBrowserTest::SetUpOnMainThread(); |
176 if (!ui::TouchSelectionMenuRunner::GetInstance()) | 183 if (!ui::TouchSelectionMenuRunner::GetInstance()) |
177 menu_runner_.reset(new TestTouchSelectionMenuRunner); | 184 menu_runner_.reset(new TestTouchSelectionMenuRunner); |
178 } | 185 } |
179 | 186 |
| 187 private: |
180 void TearDownOnMainThread() override { | 188 void TearDownOnMainThread() override { |
181 menu_runner_ = nullptr; | 189 menu_runner_ = nullptr; |
182 selection_controller_client_ = nullptr; | 190 selection_controller_client_ = nullptr; |
183 ContentBrowserTest::TearDownOnMainThread(); | 191 ContentBrowserTest::TearDownOnMainThread(); |
184 } | 192 } |
185 | 193 |
186 std::unique_ptr<TestTouchSelectionMenuRunner> menu_runner_; | 194 std::unique_ptr<TestTouchSelectionMenuRunner> menu_runner_; |
187 | 195 |
188 TestTouchSelectionControllerClientAura* selection_controller_client_ = | 196 TestTouchSelectionControllerClientAura* selection_controller_client_ = |
189 nullptr; | 197 nullptr; |
(...skipping 26 matching lines...) Expand all Loading... |
216 rwhva->OnGestureEvent(&long_press); | 224 rwhva->OnGestureEvent(&long_press); |
217 | 225 |
218 selection_controller_client()->Wait(); | 226 selection_controller_client()->Wait(); |
219 | 227 |
220 // Check that selection is active and the quick menu is showing. | 228 // Check that selection is active and the quick menu is showing. |
221 EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE, | 229 EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE, |
222 rwhva->selection_controller()->active_status()); | 230 rwhva->selection_controller()->active_status()); |
223 EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()); | 231 EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()); |
224 } | 232 } |
225 | 233 |
| 234 class TouchSelectionControllerClientAuraSiteIsolationTest |
| 235 : public TouchSelectionControllerClientAuraTest { |
| 236 public: |
| 237 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 238 IsolateAllSitesForTesting(command_line); |
| 239 } |
| 240 |
| 241 void SetUpOnMainThread() override { |
| 242 TouchSelectionControllerClientAuraTest::SetUpOnMainThread(); |
| 243 host_resolver()->AddRule("*", "127.0.0.1"); |
| 244 SetupCrossSiteRedirector(embedded_test_server()); |
| 245 ASSERT_TRUE(embedded_test_server()->Start()); |
| 246 } |
| 247 |
| 248 void SelectWithLongPress(gfx::Point point) { |
| 249 // Get main frame view for event insertion. |
| 250 RenderWidgetHostViewAura* main_view = GetRenderWidgetHostViewAura(); |
| 251 |
| 252 SendTouch(main_view, ui::ET_TOUCH_PRESSED, point); |
| 253 SendTouch(main_view, ui::ET_TOUCH_RELEASED, point); |
| 254 SendGestureTap(main_view, point); |
| 255 SendGestureLongPress(main_view, point); |
| 256 } |
| 257 |
| 258 void SimpleTap(gfx::Point point) { |
| 259 // Get main frame view for event insertion. |
| 260 RenderWidgetHostViewAura* main_view = GetRenderWidgetHostViewAura(); |
| 261 |
| 262 SendTouch(main_view, ui::ET_TOUCH_PRESSED, point); |
| 263 SendTouch(main_view, ui::ET_TOUCH_RELEASED, point); |
| 264 SendGestureTap(main_view, point); |
| 265 } |
| 266 |
| 267 private: |
| 268 void SendTouch(RenderWidgetHostViewAura* view, |
| 269 ui::EventType type, |
| 270 gfx::Point point) { |
| 271 DCHECK(type >= ui::ET_TOUCH_RELEASED && type << ui::ET_TOUCH_CANCELLED); |
| 272 ui::TouchEvent touch( |
| 273 type, point, ui::EventTimeForNow(), |
| 274 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); |
| 275 view->OnTouchEvent(&touch); |
| 276 } |
| 277 |
| 278 void SendGestureTap(RenderWidgetHostViewAura* view, gfx::Point point) { |
| 279 ui::GestureEventDetails tap_down_details(ui::ET_GESTURE_TAP_DOWN); |
| 280 tap_down_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN); |
| 281 ui::GestureEvent gesture_tap_down(point.x(), point.y(), 0, |
| 282 ui::EventTimeForNow(), tap_down_details); |
| 283 view->OnGestureEvent(&gesture_tap_down); |
| 284 ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP); |
| 285 tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN); |
| 286 tap_details.set_tap_count(1); |
| 287 ui::GestureEvent gesture_tap(point.x(), point.y(), 0, ui::EventTimeForNow(), |
| 288 tap_details); |
| 289 view->OnGestureEvent(&gesture_tap); |
| 290 } |
| 291 |
| 292 void SendGestureLongPress(RenderWidgetHostViewAura* view, gfx::Point point) { |
| 293 ui::GestureEventDetails long_press_details(ui::ET_GESTURE_LONG_PRESS); |
| 294 long_press_details.set_device_type( |
| 295 ui::GestureDeviceType::DEVICE_TOUCHSCREEN); |
| 296 ui::GestureEvent gesture_long_press( |
| 297 point.x(), point.y(), 0, ui::EventTimeForNow(), long_press_details); |
| 298 view->OnGestureEvent(&gesture_long_press); |
| 299 } |
| 300 }; |
| 301 |
| 302 class FrameStableObserver { |
| 303 public: |
| 304 FrameStableObserver(RenderWidgetHostViewBase* view, base::TimeDelta delta) |
| 305 : view_(view), delta_(delta) {} |
| 306 virtual ~FrameStableObserver() {} |
| 307 |
| 308 void WaitUntilStable() { |
| 309 uint32_t current_frame_number = view_->RendererFrameNumber(); |
| 310 uint32_t previous_frame_number; |
| 311 |
| 312 do { |
| 313 base::RunLoop run_loop; |
| 314 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 315 FROM_HERE, run_loop.QuitClosure(), delta_); |
| 316 run_loop.Run(); |
| 317 previous_frame_number = current_frame_number; |
| 318 current_frame_number = view_->RendererFrameNumber(); |
| 319 } while (current_frame_number != previous_frame_number); |
| 320 } |
| 321 |
| 322 private: |
| 323 RenderWidgetHostViewBase* view_; |
| 324 base::TimeDelta delta_; |
| 325 |
| 326 DISALLOW_COPY_AND_ASSIGN(FrameStableObserver); |
| 327 }; |
| 328 |
| 329 IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraSiteIsolationTest, |
| 330 BasicSelectionIsolatedIframe) { |
| 331 GURL test_url(embedded_test_server()->GetURL( |
| 332 "a.com", "/cross_site_iframe_factory.html?a(a)")); |
| 333 EXPECT_TRUE(NavigateToURL(shell(), test_url)); |
| 334 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 335 ->GetFrameTree() |
| 336 ->root(); |
| 337 EXPECT_EQ( |
| 338 " Site A\n" |
| 339 " +--Site A\n" |
| 340 "Where A = http://a.com/", |
| 341 FrameTreeVisualizer().DepictFrameTree(root)); |
| 342 TestNavigationObserver observer(shell()->web_contents()); |
| 343 EXPECT_EQ(1u, root->child_count()); |
| 344 FrameTreeNode* child = root->child_at(0); |
| 345 |
| 346 RenderWidgetHostViewAura* parent_view = |
| 347 static_cast<RenderWidgetHostViewAura*>( |
| 348 root->current_frame_host()->GetRenderWidgetHost()->GetView()); |
| 349 TestTouchSelectionControllerClientAura* parent_selection_controller_client = |
| 350 new TestTouchSelectionControllerClientAura(parent_view); |
| 351 parent_view->SetSelectionControllerClientForTest( |
| 352 base::WrapUnique(parent_selection_controller_client)); |
| 353 |
| 354 // We need to load the desired subframe and then wait until it's stable, i.e. |
| 355 // generates no new frames for some reasonable time period: a stray frame |
| 356 // between touch selection's pre-handling of GestureLongPress and the |
| 357 // expected frame containing the selected region can confuse the |
| 358 // TouchSelectionController, causing it to fail to show selection handles. |
| 359 // Note this is an issue with the TouchSelectionController in general, and |
| 360 // not a property of this test. |
| 361 GURL child_url( |
| 362 embedded_test_server()->GetURL("b.com", "/touch_selection.html")); |
| 363 NavigateFrameToURL(child, child_url); |
| 364 EXPECT_EQ( |
| 365 " Site A ------------ proxies for B\n" |
| 366 " +--Site B ------- proxies for A\n" |
| 367 "Where A = http://a.com/\n" |
| 368 " B = http://b.com/", |
| 369 FrameTreeVisualizer().DepictFrameTree(root)); |
| 370 |
| 371 // The child will change with the cross-site navigation. It shouldn't change |
| 372 // after this. |
| 373 child = root->child_at(0); |
| 374 WaitForChildFrameSurfaceReady(child->current_frame_host()); |
| 375 |
| 376 RenderWidgetHostViewChildFrame* child_view = |
| 377 static_cast<RenderWidgetHostViewChildFrame*>( |
| 378 child->current_frame_host()->GetRenderWidgetHost()->GetView()); |
| 379 |
| 380 EXPECT_EQ(child_url, observer.last_navigation_url()); |
| 381 EXPECT_TRUE(observer.last_navigation_succeeded()); |
| 382 FrameStableObserver child_frame_stable_observer(child_view, |
| 383 TestTimeouts::tiny_timeout()); |
| 384 child_frame_stable_observer.WaitUntilStable(); |
| 385 |
| 386 EXPECT_EQ(ui::TouchSelectionController::INACTIVE, |
| 387 parent_view->selection_controller()->active_status()); |
| 388 |
| 389 // Find the location of some text to select. |
| 390 gfx::PointF point_f; |
| 391 std::string str; |
| 392 EXPECT_TRUE(ExecuteScriptAndExtractString(child->current_frame_host(), |
| 393 "get_point_inside_text()", &str)); |
| 394 JSONToPoint(str, &point_f); |
| 395 gfx::Point origin = child_view->GetViewOriginInRoot(); |
| 396 gfx::Vector2dF origin_vec(origin.x(), origin.y()); |
| 397 point_f += origin_vec; |
| 398 |
| 399 // Initiate selection with a sequence of events that go through the targeting |
| 400 // system. |
| 401 parent_selection_controller_client->InitWaitForSelectionEvent( |
| 402 ui::SELECTION_HANDLES_SHOWN); |
| 403 |
| 404 SelectWithLongPress(gfx::Point(point_f.x(), point_f.y())); |
| 405 |
| 406 parent_selection_controller_client->Wait(); |
| 407 |
| 408 // Check that selection is active and the quick menu is showing. |
| 409 EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE, |
| 410 parent_view->selection_controller()->active_status()); |
| 411 EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()); |
| 412 |
| 413 // Tap outside the iframe and make sure the selection handles go away. |
| 414 // TODO(wjmaclean): As we expand test coverage, also add one where we tap |
| 415 // *inside* the oopif, but not on the text, to clear. |
| 416 parent_selection_controller_client->InitWaitForSelectionEvent( |
| 417 ui::SELECTION_HANDLES_CLEARED); |
| 418 gfx::PointF point_outside_iframe = gfx::PointF(-1.f, -1.f) + origin_vec; |
| 419 SimpleTap(gfx::Point(point_outside_iframe.x(), point_outside_iframe.y())); |
| 420 parent_selection_controller_client->Wait(); |
| 421 |
| 422 EXPECT_EQ(ui::TouchSelectionController::INACTIVE, |
| 423 parent_view->selection_controller()->active_status()); |
| 424 EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()); |
| 425 } |
| 426 |
226 // Tests that tapping in a textfield brings up the insertion handle, but not the | 427 // Tests that tapping in a textfield brings up the insertion handle, but not the |
227 // quick menu, initially. Then, successive taps on the insertion handle toggle | 428 // quick menu, initially. Then, successive taps on the insertion handle toggle |
228 // the quick menu visibility. | 429 // the quick menu visibility. |
229 IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, | 430 IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, |
230 BasicInsertionFollowedByTapsOnHandle) { | 431 BasicInsertionFollowedByTapsOnHandle) { |
231 // Set the test page up. | 432 // Set the test page up. |
232 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html")); | 433 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html")); |
233 InitSelectionController(); | 434 InitSelectionController(); |
234 | 435 |
235 RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura(); | 436 RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura(); |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 | 845 |
645 // The handle should have moved to right. | 846 // The handle should have moved to right. |
646 EXPECT_EQ(initial_handle_rect.y(), moved_handle_rect.y()); | 847 EXPECT_EQ(initial_handle_rect.y(), moved_handle_rect.y()); |
647 EXPECT_LT(initial_handle_rect.x(), moved_handle_rect.x()); | 848 EXPECT_LT(initial_handle_rect.x(), moved_handle_rect.x()); |
648 | 849 |
649 EXPECT_EQ(ui::TouchSelectionController::INSERTION_ACTIVE, | 850 EXPECT_EQ(ui::TouchSelectionController::INSERTION_ACTIVE, |
650 rwhva->selection_controller()->active_status()); | 851 rwhva->selection_controller()->active_status()); |
651 } | 852 } |
652 | 853 |
653 } // namespace content | 854 } // namespace content |
OLD | NEW |