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 "content/browser/plugin_loader_posix.h"
7 #include "base/at_exit.h"
9 #include "base/files/file_path.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/message_loop.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/browser/browser_thread_impl.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "webkit/plugins/webplugininfo.h"
20 class MockPluginLoaderPosix
: public PluginLoaderPosix
{
22 MOCK_METHOD0(LoadPluginsInternal
, void(void));
24 size_t number_of_pending_callbacks() {
25 return callbacks_
.size();
28 std::vector
<base::FilePath
>* canonical_list() {
29 return &canonical_list_
;
32 size_t next_load_index() {
33 return next_load_index_
;
36 const std::vector
<webkit::WebPluginInfo
>& loaded_plugins() {
37 return loaded_plugins_
;
40 std::vector
<webkit::WebPluginInfo
>* internal_plugins() {
41 return &internal_plugins_
;
44 void RealLoadPluginsInternal() {
45 PluginLoaderPosix::LoadPluginsInternal();
48 void TestOnPluginLoaded(uint32 index
, const webkit::WebPluginInfo
& plugin
) {
49 OnPluginLoaded(index
, plugin
);
52 void TestOnPluginLoadFailed(uint32 index
, const base::FilePath
& path
) {
53 OnPluginLoadFailed(index
, path
);
57 virtual ~MockPluginLoaderPosix() {}
60 void VerifyCallback(int* run_count
, const std::vector
<webkit::WebPluginInfo
>&) {
64 class PluginLoaderPosixTest
: public testing::Test
{
66 PluginLoaderPosixTest()
67 : plugin1_(ASCIIToUTF16("plugin1"), base::FilePath("/tmp/one.plugin"),
68 ASCIIToUTF16("1.0"), string16()),
69 plugin2_(ASCIIToUTF16("plugin2"), base::FilePath("/tmp/two.plugin"),
70 ASCIIToUTF16("2.0"), string16()),
71 plugin3_(ASCIIToUTF16("plugin3"), base::FilePath("/tmp/three.plugin"),
72 ASCIIToUTF16("3.0"), string16()),
73 file_thread_(BrowserThread::FILE, &message_loop_
),
74 io_thread_(BrowserThread::IO
, &message_loop_
),
75 plugin_loader_(new MockPluginLoaderPosix
) {
78 virtual void SetUp() OVERRIDE
{
79 PluginServiceImpl::GetInstance()->Init();
82 base::MessageLoop
* message_loop() { return &message_loop_
; }
83 MockPluginLoaderPosix
* plugin_loader() { return plugin_loader_
.get(); }
85 void AddThreePlugins() {
86 plugin_loader_
->canonical_list()->clear();
87 plugin_loader_
->canonical_list()->push_back(plugin1_
.path
);
88 plugin_loader_
->canonical_list()->push_back(plugin2_
.path
);
89 plugin_loader_
->canonical_list()->push_back(plugin3_
.path
);
92 // Data used for testing.
93 webkit::WebPluginInfo plugin1_
;
94 webkit::WebPluginInfo plugin2_
;
95 webkit::WebPluginInfo plugin3_
;
98 base::ShadowingAtExitManager at_exit_manager_
; // Destroys PluginService.
100 base::MessageLoopForIO message_loop_
;
101 BrowserThreadImpl file_thread_
;
102 BrowserThreadImpl io_thread_
;
104 scoped_refptr
<MockPluginLoaderPosix
> plugin_loader_
;
107 TEST_F(PluginLoaderPosixTest
, QueueRequests
) {
108 int did_callback
= 0;
109 PluginService::GetPluginsCallback callback
=
110 base::Bind(&VerifyCallback
, base::Unretained(&did_callback
));
112 EXPECT_EQ(0u, plugin_loader()->number_of_pending_callbacks());
113 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback
);
114 EXPECT_EQ(1u, plugin_loader()->number_of_pending_callbacks());
116 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback
);
117 EXPECT_EQ(2u, plugin_loader()->number_of_pending_callbacks());
119 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(2);
120 message_loop()->RunUntilIdle();
122 EXPECT_EQ(0, did_callback
);
124 plugin_loader()->canonical_list()->clear();
125 plugin_loader()->canonical_list()->push_back(plugin1_
.path
);
126 plugin_loader()->TestOnPluginLoaded(0, plugin1_
);
127 message_loop()->RunUntilIdle();
129 EXPECT_EQ(1, did_callback
);
130 EXPECT_EQ(1u, plugin_loader()->number_of_pending_callbacks());
132 plugin_loader()->canonical_list()->clear();
133 plugin_loader()->canonical_list()->push_back(plugin1_
.path
);
134 plugin_loader()->TestOnPluginLoaded(0, plugin1_
);
135 message_loop()->RunUntilIdle();
137 EXPECT_EQ(2, did_callback
);
138 EXPECT_EQ(0u, plugin_loader()->number_of_pending_callbacks());
141 TEST_F(PluginLoaderPosixTest
, ThreeSuccessfulLoads
) {
142 int did_callback
= 0;
143 PluginService::GetPluginsCallback callback
=
144 base::Bind(&VerifyCallback
, base::Unretained(&did_callback
));
146 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback
);
148 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
149 message_loop()->RunUntilIdle();
153 EXPECT_EQ(0u, plugin_loader()->next_load_index());
155 const std::vector
<webkit::WebPluginInfo
>& plugins(
156 plugin_loader()->loaded_plugins());
158 plugin_loader()->TestOnPluginLoaded(0, plugin1_
);
159 EXPECT_EQ(1u, plugin_loader()->next_load_index());
160 EXPECT_EQ(1u, plugins
.size());
161 EXPECT_EQ(plugin1_
.name
, plugins
[0].name
);
163 message_loop()->RunUntilIdle();
164 EXPECT_EQ(0, did_callback
);
166 plugin_loader()->TestOnPluginLoaded(1, plugin2_
);
167 EXPECT_EQ(2u, plugin_loader()->next_load_index());
168 EXPECT_EQ(2u, plugins
.size());
169 EXPECT_EQ(plugin2_
.name
, plugins
[1].name
);
171 message_loop()->RunUntilIdle();
172 EXPECT_EQ(0, did_callback
);
174 plugin_loader()->TestOnPluginLoaded(2, plugin3_
);
175 EXPECT_EQ(3u, plugins
.size());
176 EXPECT_EQ(plugin3_
.name
, plugins
[2].name
);
178 message_loop()->RunUntilIdle();
179 EXPECT_EQ(1, did_callback
);
182 TEST_F(PluginLoaderPosixTest
, ThreeSuccessfulLoadsThenCrash
) {
183 int did_callback
= 0;
184 PluginService::GetPluginsCallback callback
=
185 base::Bind(&VerifyCallback
, base::Unretained(&did_callback
));
187 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback
);
189 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(2);
190 message_loop()->RunUntilIdle();
194 EXPECT_EQ(0u, plugin_loader()->next_load_index());
196 const std::vector
<webkit::WebPluginInfo
>& plugins(
197 plugin_loader()->loaded_plugins());
199 plugin_loader()->TestOnPluginLoaded(0, plugin1_
);
200 EXPECT_EQ(1u, plugin_loader()->next_load_index());
201 EXPECT_EQ(1u, plugins
.size());
202 EXPECT_EQ(plugin1_
.name
, plugins
[0].name
);
204 message_loop()->RunUntilIdle();
205 EXPECT_EQ(0, did_callback
);
207 plugin_loader()->TestOnPluginLoaded(1, plugin2_
);
208 EXPECT_EQ(2u, plugin_loader()->next_load_index());
209 EXPECT_EQ(2u, plugins
.size());
210 EXPECT_EQ(plugin2_
.name
, plugins
[1].name
);
212 message_loop()->RunUntilIdle();
213 EXPECT_EQ(0, did_callback
);
215 plugin_loader()->TestOnPluginLoaded(2, plugin3_
);
216 EXPECT_EQ(3u, plugins
.size());
217 EXPECT_EQ(plugin3_
.name
, plugins
[2].name
);
219 message_loop()->RunUntilIdle();
220 EXPECT_EQ(1, did_callback
);
222 plugin_loader()->OnProcessCrashed(42);
225 TEST_F(PluginLoaderPosixTest
, TwoFailures
) {
226 int did_callback
= 0;
227 PluginService::GetPluginsCallback callback
=
228 base::Bind(&VerifyCallback
, base::Unretained(&did_callback
));
230 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback
);
232 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
233 message_loop()->RunUntilIdle();
237 EXPECT_EQ(0u, plugin_loader()->next_load_index());
239 const std::vector
<webkit::WebPluginInfo
>& plugins(
240 plugin_loader()->loaded_plugins());
242 plugin_loader()->TestOnPluginLoadFailed(0, plugin1_
.path
);
243 EXPECT_EQ(1u, plugin_loader()->next_load_index());
244 EXPECT_EQ(0u, plugins
.size());
246 message_loop()->RunUntilIdle();
247 EXPECT_EQ(0, did_callback
);
249 plugin_loader()->TestOnPluginLoaded(1, plugin2_
);
250 EXPECT_EQ(2u, plugin_loader()->next_load_index());
251 EXPECT_EQ(1u, plugins
.size());
252 EXPECT_EQ(plugin2_
.name
, plugins
[0].name
);
254 message_loop()->RunUntilIdle();
255 EXPECT_EQ(0, did_callback
);
257 plugin_loader()->TestOnPluginLoadFailed(2, plugin3_
.path
);
258 EXPECT_EQ(1u, plugins
.size());
260 message_loop()->RunUntilIdle();
261 EXPECT_EQ(1, did_callback
);
264 TEST_F(PluginLoaderPosixTest
, CrashedProcess
) {
265 int did_callback
= 0;
266 PluginService::GetPluginsCallback callback
=
267 base::Bind(&VerifyCallback
, base::Unretained(&did_callback
));
269 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback
);
271 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
272 message_loop()->RunUntilIdle();
276 EXPECT_EQ(0u, plugin_loader()->next_load_index());
278 const std::vector
<webkit::WebPluginInfo
>& plugins(
279 plugin_loader()->loaded_plugins());
281 plugin_loader()->TestOnPluginLoaded(0, plugin1_
);
282 EXPECT_EQ(1u, plugin_loader()->next_load_index());
283 EXPECT_EQ(1u, plugins
.size());
284 EXPECT_EQ(plugin1_
.name
, plugins
[0].name
);
286 message_loop()->RunUntilIdle();
287 EXPECT_EQ(0, did_callback
);
289 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
290 plugin_loader()->OnProcessCrashed(42);
291 EXPECT_EQ(1u, plugin_loader()->canonical_list()->size());
292 EXPECT_EQ(0u, plugin_loader()->next_load_index());
293 EXPECT_EQ(plugin3_
.path
.value(),
294 plugin_loader()->canonical_list()->at(0).value());
297 TEST_F(PluginLoaderPosixTest
, InternalPlugin
) {
298 int did_callback
= 0;
299 PluginService::GetPluginsCallback callback
=
300 base::Bind(&VerifyCallback
, base::Unretained(&did_callback
));
302 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback
);
304 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
305 message_loop()->RunUntilIdle();
307 plugin2_
.path
= base::FilePath("/internal/plugin.plugin");
311 plugin_loader()->internal_plugins()->clear();
312 plugin_loader()->internal_plugins()->push_back(plugin2_
);
314 EXPECT_EQ(0u, plugin_loader()->next_load_index());
316 const std::vector
<webkit::WebPluginInfo
>& plugins(
317 plugin_loader()->loaded_plugins());
319 plugin_loader()->TestOnPluginLoaded(0, plugin1_
);
320 EXPECT_EQ(1u, plugin_loader()->next_load_index());
321 EXPECT_EQ(1u, plugins
.size());
322 EXPECT_EQ(plugin1_
.name
, plugins
[0].name
);
324 message_loop()->RunUntilIdle();
325 EXPECT_EQ(0, did_callback
);
327 // Internal plugins can fail to load if they're built-in with manual
328 // entrypoint functions.
329 plugin_loader()->TestOnPluginLoadFailed(1, plugin2_
.path
);
330 EXPECT_EQ(2u, plugin_loader()->next_load_index());
331 EXPECT_EQ(2u, plugins
.size());
332 EXPECT_EQ(plugin2_
.name
, plugins
[1].name
);
333 EXPECT_EQ(0u, plugin_loader()->internal_plugins()->size());
335 message_loop()->RunUntilIdle();
336 EXPECT_EQ(0, did_callback
);
338 plugin_loader()->TestOnPluginLoaded(2, plugin3_
);
339 EXPECT_EQ(3u, plugins
.size());
340 EXPECT_EQ(plugin3_
.name
, plugins
[2].name
);
342 message_loop()->RunUntilIdle();
343 EXPECT_EQ(1, did_callback
);
346 TEST_F(PluginLoaderPosixTest
, AllCrashed
) {
347 int did_callback
= 0;
348 PluginService::GetPluginsCallback callback
=
349 base::Bind(&VerifyCallback
, base::Unretained(&did_callback
));
351 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback
);
353 // Spin the loop so that the canonical list of plugins can be set.
354 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
355 message_loop()->RunUntilIdle();
358 EXPECT_EQ(0u, plugin_loader()->next_load_index());
360 // Mock the first two calls like normal.
361 testing::Expectation first
=
362 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(2);
363 // On the last call, go through the default impl.
364 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal())
367 testing::Invoke(plugin_loader(),
368 &MockPluginLoaderPosix::RealLoadPluginsInternal
));
369 plugin_loader()->OnProcessCrashed(42);
370 plugin_loader()->OnProcessCrashed(42);
371 plugin_loader()->OnProcessCrashed(42);
373 message_loop()->RunUntilIdle();
374 EXPECT_EQ(1, did_callback
);
376 EXPECT_EQ(0u, plugin_loader()->loaded_plugins().size());
379 } // namespace content