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 "apps/app_window.h"
6 #include "apps/app_window_registry.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/app/chrome_command_ids.h"
10 #include "chrome/browser/apps/app_browsertest_util.h"
11 #include "chrome/browser/chrome_content_browser_client.h"
12 #include "chrome/browser/extensions/extension_test_message_listener.h"
13 #include "chrome/browser/guest_view/guest_view_base.h"
14 #include "chrome/browser/guest_view/guest_view_manager.h"
15 #include "chrome/browser/guest_view/guest_view_manager_factory.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h"
18 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
19 #include "chrome/test/base/interactive_test_utils.h"
20 #include "chrome/test/base/test_launcher_utils.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/render_view_host.h"
25 #include "content/public/browser/render_widget_host_iterator.h"
26 #include "content/public/browser/render_widget_host_view.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/content_switches.h"
29 #include "content/public/test/browser_test_utils.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 apps::AppWindow
;
38 class TestGuestViewManager
: public GuestViewManager
{
40 explicit TestGuestViewManager(content::BrowserContext
* context
) :
41 GuestViewManager(context
),
42 web_contents_(NULL
) {}
44 content::WebContents
* WaitForGuestCreated() {
48 message_loop_runner_
= new content::MessageLoopRunner
;
49 message_loop_runner_
->Run();
54 // GuestViewManager override:
55 virtual void AddGuest(int guest_instance_id
,
56 content::WebContents
* guest_web_contents
) OVERRIDE
{
57 GuestViewManager::AddGuest(guest_instance_id
, guest_web_contents
);
58 web_contents_
= guest_web_contents
;
60 if (message_loop_runner_
)
61 message_loop_runner_
->Quit();
64 content::WebContents
* web_contents_
;
65 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
68 // Test factory for creating test instances of GuestViewManager.
69 class TestGuestViewManagerFactory
: public GuestViewManagerFactory
{
71 TestGuestViewManagerFactory() :
72 test_guest_view_manager_(NULL
) {}
74 virtual ~TestGuestViewManagerFactory() {}
76 virtual GuestViewManager
* CreateGuestViewManager(
77 content::BrowserContext
* context
) OVERRIDE
{
78 return GetManager(context
);
81 TestGuestViewManager
* GetManager(content::BrowserContext
* context
) {
82 if (!test_guest_view_manager_
) {
83 test_guest_view_manager_
= new TestGuestViewManager(context
);
85 return test_guest_view_manager_
;
89 TestGuestViewManager
* test_guest_view_manager_
;
91 DISALLOW_COPY_AND_ASSIGN(TestGuestViewManagerFactory
);
94 class WebViewInteractiveTest
95 : public extensions::PlatformAppBrowserTest
{
97 WebViewInteractiveTest()
98 : guest_web_contents_(NULL
),
99 embedder_web_contents_(NULL
),
100 corner_(gfx::Point()),
101 mouse_click_result_(false),
103 GuestViewManager::set_factory_for_testing(&factory_
);
106 TestGuestViewManager
* GetGuestViewManager() {
107 return factory_
.GetManager(browser()->profile());
110 void MoveMouseInsideWindowWithListener(gfx::Point point
,
111 const std::string
& message
) {
112 ExtensionTestMessageListener
move_listener(message
, false);
113 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
114 gfx::Point(corner_
.x() + point
.x(), corner_
.y() + point
.y())));
115 ASSERT_TRUE(move_listener
.WaitUntilSatisfied());
118 void SendMouseClickWithListener(ui_controls::MouseButton button
,
119 const std::string
& message
) {
120 ExtensionTestMessageListener
listener(message
, false);
121 SendMouseClick(button
);
122 ASSERT_TRUE(listener
.WaitUntilSatisfied());
125 void SendMouseClick(ui_controls::MouseButton button
) {
126 SendMouseEvent(button
, ui_controls::DOWN
);
127 SendMouseEvent(button
, ui_controls::UP
);
130 void MoveMouseInsideWindow(const gfx::Point
& point
) {
131 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
132 gfx::Point(corner_
.x() + point
.x(), corner_
.y() + point
.y())));
135 gfx::NativeWindow
GetPlatformAppWindow() {
136 const apps::AppWindowRegistry::AppWindowList
& app_windows
=
137 apps::AppWindowRegistry::Get(browser()->profile())->app_windows();
138 return (*app_windows
.begin())->GetNativeWindow();
141 void SendKeyPressToPlatformApp(ui::KeyboardCode key
) {
142 ASSERT_EQ(1U, GetAppWindowCount());
143 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
144 GetPlatformAppWindow(), key
, false, false, false, false));
147 void SendCopyKeyPressToPlatformApp() {
148 ASSERT_EQ(1U, GetAppWindowCount());
149 #if defined(OS_MACOSX)
150 // Send Cmd+C on MacOSX.
151 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
152 GetPlatformAppWindow(), ui::VKEY_C
, false, false, false, true));
154 // Send Ctrl+C on Windows and Linux/ChromeOS.
155 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
156 GetPlatformAppWindow(), ui::VKEY_C
, true, false, false, false));
160 void SendStartOfLineKeyPressToPlatformApp() {
161 #if defined(OS_MACOSX)
162 // Send Cmd+Left on MacOSX.
163 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
164 GetPlatformAppWindow(), ui::VKEY_LEFT
, false, false, false, true));
166 // Send Ctrl+Left on Windows and Linux/ChromeOS.
167 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
168 GetPlatformAppWindow(), ui::VKEY_LEFT
, true, false, false, false));
172 void SendBackShortcutToPlatformApp() {
173 #if defined(OS_MACOSX)
174 // Send Cmd+[ on MacOSX.
175 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
176 GetPlatformAppWindow(), ui::VKEY_OEM_4
, false, false, false, true));
178 // Send browser back key on Linux/Windows.
179 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
180 GetPlatformAppWindow(), ui::VKEY_BROWSER_BACK
,
181 false, false, false, false));
185 void SendForwardShortcutToPlatformApp() {
186 #if defined(OS_MACOSX)
187 // Send Cmd+] on MacOSX.
188 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
189 GetPlatformAppWindow(), ui::VKEY_OEM_6
, false, false, false, true));
191 // Send browser back key on Linux/Windows.
192 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
193 GetPlatformAppWindow(), ui::VKEY_BROWSER_FORWARD
,
194 false, false, false, false));
198 void SendMouseEvent(ui_controls::MouseButton button
,
199 ui_controls::MouseButtonState state
) {
201 mouse_click_result_
= ui_test_utils::SendMouseEventsSync(button
,
203 first_click_
= false;
205 ASSERT_EQ(mouse_click_result_
, ui_test_utils::SendMouseEventsSync(
215 scoped_ptr
<ExtensionTestMessageListener
> RunAppHelper(
216 const std::string
& test_name
,
217 const std::string
& app_location
,
218 TestServer test_server
,
219 content::WebContents
** embedder_web_contents
) {
220 // For serving guest pages.
221 if ((test_server
== NEEDS_TEST_SERVER
) && !StartEmbeddedTestServer()) {
222 LOG(ERROR
) << "FAILED TO START TEST SERVER.";
223 return scoped_ptr
<ExtensionTestMessageListener
>();
226 LoadAndLaunchPlatformApp(app_location
.c_str(), "Launched");
227 if (!ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow())) {
228 LOG(ERROR
) << "UNABLE TO FOCUS TEST WINDOW.";
229 return scoped_ptr
<ExtensionTestMessageListener
>();
232 // Flush any pending events to make sure we start with a clean slate.
233 content::RunAllPendingInMessageLoop();
235 *embedder_web_contents
= GetFirstAppWindowWebContents();
237 scoped_ptr
<ExtensionTestMessageListener
> done_listener(
238 new ExtensionTestMessageListener("TEST_PASSED", false));
239 done_listener
->set_failure_message("TEST_FAILED");
240 if (!content::ExecuteScript(
241 *embedder_web_contents
,
242 base::StringPrintf("runTest('%s')", test_name
.c_str()))) {
243 LOG(ERROR
) << "UNABLE TO START TEST";
244 return scoped_ptr
<ExtensionTestMessageListener
>();
247 return done_listener
.Pass();
250 void TestHelper(const std::string
& test_name
,
251 const std::string
& app_location
,
252 TestServer test_server
) {
253 content::WebContents
* embedder_web_contents
= NULL
;
254 scoped_ptr
<ExtensionTestMessageListener
> done_listener(
256 test_name
, app_location
, test_server
, &embedder_web_contents
));
258 ASSERT_TRUE(done_listener
);
259 ASSERT_TRUE(done_listener
->WaitUntilSatisfied());
261 guest_web_contents_
= GetGuestViewManager()->WaitForGuestCreated();
264 void RunTest(const std::string
& app_name
) {
266 void SetupTest(const std::string
& app_name
,
267 const std::string
& guest_url_spec
) {
268 ASSERT_TRUE(StartEmbeddedTestServer());
269 GURL::Replacements replace_host
;
270 std::string
host_str("localhost"); // Must stay in scope with replace_host.
271 replace_host
.SetHostStr(host_str
);
273 GURL guest_url
= embedded_test_server()->GetURL(guest_url_spec
);
274 guest_url
= guest_url
.ReplaceComponents(replace_host
);
276 ui_test_utils::UrlLoadObserver
guest_observer(
277 guest_url
, content::NotificationService::AllSources());
279 LoadAndLaunchPlatformApp(app_name
.c_str(), "connected");
281 guest_observer
.Wait();
282 content::Source
<content::NavigationController
> source
=
283 guest_observer
.source();
284 EXPECT_TRUE(source
->GetWebContents()->GetRenderProcessHost()->
287 guest_web_contents_
= source
->GetWebContents();
288 embedder_web_contents_
=
289 GuestViewBase::FromWebContents(guest_web_contents_
)->
290 embedder_web_contents();
292 gfx::Rect offset
= embedder_web_contents_
->GetContainerBounds();
293 corner_
= gfx::Point(offset
.x(), offset
.y());
295 const testing::TestInfo
* const test_info
=
296 testing::UnitTest::GetInstance()->current_test_info();
297 const char* prefix
= "DragDropWithinWebView";
298 if (!strncmp(test_info
->name(), prefix
, strlen(prefix
))) {
299 // In the drag drop test we add 20px padding to the page body because on
300 // windows if we get too close to the edge of the window the resize cursor
301 // appears and we start dragging the window edge.
302 corner_
.Offset(20, 20);
306 content::WebContents
* guest_web_contents() {
307 return guest_web_contents_
;
310 content::WebContents
* embedder_web_contents() {
311 return embedder_web_contents_
;
314 gfx::Point
corner() {
318 void SimulateRWHMouseClick(content::RenderWidgetHost
* rwh
,
319 blink::WebMouseEvent::Button button
,
322 blink::WebMouseEvent mouse_event
;
323 mouse_event
.button
= button
;
324 mouse_event
.x
= mouse_event
.windowX
= x
;
325 mouse_event
.y
= mouse_event
.windowY
= y
;
326 mouse_event
.modifiers
= 0;
328 mouse_event
.type
= blink::WebInputEvent::MouseDown
;
329 rwh
->ForwardMouseEvent(mouse_event
);
330 mouse_event
.type
= blink::WebInputEvent::MouseUp
;
331 rwh
->ForwardMouseEvent(mouse_event
);
334 class PopupCreatedObserver
{
336 explicit PopupCreatedObserver()
337 : initial_widget_count_(0),
338 last_render_widget_host_(NULL
),
339 seen_new_widget_(false) {}
341 ~PopupCreatedObserver() {}
344 size_t current_widget_count
= CountWidgets();
345 if (!seen_new_widget_
&&
346 current_widget_count
== initial_widget_count_
+ 1) {
347 seen_new_widget_
= true;
350 // If we haven't seen any new widget or we get 0 size widget, we need to
352 bool needs_to_schedule_wait
= true;
354 if (seen_new_widget_
) {
355 gfx::Rect popup_bounds
=
356 last_render_widget_host_
->GetView()->GetViewBounds();
357 if (!popup_bounds
.size().IsEmpty())
358 needs_to_schedule_wait
= false;
361 if (needs_to_schedule_wait
) {
366 message_loop_
->Quit();
369 if (!message_loop_
) {
370 message_loop_
= new content::MessageLoopRunner
;
371 message_loop_
->Run();
375 void Init() { initial_widget_count_
= CountWidgets(); }
377 // Returns the last widget created.
378 content::RenderWidgetHost
* last_render_widget_host() {
379 return last_render_widget_host_
;
383 void ScheduleWait() {
384 base::MessageLoop::current()->PostDelayedTask(
386 base::Bind(&PopupCreatedObserver::Wait
, base::Unretained(this)),
387 base::TimeDelta::FromMilliseconds(200));
390 size_t CountWidgets() {
391 scoped_ptr
<content::RenderWidgetHostIterator
> widgets(
392 content::RenderWidgetHost::GetRenderWidgetHosts());
393 size_t num_widgets
= 0;
394 while (content::RenderWidgetHost
* widget
= widgets
->GetNextHost()) {
395 if (widget
->IsRenderView())
398 last_render_widget_host_
= widget
;
403 size_t initial_widget_count_
;
404 content::RenderWidgetHost
* last_render_widget_host_
;
405 scoped_refptr
<content::MessageLoopRunner
> message_loop_
;
406 bool seen_new_widget_
;
408 DISALLOW_COPY_AND_ASSIGN(PopupCreatedObserver
);
411 void WaitForTitle(const char* title
) {
412 base::string16
expected_title(base::ASCIIToUTF16(title
));
413 base::string16
error_title(base::ASCIIToUTF16("FAILED"));
414 content::TitleWatcher
title_watcher(guest_web_contents(), expected_title
);
415 title_watcher
.AlsoWaitForTitle(error_title
);
416 ASSERT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
419 void PopupTestHelper(const gfx::Point
& padding
) {
420 PopupCreatedObserver popup_observer
;
421 popup_observer
.Init();
422 // Press alt+DOWN to open popup.
424 content::SimulateKeyPress(
425 guest_web_contents(), ui::VKEY_DOWN
, false, false, alt
, false);
426 popup_observer
.Wait();
428 content::RenderWidgetHost
* popup_rwh
=
429 popup_observer
.last_render_widget_host();
430 gfx::Rect popup_bounds
= popup_rwh
->GetView()->GetViewBounds();
432 content::RenderViewHost
* embedder_rvh
=
433 GetFirstAppWindowWebContents()->GetRenderViewHost();
434 gfx::Rect embedder_bounds
= embedder_rvh
->GetView()->GetViewBounds();
435 gfx::Vector2d diff
= popup_bounds
.origin() - embedder_bounds
.origin();
436 LOG(INFO
) << "DIFF: x = " << diff
.x() << ", y = " << diff
.y();
438 const int left_spacing
= 40 + padding
.x(); // div.style.paddingLeft = 40px.
439 // div.style.paddingTop = 50px + (input box height = 26px).
440 const int top_spacing
= 50 + 26 + padding
.y();
442 // If the popup is placed within |threshold_px| of the expected position,
443 // then we consider the test as a pass.
444 const int threshold_px
= 10;
446 EXPECT_LE(std::abs(diff
.x() - left_spacing
), threshold_px
);
447 EXPECT_LE(std::abs(diff
.y() - top_spacing
), threshold_px
);
450 content::SimulateKeyPress(
451 guest_web_contents(), ui::VKEY_ESCAPE
, false, false, false, false);
454 void DragTestStep1() {
455 // Move mouse to start of text.
456 MoveMouseInsideWindow(gfx::Point(45, 8));
457 MoveMouseInsideWindow(gfx::Point(45, 9));
458 SendMouseEvent(ui_controls::LEFT
, ui_controls::DOWN
);
460 MoveMouseInsideWindow(gfx::Point(74, 12));
461 MoveMouseInsideWindow(gfx::Point(78, 12));
463 // Now wait a bit before moving mouse to initiate drag/drop.
464 base::MessageLoop::current()->PostDelayedTask(
466 base::Bind(&WebViewInteractiveTest::DragTestStep2
,
467 base::Unretained(this)),
468 base::TimeDelta::FromMilliseconds(200));
471 void DragTestStep2() {
472 // Drag source over target.
473 MoveMouseInsideWindow(gfx::Point(76, 76));
475 // Create a second mouse over the source to trigger the drag over event.
476 MoveMouseInsideWindow(gfx::Point(76, 77));
478 // Release mouse to drop.
479 SendMouseEvent(ui_controls::LEFT
, ui_controls::UP
);
480 SendMouseClick(ui_controls::LEFT
);
484 // Note that following ExtensionTestMessageListener and ExecuteScript*
485 // call must be after we quit |quit_closure_|. Otherwise the class
486 // here won't be able to receive messages sent by chrome.test.sendMessage.
487 // This is because of the nature of drag and drop code (esp. the
488 // MessageLoop) in it.
490 // Now check if we got a drop and read the drop data.
491 embedder_web_contents_
= GetFirstAppWindowWebContents();
492 ExtensionTestMessageListener
drop_listener("guest-got-drop", false);
493 EXPECT_TRUE(content::ExecuteScript(embedder_web_contents_
,
494 "window.checkIfGuestGotDrop()"));
495 EXPECT_TRUE(drop_listener
.WaitUntilSatisfied());
497 std::string last_drop_data
;
498 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
499 embedder_web_contents_
,
500 "window.domAutomationController.send(getLastDropData())",
503 last_drop_data_
= last_drop_data
;
507 TestGuestViewManagerFactory factory_
;
508 content::WebContents
* guest_web_contents_
;
509 content::WebContents
* embedder_web_contents_
;
511 bool mouse_click_result_
;
513 // Only used in drag/drop test.
514 base::Closure quit_closure_
;
515 std::string last_drop_data_
;
518 // ui_test_utils::SendMouseMoveSync doesn't seem to work on OS_MACOSX, and
519 // likely won't work on many other platforms as well, so for now this test
520 // is for Windows and Linux only. As of Sept 17th, 2013 this test is disabled
521 // on Windows due to flakines, see http://crbug.com/293445.
523 // Disabled on Linux Aura because pointer lock does not work on Linux Aura.
526 #if defined(OS_LINUX) && !defined(USE_AURA)
528 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, PointerLock
) {
529 SetupTest("web_view/pointer_lock",
530 "/extensions/platform_apps/web_view/pointer_lock/guest.html");
532 // Move the mouse over the Lock Pointer button.
533 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
534 gfx::Point(corner().x() + 75, corner().y() + 25)));
536 // Click the Lock Pointer button. The first two times the button is clicked
537 // the permission API will deny the request (intentional).
538 ExtensionTestMessageListener
exception_listener("request exception", false);
539 SendMouseClickWithListener(ui_controls::LEFT
, "lock error");
540 ASSERT_TRUE(exception_listener
.WaitUntilSatisfied());
541 SendMouseClickWithListener(ui_controls::LEFT
, "lock error");
543 // Click the Lock Pointer button, locking the mouse to lockTarget1.
544 SendMouseClickWithListener(ui_controls::LEFT
, "locked");
546 // Attempt to move the mouse off of the lock target, and onto lockTarget2,
547 // (which would trigger a test failure).
548 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
549 gfx::Point(corner().x() + 74, corner().y() + 74)));
550 MoveMouseInsideWindowWithListener(gfx::Point(75, 75), "mouse-move");
553 // When the mouse is unlocked on win aura, sending a test mouse click clicks
554 // where the mouse moved to while locked. I was unable to figure out why, and
555 // since the issue only occurs with the test mouse events, just fix it with
556 // a simple workaround - moving the mouse back to where it should be.
557 // TODO(mthiesse): Fix Win Aura simulated mouse events while mouse locked.
558 MoveMouseInsideWindowWithListener(gfx::Point(75, 25), "mouse-move");
561 ExtensionTestMessageListener
unlocked_listener("unlocked", false);
562 // Send a key press to unlock the mouse.
563 SendKeyPressToPlatformApp(ui::VKEY_ESCAPE
);
565 // Wait for page to receive (successful) mouse unlock response.
566 ASSERT_TRUE(unlocked_listener
.WaitUntilSatisfied());
568 // After the second lock, guest.js sends a message to main.js to remove the
569 // webview object. main.js then removes the div containing the webview, which
570 // should unlock, and leave the mouse over the mousemove-capture-container
571 // div. We then move the mouse over that div to ensure the mouse was properly
572 // unlocked and that the div receieves the message.
573 ExtensionTestMessageListener
move_captured_listener("move-captured", false);
574 move_captured_listener
.set_failure_message("timeout");
576 // Mouse should already be over lock button (since we just unlocked), so send
577 // click to re-lock the mouse.
578 SendMouseClickWithListener(ui_controls::LEFT
, "deleted");
580 // A mousemove event is triggered on the mousemove-capture-container element
581 // when we delete the webview container (since the mouse moves onto the
582 // element), but just in case, send an explicit mouse movement to be safe.
583 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
584 gfx::Point(corner().x() + 50, corner().y() + 10)));
586 // Wait for page to receive second (successful) mouselock response.
587 bool success
= move_captured_listener
.WaitUntilSatisfied();
589 fprintf(stderr
, "TIMEOUT - retrying\n");
590 // About 1 in 40 tests fail to detect mouse moves at this point (why?).
591 // Sending a right click seems to fix this (why?).
592 ExtensionTestMessageListener
move_listener2("move-captured", false);
593 SendMouseClick(ui_controls::RIGHT
);
594 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
595 gfx::Point(corner().x() + 51, corner().y() + 11)));
596 ASSERT_TRUE(move_listener2
.WaitUntilSatisfied());
600 #endif // defined(OS_LINUX) && !defined(USE_AURA)
602 // Tests that if a <webview> is focused before navigation then the guest starts
604 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_FocusBeforeNavigation
) {
605 TestHelper("testFocusBeforeNavigation", "web_view/focus", NO_TEST_SERVER
);
608 // Tests that setting focus on the <webview> sets focus on the guest.
609 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_FocusEvent
) {
610 TestHelper("testFocusEvent", "web_view/focus", NO_TEST_SERVER
);
613 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_FocusTracksEmbedder
) {
614 content::WebContents
* embedder_web_contents
= NULL
;
616 scoped_ptr
<ExtensionTestMessageListener
> done_listener(
617 RunAppHelper("testFocusTracksEmbedder", "web_view/focus", NO_TEST_SERVER
,
618 &embedder_web_contents
));
619 done_listener
->WaitUntilSatisfied();
621 ExtensionTestMessageListener
next_step_listener("TEST_STEP_PASSED", false);
622 next_step_listener
.set_failure_message("TEST_STEP_FAILED");
623 EXPECT_TRUE(content::ExecuteScript(
624 embedder_web_contents
,
625 "window.runCommand('testFocusTracksEmbedderRunNextStep');"));
627 // Blur the embedder.
628 embedder_web_contents
->GetRenderViewHost()->Blur();
629 // Ensure that the guest is also blurred.
630 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
633 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_AdvanceFocus
) {
634 content::WebContents
* embedder_web_contents
= NULL
;
637 scoped_ptr
<ExtensionTestMessageListener
> done_listener(
638 RunAppHelper("testAdvanceFocus", "web_view/focus", NO_TEST_SERVER
,
639 &embedder_web_contents
));
640 done_listener
->WaitUntilSatisfied();
644 ExtensionTestMessageListener
listener("button1-focused", false);
645 listener
.set_failure_message("TEST_FAILED");
646 SimulateRWHMouseClick(embedder_web_contents
->GetRenderViewHost(),
647 blink::WebMouseEvent::ButtonLeft
, 200, 20);
648 content::SimulateKeyPress(embedder_web_contents
, ui::VKEY_TAB
,
649 false, false, false, false);
650 ASSERT_TRUE(listener
.WaitUntilSatisfied());
654 // Wait for button1 to be focused again, this means we were asked to
655 // move the focus to the next focusable element.
656 ExtensionTestMessageListener
listener("button1-advance-focus", false);
657 listener
.set_failure_message("TEST_FAILED");
658 // TODO(fsamuel): A third Tab key press should not be necessary.
659 // The <webview> will take keyboard focus but it will not focus an initial
660 // element. The initial element is dependent upon tab direction which blink
661 // does not propagate to the plugin.
662 // See http://crbug.com/147644.
663 content::SimulateKeyPress(embedder_web_contents
, ui::VKEY_TAB
,
664 false, false, false, false);
665 content::SimulateKeyPress(embedder_web_contents
, ui::VKEY_TAB
,
666 false, false, false, false);
667 content::SimulateKeyPress(embedder_web_contents
, ui::VKEY_TAB
,
668 false, false, false, false);
669 ASSERT_TRUE(listener
.WaitUntilSatisfied());
673 // Tests that blurring <webview> also blurs the guest.
674 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_BlurEvent
) {
675 TestHelper("testBlurEvent", "web_view/focus", NO_TEST_SERVER
);
678 // Tests that guests receive edit commands and respond appropriately.
679 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, EditCommands
) {
680 LoadAndLaunchPlatformApp("web_view/edit_commands", "connected");
682 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
683 GetPlatformAppWindow()));
685 // Flush any pending events to make sure we start with a clean slate.
686 content::RunAllPendingInMessageLoop();
688 ExtensionTestMessageListener
copy_listener("copy", false);
689 SendCopyKeyPressToPlatformApp();
691 // Wait for the guest to receive a 'copy' edit command.
692 ASSERT_TRUE(copy_listener
.WaitUntilSatisfied());
695 // Tests that guests receive edit commands and respond appropriately.
696 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, EditCommandsNoMenu
) {
697 SetupTest("web_view/edit_commands_no_menu",
698 "/extensions/platform_apps/web_view/edit_commands_no_menu/"
701 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
702 GetPlatformAppWindow()));
704 // Flush any pending events to make sure we start with a clean slate.
705 content::RunAllPendingInMessageLoop();
707 ExtensionTestMessageListener
start_of_line_listener("StartOfLine", false);
708 SendStartOfLineKeyPressToPlatformApp();
709 // Wait for the guest to receive a 'copy' edit command.
710 ASSERT_TRUE(start_of_line_listener
.WaitUntilSatisfied());
713 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
714 NewWindow_NewWindowNameTakesPrecedence
) {
715 TestHelper("testNewWindowNameTakesPrecedence",
716 "web_view/newwindow",
720 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
721 NewWindow_WebViewNameTakesPrecedence
) {
722 TestHelper("testWebViewNameTakesPrecedence",
723 "web_view/newwindow",
727 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_NoName
) {
728 TestHelper("testNoName",
729 "web_view/newwindow",
733 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_Redirect
) {
734 TestHelper("testNewWindowRedirect",
735 "web_view/newwindow",
739 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_Close
) {
740 TestHelper("testNewWindowClose",
741 "web_view/newwindow",
745 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_ExecuteScript
) {
746 TestHelper("testNewWindowExecuteScript",
747 "web_view/newwindow",
751 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
752 NewWindow_DeclarativeWebRequest
) {
753 TestHelper("testNewWindowDeclarativeWebRequest",
754 "web_view/newwindow",
758 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_WebRequest
) {
759 TestHelper("testNewWindowWebRequest",
760 "web_view/newwindow",
764 // A custom elements bug needs to be addressed to enable this test:
765 // See http://crbug.com/282477 for more information.
766 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
767 DISABLED_NewWindow_WebRequestCloseWindow
) {
768 TestHelper("testNewWindowWebRequestCloseWindow",
769 "web_view/newwindow",
773 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
774 NewWindow_WebRequestRemoveElement
) {
775 TestHelper("testNewWindowWebRequestRemoveElement",
776 "web_view/newwindow",
780 // Tests that Ctrl+Click/Cmd+Click on a link fires up the newwindow API.
781 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, NewWindow_OpenInNewTab
) {
782 content::WebContents
* embedder_web_contents
= NULL
;
784 ExtensionTestMessageListener
loaded_listener("Loaded", false);
785 scoped_ptr
<ExtensionTestMessageListener
> done_listener(
786 RunAppHelper("testNewWindowOpenInNewTab",
787 "web_view/newwindow",
789 &embedder_web_contents
));
791 loaded_listener
.WaitUntilSatisfied();
792 #if defined(OS_MACOSX)
793 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
794 GetPlatformAppWindow(), ui::VKEY_RETURN
,
795 false, false, false, true /* cmd */));
797 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
798 GetPlatformAppWindow(), ui::VKEY_RETURN
,
799 true /* ctrl */, false, false, false));
802 // Wait for the embedder to receive a 'newwindow' event.
803 ASSERT_TRUE(done_listener
->WaitUntilSatisfied());
807 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, ExecuteCode
) {
808 ASSERT_TRUE(RunPlatformAppTestWithArg(
809 "platform_apps/web_view/common", "execute_code")) << message_
;
812 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, PopupPositioningBasic
) {
813 TestHelper("testBasic", "web_view/popup_positioning", NO_TEST_SERVER
);
814 ASSERT_TRUE(guest_web_contents());
815 PopupTestHelper(gfx::Point());
817 // TODO(lazyboy): Move the embedder window to a random location and
818 // make sure we keep rendering popups correct in webview.
821 // Tests that moving browser plugin (without resize/UpdateRects) correctly
822 // repositions popup.
823 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, PopupPositioningMoved
) {
824 TestHelper("testMoved", "web_view/popup_positioning", NO_TEST_SERVER
);
825 ASSERT_TRUE(guest_web_contents());
826 PopupTestHelper(gfx::Point(20, 0));
829 // Drag and drop inside a webview is currently only enabled for linux and mac,
830 // but the tests don't work on anything except chromeos for now. This is because
831 // of simulating mouse drag code's dependency on platforms.
832 #if defined(OS_CHROMEOS)
833 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, DragDropWithinWebView
) {
834 LoadAndLaunchPlatformApp("web_view/dnd_within_webview", "connected");
835 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow()));
837 embedder_web_contents_
= GetFirstAppWindowWebContents();
838 gfx::Rect offset
= embedder_web_contents_
->GetContainerBounds();
839 corner_
= gfx::Point(offset
.x(), offset
.y());
841 // In the drag drop test we add 20px padding to the page body because on
842 // windows if we get too close to the edge of the window the resize cursor
843 // appears and we start dragging the window edge.
844 corner_
.Offset(20, 20);
846 // Flush any pending events to make sure we start with a clean slate.
847 content::RunAllPendingInMessageLoop();
849 base::RunLoop run_loop
;
850 quit_closure_
= run_loop
.QuitClosure();
851 base::MessageLoop::current()->PostTask(
853 base::Bind(&WebViewInteractiveTest::DragTestStep1
,
854 base::Unretained(this)));
857 if (last_drop_data_
== "Drop me")
860 LOG(INFO
) << "Drag was cancelled in interactive_test, restarting drag";
862 // Reset state for next try.
863 ExtensionTestMessageListener
reset_listener("resetStateReply", false);
864 EXPECT_TRUE(content::ExecuteScript(embedder_web_contents_
,
865 "window.resetState()"));
866 ASSERT_TRUE(reset_listener
.WaitUntilSatisfied());
868 ASSERT_EQ("Drop me", last_drop_data_
);
870 #endif // (defined(OS_CHROMEOS))
872 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Navigation
) {
873 TestHelper("testNavigation", "web_view/navigation", NO_TEST_SERVER
);
876 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Navigation_BackForwardKeys
) {
877 LoadAndLaunchPlatformApp("web_view/navigation", "Launched");
878 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
879 GetPlatformAppWindow()));
880 // Flush any pending events to make sure we start with a clean slate.
881 content::RunAllPendingInMessageLoop();
883 content::WebContents
* embedder_web_contents
= GetFirstAppWindowWebContents();
884 ASSERT_TRUE(embedder_web_contents
);
886 ExtensionTestMessageListener
done_listener(
887 "TEST_PASSED", false);
888 done_listener
.set_failure_message("TEST_FAILED");
889 ExtensionTestMessageListener
ready_back_key_listener(
890 "ReadyForBackKey", false);
891 ExtensionTestMessageListener
ready_forward_key_listener(
892 "ReadyForForwardKey", false);
894 EXPECT_TRUE(content::ExecuteScript(
895 embedder_web_contents
,
896 "runTest('testBackForwardKeys')"));
898 ASSERT_TRUE(ready_back_key_listener
.WaitUntilSatisfied());
899 SendBackShortcutToPlatformApp();
901 ASSERT_TRUE(ready_forward_key_listener
.WaitUntilSatisfied());
902 SendForwardShortcutToPlatformApp();
904 ASSERT_TRUE(done_listener
.WaitUntilSatisfied());
907 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
,
908 PointerLock_PointerLockLostWithFocus
) {
909 TestHelper("testPointerLockLostWithFocus",
910 "web_view/pointerlock",
914 // This test exercies the following scenario:
915 // 1. An <input> in guest has focus.
916 // 2. User takes focus to embedder by clicking e.g. an <input> in embedder.
917 // 3. User brings back the focus directly to the <input> in #1.
919 // Now we need to make sure TextInputTypeChanged fires properly for the guest's
920 // view upon step #3. We simply read the input type's state after #3 to
921 // make sure it's not TEXT_INPUT_TYPE_NONE.
922 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, Focus_FocusRestored
) {
923 TestHelper("testFocusRestored", "web_view/focus", NO_TEST_SERVER
);
924 content::WebContents
* embedder_web_contents
= GetFirstAppWindowWebContents();
925 ASSERT_TRUE(embedder_web_contents
);
926 ASSERT_TRUE(guest_web_contents());
928 // 1) We click on the guest so that we get a focus event.
929 ExtensionTestMessageListener
next_step_listener("TEST_STEP_PASSED", false);
930 next_step_listener
.set_failure_message("TEST_STEP_FAILED");
932 content::SimulateMouseClickAt(guest_web_contents(),
934 blink::WebMouseEvent::ButtonLeft
,
936 EXPECT_TRUE(content::ExecuteScript(
937 embedder_web_contents
,
938 "window.runCommand('testFocusRestoredRunNextStep', 1);"));
940 // Wait for the next step to complete.
941 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
943 // 2) We click on the embedder so the guest's focus goes away and it observes
945 next_step_listener
.Reset();
947 content::SimulateMouseClickAt(embedder_web_contents
,
949 blink::WebMouseEvent::ButtonLeft
,
950 gfx::Point(200, 20));
951 EXPECT_TRUE(content::ExecuteScript(
952 embedder_web_contents
,
953 "window.runCommand('testFocusRestoredRunNextStep', 2);"));
955 // Wait for the next step to complete.
956 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
958 // 3) We click on the guest again to bring back focus directly to the previous
959 // input element, then we ensure text_input_type is properly set.
960 next_step_listener
.Reset();
962 content::SimulateMouseClickAt(guest_web_contents(),
964 blink::WebMouseEvent::ButtonLeft
,
966 EXPECT_TRUE(content::ExecuteScript(
967 embedder_web_contents
,
968 "window.runCommand('testFocusRestoredRunNextStep', 3)"));
970 // Wait for the next step to complete.
971 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
973 // |text_input_client| is not available for mac and android.
974 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
975 ui::TextInputClient
* text_input_client
=
976 embedder_web_contents
->GetRenderViewHost()->GetView()
977 ->GetTextInputClient();
978 ASSERT_TRUE(text_input_client
);
979 ASSERT_TRUE(text_input_client
->GetTextInputType() !=
980 ui::TEXT_INPUT_TYPE_NONE
);
984 // ui::TextInputClient is NULL for mac and android.
985 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
986 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, DISABLED_Focus_InputMethod
) {
987 content::WebContents
* embedder_web_contents
= NULL
;
988 scoped_ptr
<ExtensionTestMessageListener
> done_listener(
989 RunAppHelper("testInputMethod", "web_view/focus", NO_TEST_SERVER
,
990 &embedder_web_contents
));
991 ASSERT_TRUE(done_listener
->WaitUntilSatisfied());
993 ui::TextInputClient
* text_input_client
=
994 embedder_web_contents
->GetRenderViewHost()->GetView()
995 ->GetTextInputClient();
996 ASSERT_TRUE(text_input_client
);
998 ExtensionTestMessageListener
next_step_listener("TEST_STEP_PASSED", false);
999 next_step_listener
.set_failure_message("TEST_STEP_FAILED");
1001 // An input element inside the <webview> gets focus and is given some
1002 // user input via IME.
1004 ui::CompositionText composition
;
1005 composition
.text
= base::UTF8ToUTF16("InputTest123");
1006 text_input_client
->SetCompositionText(composition
);
1007 EXPECT_TRUE(content::ExecuteScript(
1008 embedder_web_contents
,
1009 "window.runCommand('testInputMethodRunNextStep', 1);"));
1011 // Wait for the next step to complete.
1012 ASSERT_TRUE(next_step_listener
.WaitUntilSatisfied());
1015 // A composition is committed via IME.
1017 next_step_listener
.Reset();
1019 ui::CompositionText composition
;
1020 composition
.text
= base::UTF8ToUTF16("InputTest456");
1021 text_input_client
->SetCompositionText(composition
);
1022 text_input_client
->ConfirmCompositionText();
1023 EXPECT_TRUE(content::ExecuteScript(
1024 embedder_web_contents
,
1025 "window.runCommand('testInputMethodRunNextStep', 2);"));
1027 // Wait for the next step to complete.
1028 EXPECT_TRUE(next_step_listener
.WaitUntilSatisfied());
1031 // Moving focus causes IME cancel, and the composition will be committed
1032 // in first <input> in the <webview>, not in the second <input>.
1034 next_step_listener
.Reset();
1035 ui::CompositionText composition
;
1036 composition
.text
= base::UTF8ToUTF16("InputTest789");
1037 text_input_client
->SetCompositionText(composition
);
1038 EXPECT_TRUE(content::ExecuteScript(
1039 embedder_web_contents
,
1040 "window.runCommand('testInputMethodRunNextStep', 3);"));
1042 // Wait for the next step to complete.
1043 EXPECT_TRUE(next_step_listener
.WaitUntilSatisfied());
1046 // Tests ExtendSelectionAndDelete message works in <webview>.
1048 next_step_listener
.Reset();
1050 // At this point we have set focus on first <input> in the <webview>,
1051 // and the value it contains is 'InputTestABC' with caret set after 'T'.
1052 // Now we delete 'Test' in 'InputTestABC', as the caret is after 'T':
1053 // delete before 1 character ('T') and after 3 characters ('est').
1054 text_input_client
->ExtendSelectionAndDelete(1, 3);
1055 EXPECT_TRUE(content::ExecuteScript(
1056 embedder_web_contents
,
1057 "window.runCommand('testInputMethodRunNextStep', 4);"));
1059 // Wait for the next step to complete.
1060 EXPECT_TRUE(next_step_listener
.WaitUntilSatisfied());
1065 #if defined(OS_MACOSX)
1066 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest
, TextSelection
) {
1067 SetupTest("web_view/text_selection",
1068 "/extensions/platform_apps/web_view/text_selection/guest.html");
1069 ASSERT_TRUE(guest_web_contents());
1070 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
1071 GetPlatformAppWindow()));
1073 // Wait until guest sees a context menu, select an arbitrary item (copy).
1074 ExtensionTestMessageListener
ctx_listener("MSG_CONTEXTMENU", false);
1075 ContextMenuNotificationObserver
menu_observer(IDC_CONTENT_CONTEXT_COPY
);
1076 SimulateRWHMouseClick(guest_web_contents()->GetRenderViewHost(),
1077 blink::WebMouseEvent::ButtonRight
, 20, 20);
1078 ASSERT_TRUE(ctx_listener
.WaitUntilSatisfied());
1080 // Now verify that the selection text propagates properly to RWHV.
1081 content::RenderWidgetHostView
* guest_rwhv
=
1082 guest_web_contents()->GetRenderWidgetHostView();
1083 ASSERT_TRUE(guest_rwhv
);
1084 std::string selected_text
= base::UTF16ToUTF8(guest_rwhv
->GetSelectedText());
1085 ASSERT_TRUE(selected_text
.size() >= 10u);
1086 ASSERT_EQ("AAAAAAAAAA", selected_text
.substr(0, 10));