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.
8 #include "base/at_exit.h"
9 #include "base/message_loop.h"
10 #include "chrome/browser/chrome_plugin_service_filter.h"
11 #include "chrome/browser/chromeos/gview_request_interceptor.h"
12 #include "chrome/browser/plugins/plugin_prefs.h"
13 #include "chrome/browser/plugins/plugin_prefs_factory.h"
14 #include "chrome/common/chrome_paths.h"
15 #include "chrome/test/base/testing_pref_service.h"
16 #include "chrome/test/base/testing_profile.h"
17 #include "content/public/browser/plugin_service.h"
18 #include "content/public/browser/resource_request_info.h"
19 #include "content/public/test/mock_resource_context.h"
20 #include "content/public/test/test_browser_thread.h"
21 #include "net/base/load_flags.h"
22 #include "net/url_request/url_request.h"
23 #include "net/url_request/url_request_job.h"
24 #include "net/url_request/url_request_job_factory.h"
25 #include "net/url_request/url_request_job_factory_impl.h"
26 #include "net/url_request/url_request_test_job.h"
27 #include "net/url_request/url_request_test_util.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "webkit/plugins/npapi/mock_plugin_list.h"
31 using content::BrowserThread
;
32 using content::PluginService
;
38 const char kPdfUrl
[] = "http://foo.com/file.pdf";
39 const char kPptUrl
[] = "http://foo.com/file.ppt";
40 const char kHtmlUrl
[] = "http://foo.com/index.html";
41 const char kPdfBlob
[] = "blob:blobinternal:///d17c4eef-28e7-42bd-bafa-78d5cb8";
43 const char kPdfUrlIntercepted
[] =
44 "http://docs.google.com/gview?url=http%3A//foo.com/file.pdf";
45 const char kPptUrlIntercepted
[] =
46 "http://docs.google.com/gview?url=http%3A//foo.com/file.ppt";
48 void AssertPluginEnabled(bool did_enable
) {
49 ASSERT_TRUE(did_enable
);
50 MessageLoop::current()->QuitWhenIdle();
53 class GViewURLRequestTestJob
: public net::URLRequestTestJob
{
55 GViewURLRequestTestJob(net::URLRequest
* request
,
56 net::NetworkDelegate
* network_delegate
)
57 : net::URLRequestTestJob(request
, network_delegate
, true) {
60 virtual bool GetMimeType(std::string
* mime_type
) const {
61 // During the course of a single test, two URLRequestJobs are
62 // created -- the first is for the viewable document URL, and the
63 // second is for the rediected URL. In order to test the
64 // interceptor, the mime type of the first request must be one of
65 // the supported viewable mime types. So when the net::URLRequestJob
66 // is a request for one of the test URLs that point to viewable
67 // content, return an appropraite mime type. Otherwise, return
69 const GURL
& request_url
= request_
->url();
70 if (request_url
== GURL(kPdfUrl
) || request_url
== GURL(kPdfBlob
)) {
71 *mime_type
= "application/pdf";
72 } else if (request_url
== GURL(kPptUrl
)) {
73 *mime_type
= "application/vnd.ms-powerpoint";
75 *mime_type
= "text/html";
81 ~GViewURLRequestTestJob() {}
84 class GViewRequestProtocolFactory
85 : public net::URLRequestJobFactory::ProtocolHandler
{
87 GViewRequestProtocolFactory() {}
88 virtual ~GViewRequestProtocolFactory() {}
90 virtual net::URLRequestJob
* MaybeCreateJob(
91 net::URLRequest
* request
, net::NetworkDelegate
* network_delegate
) const {
92 return new GViewURLRequestTestJob(request
, network_delegate
);
96 class GViewRequestInterceptorTest
: public testing::Test
{
98 GViewRequestInterceptorTest()
99 : ui_thread_(BrowserThread::UI
, &message_loop_
),
100 file_thread_(BrowserThread::FILE, &message_loop_
),
101 io_thread_(BrowserThread::IO
, &message_loop_
) {}
103 virtual void SetUp() {
104 net::URLRequestContext
* request_context
=
105 resource_context_
.GetRequestContext();
106 old_factory_
= request_context
->job_factory();
107 job_factory_
.SetProtocolHandler("http", new GViewRequestProtocolFactory
);
108 job_factory_
.AddInterceptor(new GViewRequestInterceptor
);
109 request_context
->set_job_factory(&job_factory_
);
110 plugin_prefs_
= PluginPrefs::GetForTestingProfile(&profile_
);
111 PluginPrefsFactory::GetInstance()->RegisterUserPrefsOnProfile(&profile_
);
112 ChromePluginServiceFilter
* filter
=
113 ChromePluginServiceFilter::GetInstance();
114 filter
->RegisterResourceContext(plugin_prefs_
, &resource_context_
);
115 PluginService::GetInstance()->SetFilter(filter
);
117 ASSERT_TRUE(PathService::Get(chrome::FILE_PDF_PLUGIN
, &pdf_path_
));
119 PluginService::GetInstance()->SetPluginListForTesting(&plugin_list_
);
120 PluginService::GetInstance()->Init();
123 virtual void TearDown() {
124 plugin_prefs_
->ShutdownOnUIThread();
125 net::URLRequestContext
* request_context
=
126 resource_context_
.GetRequestContext();
127 request_context
->set_job_factory(old_factory_
);
128 ChromePluginServiceFilter
* filter
=
129 ChromePluginServiceFilter::GetInstance();
130 filter
->UnregisterResourceContext(&resource_context_
);
131 PluginService::GetInstance()->SetFilter(NULL
);
134 void RegisterPDFPlugin() {
135 webkit::WebPluginInfo info
;
136 info
.path
= pdf_path_
;
137 info
.mime_types
.push_back(webkit::WebPluginMimeType(
138 "application/pdf", ".test", "Test Plugin"));
139 plugin_list_
.AddPluginToLoad(info
);
140 plugin_list_
.RefreshPlugins();
143 void UnregisterPDFPlugin() {
144 plugin_list_
.ClearPluginsToLoad();
145 plugin_list_
.RefreshPlugins();
148 void SetPDFPluginLoadedState(bool want_loaded
) {
149 webkit::WebPluginInfo info
;
150 bool is_loaded
= PluginService::GetInstance()->GetPluginInfoByPath(
152 if (is_loaded
== want_loaded
)
156 // This "loads" the plug-in even if it's not present on the
157 // system - which is OK since we don't actually use it, just
158 // need it to be "enabled" for the test.
161 UnregisterPDFPlugin();
163 is_loaded
= PluginService::GetInstance()->GetPluginInfoByPath(
165 ASSERT_EQ(want_loaded
, is_loaded
);
168 void SetupRequest(net::URLRequest
* request
) {
169 content::ResourceRequestInfo::AllocateForTesting(request
,
170 ResourceType::MAIN_FRAME
,
177 base::ShadowingAtExitManager at_exit_manager_
; // Deletes PluginService.
178 MessageLoopForIO message_loop_
;
179 content::TestBrowserThread ui_thread_
;
180 content::TestBrowserThread file_thread_
;
181 content::TestBrowserThread io_thread_
;
182 webkit::npapi::MockPluginList plugin_list_
;
183 TestingProfile profile_
;
184 scoped_refptr
<PluginPrefs
> plugin_prefs_
;
185 net::URLRequestJobFactoryImpl job_factory_
;
186 const net::URLRequestJobFactory
* old_factory_
;
187 net::TestDelegate test_delegate_
;
189 content::MockResourceContext resource_context_
;
192 TEST_F(GViewRequestInterceptorTest
, DoNotInterceptHtml
) {
193 net::URLRequest
request(
194 GURL(kHtmlUrl
), &test_delegate_
, resource_context_
.GetRequestContext());
195 SetupRequest(&request
);
197 MessageLoop::current()->Run();
198 EXPECT_EQ(0, test_delegate_
.received_redirect_count());
199 EXPECT_EQ(GURL(kHtmlUrl
), request
.url());
202 TEST_F(GViewRequestInterceptorTest
, DoNotInterceptDownload
) {
203 net::URLRequest
request(
204 GURL(kPdfUrl
), &test_delegate_
, resource_context_
.GetRequestContext());
205 SetupRequest(&request
);
206 request
.set_load_flags(net::LOAD_IS_DOWNLOAD
);
208 MessageLoop::current()->Run();
209 EXPECT_EQ(0, test_delegate_
.received_redirect_count());
210 EXPECT_EQ(GURL(kPdfUrl
), request
.url());
213 TEST_F(GViewRequestInterceptorTest
, DoNotInterceptPdfWhenEnabled
) {
214 ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(true));
215 plugin_prefs_
->EnablePlugin(true, pdf_path_
,
216 base::Bind(&AssertPluginEnabled
));
217 MessageLoop::current()->Run();
219 net::URLRequest
request(
220 GURL(kPdfUrl
), &test_delegate_
, resource_context_
.GetRequestContext());
221 SetupRequest(&request
);
223 MessageLoop::current()->Run();
224 EXPECT_EQ(0, test_delegate_
.received_redirect_count());
225 EXPECT_EQ(GURL(kPdfUrl
), request
.url());
228 TEST_F(GViewRequestInterceptorTest
, InterceptPdfWhenDisabled
) {
229 ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(true));
230 plugin_prefs_
->EnablePlugin(false, pdf_path_
,
231 base::Bind(&AssertPluginEnabled
));
232 MessageLoop::current()->Run();
234 net::URLRequest
request(
235 GURL(kPdfUrl
), &test_delegate_
, resource_context_
.GetRequestContext());
236 SetupRequest(&request
);
238 MessageLoop::current()->Run();
239 EXPECT_EQ(1, test_delegate_
.received_redirect_count());
240 EXPECT_EQ(GURL(kPdfUrlIntercepted
), request
.url());
243 #if !defined(GOOGLE_CHROME_BUILD)
244 // Official builds have pdf plugin by default, and we cannot unload it, so the
245 // test fails. Since pdf plugin is always present, we don't need to run this
247 TEST_F(GViewRequestInterceptorTest
, InterceptPdfWithNoPlugin
) {
248 ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(false));
250 net::URLRequest
request(
251 GURL(kPdfUrl
), &test_delegate_
, resource_context_
.GetRequestContext());
252 SetupRequest(&request
);
254 MessageLoop::current()->Run();
255 EXPECT_EQ(1, test_delegate_
.received_redirect_count());
256 EXPECT_EQ(GURL(kPdfUrlIntercepted
), request
.url());
260 TEST_F(GViewRequestInterceptorTest
, InterceptPowerpoint
) {
261 net::URLRequest
request(
262 GURL(kPptUrl
), &test_delegate_
, resource_context_
.GetRequestContext());
263 SetupRequest(&request
);
265 MessageLoop::current()->Run();
266 EXPECT_EQ(1, test_delegate_
.received_redirect_count());
267 EXPECT_EQ(GURL(kPptUrlIntercepted
), request
.url());
270 TEST_F(GViewRequestInterceptorTest
, DoNotInterceptPost
) {
271 ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(false));
273 net::URLRequest
request(
274 GURL(kPdfUrl
), &test_delegate_
, resource_context_
.GetRequestContext());
275 SetupRequest(&request
);
276 request
.set_method("POST");
278 MessageLoop::current()->Run();
279 EXPECT_EQ(0, test_delegate_
.received_redirect_count());
280 EXPECT_EQ(GURL(kPdfUrl
), request
.url());
283 TEST_F(GViewRequestInterceptorTest
, DoNotInterceptBlob
) {
284 ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(false));
286 net::URLRequest
request(
287 GURL(kPdfBlob
), &test_delegate_
, resource_context_
.GetRequestContext());
288 SetupRequest(&request
);
290 MessageLoop::current()->Run();
291 EXPECT_EQ(0, test_delegate_
.received_redirect_count());
292 EXPECT_EQ(GURL(kPdfBlob
), request
.url());
297 } // namespace chromeos