blob: 9ab74a69acd624f3a1749733e739bb94a708ff09 [file] [log] [blame]
[email protected]677d0942012-08-28 17:42:111// 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
[email protected]b6026282012-10-01 23:07:055#include <vector>
6
7#include "base/bind.h"
8#include "base/callback.h"
[email protected]677d0942012-08-28 17:42:119#include "base/command_line.h"
thestig18dfb7a52014-08-26 10:44:0410#include "base/files/file_util.h"
[email protected]b6026282012-10-01 23:07:0511#include "base/memory/ref_counted.h"
[email protected]677d0942012-08-28 17:42:1112#include "base/path_service.h"
[email protected]1f870d52014-01-30 07:51:1813#include "base/prefs/pref_service.h"
[email protected]d09a4ce1c2013-07-24 17:37:0214#include "base/process/kill.h"
[email protected]135cb802013-06-09 16:44:2015#include "base/strings/utf_string_conversions.h"
[email protected]0f5e57f52012-09-20 20:53:1816#include "chrome/browser/plugins/plugin_prefs.h"
[email protected]1f870d52014-01-30 07:51:1817#include "chrome/browser/profiles/profile.h"
[email protected]677d0942012-08-28 17:42:1118#include "chrome/browser/ui/browser.h"
[email protected]da2bfa42013-01-29 23:47:0519#include "chrome/browser/ui/tabs/tab_strip_model.h"
[email protected]1f870d52014-01-30 07:51:1820#include "chrome/common/pref_names.h"
[email protected]677d0942012-08-28 17:42:1121#include "chrome/test/base/in_process_browser_test.h"
22#include "chrome/test/base/ui_test_utils.h"
[email protected]677d0942012-08-28 17:42:1123#include "content/public/browser/browser_child_process_host_iterator.h"
[email protected]135cb802013-06-09 16:44:2024#include "content/public/browser/browser_thread.h"
[email protected]677d0942012-08-28 17:42:1125#include "content/public/browser/child_process_data.h"
26#include "content/public/browser/plugin_service.h"
[email protected]1f870d52014-01-30 07:51:1827#include "content/public/browser/web_contents.h"
[email protected]73270292013-08-09 03:48:0728#include "content/public/common/content_constants.h"
[email protected]677d0942012-08-28 17:42:1129#include "content/public/common/content_paths.h"
[email protected]d5d383252013-07-04 14:44:3230#include "content/public/common/process_type.h"
[email protected]d7bd3e52013-07-21 04:29:2031#include "content/public/common/webplugininfo.h"
[email protected]677d0942012-08-28 17:42:1132#include "content/public/test/browser_test_utils.h"
33#include "content/public/test/test_utils.h"
[email protected]d96cf752014-04-09 04:05:2834#include "net/base/filename_util.h"
[email protected]677d0942012-08-28 17:42:1135
[email protected]1f870d52014-01-30 07:51:1836#if defined(OS_WIN)
[email protected]1f870d52014-01-30 07:51:1837#include "ui/aura/window.h"
[email protected]7a60cd3a2014-03-20 20:54:5738#include "ui/aura/window_tree_host.h"
[email protected]1f870d52014-01-30 07:51:1839#endif
40
[email protected]677d0942012-08-28 17:42:1141using content::BrowserThread;
42
[email protected]b6026282012-10-01 23:07:0543namespace {
44
45class CallbackBarrier : public base::RefCountedThreadSafe<CallbackBarrier> {
46 public:
47 explicit CallbackBarrier(const base::Closure& target_callback)
48 : target_callback_(target_callback),
49 outstanding_callbacks_(0),
50 did_enable_(true) {
51 }
52
53 base::Callback<void(bool)> CreateCallback() {
54 outstanding_callbacks_++;
55 return base::Bind(&CallbackBarrier::MayRunTargetCallback, this);
56 }
57
58 private:
59 friend class base::RefCountedThreadSafe<CallbackBarrier>;
60
61 ~CallbackBarrier() {
62 EXPECT_TRUE(target_callback_.is_null());
63 }
64
65 void MayRunTargetCallback(bool did_enable) {
66 EXPECT_GT(outstanding_callbacks_, 0);
67 did_enable_ = did_enable_ && did_enable;
68 if (--outstanding_callbacks_ == 0) {
69 EXPECT_TRUE(did_enable_);
70 target_callback_.Run();
71 target_callback_.Reset();
72 }
73 }
74
75 base::Closure target_callback_;
76 int outstanding_callbacks_;
77 bool did_enable_;
78};
79
80} // namespace
81
[email protected]677d0942012-08-28 17:42:1182class ChromePluginTest : public InProcessBrowserTest {
83 protected:
84 ChromePluginTest() {}
85
[email protected]3bbe942e2012-08-28 23:15:3586 static GURL GetURL(const char* filename) {
[email protected]650b2d52013-02-10 03:41:4587 base::FilePath path;
[email protected]3bbe942e2012-08-28 23:15:3588 PathService::Get(content::DIR_TEST_DATA, &path);
89 path = path.AppendASCII("plugin").AppendASCII(filename);
[email protected]7567484142013-07-11 17:36:0790 CHECK(base::PathExists(path));
[email protected]3bbe942e2012-08-28 23:15:3591 return net::FilePathToFileURL(path);
92 }
93
[email protected]677d0942012-08-28 17:42:1194 static void LoadAndWait(Browser* window, const GURL& url, bool pass) {
[email protected]da2bfa42013-01-29 23:47:0595 content::WebContents* web_contents =
96 window->tab_strip_model()->GetActiveWebContents();
[email protected]cc2a2a22013-12-24 23:12:1597 base::string16 expected_title(
98 base::ASCIIToUTF16(pass ? "OK" : "plugin_not_found"));
[email protected]677d0942012-08-28 17:42:1199 content::TitleWatcher title_watcher(web_contents, expected_title);
[email protected]cc2a2a22013-12-24 23:12:15100 title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL"));
101 title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16(
[email protected]677d0942012-08-28 17:42:11102 pass ? "plugin_not_found" : "OK"));
103 ui_test_utils::NavigateToURL(window, url);
104 ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
105 }
106
107 static void CrashFlash() {
108 scoped_refptr<content::MessageLoopRunner> runner =
109 new content::MessageLoopRunner;
110 BrowserThread::PostTask(
111 BrowserThread::IO,
112 FROM_HERE,
113 base::Bind(&CrashFlashInternal, runner->QuitClosure()));
114 runner->Run();
115 }
116
[email protected]650b2d52013-02-10 03:41:45117 static void GetFlashPath(std::vector<base::FilePath>* paths) {
[email protected]b6026282012-10-01 23:07:05118 paths->clear();
[email protected]d7bd3e52013-07-21 04:29:20119 std::vector<content::WebPluginInfo> plugins = GetPlugins();
120 for (std::vector<content::WebPluginInfo>::const_iterator it =
[email protected]b6026282012-10-01 23:07:05121 plugins.begin(); it != plugins.end(); ++it) {
[email protected]cc2a2a22013-12-24 23:12:15122 if (it->name == base::ASCIIToUTF16(content::kFlashPluginName))
[email protected]b6026282012-10-01 23:07:05123 paths->push_back(it->path);
[email protected]43075012012-08-29 05:42:49124 }
[email protected]43075012012-08-29 05:42:49125 }
126
[email protected]d7bd3e52013-07-21 04:29:20127 static std::vector<content::WebPluginInfo> GetPlugins() {
128 std::vector<content::WebPluginInfo> plugins;
[email protected]677d0942012-08-28 17:42:11129 scoped_refptr<content::MessageLoopRunner> runner =
130 new content::MessageLoopRunner;
131 content::PluginService::GetInstance()->GetPlugins(
[email protected]43075012012-08-29 05:42:49132 base::Bind(&GetPluginsInfoCallback, &plugins, runner->QuitClosure()));
[email protected]677d0942012-08-28 17:42:11133 runner->Run();
[email protected]43075012012-08-29 05:42:49134 return plugins;
[email protected]677d0942012-08-28 17:42:11135 }
136
[email protected]3bbe942e2012-08-28 23:15:35137 static void EnableFlash(bool enable, Profile* profile) {
[email protected]650b2d52013-02-10 03:41:45138 std::vector<base::FilePath> paths;
[email protected]b6026282012-10-01 23:07:05139 GetFlashPath(&paths);
140 ASSERT_FALSE(paths.empty());
[email protected]677d0942012-08-28 17:42:11141
[email protected]cadac622013-06-11 16:46:36142 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile).get();
[email protected]677d0942012-08-28 17:42:11143 scoped_refptr<content::MessageLoopRunner> runner =
144 new content::MessageLoopRunner;
[email protected]b6026282012-10-01 23:07:05145 scoped_refptr<CallbackBarrier> callback_barrier(
146 new CallbackBarrier(runner->QuitClosure()));
[email protected]650b2d52013-02-10 03:41:45147 for (std::vector<base::FilePath>::iterator iter = paths.begin();
[email protected]b6026282012-10-01 23:07:05148 iter != paths.end(); ++iter) {
149 plugin_prefs->EnablePlugin(enable, *iter,
150 callback_barrier->CreateCallback());
151 }
[email protected]677d0942012-08-28 17:42:11152 runner->Run();
153 }
154
155 static void EnsureFlashProcessCount(int expected) {
156 int actual = 0;
157 scoped_refptr<content::MessageLoopRunner> runner =
158 new content::MessageLoopRunner;
159 BrowserThread::PostTask(
160 BrowserThread::IO,
161 FROM_HERE,
162 base::Bind(&CountPluginProcesses, &actual, runner->QuitClosure()));
163 runner->Run();
164 ASSERT_EQ(expected, actual);
165 }
166
167 private:
168 static void CrashFlashInternal(const base::Closure& quit_task) {
169 bool found = false;
170 for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]f3b357692013-03-22 05:16:13171 if (iter.GetData().process_type != content::PROCESS_TYPE_PLUGIN &&
172 iter.GetData().process_type != content::PROCESS_TYPE_PPAPI_PLUGIN) {
[email protected]677d0942012-08-28 17:42:11173 continue;
174 }
175 base::KillProcess(iter.GetData().handle, 0, true);
176 found = true;
177 }
178 ASSERT_TRUE(found) << "Didn't find Flash process!";
179 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
180 }
181
182 static void GetPluginsInfoCallback(
[email protected]d7bd3e52013-07-21 04:29:20183 std::vector<content::WebPluginInfo>* rv,
[email protected]677d0942012-08-28 17:42:11184 const base::Closure& quit_task,
[email protected]d7bd3e52013-07-21 04:29:20185 const std::vector<content::WebPluginInfo>& plugins) {
[email protected]43075012012-08-29 05:42:49186 *rv = plugins;
[email protected]677d0942012-08-28 17:42:11187 quit_task.Run();
188 }
189
190 static void CountPluginProcesses(int* count, const base::Closure& quit_task) {
191 for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]f3b357692013-03-22 05:16:13192 if (iter.GetData().process_type == content::PROCESS_TYPE_PLUGIN ||
193 iter.GetData().process_type == content::PROCESS_TYPE_PPAPI_PLUGIN) {
[email protected]677d0942012-08-28 17:42:11194 (*count)++;
195 }
196 }
197 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
198 }
199};
200
201// Tests a bunch of basic scenarios with Flash.
[email protected]407cc4812012-09-20 14:39:30202// This test fails under ASan on Mac, see http://crbug.com/147004.
[email protected]a62ca0a2012-10-04 18:51:38203// It fails elsewhere, too. See http://crbug.com/152071.
[email protected]4eef2892012-10-30 00:18:00204IN_PROC_BROWSER_TEST_F(ChromePluginTest, DISABLED_Flash) {
[email protected]677d0942012-08-28 17:42:11205 // Official builds always have bundled Flash.
206#if !defined(OFFICIAL_BUILD)
[email protected]650b2d52013-02-10 03:41:45207 std::vector<base::FilePath> flash_paths;
[email protected]b6026282012-10-01 23:07:05208 GetFlashPath(&flash_paths);
209 if (flash_paths.empty()) {
[email protected]677d0942012-08-28 17:42:11210 LOG(INFO) << "Test not running because couldn't find Flash.";
211 return;
212 }
213#endif
214
[email protected]3bbe942e2012-08-28 23:15:35215 GURL url = GetURL("flash.html");
[email protected]677d0942012-08-28 17:42:11216 EnsureFlashProcessCount(0);
217
218 // Try a single tab.
219 ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
220 EnsureFlashProcessCount(1);
221 Profile* profile = browser()->profile();
222 // Try another tab.
223 ASSERT_NO_FATAL_FAILURE(LoadAndWait(CreateBrowser(profile), url, true));
224 // Try an incognito window.
225 ASSERT_NO_FATAL_FAILURE(LoadAndWait(CreateIncognitoBrowser(), url, true));
226 EnsureFlashProcessCount(1);
227
228 // Now kill Flash process and verify it reloads.
229 CrashFlash();
230 EnsureFlashProcessCount(0);
231
232 ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
233 EnsureFlashProcessCount(1);
234
235 // Now try disabling it.
[email protected]3bbe942e2012-08-28 23:15:35236 EnableFlash(false, profile);
[email protected]677d0942012-08-28 17:42:11237 CrashFlash();
238
239 ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, false));
240 EnsureFlashProcessCount(0);
[email protected]3bbe942e2012-08-28 23:15:35241
242 // Now enable it again.
243 EnableFlash(true, profile);
244 ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
245 EnsureFlashProcessCount(1);
[email protected]677d0942012-08-28 17:42:11246}
[email protected]43075012012-08-29 05:42:49247
[email protected]b946b422014-03-18 22:53:40248#if defined(OFFICIAL_BUILD)
[email protected]43075012012-08-29 05:42:49249// Verify that the official builds have the known set of plugins.
250IN_PROC_BROWSER_TEST_F(ChromePluginTest, InstalledPlugins) {
[email protected]43075012012-08-29 05:42:49251 const char* expected[] = {
252 "Chrome PDF Viewer",
253 "Shockwave Flash",
254 "Native Client",
[email protected]43075012012-08-29 05:42:49255 "Chrome Remote Desktop Viewer",
[email protected]ecaebf62012-09-25 00:07:52256#if defined(OS_CHROMEOS)
[email protected]43075012012-08-29 05:42:49257 "Google Talk Plugin",
258 "Google Talk Plugin Video Accelerator",
259 "Netflix",
260#endif
261 };
262
[email protected]d7bd3e52013-07-21 04:29:20263 std::vector<content::WebPluginInfo> plugins = GetPlugins();
[email protected]43075012012-08-29 05:42:49264 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(expected); ++i) {
265 size_t j = 0;
266 for (; j < plugins.size(); ++j) {
[email protected]cc2a2a22013-12-24 23:12:15267 if (plugins[j].name == base::ASCIIToUTF16(expected[i]))
[email protected]43075012012-08-29 05:42:49268 break;
269 }
270 ASSERT_TRUE(j != plugins.size()) << "Didn't find " << expected[i];
271 }
272}
[email protected]b946b422014-03-18 22:53:40273#endif