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 testing::WithParamInterface<bool> { |
| 237 public: |
| 238 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 239 IsolateAllSitesForTesting(command_line); |
| 240 } |
| 241 |
| 242 void SetUpOnMainThread() override { |
| 243 TouchSelectionControllerClientAuraTest::SetUpOnMainThread(); |
| 244 host_resolver()->AddRule("*", "127.0.0.1"); |
| 245 SetupCrossSiteRedirector(embedded_test_server()); |
| 246 ASSERT_TRUE(embedded_test_server()->Start()); |
| 247 } |
| 248 |
| 249 void SelectWithLongPress(gfx::Point point) { |
| 250 // Get main frame view for event insertion. |
| 251 RenderWidgetHostViewAura* main_view = GetRenderWidgetHostViewAura(); |
| 252 |
| 253 SendTouch(main_view, ui::ET_TOUCH_PRESSED, point); |
| 254 SendTouch(main_view, ui::ET_TOUCH_RELEASED, point); |
| 255 SendGestureTap(main_view, point); |
| 256 SendGestureLongPress(main_view, point); |
| 257 } |
| 258 |
| 259 void SimpleTap(gfx::Point point) { |
| 260 // Get main frame view for event insertion. |
| 261 RenderWidgetHostViewAura* main_view = GetRenderWidgetHostViewAura(); |
| 262 |
| 263 SendTouch(main_view, ui::ET_TOUCH_PRESSED, point); |
| 264 SendTouch(main_view, ui::ET_TOUCH_RELEASED, point); |
| 265 SendGestureTap(main_view, point); |
| 266 } |
| 267 |
| 268 private: |
| 269 void SendTouch(RenderWidgetHostViewAura* view, |
| 270 ui::EventType type, |
| 271 gfx::Point point) { |
| 272 DCHECK(type >= ui::ET_TOUCH_RELEASED && type << ui::ET_TOUCH_CANCELLED); |
| 273 ui::TouchEvent touch( |
| 274 type, point, ui::EventTimeForNow(), |
| 275 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); |
| 276 view->OnTouchEvent(&touch); |
| 277 } |
| 278 |
| 279 void SendGestureTap(RenderWidgetHostViewAura* view, gfx::Point point) { |
| 280 ui::GestureEventDetails tap_down_details(ui::ET_GESTURE_TAP_DOWN); |
| 281 tap_down_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN); |
| 282 ui::GestureEvent gesture_tap_down(point.x(), point.y(), 0, |
| 283 ui::EventTimeForNow(), tap_down_details); |
| 284 view->OnGestureEvent(&gesture_tap_down); |
| 285 ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP); |
| 286 tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN); |
| 287 tap_details.set_tap_count(1); |
| 288 ui::GestureEvent gesture_tap(point.x(), point.y(), 0, ui::EventTimeForNow(), |
| 289 tap_details); |
| 290 view->OnGestureEvent(&gesture_tap); |
| 291 } |
| 292 |
| 293 void SendGestureLongPress(RenderWidgetHostViewAura* view, gfx::Point point) { |
| 294 ui::GestureEventDetails long_press_details(ui::ET_GESTURE_LONG_PRESS); |
| 295 long_press_details.set_device_type( |
| 296 ui::GestureDeviceType::DEVICE_TOUCHSCREEN); |
| 297 ui::GestureEvent gesture_long_press( |
| 298 point.x(), point.y(), 0, ui::EventTimeForNow(), long_press_details); |
| 299 view->OnGestureEvent(&gesture_long_press); |
| 300 } |
| 301 }; |
| 302 |
| 303 class FrameStableObserver { |
| 304 public: |
| 305 FrameStableObserver(RenderWidgetHostViewBase* view, base::TimeDelta delta) |
| 306 : view_(view), delta_(delta) {} |
| 307 virtual ~FrameStableObserver() {} |
| 308 |
| 309 void WaitUntilStable() { |
| 310 uint32_t current_frame_number = view_->RendererFrameNumber(); |
| 311 uint32_t previous_frame_number; |
| 312 |
| 313 do { |
| 314 base::RunLoop run_loop; |
| 315 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 316 FROM_HERE, run_loop.QuitClosure(), delta_); |
| 317 run_loop.Run(); |
| 318 previous_frame_number = current_frame_number; |
| 319 current_frame_number = view_->RendererFrameNumber(); |
| 320 } while (current_frame_number != previous_frame_number); |
| 321 } |
| 322 |
| 323 private: |
| 324 RenderWidgetHostViewBase* view_; |
| 325 base::TimeDelta delta_; |
| 326 |
| 327 DISALLOW_COPY_AND_ASSIGN(FrameStableObserver); |
| 328 }; |
| 329 |
| 330 INSTANTIATE_TEST_CASE_P(TouchSelectionForCrossProcessFramesTests, |
| 331 TouchSelectionControllerClientAuraSiteIsolationTest, |
| 332 testing::Bool()); |
| 333 |
| 334 IN_PROC_BROWSER_TEST_P(TouchSelectionControllerClientAuraSiteIsolationTest, |
| 335 BasicSelectionIsolatedIframe) { |
| 336 GURL test_url(embedded_test_server()->GetURL( |
| 337 "a.com", "/cross_site_iframe_factory.html?a(a)")); |
| 338 EXPECT_TRUE(NavigateToURL(shell(), test_url)); |
| 339 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 340 ->GetFrameTree() |
| 341 ->root(); |
| 342 EXPECT_EQ( |
| 343 " Site A\n" |
| 344 " +--Site A\n" |
| 345 "Where A = http://a.com/", |
| 346 FrameTreeVisualizer().DepictFrameTree(root)); |
| 347 TestNavigationObserver observer(shell()->web_contents()); |
| 348 EXPECT_EQ(1u, root->child_count()); |
| 349 FrameTreeNode* child = root->child_at(0); |
| 350 |
| 351 RenderWidgetHostViewAura* parent_view = |
| 352 static_cast<RenderWidgetHostViewAura*>( |
| 353 root->current_frame_host()->GetRenderWidgetHost()->GetView()); |
| 354 TestTouchSelectionControllerClientAura* parent_selection_controller_client = |
| 355 new TestTouchSelectionControllerClientAura(parent_view); |
| 356 parent_view->SetSelectionControllerClientForTest( |
| 357 base::WrapUnique(parent_selection_controller_client)); |
| 358 |
| 359 // We need to load the desired subframe and then wait until it's stable, i.e. |
| 360 // generates no new frames for some reasonable time period: a stray frame |
| 361 // between touch selection's pre-handling of GestureLongPress and the |
| 362 // expected frame containing the selected region can confuse the |
| 363 // TouchSelectionController, causing it to fail to show selection handles. |
| 364 // Note this is an issue with the TouchSelectionController in general, and |
| 365 // not a property of this test. |
| 366 GURL child_url( |
| 367 embedded_test_server()->GetURL("b.com", "/touch_selection.html")); |
| 368 NavigateFrameToURL(child, child_url); |
| 369 EXPECT_EQ( |
| 370 " Site A ------------ proxies for B\n" |
| 371 " +--Site B ------- proxies for A\n" |
| 372 "Where A = http://a.com/\n" |
| 373 " B = http://b.com/", |
| 374 FrameTreeVisualizer().DepictFrameTree(root)); |
| 375 |
| 376 // The child will change with the cross-site navigation. It shouldn't change |
| 377 // after this. |
| 378 child = root->child_at(0); |
| 379 WaitForChildFrameSurfaceReady(child->current_frame_host()); |
| 380 |
| 381 RenderWidgetHostViewChildFrame* child_view = |
| 382 static_cast<RenderWidgetHostViewChildFrame*>( |
| 383 child->current_frame_host()->GetRenderWidgetHost()->GetView()); |
| 384 |
| 385 EXPECT_EQ(child_url, observer.last_navigation_url()); |
| 386 EXPECT_TRUE(observer.last_navigation_succeeded()); |
| 387 FrameStableObserver child_frame_stable_observer(child_view, |
| 388 TestTimeouts::tiny_timeout()); |
| 389 child_frame_stable_observer.WaitUntilStable(); |
| 390 |
| 391 EXPECT_EQ(ui::TouchSelectionController::INACTIVE, |
| 392 parent_view->selection_controller()->active_status()); |
| 393 |
| 394 // Find the location of some text to select. |
| 395 gfx::PointF point_f; |
| 396 std::string str; |
| 397 EXPECT_TRUE(ExecuteScriptAndExtractString(child->current_frame_host(), |
| 398 "get_point_inside_text()", &str)); |
| 399 JSONToPoint(str, &point_f); |
| 400 gfx::Point origin = child_view->GetViewOriginInRoot(); |
| 401 gfx::Vector2dF origin_vec(origin.x(), origin.y()); |
| 402 point_f += origin_vec; |
| 403 |
| 404 // Initiate selection with a sequence of events that go through the targeting |
| 405 // system. |
| 406 parent_selection_controller_client->InitWaitForSelectionEvent( |
| 407 ui::SELECTION_HANDLES_SHOWN); |
| 408 |
| 409 SelectWithLongPress(gfx::Point(point_f.x(), point_f.y())); |
| 410 |
| 411 parent_selection_controller_client->Wait(); |
| 412 |
| 413 // Check that selection is active and the quick menu is showing. |
| 414 EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE, |
| 415 parent_view->selection_controller()->active_status()); |
| 416 EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()); |
| 417 |
| 418 // Tap inside/outside the iframe and make sure the selection handles go away. |
| 419 parent_selection_controller_client->InitWaitForSelectionEvent( |
| 420 ui::SELECTION_HANDLES_CLEARED); |
| 421 if (GetParam()) { |
| 422 gfx::PointF point_outside_iframe = gfx::PointF(-1.f, -1.f) + origin_vec; |
| 423 SimpleTap(gfx::Point(point_outside_iframe.x(), point_outside_iframe.y())); |
| 424 } else { |
| 425 gfx::PointF point_inside_iframe = gfx::PointF(+1.f, +1.f) + origin_vec; |
| 426 SimpleTap(gfx::Point(point_inside_iframe.x(), point_inside_iframe.y())); |
| 427 } |
| 428 parent_selection_controller_client->Wait(); |
| 429 |
| 430 EXPECT_EQ(ui::TouchSelectionController::INACTIVE, |
| 431 parent_view->selection_controller()->active_status()); |
| 432 EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()); |
| 433 } |
| 434 |
226 // Tests that tapping in a textfield brings up the insertion handle, but not the | 435 // 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 | 436 // quick menu, initially. Then, successive taps on the insertion handle toggle |
228 // the quick menu visibility. | 437 // the quick menu visibility. |
229 IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, | 438 IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, |
230 BasicInsertionFollowedByTapsOnHandle) { | 439 BasicInsertionFollowedByTapsOnHandle) { |
231 // Set the test page up. | 440 // Set the test page up. |
232 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html")); | 441 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html")); |
233 InitSelectionController(); | 442 InitSelectionController(); |
234 | 443 |
235 RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura(); | 444 RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura(); |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 | 853 |
645 // The handle should have moved to right. | 854 // The handle should have moved to right. |
646 EXPECT_EQ(initial_handle_rect.y(), moved_handle_rect.y()); | 855 EXPECT_EQ(initial_handle_rect.y(), moved_handle_rect.y()); |
647 EXPECT_LT(initial_handle_rect.x(), moved_handle_rect.x()); | 856 EXPECT_LT(initial_handle_rect.x(), moved_handle_rect.x()); |
648 | 857 |
649 EXPECT_EQ(ui::TouchSelectionController::INSERTION_ACTIVE, | 858 EXPECT_EQ(ui::TouchSelectionController::INSERTION_ACTIVE, |
650 rwhva->selection_controller()->active_status()); | 859 rwhva->selection_controller()->active_status()); |
651 } | 860 } |
652 | 861 |
653 } // namespace content | 862 } // namespace content |
OLD | NEW |