blob: 8027836d925e1d433eed488c90de2b3cb49c045b [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/feature_list.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pdf_uma.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "net/base/escape.h"
#include "net/http/http_response_headers.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
PDFIFrameNavigationThrottle::PDFIFrameNavigationThrottle(
content::NavigationHandle* navigation_handle)
: content::NavigationThrottle(navigation_handle) {}
PDFIFrameNavigationThrottle::~PDFIFrameNavigationThrottle() {}
const char* PDFIFrameNavigationThrottle::GetNameForLogging() {
return "PDFIFrameNavigationThrottle";
}
// static
std::unique_ptr<content::NavigationThrottle>
PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(
content::NavigationHandle* handle) {
if (handle->IsInMainFrame())
return nullptr;
#if BUILDFLAG(ENABLE_PLUGINS)
content::WebPluginInfo pdf_plugin_info;
base::FilePath pdf_plugin_path =
base::FilePath::FromUTF8Unsafe(ChromeContentClient::kPDFPluginPath);
content::PluginService::GetInstance()->GetPluginInfoByPath(pdf_plugin_path,
&pdf_plugin_info);
ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
int process_id =
handle->GetWebContents()->GetMainFrame()->GetProcess()->GetID();
int routing_id = handle->GetWebContents()->GetMainFrame()->GetRoutingID();
content::ResourceContext* resource_context =
handle->GetWebContents()->GetBrowserContext()->GetResourceContext();
if (filter->IsPluginAvailable(process_id, routing_id, resource_context,
handle->GetURL(), url::Origin(),
&pdf_plugin_info)) {
return nullptr;
}
#endif
// If ENABLE_PLUGINS is false, the PDF plugin is not available, so we should
// always intercept PDF iframe navigations.
return base::MakeUnique<PDFIFrameNavigationThrottle>(handle);
}
content::NavigationThrottle::ThrottleCheckResult
PDFIFrameNavigationThrottle::WillProcessResponse() {
const net::HttpResponseHeaders* response_headers =
navigation_handle()->GetResponseHeaders();
if (!response_headers)
return content::NavigationThrottle::PROCEED;
std::string mime_type;
response_headers->GetMimeType(&mime_type);
if (mime_type != kPDFMimeType)
return content::NavigationThrottle::PROCEED;
ReportPDFLoadStatus(PDFLoadStatus::kLoadedIframePdfWithNoPdfViewer);
if (!base::FeatureList::IsEnabled(features::kClickToOpenPDFPlaceholder))
return content::NavigationThrottle::PROCEED;
std::string html = base::StringPrintf(
R"(<body style="margin: 0;"><object data="%s" type="application/pdf" )"
R"(style="width: 100%%; height: 100%%;"></object></body>)",
navigation_handle()->GetURL().spec().c_str());
GURL data_url("data:text/html," + net::EscapePath(html));
navigation_handle()->GetWebContents()->OpenURL(
content::OpenURLParams(data_url, navigation_handle()->GetReferrer(),
navigation_handle()->GetFrameTreeNodeId(),
WindowOpenDisposition::CURRENT_TAB,
ui::PAGE_TRANSITION_AUTO_SUBFRAME, false));
return content::NavigationThrottle::CANCEL_AND_IGNORE;
}