Commit 212c6daa authored by fsamuel's avatar fsamuel Committed by Commit bot

Move ContentWindow from BrowserPlugin To GuestView

This CL plumbs out the swapped out RenderView's routing ID out to the content embedder which then uses it to expose its contentWindow to an optional callback in the AttachGuest API Method.

This patch also makes it fairly trivial to support a contentWindow in other GuestViews.

BUG=330264

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

Cr-Commit-Position: refs/heads/master@{#295477}
parent 271b5ac0
...@@ -238,12 +238,6 @@ void BrowserPluginGuest::Initialize( ...@@ -238,12 +238,6 @@ void BrowserPluginGuest::Initialize(
OnResizeGuest(browser_plugin_instance_id_, params.resize_guest_params); OnResizeGuest(browser_plugin_instance_id_, params.resize_guest_params);
// Create a swapped out RenderView for the guest in the embedder render
// process, so that the embedder can access the guest's window object.
int guest_routing_id =
GetWebContents()->CreateSwappedOutRenderView(
embedder_web_contents_->GetSiteInstance());
// TODO(chrishtr): this code is wrong. The navigate_on_drag_drop field will // TODO(chrishtr): this code is wrong. The navigate_on_drag_drop field will
// be reset again the next time preferences are updated. // be reset again the next time preferences are updated.
WebPreferences prefs = WebPreferences prefs =
...@@ -262,9 +256,6 @@ void BrowserPluginGuest::Initialize( ...@@ -262,9 +256,6 @@ void BrowserPluginGuest::Initialize(
// Inform the embedder of the guest's attachment. // Inform the embedder of the guest's attachment.
SendMessageToEmbedder( SendMessageToEmbedder(
new BrowserPluginMsg_Attach_ACK(browser_plugin_instance_id_)); new BrowserPluginMsg_Attach_ACK(browser_plugin_instance_id_));
SendMessageToEmbedder(new BrowserPluginMsg_GuestContentWindowReady(
browser_plugin_instance_id_, guest_routing_id));
} }
BrowserPluginGuest::~BrowserPluginGuest() { BrowserPluginGuest::~BrowserPluginGuest() {
...@@ -558,7 +549,7 @@ void BrowserPluginGuest::Attach( ...@@ -558,7 +549,7 @@ void BrowserPluginGuest::Attach(
if (attached()) if (attached())
return; return;
delegate_->WillAttach(embedder_web_contents); delegate_->WillAttach(embedder_web_contents, browser_plugin_instance_id);
// If a RenderView has already been created for this new window, then we need // If a RenderView has already been created for this new window, then we need
// to initialize the browser-side state now so that the RenderFrameHostManager // to initialize the browser-side state now so that the RenderFrameHostManager
...@@ -575,7 +566,13 @@ void BrowserPluginGuest::Attach( ...@@ -575,7 +566,13 @@ void BrowserPluginGuest::Attach(
SendQueuedMessages(); SendQueuedMessages();
delegate_->DidAttach(); // Create a swapped out RenderView for the guest in the embedder render
// process, so that the embedder can access the guest's window object.
int guest_routing_id =
GetWebContents()->CreateSwappedOutRenderView(
embedder_web_contents_->GetSiteInstance());
delegate_->DidAttach(guest_routing_id);
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached")); RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
} }
......
...@@ -8,24 +8,11 @@ namespace content { ...@@ -8,24 +8,11 @@ namespace content {
namespace browser_plugin { namespace browser_plugin {
// Internal method bindings.
const char kMethodInternalAttach[] = "-internal-attach";
// Attributes. // Attributes.
const char kAttributeAllowTransparency[] = "allowtransparency"; const char kAttributeAllowTransparency[] = "allowtransparency";
const char kAttributeContentWindow[] = "contentWindow";
const char kAttributeSrc[] = "src";
// Parameters/properties on events.
const char kWindowID[] = "windowId";
// Error messages.
const char kErrorCannotRemovePartition[] =
"Cannot remove partition attribute after navigating.";
// Other. // Other.
const int kInstanceIDNone = 0; const int kInstanceIDNone = 0;
const int kInvalidPermissionRequestID = 0;
} // namespace browser_plugin } // namespace browser_plugin
......
...@@ -9,23 +9,11 @@ namespace content { ...@@ -9,23 +9,11 @@ namespace content {
namespace browser_plugin { namespace browser_plugin {
// Internal method bindings.
extern const char kMethodInternalAttach[];
// Attributes. // Attributes.
extern const char kAttributeAllowTransparency[]; extern const char kAttributeAllowTransparency[];
extern const char kAttributeContentWindow[];
extern const char kAttributeSrc[];
// Parameters/properties on events.
extern const char kWindowID[];
// Error messages.
extern const char kErrorCannotRemovePartition[];
// Other. // Other.
extern const int kInstanceIDNone; extern const int kInstanceIDNone;
extern const int kInvalidPermissionRequestID;
} // namespace browser_plugin } // namespace browser_plugin
......
...@@ -181,12 +181,6 @@ IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_ResizeGuest, ...@@ -181,12 +181,6 @@ IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_ResizeGuest,
IPC_MESSAGE_CONTROL1(BrowserPluginMsg_Attach_ACK, IPC_MESSAGE_CONTROL1(BrowserPluginMsg_Attach_ACK,
int /* browser_plugin_instance_id */) int /* browser_plugin_instance_id */)
// Once the swapped out guest RenderView has been created in the embedder render
// process, the browser process informs the embedder of its routing ID.
IPC_MESSAGE_CONTROL2(BrowserPluginMsg_GuestContentWindowReady,
int /* browser_plugin_instance_id */,
int /* source_routing_id */)
// When the guest crashes, the browser process informs the embedder through this // When the guest crashes, the browser process informs the embedder through this
// message. // message.
IPC_MESSAGE_CONTROL1(BrowserPluginMsg_GuestGone, IPC_MESSAGE_CONTROL1(BrowserPluginMsg_GuestGone,
......
...@@ -27,14 +27,18 @@ class CONTENT_EXPORT BrowserPluginGuestDelegate { ...@@ -27,14 +27,18 @@ class CONTENT_EXPORT BrowserPluginGuestDelegate {
virtual ~BrowserPluginGuestDelegate() {} virtual ~BrowserPluginGuestDelegate() {}
// Notification that the embedder will begin attachment. This is called // Notification that the embedder will begin attachment. This is called
// prior to resuming resource loads. // prior to resuming resource loads. |element_instance_id| uniquely identifies
virtual void WillAttach(content::WebContents* embedder_web_contents) {} // the element that will serve as a container for the guest.
virtual void WillAttach(content::WebContents* embedder_web_contents,
int element_instance_id) {}
virtual WebContents* CreateNewGuestWindow( virtual WebContents* CreateNewGuestWindow(
const WebContents::CreateParams& create_params); const WebContents::CreateParams& create_params);
// Notification that the embedder has completed attachment. // Notification that the embedder has completed attachment. The
virtual void DidAttach() {} // |guest_proxy_routing_id| is the routing ID for the RenderView in the
// embedder that will serve as a contentWindow proxy for the guest.
virtual void DidAttach(int guest_proxy_routing_id) {}
// Notification that the BrowserPlugin has resized. // Notification that the BrowserPlugin has resized.
virtual void ElementSizeChanged(const gfx::Size& old_size, virtual void ElementSizeChanged(const gfx::Size& old_size,
......
...@@ -107,8 +107,6 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) { ...@@ -107,8 +107,6 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
OnCompositorFrameSwapped(message)) OnCompositorFrameSwapped(message))
IPC_MESSAGE_HANDLER(BrowserPluginMsg_CopyFromCompositingSurface, IPC_MESSAGE_HANDLER(BrowserPluginMsg_CopyFromCompositingSurface,
OnCopyFromCompositingSurface) OnCopyFromCompositingSurface)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestContentWindowReady,
OnGuestContentWindowReady)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone) IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor, OnSetCursor) IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor, OnSetCursor)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMouseLock, OnSetMouseLock) IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMouseLock, OnSetMouseLock)
...@@ -275,12 +273,6 @@ void BrowserPlugin::OnCopyFromCompositingSurface(int browser_plugin_instance_id, ...@@ -275,12 +273,6 @@ void BrowserPlugin::OnCopyFromCompositingSurface(int browser_plugin_instance_id,
dest_size); dest_size);
} }
void BrowserPlugin::OnGuestContentWindowReady(int browser_plugin_instance_id,
int content_window_routing_id) {
DCHECK(content_window_routing_id != MSG_ROUTING_NONE);
content_window_routing_id_ = content_window_routing_id;
}
void BrowserPlugin::OnGuestGone(int browser_plugin_instance_id) { void BrowserPlugin::OnGuestGone(int browser_plugin_instance_id) {
guest_crashed_ = true; guest_crashed_ = true;
...@@ -327,17 +319,6 @@ void BrowserPlugin::OnShouldAcceptTouchEvents(int browser_plugin_instance_id, ...@@ -327,17 +319,6 @@ void BrowserPlugin::OnShouldAcceptTouchEvents(int browser_plugin_instance_id,
} }
} }
NPObject* BrowserPlugin::GetContentWindow() const {
if (content_window_routing_id_ == MSG_ROUTING_NONE)
return NULL;
RenderViewImpl* guest_render_view = RenderViewImpl::FromRoutingID(
content_window_routing_id_);
if (!guest_render_view)
return NULL;
blink::WebFrame* guest_frame = guest_render_view->GetWebView()->mainFrame();
return guest_frame->windowObject();
}
void BrowserPlugin::ShowSadGraphic() { void BrowserPlugin::ShowSadGraphic() {
// If the BrowserPlugin is scheduled to be deleted, then container_ will be // If the BrowserPlugin is scheduled to be deleted, then container_ will be
// NULL so we shouldn't attempt to access it. // NULL so we shouldn't attempt to access it.
...@@ -519,7 +500,6 @@ bool BrowserPlugin::ShouldForwardToBrowserPlugin( ...@@ -519,7 +500,6 @@ bool BrowserPlugin::ShouldForwardToBrowserPlugin(
case BrowserPluginMsg_BuffersSwapped::ID: case BrowserPluginMsg_BuffersSwapped::ID:
case BrowserPluginMsg_CompositorFrameSwapped::ID: case BrowserPluginMsg_CompositorFrameSwapped::ID:
case BrowserPluginMsg_CopyFromCompositingSurface::ID: case BrowserPluginMsg_CopyFromCompositingSurface::ID:
case BrowserPluginMsg_GuestContentWindowReady::ID:
case BrowserPluginMsg_GuestGone::ID: case BrowserPluginMsg_GuestGone::ID:
case BrowserPluginMsg_SetCursor::ID: case BrowserPluginMsg_SetCursor::ID:
case BrowserPluginMsg_SetMouseLock::ID: case BrowserPluginMsg_SetMouseLock::ID:
......
...@@ -63,9 +63,6 @@ class CONTENT_EXPORT BrowserPlugin : ...@@ -63,9 +63,6 @@ class CONTENT_EXPORT BrowserPlugin :
// BrowserPlugin accordingly. // BrowserPlugin accordingly.
void ParseAllowTransparencyAttribute(); void ParseAllowTransparencyAttribute();
// Get the guest's DOMWindow proxy.
NPObject* GetContentWindow() const;
// Returns whether the guest process has crashed. // Returns whether the guest process has crashed.
bool guest_crashed() const { return guest_crashed_; } bool guest_crashed() const { return guest_crashed_; }
...@@ -199,8 +196,6 @@ class CONTENT_EXPORT BrowserPlugin : ...@@ -199,8 +196,6 @@ class CONTENT_EXPORT BrowserPlugin :
int request_id, int request_id,
gfx::Rect source_rect, gfx::Rect source_rect,
gfx::Size dest_size); gfx::Size dest_size);
void OnGuestContentWindowReady(int instance_id,
int content_window_routing_id);
void OnGuestGone(int instance_id); void OnGuestGone(int instance_id);
void OnSetCursor(int instance_id, const WebCursor& cursor); void OnSetCursor(int instance_id, const WebCursor& cursor);
void OnSetMouseLock(int instance_id, bool enable); void OnSetMouseLock(int instance_id, bool enable);
......
...@@ -188,32 +188,6 @@ class BrowserPluginPropertyBindingAllowTransparency ...@@ -188,32 +188,6 @@ class BrowserPluginPropertyBindingAllowTransparency
DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAllowTransparency); DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAllowTransparency);
}; };
class BrowserPluginPropertyBindingContentWindow
: public BrowserPluginPropertyBinding {
public:
BrowserPluginPropertyBindingContentWindow()
: BrowserPluginPropertyBinding(browser_plugin::kAttributeContentWindow) {
}
virtual bool GetProperty(BrowserPluginBindings* bindings,
NPVariant* result) OVERRIDE {
NPObject* obj = bindings->instance()->GetContentWindow();
if (obj) {
result->type = NPVariantType_Object;
result->value.objectValue = WebBindings::retainObject(obj);
}
return true;
}
virtual bool SetProperty(BrowserPluginBindings* bindings,
NPObject* np_obj,
const NPVariant* variant) OVERRIDE {
return false;
}
virtual void RemoveProperty(BrowserPluginBindings* bindings,
NPObject* np_obj) OVERRIDE {}
private:
DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingContentWindow);
};
// BrowserPluginBindings ------------------------------------------------------ // BrowserPluginBindings ------------------------------------------------------
...@@ -235,7 +209,6 @@ BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance) ...@@ -235,7 +209,6 @@ BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance)
property_bindings_.push_back( property_bindings_.push_back(
new BrowserPluginPropertyBindingAllowTransparency); new BrowserPluginPropertyBindingAllowTransparency);
property_bindings_.push_back(new BrowserPluginPropertyBindingContentWindow);
} }
BrowserPluginBindings::~BrowserPluginBindings() { BrowserPluginBindings::~BrowserPluginBindings() {
......
...@@ -36,11 +36,6 @@ class BrowserPluginBindings { ...@@ -36,11 +36,6 @@ class BrowserPluginBindings {
bool HasMethod(NPIdentifier name) const; bool HasMethod(NPIdentifier name) const;
bool InvokeMethod(NPIdentifier name,
const NPVariant* args,
uint32 arg_count,
NPVariant* result);
bool HasProperty(NPIdentifier name) const; bool HasProperty(NPIdentifier name) const;
bool SetProperty(NPObject* np_obj, bool SetProperty(NPObject* np_obj,
NPIdentifier name, NPIdentifier name,
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h"
#include "extensions/browser/process_map.h" #include "extensions/browser/process_map.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/features/feature.h" #include "extensions/common/features/feature.h"
#include "extensions/common/features/feature_provider.h" #include "extensions/common/features/feature_provider.h"
#include "extensions/common/guest_view/guest_view_constants.h" #include "extensions/common/guest_view/guest_view_constants.h"
...@@ -105,6 +106,7 @@ GuestViewBase::GuestViewBase(content::BrowserContext* browser_context, ...@@ -105,6 +106,7 @@ GuestViewBase::GuestViewBase(content::BrowserContext* browser_context,
browser_context_(browser_context), browser_context_(browser_context),
guest_instance_id_(guest_instance_id), guest_instance_id_(guest_instance_id),
view_instance_id_(guestview::kInstanceIDNone), view_instance_id_(guestview::kInstanceIDNone),
element_instance_id_(guestview::kInstanceIDNone),
initialized_(false), initialized_(false),
auto_size_enabled_(false), auto_size_enabled_(false),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
...@@ -311,10 +313,16 @@ void GuestViewBase::Destroy() { ...@@ -311,10 +313,16 @@ void GuestViewBase::Destroy() {
delete web_contents(); delete web_contents();
} }
void GuestViewBase::DidAttach() { void GuestViewBase::DidAttach(int guest_proxy_routing_id) {
// Give the derived class an opportunity to perform some actions. // Give the derived class an opportunity to perform some actions.
DidAttachToEmbedder(); DidAttachToEmbedder();
// Inform the associated GuestViewContainer that the contentWindow is ready.
embedder_web_contents()->Send(new ExtensionMsg_GuestAttached(
embedder_web_contents()->GetMainFrame()->GetRoutingID(),
element_instance_id_,
guest_proxy_routing_id));
SendQueuedEvents(); SendQueuedEvents();
} }
...@@ -350,7 +358,8 @@ void GuestViewBase::RegisterDestructionCallback( ...@@ -350,7 +358,8 @@ void GuestViewBase::RegisterDestructionCallback(
destruction_callback_ = callback; destruction_callback_ = callback;
} }
void GuestViewBase::WillAttach(content::WebContents* embedder_web_contents) { void GuestViewBase::WillAttach(content::WebContents* embedder_web_contents,
int element_instance_id) {
// After attachment, this GuestViewBase's lifetime is restricted to the // After attachment, this GuestViewBase's lifetime is restricted to the
// lifetime of its embedder WebContents. Observing the RenderProcessHost // lifetime of its embedder WebContents. Observing the RenderProcessHost
// of the embedder is no longer necessary. // of the embedder is no longer necessary.
...@@ -358,6 +367,7 @@ void GuestViewBase::WillAttach(content::WebContents* embedder_web_contents) { ...@@ -358,6 +367,7 @@ void GuestViewBase::WillAttach(content::WebContents* embedder_web_contents) {
embedder_web_contents_ = embedder_web_contents; embedder_web_contents_ = embedder_web_contents;
embedder_web_contents_observer_.reset( embedder_web_contents_observer_.reset(
new EmbedderWebContentsObserver(this)); new EmbedderWebContentsObserver(this));
element_instance_id_ = element_instance_id;
WillAttachToEmbedder(); WillAttachToEmbedder();
} }
......
...@@ -235,7 +235,7 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, ...@@ -235,7 +235,7 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
// BrowserPluginGuestDelegate implementation. // BrowserPluginGuestDelegate implementation.
virtual void Destroy() OVERRIDE FINAL; virtual void Destroy() OVERRIDE FINAL;
virtual void DidAttach() OVERRIDE FINAL; virtual void DidAttach(int guest_proxy_routing_id) OVERRIDE FINAL;
virtual void ElementSizeChanged(const gfx::Size& old_size, virtual void ElementSizeChanged(const gfx::Size& old_size,
const gfx::Size& new_size) OVERRIDE FINAL; const gfx::Size& new_size) OVERRIDE FINAL;
virtual void GuestSizeChanged(const gfx::Size& old_size, virtual void GuestSizeChanged(const gfx::Size& old_size,
...@@ -243,7 +243,8 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, ...@@ -243,7 +243,8 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
virtual void RegisterDestructionCallback( virtual void RegisterDestructionCallback(
const DestructionCallback& callback) OVERRIDE FINAL; const DestructionCallback& callback) OVERRIDE FINAL;
virtual void WillAttach( virtual void WillAttach(
content::WebContents* embedder_web_contents) OVERRIDE FINAL; content::WebContents* embedder_web_contents,
int browser_plugin_instance_id) OVERRIDE FINAL;
// Dispatches an event |event_name| to the embedder with the |event| fields. // Dispatches an event |event_name| to the embedder with the |event| fields.
void DispatchEventToEmbedder(Event* event); void DispatchEventToEmbedder(Event* event);
...@@ -288,13 +289,19 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, ...@@ -288,13 +289,19 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
std::string embedder_extension_id_; std::string embedder_extension_id_;
int embedder_render_process_id_; int embedder_render_process_id_;
content::BrowserContext* browser_context_; content::BrowserContext* browser_context_;
// |guest_instance_id_| is a profile-wide unique identifier for a guest // |guest_instance_id_| is a profile-wide unique identifier for a guest
// WebContents. // WebContents.
const int guest_instance_id_; const int guest_instance_id_;
// |view_instance_id_| is an identifier that's unique within a particular // |view_instance_id_| is an identifier that's unique within a particular
// embedder RenderViewHost for a particular <*view> instance. // embedder RenderViewHost for a particular <*view> instance.
int view_instance_id_; int view_instance_id_;
// |element_instance_id_| is an identififer that's unique to a particular
// GuestViewContainer element.
int element_instance_id_;
bool initialized_; bool initialized_;
// This is a queue of Events that are destined to be sent to the embedder once // This is a queue of Events that are destined to be sent to the embedder once
......
...@@ -516,6 +516,12 @@ IPC_MESSAGE_CONTROL1(ExtensionMsg_TransferBlobs, ...@@ -516,6 +516,12 @@ IPC_MESSAGE_CONTROL1(ExtensionMsg_TransferBlobs,
IPC_MESSAGE_CONTROL1(ExtensionMsg_CreateMimeHandlerViewGuestACK, IPC_MESSAGE_CONTROL1(ExtensionMsg_CreateMimeHandlerViewGuestACK,
int /* element_instance_id */) int /* element_instance_id */)
// Once a RenderView proxy has been created for the guest in the embedder render
// process, this IPC informs the embedder of the proxy's routing ID.
IPC_MESSAGE_ROUTED2(ExtensionMsg_GuestAttached,
int /* element_instance_id */,
int /* source_routing_id */)
// Messages sent from the renderer to the browser. // Messages sent from the renderer to the browser.
// A renderer sends this message when an extension process starts an API // A renderer sends this message when an extension process starts an API
......
...@@ -6,8 +6,20 @@ ...@@ -6,8 +6,20 @@
#include "content/public/renderer/browser_plugin_delegate.h" #include "content/public/renderer/browser_plugin_delegate.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 "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
#include "third_party/WebKit/public/web/WebView.h"
namespace {
typedef std::pair<int, int> GuestViewID;
typedef std::map<GuestViewID, extensions::GuestViewContainer*>
GuestViewContainerMap;
static base::LazyInstance<GuestViewContainerMap> g_guest_view_container_map =
LAZY_INSTANCE_INITIALIZER;
} // namespace
namespace extensions { namespace extensions {
...@@ -17,14 +29,61 @@ GuestViewContainer::GuestViewContainer( ...@@ -17,14 +29,61 @@ GuestViewContainer::GuestViewContainer(
: content::BrowserPluginDelegate(render_frame, mime_type), : content::BrowserPluginDelegate(render_frame, mime_type),
content::RenderFrameObserver(render_frame), content::RenderFrameObserver(render_frame),
mime_type_(mime_type), mime_type_(mime_type),
element_instance_id_(guestview::kInstanceIDNone) { element_instance_id_(guestview::kInstanceIDNone),
render_view_routing_id_(render_frame->GetRenderView()->GetRoutingID()),
attached_(false),
attach_pending_(false),
isolate_(NULL) {
} }
GuestViewContainer::~GuestViewContainer() { GuestViewContainer::~GuestViewContainer() {
if (element_instance_id_ != guestview::kInstanceIDNone) {
g_guest_view_container_map.Get().erase(
GuestViewID(render_view_routing_id_, element_instance_id_));
}
}
GuestViewContainer* GuestViewContainer::FromID(int render_view_routing_id,
int element_instance_id) {
GuestViewContainerMap* guest_view_containers =
g_guest_view_container_map.Pointer();
GuestViewContainerMap::iterator it = guest_view_containers->find(
GuestViewID(render_view_routing_id, element_instance_id));
return it == guest_view_containers->end() ? NULL : it->second;
}
void GuestViewContainer::AttachGuest(int element_instance_id,
int guest_instance_id,
scoped_ptr<base::DictionaryValue> params,
v8::Handle<v8::Function> callback,
v8::Isolate* isolate) {
// GuestViewContainer supports reattachment (i.e. attached_ == true) but not
// while a current attach process is pending.
if (attach_pending_)
return;
// Step 1, send the attach params to chrome/.
render_frame()->Send(new ExtensionHostMsg_AttachGuest(render_view_routing_id_,
element_instance_id,
guest_instance_id,
*params));
// Step 2, attach plugin through content/.
render_frame()->AttachGuest(element_instance_id);
callback_.reset(callback);
isolate_ = isolate;
attach_pending_ = true;
} }
void GuestViewContainer::SetElementInstanceID(int element_instance_id) { void GuestViewContainer::SetElementInstanceID(int element_instance_id) {
GuestViewID guest_view_id(render_view_routing_id_, element_instance_id);
DCHECK_EQ(element_instance_id_, guestview::kInstanceIDNone);
DCHECK(g_guest_view_container_map.Get().find(guest_view_id) ==
g_guest_view_container_map.Get().end());
element_instance_id_ = element_instance_id; element_instance_id_ = element_instance_id;
g_guest_view_container_map.Get().insert(std::make_pair(guest_view_id, this));
} }
void GuestViewContainer::DidFinishLoading() { void GuestViewContainer::DidFinishLoading() {
...@@ -47,7 +106,7 @@ void GuestViewContainer::OnDestruct() { ...@@ -47,7 +106,7 @@ void GuestViewContainer::OnDestruct() {
} }
bool GuestViewContainer::OnMessageReceived(const IPC::Message& message) { bool GuestViewContainer::OnMessageReceived(const IPC::Message& message) {
if (message.type() != ExtensionMsg_CreateMimeHandlerViewGuestACK::ID) if (!ShouldHandleMessage(message))
return false; return false;
DCHECK_NE(element_instance_id_, guestview::kInstanceIDNone); DCHECK_NE(element_instance_id_, guestview::kInstanceIDNone);
...@@ -62,6 +121,7 @@ bool GuestViewContainer::OnMessageReceived(const IPC::Message& message) { ...@@ -62,6 +121,7 @@ bool GuestViewContainer::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(GuestViewContainer, message) IPC_BEGIN_MESSAGE_MAP(GuestViewContainer, 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;
...@@ -75,4 +135,52 @@ void GuestViewContainer::OnCreateMimeHandlerViewGuestACK( ...@@ -75,4 +135,52 @@ void GuestViewContainer::OnCreateMimeHandlerViewGuestACK(
render_frame()->AttachGuest(element_instance_id); render_frame()->AttachGuest(element_instance_id);
} }
void GuestViewContainer::OnGuestAttached(int element_instance_id,
int guest_routing_id) {
attached_ = true;
attach_pending_ = false;
// If we don't have a callback then there's nothing more to do.
if (callback_.IsEmpty())
return;
content::RenderView* guest_proxy_render_view =
content::RenderView::FromRoutingID(guest_routing_id);
// TODO(fsamuel): Should we be reporting an error to JavaScript or DCHECKing?
if (!guest_proxy_render_view)
return;
v8::HandleScope handle_scope(isolate_);
v8::Handle<v8::Function> callback = callback_.NewHandle(isolate_);
v8::Handle<v8::Context> context = callback->CreationContext();
if (context.IsEmpty())
return;
blink::WebFrame* frame = guest_proxy_render_view->GetWebView()->mainFrame();
v8::Local<v8::Value> window = frame->mainWorldScriptContext()->Global();
const int argc = 1;
v8::Handle<v8::Value> argv[argc] = { window };
v8::Context::Scope context_scope(context);
blink::WebScopedMicrotaskSuppression suppression;
// Call the AttachGuest API's callback with the guest proxy as the first
// parameter.
callback->Call(context->Global(), argc, argv);
callback_.reset();
}
// static
bool GuestViewContainer::ShouldHandleMessage(const IPC::Message& message) {
switch (message.type()) {
case ExtensionMsg_CreateMimeHandlerViewGuestACK::ID:
case ExtensionMsg_GuestAttached::ID:
return true;
default:
break;
}
return false;
}
} // namespace extensions } // namespace extensions
...@@ -5,14 +5,14 @@ ...@@ -5,14 +5,14 @@
#ifndef CHROME_RENDERER_GUEST_VIEW_GUEST_VIEW_CONTAINER_H_ #ifndef CHROME_RENDERER_GUEST_VIEW_GUEST_VIEW_CONTAINER_H_
#define CHROME_RENDERER_GUEST_VIEW_GUEST_VIEW_CONTAINER_H_ #define CHROME_RENDERER_GUEST_VIEW_GUEST_VIEW_CONTAINER_H_
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
#include "content/public/renderer/browser_plugin_delegate.h" #include "content/public/renderer/browser_plugin_delegate.h"
#include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_frame_observer.h"
#include "ipc/ipc_listener.h" #include "extensions/renderer/scoped_persistent.h"
namespace extensions { namespace extensions {
// TODO(lazyboy): This should live under /extensions.
class GuestViewContainer : public content::BrowserPluginDelegate, class GuestViewContainer : public content::BrowserPluginDelegate,
public content::RenderFrameObserver { public content::RenderFrameObserver {
public: public:
...@@ -20,6 +20,15 @@ class GuestViewContainer : public content::BrowserPluginDelegate, ...@@ -20,6 +20,15 @@ class GuestViewContainer : public content::BrowserPluginDelegate,
const std::string& mime_type); const std::string& mime_type);
virtual ~GuestViewContainer(); virtual ~GuestViewContainer();
static GuestViewContainer* FromID(int render_view_routing_id,
int element_instance_id);
void AttachGuest(int element_instance_id,
int guest_instance_id,
scoped_ptr<base::DictionaryValue> params,
v8::Handle<v8::Function> callback,
v8::Isolate* isolate);
// BrowserPluginDelegate implementation. // BrowserPluginDelegate implementation.
virtual void SetElementInstanceID(int element_instance_id) OVERRIDE; virtual void SetElementInstanceID(int element_instance_id) OVERRIDE;
virtual void DidFinishLoading() OVERRIDE; virtual void DidFinishLoading() OVERRIDE;
...@@ -31,10 +40,22 @@ class GuestViewContainer : public content::BrowserPluginDelegate, ...@@ -31,10 +40,22 @@ class GuestViewContainer : public content::BrowserPluginDelegate,
private: private:
void OnCreateMimeHandlerViewGuestACK(int element_instance_id); void OnCreateMimeHandlerViewGuestACK(int element_instance_id);
void OnGuestAttached(int element_instance_id, int guest_routing_id);
static bool ShouldHandleMessage(const IPC::Message& mesage);
const std::string mime_type_; const std::string mime_type_;
int element_instance_id_; int element_instance_id_;
std::string html_string_; std::string html_string_;
// Save the RenderView RoutingID here so that we can use it during
// destruction.
int render_view_routing_id_;
bool attached_;
bool attach_pending_;
ScopedPersistent<v8::Function> callback_;
v8::Isolate* isolate_;
DISALLOW_COPY_AND_ASSIGN(GuestViewContainer); DISALLOW_COPY_AND_ASSIGN(GuestViewContainer);
}; };
......
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
#include <string> #include <string>
#include "base/bind.h" #include "base/bind.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h" #include "content/public/renderer/render_view.h"
#include "content/public/renderer/v8_value_converter.h" #include "content/public/renderer/v8_value_converter.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/extension_messages.h" #include "extensions/common/extension_messages.h"
#include "extensions/renderer/guest_view/guest_view_container.h"
#include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
...@@ -29,14 +29,29 @@ GuestViewInternalCustomBindings::GuestViewInternalCustomBindings( ...@@ -29,14 +29,29 @@ GuestViewInternalCustomBindings::GuestViewInternalCustomBindings(
void GuestViewInternalCustomBindings::AttachGuest( void GuestViewInternalCustomBindings::AttachGuest(
const v8::FunctionCallbackInfo<v8::Value>& args) { const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK(args.Length() == 3 && args[0]->IsInt32() && args[1]->IsInt32() && // Allow for an optional callback parameter.
args[2]->IsObject()); CHECK(args.Length() >= 3 && args.Length() <= 4);
// Element Instance ID.
CHECK(args[0]->IsInt32());
// Guest Instance ID.
CHECK(args[1]->IsInt32());
// Attach Parameters.
CHECK(args[2]->IsObject());
// Optional Callback Function.
CHECK(args.Length() < 4 || args[3]->IsFunction());
content::RenderFrame* render_frame = context()->GetRenderFrame(); int element_instance_id = args[0]->Int32Value();
if (!render_frame) // An element instance ID uniquely identifies a GuestViewContainer within
// a RenderView.
GuestViewContainer* guest_view_container =
GuestViewContainer::FromID(context()->GetRenderView()->GetRoutingID(),
element_instance_id);
// TODO(fsamuel): Should we be reporting an error if the element instance ID
// is invalid?
if (!guest_view_container)
return; return;
int element_instance_id = args[0]->Int32Value();
int guest_instance_id = args[1]->Int32Value(); int guest_instance_id = args[1]->Int32Value();
scoped_ptr<base::DictionaryValue> params; scoped_ptr<base::DictionaryValue> params;
...@@ -49,15 +64,13 @@ void GuestViewInternalCustomBindings::AttachGuest( ...@@ -49,15 +64,13 @@ void GuestViewInternalCustomBindings::AttachGuest(
static_cast<base::DictionaryValue*>(params_as_value.release())); static_cast<base::DictionaryValue*>(params_as_value.release()));
} }
// Step 1, send the attach params to chrome/. guest_view_container->AttachGuest(
render_frame->Send(new ExtensionHostMsg_AttachGuest(
render_frame->GetRenderView()->GetRoutingID(),
element_instance_id, element_instance_id,
guest_instance_id, guest_instance_id,
*params)); params.Pass(),
args.Length() == 4 ? args[3].As<v8::Function>() :
// Step 2, attach plugin through content/. v8::Handle<v8::Function>(),
render_frame->AttachGuest(element_instance_id); args.GetIsolate());
args.GetReturnValue().Set(v8::Boolean::New(context()->isolate(), true)); args.GetReturnValue().Set(v8::Boolean::New(context()->isolate(), true));
} }
......
...@@ -94,6 +94,7 @@ function WebViewInternal(webviewNode) { ...@@ -94,6 +94,7 @@ function WebViewInternal(webviewNode) {
this.elementAttached = false; this.elementAttached = false;
this.beforeFirstNavigation = true; this.beforeFirstNavigation = true;
this.contentWindow = null;
this.validPartitionId = true; this.validPartitionId = true;
// Used to save some state upon deferred attachment. // Used to save some state upon deferred attachment.
// If <object> bindings is not available, we defer attachment. // If <object> bindings is not available, we defer attachment.
...@@ -166,6 +167,7 @@ WebViewInternal.prototype.reset = function() { ...@@ -166,6 +167,7 @@ WebViewInternal.prototype.reset = function() {
this.beforeFirstNavigation = true; this.beforeFirstNavigation = true;
this.validPartitionId = true; this.validPartitionId = true;
this.partition.validPartitionId = true; this.partition.validPartitionId = true;
this.contentWindow = null;
} }
this.internalInstanceId = 0; this.internalInstanceId = 0;
}; };
...@@ -419,10 +421,11 @@ WebViewInternal.prototype.setupWebviewNodeProperties = function() { ...@@ -419,10 +421,11 @@ WebViewInternal.prototype.setupWebviewNodeProperties = function() {
// dynamic getter value. // dynamic getter value.
Object.defineProperty(this.webviewNode, 'contentWindow', { Object.defineProperty(this.webviewNode, 'contentWindow', {
get: function() { get: function() {
if (browserPluginNode.contentWindow) if (this.contentWindow) {
return browserPluginNode.contentWindow; return this.contentWindow;
}
window.console.error(ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE); window.console.error(ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE);
}, }.bind(this),
// No setter. // No setter.
enumerable: true enumerable: true
}); });
...@@ -575,7 +578,11 @@ WebViewInternal.prototype.handleBrowserPluginAttributeMutation = ...@@ -575,7 +578,11 @@ WebViewInternal.prototype.handleBrowserPluginAttributeMutation =
guestViewInternalNatives.AttachGuest( guestViewInternalNatives.AttachGuest(
this.internalInstanceId, this.internalInstanceId,
this.guestInstanceId, this.guestInstanceId,
params); params,
function(w) {
this.contentWindow = w;
}.bind(this)
);
}.bind(this), 0); }.bind(this), 0);
} }
...@@ -879,7 +886,10 @@ WebViewInternal.prototype.attachWindow = function(guestInstanceId, ...@@ -879,7 +886,10 @@ WebViewInternal.prototype.attachWindow = function(guestInstanceId,
return guestViewInternalNatives.AttachGuest( return guestViewInternalNatives.AttachGuest(
this.internalInstanceId, this.internalInstanceId,
this.guestInstanceId, this.guestInstanceId,
params); params, function(w) {
this.contentWindow = w;
}.bind(this)
);
}; };
// Registers browser plugin <object> custom element. // Registers browser plugin <object> custom element.
......
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