blob: 92c8364ee383d53e7489a9a9c186af6da1a6edef [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"
rvargasf8d789c2015-04-01 04:10:1214#include "base/process/process.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]677d0942012-08-28 17:42:1120#include "chrome/test/base/in_process_browser_test.h"
21#include "chrome/test/base/ui_test_utils.h"
[email protected]677d0942012-08-28 17:42:1122#include "content/public/browser/browser_child_process_host_iterator.h"
[email protected]135cb802013-06-09 16:44:2023#include "content/public/browser/browser_thread.h"
[email protected]677d0942012-08-28 17:42:1124#include "content/public/browser/child_process_data.h"
25#include "content/public/browser/plugin_service.h"
[email protected]1f870d52014-01-30 07:51:1826#include "content/public/browser/web_contents.h"
[email protected]73270292013-08-09 03:48:0727#include "content/public/common/content_constants.h"
[email protected]677d0942012-08-28 17:42:1128#include "content/public/common/content_paths.h"
[email protected]d5d383252013-07-04 14:44:3229#include "content/public/common/process_type.h"
[email protected]d7bd3e52013-07-21 04:29:2030#include "content/public/common/webplugininfo.h"
[email protected]677d0942012-08-28 17:42:1131#include "content/public/test/browser_test_utils.h"
32#include "content/public/test/test_utils.h"
[email protected]d96cf752014-04-09 04:05:2833#include "net/base/filename_util.h"
[email protected]677d0942012-08-28 17:42:1134
[email protected]1f870d52014-01-30 07:51:1835#if defined(OS_WIN)
[email protected]1f870d52014-01-30 07:51:1836#include "ui/aura/window.h"
[email protected]7a60cd3a2014-03-20 20:54:5737#include "ui/aura/window_tree_host.h"
[email protected]1f870d52014-01-30 07:51:1838#endif
39
[email protected]677d0942012-08-28 17:42:1140using content::BrowserThread;
41
[email protected]b6026282012-10-01 23:07:0542namespace {
43
44class CallbackBarrier : public base::RefCountedThreadSafe<CallbackBarrier> {
45 public:
46 explicit CallbackBarrier(const base::Closure& target_callback)
47 : target_callback_(target_callback),
48 outstanding_callbacks_(0),
49 did_enable_(true) {
50 }
51
52 base::Callback<void(bool)> CreateCallback() {
53 outstanding_callbacks_++;
54 return base::Bind(&CallbackBarrier::MayRunTargetCallback, this);
55 }
56
57 private:
58 friend class base::RefCountedThreadSafe<CallbackBarrier>;
59
60 ~CallbackBarrier() {
61 EXPECT_TRUE(target_callback_.is_null());
62 }
63
64 void MayRunTargetCallback(bool did_enable) {
65 EXPECT_GT(outstanding_callbacks_, 0);
66 did_enable_ = did_enable_ && did_enable;
67 if (--outstanding_callbacks_ == 0) {
68 EXPECT_TRUE(did_enable_);
69 target_callback_.Run();
70 target_callback_.Reset();
71 }
72 }
73
74 base::Closure target_callback_;
75 int outstanding_callbacks_;
76 bool did_enable_;
77};
78
79} // namespace
80
[email protected]677d0942012-08-28 17:42:1181class ChromePluginTest : public InProcessBrowserTest {
82 protected:
83 ChromePluginTest() {}
84
[email protected]3bbe942e2012-08-28 23:15:3585 static GURL GetURL(const char* filename) {
[email protected]650b2d52013-02-10 03:41:4586 base::FilePath path;
[email protected]3bbe942e2012-08-28 23:15:3587 PathService::Get(content::DIR_TEST_DATA, &path);
88 path = path.AppendASCII("plugin").AppendASCII(filename);
[email protected]7567484142013-07-11 17:36:0789 CHECK(base::PathExists(path));
[email protected]3bbe942e2012-08-28 23:15:3590 return net::FilePathToFileURL(path);
91 }
92
[email protected]677d0942012-08-28 17:42:1193 static void LoadAndWait(Browser* window, const GURL& url, bool pass) {
[email protected]da2bfa42013-01-29 23:47:0594 content::WebContents* web_contents =
95 window->tab_strip_model()->GetActiveWebContents();
[email protected]cc2a2a22013-12-24 23:12:1596 base::string16 expected_title(
97 base::ASCIIToUTF16(pass ? "OK" : "plugin_not_found"));
[email protected]677d0942012-08-28 17:42:1198 content::TitleWatcher title_watcher(web_contents, expected_title);
[email protected]cc2a2a22013-12-24 23:12:1599 title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL"));
100 title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16(
[email protected]677d0942012-08-28 17:42:11101 pass ? "plugin_not_found" : "OK"));
102 ui_test_utils::NavigateToURL(window, url);
103 ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
104 }
105
106 static void CrashFlash() {
107 scoped_refptr<content::MessageLoopRunner> runner =
108 new content::MessageLoopRunner;
109 BrowserThread::PostTask(
110 BrowserThread::IO,
111 FROM_HERE,
112 base::Bind(&CrashFlashInternal, runner->QuitClosure()));
113 runner->Run();
114 }
115
[email protected]650b2d52013-02-10 03:41:45116 static void GetFlashPath(std::vector<base::FilePath>* paths) {
[email protected]b6026282012-10-01 23:07:05117 paths->clear();
[email protected]d7bd3e52013-07-21 04:29:20118 std::vector<content::WebPluginInfo> plugins = GetPlugins();
119 for (std::vector<content::WebPluginInfo>::const_iterator it =
[email protected]b6026282012-10-01 23:07:05120 plugins.begin(); it != plugins.end(); ++it) {
[email protected]cc2a2a22013-12-24 23:12:15121 if (it->name == base::ASCIIToUTF16(content::kFlashPluginName))
[email protected]b6026282012-10-01 23:07:05122 paths->push_back(it->path);
[email protected]43075012012-08-29 05:42:49123 }
[email protected]43075012012-08-29 05:42:49124 }
125
[email protected]d7bd3e52013-07-21 04:29:20126 static std::vector<content::WebPluginInfo> GetPlugins() {
127 std::vector<content::WebPluginInfo> plugins;
[email protected]677d0942012-08-28 17:42:11128 scoped_refptr<content::MessageLoopRunner> runner =
129 new content::MessageLoopRunner;
130 content::PluginService::GetInstance()->GetPlugins(
[email protected]43075012012-08-29 05:42:49131 base::Bind(&GetPluginsInfoCallback, &plugins, runner->QuitClosure()));
[email protected]677d0942012-08-28 17:42:11132 runner->Run();
[email protected]43075012012-08-29 05:42:49133 return plugins;
[email protected]677d0942012-08-28 17:42:11134 }
135
[email protected]3bbe942e2012-08-28 23:15:35136 static void EnableFlash(bool enable, Profile* profile) {
[email protected]650b2d52013-02-10 03:41:45137 std::vector<base::FilePath> paths;
[email protected]b6026282012-10-01 23:07:05138 GetFlashPath(&paths);
139 ASSERT_FALSE(paths.empty());
[email protected]677d0942012-08-28 17:42:11140
[email protected]cadac622013-06-11 16:46:36141 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile).get();
[email protected]677d0942012-08-28 17:42:11142 scoped_refptr<content::MessageLoopRunner> runner =
143 new content::MessageLoopRunner;
[email protected]b6026282012-10-01 23:07:05144 scoped_refptr<CallbackBarrier> callback_barrier(
145 new CallbackBarrier(runner->QuitClosure()));
[email protected]650b2d52013-02-10 03:41:45146 for (std::vector<base::FilePath>::iterator iter = paths.begin();
[email protected]b6026282012-10-01 23:07:05147 iter != paths.end(); ++iter) {
148 plugin_prefs->EnablePlugin(enable, *iter,
149 callback_barrier->CreateCallback());
150 }
[email protected]677d0942012-08-28 17:42:11151 runner->Run();
152 }
153
154 static void EnsureFlashProcessCount(int expected) {
155 int actual = 0;
156 scoped_refptr<content::MessageLoopRunner> runner =
157 new content::MessageLoopRunner;
158 BrowserThread::PostTask(
159 BrowserThread::IO,
160 FROM_HERE,
161 base::Bind(&CountPluginProcesses, &actual, runner->QuitClosure()));
162 runner->Run();
163 ASSERT_EQ(expected, actual);
164 }
165
166 private:
167 static void CrashFlashInternal(const base::Closure& quit_task) {
168 bool found = false;
169 for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]f3b357692013-03-22 05:16:13170 if (iter.GetData().process_type != content::PROCESS_TYPE_PLUGIN &&
171 iter.GetData().process_type != content::PROCESS_TYPE_PPAPI_PLUGIN) {
[email protected]677d0942012-08-28 17:42:11172 continue;
173 }
rvargasf8d789c2015-04-01 04:10:12174 base::Process process = base::Process::DeprecatedGetProcessFromHandle(
175 iter.GetData().handle);
176 process.Terminate(0, true);
[email protected]677d0942012-08-28 17:42:11177 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(
[email protected]d7bd3e52013-07-21 04:29:20184 std::vector<content::WebPluginInfo>* rv,
[email protected]677d0942012-08-28 17:42:11185 const base::Closure& quit_task,
[email protected]d7bd3e52013-07-21 04:29:20186 const std::vector<content::WebPluginInfo>& plugins) {
[email protected]43075012012-08-29 05:42:49187 *rv = plugins;
[email protected]677d0942012-08-28 17:42:11188 quit_task.Run();
189 }
190
191 static void CountPluginProcesses(int* count, const base::Closure& quit_task) {
192 for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]f3b357692013-03-22 05:16:13193 if (iter.GetData().process_type == content::PROCESS_TYPE_PLUGIN ||
194 iter.GetData().process_type == content::PROCESS_TYPE_PPAPI_PLUGIN) {
[email protected]677d0942012-08-28 17:42:11195 (*count)++;
196 }
197 }
198 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
199 }
200};
201
202// Tests a bunch of basic scenarios with Flash.
[email protected]407cc4812012-09-20 14:39:30203// This test fails under ASan on Mac, see http://crbug.com/147004.
[email protected]a62ca0a2012-10-04 18:51:38204// It fails elsewhere, too. See http://crbug.com/152071.
[email protected]4eef2892012-10-30 00:18:00205IN_PROC_BROWSER_TEST_F(ChromePluginTest, DISABLED_Flash) {
[email protected]677d0942012-08-28 17:42:11206 // Official builds always have bundled Flash.
207#if !defined(OFFICIAL_BUILD)
[email protected]650b2d52013-02-10 03:41:45208 std::vector<base::FilePath> flash_paths;
[email protected]b6026282012-10-01 23:07:05209 GetFlashPath(&flash_paths);
210 if (flash_paths.empty()) {
[email protected]677d0942012-08-28 17:42:11211 LOG(INFO) << "Test not running because couldn't find Flash.";
212 return;
213 }
214#endif
215
[email protected]3bbe942e2012-08-28 23:15:35216 GURL url = GetURL("flash.html");
[email protected]677d0942012-08-28 17:42:11217 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.
[email protected]3bbe942e2012-08-28 23:15:35237 EnableFlash(false, profile);
[email protected]677d0942012-08-28 17:42:11238 CrashFlash();
239
240 ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, false));
241 EnsureFlashProcessCount(0);
[email protected]3bbe942e2012-08-28 23:15:35242
243 // Now enable it again.
244 EnableFlash(true, profile);
245 ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
246 EnsureFlashProcessCount(1);
[email protected]677d0942012-08-28 17:42:11247}
[email protected]43075012012-08-29 05:42:49248
[email protected]b946b422014-03-18 22:53:40249#if defined(OFFICIAL_BUILD)
[email protected]43075012012-08-29 05:42:49250// Verify that the official builds have the known set of plugins.
251IN_PROC_BROWSER_TEST_F(ChromePluginTest, InstalledPlugins) {
[email protected]43075012012-08-29 05:42:49252 const char* expected[] = {
253 "Chrome PDF Viewer",
254 "Shockwave Flash",
255 "Native Client",
[email protected]43075012012-08-29 05:42:49256 };
257
[email protected]d7bd3e52013-07-21 04:29:20258 std::vector<content::WebPluginInfo> plugins = GetPlugins();
viettrungluu9e65ad12014-10-16 04:22:26259 for (size_t i = 0; i < arraysize(expected); ++i) {
[email protected]43075012012-08-29 05:42:49260 size_t j = 0;
261 for (; j < plugins.size(); ++j) {
[email protected]cc2a2a22013-12-24 23:12:15262 if (plugins[j].name == base::ASCIIToUTF16(expected[i]))
[email protected]43075012012-08-29 05:42:49263 break;
264 }
265 ASSERT_TRUE(j != plugins.size()) << "Didn't find " << expected[i];
266 }
267}
[email protected]b946b422014-03-18 22:53:40268#endif