Rename Animate as Begin(Main)Frame
[chromium-blink-merge.git] / content / browser / plugin_service_impl_browsertest.cc
blob7a3271e6c78f92f57a832e59e93e2650fb7a3673
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_service_impl.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/path_service.h"
11 #include "content/public/browser/browser_context.h"
12 #include "content/public/browser/plugin_service_filter.h"
13 #include "content/public/browser/resource_context.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/common/content_switches.h"
16 #include "content/public/test/content_browser_test.h"
17 #include "content/public/test/test_browser_thread.h"
18 #include "content/public/test/test_utils.h"
19 #include "content/shell/browser/shell.h"
20 #include "testing/gmock/include/gmock/gmock.h"
22 namespace content {
24 const char kNPAPITestPluginMimeType[] = "application/vnd.npapi-test";
26 void OpenChannel(PluginProcessHost::Client* client) {
27 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
28 // Start opening the channel
29 PluginServiceImpl::GetInstance()->OpenChannelToNpapiPlugin(
30 0, 0, GURL(), GURL(), kNPAPITestPluginMimeType, client);
33 // Mock up of the Client and the Listener classes that would supply the
34 // communication channel with the plugin.
35 class MockPluginProcessHostClient : public PluginProcessHost::Client,
36 public IPC::Listener {
37 public:
38 MockPluginProcessHostClient(ResourceContext* context, bool expect_fail)
39 : context_(context),
40 channel_(NULL),
41 set_plugin_info_called_(false),
42 expect_fail_(expect_fail) {
45 virtual ~MockPluginProcessHostClient() {
46 if (channel_)
47 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_);
50 // PluginProcessHost::Client implementation.
51 virtual int ID() OVERRIDE { return 42; }
52 virtual bool OffTheRecord() OVERRIDE { return false; }
53 virtual ResourceContext* GetResourceContext() OVERRIDE {
54 return context_;
56 virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {}
57 virtual void OnSentPluginChannelRequest() OVERRIDE {}
59 virtual void OnChannelOpened(const IPC::ChannelHandle& handle) OVERRIDE {
60 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
61 ASSERT_TRUE(set_plugin_info_called_);
62 ASSERT_TRUE(!channel_);
63 channel_ = IPC::Channel::CreateClient(handle, this).release();
64 ASSERT_TRUE(channel_->Connect());
67 virtual void SetPluginInfo(const WebPluginInfo& info) OVERRIDE {
68 ASSERT_TRUE(info.mime_types.size());
69 ASSERT_EQ(kNPAPITestPluginMimeType, info.mime_types[0].mime_type);
70 set_plugin_info_called_ = true;
73 virtual void OnError() OVERRIDE {
74 Fail();
77 // IPC::Listener implementation.
78 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
79 Fail();
80 return false;
82 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
83 if (expect_fail_)
84 FAIL();
85 QuitMessageLoop();
87 virtual void OnChannelError() OVERRIDE {
88 Fail();
90 #if defined(OS_POSIX)
91 virtual void OnChannelDenied() OVERRIDE {
92 Fail();
94 virtual void OnChannelListenError() OVERRIDE {
95 Fail();
97 #endif
99 private:
100 void Fail() {
101 if (!expect_fail_)
102 FAIL();
103 QuitMessageLoop();
106 void QuitMessageLoop() {
107 BrowserThread::PostTask(
108 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
111 ResourceContext* context_;
112 IPC::Channel* channel_;
113 bool set_plugin_info_called_;
114 bool expect_fail_;
115 DISALLOW_COPY_AND_ASSIGN(MockPluginProcessHostClient);
118 class MockPluginServiceFilter : public content::PluginServiceFilter {
119 public:
120 MockPluginServiceFilter() {}
122 virtual bool IsPluginAvailable(
123 int render_process_id,
124 int render_view_id,
125 const void* context,
126 const GURL& url,
127 const GURL& policy_url,
128 WebPluginInfo* plugin) OVERRIDE { return true; }
130 virtual bool CanLoadPlugin(
131 int render_process_id,
132 const base::FilePath& path) OVERRIDE { return false; }
135 class PluginServiceTest : public ContentBrowserTest {
136 public:
137 PluginServiceTest() {}
139 ResourceContext* GetResourceContext() {
140 return shell()->web_contents()->GetBrowserContext()->GetResourceContext();
143 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
144 #if defined(OS_MACOSX)
145 base::FilePath browser_directory;
146 PathService::Get(base::DIR_MODULE, &browser_directory);
147 command_line->AppendSwitchPath(switches::kExtraPluginDir,
148 browser_directory.AppendASCII("plugins"));
149 #endif
150 // TODO(jam): since these plugin tests are running under Chrome, we need to
151 // tell it to disable its security features for old plugins. Once this is
152 // running under content_browsertests, these flags won't be needed.
153 // http://crbug.com/90448
154 // switches::kAlwaysAuthorizePlugins
155 command_line->AppendSwitch("always-authorize-plugins");
159 // Try to open a channel to the test plugin. Minimal plugin process spawning
160 // test for the PluginService interface.
161 IN_PROC_BROWSER_TEST_F(PluginServiceTest, OpenChannelToPlugin) {
162 if (!PluginServiceImpl::GetInstance()->NPAPIPluginsSupported())
163 return;
164 MockPluginProcessHostClient mock_client(GetResourceContext(), false);
165 BrowserThread::PostTask(
166 BrowserThread::IO, FROM_HERE,
167 base::Bind(&OpenChannel, &mock_client));
168 RunMessageLoop();
171 IN_PROC_BROWSER_TEST_F(PluginServiceTest, OpenChannelToDeniedPlugin) {
172 if (!PluginServiceImpl::GetInstance()->NPAPIPluginsSupported())
173 return;
174 MockPluginServiceFilter filter;
175 PluginServiceImpl::GetInstance()->SetFilter(&filter);
176 MockPluginProcessHostClient mock_client(GetResourceContext(), true);
177 BrowserThread::PostTask(
178 BrowserThread::IO, FROM_HERE,
179 base::Bind(&OpenChannel, &mock_client));
180 RunMessageLoop();
183 // A strict mock that fails if any of the methods are called. They shouldn't be
184 // called since the request should get canceled before then.
185 class MockCanceledPluginServiceClient : public PluginProcessHost::Client {
186 public:
187 MockCanceledPluginServiceClient(ResourceContext* context)
188 : context_(context),
189 get_resource_context_called_(false) {
192 virtual ~MockCanceledPluginServiceClient() {}
194 // Client implementation.
195 MOCK_METHOD0(ID, int());
196 virtual ResourceContext* GetResourceContext() OVERRIDE {
197 get_resource_context_called_ = true;
198 return context_;
200 MOCK_METHOD0(OffTheRecord, bool());
201 MOCK_METHOD1(OnFoundPluginProcessHost, void(PluginProcessHost* host));
202 MOCK_METHOD0(OnSentPluginChannelRequest, void());
203 MOCK_METHOD1(OnChannelOpened, void(const IPC::ChannelHandle& handle));
204 MOCK_METHOD1(SetPluginInfo, void(const WebPluginInfo& info));
205 MOCK_METHOD0(OnError, void());
207 bool get_resource_context_called() const {
208 return get_resource_context_called_;
211 private:
212 ResourceContext* context_;
213 bool get_resource_context_called_;
215 DISALLOW_COPY_AND_ASSIGN(MockCanceledPluginServiceClient);
218 void QuitUIMessageLoopFromIOThread() {
219 BrowserThread::PostTask(
220 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
223 void OpenChannelAndThenCancel(PluginProcessHost::Client* client) {
224 OpenChannel(client);
225 // Immediately cancel it. This is guaranteed to work since PluginService needs
226 // to consult its filter on the FILE thread.
227 PluginServiceImpl::GetInstance()->CancelOpenChannelToNpapiPlugin(client);
228 // Before we terminate the test, add a roundtrip through the FILE thread to
229 // make sure that it's had a chance to post back to the IO thread. Then signal
230 // the UI thread to stop and exit the test.
231 BrowserThread::PostTaskAndReply(
232 BrowserThread::FILE, FROM_HERE,
233 base::Bind(&base::DoNothing),
234 base::Bind(&QuitUIMessageLoopFromIOThread));
237 // Should not attempt to open a channel, since it should be canceled early on.
238 IN_PROC_BROWSER_TEST_F(PluginServiceTest, CancelOpenChannelToPluginService) {
239 ::testing::StrictMock<MockCanceledPluginServiceClient> mock_client(
240 GetResourceContext());
241 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
242 base::Bind(OpenChannelAndThenCancel, &mock_client));
243 RunMessageLoop();
244 EXPECT_TRUE(mock_client.get_resource_context_called());
247 class MockCanceledBeforeSentPluginProcessHostClient
248 : public MockCanceledPluginServiceClient {
249 public:
250 MockCanceledBeforeSentPluginProcessHostClient(
251 ResourceContext* context)
252 : MockCanceledPluginServiceClient(context),
253 set_plugin_info_called_(false),
254 on_found_plugin_process_host_called_(false),
255 host_(NULL) {}
257 virtual ~MockCanceledBeforeSentPluginProcessHostClient() {}
259 // Client implementation.
260 virtual void SetPluginInfo(const WebPluginInfo& info) OVERRIDE {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
262 ASSERT_TRUE(info.mime_types.size());
263 ASSERT_EQ(kNPAPITestPluginMimeType, info.mime_types[0].mime_type);
264 set_plugin_info_called_ = true;
266 virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {
267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
268 set_on_found_plugin_process_host_called();
269 set_host(host);
270 // This gets called right before we request the plugin<=>renderer channel,
271 // so we have to post a task to cancel it.
272 base::MessageLoop::current()->PostTask(
273 FROM_HERE,
274 base::Bind(&PluginProcessHost::CancelPendingRequest,
275 base::Unretained(host),
276 this));
277 base::MessageLoop::current()->PostTask(
278 FROM_HERE, base::Bind(&QuitUIMessageLoopFromIOThread));
281 bool set_plugin_info_called() const {
282 return set_plugin_info_called_;
285 bool on_found_plugin_process_host_called() const {
286 return on_found_plugin_process_host_called_;
289 protected:
290 void set_on_found_plugin_process_host_called() {
291 on_found_plugin_process_host_called_ = true;
293 void set_host(PluginProcessHost* host) {
294 host_ = host;
297 PluginProcessHost* host() const { return host_; }
299 private:
300 bool set_plugin_info_called_;
301 bool on_found_plugin_process_host_called_;
302 PluginProcessHost* host_;
304 DISALLOW_COPY_AND_ASSIGN(MockCanceledBeforeSentPluginProcessHostClient);
307 IN_PROC_BROWSER_TEST_F(
308 PluginServiceTest, CancelBeforeSentOpenChannelToPluginProcessHost) {
309 if (!PluginServiceImpl::GetInstance()->NPAPIPluginsSupported())
310 return;
311 ::testing::StrictMock<MockCanceledBeforeSentPluginProcessHostClient>
312 mock_client(GetResourceContext());
313 BrowserThread::PostTask(
314 BrowserThread::IO, FROM_HERE,
315 base::Bind(&OpenChannel, &mock_client));
316 RunMessageLoop();
317 EXPECT_TRUE(mock_client.get_resource_context_called());
318 EXPECT_TRUE(mock_client.set_plugin_info_called());
319 EXPECT_TRUE(mock_client.on_found_plugin_process_host_called());
322 class MockCanceledAfterSentPluginProcessHostClient
323 : public MockCanceledBeforeSentPluginProcessHostClient {
324 public:
325 MockCanceledAfterSentPluginProcessHostClient(
326 ResourceContext* context)
327 : MockCanceledBeforeSentPluginProcessHostClient(context),
328 on_sent_plugin_channel_request_called_(false) {}
329 virtual ~MockCanceledAfterSentPluginProcessHostClient() {}
331 // Client implementation.
333 virtual int ID() OVERRIDE { return 42; }
334 virtual bool OffTheRecord() OVERRIDE { return false; }
336 // We override this guy again since we don't want to cancel yet.
337 virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {
338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
339 set_on_found_plugin_process_host_called();
340 set_host(host);
343 virtual void OnSentPluginChannelRequest() OVERRIDE {
344 on_sent_plugin_channel_request_called_ = true;
345 host()->CancelSentRequest(this);
346 BrowserThread::PostTask(
347 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
350 bool on_sent_plugin_channel_request_called() const {
351 return on_sent_plugin_channel_request_called_;
354 private:
355 bool on_sent_plugin_channel_request_called_;
357 DISALLOW_COPY_AND_ASSIGN(MockCanceledAfterSentPluginProcessHostClient);
360 // Should not attempt to open a channel, since it should be canceled early on.
361 IN_PROC_BROWSER_TEST_F(
362 PluginServiceTest, CancelAfterSentOpenChannelToPluginProcessHost) {
363 if (!PluginServiceImpl::GetInstance()->NPAPIPluginsSupported())
364 return;
365 ::testing::StrictMock<MockCanceledAfterSentPluginProcessHostClient>
366 mock_client(GetResourceContext());
367 BrowserThread::PostTask(
368 BrowserThread::IO, FROM_HERE,
369 base::Bind(&OpenChannel, &mock_client));
370 RunMessageLoop();
371 EXPECT_TRUE(mock_client.get_resource_context_called());
372 EXPECT_TRUE(mock_client.set_plugin_info_called());
373 EXPECT_TRUE(mock_client.on_found_plugin_process_host_called());
374 EXPECT_TRUE(mock_client.on_sent_plugin_channel_request_called());
377 } // namespace content