blob: 832b0f38ea87e2adb36d7a7088d79d1630db6775 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include <vector>
#include "base/at_exit.h"
#include "base/message_loop.h"
#include "chrome/browser/chrome_plugin_service_filter.h"
#include "chrome/browser/chromeos/gview_request_interceptor.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/plugins/plugin_prefs_factory.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/testing_pref_service.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_job_factory.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/plugins/npapi/mock_plugin_list.h"
using content::BrowserThread;
using content::PluginService;
namespace chromeos {
namespace {
const char kPdfUrl[] = "http://foo.com/file.pdf";
const char kPptUrl[] = "http://foo.com/file.ppt";
const char kHtmlUrl[] = "http://foo.com/index.html";
const char kPdfBlob[] = "blob:blobinternal:///d17c4eef-28e7-42bd-bafa-78d5cb8";
const char kPdfUrlIntercepted[] =
"http://docs.google.com/gview?url=http%3A//foo.com/file.pdf";
const char kPptUrlIntercepted[] =
"http://docs.google.com/gview?url=http%3A//foo.com/file.ppt";
void AssertPluginEnabled(bool did_enable) {
ASSERT_TRUE(did_enable);
MessageLoop::current()->QuitWhenIdle();
}
class GViewURLRequestTestJob : public net::URLRequestTestJob {
public:
GViewURLRequestTestJob(net::URLRequest* request,
net::NetworkDelegate* network_delegate)
: net::URLRequestTestJob(request, network_delegate, true) {
}
virtual bool GetMimeType(std::string* mime_type) const {
// During the course of a single test, two URLRequestJobs are
// created -- the first is for the viewable document URL, and the
// second is for the rediected URL. In order to test the
// interceptor, the mime type of the first request must be one of
// the supported viewable mime types. So when the net::URLRequestJob
// is a request for one of the test URLs that point to viewable
// content, return an appropraite mime type. Otherwise, return
// "text/html".
const GURL& request_url = request_->url();
if (request_url == GURL(kPdfUrl) || request_url == GURL(kPdfBlob)) {
*mime_type = "application/pdf";
} else if (request_url == GURL(kPptUrl)) {
*mime_type = "application/vnd.ms-powerpoint";
} else {
*mime_type = "text/html";
}
return true;
}
private:
~GViewURLRequestTestJob() {}
};
class GViewRequestProtocolFactory
: public net::URLRequestJobFactory::ProtocolHandler {
public:
GViewRequestProtocolFactory() {}
virtual ~GViewRequestProtocolFactory() {}
virtual net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
return new GViewURLRequestTestJob(request, network_delegate);
}
};
class GViewRequestInterceptorTest : public testing::Test {
public:
GViewRequestInterceptorTest()
: ui_thread_(BrowserThread::UI, &message_loop_),
file_thread_(BrowserThread::FILE, &message_loop_),
io_thread_(BrowserThread::IO, &message_loop_),
plugin_list_(NULL, 0) {}
virtual void SetUp() {
net::URLRequestContext* request_context =
resource_context_.GetRequestContext();
old_factory_ = request_context->job_factory();
job_factory_.SetProtocolHandler("http", new GViewRequestProtocolFactory);
job_factory_.AddInterceptor(new GViewRequestInterceptor);
request_context->set_job_factory(&job_factory_);
plugin_prefs_ = PluginPrefs::GetForTestingProfile(&profile_);
PluginPrefsFactory::GetInstance()->RegisterUserPrefsOnProfile(&profile_);
ChromePluginServiceFilter* filter =
ChromePluginServiceFilter::GetInstance();
filter->RegisterResourceContext(plugin_prefs_, &resource_context_);
PluginService::GetInstance()->SetFilter(filter);
ASSERT_TRUE(PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path_));
PluginService::GetInstance()->SetPluginListForTesting(&plugin_list_);
PluginService::GetInstance()->Init();
}
virtual void TearDown() {
plugin_prefs_->ShutdownOnUIThread();
net::URLRequestContext* request_context =
resource_context_.GetRequestContext();
request_context->set_job_factory(old_factory_);
ChromePluginServiceFilter* filter =
ChromePluginServiceFilter::GetInstance();
filter->UnregisterResourceContext(&resource_context_);
PluginService::GetInstance()->SetFilter(NULL);
}
void RegisterPDFPlugin() {
webkit::WebPluginInfo info;
info.path = pdf_path_;
plugin_list_.AddPluginToLoad(info);
plugin_list_.RefreshPlugins();
}
void UnregisterPDFPlugin() {
plugin_list_.ClearPluginsToLoad();
plugin_list_.RefreshPlugins();
}
void SetPDFPluginLoadedState(bool want_loaded) {
webkit::WebPluginInfo info;
bool is_loaded = PluginService::GetInstance()->GetPluginInfoByPath(
pdf_path_, &info);
if (is_loaded == want_loaded)
return;
if (want_loaded) {
// This "loads" the plug-in even if it's not present on the
// system - which is OK since we don't actually use it, just
// need it to be "enabled" for the test.
RegisterPDFPlugin();
} else {
UnregisterPDFPlugin();
}
is_loaded = PluginService::GetInstance()->GetPluginInfoByPath(
pdf_path_, &info);
ASSERT_EQ(want_loaded, is_loaded);
}
void SetupRequest(net::URLRequest* request) {
content::ResourceRequestInfo::AllocateForTesting(request,
ResourceType::MAIN_FRAME,
&resource_context_,
-1,
-1);
}
protected:
base::ShadowingAtExitManager at_exit_manager_; // Deletes PluginService.
MessageLoopForIO message_loop_;
content::TestBrowserThread ui_thread_;
content::TestBrowserThread file_thread_;
content::TestBrowserThread io_thread_;
webkit::npapi::MockPluginList plugin_list_;
TestingProfile profile_;
scoped_refptr<PluginPrefs> plugin_prefs_;
net::URLRequestJobFactoryImpl job_factory_;
const net::URLRequestJobFactory* old_factory_;
TestDelegate test_delegate_;
FilePath pdf_path_;
content::MockResourceContext resource_context_;
};
TEST_F(GViewRequestInterceptorTest, DoNotInterceptHtml) {
net::URLRequest request(
GURL(kHtmlUrl), &test_delegate_, resource_context_.GetRequestContext());
SetupRequest(&request);
request.Start();
MessageLoop::current()->Run();
EXPECT_EQ(0, test_delegate_.received_redirect_count());
EXPECT_EQ(GURL(kHtmlUrl), request.url());
}
TEST_F(GViewRequestInterceptorTest, DoNotInterceptDownload) {
net::URLRequest request(
GURL(kPdfUrl), &test_delegate_, resource_context_.GetRequestContext());
SetupRequest(&request);
request.set_load_flags(net::LOAD_IS_DOWNLOAD);
request.Start();
MessageLoop::current()->Run();
EXPECT_EQ(0, test_delegate_.received_redirect_count());
EXPECT_EQ(GURL(kPdfUrl), request.url());
}
TEST_F(GViewRequestInterceptorTest, DoNotInterceptPdfWhenEnabled) {
ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(true));
plugin_prefs_->EnablePlugin(true, pdf_path_,
base::Bind(&AssertPluginEnabled));
MessageLoop::current()->Run();
net::URLRequest request(
GURL(kPdfUrl), &test_delegate_, resource_context_.GetRequestContext());
SetupRequest(&request);
request.Start();
MessageLoop::current()->Run();
EXPECT_EQ(0, test_delegate_.received_redirect_count());
EXPECT_EQ(GURL(kPdfUrl), request.url());
}
TEST_F(GViewRequestInterceptorTest, InterceptPdfWhenDisabled) {
ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(true));
plugin_prefs_->EnablePlugin(false, pdf_path_,
base::Bind(&AssertPluginEnabled));
MessageLoop::current()->Run();
net::URLRequest request(
GURL(kPdfUrl), &test_delegate_, resource_context_.GetRequestContext());
SetupRequest(&request);
request.Start();
MessageLoop::current()->Run();
EXPECT_EQ(1, test_delegate_.received_redirect_count());
EXPECT_EQ(GURL(kPdfUrlIntercepted), request.url());
}
#if !defined(GOOGLE_CHROME_BUILD)
// Official builds have pdf plugin by default, and we cannot unload it, so the
// test fails. Since pdf plugin is always present, we don't need to run this
// test.
TEST_F(GViewRequestInterceptorTest, InterceptPdfWithNoPlugin) {
ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(false));
net::URLRequest request(
GURL(kPdfUrl), &test_delegate_, resource_context_.GetRequestContext());
SetupRequest(&request);
request.Start();
MessageLoop::current()->Run();
EXPECT_EQ(1, test_delegate_.received_redirect_count());
EXPECT_EQ(GURL(kPdfUrlIntercepted), request.url());
}
#endif
TEST_F(GViewRequestInterceptorTest, InterceptPowerpoint) {
net::URLRequest request(
GURL(kPptUrl), &test_delegate_, resource_context_.GetRequestContext());
SetupRequest(&request);
request.Start();
MessageLoop::current()->Run();
EXPECT_EQ(1, test_delegate_.received_redirect_count());
EXPECT_EQ(GURL(kPptUrlIntercepted), request.url());
}
TEST_F(GViewRequestInterceptorTest, DoNotInterceptPost) {
ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(false));
net::URLRequest request(
GURL(kPdfUrl), &test_delegate_, resource_context_.GetRequestContext());
SetupRequest(&request);
request.set_method("POST");
request.Start();
MessageLoop::current()->Run();
EXPECT_EQ(0, test_delegate_.received_redirect_count());
EXPECT_EQ(GURL(kPdfUrl), request.url());
}
TEST_F(GViewRequestInterceptorTest, DoNotInterceptBlob) {
ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(false));
net::URLRequest request(
GURL(kPdfBlob), &test_delegate_, resource_context_.GetRequestContext());
SetupRequest(&request);
request.Start();
MessageLoop::current()->Run();
EXPECT_EQ(0, test_delegate_.received_redirect_count());
EXPECT_EQ(GURL(kPdfBlob), request.url());
}
} // namespace
} // namespace chromeos