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 "apps/shell_window.h"
6#include "apps/shell_window_registry.h"
7#include "base/strings/stringprintf.h"
8#include "base/strings/utf_string_conversions.h"
9#include "chrome/browser/apps/app_browsertest_util.h"
10#include "chrome/browser/extensions/extension_test_message_listener.h"
11#include "chrome/browser/profiles/profile.h"
12#include "chrome/test/base/interactive_test_utils.h"
13#include "chrome/test/base/test_launcher_utils.h"
14#include "chrome/test/base/ui_test_utils.h"
15#include "content/public/browser/notification_service.h"
16#include "content/public/browser/render_process_host.h"
17#include "content/public/browser/render_view_host.h"
18#include "content/public/browser/render_widget_host_view.h"
19#include "content/public/browser/web_contents.h"
20#include "content/public/browser/web_contents_view.h"
21#include "content/public/common/content_switches.h"
22#include "content/public/test/browser_test_utils.h"
23#include "net/test/embedded_test_server/embedded_test_server.h"
24#include "ui/base/test/ui_controls.h"
25#include "ui/events/keycodes/keyboard_codes.h"
26
27using apps::ShellWindow;
28
29class WebViewInteractiveTest
30    : public extensions::PlatformAppBrowserTest {
31 public:
32  WebViewInteractiveTest()
33      : corner_(gfx::Point()),
34        mouse_click_result_(false),
35        first_click_(true) {}
36
37  virtual void SetUp() OVERRIDE {
38    // We need real contexts, otherwise the embedder doesn't composite, but the
39    // guest does, and that isn't an expected configuration.
40    UseRealGLContexts();
41    extensions::PlatformAppBrowserTest::SetUp();
42  }
43
44  void MoveMouseInsideWindowWithListener(gfx::Point point,
45                                         const std::string& message) {
46    ExtensionTestMessageListener move_listener(message, false);
47    ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
48        gfx::Point(corner_.x() + point.x(), corner_.y() + point.y())));
49    ASSERT_TRUE(move_listener.WaitUntilSatisfied());
50  }
51
52  void SendMouseClickWithListener(ui_controls::MouseButton button,
53                                  const std::string& message) {
54    ExtensionTestMessageListener listener(message, false);
55    SendMouseClick(button);
56    ASSERT_TRUE(listener.WaitUntilSatisfied());
57  }
58
59  void SendMouseClick(ui_controls::MouseButton button) {
60    SendMouseEvent(button, ui_controls::DOWN);
61    SendMouseEvent(button, ui_controls::UP);
62  }
63
64  void MoveMouseInsideWindow(const gfx::Point& point) {
65    ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
66        gfx::Point(corner_.x() + point.x(), corner_.y() + point.y())));
67  }
68
69  gfx::NativeWindow GetPlatformAppWindow() {
70    const apps::ShellWindowRegistry::ShellWindowList& shell_windows =
71        apps::ShellWindowRegistry::Get(
72            browser()->profile())->shell_windows();
73    return (*shell_windows.begin())->GetNativeWindow();
74  }
75
76  void SendKeyPressToPlatformApp(ui::KeyboardCode key) {
77    ASSERT_EQ(1U, GetShellWindowCount());
78    ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
79        GetPlatformAppWindow(), key, false, false, false, false));
80  }
81
82  void SendCopyKeyPressToPlatformApp() {
83    ASSERT_EQ(1U, GetShellWindowCount());
84#if defined(OS_MACOSX)
85    // Send Cmd+C on MacOSX.
86    ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
87        GetPlatformAppWindow(), ui::VKEY_C, false, false, false, true));
88#else
89    // Send Ctrl+C on Windows and Linux/ChromeOS.
90    ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
91        GetPlatformAppWindow(), ui::VKEY_C, true, false, false, false));
92#endif
93  }
94
95  void SendStartOfLineKeyPressToPlatformApp() {
96#if defined(OS_MACOSX)
97    // Send Cmd+Left on MacOSX.
98    ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
99        GetPlatformAppWindow(), ui::VKEY_LEFT, false, false, false, true));
100#else
101    // Send Ctrl+Left on Windows and Linux/ChromeOS.
102    ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
103        GetPlatformAppWindow(), ui::VKEY_LEFT, true, false, false, false));
104#endif
105  }
106
107  void SendBackShortcutToPlatformApp() {
108#if defined(OS_MACOSX)
109    // Send Cmd+[ on MacOSX.
110    ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
111        GetPlatformAppWindow(), ui::VKEY_OEM_4, false, false, false, true));
112#else
113    // Send browser back key on Linux/Windows.
114    ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
115        GetPlatformAppWindow(), ui::VKEY_BROWSER_BACK,
116        false, false, false, false));
117#endif
118  }
119
120  void SendForwardShortcutToPlatformApp() {
121#if defined(OS_MACOSX)
122    // Send Cmd+] on MacOSX.
123    ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
124        GetPlatformAppWindow(), ui::VKEY_OEM_6, false, false, false, true));
125#else
126    // Send browser back key on Linux/Windows.
127    ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
128        GetPlatformAppWindow(), ui::VKEY_BROWSER_FORWARD,
129        false, false, false, false));
130#endif
131  }
132
133  void SendMouseEvent(ui_controls::MouseButton button,
134                      ui_controls::MouseButtonState state) {
135    if (first_click_) {
136      mouse_click_result_ = ui_test_utils::SendMouseEventsSync(button,
137                                                                state);
138      first_click_ = false;
139    } else {
140      ASSERT_EQ(mouse_click_result_, ui_test_utils::SendMouseEventsSync(
141          button, state));
142    }
143  }
144
145  enum TestServer {
146    NEEDS_TEST_SERVER,
147    NO_TEST_SERVER
148  };
149
150  scoped_ptr<ExtensionTestMessageListener> RunAppHelper(
151      const std::string& test_name,
152      const std::string& app_location,
153      TestServer test_server,
154      content::WebContents** embedder_web_contents) {
155    // For serving guest pages.
156    if ((test_server == NEEDS_TEST_SERVER) && !StartEmbeddedTestServer()) {
157      LOG(ERROR) << "FAILED TO START TEST SERVER.";
158      return scoped_ptr<ExtensionTestMessageListener>();
159    }
160
161    ExtensionTestMessageListener launched_listener("Launched", false);
162    LoadAndLaunchPlatformApp(app_location.c_str());
163    if (!launched_listener.WaitUntilSatisfied()) {
164      LOG(ERROR) << "TEST DID NOT LAUNCH.";
165      return scoped_ptr<ExtensionTestMessageListener>();
166    }
167
168    if (!ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow())) {
169      LOG(ERROR) << "UNABLE TO FOCUS TEST WINDOW.";
170      return scoped_ptr<ExtensionTestMessageListener>();
171    }
172
173    // Flush any pending events to make sure we start with a clean slate.
174    content::RunAllPendingInMessageLoop();
175
176    *embedder_web_contents = GetFirstShellWindowWebContents();
177
178    scoped_ptr<ExtensionTestMessageListener> done_listener(
179        new ExtensionTestMessageListener("TEST_PASSED", false));
180    done_listener->AlsoListenForFailureMessage("TEST_FAILED");
181    if (!content::ExecuteScript(
182            *embedder_web_contents,
183            base::StringPrintf("runTest('%s')", test_name.c_str()))) {
184      LOG(ERROR) << "UNABLE TO START TEST";
185      return scoped_ptr<ExtensionTestMessageListener>();
186    }
187
188    return done_listener.Pass();
189  }
190
191  void TestHelper(const std::string& test_name,
192                  const std::string& app_location,
193                  TestServer test_server) {
194    content::WebContents* embedder_web_contents = NULL;
195    scoped_ptr<ExtensionTestMessageListener> done_listener(
196        RunAppHelper(
197            test_name, app_location, test_server, &embedder_web_contents));
198
199    ASSERT_TRUE(done_listener);
200    ASSERT_TRUE(done_listener->WaitUntilSatisfied());
201  }
202
203  void RunTest(const std::string& app_name) {
204  }
205  void SetupTest(const std::string& app_name,
206                 const std::string& guest_url_spec) {
207    ASSERT_TRUE(StartEmbeddedTestServer());
208    GURL::Replacements replace_host;
209    std::string host_str("localhost");  // Must stay in scope with replace_host.
210    replace_host.SetHostStr(host_str);
211
212    GURL guest_url = embedded_test_server()->GetURL(guest_url_spec);
213    guest_url = guest_url.ReplaceComponents(replace_host);
214
215    ui_test_utils::UrlLoadObserver guest_observer(
216        guest_url, content::NotificationService::AllSources());
217
218    ExtensionTestMessageListener guest_connected_listener("connected", false);
219    LoadAndLaunchPlatformApp(app_name.c_str());
220
221    guest_observer.Wait();
222
223    // Wait until the guest process reports that it has established a message
224    // channel with the app.
225    ASSERT_TRUE(guest_connected_listener.WaitUntilSatisfied());
226    content::Source<content::NavigationController> source =
227        guest_observer.source();
228    EXPECT_TRUE(source->GetWebContents()->GetRenderProcessHost()->IsGuest());
229
230    guest_web_contents_ = source->GetWebContents();
231    embedder_web_contents_ = guest_web_contents_->GetEmbedderWebContents();
232
233    gfx::Rect offset;
234    embedder_web_contents_->GetView()->GetContainerBounds(&offset);
235    corner_ = gfx::Point(offset.x(), offset.y());
236
237    const testing::TestInfo* const test_info =
238            testing::UnitTest::GetInstance()->current_test_info();
239    const char* prefix = "DragDropWithinWebView";
240    if (!strncmp(test_info->name(), prefix, strlen(prefix))) {
241      // In the drag drop test we add 20px padding to the page body because on
242      // windows if we get too close to the edge of the window the resize cursor
243      // appears and we start dragging the window edge.
244      corner_.Offset(20, 20);
245    }
246  }
247
248  content::WebContents* guest_web_contents() {
249    return guest_web_contents_;
250  }
251
252  content::WebContents* embedder_web_contents() {
253    return embedder_web_contents_;
254  }
255
256  gfx::Point corner() {
257    return corner_;
258  }
259
260  void SimulateRWHMouseClick(content::RenderWidgetHost* rwh, int x, int y) {
261    blink::WebMouseEvent mouse_event;
262    mouse_event.button = blink::WebMouseEvent::ButtonLeft;
263    mouse_event.x = mouse_event.windowX = x;
264    mouse_event.y = mouse_event.windowY = y;
265    mouse_event.modifiers = 0;
266
267    mouse_event.type = blink::WebInputEvent::MouseDown;
268    rwh->ForwardMouseEvent(mouse_event);
269    mouse_event.type = blink::WebInputEvent::MouseUp;
270    rwh->ForwardMouseEvent(mouse_event);
271  }
272
273  // TODO(lazyboy): implement
274  class PopupCreatedObserver {
275   public:
276    PopupCreatedObserver() : created_(false), last_render_widget_host_(NULL) {
277    }
278    virtual ~PopupCreatedObserver() {
279    }
280    void Reset() {
281      created_ = false;
282    }
283    void Start() {
284      if (created_)
285        return;
286      message_loop_ = new content::MessageLoopRunner;
287      message_loop_->Run();
288    }
289    content::RenderWidgetHost* last_render_widget_host() {
290      return last_render_widget_host_;
291    }
292
293   private:
294    scoped_refptr<content::MessageLoopRunner> message_loop_;
295    bool created_;
296    content::RenderWidgetHost* last_render_widget_host_;
297  };
298
299  void WaitForTitle(const char* title) {
300    base::string16 expected_title(ASCIIToUTF16(title));
301    base::string16 error_title(ASCIIToUTF16("FAILED"));
302    content::TitleWatcher title_watcher(guest_web_contents(), expected_title);
303    title_watcher.AlsoWaitForTitle(error_title);
304    ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
305  }
306
307  void PopupTestHelper(const gfx::Point& padding) {
308    PopupCreatedObserver popup_created_observer;
309    popup_created_observer.Reset();
310
311    content::SimulateKeyPress(
312        guest_web_contents(),
313        ui::VKEY_C,  // C to autocomplete.
314        false, false, false, false);
315
316    WaitForTitle("PASSED1");
317
318    popup_created_observer.Start();
319
320    content::RenderWidgetHost* popup_rwh = NULL;
321    popup_rwh = popup_created_observer.last_render_widget_host();
322    // Popup must be present.
323    ASSERT_TRUE(popup_rwh);
324    ASSERT_TRUE(!popup_rwh->IsRenderView());
325    ASSERT_TRUE(popup_rwh->GetView());
326
327    base::string16 expected_title = ASCIIToUTF16("PASSED2");
328    base::string16 error_title = ASCIIToUTF16("FAILED");
329    content::TitleWatcher title_watcher(guest_web_contents(), expected_title);
330    title_watcher.AlsoWaitForTitle(error_title);
331    EXPECT_TRUE(content::ExecuteScript(guest_web_contents(),
332                                       "changeTitle();"));
333    ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
334
335    gfx::Rect popup_bounds = popup_rwh->GetView()->GetViewBounds();
336    // (2, 2) is expected to lie on the first datalist element.
337    SimulateRWHMouseClick(popup_rwh, 2, 2);
338
339    content::RenderViewHost* embedder_rvh =
340        GetFirstShellWindowWebContents()->GetRenderViewHost();
341    gfx::Rect embedder_bounds = embedder_rvh->GetView()->GetViewBounds();
342    gfx::Vector2d diff = popup_bounds.origin() - embedder_bounds.origin();
343    LOG(INFO) << "DIFF: x = " << diff.x() << ", y = " << diff.y();
344
345    const int left_spacing = 40 + padding.x();  // div.style.paddingLeft = 40px.
346    // div.style.paddingTop = 50px + (input box height = 26px).
347    const int top_spacing = 50 + 26 + padding.y();
348
349    // If the popup is placed within |threshold_px| of the expected position,
350    // then we consider the test as a pass.
351    const int threshold_px = 10;
352
353    EXPECT_LE(std::abs(diff.x() - left_spacing), threshold_px);
354    EXPECT_LE(std::abs(diff.y() - top_spacing), threshold_px);
355
356    WaitForTitle("PASSED3");
357  }
358
359  void DragTestStep1() {
360    // Move mouse to start of text.
361    MoveMouseInsideWindow(gfx::Point(45, 8));
362    MoveMouseInsideWindow(gfx::Point(45, 9));
363    SendMouseEvent(ui_controls::LEFT, ui_controls::DOWN);
364
365    MoveMouseInsideWindow(gfx::Point(74, 12));
366    MoveMouseInsideWindow(gfx::Point(78, 12));
367
368    // Now wait a bit before moving mouse to initiate drag/drop.
369    base::MessageLoop::current()->PostDelayedTask(
370        FROM_HERE,
371        base::Bind(&WebViewInteractiveTest::DragTestStep2,
372                   base::Unretained(this)),
373        base::TimeDelta::FromMilliseconds(200));
374  }
375
376  void DragTestStep2() {
377    // Drag source over target.
378    MoveMouseInsideWindow(gfx::Point(76, 76));
379
380    // Create a second mouse over the source to trigger the drag over event.
381    MoveMouseInsideWindow(gfx::Point(76, 77));
382
383    // Release mouse to drop.
384    SendMouseEvent(ui_controls::LEFT, ui_controls::UP);
385    SendMouseClick(ui_controls::LEFT);
386
387    quit_closure_.Run();
388
389    // Note that following ExtensionTestMessageListener and ExecuteScript*
390    // call must be after we quit |quit_closure_|. Otherwise the class
391    // here won't be able to receive messages sent by chrome.test.sendMessage.
392    // This is because of the nature of drag and drop code (esp. the
393    // MessageLoop) in it.
394
395    // Now check if we got a drop and read the drop data.
396    embedder_web_contents_ = GetFirstShellWindowWebContents();
397    ExtensionTestMessageListener drop_listener("guest-got-drop", false);
398    EXPECT_TRUE(content::ExecuteScript(embedder_web_contents_,
399                                       "window.checkIfGuestGotDrop()"));
400    EXPECT_TRUE(drop_listener.WaitUntilSatisfied());
401
402    std::string last_drop_data;
403    EXPECT_TRUE(content::ExecuteScriptAndExtractString(
404                    embedder_web_contents_,
405                    "window.domAutomationController.send(getLastDropData())",
406                    &last_drop_data));
407
408    last_drop_data_ = last_drop_data;
409  }
410
411 protected:
412  content::WebContents* guest_web_contents_;
413  content::WebContents* embedder_web_contents_;
414  gfx::Point corner_;
415  bool mouse_click_result_;
416  bool first_click_;
417  // Only used in drag/drop test.
418  base::Closure quit_closure_;
419  std::string last_drop_data_;
420};
421
422// ui_test_utils::SendMouseMoveSync doesn't seem to work on OS_MACOSX, and
423// likely won't work on many other platforms as well, so for now this test
424// is for Windows and Linux only. As of Sept 17th, 2013 this test is disabled
425// on Windows due to flakines, see http://crbug.com/293445.
426
427#if defined(OS_LINUX)
428
429IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, PointerLock) {
430  SetupTest("web_view/pointer_lock",
431            "/extensions/platform_apps/web_view/pointer_lock/guest.html");
432
433  // Move the mouse over the Lock Pointer button.
434  ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
435      gfx::Point(corner().x() + 75, corner().y() + 25)));
436
437  // Click the Lock Pointer button. The first two times the button is clicked
438  // the permission API will deny the request (intentional).
439  ExtensionTestMessageListener exception_listener("request exception", false);
440  SendMouseClickWithListener(ui_controls::LEFT, "lock error");
441  ASSERT_TRUE(exception_listener.WaitUntilSatisfied());
442  SendMouseClickWithListener(ui_controls::LEFT, "lock error");
443
444  // Click the Lock Pointer button, locking the mouse to lockTarget1.
445  SendMouseClickWithListener(ui_controls::LEFT, "locked");
446
447  // Attempt to move the mouse off of the lock target, and onto lockTarget2,
448  // (which would trigger a test failure).
449  ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
450      gfx::Point(corner().x() + 74, corner().y() + 74)));
451  MoveMouseInsideWindowWithListener(gfx::Point(75, 75), "mouse-move");
452
453#if (defined(OS_WIN) && defined(USE_AURA))
454  // When the mouse is unlocked on win aura, sending a test mouse click clicks
455  // where the mouse moved to while locked. I was unable to figure out why, and
456  // since the issue only occurs with the test mouse events, just fix it with
457  // a simple workaround - moving the mouse back to where it should be.
458  // TODO(mthiesse): Fix Win Aura simulated mouse events while mouse locked.
459  MoveMouseInsideWindowWithListener(gfx::Point(75, 25), "mouse-move");
460#endif
461
462  ExtensionTestMessageListener unlocked_listener("unlocked", false);
463  // Send a key press to unlock the mouse.
464  SendKeyPressToPlatformApp(ui::VKEY_ESCAPE);
465
466  // Wait for page to receive (successful) mouse unlock response.
467  ASSERT_TRUE(unlocked_listener.WaitUntilSatisfied());
468
469  // After the second lock, guest.js sends a message to main.js to remove the
470  // webview object. main.js then removes the div containing the webview, which
471  // should unlock, and leave the mouse over the mousemove-capture-container
472  // div. We then move the mouse over that div to ensure the mouse was properly
473  // unlocked and that the div receieves the message.
474  ExtensionTestMessageListener move_captured_listener("move-captured", false);
475  move_captured_listener.AlsoListenForFailureMessage("timeout");
476
477  // Mouse should already be over lock button (since we just unlocked), so send
478  // click to re-lock the mouse.
479  SendMouseClickWithListener(ui_controls::LEFT, "deleted");
480
481  // A mousemove event is triggered on the mousemove-capture-container element
482  // when we delete the webview container (since the mouse moves onto the
483  // element), but just in case, send an explicit mouse movement to be safe.
484  ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
485      gfx::Point(corner().x() + 50, corner().y() + 10)));
486
487  // Wait for page to receive second (successful) mouselock response.
488  bool success = move_captured_listener.WaitUntilSatisfied();
489  if (!success) {
490    fprintf(stderr, "TIMEOUT - retrying\n");
491    // About 1 in 40 tests fail to detect mouse moves at this point (why?).
492    // Sending a right click seems to fix this (why?).
493    ExtensionTestMessageListener move_listener2("move-captured", false);
494    SendMouseClick(ui_controls::RIGHT);
495    ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
496        gfx::Point(corner().x() + 51, corner().y() + 11)));
497    ASSERT_TRUE(move_listener2.WaitUntilSatisfied());
498  }
499}
500
501#endif  // (defined(OS_WIN) || defined(OS_LINUX))
502
503// Tests that setting focus on the <webview> sets focus on the guest.
504IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_FocusEvent) {
505  TestHelper("testFocusEvent", "web_view/focus", NO_TEST_SERVER);
506}
507
508// Tests that setting focus on the <webview> sets focus on the guest.
509IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Focus_BlurEvent) {
510  TestHelper("testBlurEvent", "web_view/focus", NO_TEST_SERVER);
511}
512
513// Tests that guests receive edit commands and respond appropriately.
514IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, EditCommands) {
515  ExtensionTestMessageListener guest_connected_listener("connected", false);
516  LoadAndLaunchPlatformApp("web_view/edit_commands");
517  // Wait until the guest process reports that it has established a message
518  // channel with the app.
519  ASSERT_TRUE(guest_connected_listener.WaitUntilSatisfied());
520
521  ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
522      GetPlatformAppWindow()));
523
524  // Flush any pending events to make sure we start with a clean slate.
525  content::RunAllPendingInMessageLoop();
526
527  ExtensionTestMessageListener copy_listener("copy", false);
528  SendCopyKeyPressToPlatformApp();
529
530  // Wait for the guest to receive a 'copy' edit command.
531  ASSERT_TRUE(copy_listener.WaitUntilSatisfied());
532}
533
534// Tests that guests receive edit commands and respond appropriately.
535IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, EditCommandsNoMenu) {
536  SetupTest("web_view/edit_commands_no_menu",
537      "/extensions/platform_apps/web_view/edit_commands_no_menu/"
538      "guest.html");
539
540  ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
541      GetPlatformAppWindow()));
542
543  // Flush any pending events to make sure we start with a clean slate.
544  content::RunAllPendingInMessageLoop();
545
546  ExtensionTestMessageListener start_of_line_listener("StartOfLine", false);
547  SendStartOfLineKeyPressToPlatformApp();
548  // Wait for the guest to receive a 'copy' edit command.
549  ASSERT_TRUE(start_of_line_listener.WaitUntilSatisfied());
550}
551
552IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
553                       NewWindow_NewWindowNameTakesPrecedence) {
554  TestHelper("testNewWindowNameTakesPrecedence",
555             "web_view/newwindow",
556             NEEDS_TEST_SERVER);
557}
558
559IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
560                       NewWindow_WebViewNameTakesPrecedence) {
561  TestHelper("testWebViewNameTakesPrecedence",
562             "web_view/newwindow",
563             NEEDS_TEST_SERVER);
564}
565
566IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_NoName) {
567  TestHelper("testNoName",
568             "web_view/newwindow",
569             NEEDS_TEST_SERVER);
570}
571
572IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_Redirect) {
573  TestHelper("testNewWindowRedirect",
574             "web_view/newwindow",
575             NEEDS_TEST_SERVER);
576}
577
578IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_Close) {
579  TestHelper("testNewWindowClose",
580             "web_view/newwindow",
581             NEEDS_TEST_SERVER);
582}
583
584IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_ExecuteScript) {
585  TestHelper("testNewWindowExecuteScript",
586             "web_view/newwindow",
587             NEEDS_TEST_SERVER);
588}
589
590IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
591                       NewWindow_DeclarativeWebRequest) {
592  TestHelper("testNewWindowDeclarativeWebRequest",
593             "web_view/newwindow",
594             NEEDS_TEST_SERVER);
595}
596
597IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_WebRequest) {
598  TestHelper("testNewWindowWebRequest",
599             "web_view/newwindow",
600             NEEDS_TEST_SERVER);
601}
602
603// A custom elements bug needs to be addressed to enable this test:
604// See http://crbug.com/282477 for more information.
605IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
606                       DISABLED_NewWindow_WebRequestCloseWindow) {
607  TestHelper("testNewWindowWebRequestCloseWindow",
608             "web_view/newwindow",
609             NEEDS_TEST_SERVER);
610}
611
612IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
613                       NewWindow_WebRequestRemoveElement) {
614  TestHelper("testNewWindowWebRequestRemoveElement",
615             "web_view/newwindow",
616             NEEDS_TEST_SERVER);
617}
618
619// Tests that Ctrl+Click/Cmd+Click on a link fires up the newwindow API.
620IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, NewWindow_OpenInNewTab) {
621  content::WebContents* embedder_web_contents = NULL;
622
623  ExtensionTestMessageListener loaded_listener("Loaded", false);
624  scoped_ptr<ExtensionTestMessageListener> done_listener(
625    RunAppHelper("testNewWindowOpenInNewTab",
626                 "web_view/newwindow",
627                 NEEDS_TEST_SERVER,
628                 &embedder_web_contents));
629
630  loaded_listener.WaitUntilSatisfied();
631#if defined(OS_MACOSX)
632  ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
633      GetPlatformAppWindow(), ui::VKEY_RETURN,
634      false, false, false, true /* cmd */));
635#else
636  ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
637      GetPlatformAppWindow(), ui::VKEY_RETURN,
638      true /* ctrl */, false, false, false));
639#endif
640
641  // Wait for the embedder to receive a 'newwindow' event.
642  ASSERT_TRUE(done_listener->WaitUntilSatisfied());
643}
644
645
646IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, ExecuteCode) {
647  ASSERT_TRUE(RunPlatformAppTestWithArg(
648      "platform_apps/web_view/common", "execute_code")) << message_;
649}
650
651// This test used the old Autofill UI, which has been removed.
652// See crbug.com/259438
653IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_PopupPositioning) {
654  SetupTest(
655      "web_view/popup_positioning",
656      "/extensions/platform_apps/web_view/popup_positioning/guest.html");
657  ASSERT_TRUE(guest_web_contents());
658
659  PopupTestHelper(gfx::Point());
660
661  // moveTo a random location and run the steps again.
662  EXPECT_TRUE(content::ExecuteScript(embedder_web_contents(),
663                                     "window.moveTo(16, 20);"));
664  PopupTestHelper(gfx::Point());
665}
666
667// Tests that moving browser plugin (without resize/UpdateRects) correctly
668// repositions popup.
669// Started flakily failing after a Blink roll: http://crbug.com/245332
670IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_PopupPositioningMoved) {
671  SetupTest(
672      "web_view/popup_positioning_moved",
673      "/extensions/platform_apps/web_view/popup_positioning_moved"
674      "/guest.html");
675  ASSERT_TRUE(guest_web_contents());
676
677  PopupTestHelper(gfx::Point(20, 0));
678}
679
680// Drag and drop inside a webview is currently only enabled for linux and mac,
681// but the tests don't work on anything except chromeos for now. This is because
682// of simulating mouse drag code's dependency on platforms.
683#if defined(OS_CHROMEOS)
684// This test is flaky. See crbug.com/309032
685IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, DISABLED_DragDropWithinWebView) {
686  ExtensionTestMessageListener guest_connected_listener("connected", false);
687  LoadAndLaunchPlatformApp("web_view/dnd_within_webview");
688  ASSERT_TRUE(guest_connected_listener.WaitUntilSatisfied());
689
690  ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow()));
691
692  gfx::Rect offset;
693  embedder_web_contents_ = GetFirstShellWindowWebContents();
694  embedder_web_contents_->GetView()->GetContainerBounds(&offset);
695  corner_ = gfx::Point(offset.x(), offset.y());
696
697  // In the drag drop test we add 20px padding to the page body because on
698  // windows if we get too close to the edge of the window the resize cursor
699  // appears and we start dragging the window edge.
700  corner_.Offset(20, 20);
701
702  // Flush any pending events to make sure we start with a clean slate.
703  content::RunAllPendingInMessageLoop();
704  for (;;) {
705    base::RunLoop run_loop;
706    quit_closure_ = run_loop.QuitClosure();
707    base::MessageLoop::current()->PostTask(
708        FROM_HERE,
709        base::Bind(&WebViewInteractiveTest::DragTestStep1,
710                   base::Unretained(this)));
711    run_loop.Run();
712
713    if (last_drop_data_ == "Drop me")
714      break;
715
716    LOG(INFO) << "Drag was cancelled in interactive_test, restarting drag";
717
718    // Reset state for next try.
719    ExtensionTestMessageListener reset_listener("resetStateReply", false);
720    EXPECT_TRUE(content::ExecuteScript(embedder_web_contents_,
721                                       "window.resetState()"));
722    ASSERT_TRUE(reset_listener.WaitUntilSatisfied());
723  }
724  ASSERT_EQ("Drop me", last_drop_data_);
725}
726#endif  // (defined(OS_CHROMEOS))
727
728IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Navigation) {
729  TestHelper("testNavigation", "web_view/navigation", NO_TEST_SERVER);
730}
731
732IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, Navigation_BackForwardKeys) {
733  ExtensionTestMessageListener launched_listener("Launched", false);
734  LoadAndLaunchPlatformApp("web_view/navigation");
735  ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
736
737  ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
738      GetPlatformAppWindow()));
739  // Flush any pending events to make sure we start with a clean slate.
740  content::RunAllPendingInMessageLoop();
741
742  content::WebContents* embedder_web_contents =
743      GetFirstShellWindowWebContents();
744  ASSERT_TRUE(embedder_web_contents);
745
746  ExtensionTestMessageListener done_listener(
747      "TEST_PASSED", false);
748  done_listener.AlsoListenForFailureMessage("TEST_FAILED");
749  ExtensionTestMessageListener ready_back_key_listener(
750      "ReadyForBackKey", false);
751  ExtensionTestMessageListener ready_forward_key_listener(
752      "ReadyForForwardKey", false);
753
754  EXPECT_TRUE(content::ExecuteScript(
755                  embedder_web_contents,
756                  "runTest('testBackForwardKeys')"));
757
758  ASSERT_TRUE(ready_back_key_listener.WaitUntilSatisfied());
759  SendBackShortcutToPlatformApp();
760
761  ASSERT_TRUE(ready_forward_key_listener.WaitUntilSatisfied());
762  SendForwardShortcutToPlatformApp();
763
764  ASSERT_TRUE(done_listener.WaitUntilSatisfied());
765}
766
767IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
768                       PointerLock_PointerLockLostWithFocus) {
769  TestHelper("testPointerLockLostWithFocus",
770             "web_view/pointerlock",
771             NO_TEST_SERVER);
772}
773