Commit 19c1d109 authored by raymes's avatar raymes Committed by Commit bot

Add PostMessage support for MimeHandlerView

This adds PostMessage support for MimeHandlerView allow sites that embed extension mime handlers to communicate with them.

BUG=415858

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

Cr-Commit-Position: refs/heads/master@{#309512}
parent 6e473cb7
...@@ -4,10 +4,17 @@ ...@@ -4,10 +4,17 @@
#include "content/public/renderer/browser_plugin_delegate.h" #include "content/public/renderer/browser_plugin_delegate.h"
#include "v8/include/v8.h"
namespace content { namespace content {
bool BrowserPluginDelegate::OnMessageReceived(const IPC::Message& message) { bool BrowserPluginDelegate::OnMessageReceived(const IPC::Message& message) {
return false; return false;
} }
v8::Local<v8::Object> BrowserPluginDelegate::V8ScriptableObject(
v8::Isolate* isolate) {
return v8::Local<v8::Object>();
}
} // namespace content } // namespace content
...@@ -10,6 +10,12 @@ ...@@ -10,6 +10,12 @@
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "ipc/ipc_message.h" #include "ipc/ipc_message.h"
namespace v8 {
class Isolate;
class Object;
template<typename T> class Local;
} // namespace v8
namespace content { namespace content {
class RenderFrame; class RenderFrame;
...@@ -38,6 +44,9 @@ class CONTENT_EXPORT BrowserPluginDelegate { ...@@ -38,6 +44,9 @@ class CONTENT_EXPORT BrowserPluginDelegate {
// Called when a message is received. Returns true iff the message was // Called when a message is received. Returns true iff the message was
// handled. // handled.
virtual bool OnMessageReceived(const IPC::Message& message); virtual bool OnMessageReceived(const IPC::Message& message);
// Return a scriptable object for the plugin.
virtual v8::Local<v8::Object> V8ScriptableObject(v8::Isolate* isolate);
}; };
} // namespace content } // namespace content
......
...@@ -374,6 +374,10 @@ void BrowserPlugin::destroy() { ...@@ -374,6 +374,10 @@ void BrowserPlugin::destroy() {
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
} }
v8::Local<v8::Object> BrowserPlugin::v8ScriptableObject(v8::Isolate* isolate) {
return delegate_->V8ScriptableObject(isolate);
}
bool BrowserPlugin::supportsKeyboardFocus() const { bool BrowserPlugin::supportsKeyboardFocus() const {
return true; return true;
} }
......
...@@ -78,6 +78,8 @@ class CONTENT_EXPORT BrowserPlugin : ...@@ -78,6 +78,8 @@ class CONTENT_EXPORT BrowserPlugin :
virtual blink::WebPluginContainer* container() const override; virtual blink::WebPluginContainer* container() const override;
virtual bool initialize(blink::WebPluginContainer* container) override; virtual bool initialize(blink::WebPluginContainer* container) override;
virtual void destroy() override; virtual void destroy() override;
virtual v8::Local<v8::Object> v8ScriptableObject(
v8::Isolate* isolate) override;
virtual bool supportsKeyboardFocus() const override; virtual bool supportsKeyboardFocus() const override;
virtual bool supportsEditCommands() const override; virtual bool supportsEditCommands() const override;
virtual bool supportsInputMethod() const override; virtual bool supportsInputMethod() const override;
......
...@@ -5,20 +5,83 @@ ...@@ -5,20 +5,83 @@
#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h" #include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
#include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "extensions/common/extension_messages.h" #include "extensions/common/extension_messages.h"
#include "extensions/common/guest_view/guest_view_constants.h" #include "extensions/common/guest_view/guest_view_constants.h"
#include "gin/arguments.h"
#include "gin/dictionary.h"
#include "gin/handle.h"
#include "gin/interceptor.h"
#include "gin/object_template_builder.h"
#include "gin/wrappable.h"
#include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
namespace extensions { namespace extensions {
namespace {
const char kPostMessageName[] = "postMessage";
// The gin-backed scriptable object which is exposed by the BrowserPlugin for
// MimeHandlerViewContainer. This currently only implements "postMessage".
class ScriptableObject : public gin::Wrappable<ScriptableObject>,
public gin::NamedPropertyInterceptor {
public:
static gin::WrapperInfo kWrapperInfo;
static v8::Handle<v8::Object> Create(
v8::Isolate* isolate,
base::WeakPtr<MimeHandlerViewContainer> container) {
ScriptableObject* scriptable_object =
new ScriptableObject(isolate, container);
return gin::CreateHandle(isolate, scriptable_object).ToV8()->ToObject();
}
// gin::NamedPropertyInterceptor
v8::Local<v8::Value> GetNamedProperty(
v8::Isolate* isolate,
const std::string& identifier) override {
if (identifier == kPostMessageName) {
return gin::CreateFunctionTemplate(isolate,
base::Bind(&MimeHandlerViewContainer::PostMessage,
container_, isolate))->GetFunction();
}
return v8::Local<v8::Value>();
}
private:
ScriptableObject(v8::Isolate* isolate,
base::WeakPtr<MimeHandlerViewContainer> container)
: gin::NamedPropertyInterceptor(isolate, this),
container_(container) {}
virtual ~ScriptableObject() {}
// gin::Wrappable
virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override {
return gin::Wrappable<ScriptableObject>::GetObjectTemplateBuilder(isolate)
.AddNamedPropertyInterceptor();
}
base::WeakPtr<MimeHandlerViewContainer> container_;
};
// static
gin::WrapperInfo ScriptableObject::kWrapperInfo = { gin::kEmbedderNativeGin };
} // namespace
MimeHandlerViewContainer::MimeHandlerViewContainer( MimeHandlerViewContainer::MimeHandlerViewContainer(
content::RenderFrame* render_frame, content::RenderFrame* render_frame,
const std::string& mime_type, const std::string& mime_type,
const GURL& original_url) const GURL& original_url)
: GuestViewContainer(render_frame), : GuestViewContainer(render_frame),
mime_type_(mime_type), mime_type_(mime_type),
original_url_(original_url) { original_url_(original_url),
guest_proxy_routing_id_(-1),
weak_factory_(this) {
DCHECK(!mime_type_.empty()); DCHECK(!mime_type_.empty());
is_embedded_ = !render_frame->GetWebFrame()->document().isPluginDocument(); is_embedded_ = !render_frame->GetWebFrame()->document().isPluginDocument();
} }
...@@ -28,6 +91,20 @@ MimeHandlerViewContainer::~MimeHandlerViewContainer() { ...@@ -28,6 +91,20 @@ MimeHandlerViewContainer::~MimeHandlerViewContainer() {
loader_->cancel(); loader_->cancel();
} }
void MimeHandlerViewContainer::Ready() {
blink::WebFrame* frame = render_frame()->GetWebFrame();
blink::WebURLLoaderOptions options;
// The embedded plugin is allowed to be cross-origin.
options.crossOriginRequestPolicy =
blink::WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
DCHECK(!loader_);
loader_.reset(frame->createAssociatedURLLoader(options));
blink::WebURLRequest request(original_url_);
request.setRequestContext(blink::WebURLRequest::RequestContextObject);
loader_->loadAsynchronously(request, this);
}
void MimeHandlerViewContainer::DidFinishLoading() { void MimeHandlerViewContainer::DidFinishLoading() {
DCHECK(!is_embedded_); DCHECK(!is_embedded_);
CreateMimeHandlerViewGuest(); CreateMimeHandlerViewGuest();
...@@ -43,23 +120,20 @@ bool MimeHandlerViewContainer::OnMessageReceived(const IPC::Message& message) { ...@@ -43,23 +120,20 @@ bool MimeHandlerViewContainer::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(MimeHandlerViewContainer, message) IPC_BEGIN_MESSAGE_MAP(MimeHandlerViewContainer, message)
IPC_MESSAGE_HANDLER(ExtensionMsg_CreateMimeHandlerViewGuestACK, IPC_MESSAGE_HANDLER(ExtensionMsg_CreateMimeHandlerViewGuestACK,
OnCreateMimeHandlerViewGuestACK) OnCreateMimeHandlerViewGuestACK)
IPC_MESSAGE_HANDLER(ExtensionMsg_GuestAttached, OnGuestAttached)
IPC_MESSAGE_UNHANDLED(handled = false) IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP() IPC_END_MESSAGE_MAP()
return handled; return handled;
} }
void MimeHandlerViewContainer::Ready() { v8::Local<v8::Object> MimeHandlerViewContainer::V8ScriptableObject(
blink::WebFrame* frame = render_frame()->GetWebFrame(); v8::Isolate* isolate) {
blink::WebURLLoaderOptions options; if (scriptable_object_.IsEmpty()) {
// The embedded plugin is allowed to be cross-origin. v8::Local<v8::Object> object =
options.crossOriginRequestPolicy = ScriptableObject::Create(isolate, weak_factory_.GetWeakPtr());
blink::WebURLLoaderOptions::CrossOriginRequestPolicyAllow; scriptable_object_.reset(object);
DCHECK(!loader_); }
loader_.reset(frame->createAssociatedURLLoader(options)); return scriptable_object_.NewHandle(isolate);
blink::WebURLRequest request(original_url_);
request.setRequestContext(blink::WebURLRequest::RequestContextObject);
loader_->loadAsynchronously(request, this);
} }
void MimeHandlerViewContainer::didReceiveData(blink::WebURLLoader* /* unused */, void MimeHandlerViewContainer::didReceiveData(blink::WebURLLoader* /* unused */,
...@@ -77,6 +151,34 @@ void MimeHandlerViewContainer::didFinishLoading( ...@@ -77,6 +151,34 @@ void MimeHandlerViewContainer::didFinishLoading(
CreateMimeHandlerViewGuest(); CreateMimeHandlerViewGuest();
} }
void MimeHandlerViewContainer::PostMessage(v8::Isolate* isolate,
v8::Handle<v8::Value> message) {
content::RenderView* guest_proxy_render_view =
content::RenderView::FromRoutingID(guest_proxy_routing_id_);
if (!guest_proxy_render_view)
return;
blink::WebFrame* guest_proxy_frame =
guest_proxy_render_view->GetWebView()->mainFrame();
if (!guest_proxy_frame)
return;
v8::Local<v8::Object> guest_proxy_window =
guest_proxy_frame->mainWorldScriptContext()->Global();
gin::Dictionary window_object(isolate, guest_proxy_window);
v8::Handle<v8::Function> post_message;
if (!window_object.Get(std::string(kPostMessageName), &post_message))
return;
v8::Handle<v8::Value> args[] = {
message,
// Post the message to any domain inside the browser plugin. The embedder
// should already know what is embedded.
gin::StringToV8(isolate, "*")
};
post_message.As<v8::Function>()->Call(
guest_proxy_window, arraysize(args), args);
}
void MimeHandlerViewContainer::OnCreateMimeHandlerViewGuestACK( void MimeHandlerViewContainer::OnCreateMimeHandlerViewGuestACK(
int element_instance_id) { int element_instance_id) {
DCHECK_NE(this->element_instance_id(), guestview::kInstanceIDNone); DCHECK_NE(this->element_instance_id(), guestview::kInstanceIDNone);
...@@ -84,6 +186,13 @@ void MimeHandlerViewContainer::OnCreateMimeHandlerViewGuestACK( ...@@ -84,6 +186,13 @@ void MimeHandlerViewContainer::OnCreateMimeHandlerViewGuestACK(
render_frame()->AttachGuest(element_instance_id); render_frame()->AttachGuest(element_instance_id);
} }
void MimeHandlerViewContainer::OnGuestAttached(int /* unused */,
int guest_proxy_routing_id) {
// Save the RenderView routing ID of the guest here so it can be used to route
// PostMessage calls.
guest_proxy_routing_id_ = guest_proxy_routing_id;
}
void MimeHandlerViewContainer::CreateMimeHandlerViewGuest() { void MimeHandlerViewContainer::CreateMimeHandlerViewGuest() {
// The loader has completed loading |html_string_| so we can dispose it. // The loader has completed loading |html_string_| so we can dispose it.
loader_.reset(); loader_.reset();
......
...@@ -5,10 +5,13 @@ ...@@ -5,10 +5,13 @@
#ifndef EXTENSIONS_RENDERER_GUEST_VIEW_MIME_HANDLER_VIEW_CONTAINER_H_ #ifndef EXTENSIONS_RENDERER_GUEST_VIEW_MIME_HANDLER_VIEW_CONTAINER_H_
#define EXTENSIONS_RENDERER_GUEST_VIEW_MIME_HANDLER_VIEW_CONTAINER_H_ #define EXTENSIONS_RENDERER_GUEST_VIEW_MIME_HANDLER_VIEW_CONTAINER_H_
#include "base/memory/weak_ptr.h"
#include "extensions/renderer/guest_view/guest_view_container.h" #include "extensions/renderer/guest_view/guest_view_container.h"
#include "extensions/renderer/scoped_persistent.h"
#include "third_party/WebKit/public/platform/WebURLLoader.h" #include "third_party/WebKit/public/platform/WebURLLoader.h"
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h" #include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
#include "url/gurl.h" #include "url/gurl.h"
#include "v8/include/v8.h"
namespace extensions { namespace extensions {
...@@ -37,10 +40,11 @@ class MimeHandlerViewContainer : public GuestViewContainer, ...@@ -37,10 +40,11 @@ class MimeHandlerViewContainer : public GuestViewContainer,
~MimeHandlerViewContainer() override; ~MimeHandlerViewContainer() override;
// BrowserPluginDelegate implementation. // BrowserPluginDelegate implementation.
void Ready() override;
void DidFinishLoading() override; void DidFinishLoading() override;
void DidReceiveData(const char* data, int data_length) override; void DidReceiveData(const char* data, int data_length) override;
bool OnMessageReceived(const IPC::Message& message) override; bool OnMessageReceived(const IPC::Message& message) override;
void Ready() override; v8::Local<v8::Object> V8ScriptableObject(v8::Isolate*) override;
// WebURLLoaderClient overrides. // WebURLLoaderClient overrides.
void didReceiveData(blink::WebURLLoader* loader, void didReceiveData(blink::WebURLLoader* loader,
...@@ -51,9 +55,15 @@ class MimeHandlerViewContainer : public GuestViewContainer, ...@@ -51,9 +55,15 @@ class MimeHandlerViewContainer : public GuestViewContainer,
double finish_time, double finish_time,
int64_t total_encoded_data_length) override; int64_t total_encoded_data_length) override;
// Post a JavaScript message to the guest.
void PostMessage(v8::Isolate* isolate,
v8::Handle<v8::Value> message);
private: private:
// Message handlers. // Message handlers.
void OnCreateMimeHandlerViewGuestACK(int element_instance_id); void OnCreateMimeHandlerViewGuestACK(int element_instance_id);
void OnGuestAttached(int element_instance_id,
int guest_proxy_routing_id);
void CreateMimeHandlerViewGuest(); void CreateMimeHandlerViewGuest();
...@@ -69,10 +79,18 @@ class MimeHandlerViewContainer : public GuestViewContainer, ...@@ -69,10 +79,18 @@ class MimeHandlerViewContainer : public GuestViewContainer,
// The original URL of the plugin. // The original URL of the plugin.
GURL original_url_; GURL original_url_;
// The RenderView routing ID of the guest.
int guest_proxy_routing_id_;
// A URL loader to load the |original_url_| when the plugin is embedded. In // A URL loader to load the |original_url_| when the plugin is embedded. In
// the embedded case, no URL request is made automatically. // the embedded case, no URL request is made automatically.
scoped_ptr<blink::WebURLLoader> loader_; scoped_ptr<blink::WebURLLoader> loader_;
// The scriptable object that backs the plugin.
ScopedPersistent<v8::Object> scriptable_object_;
base::WeakPtrFactory<MimeHandlerViewContainer> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MimeHandlerViewContainer); DISALLOW_COPY_AND_ASSIGN(MimeHandlerViewContainer);
}; };
......
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