blob: 162fef6023a41f2989bd40a5d0dce29fae44b417 [file] [log] [blame]
// Copyright 2017 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 "chrome/browser/plugins/pdf_iframe_navigation_throttle.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/navigation_handle.h"
#include "net/http/http_util.h"
#include "ppapi/features/features.h"
#if BUILDFLAG(ENABLE_PLUGINS)
#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
#include "content/public/browser/plugin_service.h"
#endif
namespace {
const char kHeader[] = "HTTP/1.1 200 OK\r\n";
const char kExampleURL[] = "http://example.com";
#if BUILDFLAG(ENABLE_PLUGINS)
void PluginsLoadedCallback(base::OnceClosure callback,
const std::vector<content::WebPluginInfo>& plugins) {
std::move(callback).Run();
}
#endif
} // namespace
class PDFIFrameNavigationThrottleTest : public ChromeRenderViewHostTestHarness {
public:
void SetAlwaysOpenPdfExternallyForTests(bool always_open_pdf_externally) {
#if BUILDFLAG(ENABLE_PLUGINS)
PluginPrefs::GetForTestingProfile(profile())
->SetAlwaysOpenPdfExternallyForTests(always_open_pdf_externally);
ChromePluginServiceFilter* filter =
ChromePluginServiceFilter::GetInstance();
filter->RegisterResourceContext(profile(), profile()->GetResourceContext());
#endif
}
std::string GetHeaderWithMimeType(const std::string& mime_type) {
return "HTTP/1.1 200 OK\r\n"
"content-type: " +
mime_type + "\r\n";
}
content::RenderFrameHost* subframe() { return subframe_; }
private:
void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp();
#if BUILDFLAG(ENABLE_PLUGINS)
content::PluginService::GetInstance()->Init();
// Load plugins.
base::RunLoop run_loop;
content::PluginService::GetInstance()->GetPlugins(
base::BindOnce(&PluginsLoadedCallback, run_loop.QuitClosure()));
run_loop.Run();
#endif
content::RenderFrameHostTester::For(main_rfh())
->InitializeRenderFrameIfNeeded();
subframe_ = content::RenderFrameHostTester::For(main_rfh())
->AppendChild("subframe");
feature_list_.InitAndEnableFeature(features::kClickToOpenPDFPlaceholder);
}
base::test::ScopedFeatureList feature_list_;
content::RenderFrameHost* subframe_;
};
TEST_F(PDFIFrameNavigationThrottleTest, OnlyCreateThrottleForSubframes) {
// Disable the PDF plugin to test main vs. subframes.
SetAlwaysOpenPdfExternallyForTests(true);
// Never create throttle for main frames.
std::unique_ptr<content::NavigationHandle> handle =
content::NavigationHandle::CreateNavigationHandleForTesting(
GURL(kExampleURL), main_rfh());
handle->CallWillProcessResponseForTesting(
main_rfh(), net::HttpUtil::AssembleRawHeaders(kHeader, strlen(kHeader)));
std::unique_ptr<content::NavigationThrottle> throttle =
PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle.get());
ASSERT_EQ(nullptr, throttle);
// Create a throttle for subframes.
handle = content::NavigationHandle::CreateNavigationHandleForTesting(
GURL(kExampleURL), subframe());
handle->CallWillProcessResponseForTesting(
subframe(), net::HttpUtil::AssembleRawHeaders(kHeader, strlen(kHeader)));
throttle = PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle.get());
ASSERT_NE(nullptr, throttle);
}
TEST_F(PDFIFrameNavigationThrottleTest, InterceptPDFOnly) {
// Setup
SetAlwaysOpenPdfExternallyForTests(true);
std::unique_ptr<content::NavigationHandle> handle =
content::NavigationHandle::CreateNavigationHandleForTesting(
GURL(kExampleURL), subframe());
// Verify that we CANCEL for PDF mime type.
std::string header = GetHeaderWithMimeType("application/pdf");
handle->CallWillProcessResponseForTesting(
subframe(),
net::HttpUtil::AssembleRawHeaders(header.c_str(), header.size()));
std::unique_ptr<content::NavigationThrottle> throttle =
PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle.get());
ASSERT_NE(nullptr, throttle);
ASSERT_EQ(content::NavigationThrottle::CANCEL_AND_IGNORE,
throttle->WillProcessResponse());
// Verify that we PROCEED for other mime types.
// Blank mime type
handle->CallWillProcessResponseForTesting(
subframe(), net::HttpUtil::AssembleRawHeaders(kHeader, strlen(kHeader)));
throttle = PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle.get());
ASSERT_NE(nullptr, throttle);
ASSERT_EQ(content::NavigationThrottle::PROCEED,
throttle->WillProcessResponse());
// HTML
header = GetHeaderWithMimeType("text/html");
handle->CallWillProcessResponseForTesting(
subframe(),
net::HttpUtil::AssembleRawHeaders(header.c_str(), header.size()));
throttle = PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle.get());
ASSERT_NE(nullptr, throttle);
ASSERT_EQ(content::NavigationThrottle::PROCEED,
throttle->WillProcessResponse());
// PNG
header = GetHeaderWithMimeType("image/png");
handle->CallWillProcessResponseForTesting(
subframe(),
net::HttpUtil::AssembleRawHeaders(header.c_str(), header.size()));
throttle = PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle.get());
ASSERT_NE(nullptr, throttle);
ASSERT_EQ(content::NavigationThrottle::PROCEED,
throttle->WillProcessResponse());
}
#if BUILDFLAG(ENABLE_PLUGINS)
TEST_F(PDFIFrameNavigationThrottleTest, CancelOnlyIfPDFViewerIsDisabled) {
// Setup
std::unique_ptr<content::NavigationHandle> handle =
content::NavigationHandle::CreateNavigationHandleForTesting(
GURL(kExampleURL), subframe());
std::string header = GetHeaderWithMimeType("application/pdf");
handle->CallWillProcessResponseForTesting(
subframe(),
net::HttpUtil::AssembleRawHeaders(header.c_str(), header.size()));
// Test PDF Viewer enabled.
SetAlwaysOpenPdfExternallyForTests(false);
std::unique_ptr<content::NavigationThrottle> throttle =
PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle.get());
ASSERT_EQ(nullptr, throttle);
// Test PDF Viewer disabled.
SetAlwaysOpenPdfExternallyForTests(true);
throttle = PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle.get());
ASSERT_NE(nullptr, throttle);
ASSERT_EQ(content::NavigationThrottle::CANCEL_AND_IGNORE,
throttle->WillProcessResponse());
}
#endif