Don't crash when SimpleCache index is corrupt.
[chromium-blink-merge.git] / chrome / browser / chrome_plugin_browsertest.cc
blobfd6af372db8a92acaa6246e4bc5b658c06951ab2
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.
5 #include <vector>
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_util.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/common/chrome_process_type.h"
19 #include "chrome/test/base/in_process_browser_test.h"
20 #include "chrome/test/base/ui_test_utils.h"
21 #include "content/public/browser/browser_child_process_host_iterator.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/common/content_paths.h"
26 #include "content/public/test/browser_test_utils.h"
27 #include "content/public/test/test_utils.h"
28 #include "net/base/net_util.h"
29 #include "webkit/plugins/plugin_constants.h"
30 #include "webkit/plugins/webplugininfo.h"
32 using content::BrowserThread;
34 namespace {
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) {
44 base::Callback<void(bool)> CreateCallback() {
45 outstanding_callbacks_++;
46 return base::Bind(&CallbackBarrier::MayRunTargetCallback, this);
49 private:
50 friend class base::RefCountedThreadSafe<CallbackBarrier>;
52 ~CallbackBarrier() {
53 EXPECT_TRUE(target_callback_.is_null());
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();
66 base::Closure target_callback_;
67 int outstanding_callbacks_;
68 bool did_enable_;
71 } // namespace
73 class ChromePluginTest : public InProcessBrowserTest {
74 protected:
75 ChromePluginTest() {}
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(file_util::PathExists(path));
82 return net::FilePathToFileURL(path);
85 static void LoadAndWait(Browser* window, const GURL& url, bool pass) {
86 content::WebContents* web_contents =
87 window->tab_strip_model()->GetActiveWebContents();
88 string16 expected_title(ASCIIToUTF16(pass ? "OK" : "plugin_not_found"));
89 content::TitleWatcher title_watcher(web_contents, expected_title);
90 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
91 title_watcher.AlsoWaitForTitle(ASCIIToUTF16(
92 pass ? "plugin_not_found" : "OK"));
93 ui_test_utils::NavigateToURL(window, url);
94 ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
97 static void CrashFlash() {
98 scoped_refptr<content::MessageLoopRunner> runner =
99 new content::MessageLoopRunner;
100 BrowserThread::PostTask(
101 BrowserThread::IO,
102 FROM_HERE,
103 base::Bind(&CrashFlashInternal, runner->QuitClosure()));
104 runner->Run();
107 static void GetFlashPath(std::vector<base::FilePath>* paths) {
108 paths->clear();
109 std::vector<webkit::WebPluginInfo> plugins = GetPlugins();
110 for (std::vector<webkit::WebPluginInfo>::const_iterator it =
111 plugins.begin(); it != plugins.end(); ++it) {
112 if (it->name == ASCIIToUTF16(kFlashPluginName))
113 paths->push_back(it->path);
117 static std::vector<webkit::WebPluginInfo> GetPlugins() {
118 std::vector<webkit::WebPluginInfo> plugins;
119 scoped_refptr<content::MessageLoopRunner> runner =
120 new content::MessageLoopRunner;
121 content::PluginService::GetInstance()->GetPlugins(
122 base::Bind(&GetPluginsInfoCallback, &plugins, runner->QuitClosure()));
123 runner->Run();
124 return plugins;
127 static void EnableFlash(bool enable, Profile* profile) {
128 std::vector<base::FilePath> paths;
129 GetFlashPath(&paths);
130 ASSERT_FALSE(paths.empty());
132 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile).get();
133 scoped_refptr<content::MessageLoopRunner> runner =
134 new content::MessageLoopRunner;
135 scoped_refptr<CallbackBarrier> callback_barrier(
136 new CallbackBarrier(runner->QuitClosure()));
137 for (std::vector<base::FilePath>::iterator iter = paths.begin();
138 iter != paths.end(); ++iter) {
139 plugin_prefs->EnablePlugin(enable, *iter,
140 callback_barrier->CreateCallback());
142 runner->Run();
145 static void EnsureFlashProcessCount(int expected) {
146 int actual = 0;
147 scoped_refptr<content::MessageLoopRunner> runner =
148 new content::MessageLoopRunner;
149 BrowserThread::PostTask(
150 BrowserThread::IO,
151 FROM_HERE,
152 base::Bind(&CountPluginProcesses, &actual, runner->QuitClosure()));
153 runner->Run();
154 ASSERT_EQ(expected, actual);
157 private:
158 static void CrashFlashInternal(const base::Closure& quit_task) {
159 bool found = false;
160 for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
161 if (iter.GetData().process_type != content::PROCESS_TYPE_PLUGIN &&
162 iter.GetData().process_type != content::PROCESS_TYPE_PPAPI_PLUGIN) {
163 continue;
165 base::KillProcess(iter.GetData().handle, 0, true);
166 found = true;
168 ASSERT_TRUE(found) << "Didn't find Flash process!";
169 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
172 static void GetPluginsInfoCallback(
173 std::vector<webkit::WebPluginInfo>* rv,
174 const base::Closure& quit_task,
175 const std::vector<webkit::WebPluginInfo>& plugins) {
176 *rv = plugins;
177 quit_task.Run();
180 static void CountPluginProcesses(int* count, const base::Closure& quit_task) {
181 for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
182 if (iter.GetData().process_type == content::PROCESS_TYPE_PLUGIN ||
183 iter.GetData().process_type == content::PROCESS_TYPE_PPAPI_PLUGIN) {
184 (*count)++;
187 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
191 // Tests a bunch of basic scenarios with Flash.
192 // This test fails under ASan on Mac, see http://crbug.com/147004.
193 // It fails elsewhere, too. See http://crbug.com/152071.
194 IN_PROC_BROWSER_TEST_F(ChromePluginTest, DISABLED_Flash) {
195 // Official builds always have bundled Flash.
196 #if !defined(OFFICIAL_BUILD)
197 std::vector<base::FilePath> flash_paths;
198 GetFlashPath(&flash_paths);
199 if (flash_paths.empty()) {
200 LOG(INFO) << "Test not running because couldn't find Flash.";
201 return;
203 #endif
205 GURL url = GetURL("flash.html");
206 EnsureFlashProcessCount(0);
208 // Try a single tab.
209 ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
210 EnsureFlashProcessCount(1);
211 Profile* profile = browser()->profile();
212 // Try another tab.
213 ASSERT_NO_FATAL_FAILURE(LoadAndWait(CreateBrowser(profile), url, true));
214 // Try an incognito window.
215 ASSERT_NO_FATAL_FAILURE(LoadAndWait(CreateIncognitoBrowser(), url, true));
216 EnsureFlashProcessCount(1);
218 // Now kill Flash process and verify it reloads.
219 CrashFlash();
220 EnsureFlashProcessCount(0);
222 ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
223 EnsureFlashProcessCount(1);
225 // Now try disabling it.
226 EnableFlash(false, profile);
227 CrashFlash();
229 ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, false));
230 EnsureFlashProcessCount(0);
232 // Now enable it again.
233 EnableFlash(true, profile);
234 ASSERT_NO_FATAL_FAILURE(LoadAndWait(browser(), url, true));
235 EnsureFlashProcessCount(1);
238 // Verify that the official builds have the known set of plugins.
239 IN_PROC_BROWSER_TEST_F(ChromePluginTest, InstalledPlugins) {
240 #if !defined(OFFICIAL_BUILD)
241 return;
242 #endif
243 const char* expected[] = {
244 "Chrome PDF Viewer",
245 "Shockwave Flash",
246 "Native Client",
247 "Chrome Remote Desktop Viewer",
248 #if defined(OS_CHROMEOS)
249 "Google Talk Plugin",
250 "Google Talk Plugin Video Accelerator",
251 "Netflix",
252 #endif
255 std::vector<webkit::WebPluginInfo> plugins = GetPlugins();
256 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(expected); ++i) {
257 size_t j = 0;
258 for (; j < plugins.size(); ++j) {
259 if (plugins[j].name == ASCIIToUTF16(expected[i]))
260 break;
262 ASSERT_TRUE(j != plugins.size()) << "Didn't find " << expected[i];