Update mojo surfaces bindings and mojo/cc/ glue
[chromium-blink-merge.git] / chrome / browser / apps / web_view_interactive_browsertest.cc
blob90f9d7c0619c237ac5a996b324131a3778c5fce0
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/profiles/profile.h"
14 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h"
15 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
16 #include "chrome/test/base/interactive_test_utils.h"
17 #include "chrome/test/base/test_launcher_utils.h"
18 #include "chrome/test/base/ui_test_utils.h"
19 #include "content/public/browser/notification_service.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/render_widget_host_iterator.h"
23 #include "content/public/browser/render_widget_host_view.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/common/content_switches.h"
26 #include "content/public/test/browser_test_utils.h"
27 #include "extensions/browser/guest_view/guest_view_base.h"
28 #include "extensions/browser/guest_view/guest_view_manager.h"
29 #include "extensions/browser/guest_view/guest_view_manager_factory.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 extensions::GuestViewManager {
39 public:
40 explicit TestGuestViewManager(content::BrowserContext* context) :
41 GuestViewManager(context),
42 web_contents_(NULL) {}
44 content::WebContents* WaitForGuestCreated() {
45 if (web_contents_)
46 return web_contents_;
48 message_loop_runner_ = new content::MessageLoopRunner;
49 message_loop_runner_->Run();
50 return web_contents_;
53 private:
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 extensions::GuestViewManagerFactory {
70 public:
71 TestGuestViewManagerFactory() :
72 test_guest_view_manager_(NULL) {}
74 virtual ~TestGuestViewManagerFactory() {}
76 virtual extensions::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_;
88 private:
89 TestGuestViewManager* test_guest_view_manager_;
91 DISALLOW_COPY_AND_ASSIGN(TestGuestViewManagerFactory);
94 class WebViewInteractiveTest
95 : public extensions::PlatformAppBrowserTest {
96 public:
97 WebViewInteractiveTest()
98 : guest_web_contents_(NULL),
99 embedder_web_contents_(NULL),
100 corner_(gfx::Point()),
101 mouse_click_result_(false),
102 first_click_(true) {
103 extensions::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));
153 #else
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));
157 #endif
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));
165 #else
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));
169 #endif
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));
177 #else
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));
182 #endif
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));
190 #else
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));
195 #endif
198 void SendMouseEvent(ui_controls::MouseButton button,
199 ui_controls::MouseButtonState state) {
200 if (first_click_) {
201 mouse_click_result_ = ui_test_utils::SendMouseEventsSync(button,
202 state);
203 first_click_ = false;
204 } else {
205 ASSERT_EQ(mouse_click_result_, ui_test_utils::SendMouseEventsSync(
206 button, state));
210 enum TestServer {
211 NEEDS_TEST_SERVER,
212 NO_TEST_SERVER
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(
255 RunAppHelper(
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()->
285 IsIsolatedGuest());
287 guest_web_contents_ = source->GetWebContents();
288 embedder_web_contents_ =
289 extensions::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() {
315 return corner_;
318 void SimulateRWHMouseClick(content::RenderWidgetHost* rwh,
319 blink::WebMouseEvent::Button button,
320 int x,
321 int y) {
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 {
335 public:
336 PopupCreatedObserver()
337 : initial_widget_count_(0),
338 last_render_widget_host_(NULL),
339 seen_new_widget_(false) {}
341 ~PopupCreatedObserver() {}
343 void Wait() {
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
351 // schedule waiting.
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) {
362 ScheduleWait();
363 } else {
364 // We are done.
365 if (message_loop_)
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_;
382 private:
383 void ScheduleWait() {
384 base::MessageLoop::current()->PostDelayedTask(
385 FROM_HERE,
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())
396 continue;
397 ++num_widgets;
398 last_render_widget_host_ = widget;
400 return num_widgets;
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.
423 bool alt = true;
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);
449 // Close the popup.
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(
465 FROM_HERE,
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);
482 quit_closure_.Run();
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())",
501 &last_drop_data));
503 last_drop_data_ = last_drop_data;
506 protected:
507 TestGuestViewManagerFactory factory_;
508 content::WebContents* guest_web_contents_;
509 content::WebContents* embedder_web_contents_;
510 gfx::Point corner_;
511 bool mouse_click_result_;
512 bool first_click_;
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.
524 // crbug.com/341876
526 #if defined(OS_LINUX)
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");
552 #if defined(OS_WIN)
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");
559 #endif
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();
588 if (!success) {
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 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, PointerLockFocus) {
601 SetupTest("web_view/pointer_lock_focus",
602 "/extensions/platform_apps/web_view/pointer_lock_focus/guest.html");
604 // Move the mouse over the Lock Pointer button.
605 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
606 gfx::Point(corner().x() + 75, corner().y() + 25)));
608 // Click the Lock Pointer button, locking the mouse to lockTarget.
609 // This will also change focus to another element
610 SendMouseClickWithListener(ui_controls::LEFT, "locked");
612 // Try to unlock the mouse now that the focus is outside of the BrowserPlugin
613 ExtensionTestMessageListener unlocked_listener("unlocked", false);
614 // Send a key press to unlock the mouse.
615 SendKeyPressToPlatformApp(ui::VKEY_ESCAPE);
617 // Wait for page to receive (successful) mouse unlock response.
618 ASSERT_TRUE(unlocked_listener.WaitUntilSatisfied());
621 #endif // defined(OS_LINUX)
623 // Tests that if a <webview> is focused before navigation then the guest starts
624 // off focused.
625 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_FocusBeforeNavigation) {
626 TestHelper("testFocusBeforeNavigation", "web_view/focus", NO_TEST_SERVER);
629 // Tests that setting focus on the <webview> sets focus on the guest.
630 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_FocusEvent) {
631 TestHelper("testFocusEvent", "web_view/focus", NO_TEST_SERVER);
634 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_FocusTracksEmbedder) {
635 content::WebContents* embedder_web_contents = NULL;
637 scoped_ptr<ExtensionTestMessageListener> done_listener(
638 RunAppHelper("testFocusTracksEmbedder", "web_view/focus", NO_TEST_SERVER,
639 &embedder_web_contents));
640 done_listener->WaitUntilSatisfied();
642 ExtensionTestMessageListener next_step_listener("TEST_STEP_PASSED", false);
643 next_step_listener.set_failure_message("TEST_STEP_FAILED");
644 EXPECT_TRUE(content::ExecuteScript(
645 embedder_web_contents,
646 "window.runCommand('testFocusTracksEmbedderRunNextStep');"));
648 // Blur the embedder.
649 embedder_web_contents->GetRenderViewHost()->Blur();
650 // Ensure that the guest is also blurred.
651 ASSERT_TRUE(next_step_listener.WaitUntilSatisfied());
654 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_AdvanceFocus) {
655 content::WebContents* embedder_web_contents = NULL;
658 scoped_ptr<ExtensionTestMessageListener> done_listener(
659 RunAppHelper("testAdvanceFocus", "web_view/focus", NO_TEST_SERVER,
660 &embedder_web_contents));
661 done_listener->WaitUntilSatisfied();
665 ExtensionTestMessageListener listener("button1-focused", false);
666 listener.set_failure_message("TEST_FAILED");
667 SimulateRWHMouseClick(embedder_web_contents->GetRenderViewHost(),
668 blink::WebMouseEvent::ButtonLeft, 200, 20);
669 content::SimulateKeyPress(embedder_web_contents, ui::VKEY_TAB,
670 false, false, false, false);
671 ASSERT_TRUE(listener.WaitUntilSatisfied());
675 // Wait for button1 to be focused again, this means we were asked to
676 // move the focus to the next focusable element.
677 ExtensionTestMessageListener listener("button1-advance-focus", false);
678 listener.set_failure_message("TEST_FAILED");
679 // TODO(fsamuel): A third Tab key press should not be necessary.
680 // The <webview> will take keyboard focus but it will not focus an initial
681 // element. The initial element is dependent upon tab direction which blink
682 // does not propagate to the plugin.
683 // See http://crbug.com/147644.
684 content::SimulateKeyPress(embedder_web_contents, ui::VKEY_TAB,
685 false, false, false, false);
686 content::SimulateKeyPress(embedder_web_contents, ui::VKEY_TAB,
687 false, false, false, false);
688 content::SimulateKeyPress(embedder_web_contents, ui::VKEY_TAB,
689 false, false, false, false);
690 ASSERT_TRUE(listener.WaitUntilSatisfied());
694 // Tests that blurring <webview> also blurs the guest.
695 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_BlurEvent) {
696 TestHelper("testBlurEvent", "web_view/focus", NO_TEST_SERVER);
699 // Tests that guests receive edit commands and respond appropriately.
700 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, EditCommands) {
701 LoadAndLaunchPlatformApp("web_view/edit_commands", "connected");
703 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
704 GetPlatformAppWindow()));
706 // Flush any pending events to make sure we start with a clean slate.
707 content::RunAllPendingInMessageLoop();
709 ExtensionTestMessageListener copy_listener("copy", false);
710 SendCopyKeyPressToPlatformApp();
712 // Wait for the guest to receive a 'copy' edit command.
713 ASSERT_TRUE(copy_listener.WaitUntilSatisfied());
716 // Tests that guests receive edit commands and respond appropriately.
717 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, EditCommandsNoMenu) {
718 SetupTest("web_view/edit_commands_no_menu",
719 "/extensions/platform_apps/web_view/edit_commands_no_menu/"
720 "guest.html");
722 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
723 GetPlatformAppWindow()));
725 // Flush any pending events to make sure we start with a clean slate.
726 content::RunAllPendingInMessageLoop();
728 ExtensionTestMessageListener start_of_line_listener("StartOfLine", false);
729 SendStartOfLineKeyPressToPlatformApp();
730 // Wait for the guest to receive a 'copy' edit command.
731 ASSERT_TRUE(start_of_line_listener.WaitUntilSatisfied());
734 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
735 NewWindow_NewWindowNameTakesPrecedence) {
736 TestHelper("testNewWindowNameTakesPrecedence",
737 "web_view/newwindow",
738 NEEDS_TEST_SERVER);
741 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
742 NewWindow_WebViewNameTakesPrecedence) {
743 TestHelper("testWebViewNameTakesPrecedence",
744 "web_view/newwindow",
745 NEEDS_TEST_SERVER);
748 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_NoName) {
749 TestHelper("testNoName",
750 "web_view/newwindow",
751 NEEDS_TEST_SERVER);
754 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_Redirect) {
755 TestHelper("testNewWindowRedirect",
756 "web_view/newwindow",
757 NEEDS_TEST_SERVER);
760 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_Close) {
761 TestHelper("testNewWindowClose",
762 "web_view/newwindow",
763 NEEDS_TEST_SERVER);
766 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_DeferredAttachment) {
767 TestHelper("testNewWindowDeferredAttachment",
768 "web_view/newwindow",
769 NEEDS_TEST_SERVER);
772 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_ExecuteScript) {
773 TestHelper("testNewWindowExecuteScript",
774 "web_view/newwindow",
775 NEEDS_TEST_SERVER);
778 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
779 NewWindow_DeclarativeWebRequest) {
780 TestHelper("testNewWindowDeclarativeWebRequest",
781 "web_view/newwindow",
782 NEEDS_TEST_SERVER);
785 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_WebRequest) {
786 TestHelper("testNewWindowWebRequest",
787 "web_view/newwindow",
788 NEEDS_TEST_SERVER);
791 // A custom elements bug needs to be addressed to enable this test:
792 // See http://crbug.com/282477 for more information.
793 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
794 DISABLED_NewWindow_WebRequestCloseWindow) {
795 TestHelper("testNewWindowWebRequestCloseWindow",
796 "web_view/newwindow",
797 NEEDS_TEST_SERVER);
800 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
801 NewWindow_WebRequestRemoveElement) {
802 TestHelper("testNewWindowWebRequestRemoveElement",
803 "web_view/newwindow",
804 NEEDS_TEST_SERVER);
807 // Tests that Ctrl+Click/Cmd+Click on a link fires up the newwindow API.
808 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_OpenInNewTab) {
809 content::WebContents* embedder_web_contents = NULL;
811 ExtensionTestMessageListener loaded_listener("Loaded", false);
812 scoped_ptr<ExtensionTestMessageListener> done_listener(
813 RunAppHelper("testNewWindowOpenInNewTab",
814 "web_view/newwindow",
815 NEEDS_TEST_SERVER,
816 &embedder_web_contents));
818 loaded_listener.WaitUntilSatisfied();
819 #if defined(OS_MACOSX)
820 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
821 GetPlatformAppWindow(), ui::VKEY_RETURN,
822 false, false, false, true /* cmd */));
823 #else
824 ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
825 GetPlatformAppWindow(), ui::VKEY_RETURN,
826 true /* ctrl */, false, false, false));
827 #endif
829 // Wait for the embedder to receive a 'newwindow' event.
830 ASSERT_TRUE(done_listener->WaitUntilSatisfied());
834 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, ExecuteCode) {
835 ASSERT_TRUE(RunPlatformAppTestWithArg(
836 "platform_apps/web_view/common", "execute_code")) << message_;
839 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, PopupPositioningBasic) {
840 TestHelper("testBasic", "web_view/popup_positioning", NO_TEST_SERVER);
841 ASSERT_TRUE(guest_web_contents());
842 PopupTestHelper(gfx::Point());
844 // TODO(lazyboy): Move the embedder window to a random location and
845 // make sure we keep rendering popups correct in webview.
848 // Tests that moving browser plugin (without resize/UpdateRects) correctly
849 // repositions popup.
850 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, PopupPositioningMoved) {
851 TestHelper("testMoved", "web_view/popup_positioning", NO_TEST_SERVER);
852 ASSERT_TRUE(guest_web_contents());
853 PopupTestHelper(gfx::Point(20, 0));
856 // Drag and drop inside a webview is currently only enabled for linux and mac,
857 // but the tests don't work on anything except chromeos for now. This is because
858 // of simulating mouse drag code's dependency on platforms.
859 #if defined(OS_CHROMEOS) && !defined(USE_OZONE)
860 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DragDropWithinWebView) {
861 LoadAndLaunchPlatformApp("web_view/dnd_within_webview", "connected");
862 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow()));
864 embedder_web_contents_ = GetFirstAppWindowWebContents();
865 gfx::Rect offset = embedder_web_contents_->GetContainerBounds();
866 corner_ = gfx::Point(offset.x(), offset.y());
868 // In the drag drop test we add 20px padding to the page body because on
869 // windows if we get too close to the edge of the window the resize cursor
870 // appears and we start dragging the window edge.
871 corner_.Offset(20, 20);
873 // Flush any pending events to make sure we start with a clean slate.
874 content::RunAllPendingInMessageLoop();
875 for (;;) {
876 base::RunLoop run_loop;
877 quit_closure_ = run_loop.QuitClosure();
878 base::MessageLoop::current()->PostTask(
879 FROM_HERE,
880 base::Bind(&WebViewInteractiveTest::DragTestStep1,
881 base::Unretained(this)));
882 run_loop.Run();
884 if (last_drop_data_ == "Drop me")
885 break;
887 LOG(INFO) << "Drag was cancelled in interactive_test, restarting drag";
889 // Reset state for next try.
890 ExtensionTestMessageListener reset_listener("resetStateReply", false);
891 EXPECT_TRUE(content::ExecuteScript(embedder_web_contents_,
892 "window.resetState()"));
893 ASSERT_TRUE(reset_listener.WaitUntilSatisfied());
895 ASSERT_EQ("Drop me", last_drop_data_);
897 #endif // (defined(OS_CHROMEOS))
899 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Navigation) {
900 TestHelper("testNavigation", "web_view/navigation", NO_TEST_SERVER);
903 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Navigation_BackForwardKeys) {
904 LoadAndLaunchPlatformApp("web_view/navigation", "Launched");
905 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
906 GetPlatformAppWindow()));
907 // Flush any pending events to make sure we start with a clean slate.
908 content::RunAllPendingInMessageLoop();
910 content::WebContents* embedder_web_contents = GetFirstAppWindowWebContents();
911 ASSERT_TRUE(embedder_web_contents);
913 ExtensionTestMessageListener done_listener(
914 "TEST_PASSED", false);
915 done_listener.set_failure_message("TEST_FAILED");
916 ExtensionTestMessageListener ready_back_key_listener(
917 "ReadyForBackKey", false);
918 ExtensionTestMessageListener ready_forward_key_listener(
919 "ReadyForForwardKey", false);
921 EXPECT_TRUE(content::ExecuteScript(
922 embedder_web_contents,
923 "runTest('testBackForwardKeys')"));
925 ASSERT_TRUE(ready_back_key_listener.WaitUntilSatisfied());
926 SendBackShortcutToPlatformApp();
928 ASSERT_TRUE(ready_forward_key_listener.WaitUntilSatisfied());
929 SendForwardShortcutToPlatformApp();
931 ASSERT_TRUE(done_listener.WaitUntilSatisfied());
934 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
935 PointerLock_PointerLockLostWithFocus) {
936 TestHelper("testPointerLockLostWithFocus",
937 "web_view/pointerlock",
938 NO_TEST_SERVER);
941 // This test exercies the following scenario:
942 // 1. An <input> in guest has focus.
943 // 2. User takes focus to embedder by clicking e.g. an <input> in embedder.
944 // 3. User brings back the focus directly to the <input> in #1.
946 // Now we need to make sure TextInputTypeChanged fires properly for the guest's
947 // view upon step #3. We simply read the input type's state after #3 to
948 // make sure it's not TEXT_INPUT_TYPE_NONE.
949 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_FocusRestored) {
950 TestHelper("testFocusRestored", "web_view/focus", NO_TEST_SERVER);
951 content::WebContents* embedder_web_contents = GetFirstAppWindowWebContents();
952 ASSERT_TRUE(embedder_web_contents);
953 ASSERT_TRUE(guest_web_contents());
955 // 1) We click on the guest so that we get a focus event.
956 ExtensionTestMessageListener next_step_listener("TEST_STEP_PASSED", false);
957 next_step_listener.set_failure_message("TEST_STEP_FAILED");
959 content::SimulateMouseClickAt(guest_web_contents(),
961 blink::WebMouseEvent::ButtonLeft,
962 gfx::Point(10, 10));
963 EXPECT_TRUE(content::ExecuteScript(
964 embedder_web_contents,
965 "window.runCommand('testFocusRestoredRunNextStep', 1);"));
967 // Wait for the next step to complete.
968 ASSERT_TRUE(next_step_listener.WaitUntilSatisfied());
970 // 2) We click on the embedder so the guest's focus goes away and it observes
971 // a blur event.
972 next_step_listener.Reset();
974 content::SimulateMouseClickAt(embedder_web_contents,
976 blink::WebMouseEvent::ButtonLeft,
977 gfx::Point(200, 20));
978 EXPECT_TRUE(content::ExecuteScript(
979 embedder_web_contents,
980 "window.runCommand('testFocusRestoredRunNextStep', 2);"));
982 // Wait for the next step to complete.
983 ASSERT_TRUE(next_step_listener.WaitUntilSatisfied());
985 // 3) We click on the guest again to bring back focus directly to the previous
986 // input element, then we ensure text_input_type is properly set.
987 next_step_listener.Reset();
989 content::SimulateMouseClickAt(guest_web_contents(),
991 blink::WebMouseEvent::ButtonLeft,
992 gfx::Point(10, 10));
993 EXPECT_TRUE(content::ExecuteScript(
994 embedder_web_contents,
995 "window.runCommand('testFocusRestoredRunNextStep', 3)"));
997 // Wait for the next step to complete.
998 ASSERT_TRUE(next_step_listener.WaitUntilSatisfied());
1000 // |text_input_client| is not available for mac and android.
1001 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
1002 ui::TextInputClient* text_input_client =
1003 embedder_web_contents->GetRenderViewHost()->GetView()
1004 ->GetTextInputClient();
1005 ASSERT_TRUE(text_input_client);
1006 ASSERT_TRUE(text_input_client->GetTextInputType() !=
1007 ui::TEXT_INPUT_TYPE_NONE);
1008 #endif
1011 // ui::TextInputClient is NULL for mac and android.
1012 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
1013 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_Focus_InputMethod) {
1014 content::WebContents* embedder_web_contents = NULL;
1015 scoped_ptr<ExtensionTestMessageListener> done_listener(
1016 RunAppHelper("testInputMethod", "web_view/focus", NO_TEST_SERVER,
1017 &embedder_web_contents));
1018 ASSERT_TRUE(done_listener->WaitUntilSatisfied());
1020 ui::TextInputClient* text_input_client =
1021 embedder_web_contents->GetRenderViewHost()->GetView()
1022 ->GetTextInputClient();
1023 ASSERT_TRUE(text_input_client);
1025 ExtensionTestMessageListener next_step_listener("TEST_STEP_PASSED", false);
1026 next_step_listener.set_failure_message("TEST_STEP_FAILED");
1028 // An input element inside the <webview> gets focus and is given some
1029 // user input via IME.
1031 ui::CompositionText composition;
1032 composition.text = base::UTF8ToUTF16("InputTest123");
1033 text_input_client->SetCompositionText(composition);
1034 EXPECT_TRUE(content::ExecuteScript(
1035 embedder_web_contents,
1036 "window.runCommand('testInputMethodRunNextStep', 1);"));
1038 // Wait for the next step to complete.
1039 ASSERT_TRUE(next_step_listener.WaitUntilSatisfied());
1042 // A composition is committed via IME.
1044 next_step_listener.Reset();
1046 ui::CompositionText composition;
1047 composition.text = base::UTF8ToUTF16("InputTest456");
1048 text_input_client->SetCompositionText(composition);
1049 text_input_client->ConfirmCompositionText();
1050 EXPECT_TRUE(content::ExecuteScript(
1051 embedder_web_contents,
1052 "window.runCommand('testInputMethodRunNextStep', 2);"));
1054 // Wait for the next step to complete.
1055 EXPECT_TRUE(next_step_listener.WaitUntilSatisfied());
1058 // Moving focus causes IME cancel, and the composition will be committed
1059 // in first <input> in the <webview>, not in the second <input>.
1061 next_step_listener.Reset();
1062 ui::CompositionText composition;
1063 composition.text = base::UTF8ToUTF16("InputTest789");
1064 text_input_client->SetCompositionText(composition);
1065 EXPECT_TRUE(content::ExecuteScript(
1066 embedder_web_contents,
1067 "window.runCommand('testInputMethodRunNextStep', 3);"));
1069 // Wait for the next step to complete.
1070 EXPECT_TRUE(next_step_listener.WaitUntilSatisfied());
1073 // Tests ExtendSelectionAndDelete message works in <webview>.
1075 next_step_listener.Reset();
1077 // At this point we have set focus on first <input> in the <webview>,
1078 // and the value it contains is 'InputTestABC' with caret set after 'T'.
1079 // Now we delete 'Test' in 'InputTestABC', as the caret is after 'T':
1080 // delete before 1 character ('T') and after 3 characters ('est').
1081 text_input_client->ExtendSelectionAndDelete(1, 3);
1082 EXPECT_TRUE(content::ExecuteScript(
1083 embedder_web_contents,
1084 "window.runCommand('testInputMethodRunNextStep', 4);"));
1086 // Wait for the next step to complete.
1087 EXPECT_TRUE(next_step_listener.WaitUntilSatisfied());
1090 #endif
1092 #if defined(OS_MACOSX)
1093 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, TextSelection) {
1094 SetupTest("web_view/text_selection",
1095 "/extensions/platform_apps/web_view/text_selection/guest.html");
1096 ASSERT_TRUE(guest_web_contents());
1097 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
1098 GetPlatformAppWindow()));
1100 // Wait until guest sees a context menu, select an arbitrary item (copy).
1101 ExtensionTestMessageListener ctx_listener("MSG_CONTEXTMENU", false);
1102 ContextMenuNotificationObserver menu_observer(IDC_CONTENT_CONTEXT_COPY);
1103 SimulateRWHMouseClick(guest_web_contents()->GetRenderViewHost(),
1104 blink::WebMouseEvent::ButtonRight, 20, 20);
1105 ASSERT_TRUE(ctx_listener.WaitUntilSatisfied());
1107 // Now verify that the selection text propagates properly to RWHV.
1108 content::RenderWidgetHostView* guest_rwhv =
1109 guest_web_contents()->GetRenderWidgetHostView();
1110 ASSERT_TRUE(guest_rwhv);
1111 std::string selected_text = base::UTF16ToUTF8(guest_rwhv->GetSelectedText());
1112 ASSERT_TRUE(selected_text.size() >= 10u);
1113 ASSERT_EQ("AAAAAAAAAA", selected_text.substr(0, 10));
1115 #endif