Commit 9dcebac2 authored by raymes's avatar raymes Committed by Commit bot

Make the logic for stream interception by MimeHandlerViews consistent with starting the plugin

Currently there is logic in the renderer which checks whether a plugin can
handle a mime type and if it can the plugin is started. This is also how
MimeHandlerView plugins are started in the renderer. MimeHandlerViews also
rely on the original http request being intercepted as a stream which the
plugin can read when it chooses. This happens in the browser. Currently
the logic for determining whether the stream should be intercepted is different
to the logic for determining whether to start the plugin which can lead to
problems in some cases. This CL makes sure the logic is the same: on both
sides we check whether the plugin can handle the mime type.

MimeHandlerView plugins load a chrome extension inside a BrowserPlugin.
Once it has been determined that the plugin can handle the mime type inside
BufferedResourceHandler, the extension ID of the plugin is passed down through into
ChromeResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream.
It is then checked that the extension is enabled and if so the stream is intercepted.
There is some complexity because we also need to support the legacy case
where the stream is intercepted for the streamsPrivate api in which case there is no
MimeHandlerView plugin.

This CL was originally written by deepak.m1@samsung.com (Deepak Mittal)
and landed here: https://codereview.chromium.org/953793003/. It was reverted
because of a bug it triggered with not downloading PDFs when the PDF plugin
was disabled. This bug has been addressed and a test added for that case.

BUG=443466

Review URL: https://codereview.chromium.org/1164073006

