1// Copyright 2014 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/files/file_util.h"
6#include "base/memory/ref_counted.h"
7#include "base/path_service.h"
8#include "base/prefs/pref_service.h"
9#include "base/strings/utf_string_conversions.h"
10#include "chrome/app/chrome_command_ids.h"
11#include "chrome/browser/plugins/plugin_prefs.h"
12#include "chrome/browser/profiles/profile.h"
13#include "chrome/browser/ui/browser.h"
14#include "chrome/browser/ui/browser_commands.h"
15#include "chrome/browser/ui/find_bar/find_bar.h"
16#include "chrome/browser/ui/find_bar/find_bar_controller.h"
17#include "chrome/browser/ui/find_bar/find_bar_host_unittest_util.h"
18#include "chrome/browser/ui/tabs/tab_strip_model.h"
19#include "chrome/common/pref_names.h"
20#include "chrome/test/base/in_process_browser_test.h"
21#include "chrome/test/base/ui_test_utils.h"
22#include "content/public/browser/browser_thread.h"
23#include "content/public/browser/child_process_data.h"
24#include "content/public/browser/plugin_service.h"
25#include "content/public/browser/web_contents.h"
26#include "content/public/common/content_constants.h"
27#include "content/public/common/content_paths.h"
28#include "content/public/common/process_type.h"
29#include "content/public/common/webplugininfo.h"
30#include "content/public/test/browser_test_utils.h"
31#include "content/public/test/test_navigation_observer.h"
32#include "content/public/test/test_utils.h"
33
34#if defined(OS_WIN)
35#include "ui/aura/window.h"
36#include "ui/aura/window_tree_host.h"
37#endif
38
39#if defined(OS_WIN)
40
41namespace {
42
43BOOL CALLBACK EnumerateChildren(HWND hwnd, LPARAM l_param) {
44  HWND* child = reinterpret_cast<HWND*>(l_param);
45  *child = hwnd;
46  // The first child window is the plugin, then its children. So stop
47  // enumerating after the first callback.
48  return FALSE;
49}
50
51}  // namespace
52
53typedef InProcessBrowserTest ChromePluginTest;
54
55// Test that if a background tab loads an NPAPI plugin, they are displayed after
56// switching to that page.  http://crbug.com/335900
57// flaky: http://crbug.com/406631
58IN_PROC_BROWSER_TEST_F(ChromePluginTest, DISABLED_WindowedNPAPIPluginHidden) {
59  browser()->profile()->GetPrefs()->SetBoolean(prefs::kPluginsAlwaysAuthorize,
60                                               true);
61
62  // First load the page in the background and wait for the NPAPI plugin's
63  // window to be created.
64  GURL url = ui_test_utils::GetTestUrl(
65      base::FilePath(),
66      base::FilePath().AppendASCII("windowed_npapi_plugin.html"));
67
68  ui_test_utils::NavigateToURLWithDisposition(
69      browser(), url, NEW_BACKGROUND_TAB,
70      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
71
72  // We create a third window just to trigger the second one to update its
73  // constrained window list. Normally this would be triggered by the status bar
74  // animation closing after the user middle clicked a link.
75  ui_test_utils::NavigateToURLWithDisposition(
76      browser(), GURL("about:blank"), NEW_BACKGROUND_TAB,
77      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
78
79  base::string16 expected_title(base::ASCIIToUTF16("created"));
80  content::WebContents* tab =
81      browser()->tab_strip_model()->GetWebContentsAt(1);
82  if (tab->GetTitle() != expected_title) {
83    content::TitleWatcher title_watcher(tab, expected_title);
84    EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
85  }
86
87  // Now activate the tab and verify that the plugin painted.
88  browser()->tab_strip_model()->ActivateTabAt(1, true);
89
90  base::string16 expected_title2(base::ASCIIToUTF16("shown"));
91  content::TitleWatcher title_watcher2(tab, expected_title2);
92  EXPECT_EQ(expected_title2, title_watcher2.WaitAndGetTitle());
93
94  HWND child = NULL;
95  HWND hwnd = tab->GetNativeView()->GetHost()->GetAcceleratedWidget();
96  EnumChildWindows(hwnd, EnumerateChildren,reinterpret_cast<LPARAM>(&child));
97
98  RECT region;
99  int result = GetWindowRgnBox(child, &region);
100  ASSERT_NE(result, NULLREGION);
101}
102
103typedef InProcessBrowserTest PrintPreviewTest;
104
105// This test verifies that constrained windows aren't covered by windowed NPAPI
106// plugins. The code which fixes this is in WebContentsViewAura::WindowObserver.
107// flaky: http://crbug.com/406631
108IN_PROC_BROWSER_TEST_F(PrintPreviewTest, DISABLED_WindowedNPAPIPluginHidden) {
109  browser()->profile()->GetPrefs()->SetBoolean(prefs::kPluginsAlwaysAuthorize,
110                                               true);
111
112  // First load the page and wait for the NPAPI plugin's window to display.
113  base::string16 expected_title(base::ASCIIToUTF16("ready"));
114  content::WebContents* tab =
115      browser()->tab_strip_model()->GetActiveWebContents();
116  content::TitleWatcher title_watcher(tab, expected_title);
117
118  GURL url = ui_test_utils::GetTestUrl(
119      base::FilePath().AppendASCII("printing"),
120      base::FilePath().AppendASCII("npapi_plugin.html"));
121  ui_test_utils::NavigateToURL(browser(), url);
122
123  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
124
125  // Now get the region of the plugin before and after the print preview is
126  // shown. They should be different.
127  HWND hwnd = tab->GetNativeView()->GetHost()->GetAcceleratedWidget();
128  HWND child = NULL;
129  EnumChildWindows(hwnd, EnumerateChildren,reinterpret_cast<LPARAM>(&child));
130
131  RECT region_before, region_after;
132  int result = GetWindowRgnBox(child, &region_before);
133  ASSERT_EQ(result, SIMPLEREGION);
134
135  // Now print preview.
136  content::TestNavigationObserver nav_observer(NULL);
137  nav_observer.StartWatchingNewWebContents();
138  chrome::ExecuteCommand(browser(), IDC_PRINT);
139  nav_observer.Wait();
140  nav_observer.StopWatchingNewWebContents();
141
142  result = GetWindowRgnBox(child, &region_after);
143  if (result == NULLREGION) {
144    // Depending on the browser window size, the plugin could be full covered.
145    return;
146  }
147
148  if (result == COMPLEXREGION) {
149    // Complex region, by definition not equal to the initial region.
150    return;
151  }
152
153  ASSERT_EQ(result, SIMPLEREGION);
154  bool rects_equal =
155      region_before.left == region_after.left &&
156      region_before.top == region_after.top &&
157      region_before.right == region_after.right &&
158      region_before.bottom == region_after.bottom;
159  ASSERT_FALSE(rects_equal);
160}
161
162typedef InProcessBrowserTest FindInPageControllerTest;
163
164void EnsureFindBoxOpen(Browser* browser) {
165  chrome::ShowFindBar(browser);
166  gfx::Point position;
167  bool fully_visible = false;
168  FindBarTesting* find_bar =
169      browser->GetFindBarController()->find_bar()->GetFindBarTesting();
170  EXPECT_TRUE(find_bar->GetFindBarWindowInfo(&position, &fully_visible));
171  EXPECT_TRUE(fully_visible);
172}
173
174// Ensure that the find bar is always over a windowed NPAPI plugin.
175// flaky: http://crbug.com/406631
176IN_PROC_BROWSER_TEST_F(FindInPageControllerTest,
177                       DISABLED_WindowedNPAPIPluginHidden) {
178  chrome::DisableFindBarAnimationsDuringTesting(true);
179  browser()->profile()->GetPrefs()->SetBoolean(prefs::kPluginsAlwaysAuthorize,
180                                               true);
181
182  // First load the page and wait for the NPAPI plugin's window to display.
183  base::string16 expected_title(base::ASCIIToUTF16("ready"));
184  content::WebContents* tab =
185      browser()->tab_strip_model()->GetActiveWebContents();
186  content::TitleWatcher title_watcher(tab, expected_title);
187
188  GURL url = ui_test_utils::GetTestUrl(
189      base::FilePath().AppendASCII("printing"),
190      base::FilePath().AppendASCII("npapi_plugin.html"));
191  ui_test_utils::NavigateToURL(browser(), url);
192
193  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
194
195  // Now get the region of the plugin before the find bar is shown.
196  HWND hwnd = tab->GetNativeView()->GetHost()->GetAcceleratedWidget();
197  HWND child = NULL;
198  EnumChildWindows(hwnd, EnumerateChildren, reinterpret_cast<LPARAM>(&child));
199
200  RECT region_before, region_after;
201  int result = GetWindowRgnBox(child, &region_before);
202  ASSERT_EQ(result, SIMPLEREGION);
203
204  // Create a new tab and open the find bar there.
205  chrome::NewTab(browser());
206  browser()->tab_strip_model()->ActivateTabAt(1, true);
207  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
208
209  EnsureFindBoxOpen(browser());
210
211  // Now switch back to the original tab with the plugin and show the find bar.
212  browser()->tab_strip_model()->ActivateTabAt(0, true);
213  EnsureFindBoxOpen(browser());
214
215  result = GetWindowRgnBox(child, &region_after);
216  if (result == NULLREGION) {
217    // Depending on the browser window size, the plugin could be full covered.
218    return;
219  }
220
221  if (result == COMPLEXREGION) {
222    // Complex region, by definition not equal to the initial region.
223    return;
224  }
225
226  ASSERT_EQ(result, SIMPLEREGION);
227  bool rects_equal =
228      region_before.left == region_after.left &&
229      region_before.top == region_after.top &&
230      region_before.right == region_after.right &&
231      region_before.bottom == region_after.bottom;
232  ASSERT_FALSE(rects_equal);
233}
234
235#endif
236