1 // Copyright 2013 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 "base/strings/stringprintf.h" 6 #include "base/strings/utf_string_conversions.h" 7 #include "chrome/app/chrome_command_ids.h" 8 #include "chrome/browser/apps/app_browsertest_util.h" 9 #include "chrome/browser/chrome_content_browser_client.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h" 12 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h" 13 #include "chrome/test/base/interactive_test_utils.h" 14 #include "chrome/test/base/test_launcher_utils.h" 15 #include "chrome/test/base/ui_test_utils.h" 16 #include "content/public/browser/notification_service.h" 17 #include "content/public/browser/render_process_host.h" 18 #include "content/public/browser/render_view_host.h" 19 #include "content/public/browser/render_widget_host_iterator.h" 20 #include "content/public/browser/render_widget_host_view.h" 21 #include "content/public/browser/web_contents.h" 22 #include "content/public/common/content_switches.h" 23 #include "content/public/test/browser_test_utils.h" 24 #include "extensions/browser/app_window/app_window.h" 25 #include "extensions/browser/app_window/app_window_registry.h" 26 #include "extensions/browser/guest_view/guest_view_base.h" 27 #include "extensions/browser/guest_view/guest_view_manager.h" 28 #include "extensions/browser/guest_view/guest_view_manager_factory.h" 29 #include "extensions/test/extension_test_message_listener.h" 30 #include "net/test/embedded_test_server/embedded_test_server.h" 31 #include "ui/base/ime/composition_text.h" 32 #include "ui/base/ime/text_input_client.h" 33 #include "ui/base/test/ui_controls.h" 34 #include "ui/events/keycodes/keyboard_codes.h" 35 36 using extensions::AppWindow; 37 38 class TestGuestViewManager : public extensions::GuestViewManager { 39 public: 40 explicit TestGuestViewManager(content::BrowserContext* context) 41 : GuestViewManager(context), 42 guest_add_count_(0), 43 guest_remove_count_(0), 44 web_contents_(NULL) {} 45 46 content::WebContents* WaitForGuestAdded() { 47 if (web_contents_) 48 return web_contents_; 49 50 add_message_loop_runner_ = new content::MessageLoopRunner; 51 add_message_loop_runner_->Run(); 52 return web_contents_; 53 } 54 55 // Waits so that at least |expected_remove_count| guests' creation 56 // has been seen by this manager. 57 void WaitForGuestRemoved(size_t expected_remove_count) { 58 if (guest_remove_count_ >= expected_remove_count) 59 return; 60 61 remove_message_loop_runner_ = new content::MessageLoopRunner; 62 remove_message_loop_runner_->Run(); 63 } 64 65 size_t guest_add_count() { return guest_add_count_; } 66 67 private: 68 // GuestViewManager override: 69 virtual void AddGuest(int guest_instance_id, 70 content::WebContents* guest_web_contents) OVERRIDE{ 71 GuestViewManager::AddGuest(guest_instance_id, guest_web_contents); 72 web_contents_ = guest_web_contents; 73 ++guest_add_count_; 74 75 if (add_message_loop_runner_.get()) 76 add_message_loop_runner_->Quit(); 77 } 78 79 virtual void RemoveGuest(int guest_instance_id) OVERRIDE { 80 GuestViewManager::RemoveGuest(guest_instance_id); 81 ++guest_remove_count_; 82 83 if (remove_message_loop_runner_.get()) 84 remove_message_loop_runner_->Quit(); 85 } 86 87 size_t guest_add_count_; 88 size_t guest_remove_count_; 89 content::WebContents* web_contents_; 90 scoped_refptr<content::MessageLoopRunner> add_message_loop_runner_; 91 scoped_refptr<content::MessageLoopRunner> remove_message_loop_runner_; 92 }; 93 94 // Test factory for creating test instances of GuestViewManager. 95 class TestGuestViewManagerFactory : public extensions::GuestViewManagerFactory { 96 public: 97 TestGuestViewManagerFactory() : 98 test_guest_view_manager_(NULL) {} 99 100 virtual ~TestGuestViewManagerFactory() {} 101 102 virtual extensions::GuestViewManager* CreateGuestViewManager( 103 content::BrowserContext* context) OVERRIDE { 104 return GetManager(context); 105 } 106 107 TestGuestViewManager* GetManager(content::BrowserContext* context) { 108 if (!test_guest_view_manager_) { 109 test_guest_view_manager_ = new TestGuestViewManager(context); 110 } 111 return test_guest_view_manager_; 112 } 113 114 private: 115 TestGuestViewManager* test_guest_view_manager_; 116 117 DISALLOW_COPY_AND_ASSIGN(TestGuestViewManagerFactory); 118 }; 119 120 class WebViewInteractiveTest 121 : public extensions::PlatformAppBrowserTest { 122 public: 123 WebViewInteractiveTest() 124 : guest_web_contents_(NULL), 125 embedder_web_contents_(NULL), 126 corner_(gfx::Point()), 127 mouse_click_result_(false), 128 first_click_(true) { 129 extensions::GuestViewManager::set_factory_for_testing(&factory_); 130 } 131 132 TestGuestViewManager* GetGuestViewManager() { 133 return factory_.GetManager(browser()->profile()); 134 } 135 136 void MoveMouseInsideWindowWithListener(gfx::Point point, 137 const std::string& message) { 138 ExtensionTestMessageListener move_listener(message, false); 139 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync( 140 gfx::Point(corner_.x() + point.x(), corner_.y() + point.y()))); 141 ASSERT_TRUE(move_listener.WaitUntilSatisfied()); 142 } 143 144 void SendMouseClickWithListener(ui_controls::MouseButton button, 145 const std::string& message) { 146 ExtensionTestMessageListener listener(message, false); 147 SendMouseClick(button); 148 ASSERT_TRUE(listener.WaitUntilSatisfied()); 149 } 150 151 void SendMouseClick(ui_controls::MouseButton button) { 152 SendMouseEvent(button, ui_controls::DOWN); 153 SendMouseEvent(button, ui_controls::UP); 154 } 155 156 void MoveMouseInsideWindow(const gfx::Point& point) { 157 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync( 158 gfx::Point(corner_.x() + point.x(), corner_.y() + point.y()))); 159 } 160 161 gfx::NativeWindow GetPlatformAppWindow() { 162 const extensions::AppWindowRegistry::AppWindowList& app_windows = 163 extensions::AppWindowRegistry::Get(browser()->profile())->app_windows(); 164 return (*app_windows.begin())->GetNativeWindow(); 165 } 166 167 void SendKeyPressToPlatformApp(ui::KeyboardCode key) { 168 ASSERT_EQ(1U, GetAppWindowCount()); 169 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( 170 GetPlatformAppWindow(), key, false, false, false, false)); 171 } 172 173 void SendCopyKeyPressToPlatformApp() { 174 ASSERT_EQ(1U, GetAppWindowCount()); 175 #if defined(OS_MACOSX) 176 // Send Cmd+C on MacOSX. 177 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( 178 GetPlatformAppWindow(), ui::VKEY_C, false, false, false, true)); 179 #else 180 // Send Ctrl+C on Windows and Linux/ChromeOS. 181 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( 182 GetPlatformAppWindow(), ui::VKEY_C, true, false, false, false)); 183 #endif 184 } 185 186 void SendStartOfLineKeyPressToPlatformApp() { 187 #if defined(OS_MACOSX) 188 // Send Cmd+Left on MacOSX. 189 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( 190 GetPlatformAppWindow(), ui::VKEY_LEFT, false, false, false, true)); 191 #else 192 // Send Ctrl+Left on Windows and Linux/ChromeOS. 193 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( 194 GetPlatformAppWindow(), ui::VKEY_LEFT, true, false, false, false)); 195 #endif 196 } 197 198 void SendBackShortcutToPlatformApp() { 199 #if defined(OS_MACOSX) 200 // Send Cmd+[ on MacOSX. 201 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( 202 GetPlatformAppWindow(), ui::VKEY_OEM_4, false, false, false, true)); 203 #else 204 // Send browser back key on Linux/Windows. 205 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( 206 GetPlatformAppWindow(), ui::VKEY_BROWSER_BACK, 207 false, false, false, false)); 208 #endif 209 } 210 211 void SendForwardShortcutToPlatformApp() { 212 #if defined(OS_MACOSX) 213 // Send Cmd+] on MacOSX. 214 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( 215 GetPlatformAppWindow(), ui::VKEY_OEM_6, false, false, false, true)); 216 #else 217 // Send browser back key on Linux/Windows. 218 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( 219 GetPlatformAppWindow(), ui::VKEY_BROWSER_FORWARD, 220 false, false, false, false)); 221 #endif 222 } 223 224 void SendMouseEvent(ui_controls::MouseButton button, 225 ui_controls::MouseButtonState state) { 226 if (first_click_) { 227 mouse_click_result_ = ui_test_utils::SendMouseEventsSync(button, 228 state); 229 first_click_ = false; 230 } else { 231 ASSERT_EQ(mouse_click_result_, ui_test_utils::SendMouseEventsSync( 232 button, state)); 233 } 234 } 235 236 enum TestServer { 237 NEEDS_TEST_SERVER, 238 NO_TEST_SERVER 239 }; 240 241 scoped_ptr<ExtensionTestMessageListener> RunAppHelper( 242 const std::string& test_name, 243 const std::string& app_location, 244 TestServer test_server, 245 content::WebContents** embedder_web_contents) { 246 // For serving guest pages. 247 if ((test_server == NEEDS_TEST_SERVER) && !StartEmbeddedTestServer()) { 248 LOG(ERROR) << "FAILED TO START TEST SERVER."; 249 return scoped_ptr<ExtensionTestMessageListener>(); 250 } 251 252 LoadAndLaunchPlatformApp(app_location.c_str(), "Launched"); 253 if (!ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow())) { 254 LOG(ERROR) << "UNABLE TO FOCUS TEST WINDOW."; 255 return scoped_ptr<ExtensionTestMessageListener>(); 256 } 257 258 // Flush any pending events to make sure we start with a clean slate. 259 content::RunAllPendingInMessageLoop(); 260 261 *embedder_web_contents = GetFirstAppWindowWebContents(); 262 263 scoped_ptr<ExtensionTestMessageListener> done_listener( 264 new ExtensionTestMessageListener("TEST_PASSED", false)); 265 done_listener->set_failure_message("TEST_FAILED"); 266 if (!content::ExecuteScript( 267 *embedder_web_contents, 268 base::StringPrintf("runTest('%s')", test_name.c_str()))) { 269 LOG(ERROR) << "UNABLE TO START TEST"; 270 return scoped_ptr<ExtensionTestMessageListener>(); 271 } 272 273 return done_listener.Pass(); 274 } 275 276 void TestHelper(const std::string& test_name, 277 const std::string& app_location, 278 TestServer test_server) { 279 content::WebContents* embedder_web_contents = NULL; 280 scoped_ptr<ExtensionTestMessageListener> done_listener( 281 RunAppHelper( 282 test_name, app_location, test_server, &embedder_web_contents)); 283 284 ASSERT_TRUE(done_listener); 285 ASSERT_TRUE(done_listener->WaitUntilSatisfied()); 286 287 guest_web_contents_ = GetGuestViewManager()->WaitForGuestAdded(); 288 } 289 290 void RunTest(const std::string& app_name) { 291 } 292 void SetupTest(const std::string& app_name, 293 const std::string& guest_url_spec) { 294 ASSERT_TRUE(StartEmbeddedTestServer()); 295 GURL::Replacements replace_host; 296 std::string host_str("localhost"); // Must stay in scope with replace_host. 297 replace_host.SetHostStr(host_str); 298 299 GURL guest_url = embedded_test_server()->GetURL(guest_url_spec); 300 guest_url = guest_url.ReplaceComponents(replace_host); 301 302 ui_test_utils::UrlLoadObserver guest_observer( 303 guest_url, content::NotificationService::AllSources()); 304 305 LoadAndLaunchPlatformApp(app_name.c_str(), "connected"); 306 307 guest_observer.Wait(); 308 content::Source<content::NavigationController> source = 309 guest_observer.source(); 310 EXPECT_TRUE(source->GetWebContents()->GetRenderProcessHost()-> 311 IsIsolatedGuest()); 312 313 guest_web_contents_ = source->GetWebContents(); 314 embedder_web_contents_ = 315 extensions::GuestViewBase::FromWebContents(guest_web_contents_)-> 316 embedder_web_contents(); 317 318 gfx::Rect offset = embedder_web_contents_->GetContainerBounds(); 319 corner_ = gfx::Point(offset.x(), offset.y()); 320 321 const testing::TestInfo* const test_info = 322 testing::UnitTest::GetInstance()->current_test_info(); 323 const char* prefix = "DragDropWithinWebView"; 324 if (!strncmp(test_info->name(), prefix, strlen(prefix))) { 325 // In the drag drop test we add 20px padding to the page body because on 326 // windows if we get too close to the edge of the window the resize cursor 327 // appears and we start dragging the window edge. 328 corner_.Offset(20, 20); 329 } 330 } 331 332 content::WebContents* guest_web_contents() { 333 return guest_web_contents_; 334 } 335 336 content::WebContents* embedder_web_contents() { 337 return embedder_web_contents_; 338 } 339 340 gfx::Point corner() { 341 return corner_; 342 } 343 344 void SimulateRWHMouseClick(content::RenderWidgetHost* rwh, 345 blink::WebMouseEvent::Button button, 346 int x, 347 int y) { 348 blink::WebMouseEvent mouse_event; 349 mouse_event.button = button; 350 mouse_event.x = mouse_event.windowX = x; 351 mouse_event.y = mouse_event.windowY = y; 352 mouse_event.modifiers = 0; 353 354 mouse_event.type = blink::WebInputEvent::MouseDown; 355 rwh->ForwardMouseEvent(mouse_event); 356 mouse_event.type = blink::WebInputEvent::MouseUp; 357 rwh->ForwardMouseEvent(mouse_event); 358 } 359 360 class PopupCreatedObserver { 361 public: 362 PopupCreatedObserver() 363 : initial_widget_count_(0), 364 last_render_widget_host_(NULL), 365 seen_new_widget_(false) {} 366 367 ~PopupCreatedObserver() {} 368 369 void Wait() { 370 size_t current_widget_count = CountWidgets(); 371 if (!seen_new_widget_ && 372 current_widget_count == initial_widget_count_ + 1) { 373 seen_new_widget_ = true; 374 } 375 376 // If we haven't seen any new widget or we get 0 size widget, we need to 377 // schedule waiting. 378 bool needs_to_schedule_wait = true; 379 380 if (seen_new_widget_) { 381 gfx::Rect popup_bounds = 382 last_render_widget_host_->GetView()->GetViewBounds(); 383 if (!popup_bounds.size().IsEmpty()) 384 needs_to_schedule_wait = false; 385 } 386 387 if (needs_to_schedule_wait) { 388 ScheduleWait(); 389 } else { 390 // We are done. 391 if (message_loop_.get()) 392 message_loop_->Quit(); 393 } 394 395 if (!message_loop_.get()) { 396 message_loop_ = new content::MessageLoopRunner; 397 message_loop_->Run(); 398 } 399 } 400 401 void Init() { initial_widget_count_ = CountWidgets(); } 402 403 // Returns the last widget created. 404 content::RenderWidgetHost* last_render_widget_host() { 405 return last_render_widget_host_; 406 } 407 408 private: 409 void ScheduleWait() { 410 base::MessageLoop::current()->PostDelayedTask( 411 FROM_HERE, 412 base::Bind(&PopupCreatedObserver::Wait, base::Unretained(this)), 413 base::TimeDelta::FromMilliseconds(200)); 414 } 415 416 size_t CountWidgets() { 417 scoped_ptr<content::RenderWidgetHostIterator> widgets( 418 content::RenderWidgetHost::GetRenderWidgetHosts()); 419 size_t num_widgets = 0; 420 while (content::RenderWidgetHost* widget = widgets->GetNextHost()) { 421 if (widget->IsRenderView()) 422 continue; 423 ++num_widgets; 424 last_render_widget_host_ = widget; 425 } 426 return num_widgets; 427 } 428 429 size_t initial_widget_count_; 430 content::RenderWidgetHost* last_render_widget_host_; 431 scoped_refptr<content::MessageLoopRunner> message_loop_; 432 bool seen_new_widget_; 433 434 DISALLOW_COPY_AND_ASSIGN(PopupCreatedObserver); 435 }; 436 437 void WaitForTitle(const char* title) { 438 base::string16 expected_title(base::ASCIIToUTF16(title)); 439 base::string16 error_title(base::ASCIIToUTF16("FAILED")); 440 content::TitleWatcher title_watcher(guest_web_contents(), expected_title); 441 title_watcher.AlsoWaitForTitle(error_title); 442 ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle()); 443 } 444 445 void PopupTestHelper(const gfx::Point& padding) { 446 PopupCreatedObserver popup_observer; 447 popup_observer.Init(); 448 // Press alt+DOWN to open popup. 449 bool alt = true; 450 content::SimulateKeyPress( 451 guest_web_contents(), ui::VKEY_DOWN, false, false, alt, false); 452 popup_observer.Wait(); 453 454 content::RenderWidgetHost* popup_rwh = 455 popup_observer.last_render_widget_host(); 456 gfx::Rect popup_bounds = popup_rwh->GetView()->GetViewBounds(); 457 458 content::RenderViewHost* embedder_rvh = 459 GetFirstAppWindowWebContents()->GetRenderViewHost(); 460 gfx::Rect embedder_bounds = embedder_rvh->GetView()->GetViewBounds(); 461 gfx::Vector2d diff = popup_bounds.origin() - embedder_bounds.origin(); 462 LOG(INFO) << "DIFF: x = " << diff.x() << ", y = " << diff.y(); 463 464 const int left_spacing = 40 + padding.x(); // div.style.paddingLeft = 40px. 465 // div.style.paddingTop = 50px + (input box height = 26px). 466 const int top_spacing = 50 + 26 + padding.y(); 467 468 // If the popup is placed within |threshold_px| of the expected position, 469 // then we consider the test as a pass. 470 const int threshold_px = 10; 471 472 EXPECT_LE(std::abs(diff.x() - left_spacing), threshold_px); 473 EXPECT_LE(std::abs(diff.y() - top_spacing), threshold_px); 474 475 // Close the popup. 476 content::SimulateKeyPress( 477 guest_web_contents(), ui::VKEY_ESCAPE, false, false, false, false); 478 } 479 480 void DragTestStep1() { 481 // Move mouse to start of text. 482 MoveMouseInsideWindow(gfx::Point(45, 8)); 483 MoveMouseInsideWindow(gfx::Point(45, 9)); 484 SendMouseEvent(ui_controls::LEFT, ui_controls::DOWN); 485 486 MoveMouseInsideWindow(gfx::Point(74, 12)); 487 MoveMouseInsideWindow(gfx::Point(78, 12)); 488 489 // Now wait a bit before moving mouse to initiate drag/drop. 490 base::MessageLoop::current()->PostDelayedTask( 491 FROM_HERE, 492 base::Bind(&WebViewInteractiveTest::DragTestStep2, 493 base::Unretained(this)), 494 base::TimeDelta::FromMilliseconds(200)); 495 } 496 497 void DragTestStep2() { 498 // Drag source over target. 499 MoveMouseInsideWindow(gfx::Point(76, 76)); 500 501 // Create a second mouse over the source to trigger the drag over event. 502 MoveMouseInsideWindow(gfx::Point(76, 77)); 503 504 // Release mouse to drop. 505 SendMouseEvent(ui_controls::LEFT, ui_controls::UP); 506 SendMouseClick(ui_controls::LEFT); 507 508 quit_closure_.Run(); 509 510 // Note that following ExtensionTestMessageListener and ExecuteScript* 511 // call must be after we quit |quit_closure_|. Otherwise the class 512 // here won't be able to receive messages sent by chrome.test.sendMessage. 513 // This is because of the nature of drag and drop code (esp. the 514 // MessageLoop) in it. 515 516 // Now check if we got a drop and read the drop data. 517 embedder_web_contents_ = GetFirstAppWindowWebContents(); 518 ExtensionTestMessageListener drop_listener("guest-got-drop", false); 519 EXPECT_TRUE(content::ExecuteScript(embedder_web_contents_, 520 "window.checkIfGuestGotDrop()")); 521 EXPECT_TRUE(drop_listener.WaitUntilSatisfied()); 522 523 std::string last_drop_data; 524 EXPECT_TRUE(content::ExecuteScriptAndExtractString( 525 embedder_web_contents_, 526 "window.domAutomationController.send(getLastDropData())", 527 &last_drop_data)); 528 529 last_drop_data_ = last_drop_data; 530 } 531 532 protected: 533 TestGuestViewManagerFactory factory_; 534 content::WebContents* guest_web_contents_; 535 content::WebContents* embedder_web_contents_; 536 gfx::Point corner_; 537 bool mouse_click_result_; 538 bool first_click_; 539 // Only used in drag/drop test. 540 base::Closure quit_closure_; 541 std::string last_drop_data_; 542 }; 543 544 // ui_test_utils::SendMouseMoveSync doesn't seem to work on OS_MACOSX, and 545 // likely won't work on many other platforms as well, so for now this test 546 // is for Windows and Linux only. As of Sept 17th, 2013 this test is disabled 547 // on Windows due to flakines, see http://crbug.com/293445. 548 549 // Disabled on Linux Aura because pointer lock does not work on Linux Aura. 550 // crbug.com/341876 551 552 #if defined(OS_LINUX) 553 // flaky http://crbug.com/412086 554 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_PointerLock) { 555 SetupTest("web_view/pointer_lock", 556 "/extensions/platform_apps/web_view/pointer_lock/guest.html"); 557 558 // Move the mouse over the Lock Pointer button. 559 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync( 560 gfx::Point(corner().x() + 75, corner().y() + 25))); 561 562 // Click the Lock Pointer button. The first two times the button is clicked 563 // the permission API will deny the request (intentional). 564 ExtensionTestMessageListener exception_listener("request exception", false); 565 SendMouseClickWithListener(ui_controls::LEFT, "lock error"); 566 ASSERT_TRUE(exception_listener.WaitUntilSatisfied()); 567 SendMouseClickWithListener(ui_controls::LEFT, "lock error"); 568 569 // Click the Lock Pointer button, locking the mouse to lockTarget1. 570 SendMouseClickWithListener(ui_controls::LEFT, "locked"); 571 572 // Attempt to move the mouse off of the lock target, and onto lockTarget2, 573 // (which would trigger a test failure). 574 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync( 575 gfx::Point(corner().x() + 74, corner().y() + 74))); 576 MoveMouseInsideWindowWithListener(gfx::Point(75, 75), "mouse-move"); 577 578 #if defined(OS_WIN) 579 // When the mouse is unlocked on win aura, sending a test mouse click clicks 580 // where the mouse moved to while locked. I was unable to figure out why, and 581 // since the issue only occurs with the test mouse events, just fix it with 582 // a simple workaround - moving the mouse back to where it should be. 583 // TODO(mthiesse): Fix Win Aura simulated mouse events while mouse locked. 584 MoveMouseInsideWindowWithListener(gfx::Point(75, 25), "mouse-move"); 585 #endif 586 587 ExtensionTestMessageListener unlocked_listener("unlocked", false); 588 // Send a key press to unlock the mouse. 589 SendKeyPressToPlatformApp(ui::VKEY_ESCAPE); 590 591 // Wait for page to receive (successful) mouse unlock response. 592 ASSERT_TRUE(unlocked_listener.WaitUntilSatisfied()); 593 594 // After the second lock, guest.js sends a message to main.js to remove the 595 // webview object. main.js then removes the div containing the webview, which 596 // should unlock, and leave the mouse over the mousemove-capture-container 597 // div. We then move the mouse over that div to ensure the mouse was properly 598 // unlocked and that the div receieves the message. 599 ExtensionTestMessageListener move_captured_listener("move-captured", false); 600 move_captured_listener.set_failure_message("timeout"); 601 602 // Mouse should already be over lock button (since we just unlocked), so send 603 // click to re-lock the mouse. 604 SendMouseClickWithListener(ui_controls::LEFT, "deleted"); 605 606 // A mousemove event is triggered on the mousemove-capture-container element 607 // when we delete the webview container (since the mouse moves onto the 608 // element), but just in case, send an explicit mouse movement to be safe. 609 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync( 610 gfx::Point(corner().x() + 50, corner().y() + 10))); 611 612 // Wait for page to receive second (successful) mouselock response. 613 bool success = move_captured_listener.WaitUntilSatisfied(); 614 if (!success) { 615 fprintf(stderr, "TIMEOUT - retrying\n"); 616 // About 1 in 40 tests fail to detect mouse moves at this point (why?). 617 // Sending a right click seems to fix this (why?). 618 ExtensionTestMessageListener move_listener2("move-captured", false); 619 SendMouseClick(ui_controls::RIGHT); 620 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync( 621 gfx::Point(corner().x() + 51, corner().y() + 11))); 622 ASSERT_TRUE(move_listener2.WaitUntilSatisfied()); 623 } 624 } 625 626 // flaky http://crbug.com/412086 627 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_PointerLockFocus) { 628 SetupTest("web_view/pointer_lock_focus", 629 "/extensions/platform_apps/web_view/pointer_lock_focus/guest.html"); 630 631 // Move the mouse over the Lock Pointer button. 632 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync( 633 gfx::Point(corner().x() + 75, corner().y() + 25))); 634 635 // Click the Lock Pointer button, locking the mouse to lockTarget. 636 // This will also change focus to another element 637 SendMouseClickWithListener(ui_controls::LEFT, "locked"); 638 639 // Try to unlock the mouse now that the focus is outside of the BrowserPlugin 640 ExtensionTestMessageListener unlocked_listener("unlocked", false); 641 // Send a key press to unlock the mouse. 642 SendKeyPressToPlatformApp(ui::VKEY_ESCAPE); 643 644 // Wait for page to receive (successful) mouse unlock response. 645 ASSERT_TRUE(unlocked_listener.WaitUntilSatisfied()); 646 } 647 648 #endif // defined(OS_LINUX) 649 650 // Tests that if a <webview> is focused before navigation then the guest starts 651 // off focused. 652 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_FocusBeforeNavigation) { 653 TestHelper("testFocusBeforeNavigation", "web_view/focus", NO_TEST_SERVER); 654 } 655 656 // Tests that setting focus on the <webview> sets focus on the guest. 657 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_FocusEvent) { 658 TestHelper("testFocusEvent", "web_view/focus", NO_TEST_SERVER); 659 } 660 661 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_FocusTracksEmbedder) { 662 content::WebContents* embedder_web_contents = NULL; 663 664 scoped_ptr<ExtensionTestMessageListener> done_listener( 665 RunAppHelper("testFocusTracksEmbedder", "web_view/focus", NO_TEST_SERVER, 666 &embedder_web_contents)); 667 done_listener->WaitUntilSatisfied(); 668 669 ExtensionTestMessageListener next_step_listener("TEST_STEP_PASSED", false); 670 next_step_listener.set_failure_message("TEST_STEP_FAILED"); 671 EXPECT_TRUE(content::ExecuteScript( 672 embedder_web_contents, 673 "window.runCommand('testFocusTracksEmbedderRunNextStep');")); 674 675 // Blur the embedder. 676 embedder_web_contents->GetRenderViewHost()->Blur(); 677 // Ensure that the guest is also blurred. 678 ASSERT_TRUE(next_step_listener.WaitUntilSatisfied()); 679 } 680 681 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_AdvanceFocus) { 682 content::WebContents* embedder_web_contents = NULL; 683 684 { 685 scoped_ptr<ExtensionTestMessageListener> done_listener( 686 RunAppHelper("testAdvanceFocus", "web_view/focus", NO_TEST_SERVER, 687 &embedder_web_contents)); 688 done_listener->WaitUntilSatisfied(); 689 } 690 691 { 692 ExtensionTestMessageListener listener("button1-focused", false); 693 listener.set_failure_message("TEST_FAILED"); 694 SimulateRWHMouseClick(embedder_web_contents->GetRenderViewHost(), 695 blink::WebMouseEvent::ButtonLeft, 200, 20); 696 content::SimulateKeyPress(embedder_web_contents, ui::VKEY_TAB, 697 false, false, false, false); 698 ASSERT_TRUE(listener.WaitUntilSatisfied()); 699 } 700 701 { 702 // Wait for button1 to be focused again, this means we were asked to 703 // move the focus to the next focusable element. 704 ExtensionTestMessageListener listener("button1-advance-focus", false); 705 listener.set_failure_message("TEST_FAILED"); 706 // TODO(fsamuel): A third Tab key press should not be necessary. 707 // The <webview> will take keyboard focus but it will not focus an initial 708 // element. The initial element is dependent upon tab direction which blink 709 // does not propagate to the plugin. 710 // See http://crbug.com/147644. 711 content::SimulateKeyPress(embedder_web_contents, ui::VKEY_TAB, 712 false, false, false, false); 713 content::SimulateKeyPress(embedder_web_contents, ui::VKEY_TAB, 714 false, false, false, false); 715 content::SimulateKeyPress(embedder_web_contents, ui::VKEY_TAB, 716 false, false, false, false); 717 ASSERT_TRUE(listener.WaitUntilSatisfied()); 718 } 719 } 720 721 // Tests that blurring <webview> also blurs the guest. 722 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_BlurEvent) { 723 TestHelper("testBlurEvent", "web_view/focus", NO_TEST_SERVER); 724 } 725 726 // Tests that guests receive edit commands and respond appropriately. 727 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, EditCommands) { 728 LoadAndLaunchPlatformApp("web_view/edit_commands", "connected"); 729 730 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow( 731 GetPlatformAppWindow())); 732 733 // Flush any pending events to make sure we start with a clean slate. 734 content::RunAllPendingInMessageLoop(); 735 736 ExtensionTestMessageListener copy_listener("copy", false); 737 SendCopyKeyPressToPlatformApp(); 738 739 // Wait for the guest to receive a 'copy' edit command. 740 ASSERT_TRUE(copy_listener.WaitUntilSatisfied()); 741 } 742 743 // Tests that guests receive edit commands and respond appropriately. 744 // http://crbug.com/417892 745 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_EditCommandsNoMenu) { 746 SetupTest("web_view/edit_commands_no_menu", 747 "/extensions/platform_apps/web_view/edit_commands_no_menu/" 748 "guest.html"); 749 750 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow( 751 GetPlatformAppWindow())); 752 753 // Flush any pending events to make sure we start with a clean slate. 754 content::RunAllPendingInMessageLoop(); 755 756 ExtensionTestMessageListener start_of_line_listener("StartOfLine", false); 757 SendStartOfLineKeyPressToPlatformApp(); 758 // Wait for the guest to receive a 'copy' edit command. 759 ASSERT_TRUE(start_of_line_listener.WaitUntilSatisfied()); 760 } 761 762 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, 763 NewWindow_AttachAfterOpenerDestroyed) { 764 TestHelper("testNewWindowAttachAfterOpenerDestroyed", 765 "web_view/newwindow", 766 NEEDS_TEST_SERVER); 767 } 768 769 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, 770 NewWindow_NewWindowNameTakesPrecedence) { 771 TestHelper("testNewWindowNameTakesPrecedence", 772 "web_view/newwindow", 773 NEEDS_TEST_SERVER); 774 } 775 776 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, 777 NewWindow_WebViewNameTakesPrecedence) { 778 TestHelper("testNewWindowWebViewNameTakesPrecedence", 779 "web_view/newwindow", 780 NEEDS_TEST_SERVER); 781 } 782 783 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_NoName) { 784 TestHelper("testNewWindowNoName", 785 "web_view/newwindow", 786 NEEDS_TEST_SERVER); 787 } 788 789 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_Redirect) { 790 TestHelper("testNewWindowRedirect", 791 "web_view/newwindow", 792 NEEDS_TEST_SERVER); 793 } 794 795 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_Close) { 796 TestHelper("testNewWindowClose", 797 "web_view/newwindow", 798 NEEDS_TEST_SERVER); 799 } 800 801 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_DeferredAttachment) { 802 TestHelper("testNewWindowDeferredAttachment", 803 "web_view/newwindow", 804 NEEDS_TEST_SERVER); 805 } 806 807 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_ExecuteScript) { 808 TestHelper("testNewWindowExecuteScript", 809 "web_view/newwindow", 810 NEEDS_TEST_SERVER); 811 } 812 813 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, 814 NewWindow_DeclarativeWebRequest) { 815 TestHelper("testNewWindowDeclarativeWebRequest", 816 "web_view/newwindow", 817 NEEDS_TEST_SERVER); 818 } 819 820 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, 821 NewWindow_DiscardAfterOpenerDestroyed) { 822 TestHelper("testNewWindowDiscardAfterOpenerDestroyed", 823 "web_view/newwindow", 824 NEEDS_TEST_SERVER); 825 } 826 827 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_WebRequest) { 828 TestHelper("testNewWindowWebRequest", 829 "web_view/newwindow", 830 NEEDS_TEST_SERVER); 831 } 832 833 // A custom elements bug needs to be addressed to enable this test: 834 // See http://crbug.com/282477 for more information. 835 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, 836 DISABLED_NewWindow_WebRequestCloseWindow) { 837 TestHelper("testNewWindowWebRequestCloseWindow", 838 "web_view/newwindow", 839 NEEDS_TEST_SERVER); 840 } 841 842 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, 843 NewWindow_WebRequestRemoveElement) { 844 TestHelper("testNewWindowWebRequestRemoveElement", 845 "web_view/newwindow", 846 NEEDS_TEST_SERVER); 847 } 848 849 // Tests that Ctrl+Click/Cmd+Click on a link fires up the newwindow API. 850 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_OpenInNewTab) { 851 content::WebContents* embedder_web_contents = NULL; 852 853 ExtensionTestMessageListener loaded_listener("Loaded", false); 854 scoped_ptr<ExtensionTestMessageListener> done_listener( 855 RunAppHelper("testNewWindowOpenInNewTab", 856 "web_view/newwindow", 857 NEEDS_TEST_SERVER, 858 &embedder_web_contents)); 859 860 loaded_listener.WaitUntilSatisfied(); 861 #if defined(OS_MACOSX) 862 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( 863 GetPlatformAppWindow(), ui::VKEY_RETURN, 864 false, false, false, true /* cmd */)); 865 #else 866 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( 867 GetPlatformAppWindow(), ui::VKEY_RETURN, 868 true /* ctrl */, false, false, false)); 869 #endif 870 871 // Wait for the embedder to receive a 'newwindow' event. 872 ASSERT_TRUE(done_listener->WaitUntilSatisfied()); 873 } 874 875 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, 876 NewWindow_OpenerDestroyedWhileUnattached) { 877 TestHelper("testNewWindowOpenerDestroyedWhileUnattached", 878 "web_view/newwindow", 879 NEEDS_TEST_SERVER); 880 ASSERT_EQ(2u, GetGuestViewManager()->guest_add_count()); 881 882 // We have two guests in this test, one is the intial one, the other 883 // is the newwindow one. 884 // Before the embedder goes away, both the guests should go away. 885 // This ensures that unattached guests are gone if opener is gone. 886 GetGuestViewManager()->WaitForGuestRemoved(2u); 887 } 888 889 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, ExecuteCode) { 890 ASSERT_TRUE(RunPlatformAppTestWithArg( 891 "platform_apps/web_view/common", "execute_code")) << message_; 892 } 893 894 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, PopupPositioningBasic) { 895 TestHelper("testBasic", "web_view/popup_positioning", NO_TEST_SERVER); 896 ASSERT_TRUE(guest_web_contents()); 897 PopupTestHelper(gfx::Point()); 898 899 // TODO(lazyboy): Move the embedder window to a random location and 900 // make sure we keep rendering popups correct in webview. 901 } 902 903 // Tests that moving browser plugin (without resize/UpdateRects) correctly 904 // repositions popup. 905 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, PopupPositioningMoved) { 906 TestHelper("testMoved", "web_view/popup_positioning", NO_TEST_SERVER); 907 ASSERT_TRUE(guest_web_contents()); 908 PopupTestHelper(gfx::Point(20, 0)); 909 } 910 911 // Drag and drop inside a webview is currently only enabled for linux and mac, 912 // but the tests don't work on anything except chromeos for now. This is because 913 // of simulating mouse drag code's dependency on platforms. 914 #if defined(OS_CHROMEOS) && !defined(USE_OZONE) 915 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DragDropWithinWebView) { 916 LoadAndLaunchPlatformApp("web_view/dnd_within_webview", "connected"); 917 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow())); 918 919 embedder_web_contents_ = GetFirstAppWindowWebContents(); 920 gfx::Rect offset = embedder_web_contents_->GetContainerBounds(); 921 corner_ = gfx::Point(offset.x(), offset.y()); 922 923 // In the drag drop test we add 20px padding to the page body because on 924 // windows if we get too close to the edge of the window the resize cursor 925 // appears and we start dragging the window edge. 926 corner_.Offset(20, 20); 927 928 // Flush any pending events to make sure we start with a clean slate. 929 content::RunAllPendingInMessageLoop(); 930 for (;;) { 931 base::RunLoop run_loop; 932 quit_closure_ = run_loop.QuitClosure(); 933 base::MessageLoop::current()->PostTask( 934 FROM_HERE, 935 base::Bind(&WebViewInteractiveTest::DragTestStep1, 936 base::Unretained(this))); 937 run_loop.Run(); 938 939 if (last_drop_data_ == "Drop me") 940 break; 941 942 LOG(INFO) << "Drag was cancelled in interactive_test, restarting drag"; 943 944 // Reset state for next try. 945 ExtensionTestMessageListener reset_listener("resetStateReply", false); 946 EXPECT_TRUE(content::ExecuteScript(embedder_web_contents_, 947 "window.resetState()")); 948 ASSERT_TRUE(reset_listener.WaitUntilSatisfied()); 949 } 950 ASSERT_EQ("Drop me", last_drop_data_); 951 } 952 #endif // (defined(OS_CHROMEOS)) 953 954 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Navigation) { 955 TestHelper("testNavigation", "web_view/navigation", NO_TEST_SERVER); 956 } 957 958 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Navigation_BackForwardKeys) { 959 LoadAndLaunchPlatformApp("web_view/navigation", "Launched"); 960 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow( 961 GetPlatformAppWindow())); 962 // Flush any pending events to make sure we start with a clean slate. 963 content::RunAllPendingInMessageLoop(); 964 965 content::WebContents* embedder_web_contents = GetFirstAppWindowWebContents(); 966 ASSERT_TRUE(embedder_web_contents); 967 968 ExtensionTestMessageListener done_listener( 969 "TEST_PASSED", false); 970 done_listener.set_failure_message("TEST_FAILED"); 971 ExtensionTestMessageListener ready_back_key_listener( 972 "ReadyForBackKey", false); 973 ExtensionTestMessageListener ready_forward_key_listener( 974 "ReadyForForwardKey", false); 975 976 EXPECT_TRUE(content::ExecuteScript( 977 embedder_web_contents, 978 "runTest('testBackForwardKeys')")); 979 980 ASSERT_TRUE(ready_back_key_listener.WaitUntilSatisfied()); 981 SendBackShortcutToPlatformApp(); 982 983 ASSERT_TRUE(ready_forward_key_listener.WaitUntilSatisfied()); 984 SendForwardShortcutToPlatformApp(); 985 986 ASSERT_TRUE(done_listener.WaitUntilSatisfied()); 987 } 988 989 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, 990 PointerLock_PointerLockLostWithFocus) { 991 TestHelper("testPointerLockLostWithFocus", 992 "web_view/pointerlock", 993 NO_TEST_SERVER); 994 } 995 996 // This test exercies the following scenario: 997 // 1. An <input> in guest has focus. 998 // 2. User takes focus to embedder by clicking e.g. an <input> in embedder. 999 // 3. User brings back the focus directly to the <input> in #1. 1000 // 1001 // Now we need to make sure TextInputTypeChanged fires properly for the guest's 1002 // view upon step #3. We simply read the input type's state after #3 to 1003 // make sure it's not TEXT_INPUT_TYPE_NONE. 1004 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_FocusRestored) { 1005 TestHelper("testFocusRestored", "web_view/focus", NO_TEST_SERVER); 1006 content::WebContents* embedder_web_contents = GetFirstAppWindowWebContents(); 1007 ASSERT_TRUE(embedder_web_contents); 1008 ASSERT_TRUE(guest_web_contents()); 1009 1010 // 1) We click on the guest so that we get a focus event. 1011 ExtensionTestMessageListener next_step_listener("TEST_STEP_PASSED", false); 1012 next_step_listener.set_failure_message("TEST_STEP_FAILED"); 1013 { 1014 content::SimulateMouseClickAt(guest_web_contents(), 1015 0, 1016 blink::WebMouseEvent::ButtonLeft, 1017 gfx::Point(10, 10)); 1018 EXPECT_TRUE(content::ExecuteScript( 1019 embedder_web_contents, 1020 "window.runCommand('testFocusRestoredRunNextStep', 1);")); 1021 } 1022 // Wait for the next step to complete. 1023 ASSERT_TRUE(next_step_listener.WaitUntilSatisfied()); 1024 1025 // 2) We click on the embedder so the guest's focus goes away and it observes 1026 // a blur event. 1027 next_step_listener.Reset(); 1028 { 1029 content::SimulateMouseClickAt(embedder_web_contents, 1030 0, 1031 blink::WebMouseEvent::ButtonLeft, 1032 gfx::Point(200, 20)); 1033 EXPECT_TRUE(content::ExecuteScript( 1034 embedder_web_contents, 1035 "window.runCommand('testFocusRestoredRunNextStep', 2);")); 1036 } 1037 // Wait for the next step to complete. 1038 ASSERT_TRUE(next_step_listener.WaitUntilSatisfied()); 1039 1040 // 3) We click on the guest again to bring back focus directly to the previous 1041 // input element, then we ensure text_input_type is properly set. 1042 next_step_listener.Reset(); 1043 { 1044 content::SimulateMouseClickAt(guest_web_contents(), 1045 0, 1046 blink::WebMouseEvent::ButtonLeft, 1047 gfx::Point(10, 10)); 1048 EXPECT_TRUE(content::ExecuteScript( 1049 embedder_web_contents, 1050 "window.runCommand('testFocusRestoredRunNextStep', 3)")); 1051 } 1052 // Wait for the next step to complete. 1053 ASSERT_TRUE(next_step_listener.WaitUntilSatisfied()); 1054 1055 // |text_input_client| is not available for mac and android. 1056 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) 1057 ui::TextInputClient* text_input_client = 1058 embedder_web_contents->GetRenderViewHost()->GetView() 1059 ->GetTextInputClient(); 1060 ASSERT_TRUE(text_input_client); 1061 ASSERT_TRUE(text_input_client->GetTextInputType() != 1062 ui::TEXT_INPUT_TYPE_NONE); 1063 #endif 1064 } 1065 1066 // ui::TextInputClient is NULL for mac and android. 1067 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) 1068 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_Focus_InputMethod) { 1069 content::WebContents* embedder_web_contents = NULL; 1070 scoped_ptr<ExtensionTestMessageListener> done_listener( 1071 RunAppHelper("testInputMethod", "web_view/focus", NO_TEST_SERVER, 1072 &embedder_web_contents)); 1073 ASSERT_TRUE(done_listener->WaitUntilSatisfied()); 1074 1075 ui::TextInputClient* text_input_client = 1076 embedder_web_contents->GetRenderViewHost()->GetView() 1077 ->GetTextInputClient(); 1078 ASSERT_TRUE(text_input_client); 1079 1080 ExtensionTestMessageListener next_step_listener("TEST_STEP_PASSED", false); 1081 next_step_listener.set_failure_message("TEST_STEP_FAILED"); 1082 1083 // An input element inside the <webview> gets focus and is given some 1084 // user input via IME. 1085 { 1086 ui::CompositionText composition; 1087 composition.text = base::UTF8ToUTF16("InputTest123"); 1088 text_input_client->SetCompositionText(composition); 1089 EXPECT_TRUE(content::ExecuteScript( 1090 embedder_web_contents, 1091 "window.runCommand('testInputMethodRunNextStep', 1);")); 1092 1093 // Wait for the next step to complete. 1094 ASSERT_TRUE(next_step_listener.WaitUntilSatisfied()); 1095 } 1096 1097 // A composition is committed via IME. 1098 { 1099 next_step_listener.Reset(); 1100 1101 ui::CompositionText composition; 1102 composition.text = base::UTF8ToUTF16("InputTest456"); 1103 text_input_client->SetCompositionText(composition); 1104 text_input_client->ConfirmCompositionText(); 1105 EXPECT_TRUE(content::ExecuteScript( 1106 embedder_web_contents, 1107 "window.runCommand('testInputMethodRunNextStep', 2);")); 1108 1109 // Wait for the next step to complete. 1110 EXPECT_TRUE(next_step_listener.WaitUntilSatisfied()); 1111 } 1112 1113 // Moving focus causes IME cancel, and the composition will be committed 1114 // in first <input> in the <webview>, not in the second <input>. 1115 { 1116 next_step_listener.Reset(); 1117 ui::CompositionText composition; 1118 composition.text = base::UTF8ToUTF16("InputTest789"); 1119 text_input_client->SetCompositionText(composition); 1120 EXPECT_TRUE(content::ExecuteScript( 1121 embedder_web_contents, 1122 "window.runCommand('testInputMethodRunNextStep', 3);")); 1123 1124 // Wait for the next step to complete. 1125 EXPECT_TRUE(next_step_listener.WaitUntilSatisfied()); 1126 } 1127 1128 // Tests ExtendSelectionAndDelete message works in <webview>. 1129 { 1130 next_step_listener.Reset(); 1131 1132 // At this point we have set focus on first <input> in the <webview>, 1133 // and the value it contains is 'InputTestABC' with caret set after 'T'. 1134 // Now we delete 'Test' in 'InputTestABC', as the caret is after 'T': 1135 // delete before 1 character ('T') and after 3 characters ('est'). 1136 text_input_client->ExtendSelectionAndDelete(1, 3); 1137 EXPECT_TRUE(content::ExecuteScript( 1138 embedder_web_contents, 1139 "window.runCommand('testInputMethodRunNextStep', 4);")); 1140 1141 // Wait for the next step to complete. 1142 EXPECT_TRUE(next_step_listener.WaitUntilSatisfied()); 1143 } 1144 } 1145 #endif 1146 1147 #if defined(OS_MACOSX) 1148 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, TextSelection) { 1149 SetupTest("web_view/text_selection", 1150 "/extensions/platform_apps/web_view/text_selection/guest.html"); 1151 ASSERT_TRUE(guest_web_contents()); 1152 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow( 1153 GetPlatformAppWindow())); 1154 1155 // Wait until guest sees a context menu, select an arbitrary item (copy). 1156 ExtensionTestMessageListener ctx_listener("MSG_CONTEXTMENU", false); 1157 ContextMenuNotificationObserver menu_observer(IDC_CONTENT_CONTEXT_COPY); 1158 SimulateRWHMouseClick(guest_web_contents()->GetRenderViewHost(), 1159 blink::WebMouseEvent::ButtonRight, 20, 20); 1160 ASSERT_TRUE(ctx_listener.WaitUntilSatisfied()); 1161 1162 // Now verify that the selection text propagates properly to RWHV. 1163 content::RenderWidgetHostView* guest_rwhv = 1164 guest_web_contents()->GetRenderWidgetHostView(); 1165 ASSERT_TRUE(guest_rwhv); 1166 std::string selected_text = base::UTF16ToUTF8(guest_rwhv->GetSelectedText()); 1167 ASSERT_TRUE(selected_text.size() >= 10u); 1168 ASSERT_EQ("AAAAAAAAAA", selected_text.substr(0, 10)); 1169 } 1170 #endif 1171