Cr-Commit-Position: refs/heads/master@{#339816}
parent 0a021e87
......@@ -2,27 +2,44 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <vector>
#include "base/base_paths.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/hash.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/pdf/pdf_extension_test_util.h"
#include "chrome/browser/pdf/pdf_extension_util.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/manifest_handlers/mime_types_handler.h"
#include "extensions/test/result_catcher.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "ui/base/resource/resource_bundle.h"
#include "url/gurl.h"
const int kNumberLoadTestParts = 10;
......@@ -152,6 +169,79 @@ IN_PROC_BROWSER_TEST_P(PDFExtensionTest, Load) {
LoadAllPdfsTest("pdf", GetParam());
}
class DisablePluginHelper : public content::DownloadManager::Observer,
public content::NotificationObserver {
public:
DisablePluginHelper() {}
virtual ~DisablePluginHelper() {}
void DisablePlugin(Profile* profile) {
registrar_.Add(this, chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED,
content::Source<Profile>(profile));
scoped_refptr<PluginPrefs> prefs(PluginPrefs::GetForProfile(profile));
DCHECK(prefs.get());
prefs->EnablePluginGroup(
false, base::UTF8ToUTF16(ChromeContentClient::kPDFPluginName));
// Wait until the plugin has been disabled.
disable_run_loop_.Run();
}
const GURL& GetLastUrl() {
// Wait until the download has been created.
download_run_loop_.Run();
return last_url_;
}
// content::DownloadManager::Observer implementation.
void OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) override {
last_url_ = item->GetURL();
download_run_loop_.Quit();
}
// content::NotificationObserver implementation.
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override {
DCHECK_EQ(chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, type);
disable_run_loop_.Quit();
}
private:
content::NotificationRegistrar registrar_;
base::RunLoop disable_run_loop_;
base::RunLoop download_run_loop_;
GURL last_url_;
};
IN_PROC_BROWSER_TEST_F(PDFExtensionTest, DisablePlugin) {
// Disable the PDF plugin.
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::BrowserContext* browser_context = web_contents->GetBrowserContext();
Profile* profile = Profile::FromBrowserContext(browser_context);
DisablePluginHelper helper;
helper.DisablePlugin(profile);
// Register a download observer.
content::DownloadManager* download_manager =
content::BrowserContext::GetDownloadManager(browser_context);
download_manager->AddObserver(&helper);
// Navigate to a PDF and test that it is downloaded.
GURL url(embedded_test_server()->GetURL("/pdf/test.pdf"));
ui_test_utils::NavigateToURL(browser(), url);
ASSERT_EQ(url, helper.GetLastUrl());
// Cancel the download to shutdown cleanly.
download_manager->RemoveObserver(&helper);
std::vector<content::DownloadItem*> downloads;
download_manager->GetAllDownloads(&downloads);
ASSERT_EQ(1u, downloads.size());
downloads[0]->Cancel(false);
}
// We break PDFTest.Load up into kNumberLoadTestParts.
INSTANTIATE_TEST_CASE_P(PDFTestFiles,
PDFExtensionTest,
......
......@@ -205,36 +205,6 @@ void SendExecuteMimeTypeHandlerEvent(scoped_ptr<content::StreamInfo> stream,
extension_id, web_contents, stream.Pass(), view_id, expected_content_size,
embedded, render_process_id, render_frame_id);
}
// TODO(raymes): This won't return the right result if plugins haven't been
// loaded yet. Fixing this properly really requires fixing crbug.com/443466.
bool IsPluginEnabledForExtension(const Extension* extension,
const ResourceRequestInfo* info,
const std::string& mime_type,
const GURL& url) {
content::PluginService* service = content::PluginService::GetInstance();
std::vector<content::WebPluginInfo> plugins;
service->GetPluginInfoArray(url, mime_type, true, &plugins, nullptr);
content::PluginServiceFilter* filter = service->GetFilter();
for (auto& plugin : plugins) {
// Check that the plugin is running the extension.
if (plugin.path !=
base::FilePath::FromUTF8Unsafe(extension->url().spec())) {
continue;
}
// Check that the plugin is actually enabled.
if (!filter || filter->IsPluginAvailable(info->GetChildID(),
info->GetRenderFrameID(),
info->GetContext(),
url,
GURL(),
&plugin)) {
return true;
}
}
return false;
}
#endif // !defined(ENABLE_EXTENSIONS)
void LaunchURL(
......@@ -603,6 +573,7 @@ bool ChromeResourceDispatcherHostDelegate::ShouldForceDownloadResource(
bool ChromeResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream(
net::URLRequest* request,
const base::FilePath& plugin_path,
const std::string& mime_type,
GURL* origin,
std::string* payload) {
......@@ -626,25 +597,31 @@ bool ChromeResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream(
!extension_info_map->IsIncognitoEnabled(extension_id))) {
continue;
}
MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
if (handler && handler->CanHandleMIMEType(mime_type)) {
StreamTargetInfo target_info;
*origin = Extension::GetBaseURLFromExtensionId(extension_id);
target_info.extension_id = extension_id;
if (!handler->handler_url().empty()) {
// This is reached in the case of MimeHandlerViews. If the
// MimeHandlerView plugin is disabled, then we shouldn't intercept the
// stream.
if (!IsPluginEnabledForExtension(extension, info, mime_type,
request->url())) {
continue;
}
if (!handler)
continue;
// If a plugin path is provided then a stream is being intercepted for the
// mimeHandlerPrivate API. Otherwise a stream is being intercepted for the
// streamsPrivate API.
if (!plugin_path.empty()) {
if (handler->HasPlugin() && plugin_path == handler->GetPluginPath()) {
StreamTargetInfo target_info;
*origin = Extension::GetBaseURLFromExtensionId(extension_id);
target_info.extension_id = extension_id;
target_info.view_id = base::GenerateGUID();
*payload = target_info.view_id;
stream_target_info_[request] = target_info;
return true;
}
} else {
if (!handler->HasPlugin() && handler->CanHandleMIMEType(mime_type)) {
StreamTargetInfo target_info;
*origin = Extension::GetBaseURLFromExtensionId(extension_id);
target_info.extension_id = extension_id;
stream_target_info_[request] = target_info;
return true;
}
stream_target_info_[request] = target_info;
return true;
}
}
#endif
......
......@@ -61,6 +61,7 @@ class ChromeResourceDispatcherHostDelegate
bool ShouldForceDownloadResource(const GURL& url,
const std::string& mime_type) override;
bool ShouldInterceptResourceAsStream(net::URLRequest* request,
const base::FilePath& plugin_path,
const std::string& mime_type,
GURL* origin,
std::string* payload) override;
......
......@@ -292,6 +292,49 @@ bool MimeTypeResourceHandler::DetermineMimeType() {
return made_final_decision;
}
bool MimeTypeResourceHandler::SelectPluginHandler(bool* defer,
bool* handled_by_plugin) {
*handled_by_plugin = false;
#if defined(ENABLE_PLUGINS)
ResourceRequestInfoImpl* info = GetRequestInfo();
bool allow_wildcard = false;
bool stale;
WebPluginInfo plugin;
bool has_plugin = plugin_service_->GetPluginInfo(
info->GetChildID(), info->GetRenderFrameID(), info->GetContext(),
request()->url(), GURL(), response_->head.mime_type, allow_wildcard,
&stale, &plugin, NULL);
if (stale) {
// Refresh the plugins asynchronously.
plugin_service_->GetPlugins(
base::Bind(&MimeTypeResourceHandler::OnPluginsLoaded,
weak_ptr_factory_.GetWeakPtr()));
request()->LogBlockedBy("MimeTypeResourceHandler");
*defer = true;
return true;
}
if (has_plugin && plugin.type != WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) {
*handled_by_plugin = true;
return true;
}
// Attempt to intercept the request as a stream.
base::FilePath plugin_path;
if (has_plugin)
plugin_path = plugin.path;
std::string payload;
scoped_ptr<ResourceHandler> handler(host_->MaybeInterceptAsStream(
plugin_path, request(), response_.get(), &payload));
if (handler) {
*handled_by_plugin = true;
return UseAlternateNextHandler(handler.Pass(), payload);
}
#endif
return true;
}
bool MimeTypeResourceHandler::SelectNextHandler(bool* defer) {
DCHECK(!response_->head.mime_type.empty());
......@@ -309,13 +352,12 @@ bool MimeTypeResourceHandler::SelectNextHandler(bool* defer) {
// Allow requests for object/embed tags to be intercepted as streams.
if (info->GetResourceType() == content::RESOURCE_TYPE_OBJECT) {
DCHECK(!info->allow_download());
std::string payload;
scoped_ptr<ResourceHandler> handler(
host_->MaybeInterceptAsStream(request(), response_.get(), &payload));
if (handler) {
DCHECK(!mime_util::IsSupportedMimeType(mime_type));
return UseAlternateNextHandler(handler.Pass(), payload);
}
bool handled_by_plugin;
if (!SelectPluginHandler(defer, &handled_by_plugin))
return false;
if (handled_by_plugin || *defer)
return true;
}
if (!info->allow_download())
......@@ -332,28 +374,11 @@ bool MimeTypeResourceHandler::SelectNextHandler(bool* defer) {
if (mime_util::IsSupportedMimeType(mime_type))
return true;
std::string payload;
scoped_ptr<ResourceHandler> handler(
host_->MaybeInterceptAsStream(request(), response_.get(), &payload));
if (handler) {
return UseAlternateNextHandler(handler.Pass(), payload);
}
#if defined(ENABLE_PLUGINS)
bool stale;
bool has_plugin = HasSupportingPlugin(&stale);
if (stale) {
// Refresh the plugins asynchronously.
plugin_service_->GetPlugins(
base::Bind(&MimeTypeResourceHandler::OnPluginsLoaded,
weak_ptr_factory_.GetWeakPtr()));
request()->LogBlockedBy("MimeTypeResourceHandler");
*defer = true;
return true;
}
if (has_plugin)
bool handled_by_plugin;
if (!SelectPluginHandler(defer, &handled_by_plugin))
return false;
if (handled_by_plugin || *defer)
return true;
#endif
}
// Install download handler
......@@ -470,23 +495,6 @@ bool MimeTypeResourceHandler::MustDownload() {
return must_download_;
}
bool MimeTypeResourceHandler::HasSupportingPlugin(bool* stale) {
#if defined(ENABLE_PLUGINS)
ResourceRequestInfoImpl* info = GetRequestInfo();
bool allow_wildcard = false;
WebPluginInfo plugin;
return plugin_service_->GetPluginInfo(
info->GetChildID(), info->GetRenderFrameID(), info->GetContext(),
request()->url(), GURL(), response_->head.mime_type, allow_wildcard,
stale, &plugin, NULL);
#else
if (stale)
*stale = false;
return false;
#endif
}
bool MimeTypeResourceHandler::CopyReadBufferToNextHandler() {
if (!read_buffer_.get())
return true;
......
......@@ -66,6 +66,15 @@ class CONTENT_EXPORT MimeTypeResourceHandler
bool ShouldSniffContent();
bool DetermineMimeType();
// Determines whether a plugin will handle the current request, and if so,
// sets up the handler to direct the response to that plugin. Returns false
// if there is an error and the request should be cancelled and true
// otherwise. |defer| is set to true if plugin data is stale and needs to be
// refreshed before the request can be handled (in this case the function
// still returns true). If the request is directed to a plugin,
// |handled_by_plugin| is set to true.
bool SelectPluginHandler(bool* defer, bool* handled_by_plugin);
// Returns false if the request should be cancelled.
bool SelectNextHandler(bool* defer);
bool UseAlternateNextHandler(scoped_ptr<ResourceHandler> handler,
const std::string& payload_for_old_handler);
......@@ -74,7 +83,6 @@ class CONTENT_EXPORT MimeTypeResourceHandler
void CallReplayReadCompleted();
bool MustDownload();
bool HasSupportingPlugin(bool* is_stale);
// Copies data from |read_buffer_| to |next_handler_|.
bool CopyReadBufferToNextHandler();
......
......@@ -4,6 +4,7 @@
#include "content/browser/loader/mime_type_resource_handler.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
......@@ -12,6 +13,7 @@
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/resource_response.h"
#include "content/public/common/webplugininfo.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "content/test/fake_plugin_service.h"
......@@ -84,7 +86,8 @@ class TestResourceDispatcherHost : public ResourceDispatcherHostImpl {
public:
explicit TestResourceDispatcherHost(bool stream_has_handler)
: stream_has_handler_(stream_has_handler),
intercepted_as_stream_(false) {}
intercepted_as_stream_(false),
intercepted_as_stream_count_(0) {}
bool intercepted_as_stream() const { return intercepted_as_stream_; }
......@@ -99,9 +102,11 @@ class TestResourceDispatcherHost : public ResourceDispatcherHostImpl {
}
scoped_ptr<ResourceHandler> MaybeInterceptAsStream(
const base::FilePath& plugin_path,
net::URLRequest* request,
ResourceResponse* response,
std::string* payload) override {
intercepted_as_stream_count_++;
if (stream_has_handler_) {
intercepted_as_stream_ = true;
return scoped_ptr<ResourceHandler>(new TestResourceHandler).Pass();
......@@ -110,12 +115,20 @@ class TestResourceDispatcherHost : public ResourceDispatcherHostImpl {
}
}
int intercepted_as_stream_count() const {
return intercepted_as_stream_count_;
}
private:
// Whether the URL request should be intercepted as a stream.
bool stream_has_handler_;
// Whether the URL request has been intercepted as a stream.
bool intercepted_as_stream_;
// Count of number of times MaybeInterceptAsStream function get called in a
// test.
int intercepted_as_stream_count_;
};
class TestResourceDispatcherHostDelegate
......@@ -151,14 +164,64 @@ class TestResourceController : public ResourceController {
}
};
class TestFakePluginService : public FakePluginService {
public:
// If |is_plugin_stale| is true, GetPluginInfo will indicate the plugins are
// stale until GetPlugins is called.
TestFakePluginService(bool plugin_available, bool is_plugin_stale)
: plugin_available_(plugin_available),
is_plugin_stale_(is_plugin_stale) {}
bool GetPluginInfo(int render_process_id,
int render_frame_id,
ResourceContext* context,
const GURL& url,
const GURL& page_url,
const std::string& mime_type,
bool allow_wildcard,
bool* is_stale,
WebPluginInfo* info,
std::string* actual_mime_type) override {
*is_stale = is_plugin_stale_;
if (!is_plugin_stale_ || !plugin_available_)
return false;
info->type = WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN;
info->path = base::FilePath::FromUTF8Unsafe(
std::string("chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/"));
return true;
}
void GetPlugins(const GetPluginsCallback& callback) override {
is_plugin_stale_ = false;
std::vector<WebPluginInfo> plugins;
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, plugins));
}
private:
const bool plugin_available_;
bool is_plugin_stale_;
DISALLOW_COPY_AND_ASSIGN(TestFakePluginService);
};
class MimeTypeResourceHandlerTest : public testing::Test {
public:
MimeTypeResourceHandlerTest() : stream_has_handler_(false) {}
MimeTypeResourceHandlerTest()
: stream_has_handler_(false),
plugin_available_(false),
plugin_stale_(false) {}
void set_stream_has_handler(bool stream_has_handler) {
stream_has_handler_ = stream_has_handler;
}
void set_plugin_available(bool plugin_available) {
plugin_available_ = plugin_available;
}
void set_plugin_stale(bool plugin_stale) { plugin_stale_ = plugin_stale; }
bool TestStreamIsIntercepted(bool allow_download,
bool must_download,
ResourceType request_resource_type);
......@@ -166,6 +229,8 @@ class MimeTypeResourceHandlerTest : public testing::Test {
private:
// Whether the URL request should be intercepted as a stream.
bool stream_has_handler_;
bool plugin_available_;
bool plugin_stale_;
TestBrowserThreadBundle thread_bundle_;
};
......@@ -194,13 +259,11 @@ bool MimeTypeResourceHandlerTest::TestStreamIsIntercepted(
TestResourceDispatcherHostDelegate host_delegate(must_download);
host.SetDelegate(&host_delegate);
FakePluginService plugin_service;
TestFakePluginService plugin_service(plugin_available_, plugin_stale_);
scoped_ptr<ResourceHandler> mime_sniffing_handler(
new MimeTypeResourceHandler(
scoped_ptr<ResourceHandler>(new TestResourceHandler()).Pass(),
&host,
&plugin_service,
request.get()));
scoped_ptr<ResourceHandler>(new TestResourceHandler()).Pass(), &host,
&plugin_service, request.get()));
TestResourceController resource_controller;
mime_sniffing_handler->SetController(&resource_controller);
......@@ -212,12 +275,13 @@ bool MimeTypeResourceHandlerTest::TestStreamIsIntercepted(
mime_sniffing_handler->OnResponseStarted(response.get(), &defer);
content::RunAllPendingInMessageLoop();
EXPECT_LT(host.intercepted_as_stream_count(), 2);
return host.intercepted_as_stream();
}
// Test that stream requests are correctly intercepted under the right
// circumstances.
// circumstances. Test is not relevent when plugins are disabled.
#if defined(ENABLE_PLUGINS)
TEST_F(MimeTypeResourceHandlerTest, StreamHandling) {
bool allow_download;
bool must_download;
......@@ -226,6 +290,7 @@ TEST_F(MimeTypeResourceHandlerTest, StreamHandling) {
// Ensure the stream is handled by MaybeInterceptAsStream in the
// ResourceDispatcherHost.
set_stream_has_handler(true);
set_plugin_available(true);
// Main frame request with no download allowed. Stream shouldn't be
// intercepted.
......@@ -267,7 +332,6 @@ TEST_F(MimeTypeResourceHandlerTest, StreamHandling) {
// Test the cases where the stream isn't handled by MaybeInterceptAsStream
// in the ResourceDispatcherHost.
set_stream_has_handler(false);
allow_download = false;
must_download = false;
resource_type = RESOURCE_TYPE_OBJECT;
......@@ -279,7 +343,29 @@ TEST_F(MimeTypeResourceHandlerTest, StreamHandling) {
resource_type = RESOURCE_TYPE_MAIN_FRAME;
EXPECT_FALSE(
TestStreamIsIntercepted(allow_download, must_download, resource_type));
// Test the cases where the stream handled by MaybeInterceptAsStream
// with plugin not available. This is the case when intercepting streams for
// the streamsPrivate extensions API.
set_stream_has_handler(true);
set_plugin_available(false);
allow_download = false;
must_download = false;
resource_type = RESOURCE_TYPE_OBJECT;
EXPECT_TRUE(
TestStreamIsIntercepted(allow_download, must_download, resource_type));
// Test the cases where the stream handled by MaybeInterceptAsStream
// with plugin not available. This is the case when intercepting streams for
// the streamsPrivate extensions API with stale plugin.
set_plugin_stale(true);
allow_download = false;
must_download = false;
resource_type = RESOURCE_TYPE_OBJECT;
EXPECT_TRUE(
TestStreamIsIntercepted(allow_download, must_download, resource_type));
}
#endif
} // namespace
......
......@@ -718,19 +718,19 @@ ResourceDispatcherHostImpl::CreateResourceHandlerForDownload(
return handler.Pass();
}
scoped_ptr<ResourceHandler>
ResourceDispatcherHostImpl::MaybeInterceptAsStream(net::URLRequest* request,
ResourceResponse* response,
std::string* payload) {
scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::MaybeInterceptAsStream(
const base::FilePath& plugin_path,
net::URLRequest* request,
ResourceResponse* response,
std::string* payload) {
payload->clear();
ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request);
const std::string& mime_type = response->head.mime_type;
GURL origin;
if (!delegate_ ||
!delegate_->ShouldInterceptResourceAsStream(request,
mime_type,
&origin,
payload)) {
!delegate_->ShouldInterceptResourceAsStream(
request, plugin_path, mime_type, &origin, payload)) {
return scoped_ptr<ResourceHandler>();
}
......
......@@ -45,6 +45,10 @@
class ResourceHandler;
struct ResourceHostMsg_Request;
namespace base {
class FilePath;
}
namespace net {
class URLRequestJobFactory;
}
......@@ -233,12 +237,20 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
scoped_ptr<DownloadSaveInfo> save_info,
const DownloadUrlParameters::OnStartedCallback& started_cb);
// Must be called after the ResourceRequestInfo has been created
// and associated with the request. If |payload| is set to a non-empty value,
// the value will be sent to the old resource handler instead of canceling
// it, except on HTTP errors. This is marked virtual so it can be overriden in
// testing.
// Called to determine whether the response to |request| should be intercepted
// and handled as a stream. Streams are used to pass direct access to a
// resource response to another application (e.g. a web page) without being
// handled by the browser itself. If the request should be intercepted as a
// stream, a StreamResourceHandler is returned which provides access to the
// response. |plugin_path| is the path to the plugin which is handling the
// URL request. This may be empty if there is no plugin handling the request.
//
// This function must be called after the ResourceRequestInfo has been created
// and associated with the request. If |payload| is set to a non-empty value,
// the caller must send it to the old resource handler instead of cancelling
// it.
virtual scoped_ptr<ResourceHandler> MaybeInterceptAsStream(
const base::FilePath& plugin_path,
net::URLRequest* request,
ResourceResponse* response,
std::string* payload);
......
......@@ -60,6 +60,7 @@ bool ResourceDispatcherHostDelegate::ShouldForceDownloadResource(
bool ResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream(
net::URLRequest* request,
const base::FilePath& plugin_path,
const std::string& mime_type,
GURL* origin,
std::string* payload) {
......
......@@ -8,6 +8,7 @@
#include <string>
#include "base/basictypes.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "content/public/common/resource_type.h"
......@@ -86,20 +87,22 @@ class CONTENT_EXPORT ResourceDispatcherHostDelegate {
const std::string& mime_type);
// Returns true and sets |origin| if a Stream should be created for the
// resource.
// If true is returned, a new Stream will be created and OnStreamCreated()
// will be called with
// - a StreamHandle instance for the Stream. The handle contains the URL for
// reading the Stream etc.
// The Stream's origin will be set to |origin|.
// resource. |plugin_path| is the plugin which will be used to handle the
// request (if the stream will be rendered in a BrowserPlugin). It may be
// empty. If true is returned, a new Stream will be created and
// OnStreamCreated() will be called with a StreamHandle instance for the
// Stream. The handle contains the URL for reading the Stream etc. The
// Stream's origin will be set to |origin|.
//
// If the stream will be rendered in a BrowserPlugin, |payload| will contain
// the data that should be given to the old ResourceHandler to forward to the
// renderer process.
virtual bool ShouldInterceptResourceAsStream(net::URLRequest* request,
const std::string& mime_type,
GURL* origin,
std::string* payload);
virtual bool ShouldInterceptResourceAsStream(
net::URLRequest* request,
const base::FilePath& plugin_path,
const std::string& mime_type,
GURL* origin,
std::string* payload);
// Informs the delegate that a Stream was created. The Stream can be read from
// the blob URL of the Stream, but can only be read once.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment