Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chrome_plugin_browsertest.cc
1 // Copyright (c) 2012 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 <vector>
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/path_service.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/process/kill.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/browser/plugins/plugin_prefs.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/common/pref_names.h"
21 #include "chrome/test/base/in_process_browser_test.h"
22 #include "chrome/test/base/ui_test_utils.h"
23 #include "content/public/browser/browser_child_process_host_iterator.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/child_process_data.h"
26 #include "content/public/browser/plugin_service.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/content_constants.h"
29 #include "content/public/common/content_paths.h"
30 #include "content/public/common/process_type.h"
31 #include "content/public/common/webplugininfo.h"
32 #include "content/public/test/browser_test_utils.h"
33 #include "content/public/test/test_utils.h"
34 #include "net/base/net_util.h"
35
36 #if defined(OS_WIN)
37 #include "content/public/browser/web_contents_view.h"
38 #include "ui/aura/root_window.h"
39 #include "ui/aura/window.h"
40 #endif
41
42 using content::BrowserThread;
43
44 namespace {
45
46 class CallbackBarrier : public base::RefCountedThreadSafe<CallbackBarrier> {
47  public:
48   explicit CallbackBarrier(const base::Closure& target_callback)
49       : target_callback_(target_callback),
50         outstanding_callbacks_(0),
51         did_enable_(true) {
52   }
53
54   base::Callback<void(bool)> CreateCallback() {
55     outstanding_callbacks_++;
56     return base::Bind(&CallbackBarrier::MayRunTargetCallback, this);
57   }
58
59  private:
60   friend class base::RefCountedThreadSafe<CallbackBarrier>;
61
62   ~CallbackBarrier() {
63     EXPECT_TRUE(target_callback_.is_null());
64   }
65
66   void MayRunTargetCallback(bool did_enable) {
67     EXPECT_GT(outstanding_callbacks_, 0);
68     did_enable_ = did_enable_ && did_enable;
69     if (--outstanding_callbacks_ == 0) {
70       EXPECT_TRUE(did_enable_);
71       target_callback_.Run();
72       target_callback_.Reset();
73     }
74   }
75
76   base::Closure target_callback_;
77   int outstanding_callbacks_;
78   bool did_enable_;
79 };
80
81 }  // namespace
82
83 class ChromePluginTest : public InProcessBrowserTest {
84  protected:
85   ChromePluginTest() {}
86
87   static GURL GetURL(const char* filename) {
88     base::FilePath path;
89     PathService::Get(content::DIR_TEST_DATA, &path);
90     path = path.AppendASCII("plugin").AppendASCII(filename);
91     CHECK(base::PathExists(path));
92     return net::FilePathToFileURL(path);
93   }
94
95   static void LoadAndWait(Browser* window, const GURL& url, bool pass) {
96     content::WebContents* web_contents =
97         window->tab_strip_model()->GetActiveWebContents();
98     base::string16 expected_title(
99         base::ASCIIToUTF16(pass ? "OK" : "plugin_not_found"));
100     content::TitleWatcher title_watcher(web_contents, expected_title);
101     title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL"));
102     title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16(
103         pass ? "plugin_not_found" : "OK"));
104     ui_test_utils::NavigateToURL(window, url);
105     ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
106   }
107
108   static void CrashFlash() {
109     scoped_refptr<content::MessageLoopRunner> runner =
110         new content::MessageLoopRunner;
111     BrowserThread::PostTask(
112         BrowserThread::IO,
113         FROM_HERE,
114         base::Bind(&CrashFlashInternal, runner->QuitClosure()));
115     runner->Run();
116   }
117
118   static void GetFlashPath(std::vector<base::FilePath>* paths) {
119     paths->clear();
120     std::vector<content::WebPluginInfo> plugins = GetPlugins();
121     for (std::vector<content::WebPluginInfo>::const_iterator it =
122              plugins.begin(); it != plugins.end(); ++it) {
123       if (it->name == base::ASCIIToUTF16(content::kFlashPluginName))
124         paths->push_back(it->path);
125     }
126   }
127
128   static std::vector<content::WebPluginInfo> GetPlugins() {
129     std::vector<content::WebPluginInfo> plugins;
130     scoped_refptr<content::MessageLoopRunner> runner =
131         new content::MessageLoopRunner;
132     content::PluginService::GetInstance()->GetPlugins(
133         base::Bind(&GetPluginsInfoCallback, &plugins, runner->QuitClosure()));
134     runner->Run();
135     return plugins;
136   }
137
138   static void EnableFlash(bool enable, Profile* profile) {
139     std::vector<base::FilePath> paths;
140     GetFlashPath(&paths);
141     ASSERT_FALSE(paths.empty());
142
143     PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile).get();
144     scoped_refptr<content::MessageLoopRunner> runner =
145         new content::MessageLoopRunner;
146     scoped_refptr<CallbackBarrier> callback_barrier(
147         new CallbackBarrier(runner->QuitClosure()));
148     for (std::vector<base::FilePath>::iterator iter = paths.begin();
149          iter != paths.end(); ++iter) {
150       plugin_prefs->EnablePlugin(enable, *iter,
151                                  callback_barrier->CreateCallback());
152     }
153     runner->Run();
154   }
155
156   static void EnsureFlashProcessCount(int expected) {
157     int actual = 0;
158     scoped_refptr<content::MessageLoopRunner> runner =
159         new content::MessageLoopRunner;
160     BrowserThread::PostTask(
161         BrowserThread::IO,
162         FROM_HERE,
163         base::Bind(&CountPluginProcesses, &actual, runner->QuitClosure()));
164     runner->Run();
165     ASSERT_EQ(expected, actual);
166   }
167
168  private:
169   static void CrashFlashInternal(const base::Closure& quit_task) {
170     bool found = false;
171     for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
172       if (iter.GetData().process_type != content::PROCESS_TYPE_PLUGIN &&
173           iter.GetData().process_type != content::PROCESS_TYPE_PPAPI_PLUGIN) {
174         continue;
175       }
176       base::KillProcess(iter.GetData().handle, 0, true);
177       found = true;
178     }
179     ASSERT_TRUE(found) << "Didn't find Flash process!";
180     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
181   }
182
183   static void GetPluginsInfoCallback(
184       std::vector<content::WebPluginInfo>* rv,
185       const base::Closure& quit_task,
186       const std::vector<content::WebPluginInfo>& plugins) {
187     *rv = plugins;
188     quit_task.Run();
189   }
190
191   static void CountPluginProcesses(int* count, const base::Closure& quit_task) {
192     for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
193       if (iter.GetData().process_type == content::PROCESS_TYPE_PLUGIN ||
194           iter.GetData().process_type == content::PROCESS_TYPE_PPAPI_PLUGIN) {
195         (*count)++;
196       }
197     }
198     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
199   }
200 };
201
202 // Tests a bunch of basic scenarios with Flash.
203 // This test fails under ASan on Mac, see http://crbug.com/147004.
204 // It fails elsewhere, too.  See http://crbug.com/152071.
205 IN_PROC_BROWSER_TEST_F(ChromePluginTest, DISABLED_Flash) {
206   // Official builds always have bundled Flash.
207 #if !defined(OFFICIAL_BUILD)
208   std::vector<base::FilePath> flash_paths;
209   GetFlashPath(&flash_paths);
210   if (flash_paths.empty()) {
211     LOG(INFO) << "Test not running because couldn't find Flash.";
212     return;
213   }
214 #endif
215
216   GURL url = GetURL("flash.html");
217   EnsureFlashProcessCount(0);
218
219   // Try a single tab.
220   ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
221   EnsureFlashProcessCount(1);
222   Profile* profile = browser()->profile();
223   // Try another tab.
224   ASSERT_NO_FATAL_FAILURE(LoadAndWait(CreateBrowser(profile), url, true));
225   // Try an incognito window.
226   ASSERT_NO_FATAL_FAILURE(LoadAndWait(CreateIncognitoBrowser(), url, true));
227   EnsureFlashProcessCount(1);
228
229   // Now kill Flash process and verify it reloads.
230   CrashFlash();
231   EnsureFlashProcessCount(0);
232
233   ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
234   EnsureFlashProcessCount(1);
235
236   // Now try disabling it.
237   EnableFlash(false, profile);
238   CrashFlash();
239
240   ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, false));
241   EnsureFlashProcessCount(0);
242
243   // Now enable it again.
244   EnableFlash(true, profile);
245   ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
246   EnsureFlashProcessCount(1);
247 }
248
249 // Verify that the official builds have the known set of plugins.
250 IN_PROC_BROWSER_TEST_F(ChromePluginTest, InstalledPlugins) {
251 #if !defined(OFFICIAL_BUILD)
252   return;
253 #endif
254   const char* expected[] = {
255     "Chrome PDF Viewer",
256     "Shockwave Flash",
257     "Native Client",
258     "Chrome Remote Desktop Viewer",
259 #if defined(OS_CHROMEOS)
260     "Google Talk Plugin",
261     "Google Talk Plugin Video Accelerator",
262     "Netflix",
263 #endif
264   };
265
266   std::vector<content::WebPluginInfo> plugins = GetPlugins();
267   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(expected); ++i) {
268     size_t j = 0;
269     for (; j < plugins.size(); ++j) {
270       if (plugins[j].name == base::ASCIIToUTF16(expected[i]))
271         break;
272     }
273     ASSERT_TRUE(j != plugins.size()) << "Didn't find " << expected[i];
274   }
275 }
276
277 #if defined(OS_WIN)
278
279 namespace {
280
281 BOOL CALLBACK EnumerateChildren(HWND hwnd, LPARAM l_param) {
282   HWND* child = reinterpret_cast<HWND*>(l_param);
283   *child = hwnd;
284   // The first child window is the plugin, then its children. So stop
285   // enumerating after the first callback.
286   return FALSE;
287 }
288
289 }
290
291 // Test that if a background tab loads an NPAPI plugin, they are displayed after
292 // switching to that page.  http://crbug.com/335900
293 IN_PROC_BROWSER_TEST_F(ChromePluginTest, WindowedNPAPIPluginHidden) {
294   browser()->profile()->GetPrefs()->SetBoolean(prefs::kPluginsAlwaysAuthorize,
295                                                true);
296
297   // First load the page in the background and wait for the NPAPI plugin's
298   // window to be created.
299   GURL url = ui_test_utils::GetTestUrl(
300       base::FilePath(),
301       base::FilePath().AppendASCII("windowed_npapi_plugin.html"));
302
303   ui_test_utils::NavigateToURLWithDisposition(
304       browser(), url, NEW_BACKGROUND_TAB,
305       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
306
307   // We create a third window just to trigger the second one to update its
308   // constrained window list. Normally this would be triggered by the status bar
309   // animation closing after the user middle clicked a link.
310   ui_test_utils::NavigateToURLWithDisposition(
311       browser(), GURL("about:blank"), NEW_BACKGROUND_TAB,
312       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
313
314   base::string16 expected_title(base::ASCIIToUTF16("created"));
315   content::WebContents* tab =
316       browser()->tab_strip_model()->GetWebContentsAt(1);
317   if (tab->GetTitle() != expected_title) {
318     content::TitleWatcher title_watcher(tab, expected_title);
319     EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
320   }
321
322   // Now activate the tab and verify that the plugin painted.
323   browser()->tab_strip_model()->ActivateTabAt(1, true);
324
325   base::string16 expected_title2(base::ASCIIToUTF16("shown"));
326   content::TitleWatcher title_watcher2(tab, expected_title2);
327   EXPECT_EQ(expected_title2, title_watcher2.WaitAndGetTitle());
328
329   HWND child = NULL;
330   HWND hwnd = tab->GetView()->GetNativeView()->GetDispatcher()->host()->
331       GetAcceleratedWidget();
332   EnumChildWindows(hwnd, EnumerateChildren,reinterpret_cast<LPARAM>(&child));
333
334   RECT region;
335   int result = GetWindowRgnBox(child, &region);
336   ASSERT_NE(result, NULLREGION);
337 }
338
339 #endif