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