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.
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"
36 using extensions::AppWindow
;
38 class TestGuestViewManager
: public extensions::GuestViewManager
{
40 explicit TestGuestViewManager(content::BrowserContext
* context
)
41 : GuestViewManager(context
),
43 guest_remove_count_(0),
44 web_contents_(NULL
) {}
46 content::WebContents
* WaitForGuestAdded() {
50 add_message_loop_runner_
= new content::MessageLoopRunner
;
51 add_message_loop_runner_
->Run();
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
)
61 remove_message_loop_runner_
= new content::MessageLoopRunner
;
62 remove_message_loop_runner_
->Run();
65 size_t guest_add_count() { return guest_add_count_
; }
68 // GuestViewManager override:
69 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
;
75 if (add_message_loop_runner_
.get())
76 add_message_loop_runner_
->Quit();
79 void RemoveGuest(int guest_instance_id
) override
{
80 GuestViewManager::RemoveGuest(guest_instance_id
);
81 ++guest_remove_count_
;
83 if (remove_message_loop_runner_
.get())
84 remove_message_loop_runner_
->Quit();
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_
;
94 // Test factory for creating test instances of GuestViewManager.
95 class TestGuestViewManagerFactory
: public extensions::GuestViewManagerFactory
{
97 TestGuestViewManagerFactory() :
98 test_guest_view_manager_(NULL
) {}
100 ~TestGuestViewManagerFactory() override
{}
102 extensions::GuestViewManager
* CreateGuestViewManager(
103 content::BrowserContext
* context
) override
{
104 return GetManager(context
);
107 TestGuestViewManager
* GetManager(content::BrowserContext
* context
) {
108 if (!test_guest_view_manager_
) {
109 test_guest_view_manager_
= new TestGuestViewManager(context
);
111 return test_guest_view_manager_
;
115 TestGuestViewManager
* test_guest_view_manager_
;
117 DISALLOW_COPY_AND_ASSIGN(TestGuestViewManagerFactory
);
120 class WebViewInteractiveTest
121 : public extensions::PlatformAppBrowserTest
{
123 WebViewInteractiveTest()
124 : guest_web_contents_(NULL
),
125 embedder_web_contents_(NULL
),
126 corner_(gfx::Point()),
127 mouse_click_result_(false),
129 extensions::GuestViewManager::set_factory_for_testing(&factory_
);
132 TestGuestViewManager
* GetGuestViewManager() {
133 return factory_
.GetManager(browser()->profile());
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());
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());
151 void SendMouseClick(ui_controls::MouseButton button
) {
152 SendMouseEvent(button
, ui_controls::DOWN
);
153 SendMouseEvent(button
, ui_controls::UP
);
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())));
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();
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));
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));
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));
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));
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));
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));
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));
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));
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));
224 void SendMouseEvent(ui_controls::MouseButton button
,
225 ui_controls::MouseButtonState state
) {
227 mouse_click_result_
= ui_test_utils::SendMouseEventsSync(button
,
229 first_click_
= false;
231 ASSERT_EQ(mouse_click_result_
, ui_test_utils::SendMouseEventsSync(
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
>();
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
>();
258 // Flush any pending events to make sure we start with a clean slate.
259 content::RunAllPendingInMessageLoop();
261 *embedder_web_contents
= GetFirstAppWindowWebContents();
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
>();
273 return done_listener
.Pass();
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(
282 test_name
, app_location
, test_server
, &embedder_web_contents
));
284 ASSERT_TRUE(done_listener
);
285 ASSERT_TRUE(done_listener
->WaitUntilSatisfied());
287 guest_web_contents_
= GetGuestViewManager()->WaitForGuestAdded();
290 void RunTest(const std::string
& app_name
) {
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 replace_host
.SetHostStr("localhost");
298 GURL guest_url
= embedded_test_server()->GetURL(guest_url_spec
);
299 guest_url
= guest_url
.ReplaceComponents(replace_host
);
301 ui_test_utils::UrlLoadObserver
guest_observer(
302 guest_url
, content::NotificationService::AllSources());
304 LoadAndLaunchPlatformApp(app_name
.c_str(), "connected");
306 guest_observer
.Wait();
307 content::Source
<content::NavigationController
> source
=
308 guest_observer
.source();
309 EXPECT_TRUE(source
->GetWebContents()->GetRenderProcessHost()->
312 guest_web_contents_
= source
->GetWebContents();
313 embedder_web_contents_
=
314 extensions::GuestViewBase::FromWebContents(guest_web_contents_
)->
315 embedder_web_contents();
317 gfx::Rect offset
= embedder_web_contents_
->GetContainerBounds();
318 corner_
= gfx::Point(offset
.x(), offset
.y());
320 const testing::TestInfo
* const test_info
=
321 testing::UnitTest::GetInstance()->current_test_info();
322 const char* prefix
= "DragDropWithinWebView";
323 if (!strncmp(test_info
->name(), prefix
, strlen(prefix
))) {
324 // In the drag drop test we add 20px padding to the page body because on
325 // windows if we get too close to the edge of the window the resize cursor
326 // appears and we start dragging the window edge.
327 corner_
.Offset(20, 20);
331 content::WebContents
* guest_web_contents() {
332 return guest_web_contents_
;
335 content::WebContents
* embedder_web_contents() {
336 return embedder_web_contents_
;
339 gfx::Point
corner() {
343 void SimulateRWHMouseClick(content::RenderWidgetHost
* rwh
,
344 blink::WebMouseEvent::Button button
,
347 blink::WebMouseEvent mouse_event
;
348 mouse_event
.button
= button
;
349 mouse_event
.x
= mouse_event
.windowX
= x
;
350 mouse_event
.y
= mouse_event
.windowY
= y
;
351 mouse_event
.modifiers
= 0;
353 mouse_event
.type
= blink::WebInputEvent::MouseDown
;
354 rwh
->ForwardMouseEvent(mouse_event
);
355 mouse_event
.type
= blink::WebInputEvent::MouseUp
;
356 rwh
->ForwardMouseEvent(mouse_event
);
359 class PopupCreatedObserver
{
361 PopupCreatedObserver()
362 : initial_widget_count_(0),
363 last_render_widget_host_(NULL
),
364 seen_new_widget_(false) {}
366 ~PopupCreatedObserver() {}
369 size_t current_widget_count
= CountWidgets();
370 if (!seen_new_widget_
&&
371 current_widget_count
== initial_widget_count_
+ 1) {
372 seen_new_widget_
= true;
375 // If we haven't seen any new widget or we get 0 size widget, we need to
377 bool needs_to_schedule_wait
= true;
379 if (seen_new_widget_
) {
380 gfx::Rect popup_bounds
=
381 last_render_widget_host_
->GetView()->GetViewBounds();
382 if (!popup_bounds
.size().IsEmpty())
383 needs_to_schedule_wait
= false;
386 if (needs_to_schedule_wait
) {
390 if (message_loop_
.get())
391 message_loop_
->Quit();
394 if (!message_loop_
.get()) {
395 message_loop_
= new content::MessageLoopRunner
;
396 message_loop_
->Run();
400 void Init() { initial_widget_count_
= CountWidgets(); }
402 // Returns the last widget created.
403 content::RenderWidgetHost
* last_render_widget_host() {
404 return last_render_widget_host_
;
408 void ScheduleWait() {
409 base::MessageLoop::current()->PostDelayedTask(
411 base::Bind(&PopupCreatedObserver::Wait
, base::Unretained(this)),
412 base::TimeDelta::FromMilliseconds(200));
415 size_t CountWidgets() {
416 scoped_ptr
<content::RenderWidgetHostIterator
> widgets(
417 content::RenderWidgetHost::GetRenderWidgetHosts());
418 size_t num_widgets
= 0;
419 while (content::RenderWidgetHost
* widget
= widgets
->GetNextHost()) {
420 if (widget
->IsRenderView())
423 last_render_widget_host_
= widget
;
428 size_t initial_widget_count_
;
429 content::RenderWidgetHost
* last_render_widget_host_
;
430 scoped_refptr
<content::MessageLoopRunner
> message_loop_
;
431 bool seen_new_widget_
;
433 DISALLOW_COPY_AND_ASSIGN(PopupCreatedObserver
);
436 void WaitForTitle(const char* title
) {
437 base::string16
expected_title(base::ASCIIToUTF16(title
));
438 base::string16
error_title(base::ASCIIToUTF16("FAILED"));
439 content::TitleWatcher
title_watcher(guest_web_contents(), expected_title
);
440 title_watcher
.AlsoWaitForTitle(error_title
);
441 ASSERT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
444 void PopupTestHelper(const gfx::Point
& padding
) {
445 PopupCreatedObserver popup_observer
;
446 popup_observer
.Init();
447 // Press alt+DOWN to open popup.
449 content::SimulateKeyPress(
450 guest_web_contents(), ui::VKEY_DOWN
, false, false, alt
, false);
451 popup_observer
.Wait();
453 content::RenderWidgetHost
* popup_rwh
=
454 popup_observer
.last_render_widget_host();
455 gfx::Rect popup_bounds
= popup_rwh
->GetView()->GetViewBounds();
457 content::RenderViewHost
* embedder_rvh
=
458 GetFirstAppWindowWebContents()->GetRenderViewHost();
459 gfx::Rect embedder_bounds
= embedder_rvh
->GetView()->GetViewBounds();
460 gfx::Vector2d diff
= popup_bounds
.origin() - embedder_bounds
.origin();
461 LOG(INFO
) << "DIFF: x = " << diff
.x() << ", y = " << diff
.y();
463 const int left_spacing
= 40 + padding
.x(); // div.style.paddingLeft = 40px.
464 // div.style.paddingTop = 50px + (input box height = 26px).
465 const int top_spacing
= 50 + 26 + padding
.y();
467 // If the popup is placed within |threshold_px| of the expected position,
468 // then we consider the test as a pass.
469 const int threshold_px
= 10;
471 EXPECT_LE(std::abs(diff
.x() - left_spacing
), threshold_px
);
472 EXPECT_LE(std::abs(diff
.y() - top_spacing
), threshold_px
);
475 content::SimulateKeyPress(
476 guest_web_contents(), ui::VKEY_ESCAPE
, false, false, false, false);
479 void DragTestStep1() {
480 // Move mouse to start of text.
481 MoveMouseInsideWindow(gfx::Point(45, 8));
482 MoveMouseInsideWindow(gfx::Point(45, 9));
483 SendMouseEvent(ui_controls::LEFT
, ui_controls::DOWN
);
485 MoveMouseInsideWindow(gfx::Point(74, 12));
486 MoveMouseInsideWindow(gfx::Point(78, 12));
488 // Now wait a bit before moving mouse to initiate drag/drop.
489 base::MessageLoop::current()->PostDelayedTask(
491 base::Bind(&WebViewInteractiveTest::DragTestStep2
,
492 base::Unretained(this)),
493 base::TimeDelta::FromMilliseconds(200));
496 void DragTestStep2() {
497 // Drag source over target.
498 MoveMouseInsideWindow(gfx::Point(76, 76));
500 // Create a second mouse over the source to trigger the drag over event.
501 MoveMouseInsideWindow(gfx::Point(76, 77));
503 // Release mouse to drop.
504 SendMouseEvent(ui_controls::LEFT
, ui_controls::UP
);
505 SendMouseClick(ui_controls::LEFT
);
509 // Note that following ExtensionTestMessageListener and ExecuteScript*
510 // call must be after we quit |quit_closure_|. Otherwise the class
511 // here won't be able to receive messages sent by chrome.test.sendMessage.
512 // This is because of the nature of drag and drop code (esp. the
513 // MessageLoop) in it.
515 // Now check if we got a drop and read the drop data.
516 embedder_web_contents_
= GetFirstAppWindowWebContents();
517 ExtensionTestMessageListener
drop_listener("guest-got-drop", false);
518 EXPECT_TRUE(content::ExecuteScript(embedder_web_contents_
,
519 "window.checkIfGuestGotDrop()"));
520 EXPECT_TRUE(drop_listener
.WaitUntilSatisfied());
522 std::string last_drop_data
;
523 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
524 embedder_web_contents_
,
525 "window.domAutomationController.send(getLastDropData())",
528 last_drop_data_
= last_drop_data
;
532 TestGuestViewManagerFactory factory_
;
533 content::WebContents
* guest_web_contents_
;
534 content::WebContents
* embedder_web_contents_
;
536 bool mouse_click_result_
;
538 // Only used in drag/drop test.
539 base::Closure quit_closure_
;
540 std::string last_drop_data_
;
543 // ui_test_utils::SendMouseMoveSync doesn't seem to work on OS_MACOSX, and
544 // likely won't work on many other platforms as well, so for now this test
545 // is for Windows and Linux only. As of Sept 17th, 2013 this test is disabled
546 // on Windows due to flakines, see http://crbug.com/293445.
548 // Disabled on Linux Aura because pointer lock does not work on Linux Aura.
551 #if defined(OS_LINUX)
552 // flaky http://crbug.com/412086
553 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, DISABLED_PointerLock
) {
554 SetupTest("web_view/pointer_lock",
555 "/extensions/platform_apps/web_view/pointer_lock/guest.html");
557 // Move the mouse over the Lock Pointer button.
558 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
559 gfx::Point(corner().x() + 75, corner().y() + 25)));
561 // Click the Lock Pointer button. The first two times the button is clicked
562 // the permission API will deny the request (intentional).
563 ExtensionTestMessageListener
exception_listener("request exception", false);
564 SendMouseClickWithListener(ui_controls::LEFT
, "lock error");
565 ASSERT_TRUE(exception_listener
.WaitUntilSatisfied());
566 SendMouseClickWithListener(ui_controls::LEFT
, "lock error");
568 // Click the Lock Pointer button, locking the mouse to lockTarget1.
569 SendMouseClickWithListener(ui_controls::LEFT
, "locked");
571 // Attempt to move the mouse off of the lock target, and onto lockTarget2,
572 // (which would trigger a test failure).
573 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
574 gfx::Point(corner().x() + 74, corner().y() + 74)));
575 MoveMouseInsideWindowWithListener(gfx::Point(75, 75), "mouse-move");
578 // When the mouse is unlocked on win aura, sending a test mouse click clicks
579 // where the mouse moved to while locked. I was unable to figure out why, and
580 // since the issue only occurs with the test mouse events, just fix it with
581 // a simple workaround - moving the mouse back to where it should be.
582 // TODO(mthiesse): Fix Win Aura simulated mouse events while mouse locked.
583 MoveMouseInsideWindowWithListener(gfx::Point(75, 25), "mouse-move");
586 ExtensionTestMessageListener
unlocked_listener("unlocked", false);
587 // Send a key press to unlock the mouse.
588 SendKeyPressToPlatformApp(ui::VKEY_ESCAPE
);
590 // Wait for page to receive (successful) mouse unlock response.
591 ASSERT_TRUE(unlocked_listener
.WaitUntilSatisfied());
593 // After the second lock, guest.js sends a message to main.js to remove the
594 // webview object. main.js then removes the div containing the webview, which
595 // should unlock, and leave the mouse over the mousemove-capture-container
596 // div. We then move the mouse over that div to ensure the mouse was properly
597 // unlocked and that the div receieves the message.
598 ExtensionTestMessageListener
move_captured_listener("move-captured", false);
599 move_captured_listener
.set_failure_message("timeout");
601 // Mouse should already be over lock button (since we just unlocked), so send
602 // click to re-lock the mouse.
603 SendMouseClickWithListener(ui_controls::LEFT
, "deleted");
605 // A mousemove event is triggered on the mousemove-capture-container element
606 // when we delete the webview container (since the mouse moves onto the
607 // element), but just in case, send an explicit mouse movement to be safe.
608 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
609 gfx::Point(corner().x() + 50, corner().y() + 10)));
611 // Wait for page to receive second (successful) mouselock response.
612 bool success
= move_captured_listener
.WaitUntilSatisfied();
614 fprintf(stderr
, "TIMEOUT - retrying\n");
615 // About 1 in 40 tests fail to detect mouse moves at this point (why?).
616 // Sending a right click seems to fix this (why?).
617 ExtensionTestMessageListener
move_listener2("move-captured", false);
618 SendMouseClick(ui_controls::RIGHT
);
619 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
620 gfx::Point(corner().x() + 51, corner().y() + 11)));
621 ASSERT_TRUE(move_listener2
.WaitUntilSatisfied());
625 // flaky http://crbug.com/412086
626 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, DISABLED_PointerLockFocus
) {
627 SetupTest("web_view/pointer_lock_focus",
628 "/extensions/platform_apps/web_view/pointer_lock_focus/guest.html");
630 // Move the mouse over the Lock Pointer button.
631 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
632 gfx::Point(corner().x() + 75, corner().y() + 25)));
634 // Click the Lock Pointer button, locking the mouse to lockTarget.
635 // This will also change focus to another element
636 SendMouseClickWithListener(ui_controls::LEFT
, "locked");
638 // Try to unlock the mouse now that the focus is outside of the BrowserPlugin
639 ExtensionTestMessageListener
unlocked_listener("unlocked", false);
640 // Send a key press to unlock the mouse.
641 SendKeyPressToPlatformApp(ui::VKEY_ESCAPE
);
643 // Wait for page to receive (successful) mouse unlock response.
644 ASSERT_TRUE(unlocked_listener
.WaitUntilSatisfied());
647 #endif // defined(OS_LINUX)
649 // Tests that if a <webview> is focused before navigation then the guest starts
651 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_FocusBeforeNavigation
) {
652 TestHelper("testFocusBeforeNavigation", "web_view/focus", NO_TEST_SERVER
);
655 // Tests that setting focus on the <webview> sets focus on the guest.
656 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_FocusEvent
) {
657 TestHelper("testFocusEvent", "web_view/focus", NO_TEST_SERVER
);
660 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_FocusTracksEmbedder
) {
661 content::WebContents
* embedder_web_contents
= NULL
;
663 scoped_ptr
<ExtensionTestMessageListener
> done_listener(
664 RunAppHelper("testFocusTracksEmbedder", "web_view/focus", NO_TEST_SERVER
,
665 &embedder_web_contents
));
666 done_listener
->WaitUntilSatisfied();
668 ExtensionTestMessageListener
next_step_listener("TEST_STEP_PASSED", false);
669 next_step_listener
.set_failure_message("TEST_STEP_FAILED");
670 EXPECT_TRUE(content::ExecuteScript(
671 embedder_web_contents
,
672 "window.runCommand('testFocusTracksEmbedderRunNextStep');"));
674 // Blur the embedder.
675 embedder_web_contents
->GetRenderViewHost()->Blur();
676 // Ensure that the guest is also blurred.
677 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
680 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_AdvanceFocus
) {
681 content::WebContents
* embedder_web_contents
= NULL
;
684 scoped_ptr
<ExtensionTestMessageListener
> done_listener(
685 RunAppHelper("testAdvanceFocus", "web_view/focus", NO_TEST_SERVER
,
686 &embedder_web_contents
));
687 done_listener
->WaitUntilSatisfied();
691 ExtensionTestMessageListener
listener("button1-focused", false);
692 listener
.set_failure_message("TEST_FAILED");
693 SimulateRWHMouseClick(embedder_web_contents
->GetRenderViewHost(),
694 blink::WebMouseEvent::ButtonLeft
, 200, 20);
695 content::SimulateKeyPress(embedder_web_contents
, ui::VKEY_TAB
,
696 false, false, false, false);
697 ASSERT_TRUE(listener
.WaitUntilSatisfied());
701 // Wait for button1 to be focused again, this means we were asked to
702 // move the focus to the next focusable element.
703 ExtensionTestMessageListener
listener("button1-advance-focus", false);
704 listener
.set_failure_message("TEST_FAILED");
705 // TODO(fsamuel): A third Tab key press should not be necessary.
706 // The <webview> will take keyboard focus but it will not focus an initial
707 // element. The initial element is dependent upon tab direction which blink
708 // does not propagate to the plugin.
709 // See http://crbug.com/147644.
710 content::SimulateKeyPress(embedder_web_contents
, ui::VKEY_TAB
,
711 false, false, false, false);
712 content::SimulateKeyPress(embedder_web_contents
, ui::VKEY_TAB
,
713 false, false, false, false);
714 content::SimulateKeyPress(embedder_web_contents
, ui::VKEY_TAB
,
715 false, false, false, false);
716 ASSERT_TRUE(listener
.WaitUntilSatisfied());
720 // Tests that blurring <webview> also blurs the guest.
721 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_BlurEvent
) {
722 TestHelper("testBlurEvent", "web_view/focus", NO_TEST_SERVER
);
725 // Tests that guests receive edit commands and respond appropriately.
726 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, EditCommands
) {
727 LoadAndLaunchPlatformApp("web_view/edit_commands", "connected");
729 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
730 GetPlatformAppWindow()));
732 // Flush any pending events to make sure we start with a clean slate.
733 content::RunAllPendingInMessageLoop();
735 ExtensionTestMessageListener
copy_listener("copy", false);
736 SendCopyKeyPressToPlatformApp();
738 // Wait for the guest to receive a 'copy' edit command.
739 ASSERT_TRUE(copy_listener
.WaitUntilSatisfied());
742 // Tests that guests receive edit commands and respond appropriately.
743 // http://crbug.com/417892
744 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, DISABLED_EditCommandsNoMenu
) {
745 SetupTest("web_view/edit_commands_no_menu",
746 "/extensions/platform_apps/web_view/edit_commands_no_menu/"
749 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
750 GetPlatformAppWindow()));
752 // Flush any pending events to make sure we start with a clean slate.
753 content::RunAllPendingInMessageLoop();
755 ExtensionTestMessageListener
start_of_line_listener("StartOfLine", false);
756 SendStartOfLineKeyPressToPlatformApp();
757 // Wait for the guest to receive a 'copy' edit command.
758 ASSERT_TRUE(start_of_line_listener
.WaitUntilSatisfied());
761 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
762 NewWindow_AttachAfterOpenerDestroyed
) {
763 TestHelper("testNewWindowAttachAfterOpenerDestroyed",
764 "web_view/newwindow",
768 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
769 NewWindow_NewWindowNameTakesPrecedence
) {
770 TestHelper("testNewWindowNameTakesPrecedence",
771 "web_view/newwindow",
775 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
776 NewWindow_WebViewNameTakesPrecedence
) {
777 TestHelper("testNewWindowWebViewNameTakesPrecedence",
778 "web_view/newwindow",
782 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_NoName
) {
783 TestHelper("testNewWindowNoName",
784 "web_view/newwindow",
788 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_Redirect
) {
789 TestHelper("testNewWindowRedirect",
790 "web_view/newwindow",
794 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_Close
) {
795 TestHelper("testNewWindowClose",
796 "web_view/newwindow",
800 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_DeferredAttachment
) {
801 TestHelper("testNewWindowDeferredAttachment",
802 "web_view/newwindow",
806 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_ExecuteScript
) {
807 TestHelper("testNewWindowExecuteScript",
808 "web_view/newwindow",
812 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
813 NewWindow_DeclarativeWebRequest
) {
814 TestHelper("testNewWindowDeclarativeWebRequest",
815 "web_view/newwindow",
819 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
820 NewWindow_DiscardAfterOpenerDestroyed
) {
821 TestHelper("testNewWindowDiscardAfterOpenerDestroyed",
822 "web_view/newwindow",
826 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_WebRequest
) {
827 TestHelper("testNewWindowWebRequest",
828 "web_view/newwindow",
832 // A custom elements bug needs to be addressed to enable this test:
833 // See http://crbug.com/282477 for more information.
834 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
835 DISABLED_NewWindow_WebRequestCloseWindow
) {
836 TestHelper("testNewWindowWebRequestCloseWindow",
837 "web_view/newwindow",
841 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
842 NewWindow_WebRequestRemoveElement
) {
843 TestHelper("testNewWindowWebRequestRemoveElement",
844 "web_view/newwindow",
848 // There is a problem of missing keyup events with the command key after
849 // the NSEvent is sent to NSApplication in ui/base/test/ui_controls_mac.mm .
850 // This test is disabled on only the Mac until the problem is resolved.
851 // See http://crbug.com/425859 for more information.
852 #if !defined(OS_MACOSX)
853 // Tests that Ctrl+Click/Cmd+Click on a link fires up the newwindow API.
854 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_OpenInNewTab
) {
855 content::WebContents
* embedder_web_contents
= NULL
;
857 ExtensionTestMessageListener
loaded_listener("Loaded", false);
858 scoped_ptr
<ExtensionTestMessageListener
> done_listener(
859 RunAppHelper("testNewWindowOpenInNewTab",
860 "web_view/newwindow",
862 &embedder_web_contents
));
864 loaded_listener
.WaitUntilSatisfied();
865 #if defined(OS_MACOSX)
866 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
867 GetPlatformAppWindow(), ui::VKEY_RETURN
,
868 false, false, false, true /* cmd */));
870 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
871 GetPlatformAppWindow(), ui::VKEY_RETURN
,
872 true /* ctrl */, false, false, false));
875 // Wait for the embedder to receive a 'newwindow' event.
876 ASSERT_TRUE(done_listener
->WaitUntilSatisfied());
880 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
881 NewWindow_OpenerDestroyedWhileUnattached
) {
882 TestHelper("testNewWindowOpenerDestroyedWhileUnattached",
883 "web_view/newwindow",
885 ASSERT_EQ(2u, GetGuestViewManager()->guest_add_count());
887 // We have two guests in this test, one is the intial one, the other
888 // is the newwindow one.
889 // Before the embedder goes away, both the guests should go away.
890 // This ensures that unattached guests are gone if opener is gone.
891 GetGuestViewManager()->WaitForGuestRemoved(2u);
894 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, ExecuteCode
) {
895 ASSERT_TRUE(RunPlatformAppTestWithArg(
896 "platform_apps/web_view/common", "execute_code")) << message_
;
899 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, PopupPositioningBasic
) {
900 TestHelper("testBasic", "web_view/popup_positioning", NO_TEST_SERVER
);
901 ASSERT_TRUE(guest_web_contents());
902 PopupTestHelper(gfx::Point());
904 // TODO(lazyboy): Move the embedder window to a random location and
905 // make sure we keep rendering popups correct in webview.
908 // Tests that moving browser plugin (without resize/UpdateRects) correctly
909 // repositions popup.
910 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, PopupPositioningMoved
) {
911 TestHelper("testMoved", "web_view/popup_positioning", NO_TEST_SERVER
);
912 ASSERT_TRUE(guest_web_contents());
913 PopupTestHelper(gfx::Point(20, 0));
916 // Drag and drop inside a webview is currently only enabled for linux and mac,
917 // but the tests don't work on anything except chromeos for now. This is because
918 // of simulating mouse drag code's dependency on platforms.
919 #if defined(OS_CHROMEOS) && !defined(USE_OZONE)
920 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, DragDropWithinWebView
) {
921 LoadAndLaunchPlatformApp("web_view/dnd_within_webview", "connected");
922 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow()));
924 embedder_web_contents_
= GetFirstAppWindowWebContents();
925 gfx::Rect offset
= embedder_web_contents_
->GetContainerBounds();
926 corner_
= gfx::Point(offset
.x(), offset
.y());
928 // In the drag drop test we add 20px padding to the page body because on
929 // windows if we get too close to the edge of the window the resize cursor
930 // appears and we start dragging the window edge.
931 corner_
.Offset(20, 20);
933 // Flush any pending events to make sure we start with a clean slate.
934 content::RunAllPendingInMessageLoop();
936 base::RunLoop run_loop
;
937 quit_closure_
= run_loop
.QuitClosure();
938 base::MessageLoop::current()->PostTask(
940 base::Bind(&WebViewInteractiveTest::DragTestStep1
,
941 base::Unretained(this)));
944 if (last_drop_data_
== "Drop me")
947 LOG(INFO
) << "Drag was cancelled in interactive_test, restarting drag";
949 // Reset state for next try.
950 ExtensionTestMessageListener
reset_listener("resetStateReply", false);
951 EXPECT_TRUE(content::ExecuteScript(embedder_web_contents_
,
952 "window.resetState()"));
953 ASSERT_TRUE(reset_listener
.WaitUntilSatisfied());
955 ASSERT_EQ("Drop me", last_drop_data_
);
957 #endif // (defined(OS_CHROMEOS))
959 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Navigation
) {
960 TestHelper("testNavigation", "web_view/navigation", NO_TEST_SERVER
);
963 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Navigation_BackForwardKeys
) {
964 LoadAndLaunchPlatformApp("web_view/navigation", "Launched");
965 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
966 GetPlatformAppWindow()));
967 // Flush any pending events to make sure we start with a clean slate.
968 content::RunAllPendingInMessageLoop();
970 content::WebContents
* embedder_web_contents
= GetFirstAppWindowWebContents();
971 ASSERT_TRUE(embedder_web_contents
);
973 ExtensionTestMessageListener
done_listener(
974 "TEST_PASSED", false);
975 done_listener
.set_failure_message("TEST_FAILED");
976 ExtensionTestMessageListener
ready_back_key_listener(
977 "ReadyForBackKey", false);
978 ExtensionTestMessageListener
ready_forward_key_listener(
979 "ReadyForForwardKey", false);
981 EXPECT_TRUE(content::ExecuteScript(
982 embedder_web_contents
,
983 "runTest('testBackForwardKeys')"));
985 ASSERT_TRUE(ready_back_key_listener
.WaitUntilSatisfied());
986 SendBackShortcutToPlatformApp();
988 ASSERT_TRUE(ready_forward_key_listener
.WaitUntilSatisfied());
989 SendForwardShortcutToPlatformApp();
991 ASSERT_TRUE(done_listener
.WaitUntilSatisfied());
994 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
995 PointerLock_PointerLockLostWithFocus
) {
996 TestHelper("testPointerLockLostWithFocus",
997 "web_view/pointerlock",
1001 // This test exercies the following scenario:
1002 // 1. An <input> in guest has focus.
1003 // 2. User takes focus to embedder by clicking e.g. an <input> in embedder.
1004 // 3. User brings back the focus directly to the <input> in #1.
1006 // Now we need to make sure TextInputTypeChanged fires properly for the guest's
1007 // view upon step #3. We simply read the input type's state after #3 to
1008 // make sure it's not TEXT_INPUT_TYPE_NONE.
1009 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_FocusRestored
) {
1010 TestHelper("testFocusRestored", "web_view/focus", NO_TEST_SERVER
);
1011 content::WebContents
* embedder_web_contents
= GetFirstAppWindowWebContents();
1012 ASSERT_TRUE(embedder_web_contents
);
1013 ASSERT_TRUE(guest_web_contents());
1015 // 1) We click on the guest so that we get a focus event.
1016 ExtensionTestMessageListener
next_step_listener("TEST_STEP_PASSED", false);
1017 next_step_listener
.set_failure_message("TEST_STEP_FAILED");
1019 content::SimulateMouseClickAt(guest_web_contents(),
1021 blink::WebMouseEvent::ButtonLeft
,
1022 gfx::Point(10, 10));
1023 EXPECT_TRUE(content::ExecuteScript(
1024 embedder_web_contents
,
1025 "window.runCommand('testFocusRestoredRunNextStep', 1);"));
1027 // Wait for the next step to complete.
1028 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
1030 // 2) We click on the embedder so the guest's focus goes away and it observes
1032 next_step_listener
.Reset();
1034 content::SimulateMouseClickAt(embedder_web_contents
,
1036 blink::WebMouseEvent::ButtonLeft
,
1037 gfx::Point(200, 20));
1038 EXPECT_TRUE(content::ExecuteScript(
1039 embedder_web_contents
,
1040 "window.runCommand('testFocusRestoredRunNextStep', 2);"));
1042 // Wait for the next step to complete.
1043 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
1045 // 3) We click on the guest again to bring back focus directly to the previous
1046 // input element, then we ensure text_input_type is properly set.
1047 next_step_listener
.Reset();
1049 content::SimulateMouseClickAt(guest_web_contents(),
1051 blink::WebMouseEvent::ButtonLeft
,
1052 gfx::Point(10, 10));
1053 EXPECT_TRUE(content::ExecuteScript(
1054 embedder_web_contents
,
1055 "window.runCommand('testFocusRestoredRunNextStep', 3)"));
1057 // Wait for the next step to complete.
1058 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
1060 // |text_input_client| is not available for mac and android.
1061 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
1062 ui::TextInputClient
* text_input_client
=
1063 embedder_web_contents
->GetRenderViewHost()->GetView()
1064 ->GetTextInputClient();
1065 ASSERT_TRUE(text_input_client
);
1066 ASSERT_TRUE(text_input_client
->GetTextInputType() !=
1067 ui::TEXT_INPUT_TYPE_NONE
);
1071 // ui::TextInputClient is NULL for mac and android.
1072 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
1073 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, DISABLED_Focus_InputMethod
) {
1074 content::WebContents
* embedder_web_contents
= NULL
;
1075 scoped_ptr
<ExtensionTestMessageListener
> done_listener(
1076 RunAppHelper("testInputMethod", "web_view/focus", NO_TEST_SERVER
,
1077 &embedder_web_contents
));
1078 ASSERT_TRUE(done_listener
->WaitUntilSatisfied());
1080 ui::TextInputClient
* text_input_client
=
1081 embedder_web_contents
->GetRenderViewHost()->GetView()
1082 ->GetTextInputClient();
1083 ASSERT_TRUE(text_input_client
);
1085 ExtensionTestMessageListener
next_step_listener("TEST_STEP_PASSED", false);
1086 next_step_listener
.set_failure_message("TEST_STEP_FAILED");
1088 // An input element inside the <webview> gets focus and is given some
1089 // user input via IME.
1091 ui::CompositionText composition
;
1092 composition
.text
= base::UTF8ToUTF16("InputTest123");
1093 text_input_client
->SetCompositionText(composition
);
1094 EXPECT_TRUE(content::ExecuteScript(
1095 embedder_web_contents
,
1096 "window.runCommand('testInputMethodRunNextStep', 1);"));
1098 // Wait for the next step to complete.
1099 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
1102 // A composition is committed via IME.
1104 next_step_listener
.Reset();
1106 ui::CompositionText composition
;
1107 composition
.text
= base::UTF8ToUTF16("InputTest456");
1108 text_input_client
->SetCompositionText(composition
);
1109 text_input_client
->ConfirmCompositionText();
1110 EXPECT_TRUE(content::ExecuteScript(
1111 embedder_web_contents
,
1112 "window.runCommand('testInputMethodRunNextStep', 2);"));
1114 // Wait for the next step to complete.
1115 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
1118 // TODO(lazyboy): http://crbug.com/457007, Add a step or a separate test to
1119 // check the following, currently it turns this test to be flaky:
1120 // If we move the focus from the first <input> to the second one after we
1121 // have some composition text set but *not* committed (by calling
1122 // text_input_client->SetCompositionText()), then it would cause IME cancel
1123 // and the onging composition is committed in the first <input> in the
1124 // <webview>, not the second one.
1126 // Tests ExtendSelectionAndDelete message works in <webview>.
1128 next_step_listener
.Reset();
1130 // At this point we have set focus on first <input> in the <webview>,
1131 // and the value it contains is 'InputTest456' with caret set after 'T'.
1132 // Now we delete 'Test' in 'InputTest456', as the caret is after 'T':
1133 // delete before 1 character ('T') and after 3 characters ('est').
1134 text_input_client
->ExtendSelectionAndDelete(1, 3);
1135 EXPECT_TRUE(content::ExecuteScript(
1136 embedder_web_contents
,
1137 "window.runCommand('testInputMethodRunNextStep', 3);"));
1139 // Wait for the next step to complete.
1140 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
1145 #if defined(OS_MACOSX)
1146 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, TextSelection
) {
1147 SetupTest("web_view/text_selection",
1148 "/extensions/platform_apps/web_view/text_selection/guest.html");
1149 ASSERT_TRUE(guest_web_contents());
1150 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
1151 GetPlatformAppWindow()));
1153 // Wait until guest sees a context menu, select an arbitrary item (copy).
1154 ExtensionTestMessageListener
ctx_listener("MSG_CONTEXTMENU", false);
1155 ContextMenuNotificationObserver
menu_observer(IDC_CONTENT_CONTEXT_COPY
);
1156 SimulateRWHMouseClick(guest_web_contents()->GetRenderViewHost(),
1157 blink::WebMouseEvent::ButtonRight
, 20, 20);
1158 ASSERT_TRUE(ctx_listener
.WaitUntilSatisfied());
1160 // Now verify that the selection text propagates properly to RWHV.
1161 content::RenderWidgetHostView
* guest_rwhv
=
1162 guest_web_contents()->GetRenderWidgetHostView();
1163 ASSERT_TRUE(guest_rwhv
);
1164 std::string selected_text
= base::UTF16ToUTF8(guest_rwhv
->GetSelectedText());
1165 ASSERT_TRUE(selected_text
.size() >= 10u);
1166 ASSERT_EQ("AAAAAAAAAA", selected_text
.substr(0, 10));