Upstream version 5.34.92.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/process/kill.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/plugins/plugin_prefs.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/browser_child_process_host_iterator.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/child_process_data.h"
23 #include "content/public/browser/plugin_service.h"
24 #include "content/public/common/content_constants.h"
25 #include "content/public/common/content_paths.h"
26 #include "content/public/common/process_type.h"
27 #include "content/public/common/webplugininfo.h"
28 #include "content/public/test/browser_test_utils.h"
29 #include "content/public/test/test_utils.h"
30 #include "net/base/net_util.h"
31
32 using content::BrowserThread;
33
34 namespace {
35
36 class CallbackBarrier : public base::RefCountedThreadSafe<CallbackBarrier> {
37  public:
38   explicit CallbackBarrier(const base::Closure& target_callback)
39       : target_callback_(target_callback),
40         outstanding_callbacks_(0),
41         did_enable_(true) {
42   }
43
44   base::Callback<void(bool)> CreateCallback() {
45     outstanding_callbacks_++;
46     return base::Bind(&CallbackBarrier::MayRunTargetCallback, this);
47   }
48
49  private:
50   friend class base::RefCountedThreadSafe<CallbackBarrier>;
51
52   ~CallbackBarrier() {
53     EXPECT_TRUE(target_callback_.is_null());
54   }
55
56   void MayRunTargetCallback(bool did_enable) {
57     EXPECT_GT(outstanding_callbacks_, 0);
58     did_enable_ = did_enable_ && did_enable;
59     if (--outstanding_callbacks_ == 0) {
60       EXPECT_TRUE(did_enable_);
61       target_callback_.Run();
62       target_callback_.Reset();
63     }
64   }
65
66   base::Closure target_callback_;
67   int outstanding_callbacks_;
68   bool did_enable_;
69 };
70
71 }  // namespace
72
73 class ChromePluginTest : public InProcessBrowserTest {
74  protected:
75   ChromePluginTest() {}
76
77   static GURL GetURL(const char* filename) {
78     base::FilePath path;
79     PathService::Get(content::DIR_TEST_DATA, &path);
80     path = path.AppendASCII("plugin").AppendASCII(filename);
81     CHECK(base::PathExists(path));
82     return net::FilePathToFileURL(path);
83   }
84
85   static void LoadAndWait(Browser* window, const GURL& url, bool pass) {
86     content::WebContents* web_contents =
87         window->tab_strip_model()->GetActiveWebContents();
88     base::string16 expected_title(
89         base::ASCIIToUTF16(pass ? "OK" : "plugin_not_found"));
90     content::TitleWatcher title_watcher(web_contents, expected_title);
91     title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL"));
92     title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16(
93         pass ? "plugin_not_found" : "OK"));
94     ui_test_utils::NavigateToURL(window, url);
95     ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
96   }
97
98   static void CrashFlash() {
99     scoped_refptr<content::MessageLoopRunner> runner =
100         new content::MessageLoopRunner;
101     BrowserThread::PostTask(
102         BrowserThread::IO,
103         FROM_HERE,
104         base::Bind(&CrashFlashInternal, runner->QuitClosure()));
105     runner->Run();
106   }
107
108   static void GetFlashPath(std::vector<base::FilePath>* paths) {
109     paths->clear();
110     std::vector<content::WebPluginInfo> plugins = GetPlugins();
111     for (std::vector<content::WebPluginInfo>::const_iterator it =
112              plugins.begin(); it != plugins.end(); ++it) {
113       if (it->name == base::ASCIIToUTF16(content::kFlashPluginName))
114         paths->push_back(it->path);
115     }
116   }
117
118   static std::vector<content::WebPluginInfo> GetPlugins() {
119     std::vector<content::WebPluginInfo> plugins;
120     scoped_refptr<content::MessageLoopRunner> runner =
121         new content::MessageLoopRunner;
122     content::PluginService::GetInstance()->GetPlugins(
123         base::Bind(&GetPluginsInfoCallback, &plugins, runner->QuitClosure()));
124     runner->Run();
125     return plugins;
126   }
127
128   static void EnableFlash(bool enable, Profile* profile) {
129     std::vector<base::FilePath> paths;
130     GetFlashPath(&paths);
131     ASSERT_FALSE(paths.empty());
132
133     PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile).get();
134     scoped_refptr<content::MessageLoopRunner> runner =
135         new content::MessageLoopRunner;
136     scoped_refptr<CallbackBarrier> callback_barrier(
137         new CallbackBarrier(runner->QuitClosure()));
138     for (std::vector<base::FilePath>::iterator iter = paths.begin();
139          iter != paths.end(); ++iter) {
140       plugin_prefs->EnablePlugin(enable, *iter,
141                                  callback_barrier->CreateCallback());
142     }
143     runner->Run();
144   }
145
146   static void EnsureFlashProcessCount(int expected) {
147     int actual = 0;
148     scoped_refptr<content::MessageLoopRunner> runner =
149         new content::MessageLoopRunner;
150     BrowserThread::PostTask(
151         BrowserThread::IO,
152         FROM_HERE,
153         base::Bind(&CountPluginProcesses, &actual, runner->QuitClosure()));
154     runner->Run();
155     ASSERT_EQ(expected, actual);
156   }
157
158  private:
159   static void CrashFlashInternal(const base::Closure& quit_task) {
160     bool found = false;
161     for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
162       if (iter.GetData().process_type != content::PROCESS_TYPE_PLUGIN &&
163           iter.GetData().process_type != content::PROCESS_TYPE_PPAPI_PLUGIN) {
164         continue;
165       }
166       base::KillProcess(iter.GetData().handle, 0, true);
167       found = true;
168     }
169     ASSERT_TRUE(found) << "Didn't find Flash process!";
170     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
171   }
172
173   static void GetPluginsInfoCallback(
174       std::vector<content::WebPluginInfo>* rv,
175       const base::Closure& quit_task,
176       const std::vector<content::WebPluginInfo>& plugins) {
177     *rv = plugins;
178     quit_task.Run();
179   }
180
181   static void CountPluginProcesses(int* count, const base::Closure& quit_task) {
182     for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
183       if (iter.GetData().process_type == content::PROCESS_TYPE_PLUGIN ||
184           iter.GetData().process_type == content::PROCESS_TYPE_PPAPI_PLUGIN) {
185         (*count)++;
186       }
187     }
188     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
189   }
190 };
191
192 // Tests a bunch of basic scenarios with Flash.
193 // This test fails under ASan on Mac, see http://crbug.com/147004.
194 // It fails elsewhere, too.  See http://crbug.com/152071.
195 IN_PROC_BROWSER_TEST_F(ChromePluginTest, DISABLED_Flash) {
196   // Official builds always have bundled Flash.
197 #if !defined(OFFICIAL_BUILD)
198   std::vector<base::FilePath> flash_paths;
199   GetFlashPath(&flash_paths);
200   if (flash_paths.empty()) {
201     LOG(INFO) << "Test not running because couldn't find Flash.";
202     return;
203   }
204 #endif
205
206   GURL url = GetURL("flash.html");
207   EnsureFlashProcessCount(0);
208
209   // Try a single tab.
210   ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
211   EnsureFlashProcessCount(1);
212   Profile* profile = browser()->profile();
213   // Try another tab.
214   ASSERT_NO_FATAL_FAILURE(LoadAndWait(CreateBrowser(profile), url, true));
215   // Try an incognito window.
216   ASSERT_NO_FATAL_FAILURE(LoadAndWait(CreateIncognitoBrowser(), url, true));
217   EnsureFlashProcessCount(1);
218
219   // Now kill Flash process and verify it reloads.
220   CrashFlash();
221   EnsureFlashProcessCount(0);
222
223   ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
224   EnsureFlashProcessCount(1);
225
226   // Now try disabling it.
227   EnableFlash(false, profile);
228   CrashFlash();
229
230   ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, false));
231   EnsureFlashProcessCount(0);
232
233   // Now enable it again.
234   EnableFlash(true, profile);
235   ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
236   EnsureFlashProcessCount(1);
237 }
238
239 // Verify that the official builds have the known set of plugins.
240 IN_PROC_BROWSER_TEST_F(ChromePluginTest, InstalledPlugins) {
241 #if !defined(OFFICIAL_BUILD)
242   return;
243 #endif
244   const char* expected[] = {
245     "Chrome PDF Viewer",
246     "Shockwave Flash",
247     "Native Client",
248     "Chrome Remote Desktop Viewer",
249 #if defined(OS_CHROMEOS)
250     "Google Talk Plugin",
251     "Google Talk Plugin Video Accelerator",
252     "Netflix",
253 #endif
254   };
255
256   std::vector<content::WebPluginInfo> plugins = GetPlugins();
257   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(expected); ++i) {
258     size_t j = 0;
259     for (; j < plugins.size(); ++j) {
260       if (plugins[j].name == base::ASCIIToUTF16(expected[i]))
261         break;
262     }
263     ASSERT_TRUE(j != plugins.size()) << "Didn't find " << expected[i];
264   }
265 }