By moving the call to Load() up in SearchProvider::Start(), we are giving a chance...
[chromium-blink-merge.git] / content / browser / plugin_service_impl_browsertest.cc
blob18780355dd64c61f2217f58fb7bb3f74197dca1a
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/resource_context.h"
13 #include "content/public/browser/web_contents.h"
14 #include "content/public/common/content_switches.h"
15 #include "content/public/test/test_browser_thread.h"
16 #include "content/public/test/test_utils.h"
17 #include "content/shell/shell.h"
18 #include "content/test/content_browser_test.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "webkit/plugins/npapi/plugin_list.h"
21 #include "webkit/plugins/npapi/plugin_utils.h"
23 namespace content {
25 const char kNPAPITestPluginMimeType[] = "application/vnd.npapi-test";
27 void OpenChannel(PluginProcessHost::Client* client) {
28 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
29 // Start opening the channel
30 PluginServiceImpl::GetInstance()->OpenChannelToNpapiPlugin(
31 0, 0, GURL(), GURL(), kNPAPITestPluginMimeType, client);
34 // Mock up of the Client and the Listener classes that would supply the
35 // communication channel with the plugin.
36 class MockPluginProcessHostClient : public PluginProcessHost::Client,
37 public IPC::Listener {
38 public:
39 MockPluginProcessHostClient(ResourceContext* context)
40 : context_(context),
41 channel_(NULL),
42 set_plugin_info_called_(false) {
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_ = new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this);
64 ASSERT_TRUE(channel_->Connect());
67 virtual void SetPluginInfo(const webkit::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 QuitMessageLoop();
85 virtual void OnChannelError() OVERRIDE {
86 Fail();
88 #if defined(OS_POSIX)
89 virtual void OnChannelDenied() OVERRIDE {
90 Fail();
92 virtual void OnChannelListenError() OVERRIDE {
93 Fail();
95 #endif
97 private:
98 void Fail() {
99 FAIL();
100 QuitMessageLoop();
103 void QuitMessageLoop() {
104 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
105 MessageLoop::QuitClosure());
108 ResourceContext* context_;
109 IPC::Channel* channel_;
110 bool set_plugin_info_called_;
111 DISALLOW_COPY_AND_ASSIGN(MockPluginProcessHostClient);
114 class PluginServiceTest : public ContentBrowserTest {
115 public:
116 PluginServiceTest() {}
118 ResourceContext* GetResourceContext() {
119 return shell()->web_contents()->GetBrowserContext()->GetResourceContext();
122 virtual void SetUpCommandLine(CommandLine* command_line) {
123 #ifdef OS_MACOSX
124 FilePath browser_directory;
125 PathService::Get(base::DIR_MODULE, &browser_directory);
126 command_line->AppendSwitchPath(switches::kExtraPluginDir,
127 browser_directory.AppendASCII("plugins"));
128 #endif
129 // TODO(jam): since these plugin tests are running under Chrome, we need to
130 // tell it to disable its security features for old plugins. Once this is
131 // running under content_browsertests, these flags won't be needed.
132 // http://crbug.com/90448
133 // switches::kAlwaysAuthorizePlugins
134 command_line->AppendSwitch("always-authorize-plugins");
138 // Try to open a channel to the test plugin. Minimal plugin process spawning
139 // test for the PluginService interface.
140 IN_PROC_BROWSER_TEST_F(PluginServiceTest, OpenChannelToPlugin) {
141 if (!webkit::npapi::NPAPIPluginsSupported())
142 return;
143 MockPluginProcessHostClient mock_client(GetResourceContext());
144 BrowserThread::PostTask(
145 BrowserThread::IO, FROM_HERE,
146 base::Bind(&OpenChannel, &mock_client));
147 RunMessageLoop();
150 // A strict mock that fails if any of the methods are called. They shouldn't be
151 // called since the request should get canceled before then.
152 class MockCanceledPluginServiceClient : public PluginProcessHost::Client {
153 public:
154 MockCanceledPluginServiceClient(ResourceContext* context)
155 : context_(context),
156 get_resource_context_called_(false) {
159 virtual ~MockCanceledPluginServiceClient() {}
161 // Client implementation.
162 MOCK_METHOD0(ID, int());
163 virtual ResourceContext* GetResourceContext() OVERRIDE {
164 get_resource_context_called_ = true;
165 return context_;
167 MOCK_METHOD0(OffTheRecord, bool());
168 MOCK_METHOD1(OnFoundPluginProcessHost, void(PluginProcessHost* host));
169 MOCK_METHOD0(OnSentPluginChannelRequest, void());
170 MOCK_METHOD1(OnChannelOpened, void(const IPC::ChannelHandle& handle));
171 MOCK_METHOD1(SetPluginInfo, void(const webkit::WebPluginInfo& info));
172 MOCK_METHOD0(OnError, void());
174 bool get_resource_context_called() const {
175 return get_resource_context_called_;
178 private:
179 ResourceContext* context_;
180 bool get_resource_context_called_;
182 DISALLOW_COPY_AND_ASSIGN(MockCanceledPluginServiceClient);
185 void QuitUIMessageLoopFromIOThread() {
186 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
187 MessageLoop::QuitClosure());
190 void OpenChannelAndThenCancel(PluginProcessHost::Client* client) {
191 OpenChannel(client);
192 // Immediately cancel it. This is guaranteed to work since PluginService needs
193 // to consult its filter on the FILE thread.
194 PluginServiceImpl::GetInstance()->CancelOpenChannelToNpapiPlugin(client);
195 // Before we terminate the test, add a roundtrip through the FILE thread to
196 // make sure that it's had a chance to post back to the IO thread. Then signal
197 // the UI thread to stop and exit the test.
198 BrowserThread::PostTaskAndReply(
199 BrowserThread::FILE, FROM_HERE,
200 base::Bind(&base::DoNothing),
201 base::Bind(&QuitUIMessageLoopFromIOThread));
204 // Should not attempt to open a channel, since it should be canceled early on.
205 IN_PROC_BROWSER_TEST_F(PluginServiceTest, CancelOpenChannelToPluginService) {
206 ::testing::StrictMock<MockCanceledPluginServiceClient> mock_client(
207 GetResourceContext());
208 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
209 base::Bind(OpenChannelAndThenCancel, &mock_client));
210 RunMessageLoop();
211 EXPECT_TRUE(mock_client.get_resource_context_called());
214 class MockCanceledBeforeSentPluginProcessHostClient
215 : public MockCanceledPluginServiceClient {
216 public:
217 MockCanceledBeforeSentPluginProcessHostClient(
218 ResourceContext* context)
219 : MockCanceledPluginServiceClient(context),
220 set_plugin_info_called_(false),
221 on_found_plugin_process_host_called_(false),
222 host_(NULL) {}
224 virtual ~MockCanceledBeforeSentPluginProcessHostClient() {}
226 // Client implementation.
227 virtual void SetPluginInfo(const webkit::WebPluginInfo& info) OVERRIDE {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
229 ASSERT_TRUE(info.mime_types.size());
230 ASSERT_EQ(kNPAPITestPluginMimeType, info.mime_types[0].mime_type);
231 set_plugin_info_called_ = true;
233 virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
235 set_on_found_plugin_process_host_called();
236 set_host(host);
237 // This gets called right before we request the plugin<=>renderer channel,
238 // so we have to post a task to cancel it.
239 MessageLoop::current()->PostTask(
240 FROM_HERE,
241 base::Bind(&PluginProcessHost::CancelPendingRequest,
242 base::Unretained(host), this));
243 MessageLoop::current()->PostTask(
244 FROM_HERE,
245 base::Bind(&QuitUIMessageLoopFromIOThread));
248 bool set_plugin_info_called() const {
249 return set_plugin_info_called_;
252 bool on_found_plugin_process_host_called() const {
253 return on_found_plugin_process_host_called_;
256 protected:
257 void set_on_found_plugin_process_host_called() {
258 on_found_plugin_process_host_called_ = true;
260 void set_host(PluginProcessHost* host) {
261 host_ = host;
264 PluginProcessHost* host() const { return host_; }
266 private:
267 bool set_plugin_info_called_;
268 bool on_found_plugin_process_host_called_;
269 PluginProcessHost* host_;
271 DISALLOW_COPY_AND_ASSIGN(MockCanceledBeforeSentPluginProcessHostClient);
274 IN_PROC_BROWSER_TEST_F(
275 PluginServiceTest, CancelBeforeSentOpenChannelToPluginProcessHost) {
276 if (!webkit::npapi::NPAPIPluginsSupported())
277 return;
278 ::testing::StrictMock<MockCanceledBeforeSentPluginProcessHostClient>
279 mock_client(GetResourceContext());
280 BrowserThread::PostTask(
281 BrowserThread::IO, FROM_HERE,
282 base::Bind(&OpenChannel, &mock_client));
283 RunMessageLoop();
284 EXPECT_TRUE(mock_client.get_resource_context_called());
285 EXPECT_TRUE(mock_client.set_plugin_info_called());
286 EXPECT_TRUE(mock_client.on_found_plugin_process_host_called());
289 class MockCanceledAfterSentPluginProcessHostClient
290 : public MockCanceledBeforeSentPluginProcessHostClient {
291 public:
292 MockCanceledAfterSentPluginProcessHostClient(
293 ResourceContext* context)
294 : MockCanceledBeforeSentPluginProcessHostClient(context),
295 on_sent_plugin_channel_request_called_(false) {}
296 virtual ~MockCanceledAfterSentPluginProcessHostClient() {}
298 // Client implementation.
300 virtual int ID() OVERRIDE { return 42; }
301 virtual bool OffTheRecord() OVERRIDE { return false; }
303 // We override this guy again since we don't want to cancel yet.
304 virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {
305 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
306 set_on_found_plugin_process_host_called();
307 set_host(host);
310 virtual void OnSentPluginChannelRequest() OVERRIDE {
311 on_sent_plugin_channel_request_called_ = true;
312 host()->CancelSentRequest(this);
313 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
314 MessageLoop::QuitClosure());
317 bool on_sent_plugin_channel_request_called() const {
318 return on_sent_plugin_channel_request_called_;
321 private:
322 bool on_sent_plugin_channel_request_called_;
324 DISALLOW_COPY_AND_ASSIGN(MockCanceledAfterSentPluginProcessHostClient);
327 // Should not attempt to open a channel, since it should be canceled early on.
328 IN_PROC_BROWSER_TEST_F(
329 PluginServiceTest, CancelAfterSentOpenChannelToPluginProcessHost) {
330 if (!webkit::npapi::NPAPIPluginsSupported())
331 return;
332 ::testing::StrictMock<MockCanceledAfterSentPluginProcessHostClient>
333 mock_client(GetResourceContext());
334 BrowserThread::PostTask(
335 BrowserThread::IO, FROM_HERE,
336 base::Bind(&OpenChannel, &mock_client));
337 RunMessageLoop();
338 EXPECT_TRUE(mock_client.get_resource_context_called());
339 EXPECT_TRUE(mock_client.set_plugin_info_called());
340 EXPECT_TRUE(mock_client.on_found_plugin_process_host_called());
341 EXPECT_TRUE(mock_client.on_sent_plugin_channel_request_called());
344 } // namespace content