Commit 9539fccf authored by Ehsan Karamad's avatar Ehsan Karamad Committed by Commit Bot

[ MimeHandlerView ] Do not create PluginDocument

This CL is the second part in the implementation of navigation to PDF
resources with frame-based MimeHandlerView. This change implements the
logic for creating a MimeHandlerViewFrameContainer in response to
browser's request. To this end, when handling the resource request
response for a PDF mime-type, DOMImplementation avoids creating a
PluginDocument and implements an HTMLDocument instead. The document is
then populated with the templated HTML page injected by the plugin
response interceptor.

Design document:
https://docs.google.com/document/d/1_gJv4_fewyfjI7lcUgFX14iQxDudtEMrsjjWKpkI5BI/edit

Bug: 659750
Change-Id: I9a4490d99391d746333f76979e98682fa6742be7
Reviewed-on: https://chromium-review.googlesource.com/c/1477921Reviewed-by: default avatarJames MacLean <wjmaclean@chromium.org>
Reviewed-by: default avatarKent Tamura <tkent@chromium.org>
Reviewed-by: default avatarEhsan Karamad <ekaramad@chromium.org>
Commit-Queue: Ehsan Karamad <ekaramad@chromium.org>
Cr-Commit-Position: refs/heads/master@{#634499}
parent aecde1de
......@@ -71,6 +71,8 @@ class MimeHandlerViewContainerBase : public blink::WebAssociatedURLLoaderClient,
void DidFinishLoading() override;
protected:
MimeHandlerViewContainerBase();
virtual void CreateMimeHandlerViewGuestIfNecessary();
virtual void OnRetryCreatingMimeHandlerViewGuest(int32_t element_instance_id);
virtual void OnDestroyFrameContainer(int32_t element_instance_id);
......
......@@ -30,7 +30,8 @@ void MimeHandlerViewContainerManager::BindRequest(
}
MimeHandlerViewContainerManager::MimeHandlerViewContainerManager(
int32_t routing_id) {}
int32_t routing_id)
: render_frame_routing_id_(routing_id) {}
MimeHandlerViewContainerManager::~MimeHandlerViewContainerManager() {}
......@@ -39,6 +40,16 @@ void MimeHandlerViewContainerManager::CreateFrameContainer(
const std::string& mime_type,
const std::string& view_id) {
// TODO(ekaramad): Implement (https://crbug.com/659750).
auto* render_frame =
content::RenderFrame::FromRoutingID(render_frame_routing_id_);
if (!render_frame)
return;
DCHECK(MimeHandlerViewFrameContainer::IsSupportedMimeType(mime_type));
auto* child = render_frame->GetWebFrame()->FirstChild();
if (!child || child->IsWebRemoteFrame())
return;
MimeHandlerViewFrameContainer::CreateWithFrame(
child->ToWebLocalFrame(), resource_url, mime_type, view_id);
}
} // namespace extensions
......@@ -30,9 +30,7 @@ class MimeHandlerViewContainerManager
const std::string& view_id) override;
private:
GURL resource_url_;
std::string mime_type_;
std::string view_id_;
const int32_t render_frame_routing_id_;
DISALLOW_COPY_AND_ASSIGN(MimeHandlerViewContainerManager);
};
......
......@@ -11,6 +11,7 @@
#include "content/public/common/webplugininfo.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_thread.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_frame.h"
#include "third_party/blink/public/web/web_local_frame.h"
......@@ -19,15 +20,6 @@
namespace extensions {
namespace {
bool IsSupportedMimeType(const std::string& mime_type) {
return mime_type == "text/pdf" || mime_type == "application/pdf" ||
mime_type == "text/csv";
}
} // namespace
class MimeHandlerViewFrameContainer::RenderFrameLifetimeObserver
: public content::RenderFrameObserver {
public:
......@@ -54,6 +46,13 @@ void MimeHandlerViewFrameContainer::RenderFrameLifetimeObserver::OnDestruct() {
container_->OnDestroyFrameContainer(container_->element_instance_id_);
}
// static.
bool MimeHandlerViewFrameContainer::IsSupportedMimeType(
const std::string& mime_type) {
return mime_type == "text/pdf" || mime_type == "application/pdf" ||
mime_type == "text/csv";
}
// static
bool MimeHandlerViewFrameContainer::Create(
const blink::WebElement& plugin_element,
......@@ -77,6 +76,16 @@ bool MimeHandlerViewFrameContainer::Create(
element_instance_id);
}
// static
void MimeHandlerViewFrameContainer::CreateWithFrame(
blink::WebLocalFrame* web_frame,
const GURL& resource_url,
const std::string& mime_type,
const std::string& view_id) {
new MimeHandlerViewFrameContainer(web_frame, resource_url, mime_type,
view_id);
}
MimeHandlerViewFrameContainer::MimeHandlerViewFrameContainer(
const blink::WebElement& plugin_element,
const GURL& resource_url,
......@@ -92,23 +101,27 @@ MimeHandlerViewFrameContainer::MimeHandlerViewFrameContainer(
element_instance_id_(element_instance_id),
render_frame_lifetime_observer_(
new RenderFrameLifetimeObserver(GetEmbedderRenderFrame(), this)) {
is_embedded_ = IsEmbedded();
if (is_embedded_) {
SendResourceRequest();
} else {
// TODO(ekaramad): Currently the full page version gets the same treatment
// as the embedded version of MimeHandlerViewFrameContainer; they both send
// a request for the resource. The full page version however should not as
// there is already an intercepted stream for the navigation. Change the
// logic here to a) IsEmbedded() return false for full page, b) the current
// intercepted stream is used and no new URLRequest is sent for the
// resource, and c) ensure creation of MimeHandlerViewFrameContainer does
// not lead to its destruction right away or the Create() method above would
// incorrectly return |true|. Note that currently calling
// CreateMimeHandlerViewGuestIfNecessary() could lead to the destruction of
// |this| when |plugin_element| does not have a content frame.
NOTREACHED();
}
is_embedded_ = true;
SendResourceRequest();
}
MimeHandlerViewFrameContainer::MimeHandlerViewFrameContainer(
blink::WebLocalFrame* web_local_frame,
const GURL& resource_url,
const std::string& mime_type,
const std::string& view_id)
: MimeHandlerViewContainerBase(
content::RenderFrame::FromWebFrame(
web_local_frame->Parent()->ToWebLocalFrame()),
content::WebPluginInfo(),
mime_type,
resource_url),
element_instance_id_(content::RenderThread::Get()->GenerateRoutingID()) {
is_embedded_ = false;
view_id_ = view_id;
plugin_frame_routing_id_ =
content::RenderFrame::FromWebFrame(web_local_frame)->GetRoutingID();
MimeHandlerViewContainerBase::CreateMimeHandlerViewGuestIfNecessary();
}
MimeHandlerViewFrameContainer::~MimeHandlerViewFrameContainer() {}
......@@ -149,7 +162,10 @@ gfx::Size MimeHandlerViewFrameContainer::GetElementSize() const {
}
blink::WebFrame* MimeHandlerViewFrameContainer::GetContentFrame() const {
return blink::WebFrame::FromFrameOwnerElement(plugin_element_);
if (is_embedded_)
return blink::WebFrame::FromFrameOwnerElement(plugin_element_);
return GetEmbedderRenderFrame()->GetWebFrame()->FirstChild();
}
// mime_handler::BeforeUnloadControl implementation.
......@@ -159,13 +175,4 @@ void MimeHandlerViewFrameContainer::SetShowBeforeUnloadDialog(
// TODO(ekaramad): Implement.
}
bool MimeHandlerViewFrameContainer::IsEmbedded() const {
// TODO(ekaramad): This is currently sending a request regardless of whether
// or not this embed is due to frame navigation to resource. For such cases,
// the renderer has already started a resource request and we should not send
// twice. Find a way to get the intercepted stream and avoid sending an extra
// request here.
return true;
}
} // namespace extensions
......@@ -13,6 +13,7 @@
namespace blink {
class WebElement;
class WebFrame;
class WebLocalFrame;
} // namespace blink
namespace content {
......@@ -26,6 +27,7 @@ namespace extensions {
// for an embedded MimeHandlerView extension in a cross-origin frame.
class MimeHandlerViewFrameContainer : public MimeHandlerViewContainerBase {
public:
static bool IsSupportedMimeType(const std::string& mime_type);
static bool Create(const blink::WebElement& plugin_element,
const GURL& resource_url,
const std::string& mime_type,
......@@ -35,12 +37,24 @@ class MimeHandlerViewFrameContainer : public MimeHandlerViewContainerBase {
private:
class RenderFrameLifetimeObserver;
friend class RenderFrameLifetimeObserver;
friend class MimeHandlerViewContainerManager;
static void CreateWithFrame(blink::WebLocalFrame* web_frame,
const GURL& resource_url,
const std::string& mime_type,
const std::string& view_id);
MimeHandlerViewFrameContainer(blink::WebLocalFrame* web_frame,
const GURL& resource_url,
const std::string& mime_type,
const std::string& view_id);
MimeHandlerViewFrameContainer(const blink::WebElement& plugin_element,
const GURL& resource_url,
const std::string& mime_type,
const content::WebPluginInfo& plugin_info,
int32_t element_instance_id);
~MimeHandlerViewFrameContainer() override;
// MimeHandlerViewContainerBase overrides.
......@@ -58,13 +72,6 @@ class MimeHandlerViewFrameContainer : public MimeHandlerViewContainerBase {
bool show_dialog,
SetShowBeforeUnloadDialogCallback callback) override;
// Returns true if the container is considered as "embedded". A non-embedded
// MimeHandlerViewFrameContainer is the one which is created as a result of
// navigating a frame (either <iframe> or top-level) to a corresponding
// MimeHandlerView mimetype. For such containers there is no need to request
// the resource immediately.
bool IsEmbedded() const;
void OnMessageReceived(const IPC::Message& message);
blink::WebElement plugin_element_;
......
......@@ -258,8 +258,10 @@ Document* DOMImplementation::createDocument(const String& type,
// We do not want QuickTime to take over all image types, obviously.
if ((type == "application/pdf" || type == "text/pdf") && plugin_data &&
plugin_data->SupportsMimeType(type)) {
return PluginDocument::Create(
init, plugin_data->PluginBackgroundColorForMimeType(type));
return RuntimeEnabledFeatures::MimeHandlerViewInCrossProcessFrameEnabled()
? HTMLDocument::Create(init)
: PluginDocument::Create(
init, plugin_data->PluginBackgroundColorForMimeType(type));
}
// multipart/x-mixed-replace is only supported for images.
if (MIMETypeRegistry::IsSupportedImageResourceMIMEType(type) ||
......
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